Repository navigation
Commit 3ca71b6
fix(metadata-protocol)!: one reader of OS_METADATA_WRITABLE — the legacy OBJECTSTACK_METADATA_WRITABLE, removed in 11.0, no longer opens the hatch at the type listing (#22440)
Fixes #22411
Clause-②: no (narrowing)
## What
`OS_METADATA_WRITABLE` now has one reader.
`ObjectStackProtocolImplementation.envWritableTypes()` feeds `GET
/api/v1/meta/types` and the protocol's write gates (`isOverlayAllowed`:
the code-only create gate and the org-scope gate). It now delegates to
the repository's `envWritableMetadataTypes()`, which reads
`OS_METADATA_WRITABLE` only. `resetEnvWritableCache()` and
`resetEnvWritableMetadataTypes()` both clear that reader's single cache.
Under the legacy spelling alone, the listing and the save door now
agree, because both refuse.
## Why
The 11.0 release removed ObjectStack's own legacy env names as a
published breaking change. That was fdb41c0 (PR #2383), with the
`v11-remove-env-aliases` changeset in the 11.1.0 CHANGELOG of
`@objectstack/cli`, `@objectstack/objectql` and `@objectstack/types`,
and `docs/upgrading-to-11.md:121`. The change edited the repository's
reader and missed the protocol's hand-copied one, which kept honouring
`OBJECTSTACK_METADATA_WRITABLE`.
Measured on `origin/main` e02833c at the dispatcher `/meta` door, on
both kernel shapes, with only `OBJECTSTACK_METADATA_WRITABLE=job` set:
- `GET /meta/types` listed `job` with `allowOrgOverride: true` and
`overrideSource: env`;
- `PUT /meta/job/NEW` answered `403 NOT_CREATABLE` and stored no row.
The seat's ruling on the card (comment 6076328784) is option B: finish
11.0's removal at the reader it missed. That ruling supersedes the
card's earlier "do not retire the alias on this card" line. Premise
re-checked on `b9222dc70` before building: `git grep
OBJECTSTACK_METADATA_WRITABLE` finds no non-test producer. The non-test
hits are prose (docs, ADR-0010, the S2 changeset) plus the reader
itself. The positive control, `OS_AUTH_SECRET` over `docker/`,
`examples/` and `apps/`, finds 5 hits.
## Changes
- `packages/metadata-protocol/src/sys-metadata-repository.ts`:
`envWritableMetadataTypes` is exported at module level and its TSDoc
names it the one reader. The package index does not re-export it, so the
public surface is unchanged.
- `packages/metadata-protocol/src/protocol.ts`: `envWritableTypes`
delegates to it, `resetEnvWritableCache` clears the shared cache, and
the now-unused `readEnvWithDeprecation` import is removed.
- S2's dual-spelling pins keep their preferred-spelling legs. Their
legacy legs flip to "the hatch is shut", and each keeps the preferred
spelling as its control:
- `protocol.packaged-base-refusal.test.ts`: the listing reports `flow`
and `page` as `allowOrgOverride: false` with `overrideSource: registry`,
and every managed-item verdict equals the shut one.
- `packages/rest` `rest-meta-managed-seal-hatch.test.ts`: the same
listing reading via `GET /api/v1/meta/types`, and every PUT (and DELETE,
on an environment kernel) answers what it answers with nothing set.
- `packages/runtime` `meta-managed-content-seal.test.ts`: the card's
pins at the dispatcher door. Under the legacy spelling alone, both `job`
(the type named) and `picklist` (a type not named) are listed shut and
saved `403 NOT_CREATABLE` with no row. Control,
`OS_METADATA_WRITABLE=job`: `job` is listed `env` and saved `200` with a
row, and `picklist` is still refused.
- `content/docs/deployment/environment-variables.mdx`: the alias row
goes back into the "Removed in 11" note, which undoes the move made in
PR #2640.
- `.changeset/22411-hatch-legacy-spelling.md`: **BREAKING** on
`@objectstack/metadata-protocol`, graded `minor` on the v18 pre line. It
names the FROM and TO spellings and the one-line operator fix, and says
it finishes 11.0's removal at the reader that kept it. ADR-0087
disposition: `not-required (no-migration-prescription)`.
`check:adr-0087-registration` exits 0.
## Verification (head adbb0a5)
- `pnpm --filter @objectstack/metadata-protocol test`: 223 files passed,
3 skipped; 28330 tests passed, 19 skipped. Lock VERDICT command-exit 0.
- Typecheck: `pnpm --filter @objectstack/metadata-protocol run
typecheck` exits 0. The `rest` and `runtime` `run typecheck` runs also
exit 0, and their `check:test-typecheck` passes over each package's
`tsconfig.test.json`.
- The three edited pin files: runtime 10/10, rest 7/7, metadata-protocol
31/31.
- Every other test file in the downstream packages that touches the
hatch passes:
- objectql: 8 files, 176 tests;
- plugin-security: 3 files, 40 tests;
- rest: 4 files, 36 tests;
- runtime: 3 files, 38 tests.
Those suites read `@objectstack/metadata-protocol` through `dist/`,
which was rebuilt from this branch first.
- Gates: `node scripts/pm/dispatch-gates.mjs --repo
objectstack-ai/objectstack --commands` derives 94 commands. All were
run, plus the 4 roster gates whose roster sits under a changed directory
(`check-changeset-fixed`, `check:authz-resolver`,
`check:error-code-casing`, `check:route-ledger-census`). `--ran` reports
94 derived, 94 run, 0 NOT-MEASURED, 0 UNRUN. Two gates first answered
PREREQUISITE NOT MET (exit 3) for unbuilt dists: `check:skill-examples`
and `check:dual-build-cjs-loads`. Both were re-run after the builds at
the same head, and both exit 0.
- Lint: the narrowing is proven, not assumed. `eslint --no-inline-config
--format json` over the 5 changed TS files reports 5 files, 0 errors and
0 warnings. eslint's own config ignores the `.md` and `.mdx` ("File
ignored because no matching configuration"). The config enables no
type-aware linting: no `parserOptions.project` or `projectService`, and
0 typed rules in `--print-config` for `protocol.ts`. So this diff cannot
move the verdict on any untouched file.
- Not measured locally, owned by CI: the dogfood boots
(`managed-content-sealed.dogfood.test.ts` mentions the legacy spelling
only in a comment) and the full `rest` and `runtime` suites.
## Reverse verification of the one reader
`scripts/ablation-replace.mjs` put the protocol's second,
legacy-honouring reader back inside `envWritableTypes`. On disk: anchor
1 to 0, blob `0cf53ab1` to `ef809f30`.
- **src, no build:** `protocol.packaged-base-refusal.test.ts` gives 2
failed and 29 passed. The 2 failures are exactly the legacy-shut cases,
on both kernels.
- **dist, rebuilt:** after rebuilding `@objectstack/metadata-protocol`,
`ablation-dist-preflight` finds the marker in `dist/index.js` and
`dist/index.cjs`.
- runtime: 2 failed, 8 passed. The failures are the card's legacy-alone
case on both kernels; under the mutation the listing answered
`allowOrgOverride: true` / `env` again.
- rest: 2 failed, 5 passed. The failures are the legacy-shut cases.
- **Restore:** the blob equals HEAD and `git diff HEAD` is empty. After
the rebuild, preflight `--absent` passes on all 24 built files with a
clean tree. The green legs come back at 31/31, 10/10 and 7/7.
The result went the expected way: the pins turned red.
## Acceptance notes
- `docs/adr/0010-metadata-protection-model.md` (`:42`, `:301`, `:540`,
`:652`) still describes `OBJECTSTACK_METADATA_WRITABLE` as the live
variable. That file is Tier H and pre-11 history, and per the ruling it
stays with the seat, outside this code PR.
- The changeset states the operator action as a sentence naming FROM, TO
and the fix, not as a FROM / TO table row. With a table row,
`check:adr-0087-registration` refuses `not-required
(no-migration-prescription)` (evidence: header-framed-table). Its closed
vocabulary has no category for a deployment-environment rename:
- `registered` would put a prescription in the ledger that `os migrate
meta` cannot project;
- `unpublished` and `already-registered` do not apply;
- dropping BREAKING is forbidden.
The marker says this in writing, following the precedent of
plugin-auth's `OS_PLATFORM_OWNER_EMAIL` changeset. Who takes up that
vocabulary gap: nobody yet.
- Under the legacy spelling alone, the save door's refusal now comes
from the protocol's code-only gate, not the repository's. Code and
status are unchanged (`403 NOT_CREATABLE`). Nothing reads the legacy
name any more, so its deprecation warning no longer prints.
- Left as written because they are still true: the S2 changeset's "(and
its legacy spelling …) used to open one", the dogfood header comment,
and the `sys-metadata-repository.package-writability.test.ts` legacy
case comment ("this reader honours only `OS_METADATA_WRITABLE`").
---
_Generated by [Claude
Code](https://claude.ai/code/session_01Bw3y2DWhT9RPnrmDsNqEVG)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 2b61f2d commit 3ca71b6
7 files changed
Lines changed: 349 additions & 145 deletions
File tree
- .changeset
- content/docs/deployment
- packages
- metadata-protocol/src
- rest/src
- runtime/src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
374 | 374 | | |
375 | 375 | | |
376 | 376 | | |
377 | | - | |
| 377 | + | |
378 | 378 | | |
379 | 379 | | |
380 | 380 | | |
| |||
391 | 391 | | |
392 | 392 | | |
393 | 393 | | |
394 | | - | |
395 | 394 | | |
396 | 395 | | |
Lines changed: 82 additions & 36 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
18 | | - | |
19 | | - | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
20 | 21 | | |
21 | | - | |
22 | | - | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
23 | 25 | | |
24 | 26 | | |
25 | 27 | | |
| |||
46 | 48 | | |
47 | 49 | | |
48 | 50 | | |
49 | | - | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
50 | 55 | | |
51 | 56 | | |
52 | 57 | | |
| |||
120 | 125 | | |
121 | 126 | | |
122 | 127 | | |
123 | | - | |
124 | | - | |
125 | | - | |
126 | | - | |
127 | | - | |
128 | | - | |
129 | | - | |
130 | | - | |
131 | | - | |
132 | | - | |
133 | | - | |
134 | | - | |
135 | | - | |
136 | | - | |
137 | | - | |
138 | | - | |
139 | | - | |
140 | | - | |
141 | | - | |
142 | | - | |
143 | | - | |
144 | | - | |
145 | | - | |
146 | | - | |
147 | | - | |
148 | | - | |
149 | | - | |
150 | | - | |
151 | | - | |
152 | | - | |
153 | | - | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
154 | 200 | | |
155 | 201 | | |
156 | 202 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
7 | | - | |
| 7 | + | |
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| |||
43 | 43 | | |
44 | 44 | | |
45 | 45 | | |
46 | | - | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
47 | 54 | | |
48 | 55 | | |
49 | 56 | | |
| |||
15860 | 15867 | | |
15861 | 15868 | | |
15862 | 15869 | | |
15863 | | - | |
| 15870 | + | |
| 15871 | + | |
| 15872 | + | |
| 15873 | + | |
| 15874 | + | |
| 15875 | + | |
| 15876 | + | |
| 15877 | + | |
| 15878 | + | |
15864 | 15879 | | |
15865 | 15880 | | |
15866 | | - | |
15867 | 15881 | | |
15868 | | - | |
15869 | | - | |
15870 | | - | |
15871 | | - | |
15872 | | - | |
15873 | | - | |
15874 | | - | |
15875 | | - | |
15876 | | - | |
15877 | | - | |
15878 | | - | |
15879 | | - | |
15880 | | - | |
15881 | | - | |
15882 | | - | |
15883 | | - | |
| 15882 | + | |
| 15883 | + | |
| 15884 | + | |
| 15885 | + | |
15884 | 15886 | | |
15885 | | - | |
| 15887 | + | |
15886 | 15888 | | |
15887 | 15889 | | |
15888 | 15890 | | |
| |||
Lines changed: 19 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
359 | 359 | | |
360 | 360 | | |
361 | 361 | | |
362 | | - | |
363 | | - | |
364 | | - | |
365 | | - | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
366 | 375 | | |
367 | 376 | | |
368 | | - | |
| 377 | + | |
369 | 378 | | |
370 | 379 | | |
371 | 380 | | |
| |||
381 | 390 | | |
382 | 391 | | |
383 | 392 | | |
384 | | - | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
385 | 398 | | |
386 | 399 | | |
387 | 400 | | |
| |||
0 commit comments