Skip to content

fix(postgres): run the installed command, dedupe by instant, refuse out-of-range offsets - #49

Merged
gjtorikian merged 2 commits into
mainfrom
fix/postgres-cli-dedupe-offsets
Nov 5, 2026
Merged

gjtorikian merged 2 commits into
mainfrom
fix/postgres-cli-dedupe-offsets

Conversation

@gjtorikian

Copy link
Copy Markdown
Collaborator

Summary

Three bugs Greptile found in the MongoDB destination (#41) that sync-postgres shares, each with a test:

  • The installed command did nothing. The entrypoint check compared process.argv[1] against cli.js, but npm installs a bin as a symlink named workos-sync-postgres, so npx workos-sync-postgres imported main() and exited. invokedDirectly() now resolves both the argv path and the module URL to real paths before comparing. The Docker image was unaffected, since it runs node dist/cli.js directly.
  • dedupeByKey compared timestamps as text, so a batch mixing offset and UTC forms (01:00:00+01:00 vs 00:30:00Z) could keep the older row on the delete, relink and unlink paths. It now orders by the instant, falling back to text for a value that is not a date, which the database refuses on the write anyway.
  • parse_iso8601 accepted out-of-range offsets such as +00:99 and applied them. The offset's hours and minutes are now range-checked like the clock's. The function is recreated on every init before the fingerprint check, so existing deployments pick the check up on their next init; no generated column expression changes, so there is no drift to repair.

…ut-of-range offsets

Three findings Greptile raised on the MongoDB destination that this
package shares:

- The entrypoint check compared `process.argv[1]` against `cli.js`, but
  npm installs the `bin` as a symlink named `workos-sync-postgres`, so the
  installed command imported `main()` and exited. Both sides are now
  resolved to real paths and compared.
- `dedupeByKey` compared `updatedAt` as text, so a batch mixing offset and
  UTC forms could keep the older row. It now orders by the instant, and
  falls back to text for a value that is not a date, which the database
  refuses on the write anyway.
- `parse_iso8601` range-checked the clock but not the offset, so `+00:99`
  was accepted and applied. The function is recreated on every `init`, so
  existing deployments pick the check up on their next one; no generated
  column expression changes.
@greptile-apps

greptile-apps Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge; the previous timestamp precision issue is fixed.

Summary

This PR fixes the installed command, timestamp ordering, and invalid timezone offsets.

  • The installed Postgres command now starts through its npm symlink.
  • Repeated-key writes now keep the row with the newest timestamp instant.
  • Timestamp parsing now rejects offsets with out-of-range hours or minutes.

The previous precision finding is fixed. No new actionable issues were found.

Reviews (2) · Last reviewed commit: "fix(postgres): order a batch's timestamp..." · Reviewed by Greptile

Comment thread packages/sync-postgres/src/db/upsert.ts Resolved
… keeps

Date.parse reads three fractional digits and a timestamptz keeps six, so
two removals a microsecond apart tied and the later row in the batch won,
whichever was newer. The rest of the fraction is read alongside it now.
@gjtorikian
gjtorikian merged commit e667d58 into main Nov 5, 2026
15 checks passed
gjtorikian added a commit that referenced this pull request Nov 5, 2026
… out-of-range offsets

The same three fixes Postgres (#49) and MySQL (#50) got. npm installs the
bin as a symlink named after the command, which the old argv check did
not recognise, so `npx workos-sync-clickhouse` imported the CLI and did
nothing. Duplicate keys in a batch are now judged by the instant each
timestamp names rather than by its text, so `01:00:00+01:00` no longer
outranks `00:30:00Z`. And the timestamp projection range-checks the
clock and the offset ahead of the best-effort parser, which read
`24:00` as the next midnight and `+00:99` as a zone where the other
destinations project NULL.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant