Repository navigation
feat: signed approval of released documents (ADR-004) - #457
Merged
Merged
Conversation
Iteration 3 found approval living only in GitHub, mostly bypassed in practice, without meaning, and within an agent's reach through tokens. Propose approving item versions by the role that owns their type, with SSH-signed APPROVAL items in the DHF that are append-only; the CCB signs CR status changes; code review stays with the platform. Approval blocks only at merge and release, never within a CR. Includes the typical workflow, alternatives and open questions (presence cannot be required through allowed_signers; approvers who leave need key revocation). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add the APPROVAL item type, the approvers list (DHF/config/approvers.yaml) and the approval_roles matrix in global.yaml. `item approve --key` writes an APPROVAL item covering the pending items the signer's roles may approve and signs its file with `ssh-keygen -Y sign`. `verify approval` checks every signature, signer and claimed role against the list, that each changed item (or every item with --all) has a current approval from its role, that approvals are append-only, and that a change to the list is approved by someone on it as it was at the ref. Off until the project keeps an approvers list. Release integration is phase 2. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A CR can need ten approvals and a large team closes many CRs a day. Approvals as DHF items made every command load them all, and sequential IDs collided across parallel branches. Record approvals instead in an append-only log, DHF/approvals/<CR>/<ULID>.yaml, which the item store never reads. Add an "At scale" section for phase 2: verify only the candidate records, and make each release a signed checkpoint after which superseded records may leave the working tree. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Remove the APPROVAL item type. `item approve` writes the record to DHF/approvals/<CR or unscoped>/<ULID>.yaml with plain YAML and signs its bytes; `verify approval` reads the log, reports a record whose id differs from its file name, and checks append-only on that directory. The checks themselves are unchanged. New tests: approvals made on two branches from one base merge without colliding, a record lands under its CR, and item list does not show approvals. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Working through a team's day showed per-item signatures cost too much: ten per CR, re-signing shared items after every merge, development waiting at each merge. The requirement is approval before issue. During development every change, CR acceptance and closure included, is reviewed in its pull request. At release, a pipeline started on purpose writes a manifest of the documents' item hashes and a change report; each specification is signed by the role that owns its type, and the quality lead signs the release. Evidence is kept for the life of the device. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Remove per-item approval at merge (coverage in `verify approval`, and the --cr/--all/--role modes of `item approve`). `build release --write` now writes DHF/releases/<version>/manifest.yaml (each document's items and hashes, the rendered file's hash, the DHF and approvers-list hashes) and changes.md (what changed per document since the previous release, with its CRs). `item approve --release V` signs, in one record, every document the signer's roles own, and the release for `release_role`. `verify approval --release V` requires each signature over the current hashes and that the manifest still matches the DHF; REL items are left out, so a REL moving on after signing is not drift. Plain `verify approval` only checks the log is sound. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Charter iteration 3, approval and accountability. The branch went through three designs; its history keeps them, and the ADR records why the first two were dropped. What it delivers is the last one.
ADR-004: Signed Approval of Released Documents (Proposed)
release-baseline.yml, not a merge) writes a manifest and a change report. Each specification is signed by the role that owns its type, and the quality lead signs the release.Implementation
Approvers list
DHF/config/approvers.yaml(people, roles, public keys).Roles:
approval_roles(item type → role that signs its specification) andrelease_roleinglobal.yaml.build release --writealso writes:DHF/releases/<version>/manifest.yaml: per document, its items and hashes, plus the rendered file's hash, the DHF hash and the approvers-list hash;changes.md: per document, items added, modified and removed since the previous release, with their CRs.REL items are left out of both, so a REL moving through its states after signing is not drift.
item approve --release V --key <private key>:release_role;ssh-keygen -Y sign, never through ssh-agent.Approval log:
DHF/approvals/<scope>/<ULID>.yamlwith.sig. Records are append-only, never loaded by the item store, and collision-free across branches.verify approvalchecks that the log is sound on any PR: signatures, append-only, the approvers guard. It never asks for a signature.verify approval --release Vadditionally requires a signature from each document's role over the document's current hash, and the quality lead's signature over the manifest. It also fails if the manifest no longer matches the DHF.Off until configured: without an approvers list, existing projects see no change.
Not in this PR
Known limits (ADR open questions)
changes.mdcompares the numbers in the version: 1.10.0 sorts after 1.9.0, and a pre-release suffix sorts above its release.Validation
scripts/generate_interface.pyrun; CHANGELOG under Unreleased; no version bump.Manual review
dhf_hash, so approving the REL after signing read as drift. A test now covers it.🤖 Generated with Claude Code