Skip to content

Commit cf8b72f

Browse files
committed
docs(metadata-protocol): mark the OS_METADATA_WRITABLE case as CONTESTED, per the 2026-08-12 #8146 ruling
An in-flight maintainer ruling landed on #7682 after this work started: #8146 is settled as option B — a hatch write into a read-only package should REFUSE, the Studio badge is telling the truth, and the hatch is type-level by its own shipped documentation. The dispatch's instruction to "preserve and pin" that behaviour is therefore superseded, and the ruling says explicitly not to land a pin asserting it as correct. No behaviour change here. The hatch limb was never touched by this PR (it returns before the new package door), so nothing to revert; what changes is the CLAIM the suite and the changeset were making about it. The case is relabelled as a characterization pin of today's answer and kept, deliberately, as the tripwire the #8146 fix must invert. Re-measured on current main at that ruling's request, since the original measurement was against two-week-old builds: it still reproduces end to end through saveMetaItem on the host-config topology — `success: true`, and the row lands with `package_id = com.example.showcase`, i.e. bound INTO the read-only package rather than as the per-org override the variable's documentation describes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AmES43BMDg4bPrxTdi5q7t
1 parent fbefd17 commit cf8b72f

2 files changed

Lines changed: 49 additions & 22 deletions

File tree

‎.changeset/metadata-refusal-package-writability.md‎

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,20 @@ refused write that named a read-only base says so:
3535
this is the code selection inside the refusal branch, not a new gate. That
3636
distinction is load-bearing rather than cautious — an ADR-0005 org overlay names
3737
the read-only package it customizes *by construction*, so a package door that
38-
refused would close the overlay model itself. In particular the documented
39-
`OS_METADATA_WRITABLE` hatch is untouched: an env-hatch write into a read-only
40-
package (`OS_METADATA_WRITABLE=permission` + a `permission` set belonging to a
41-
read-only package) still succeeds, and is now pinned by a test — whether that
42-
hatch or Studio's badge is the correct semantics is a separate maintainer
43-
decision (#8146) and must move deliberately, not as a side effect of this fix.
44-
Writes that name no base keep the previous `NOT_OVERRIDABLE` / `NOT_CREATABLE`
45-
codes verbatim, and the DELETE verb is unchanged (#6960 moved that side on
46-
purpose; `DeleteOptions` names no package).
38+
refused would close the overlay model itself. Writes that name no base keep the
39+
previous `NOT_OVERRIDABLE` / `NOT_CREATABLE` codes verbatim, and the DELETE verb
40+
is unchanged (#6960 moved that side on purpose; `DeleteOptions` names no
41+
package).
42+
43+
The `OS_METADATA_WRITABLE` hatch is likewise untouched — structurally, because
44+
its limb returns before the new door. That is **not** an endorsement: the
45+
maintainer ruling of 2026-08-12 on #8146 holds that a hatch write into a
46+
read-only package should REFUSE, and the test covering it is labelled a
47+
characterization pin of today's behaviour so the #8146 fix must invert it rather
48+
than pass it silently. Re-measured on current `main` at that ruling's request:
49+
it still reproduces, and the row lands bound INTO the read-only package
50+
(`package_id = com.example.showcase`) rather than as the per-org override the
51+
variable's own documentation describes.
4752

4853
Reachability, stated so it is not mistaken for more than it is: this refusal is
4954
what answers on the host-config topology (`environmentId` undefined — the CLI's

‎packages/metadata-protocol/src/sys-metadata-repository.package-writability.test.ts‎

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,11 @@
3333
* - **no allow decision moves** — this is a code SELECTION inside the refusal
3434
* branch. An ADR-0005 overlay names the read-only package it customizes by
3535
* construction, so a package door that refused would close the overlay
36-
* model; and `OS_METADATA_WRITABLE` must keep unlocking exactly what it
37-
* unlocked before, because the hatch-vs-Studio-badge question is a separate
38-
* maintainer decision (#8146) that this card must not pre-empt.
36+
* model. `OS_METADATA_WRITABLE` is untouched for the same structural reason
37+
* (its limb returns before the door), and its case here is a CHARACTERIZATION
38+
* pin, not an endorsement: the 2026-08-12 ruling on #8146 says today's
39+
* answer is a bug, and that case is named and documented so the fix must
40+
* invert it rather than quietly pass it. See the case for the re-measurement.
3941
* - **delete is untouched** — #6960 moved the delete side deliberately and
4042
* warns against symmetrising; `DeleteOptions` carries no `packageId`.
4143
*/
@@ -255,14 +257,32 @@ describe('#7682 — the refusal discriminates on package writability', () => {
255257
expect(Array.from(engine.rows.values())[0]).toMatchObject({ package_id: READ_ONLY_PKG });
256258
});
257259

258-
it('[ruling] OS_METADATA_WRITABLE still unlocks a write into a READ-ONLY package', async () => {
259-
// The card's measured hatch case, at the layer that answers it:
260-
// `OS_METADATA_WRITABLE=permission` + a `permission` set belonging to the
261-
// read-only showcase package → the write SUCCEEDS. #7682's second half
262-
// (does the hatch or Studio's "Read-only" badge win?) is filed as #8146
263-
// and is the maintainer's to rule; this pin is what keeps that ruling
264-
// free to move the behaviour DELIBERATELY later, instead of it drifting
265-
// as a side effect of the code-selection fix.
260+
it('[CONTESTED — #8146 ruled this a BUG] OS_METADATA_WRITABLE currently unlocks a write into a READ-ONLY package', async () => {
261+
// ⛔ NOT an assertion that this behaviour is correct. Read the name.
262+
//
263+
// This is a CHARACTERIZATION pin of what `main` does today, and the
264+
// maintainer ruling of 2026-08-12 on #8146 (option B: "the server should
265+
// refuse — the badge is telling the truth") says today's answer is a bug:
266+
// the hatch is TYPE-level by its own shipped documentation
267+
// (`content/docs/deployment/environment-variables.mdx`, `OS_METADATA_WRITABLE`
268+
// — "treats them as `allowOrgOverride: true`"), so it has nothing to say
269+
// about the package dimension.
270+
//
271+
// It is kept, rather than deleted, because it is the tripwire: whoever
272+
// implements #8146 must INVERT this case, and a suite that simply went
273+
// quiet about the hatch would let that land without anyone re-reading
274+
// what the hatch is for. Re-measured on current `main` at the request of
275+
// that ruling (the original measurement was against two-week-old
276+
// builds): it still reproduces, end to end through `saveMetaItem` on the
277+
// host-config topology — `success: true`, and the row lands with
278+
// `package_id = com.example.showcase`, i.e. bound INTO the read-only
279+
// package rather than as the per-org override the documentation
280+
// describes.
281+
//
282+
// #7682's own fix does not touch this path: the hatch limb returns
283+
// before the package door, exactly as it did before. Which is the point
284+
// — the change under test neither preserves nor moves this deliberately;
285+
// it is orthogonal to it.
266286
process.env.OS_METADATA_WRITABLE = 'permission';
267287
resetEnvWritableMetadataTypes();
268288

@@ -278,8 +298,10 @@ describe('#7682 — the refusal discriminates on package writability', () => {
278298
});
279299

280300
it('without the hatch, that same permission write is refused by the package door', async () => {
281-
// The other side of the pin above: the hatch is doing the work, not an
282-
// accident of `permission` being overlay-capable.
301+
// The other side of the case above: the hatch is doing the work, not an
302+
// accident of `permission` being overlay-capable. This one IS an
303+
// assertion of correctness — with no hatch, the read-only base is what
304+
// the refusal names, which is #7682's whole point.
283305
const err = await putWith(repo, {
284306
type: 'permission', name: 'showcase_contributor', intent: 'override-artifact', packageId: READ_ONLY_PKG,
285307
});

0 commit comments

Comments
 (0)