Skip to content

Commit c35b9bf

Browse files
committed
docs: resolve ADR 0018 open question 5 -- one fold into sha256-canon-v1
Adds ADR 0018 section 15 and DECISIONS D25. The eight hash-affecting manifest additions land in one pass, into v1, before any real package is signed - not behind a v2. Why v1: a hash scheme version exists to protect history, and there is no history to protect. Minting a v2 to carry additions no v1 package ever saw leaves a version boundary that records nothing and that every future reader has to learn about. D6 is amended, not reversed. Its own reasoning - that hash semantics are hard to change once real records exist - argues for completing the allowlist now, because the allowlist is exactly the thing that becomes unchangeable. D6 conflated two separable questions: the canonical form and manifest allowlist, which get strictly more expensive with delay and are unfrozen here, and acceptance of ADR 0010 as a whole, which stays blocked on gates this work does not touch - C4's not-a-qualified -e-signature wording, required-role semantics, and the D12 contract bump. ADR 0010 stays Proposed with a completed allowlist, which is a coherent state: the bytes are settled, the legal and contract questions are not. Recorded as a real precondition rather than an assumption: the builder and canonicalizer are already shipped and running, with a golden-vector self-check on load, so this is a code change. Confirm no turnover_packages record carrying real signatures exists on any live instance before the fold ships. If one does the decision inverts and the additions go behind v2 - a signed package that stops verifying is the outcome this ADR exists to prevent. Partial folds are forbidden: each addition alone changes the canonical bytes, so piecemeal shipping means several silent breaks instead of one deliberate one. The golden vector is regenerated as the acceptance test. Also completes the turnover-additions list with the two decided since it was written - active operating restrictions per subject (section 13) and template_version on every included check (section 14) - and marks signature-role QC unblocked in the conflicts table.
1 parent ad50f1b commit c35b9bf

3 files changed

Lines changed: 106 additions & 6 deletions

File tree

‎docs/DECISIONS.md‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,3 +307,31 @@ engine scope LoopCheck refuses to become.
307307
**Rejected.** Hard-blocking phase entry; a dedicated `gates` collection (a
308308
gate is a check).
309309
**Cross-ref.** ADR 0018 §12; ADR 0007.
310+
311+
### D25 — D6 amended — the turnover manifest folds into `sha256-canon-v1` now
312+
**Decision.** ADR 0018's eight hash-affecting manifest additions land in **one
313+
pass, into `sha256-canon-v1`**, before any real package is signed — not behind a
314+
`sha256-canon-v2`. D6 is **amended, not reversed**: the canonical form and
315+
manifest allowlist are unfrozen for this fold, while ADR 0010's *acceptance*
316+
stays blocked on its own gates (the "not a qualified e-signature" wording C4,
317+
required-role semantics, and the D12 contract bump). ADR 0010 stays **Proposed**
318+
with a completed allowlist. Partial folds are forbidden — each addition alone
319+
changes the canonical bytes, so piecemeal shipping means several silent breaks
320+
instead of one deliberate one. The golden vector is regenerated as the
321+
acceptance test.
322+
**Precondition.** The builder and canonicalizer are already shipped and running,
323+
so this is a code change. **Confirm no `turnover_packages` record carrying real
324+
signatures exists on any live instance before the fold lands.** If one does, the
325+
decision inverts and the additions go behind `sha256-canon-v2`; a signed package
326+
that stops verifying is the outcome the ADR exists to prevent. Test packages are
327+
discarded, not migrated.
328+
**Rationale.** A hash version exists to protect history, and there is no history
329+
to protect. A v2 carrying additions no v1 package ever saw would leave a version
330+
boundary that records nothing. D6's own reasoning — that hash semantics are hard
331+
to change once real records exist — argues *for* completing the allowlist now,
332+
because the allowlist is exactly the thing that becomes unchangeable. D6
333+
conflated the canonical form with acceptance of the ADR; they are separable, and
334+
only one of them gets more expensive with delay.
335+
**Rejected.** Accepting ADR 0010 wholesale (its legal and contract gates are
336+
untouched by this work); minting `sha256-canon-v2` (no history to protect).
337+
**Cross-ref.** ADR 0018 §15 and open question 5; ADR 0010; D6, D12.

‎docs/adr/0010-signatures-and-turnover-package.md‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,23 @@
22

33
**Status:** proposed · **Date:** 2026-07-10
44

5+
> **The manifest allowlist and canonical form are unfrozen for one fold**
6+
> (2026-08-04, DECISIONS **D25** amending D6). ADR 0018 adds eight
7+
> hash-affecting entries to the manifest, and they land **together, in
8+
> `sha256-canon-v1`** — not a v2 — because no real package has been signed, and
9+
> a version boundary that protects no history is worse than none. See
10+
> [ADR 0018 §15](0018-multi-vendor-startup-evidence-model.md) for the decision
11+
> and the enumerated additions.
12+
>
13+
> **Precondition before the fold ships:** confirm no `turnover_packages` record
14+
> carrying real signatures exists on any live instance. If one does, the
15+
> additions go behind `sha256-canon-v2` instead. The golden vector is
16+
> regenerated as the acceptance test; **partial folds are forbidden**, since
17+
> each addition alone changes the canonical bytes.
18+
>
19+
> **This does not accept ADR 0010.** C4's on-page wording, required-role
20+
> semantics, and the D12 contract bump still gate acceptance.
21+
522
**Implementation status (committed + review-hardened, 2026-07-12):** the
623
migration (`turnover_packages` + `signatures`, `1789000026`), the server
724
builder/canonicalizer (`pb_hooks/turnover.pb.js` + `turnover_canon.js`, with a

‎docs/adr/0018-multi-vendor-startup-evidence-model.md‎

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,56 @@ manifest additions in the single fold that open question 5 recommends —
627627
real package is signed and v1 is simply defined to include it. **Decide and land
628628
this together with open question 5, not after it.**
629629

630+
### 15. One fold into `sha256-canon-v1`, before any package is signed
631+
632+
**Decided by the maintainer 2026-08-04, resolving open question 5.**
633+
634+
Every manifest addition in this ADR is hash-affecting. The choice was to absorb
635+
them all into `sha256-canon-v1` now, or accept ADR 0010 as it stands and retire
636+
v1 into a `v2` later. **The fold happens now, in one pass, into v1.**
637+
638+
**Why v1 rather than v2.** A hash scheme version exists to protect *history* —
639+
it lets old packages keep verifying under the rules they were sealed with. There
640+
is no history to protect: **no real package has been signed.** Minting a v2 to
641+
carry additions that no v1 package ever saw would leave a version boundary that
642+
records nothing, and every future reader would have to learn a distinction that
643+
never mattered. The cheap moment is the one where the cost is zero, and it does
644+
not come back.
645+
646+
**Precondition, and it is a real one.** ADR 0010's builder and canonicalizer are
647+
**already shipped and running** (`pb_hooks/turnover.pb.js`,
648+
`turnover_canon.js`, with a golden-vector self-check on load). So this is a code
649+
change, not a documentation change. Before the fold lands, **confirm no
650+
`turnover_packages` record carrying real signatures exists on any live
651+
instance.** If one does, this decision inverts on the spot and the additions go
652+
behind `sha256-canon-v2` — a signed package that stops verifying is the one
653+
outcome this whole ADR exists to prevent. Test packages are discarded, not
654+
migrated.
655+
656+
**Scope of the fold** — the eight additions listed above, landing together, with
657+
the **golden vector regenerated** as the acceptance test. Partial folds are
658+
forbidden: each one alone would change the canonical bytes, so shipping them
659+
piecemeal means several silent breaks instead of one deliberate one.
660+
661+
**This does not accept ADR 0010, and D6 is amended rather than reversed**
662+
(DECISIONS D25). D6 froze ADR 0010 on the reasoning that "accepting it now
663+
hardens hash/attestation semantics that are hard to change once real records
664+
exist." That reasoning **argues for this fold, not against it** — the allowlist
665+
is precisely the thing that becomes unchangeable, so it is the thing to get
666+
complete while it is still free. D6 conflated two separable questions:
667+
668+
- **the canonical form and manifest allowlist** — unfrozen by this decision,
669+
because delay makes it strictly more expensive and never cheaper;
670+
- **acceptance of ADR 0010 as a whole** — still blocked, on gates this ADR does
671+
not touch: the "not a qualified e-signature" wording (C4), required-role
672+
semantics, and the API v1 contract bump (D12).
673+
674+
So ADR 0010 stays **Proposed** with a completed allowlist. That is a coherent
675+
state: the bytes are settled, the legal and contract questions are not.
676+
677+
**Unblocks §9.** The Conflicts table below recorded signature-role QC as
678+
"blocks on open question #5." It no longer does.
679+
630680
## What all of this adds to the frozen turnover package
631681

632682
ADR 0010's manifest gains, per scope:
@@ -645,11 +695,17 @@ ADR 0010's manifest gains, per scope:
645695
ADR.
646696
6. **As-left conditions and scope-gap punch items** rendered as their own
647697
sections rather than buried in the punch list (§6).
698+
7. **Active operating restrictions, per subject** (§13) — the limit as data with
699+
its cause and provenance. The one section whose primary reader is the
700+
operator years later rather than the GC at turnover.
701+
8. **`template_version` on every included check** (§14) — the index that says
702+
which revision of the questions a frozen answer set was complete for.
648703

649704
Each addition is an allowlisted set of immutable fields entering the
650705
`sha256-canon-v1` canonical bytes, so **every one of them is a hash-affecting
651706
change** and must land before the first real package is signed, or behind a
652-
`sha256-canon-v2`. That is the sharpest sequencing constraint in this ADR.
707+
`sha256-canon-v2`. That is the sharpest sequencing constraint in this ADR, and
708+
it is resolved by open question 5 below: **one fold, now, into v1.**
653709

654710
## Alternatives rejected
655711

@@ -747,7 +803,7 @@ change** and must land before the first real package is signed, or behind a
747803
| Configurable phases (§1) | ARCHITECTURE §7 rejects stored required-phase maps | Global vocabulary + template-library configuration; no per-project map |
748804
| No ambiguous blanks (§4) | ARCHITECTURE §6 deliberately records unanswered lines | Blank stays legal at capture; illegal at sign/freeze |
749805
| Typed values (§7) | CLAUDE.md constraint #5: exactly four response types | Limits are metadata on `value`; no fifth type |
750-
| Signature QC (§9) | DECISIONS D6 freezes ADR 0010 | **Blocks on open question #5** — ADR 0010 must be unfrozen first |
806+
| Signature QC (§9) | DECISIONS D6 freezes ADR 0010 | ~~Blocks on open question #5~~ **Unblocked 2026-08-04 (§15):** D6 is amended by D25 — the manifest allowlist and canonical form are unfrozen for one fold; ADR 0010's *acceptance* stays blocked on its own gates |
751807
| Vendor evidence UI (§5) | DECISIONS D7 parks the ADR 0017 UI | D7's trigger condition met; D7 amended by D21 |
752808
| Continuation UI (§10) | DECISIONS D8 parks the open→resolve UI | Same; D8 amended by D21 |
753809
| Punch party vocabulary (§6) | `docs/API.md` publishes `assigned_party` as v1 | Breaking; requires the D12 version bump — sequenced post-M3 |
@@ -777,10 +833,9 @@ change** and must land before the first real package is signed, or behind a
777833
4. **Asset/position split** — worth doing at all, or is the re-verification
778834
prompt achievable with a simpler "nameplate changed on this tag" event?
779835
(Open question #12.)
780-
5. **Hash versioning.** Accept ADR 0010 *after* folding these manifest
781-
additions in (one canonical scheme), or accept it now and plan
782-
`sha256-canon-v2`? Recommendation: fold first — no real packages are signed
783-
yet, so the cheap moment is now.
836+
5. ~~**Hash versioning.**~~ **RESOLVED by the maintainer, 2026-08-04: fold
837+
first, into `sha256-canon-v1`, before any real package is signed.** See
838+
§15.
784839

785840
*Questions 6–8 were raised by the source reading, not the summary. Full
786841
reasoning in [`0018-review-notes.md`](0018-review-notes.md) R3–R5.*

0 commit comments

Comments
 (0)