Skip to content

[finding] a nested RETIRED_KEYS_BY_MAJOR row is unverifiable — check (b2) passes a fabricated one, so a typo'd nested retirement registers silently and forever #17969

Description

@zhuangjianguo

⚠️ CORRECTED AND RETITLED 2026-09-13T09:18Z by the seat that filed it (session_015c5G6TmpMKgnusmTpD7Ntt), before triage touched it. The original defect claim was wrong and is voided below; a real defect on the same machinery survives and is what this card now reports. The correction came from an at-tier contract review's ablation on PR #17954, ⛔ not from me rereading my own prose.

⛔ What I claimed and withdraw — quoted so the errata is legible

I filed this card asserting that two tombstoned tenant keys lacking RETIRED_KEYS_BY_MAJOR rows was itself a defect, and gave this as the cost:

⇒ these two tombstones can never age out. They are permanent, and nothing will ever say so.

That is false, and so was the framing I had already withdrawn once before filing ("consumers only learn by failing"). Two measurements kill it, both taken with controls:

  • packages/spec/scripts/build-schemas.ts:850-855 builds currentKeys from schema.propertiesone level deep only. A nested key such as connectionPool.idleTimeout never enters currentKeys, so it never enters newlyRetired, so check (b) never demanded a row for it. The omission was never a rule violation.
  • authorable-surface/system.json carries 0 dotted keys, against a lit control of 1241 top-level keys and 12 [RETIRED] markers. Check (c) ages [RETIRED] authorable-surface lines; a nested key has none, so there is nothing to age. "Can never age out" describes a clock that was never running.

⇒ The two rows are inert, not missing. Backfilling them would fix nothing. ⛔ Anyone reading the original claim should not act on it.

The real defect, which survives the correction

For a nested key the RETIRED_KEYS_BY_MAJOR row is inert on all three of its consumers — and one of those, check (b2), is supposed to be the guard that catches a wrong row. It cannot.

Check (b2) exists to refuse an entry naming a key the build still emits as LIVE:

(b2) The other direction: an entry that registers a key this build still emits as LIVE. Nothing consumed that registration — it pre-approves a retirement that has not happened, and check (b) would then wave the real one through without anyone writing it down.

Because its currentKeys map is top-level-only, a nested row matches nothing in it and is silently ignored rather than judged.

Measured by ablation (run during the PR #17954 contract review, registry restored byte-identical to HEAD 13a21281… afterwards):

probe check:authorable-surface
a fabricated nested row system/SchemaLevelIsolationStrategy:performance.zzNotARealKey9999 exit 0, zero ❌ — passes silently
lit control: system/SchemaLevelIsolationStrategy:strategy, a live top-level key exit 1 — refused, "names a key that is still LIVE … registered at major 18"

⇒ the pass is a reading, not an untested zero.

Consequence. A nested retirement row with a typo'd def, a typo'd path, or a stale key name enters the registry and is never contradicted — by (b), by (b2), or by (c). There are 36 nested rows under major 18 today; how many are accurate is not measured by this card and not measured by anything else. That is the declared-versus-enforced shape: the row is required by convention and by the #15679 shape, is written by hand into a generated-artefact source, and has no validator.

Scope, stated honestly

Possible shapes — ⛔ suggestions, none costed by this seat

  1. Teach the currentKeys walk to descend into nested object properties so (b) and (b2) both see nested keys. ⚠️ Widens (b) too, which would then start demanding rows for nested retirements that today owe none — a behaviour change, not just a validation fix.
  2. Give (b2) a nested-aware limb only: verify a registered nested path resolves to something in the emitted schema graph, without making (b) demand new rows.
  3. Leave it and record the blind spot where the row is written.

Dedupe

search_issues for the tombstone / registration phrasings ⇒ 0, and that zero is a reading: the same instrument on a control query returns 9 including #15939 and four of its sub-issues. Distinct from #17955 (T1 fires on a retiredKey() line), #17926 (T4 error-code provenance) and #15642 (the duration gate's scanned subtree) — those are check-widening-tells classification defects; this is a missing validator in build-schemas.ts.

⛔ Still filed bare — no domain:*, no priority:*, no type. Triage owns all three, and the retitle does not pre-empt the grading.

epic PM for #15939 · session_015c5G6TmpMKgnusmTpD7Ntt · filed 08:58Z, corrected 09:18Z

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions