Skip to content

[Decision] ADR-0049's declaration surface has two halves and only one is governed — platform-object row columns on security objects have no liveness ledger, and both #8894 ground-truth instances live there #9054

Description

@os-project-manager

Filed by the domain:devx PM seat (#6023, session session_011RB4waLuNbdruCo6X9oobm) from the #8894 measurement. Unassigned. ⛔ No domain:* set — triage's field, and the landing package depends on which option is chosen.

This is not the question #8894 asked, which is why it is not being closed inside it.#8894 was ruled "a measurement, not a gate", the measurement was taken, and it closed on its own terms: the enumeration oracle is not mechanizable in the read-determination half (measured by ablation — the oracle stays green across sys_permission_set.active's entire inert life; 2 of 4 ground-truth instances missed, and they are the two the card was filed about). Full numbers in #8894 comment 5306337804.

What the measurement surfaced on the way is a governance gap that is bigger than the card, and it needs its own ruling.

The gap, as measured

ADR-0049's "declared = enforced" surface has two halves:

Measured size of the ungoverned half: 10 security objects (plugin-security + plugin-sharing, off the curated PLATFORM_OBJECTS_BY_PACKAGE registry), 88 candidate security keys and 9 actions. Widening to identity takes it to 29 objects / ~240 keys.

Both of #8894's ground-truth instances live in the ungoverned half — that is not a coincidence, it is the reason the class keeps recurring. Recurrence is measured, not asserted: #8613, #8811, #8535 inside one week, and #9046 was found within an hour of simply pointing an enumerator at the surface. The class is not exhausted.

Options

  • A — Nothing. Close with the measurement; the class keeps being found by hand, roughly as it has been.
  • B — Extend the existing packages/spec/liveness ledger to platform-object row columns on security objects. One ledger, one vocabulary, reuses live machinery. Cost: 88 verdicts with evidence to backfill, and the boundary (10 security objects, or 29 with identity) becomes a ruling of its own.
  • C — A new, narrower ledger for just the RBAC grant catalogues (sys_permission_set, sys_position, sys_user_*), ~40 keys.

Four-prism

  • Platform long-term coherencefor B. Leaving one ADR's surface half-governed and half-not is exactly the drift the contract-first posture exists to prevent. ⛔ And it argues for one ledger: a second ledger over the same ADR is the divergence The ADR-0056 D10 authz conformance matrix has no row for the grant-catalogue active flag, and its completeness check cannot notice #8711 just spent a whole card narrowing, so C is dominated by B on this prism and should not be chosen for cheapness alone.
  • Measured business pullcuts both ways, honestly. Four instances in a week is real recurrence. But the consumer of a ledger is a human reading it, and the implementing dev reports this repo has a hard number for how well that goes: 10 of 13 re-verified entries in the sibling ledger were wrong (77%). ⚠️ That figure is the dev's measurement and I have not independently re-derived it — it is load-bearing enough that it should be re-checked before it decides anything.
  • AI-agent error-resistancethis is the prism that stops me short of recommending B. The failure mode is an agent declaring a key the runtime never enforces. A ledger catches that only if the verdict is right, and a ledger row is a comfortable place for an agent to write a confident wrong sentence with a citation attached. The local proof is sys_capability.active: its Deactivate prose asserted an enforcement that never existed, so a row written from the declaration would have read "live" — the ledger would have certified the exact falsehood it exists to catch. Compare what did work: a bare enumeration with no verdict attached found [finding] The ADR-0091 D5 recertification columns (last_certified_at / certified_by) are declared on both grant tables and nothing writes or reads them #9046 in minutes, because "here are 88 keys, four have no reader at all" is checkable and "this key is live because X" is not.
  • Startup scope disciplinefor A. 88 hand-written verdicts is a real backfill, and a permanent maintenance obligation on every future card.

Recommendation: A now, and B only if you want it — ⛔ never C

The prisms do not align and I am not going to manufacture agreement between them: coherence wants B, error-resistance wants the enumerator without the ledger, business pull splits. That disagreement is the finding, not a failure to decide.

What I would do absent an instruction: keep the enumeration halves alive as an on-demand instrument (they are mechanical, they are already written, and they are the part that demonstrably works), and not build a verdict ledger over them. A gate addition is a standing obligation on every future card, which both the triage seat and the 2026-08-16 ruling placed with you.

⚠️ If you rule B, the boundary question (10 objects vs 29) needs answering in the same stroke, or it becomes a second decision six weeks from now.

Refs: #8894 (the measurement + the fork) · #9046 (the fourth instance, found by enumeration) · #8613 · #8811 · #8535 · #8711 (the ledger-divergence precedent) · ADR-0049 · ADR-0091 D5.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions