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
The metadata write refusal answers a different code per TOPOLOGY: saveMetaItem's scoped-kernel branch refuses before the repository's package door ever runs #8184
Fallout found while implementing #7682 (package-writability discrimination in SysMetadataRepository.assertAllowed). Filed rather than fixed: #7682's dispatch declared sys-metadata-repository.ts as its file surface and explicitly forbade editing protocol.ts, which two other cards (#8136, #8003) are editing concurrently.
The two refusal points
An artifact-backed write of a type without allowOrgOverride is refused twice over, and which one answers depends on the kernel's environmentId — a row-scoping key, not a topology declaration:
packages/metadata-protocol/src/protocol.ts, inside saveMetaItem, guarded by if (this.environmentId !== undefined) (search for the not_overridable message beginning "is provided by a code package and the type has not opted into per-org overlay writes"). Emits 403 NOT_OVERRIDABLE, reads no package.
The QA run behind #7682 (#7637) measured the first row, which is why #7682's fix lands there.
Why it is worth closing
This is the same class of finding #5086 and #6710 already closed twice in this method: "keying authorization off a row-scoping key is what made a type-level declaration depend on deployment topology" (protocol.ts, the #5086 block comment). The refusal VOCABULARY now depends on it too — a cloud tenant and a self-hosted tenant get different machine-readable codes for the same refused write, and a client that learns to handle ITEM_LOCKED on one will not see it on the other.
Note it is not a regression: point 1 answered NOT_OVERRIDABLE before #7682 as well. #7682 makes the divergence visible rather than creating it.
Suggested shape (not a ruling)
Have point 1 consult the same shared isWritablePackage predicate (packages/metadata-protocol/src/package-writability.ts) that the ADR-0070 D1 gate a few hundred lines below it and the repository door both use, so one condition keeps one vocabulary on every kernel. The alternative — deleting point 1 and letting the repository answer on all topologies — is the larger change and would need its own reading of why the scoped branch exists.
packages/metadata-protocol/src/sys-metadata-repository.package-writability.test.ts (added by #7682) states this boundary in its final describe block, so whoever picks this up has the reachability argument and a harness already written.
What this is
Fallout found while implementing #7682 (package-writability discrimination in
SysMetadataRepository.assertAllowed). Filed rather than fixed: #7682's dispatch declaredsys-metadata-repository.tsas its file surface and explicitly forbade editingprotocol.ts, which two other cards (#8136, #8003) are editing concurrently.The two refusal points
An artifact-backed write of a type without
allowOrgOverrideis refused twice over, and which one answers depends on the kernel'senvironmentId— a row-scoping key, not a topology declaration:packages/metadata-protocol/src/protocol.ts, insidesaveMetaItem, guarded byif (this.environmentId !== undefined)(search for thenot_overridablemessage beginning "is provided by a code package and the type has not opted into per-org overlay writes"). Emits403 NOT_OVERRIDABLE, reads no package.packages/metadata-protocol/src/sys-metadata-repository.ts—assertAllowed, the topology-INDEPENDENT gate. After readonly-package-locks-studio: the read-only metadata refusal keys on the metadata type's overlay policy, not package writability (ITEM_LOCKED / WRITABLE_PACKAGE_REQUIRED never emitted) #7682 this one reads the base the caller named and answers403 ITEM_LOCKED(read-only base) /422 WRITABLE_PACKAGE_REQUIRED(runtime-only into a read-only base) /403 NOT_OVERRIDABLE(writable or unnamed base).Point 1 shadows point 2 whenever it runs. So after #7682, the SAME request answers differently per deployment shape:
PUT /api/v1/meta/object/showcase_task?package=READONLY_PKGenvironmentIdundefined — the flagship showcase, self-hosted servers)403 ITEM_LOCKED,lockSource: packageenvironmentIdset)403 NOT_OVERRIDABLE— package never readThe QA run behind #7682 (#7637) measured the first row, which is why #7682's fix lands there.
Why it is worth closing
This is the same class of finding #5086 and #6710 already closed twice in this method: "keying authorization off a row-scoping key is what made a type-level declaration depend on deployment topology" (
protocol.ts, the#5086block comment). The refusal VOCABULARY now depends on it too — a cloud tenant and a self-hosted tenant get different machine-readable codes for the same refused write, and a client that learns to handleITEM_LOCKEDon one will not see it on the other.Note it is not a regression: point 1 answered
NOT_OVERRIDABLEbefore #7682 as well. #7682 makes the divergence visible rather than creating it.Suggested shape (not a ruling)
Have point 1 consult the same shared
isWritablePackagepredicate (packages/metadata-protocol/src/package-writability.ts) that the ADR-0070 D1 gate a few hundred lines below it and the repository door both use, so one condition keeps one vocabulary on every kernel. The alternative — deleting point 1 and letting the repository answer on all topologies — is the larger change and would need its own reading of why the scoped branch exists.packages/metadata-protocol/src/sys-metadata-repository.package-writability.test.ts(added by #7682) states this boundary in its finaldescribeblock, so whoever picks this up has the reachability argument and a harness already written.Related
OS_METADATA_WRITABLEunlocks a write on a read-only package while Studio renders a "Read-only" badge — which one is telling the truth? #8146 — the separateOS_METADATA_WRITABLEhatch vs Studio "Read-only" badge decision.