Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .changeset/error-code-ledger-boot-refusal-prose.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
"@objectstack/spec": patch
---

The error-code ledger's TSDoc stops naming a retired verdict as a live mechanism, and states the published-face rule it is actually held to.

`packages/spec` ships `src/**/*.zod.ts`, so `api/error-code-ledger.zod.ts`'s header is published prose — a consumer reads these sentences out of the tarball. Two of them stopped being true when `check-dispatcher-error-vocabulary`'s face refusal widened from `packages/spec/src/**` to every published package's `src/` and the dispatcher vocabulary's `boot-refusal` verdict retired with it (#16649).

The first said the `boot-refusal` verdict **records** reachability for codes not yet registered, and pointed at the module the verdict was being deleted from. That is a claim about where a live mechanism lives, not about a case that can no longer arise, so a reader following the pointer would have found nothing. It now records the retirement and names what replaced it: a `door: 'none'` code has no resting place short of a row in the ledger.

The second opened `packages/spec/src/** is held to this mechanically`. True before the widening and an understatement after it — a reader would conclude only the spec tree is guarded, which is the "guarded a part" / "guarded it" confusion this whole class of gate exists to remove. It now states the published face, the stricter spec sub-face where `pending-registration` has no allowance, and the named, dated allowance outside it owed to #8846, with both finding kinds named.

No schema, accept set, default or refusal moves. `ERROR_CODE_LEDGER` holds the same members before and after, and the generated reference page is regenerated from this prose rather than hand-edited.
32 changes: 21 additions & 11 deletions content/docs/references/api/error-code-ledger.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -110,22 +110,32 @@ question.
ONE shape, no second list: a `door: 'none'` code is a row like any other —
the string under the package that stamps it, and a comment that states its
`status` and the reachability reading ("no HTTP door on this tree; the
thrown value is the boundary"). The dispatcher vocabulary's `boot-refusal`
verdict (`packages/runtime/src/dispatcher-error-vocabulary.ts`) records
that same reachability for the codes NOT yet registered, and a row here
ratchets its vocabulary row out exactly as a `pending-registration`
registration does. What registration changes for such a code is the face,
thrown value is the boundary"). Until #16649 the dispatcher vocabulary
(`packages/runtime/src/dispatcher-error-vocabulary.ts`) carried a
`boot-refusal` verdict that recorded that same reachability for the codes
NOT yet registered; it is RETIRED, because the gate below now refuses it —
and every verdict like it — under any published package's `src/`. The one
verdict that still parks a site there is `pending-registration`, and only
outside `packages/spec/src/**`, under the dated allowance spelled out below.
So a `door: 'none'` code has no resting place short of a row here, and the
ratchet is the one `pending-registration` already had: a row here makes the
site vanish from that scan. What registration changes
for such a code is the face,
not the wire: nothing demotes today, and if a door ever does answer with
it, `error.code` carries the specific code instead of the status-derived
member plus `declaredCode`. The `declaredCode` demotion (#9106) stays for
genuinely unknown / third-party spellings only.

`packages/spec/src/**` is held to this mechanically:
`check:dispatcher-error-vocabulary` refuses to classify a stamp site under
that tree as anything but `foreign-vocabulary` (a different vocabulary that
merely spells itself `code`) or `runtime-pinned` — a `boot-refusal` or
`pending-registration` row for a spec site is a finding
(`spec-face-unregistered`), and the only way out is the row here.
EVERY published package's `src/**` is held to this mechanically — #16649
widened the rule from `packages/spec/src/**` alone, which is all #16449
could afford to measure. `check:dispatcher-error-vocabulary` refuses to
classify a stamp site under one as anything but `foreign-vocabulary` (a
different vocabulary that merely spells itself `code`) or `runtime-pinned`,
and the only way out is the row here. Under `packages/spec/src/**` that is
the whole rule, so a `pending-registration` row for a spec site is a finding
(`spec-face-unregistered`); outside it, a `pending-registration` row keeps a
named, dated allowance owed to #8846 and any OTHER verdict is a finding
(`published-face-unregistered`).

A code emitted by several packages is listed once per emitting package —
the union dedupes; the per-package rows are provenance, not identity.
Expand Down
62 changes: 36 additions & 26 deletions packages/runtime/src/dispatcher-error-vocabulary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,27 @@ export type CodeStampShape =
*/
export type CodeDoor = 'dispatcher' | 'rest' | 'plugin-route' | 'none';

/**
* [#16649] `'boot-refusal'` was HERE, and is retired. It named a refusal raised
* before any HTTP boundary exists — the CLI rethrows it and aborts — and until
* #16404 the ledger ratified that class as not owed a row
* (`MONGODB_MULTI_TENANT_UNSUPPORTED` was UNregistered by #8035 on "host boot
* matching is not wire vocabulary"). #16404 deleted the exemption (the ledger
* is the published face, door or no door), which left the verdict meaning only
* "a registration this tree still owes" — #16449 discharged nine of those,
* #16649's first half the remaining fourteen, and the second half widened
* `check-dispatcher-error-vocabulary`'s face refusal from `packages/spec/src/`
* to every published package's `src/`, which is what makes the verdict
* unwritable: a row carrying it inside that face is now a
* `published-face-unregistered` finding, and the whole scan population lives
* inside it. A union member no site can legally carry is a place to park work,
* so it comes out with the widening that closed it.
*
* ⛔ Do not reintroduce it for the next pre-HTTP producer the scan finds. Its
* answer under #16404 is the ledger row, and the gate's `unclassified-site`
* text says so. REACHABILITY is still recorded — on the ledger row, as the
* `door: 'none'` reading each of the twenty-three registrations carries.
*/
export type CodeVerdict =
/**
* Reaches a wire and the ledger does not know it. Since #9106 the door
Expand All @@ -209,28 +230,6 @@ export type CodeVerdict =
* draw the same line for field-level and diagnostic codes).
*/
| 'foreign-vocabulary'
/**
* A refusal raised before any HTTP boundary exists — the CLI rethrows it
* and aborts. Until #16404 the ledger's own note ratified this class as
* NOT owed a row (`MONGODB_MULTI_TENANT_UNSUPPORTED` was UNregistered by
* #8035 on "host boot matching is not wire vocabulary").
*
* [#16404] That exemption is gone: the published face is the ledger, and
* every code that ships in `dist` is registered there, door or no door.
* This verdict now records REACHABILITY only — no door answers with the
* code, so registering it changes no HTTP body — and a row carrying it is
* a registration OWED, exactly like `pending-registration`: the row
* ratchets out when the ledger row lands (#16449 took the nine measured on
* that card's tree; #16649 took the fourteen that remained, so on this
* tree no row carries this verdict — it stays declared for the next
* pre-HTTP producer the scan finds, until the gate's spec-face refusal is
* widened to every published package and this verdict retires with it;
* see the running log below). ⛔ Under `packages/spec/src/**` the gate refuses
* this verdict outright (`spec-face-unregistered`): a spec stamp site is a
* ledger member, a foreign vocabulary or a runtime-pinned template —
* nothing between.
*/
| 'boot-refusal'
/**
* [#9223] The site builds its code by INTERPOLATION, so no source scan can
* say which codes it produces or whether they are registered — and a named
Expand Down Expand Up @@ -320,10 +319,21 @@ export const UNREGISTERED_CODE_SITES: readonly UnregisteredCodeSite[] = [
// `WALLED_MEMBERSHIP_POLICY_UNDECLARED` (`@objectstack/organizations`) —
// were registered under their stamping packages and ratcheted out
// (`stale-row`), the reachability each row recorded now carried on its
// ledger row. On this tree NO row carries the `boot-refusal` verdict; a
// future pre-HTTP producer the scan finds still lands here as an
// `unclassified-site` and takes one, then a registration, then comes out
// again. ──
// ledger row.
//
// ── [#16649, second half] The class is now closed MECHANICALLY rather than
// by having been emptied once. `check-dispatcher-error-vocabulary`'s face
// refusal, which #16449 could only afford over `packages/spec/src/`, covers
// every published package's `src/` — the whole of this scan's population on
// this tree (52 sites: 47 published-face, 5 spec-face) — so a site here is
// a ledger member, a `foreign-vocabulary` or a `runtime-pinned` template
// and nothing else, and the `boot-refusal` verdict that used to park one
// between is retired from `CodeVerdict` above. The single carve-out is
// `pending-registration` outside `packages/spec/src/`, granted 2026-09-08
// and owed to #8846; the gate's header dates it and every run prints how
// many rows still stand on it. A future pre-HTTP producer the scan finds
// lands here as an `unclassified-site` and its way out is the ledger row,
// not a row here. ──

// ── runtime-pinned: an interpolated family, checked where it can be ─────
{
Expand Down
32 changes: 21 additions & 11 deletions packages/spec/src/api/error-code-ledger.zod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,22 +106,32 @@
* ONE shape, no second list: a `door: 'none'` code is a row like any other —
* the string under the package that stamps it, and a comment that states its
* `status` and the reachability reading ("no HTTP door on this tree; the
* thrown value is the boundary"). The dispatcher vocabulary's `boot-refusal`
* verdict (`packages/runtime/src/dispatcher-error-vocabulary.ts`) records
* that same reachability for the codes NOT yet registered, and a row here
* ratchets its vocabulary row out exactly as a `pending-registration`
* registration does. What registration changes for such a code is the face,
* thrown value is the boundary"). Until #16649 the dispatcher vocabulary
* (`packages/runtime/src/dispatcher-error-vocabulary.ts`) carried a
* `boot-refusal` verdict that recorded that same reachability for the codes
* NOT yet registered; it is RETIRED, because the gate below now refuses it —
* and every verdict like it — under any published package's `src/`. The one
* verdict that still parks a site there is `pending-registration`, and only
* outside `packages/spec/src/**`, under the dated allowance spelled out below.
* So a `door: 'none'` code has no resting place short of a row here, and the
* ratchet is the one `pending-registration` already had: a row here makes the
* site vanish from that scan. What registration changes
* for such a code is the face,
* not the wire: nothing demotes today, and if a door ever does answer with
* it, `error.code` carries the specific code instead of the status-derived
* member plus `declaredCode`. The `declaredCode` demotion (#9106) stays for
* genuinely unknown / third-party spellings only.
*
* `packages/spec/src/**` is held to this mechanically:
* `check:dispatcher-error-vocabulary` refuses to classify a stamp site under
* that tree as anything but `foreign-vocabulary` (a different vocabulary that
* merely spells itself `code`) or `runtime-pinned` — a `boot-refusal` or
* `pending-registration` row for a spec site is a finding
* (`spec-face-unregistered`), and the only way out is the row here.
* EVERY published package's `src/**` is held to this mechanically — #16649
* widened the rule from `packages/spec/src/**` alone, which is all #16449
* could afford to measure. `check:dispatcher-error-vocabulary` refuses to
* classify a stamp site under one as anything but `foreign-vocabulary` (a
* different vocabulary that merely spells itself `code`) or `runtime-pinned`,
* and the only way out is the row here. Under `packages/spec/src/**` that is
* the whole rule, so a `pending-registration` row for a spec site is a finding
* (`spec-face-unregistered`); outside it, a `pending-registration` row keeps a
* named, dated allowance owed to #8846 and any OTHER verdict is a finding
* (`published-face-unregistered`).
*
* A code emitted by several packages is listed once per emitting package —
* the union dedupes; the per-package rows are provenance, not identity.
Expand Down
Loading
Loading