Honor expectedVersion on ordinary card upserts - #23
Draft
CoreyRDean wants to merge 1 commit into
Draft
CoreyRDean wants to merge 1 commit into
CoreyRDean wants to merge 1 commit into
Conversation
The ordinary POST /api/ideas upsert of an existing dedupe key now only replaces the card when the request carries the stored version. A missing or stale expectedVersion skips the write entirely and returns 409 with the stored version, so an agent upsert can no longer silently overwrite a card a user is acting on. New keys keep ingesting without it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
POST /api/ideashonoredexpectedVersiononly in blocked-replacement mode. The ordinary upsert path ranINSERT ... ON CONFLICT(dedupe_key) DO UPDATEunconditionally: publishing an existing dedupe key replaced the card's content and bumped its version with no compare-and-set, so a programmatic write could silently overwrite a card a user was mid-click on.Change
The ordinary path is now a single-statement compare-and-set: the
DO UPDATEclause carriesWHERE ideas.version = ?, bound to the request'sexpectedVersion(a safe integer, or null when absent).expectedVersion: card updated, version bumped - unchanged behavior.expectedVersion: SQLite skips the update, nothing is written, and the route returns 409 with{ error, storedVersion }so the caller can re-read the card and retry.expectedVersion- unchanged behavior.Test
node --test scripts/ideas-upsert-guard.test.mjsruns the real route (Workers env stubbed, D1-shaped adapter over in-memory SQLite) and covers the new-key 201 path, the missing and mismatchedexpectedVersion409 paths - including that the stored row is left untouched - and the matching-version update path.Summary by cubic
Makes the ordinary
POST /api/ideasupsert a compare-and-set so an agent write can no longer silently overwrite a card a user is acting on.expectedVersionmatches the stored version; otherwise SQLite skips the write and the route returns 409 with the stored version.expectedVersion, and blocked-replacement mode is untouched.scripts/ideas-upsert-guard.test.mjscovering the new-key 201 path, missing and mismatchedexpectedVersion409 paths, and the matching-version update path.Written for commit a7aeaf7. Summary will update on new commits.