Skip to content

ADR 0207 accepted with Amendment A: the enrolment code is the factorless re-proof once the directory re-bind goes (BACKLOG #1137) - #2584

Merged
wshallwshall merged 8 commits into
mainfrom
b447-adr0207-amend
Oct 28, 2026
Merged

wshallwshall merged 8 commits into
mainfrom
b447-adr0207-amend

Conversation

@wshallwshall

@wshallwshall wshallwshall commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator

Merge danger

Medium, docs only. This moves ADR 0207 (a single-use enrolment code for a directory account's first engine factor) from Proposed to Accepted, with Amendment A. Acceptance frees the build rows it governs, including the build that removes the directory re-bind under owner ruling A5. Per the Lander's rule 4i it gets its own PR. It touches only docs/adr/0207-...md, docs/adr/README.md (its index row) and one docs/PHI.md list line. git merge-tree against origin/main at open time was clean.

Evidence: how it was accepted

The owner was asked, verbatim (AskUserQuestion, 2026-10-27, about 13:35Z): "ADR 0207 review result: ACCEPT WITH NAMED AMENDMENTS ... How do you want to proceed?" The options were "Amend, then I accept (Recommended)", "Accept as written now" and "Not now". The owner answered /driver. The full question is quoted in the ADR's delegation record.

Under CLAUDE.md section 5 (owner ruling 2026-10-22), that delegates this question to the asking seat. The seat decides after adversarial review, and the record counts as the owner's ruling.

Three adversarial reviews ran:

  1. Of the Proposed ADR: ACCEPT WITH NAMED AMENDMENTS.
  2. Of Amendment A at 1d119a2: ACCEPT AFTER NAMED SMALL FIXES F1-F4. It also verified in code that all three backends serialize the audit append, and affirmed the SQLite-only engine-stopped refusal.
  3. Of the post-repair text at 83d038b: KEEP ACCEPTED AFTER NAMED SMALL FIXES. Those fixes were applied in 082741c and repaired in 5ae0f71.

Decision log records: d20261027T133727170-18c43f (amend, then accept) and d20261027T163534931-960b5f (keep accepted).

BACKLOG #1137: research an honest pass for ASVS 6.3.4 -- consistent authentication strength when AD MFA is delegated by design

Batch 447. Source branch b447-adr0207-amend, head 5ae0f71bc4adc960bc47d3ffc50c6be1b501ecd6. These SHAs will not survive the squash merge, so they are kept here:

  • 1d119a2: Amendment A (A1 factorless re-proof after A5; A2 re-baseline to #3025, #3014 and #3061; A3 check order; A4 engine-stopped host command, SQLite refusal with a note on PG and SQL Server; A5 issuer notice; A6 lifetime and IdP alternative recorded).
  • e2c6cb9: F1-F6, including the verbatim delegation record.
  • 37519aa: Status set to Accepted.
  • 2a6f300 and 83d038b: code-review repair rounds. 2a6f300 alone carries one docs-key test failure, which 83d038b fixes.
  • 082741c: third-read fixes: seal non-null columns only (as passkey_digest does for discoverable), conditional sealed writes through _write_user, and the spent notice added to docs/PHI.md.
  • 5ae0f71: repair round on those.

What acceptance unblocks: the build that removes _reauth_ad must cite Amendment A1 and AC-16 and carry the gate change in the same change. That build row is unfiled. Open acceptance boxes, each with a recommended default the build follows unless the owner rules: the 24h lifetime, whether an MFA reset issues a code, and the host command's reach.

Checks: ruff clean. pytest -k "adr or phi": 1791 passed, 95 skipped at the head. mypy was not run, because no Python changed.

QA: the code-review skill ran at level xhigh across four rounds; the tags are in the QA comment.

Known defects, shipped as critic notes:

  • One reviewer argues that sealing only when non-null is a compatibility shim CLAUDE.md section 0 argues against, and suggests plain fields plus a one-time migration reseal instead. The Manager kept the non-null mechanism the third adversarial read recommended. The build can revisit it.
  • RowSealError has no defined refusal on these paths.
  • Older "same statement" wording at ADR lines ~218 and ~249 was not updated, and ~249 omits the issuer.

Unfiled follow-ups, for the Lander to file as rows:

  • the _reauth_ad removal build under A1/AC-16;
  • the docs/SECURITY.md revoke passages and the vault re-read of the session-termination cell that A1 owes at that build.

RetriggerView in GreptileConfidence Score: 5/5

This documentation-only PR appears safe to merge.

Summary

Accepts ADR 0207 with Amendment A. No new actionable issue was established.

  • ADR 0207 makes the enrolment code the proof for a factorless directory session’s first factor.
  • The ADR spells out when enrolment codes are checked and spent.
  • The ADR sets store checks for host-issued enrolment codes.
  • The ADR adds a spent-code notice for the issuing Administrator.

Acknowledgments by wshallwshall:

  • Non-null-only sealing was kept despite the compatibility-shim concern; the build may revisit it.
  • RowSealError refusals remain undefined.
  • Older “same statement” wording and an omitted issuer reference remain known.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Future binding request] --> B[Directory lookup and factor checks]
  B --> C{Valid enrolment code?}
  C -->|No| D[Refuse without consuming the staged proof]
  C -->|Yes: TOTP| E[Verify TOTP and rotate session]
  E --> F[Enable TOTP and spend code in one conditional write]
  C -->|Yes: passkey| G[Verify attestation and check duplicates]
  G --> H[Spend code before writing credential]
  F --> I[Record use and notify issuer]
  H --> I
Loading

Reviews (1) · Last reviewed commit: "ADR 0207: repair round on the third-read..." · Reviewed by Greptile

…ind goes, re-baseline, enforced engine-stopped host command

BACKLOG #1137. Decided by the batch 447 Manager under the owner's
delegation of 2026-10-27, after an adversarial review. Status stays
Proposed.

A1: once owner ruling A5 removes _reauth_ad, the enrolment code is a
factorless directory session's re-proof at the binding step; begins are
admitted with a new budget draw; every other step-up action, session
termination included, stays refused until a factor exists (AC-16).
A2: re-baselined against #3014, #3025, #3061; AC-5, AC-13, AC-14 become
regression pins. A3: check order after the #3061 lookup; the TOTP spend
folds into the enable's conditional write; label read before the spend.
A4: host command refuses a held, non-store or unchecked SQLite store
(AC-17); the audit-fork premise is recorded as not borne out by the tree.
A5: the issuer gets a spent-notice row and email (AC-18). A6: 24h kept;
IdP-bound first factor noted, not adopted.

Proposed PR title: ADR 0207 amendment A: factorless re-proof, re-baseline, enforced host-command check
…legation record

Applies the second adversarial review of Amendment A (accept after named
small fixes):
- A1: the build that removes _reauth_ad must cite A1 and AC-16 and carry
  the gate change in the same change; its row is unfiled.
- A1: that build owes the docs/SECURITY.md passages saying a no-factor
  user can still end its sessions, and a vault re-read of the
  session-termination cell.
- A3 step 10: the passkey spend is conditional on TOTP off and no
  passkey; AC-19 pins it.
- Section 7: auth.enrolment_code_spent_notice, actor marked recipient,
  documented in SECURITY.md's Audit section.
- To resolve on acceptance: require_mfa-off answered yes.
- The delegation record quotes the owner's question verbatim.

BACKLOG #1137
…026-10-27

Status moves from Proposed to Accepted (2026-10-27). Accepted by the
batch 447 Manager under the Owner's delegation of 2026-10-27 (CLAUDE.md
section 5, "A delegated decision counts as that ruling", owner ruling
2026-10-22), after two adversarial reviews. The Proposed history is kept
in the Status line. README row: Accepted; Amended (A, 2026-10-27).
Three To-resolve items stay open with their recommendations.

BACKLOG #1137

Proposed PR title: ADR 0207 accepted with Amendment A: the enrolment code
is the factorless re-proof once the directory re-bind goes (BACKLOG #1137)
- AC-19 reaches only a code refused at the code read; the later race is
  named, not pinned as staged.
- The TOTP fold also requires no passkey; AC-19 pins that direction too.
- README row no longer says the TOTP code is spent before the stamp.
- The begin routes' budget draw and the A1 table belong to the build
  that removes _reauth_ad, which must not admit a begin without it.
- The new-address check is named as absent with admin_new_ip_step_up off
  or no recorded client; the budget drain is not bounded for a password
  holder who re-mints sessions.
- A4: a non-SQLite file is refused before the open; the unchecked
  SQLite availability cost is named; the shared-gate follow-up is named
  by subject.
- The three new users columns are sealed fields; the require_mfa-off
  step-up loss is named in Consequences; A6 cites ADR 0142 Amendment C.

BACKLOG #1137

Proposed PR title: ADR 0207 accepted with Amendment A: the enrolment code
is the factorless re-proof once the directory re-bind goes (BACKLOG #1137)
- A1's headline names the begins and the TOTP confirm form as admitted,
  matching its table; the README row says the same.
- A1 and the require_mfa-off answer rest on A5 leaving that posture to
  this ADR (A5's record says so), not on A5 removing it outright.
- AC-3 is scoped to a code refused at the read; AC-19's race clause says
  that ceremony spends nothing.
- The TOTP fold's no-passkey condition binds only the code-carrying
  write; a fold failing on its code keeps today's refused reason.
- Superseded section 3 and 7 passages carry pointers to A2 and A3.
- AC-16 pins the new-address refusal where that check runs.
- A6 no longer counts the issuer's notice as a bound; the drain's
  detection path is named truthfully; the spent notice carries the
  client address; the residual's awaited reads are corrected.
- The delegation record names the option taken and that the code-review
  rounds changed design text after both adversarial reviews.
- Qualifies require_mfa as [security].require_mfa (docs config-key test).

BACKLOG #1137

Proposed PR title: ADR 0207 accepted with Amendment A: the enrolment code
is the factorless re-proof once the directory re-bind goes (BACKLOG #1137)
The Status line and Amendment A now say the two repair rounds
(2a6f300, 83d038b) came after both adversarial reviews, and that a
third adversarial read at 83d038b covered them and returned keep
accepted after named small fixes. Amendment A names how the three new
users columns survive the users-row seal: each enters the sealed field
set only when non-null, as passkey_digest does for discoverable. Every
code write is named a conditional sealed write through _write_user.
docs/PHI.md lists the spent notice among the audit_log.detail rows
that store a client address.

BACKLOG #1137

Proposed PR title: ADR 0207 accepted with Amendment A: the enrolment code is the factorless re-proof once the directory re-bind goes (BACKLOG #1137)
Code-review findings on 082741c: the spend captures the issuer from
the record _write_user read; the host command's write names what the
seal compare guards, and that a keyless store has no compare; the seal
claims are qualified to a store with a row sealer; the write list is
"at least" and names the revoke and the unconditional disable clear;
the test_user_seal claim names a static scan; Amendment A says which
text of the fix commit no adversarial read has seen; the decision log
id is named as the original acceptance's; PHI.md cites vault BACKLOG
#2609 for the spent notice.

BACKLOG #1137

Proposed PR title: ADR 0207 accepted with Amendment A: the enrolment code is the factorless re-proof once the directory re-bind goes (BACKLOG #1137)
@wshallwshall

Copy link
Copy Markdown
Collaborator Author

QA (BACKLOG #1137, ADR 0207): code-review skill at level xhigh. Amendment A rounds round-e1a39052 and round-b460b167 (korus review_tag.py exit 0); acceptance and F-fix rounds round-30fccfa1 and round-b32a42b5 (exit 0); third-read fix round round-b20ee988 (exit 0). Tag verbatim, every round: "xhigh effort -> 10 inline angles -> dedup (no verify) -> sweep -> <=15 findings". Inline review with no verifier, per the tag; the three adversarial reads in the PR body cover the design. The round-b20ee988 repairs (5ae0f71) have had no review of their own; Amendment A names which text no adversarial read has seen.

@wshallwshall wshallwshall added the qa Builder QA record posted; not a merge gate label Oct 27, 2026
@github-actions github-actions Bot added the ci-red A required check went red. Attribute it before retrying. label Oct 27, 2026
@wshallwshall

Copy link
Copy Markdown
Collaborator Author

Lander (session 8a04c9f3), 2026-10-28. Covering review of the unreviewed repair commit 5ae0f71bc, run through a Lander subagent. This is not a QA line.

  • Head 39799ff20 adds only a clean merge of main: git merge-tree --write-tree 5ae0f71bc cf441c867 and 39799ff20^{tree} are both 4e3ecbac80ab515ff3d34332ff621ee6aa0ab3d8.
  • code-review skill, level xhigh, nonce round-03678fa8, over 082741cc6..5ae0f71bc (docs only: docs/PHI.md and the ADR 0207 file). korus review_tag.py --target round-03678fa8 --worktree <the Lander's worktree> exit 0, fork abef78fd7250443c1, tag xhigh effort -> 10 inline angles -> dedup (no verify) -> sweep -> <=15 findings. The first read, without --worktree, exited 12 because the fork ran in the Lander's worktree, not the review checkout.
  • 14 findings, all in the ADR 0207 prose. None changes shipped behaviour or weakens a shipped control. The substantive ones: Amendment A does not name 5ae0f71bc as unreviewed text (line ~628); the delegated acceptance rests on mechanisms with no adversarial read (line 3); a lost _USER_RESEAL race would silently revert concurrent column changes, a design gap for the build (line ~325).

Next: the 14 findings go into ledger rows, alongside #4676 and #4677, before this merges. Each will be named here with its row.

@wshallwshall

Copy link
Copy Markdown
Collaborator Author

Lander (session 8a04c9f3), 2026-10-28. Enqueuing at pinned head 39799ff20f4ac2c54ec585bbf9c9d5db679a4317 under the owner's ruling of 2026-10-28 in the Lander's chat: the Lander may name each finding on the PR, merge, and file its row afterwards.

Review proof: the QA rounds cover everything up to 082741cc6. The Lander's covering review (comment 6459487049, round-03678fa8) covers 5ae0f71bc. 39799ff20 is a clean merge of main (tree 4e3ecbac). All nine required contexts are a settled success on this head.

Open findings. None changes shipped behaviour or weakens a shipped control:

  • Critic notes from the QA: vault #4676, #4677
  • The 14 findings of the covering review on the ADR 0207 prose: rows follow in Lander ledger pass B

@wshallwshall
wshallwshall added this pull request to the merge queue Oct 28, 2026
Merged via the queue into main with commit d9f1687 Oct 28, 2026
51 checks passed
@wshallwshall
wshallwshall deleted the b447-adr0207-amend branch October 28, 2026 06:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-red A required check went red. Attribute it before retrying. qa Builder QA record posted; not a merge gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant