Skip to content

Commit ba672e1

Browse files
os-zhuangclaude
andauthored
chore(spec): the field-file collection proof stops being an orphan tag (#4298)
`packages/qa/dogfood/test/field-file-collection.dogfood.test.ts` declares `@proof: adr0104-field-file-collection`, but the ADR-0054 registry never learned about it — so the liveness gate has been warning on every run since #4285 landed the test: ⚠ 1 unregistered dogfood proof tag(s) — add to proof-registry.mts That warning is the registry's reverse-integrity leg doing exactly its job: an orphan tag means a proof was written but never wired into the high-risk class list, so nothing connects the test to the surface it guards. Registered as **honestly unbound**, not bound. The collection contract the proof exercises is the `lifecycle` ttl declared on the SYSTEM object `sys_file` (service-storage), not an authorable per-type property — and `object.lifecycle` is already bound to `data-lifecycle`, which carries one `proof` ref. The rest of the route (exclusive ownership, release-on-write, the per-deployment migration gate) is service code with no authorable surface to govern, so there is no other entry to bind instead. Faking a binding would misrepresent both what the proof covers and what that entry is proven by; `blockedReason` records the reason instead, the same shape as `flow-runas-userless` and `scope-depth-cli-fallback`. Enforcement is therefore unchanged: `BOUND_PROOF_PATHS` skips unbound classes, so the bound-class list and the pinned path map are byte-identical. The only behavioural change is that the gate now runs clean. Verification: `check:liveness` green with the warning gone; liveness script suite 98/98; spec suite 277 files / 7128 tests; `tsc --noEmit` clean. Gate-only change under `packages/spec/scripts/`, which is not in the package's published `files` — empty changeset. Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent ab16331 commit ba672e1

2 files changed

Lines changed: 28 additions & 0 deletions

File tree

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
---
3+
4+
chore(spec): register the `adr0104-field-file-collection` dogfood proof tag in the ADR-0054 registry, honestly unbound — the collection contract it guards is `lifecycle` on the system `sys_file` object, already bound to `data-lifecycle`. Gate-only (`packages/spec/scripts/`, not published), so this releases nothing.

packages/spec/scripts/liveness/proof-registry.mts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,30 @@ export const HIGH_RISK_CLASSES: HighRiskClass[] = [
482482
+ 'one entry would misrepresent both what it covers and what that entry is proven by. The '
483483
+ 'per-property bindings above carve out the parts that do have a single owner.',
484484
},
485+
{
486+
id: 'field-file-collection',
487+
label: 'Field-file collection (ADR-0104 PR-5b)',
488+
summary:
489+
'a field file released by its ONE owning record is tombstoned, and the sweep reclaims the row AND '
490+
+ 'the storage bytes once the declared window passes — with both vetoes intact: a tombstone that '
491+
+ 'regained an owner is un-tombstoned rather than reaped, and a REGRESSED migration flag stops '
492+
+ 'collection immediately (the guard re-reads the flag at sweep time instead of trusting the '
493+
+ 'memoized read the release path uses). This is the only code on the platform that deletes a '
494+
+ "user's bytes, and its sibling lineage — attachments — has had an end-to-end proof since #2755 "
495+
+ 'while field files, which reach collection by a different route (exclusive ownership, released '
496+
+ 'by the write path, gated per deployment), had none.',
497+
proofId: 'adr0104-field-file-collection',
498+
proofRef: 'packages/qa/dogfood/test/field-file-collection.dogfood.test.ts#adr0104-field-file-collection',
499+
bound: false,
500+
ledgerBindings: [],
501+
blockedReason:
502+
'the collection contract it guards is the `lifecycle` ttl declared on the SYSTEM object `sys_file` '
503+
+ '(service-storage), not an authorable per-type property — and `object.lifecycle` is already bound '
504+
+ 'to `data-lifecycle`, which carries one `proof` ref. The rest of the route (exclusive ownership, '
505+
+ 'release-on-write, the per-deployment migration gate) is service code with no authorable surface '
506+
+ 'to govern, so there is no other entry to bind instead. It runs unconditionally in the dogfood '
507+
+ 'suite.',
508+
},
485509
];
486510

487511
/** Bound ledger paths → the class that binds them. Key: `<type>/<path>`. */

0 commit comments

Comments
 (0)