Skip to content

Commit c09451b

Browse files
feat(spec): register driver-memory as a UNIQUE_VIOLATION emitter in the error-code ledger (#13354)
* feat(spec): register driver-memory as a UNIQUE_VIOLATION emitter in the error-code ledger ERROR_CODE_LEDGER lists a code once per emitting package -- provenance, not identity. driver-memory refuses a colliding write with code UNIQUE_VIOLATION / status 409 (conflictRefusal, memory-unique-constraint.ts), stamped in one place for both the field-level and the declared-index surface, and had no owner key. Pure append: one new owner key naming one already-registered code. No shape, mechanism, or other package's rows touched; the deduped union is unchanged, so no generated reference product moves. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KX8wnyjStaZcuMyAMNsy3N * chore(changeset): driver-memory UNIQUE_VIOLATION provenance row Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KX8wnyjStaZcuMyAMNsy3N --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 090f230 commit c09451b

2 files changed

Lines changed: 51 additions & 0 deletions

File tree

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
"@objectstack/spec": patch
3+
---
4+
5+
feat(spec): register `@objectstack/driver-memory` as an emitter of `UNIQUE_VIOLATION` in the error-code ledger (#13254)
6+
7+
`ERROR_CODE_LEDGER` (ADR-0112 D3) lists a code once per emitting package —
8+
its own header calls those rows "provenance, not identity", and they are how a
9+
reader answers "who produces this code?".
10+
11+
Since the in-memory driver started enforcing uniqueness (field-level `unique`,
12+
and object-level declared `indexes[]` entries carrying `unique`), a colliding
13+
write is refused with `code: 'UNIQUE_VIOLATION'` / `status: 409` — stamped in
14+
one place for both declaration surfaces by `conflictRefusal` in
15+
`packages/drivers/driver-memory/src/memory-unique-constraint.ts` — while
16+
`@objectstack/driver-memory` had no row at all. No gate could see that: the
17+
ledger's admission rules check casing, duplication and shadowing, never who
18+
emits, and the code itself was already registered by `@objectstack/rest`, so
19+
union membership, `ApiErrorSchema` parsing and
20+
`check:dispatcher-error-vocabulary` were all green over the gap.
21+
22+
Pure provenance append: one new owner key naming the one code. No code's
23+
identity, status, casing or union membership changes, no other package's rows
24+
are touched, and the generated reference products are unchanged because the
25+
deduped union they enumerate is unchanged.

packages/spec/src/api/error-code-ledger.zod.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,32 @@ export const ERROR_CODE_LEDGER = {
669669
'SUGGESTION_NOT_FOUND',
670670
'SUGGESTION_STATE', // suggestion exists but is not in a confirmable/dismissable state
671671
],
672+
'@objectstack/driver-memory': [
673+
// [#13254] Provenance for the in-memory driver's uniqueness refusal, which
674+
// #13197 (field-level `unique`) and #13239 (declared `indexes[]` entries)
675+
// made real: a colliding write is REFUSED rather than landed. Stamped in
676+
// ONE place for both declaration surfaces — `conflictRefusal`
677+
// (`packages/drivers/driver-memory/src/memory-unique-constraint.ts`),
678+
// `code: 'UNIQUE_VIOLATION'` / `status: 409` via the package's exported
679+
// `UNIQUE_VIOLATION_CODE` / `UNIQUE_VIOLATION_STATUS`.
680+
//
681+
// Second EMITTER of the code `@objectstack/rest` already registers for the
682+
// SQL conflict; the wire identity is deliberately the SAME, so a suite that
683+
// swaps this driver for SQLite sees ONE envelope. Per this file's header, a
684+
// code emitted by several packages is listed once per emitting package —
685+
// provenance, not identity.
686+
//
687+
// Wire-reachable by the test the "Retiring a code" section above applies
688+
// (#8035): an ordinary create/update on an object with a `unique` field
689+
// reaches `InMemoryDriver.create` on a server already serving HTTP, and
690+
// `resolveThrownHttpError` puts the driver's `code`/`status` on the
691+
// envelope. This row adds provenance ONLY: the code was already registered,
692+
// so the union, its casing and every other package's rows are unchanged.
693+
// Registered late for exactly the reason the row is worth having — no
694+
// admission rule checks WHO emits, so an unlisted emitter is invisible to
695+
// every gate the repo has.
696+
'UNIQUE_VIOLATION',
697+
],
672698
'@objectstack/driver-sql': [
673699
// [#11991] The #11756 ruling's refusal (maintainer, 2026-08-25, verbatim
674700
// 「同意」 on 「C,但 pgnative 归入 Postgres 家族」): a knex client this

0 commit comments

Comments
 (0)