Skip to content

Commit 17854cb

Browse files
Elon Muskclaude
andauthored
fix(runtime): state the owd_widening_forbidden ledger row's real wire shape (#9958) (#10000)
The `owd_widening_forbidden` row in `dispatcher-error-vocabulary.ts` justified its `pending-registration` verdict from a wire shape the live route does not produce. Its `why` said the refusal "reaches the wire verbatim" and that `packages/rest/src/meta-object-owd-gate.test.ts` "reads a 403 body whose `code` is this string". Measured against that same pin file: the body carries TWO fields. Since #9232 narrowed the flat REST door like every other, `code` is the closed ADR-0112 member the 403 derives (`PERMISSION_DENIED`) and the gate's own lowercase spelling survives, unchanged, in the open `declaredCode` sibling (`ApiErrorSchema.declaredCode`, an optional `z.string()`), so the body parses. A consumer keying on `code` alone cannot tell this refusal from any other 403. The verdict is unchanged and still follows, but from this file's HEADER rather than from the `pending-registration` doc comment: the demote is not an escape from the table — an unswept producer loses its semantic code off `error.code` until the vocabulary carries it, and registering the code is what ratchets the row out. That divergence between the header and the verdict doc comment is pre-existing and filed separately, not touched here. Prose only. No behaviour change: the accept/reject set, every emitted body and the gate's own verdict are untouched — `check:dispatcher-error-vocabulary` reports the same 17 classified sites and the same 1 awaiting a ledger entry as before the edit. Claude-Session: https://claude.ai/code/session_019bmVFqoQPq63zhKrxdYG1r Co-authored-by: Claude <noreply@anthropic.com>
1 parent d5552ca commit 17854cb

2 files changed

Lines changed: 18 additions & 2 deletions

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@objectstack/runtime': patch
3+
---
4+
5+
Correct the `owd_widening_forbidden` rationale in the dispatcher error-code ledger to the measured wire shape.
6+
7+
The row's `why` claimed the refusal "reaches the wire verbatim" in a 403 body "whose `code` is this string". Since #9232 narrowed the flat REST door, it does not: the body carries `code: PERMISSION_DENIED` — the closed ADR-0112 member the status derives — and the gate's own lowercase spelling rides the open `declaredCode` sibling beside it, which is what `packages/rest/src/meta-object-owd-gate.test.ts` actually asserts. Prose only; the `pending-registration` verdict, the accept/reject set and every emitted body are unchanged.

packages/runtime/src/dispatcher-error-vocabulary.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -378,8 +378,17 @@ export const UNREGISTERED_CODE_SITES: readonly UnregisteredCodeSite[] = [
378378
verdict: 'pending-registration',
379379
why:
380380
'The ADR-0090 D7 / ADR-0086 D1 refusal: an environment overlay may only TIGHTEN a packaged ' +
381-
"object's OWD. It reaches the wire verbatim — `packages/rest/src/meta-object-owd-gate.test.ts` " +
382-
'drives `PUT /api/v1/meta/object/:name` and reads a 403 body whose `code` is this string. ' +
381+
"object's OWD. The token reaches the wire verbatim but NOT in `code` — it rides the wire in " +
382+
'TWO fields since #9232 narrowed the flat REST door like every other: the 403 body carries the ' +
383+
'closed member the status derives in `code` (`PERMISSION_DENIED`) and this string, unchanged, ' +
384+
'in the open `declaredCode` sibling beside it. `packages/rest/src/meta-object-owd-gate.test.ts` ' +
385+
'drives `PUT /api/v1/meta/object/:name` and asserts BOTH fields on the refusal body. So the ' +
386+
'body PARSES (`ApiErrorSchema.declaredCode` is an open `z.string()`), and a consumer keying on ' +
387+
'`code` alone reads a generic `PERMISSION_DENIED` and cannot tell this refusal from any other ' +
388+
'403. ⚠️ That demote is not an escape from this table — it is the shape this file\'s header ' +
389+
'already names: the body parses, and what an unswept producer loses instead is its semantic ' +
390+
'code, silently demoted off `error.code` until registered. Which is exactly what a ' +
391+
'`pending-registration` row records, and registering the code is still what ratchets it out. ' +
383392
'[#9460] Invisible to BOTH vocabulary gates until now, and not for its casing: the file throws ' +
384393
'through a code-carrying helper (`postureError(code, message)`), so the stamp `(err as any).code ' +
385394
'= code` knows the token `code` but not the value, while the call site knows the value and never ' +

0 commit comments

Comments
 (0)