Skip to content

A legacy env overlay on an artifact-backed item of a rolled-back type can no longer be REMOVED through the ordinary delete path (403) — only via OS_METADATA_WRITABLE #6960

Description

@os-zhuang

Observation-class finding, spotted while writing the ADR-0094 D5-R revision (#6858). Dormant today — the in-repo corpus has zero such rows (measured at PR #6608) — so nothing is user-visible right now. Filing plainly and leaving the grading to triage.

The asymmetry

#6483 / PR #6608 flipped ten types to allowOrgOverride: false. That closed the write door. It did not close the read path: supportsOverlay: true is unchanged for permission / position / page / app / dataset / book, so an overlay row authored before the rollback still merges overlay-wins at read time and still shapes the effective body.

Removing such a row is where it gets stuck. deleteMetaItem refuses an artifact-backed target of a non-overridable type on both paths, and neither is conditioned on an overlay row actually existing in a way that helps:

Net: on an environment carrying a pre-rollback overlay of an artifact-backed item, the row keeps applying and the ordinary "Reset to package default" flow answers 403. The only documented removal is the operator escape hatch, OS_METADATA_WRITABLE=(type).

Why it reads as unintended rather than ruled

The save-side gate carries a comment stating that deleteMetaItem is deliberately not gated the same way, with the reason that "removing a code-only row that predates this refusal is repair, and must stay possible". That reasoning applies verbatim to this case — a legacy overlay predating the rollback is exactly repair — but the carve-out as written only covers the code-only tier (allowRuntimeCreate: false AND allowOrgOverride: false), not the artifact-backed tier a rolled-back type now sits in. So the stated intent and the enforced behaviour diverge for this one shape.

Not asserting which side should move: a delete that lifts an overlay is strictly de-escalating on the authorization surface, which argues for allowing it; equally, "any write against an artifact-backed authorization item is refused" is a clean, defensible line that an operator hatch already relieves. That is a call for triage / the maintainer, not for this finding.

Blast radius

Zero in-repo today. It bites an environment that upgrades across the #6483 rollback while holding such a row, and the symptom is a Reset button that 403s with the item still customized. Scope is the metadata protocol and all rolled-back overlayable types, not ADR-0094 — which is why #6858 recorded the carry-over in ADR-0094 D5-R prose and filed this separately rather than widening its own change.

Refs: #6483, PR #6608, #6609 (ruling A), #6858 (the ADR-0094 revision that surfaced it), ADR-0005.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions