You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 3ca71b6
Browse filesBrowse the repository at this point in the historyBrowse files
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>
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 either
6
+
7
+
Clause-②: no (narrowing)
8
+
9
+
<!-- adr-0087: not-required (no-migration-prescription) nothing authorable is removed, renamed or narrowed: no spec key, no metadata spelling, no export and no stored row changes shape, so there is nothing for `os migrate meta` to rewrite and no ledger entry to make. The operator action below is a deployment-environment rename, which the ADR-0087 ledger does not carry; 11.0 already published it, and this change makes the last reader honour it. -->
10
+
11
+
**BREAKING**, graded `minor` on the v18 prerelease line: Changesets is in pre mode with the tag `next`, and the fixed group is already majored by the line's opening marker, so this ships in an `18.0.0-next.N`.
12
+
13
+
This finishes 11.0's removal at the reader that kept it. The 11.0 release removed ObjectStack's own legacy environment-variable names, `OBJECTSTACK_METADATA_WRITABLE` among them. That change edited one of the two readers of `OS_METADATA_WRITABLE` (the metadata repository's write gate) and missed the other (the protocol's, which feeds `GET /api/v1/meta/types` and the protocol's write gates). So with only the legacy spelling set, the type listing reported a named type as writable (`allowOrgOverride: true`, `overrideSource: 'env'`), while creating a new item of that type answered `403 NOT_CREATABLE`. One deployment gave two answers to one question.
14
+
15
+
**What changes.** The protocol now reads the setting through the repository's reader, so there is one reader and it reads `OS_METADATA_WRITABLE` only. With only `OBJECTSTACK_METADATA_WRITABLE` set, the hatch is shut everywhere: the listing reports no env override, and every write the hatch would open is refused as it is with nothing set. No deprecation warning is printed for the legacy name any more, because nothing reads it.
16
+
17
+
**What does not change.**`OS_METADATA_WRITABLE` behaves exactly as before.
18
+
19
+
**Operator action.** A deployment that still sets `OBJECTSTACK_METADATA_WRITABLE` sets `OS_METADATA_WRITABLE` in its place, with the same comma-separated type list. This is the rename 11.0 already published; nothing else changes.
Copy file name to clipboardExpand all lines: content/docs/deployment/environment-variables.mdx
+1-2Lines changed: 1 addition & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -374,7 +374,7 @@ the hosted ObjectOS Cloud control plane.
374
374
375
375
Some env vars accept a legacy alias for compatibility. **Ecosystem-standard names** (e.g. `DATABASE_URL`, `AUTH_SECRET`, `BETTER_AUTH_*`, `PORT`, `CORS_*`, `MCP_SERVER_*`) are permanently accepted and no longer warn. ObjectStack's own former names are deprecated — prefer the canonical `OS_*`.
0 commit comments