You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#55 promises "an id that already exists → 409 StackConflictError, never a silent overwrite." Stack.create() pre-checks via getRecord (stack.ts:748-753), so the common path is safe — but the raw adapter createRecord doesn't uniformly enforce it, so a direct adapter call (or a race between Stack's pre-check and its write) doesn't get the promised contract:
MemoryAdapter.createRecord (testing.ts:50-54) does records.set(id, …) and order.push(id) unconditionally → a duplicate id silently overwrites the existing record and appends a duplicate order entry (corrupting pagination).
SQL adapters — SharedSqlRecordLogic.createRecord (record-logic.ts:133-162) INSERTs against the records PK; a duplicate throws a raw SQLite unique-constraint error that is not mapped to StackConflictError. isUniqueConstraintViolation is consulted only in saveVersion (record-logic.ts:447-455), not here — so a raw-adapter duplicate surfaces as an unmapped engine exception instead of the typed error the wire and ID authority under server topology: clients mint record IDs and the server trusts them #55 promise.
Fix
MemoryAdapter.createRecord: throw StackConflictError if the id already exists (before mutating records/order).
SharedSqlRecordLogic.createRecord: wrap the INSERT and map a unique-constraint violation to StackConflictError, reusing isUniqueConstraintViolation (already imported).
Both bring the raw adapters in line with Stack.create()'s pre-check and the #55 contract, and pin the "never a silent overwrite" invariant at the storage layer rather than relying solely on the Stack-level pre-check.
Tests
Raw adapter.createRecord with a duplicate id throws StackConflictError on MemoryAdapter and both SQLite adapters
MemoryAdapterorder has no duplicate entry after a rejected create
Refs
#55 (ID authority / never-silent-overwrite), #48 (the saveVersion collision-mapping precedent this mirrors). From docs/design-assessment-2026-07.md §F7.
#55 promises "an id that already exists → 409
StackConflictError, never a silent overwrite."Stack.create()pre-checks viagetRecord(stack.ts:748-753), so the common path is safe — but the raw adaptercreateRecorddoesn't uniformly enforce it, so a direct adapter call (or a race betweenStack's pre-check and its write) doesn't get the promised contract:MemoryAdapter.createRecord(testing.ts:50-54) doesrecords.set(id, …)andorder.push(id)unconditionally → a duplicate id silently overwrites the existing record and appends a duplicateorderentry (corrupting pagination).SharedSqlRecordLogic.createRecord(record-logic.ts:133-162) INSERTs against therecordsPK; a duplicate throws a raw SQLite unique-constraint error that is not mapped toStackConflictError.isUniqueConstraintViolationis consulted only insaveVersion(record-logic.ts:447-455), not here — so a raw-adapter duplicate surfaces as an unmapped engine exception instead of the typed error the wire and ID authority under server topology: clients mint record IDs and the server trusts them #55 promise.Fix
MemoryAdapter.createRecord: throwStackConflictErrorif the id already exists (before mutatingrecords/order).SharedSqlRecordLogic.createRecord: wrap the INSERT and map a unique-constraint violation toStackConflictError, reusingisUniqueConstraintViolation(already imported).Both bring the raw adapters in line with
Stack.create()'s pre-check and the #55 contract, and pin the "never a silent overwrite" invariant at the storage layer rather than relying solely on theStack-level pre-check.Tests
adapter.createRecordwith a duplicate id throwsStackConflictErroronMemoryAdapterand both SQLite adaptersMemoryAdapterorderhas no duplicate entry after a rejected createRefs
#55 (ID authority / never-silent-overwrite), #48 (the
saveVersioncollision-mapping precedent this mirrors). Fromdocs/design-assessment-2026-07.md§F7.