Commit 3f9e2ea
fix(spec): list plugin-security's class-field error codes under its own ledger key (#19782)
Fixes #19441
Clause-②: yes
## What changed
Two halves, in two packages, landed together (the triage rider: the
registration and the comment are not interchangeable).
1. **`packages/spec` ledger** —
`ERROR_CODE_LEDGER['@objectstack/plugin-security']` gains three
provenance rows, `INVALID_STATE`, `NOT_FOUND`, `NOT_OVERRIDABLE`, each
with a comment naming the throwing class, its status and its door. They
cover all four emission points the card listed (`NOT_OVERRIDABLE` is
stamped by two classes, one row). Every code was already registered
under another package (`@objectstack/rest`,
`@objectstack/metadata-protocol`), so the `ErrorCode` union and the wire
are unchanged: provenance, not identity. The `NOT_FOUND` entry in
`STANDARD_SYNONYM_WAIVERS` keeps its `code`/`shadows`; its `reason` text
now names plugin-security among the emitters (the same edit the
`FORBIDDEN` waiver got when cloud-connection joined).
2. **`plugin-security`** — the `PackagedPermissionSetLockedError`
docblock no longer says "the code is a StandardErrorCode, so no ledger
entry is minted". It now says what is true: `NOT_OVERRIDABLE` is a
registered extension code, NOT a `StandardErrorCode` member, and this
package's own owner key lists it. The two overlay-discard error classes
get a one-line pointer to their rows. The plugin-security edits are
comments only.
## Premise check (on `origin/main` `041c8cf6`)
- The four stamps are at `packaged-permission-set-lock.ts:266`, `:287`
and `permission-set-overlay-discard.ts:91`, `:101`, all spelled
`readonly code = '...'`.
- All four are live. `assertPermissionSetNotPackageDeclared` is called
from `permission-set-projection.ts` (three sites) and
`packaged-permission-set-lock-gate.ts`. `discardPermissionSetOverlay` is
registered by `security-plugin.ts` and served by rest's `POST
.../security/permission-sets/:id/discard-overlay`. The classes are
exported from `index.ts`.
- They ship: after the build, each of the three literals hits 1 file in
`packages/plugins/plugin-security/dist/*.js` (control
`UNIQUE_VIOLATION`: 1).
- None of the three was listed under plugin-security before this PR.
- `check:error-code-provenance` declares class fields out of its scan
(see its header, "BLIND ... and a class field"), so it was green before
this PR and is still green now (exit 0).
## Tests
- New pin in `error-code-ledger.test.ts`: `lists the plugin-security
class-field stamps under their stamping package`. It checks each code is
listed under plugin-security AND is still listed under its first owner,
and that it parses as an `ErrorCode`. It also checks `NOT_OVERRIDABLE`
is absent from `StandardErrorCode.options`, with a lit control:
`PERMISSION_DENIED` is present.
- `pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2
src/api/error-code-ledger.test.ts`: 21 passed.
- `src/api` (44 files): 1518 passed.
- plugin-security `packaged-permission-set-lock*.test.ts` and
`permission-set-overlay-discard.test.ts` (3 files): 33 passed.
- `typecheck` for `@objectstack/spec` (including scripts-typecheck and
test-typecheck) and for `@objectstack/plugin-security`: exit 0.
- **Ablation** (one-off, not left in the tree): I deleted the
plugin-security `NOT_OVERRIDABLE` row with
`scripts/ablation-replace.mjs` (anchor x1 -> x0, marker x0 -> x1) and
ran the pin: `1 failed | 20 passed`, failing with `NOT_OVERRIDABLE
listed under plugin-security: expected [ 'INVALID_METADATA', ...(5) ] to
include 'NOT_OVERRIDABLE'`. After the restore the blob equals HEAD
(`d8ad7285`) and `git diff HEAD` is empty. The suite imports the ledger
from `src`, so no dist rebuild was involved. My first attempt was a
no-op: the replacement text was already inside the anchor, so the tool
refused and restored. It is not counted.
## Gates (head `5a1a2efd`)
`dispatch-gates.mjs --commands` listed 89 commands; `--ran` reconciled
all of them (86 run, 3 NOT MEASURED, 0 unrun). All 86 that ran exited 0,
including `check:error-code-provenance`,
`check:dispatcher-error-vocabulary`, `check:error-code-casing`,
`check:api-surface`, `check:docs`, `check:authorable-surface`,
`check:adr-0087-registration`, `check-changeset-no-major` and
`check:nul-bytes`.
NOT MEASURED, each exit 3 PREREQUISITE (they need a whole-workspace
build that was not done locally; left to CI):
`check:dual-build-cjs-loads`, `check:i18n`, `check:type-check-debt`.
`pnpm lint` (a repo-wide scan) was not run locally; that is CI's run.
## Changeset level
The dispatch suggested `patch`. The changeset grades `@objectstack/spec`
**minor** instead: AGENTS.md's Post-Task Checklist says `Clause-②: yes`
takes at least `minor`, `check-changeset-no-major.mjs`'s level axis
enforces that, and the ledger header says registering a code widens the
published face. The precedent is #19437 (the prior plugin-security
ledger row: spec minor). plugin-security has no changeset entry because
its diff is comments only.
## Acceptance notes
- The card's other idea, making `check:error-code-provenance` see
class-field spellings, is **not** done here. That is a gate-population
change and a separate decision. Measurement for it: these four stamps
were invisible to the gate because class fields are out of its scan. The
new vitest pin holds only these rows; a future class-field stamp in any
package would still be invisible to the gate.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01VWsFyWDp8Rjb2Ma6a3Cyo8)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent 55095cc commit 3f9e2ea
5 files changed
Lines changed: 83 additions & 6 deletions
File tree
- .changeset
- packages
- plugins/plugin-security/src
- spec/src/api
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
Lines changed: 6 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
245 | 245 | | |
246 | 246 | | |
247 | 247 | | |
248 | | - | |
249 | | - | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
250 | 254 | | |
251 | 255 | | |
252 | 256 | | |
| |||
Lines changed: 10 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
86 | 86 | | |
87 | 87 | | |
88 | 88 | | |
89 | | - | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
90 | 94 | | |
91 | 95 | | |
92 | 96 | | |
| |||
96 | 100 | | |
97 | 101 | | |
98 | 102 | | |
99 | | - | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
100 | 108 | | |
101 | 109 | | |
102 | 110 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
260 | 260 | | |
261 | 261 | | |
262 | 262 | | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
263 | 288 | | |
264 | 289 | | |
265 | 290 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1090 | 1090 | | |
1091 | 1091 | | |
1092 | 1092 | | |
| 1093 | + | |
| 1094 | + | |
| 1095 | + | |
| 1096 | + | |
| 1097 | + | |
| 1098 | + | |
| 1099 | + | |
| 1100 | + | |
| 1101 | + | |
| 1102 | + | |
| 1103 | + | |
| 1104 | + | |
| 1105 | + | |
| 1106 | + | |
| 1107 | + | |
| 1108 | + | |
| 1109 | + | |
| 1110 | + | |
| 1111 | + | |
| 1112 | + | |
| 1113 | + | |
| 1114 | + | |
| 1115 | + | |
| 1116 | + | |
| 1117 | + | |
| 1118 | + | |
| 1119 | + | |
| 1120 | + | |
| 1121 | + | |
| 1122 | + | |
1093 | 1123 | | |
1094 | 1124 | | |
1095 | 1125 | | |
| |||
1507 | 1537 | | |
1508 | 1538 | | |
1509 | 1539 | | |
1510 | | - | |
1511 | | - | |
| 1540 | + | |
| 1541 | + | |
| 1542 | + | |
1512 | 1543 | | |
1513 | 1544 | | |
1514 | 1545 | | |
| |||
0 commit comments