feat(B-0852): credential persistence on USB ESP + boot-sequence auth-method picker — encrypted blob bound to USB UUID + operator passphrase Phase 1 (Aaron 2026-05-27)#5403
Merged
AceHack merged 7 commits intoMay 27, 2026
Conversation
…method picker Phase 1 substrate-engineering target authorized by Aaron 2026-05-27 after gh-login throttle on 3rd USB boot of the day. Encrypted cred-blob on USB ESP, key bound to USB UUID + operator passphrase. Boot-sequence picker offers: restore from blob / fresh device-flow login / operator-provided PAT / skip. Removes gh-login throttle on multi-boot test workflow. Composes with: B-0850 multi-vendor systemd parent, B-0833 interactive-login tension, B-0835 gh-auth-not-respected, B-0831 CI cascade 6, B-0847 per-AI identity, B-0851 persona-first scheduler, iter-4.2 ESP write channel. Phase 1 deliberately narrow (passphrase + USB UUID); Phase 3 hardware-bound keys + Phase 5 cross-cluster federation are future scope. Per .claude/rules/non-coercion-invariant.md HC-8: operator authority over own credentials absolute; no creds baked into ISO (B-0833 discipline).
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
… composition (Aaron 2026-05-27)
Aaron clarified Phase 2 (Path B = recover creds from existing PC) needs
the same encryption + optional UUID-bound key so copying ESP contents to
a different-UUID USB doesn't unlock. Iterate-quickly-not-paranoia floor:
just enough security to prevent casual physical-access leaks; full
hardware-bound work defers to Phase 3+.
Also confirmed Phase 1 + Phase 2 compose ("we can do both like you said
this will be nice together"). Added boot menu shape showing all 5 options
once both phases land + composition value table.
Both phases share the same UUID-bound-key + operator-passphrase
derivation; single crypto module + two-source ingest = bandwidth-efficient
substrate that doesn't fragment per-path.
There was a problem hiding this comment.
Pull request overview
Adds a new P1 backlog row (B-0852) describing Phase 1 credential persistence on a USB ESP (encrypted blob bound to USB UUID + operator passphrase) and updates the generated backlog index to include the new row.
Changes:
- Adds
docs/backlog/P1/B-0852-...mddescribing the planned USB ESP credential-blob + boot-sequence auth-method picker design and acceptance criteria. - Updates
docs/BACKLOG.mdto include B-0852 in the P1 section.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| docs/backlog/P1/B-0852-credential-persistence-on-usb-esp-plus-boot-sequence-auth-method-picker-encrypted-blob-bound-to-usb-uuid-plus-operator-passphrase-aaron-2026-05-27.md | New backlog row documenting the Phase 1 credential persistence/auth-method picker plan. |
| docs/BACKLOG.md | Adds the B-0852 entry to the generated backlog index. |
… + lint fixes (Aaron 2026-05-27) Operator clarification 2026-05-27: re-flash workflow should DETECT previous answers + RECOVER as DEFAULT (not opt-in). 5-second Esc-to-cancel banner preserves operator override per NCI HC-8. > "it will be very nice when i reformat if it starts picking up previous > answers and reapplies them so i don't have to ... we just need an > override escape hatch so we get a chance to say don't recover start > fresh but recover is the default." Refines Sub-target 3 implementation: detection BEFORE picker, 5-second banner with Esc override, fall-through to explicit menu on Esc OR no-detected-source. Composes value: self-healing + iteration speed + override safety + NCI preservation. Implementation sub-rows unchanged at the crypto + schema layers; only the picker UX shifts to detect-recover-default. Also: 2 MD032 blanks-around-lists fixes (conversation arc + substrate inventory lists). Conversation arc extended with turns 7-9 (Phase 2 security, Phase 1+2 composition confirm, auto-recover-by-default).
… integrates as Step 6.81-6.83 (NEW sub-range) Copilot review on PR #5403 caught: my row claimed "Step 6.9 (new)" + "Step 6.95b" but verified on origin/main 1740eea: - Step 6.9 = iter-5.4.1 self-registration (B-0812) — ALREADY USED - Step 6.95 = does not exist - Step 6.8 = iter-5.4.0 homelab gh-auth + operator pubkey copy - Step 7 = print initial credentials (iter-4 / B-0789) Renumbered picker as Step 6.81-6.83 (detection + escape-hatch banner + branch) — NEW sub-range between existing Step 6.8 (gh-auth) and Step 6.9 (self-registration). Preserves every existing step's number + meaning. Added explicit step-layout table referencing existing zeta-install.sh state so future implementers see the EXACT integration point + don't collide with existing steps. Multi-vendor scope note: picker captures intent in /esp/zeta-creds.enc; vendor-CLI install (claude/gemini/codex) happens later in first-boot scope (NOT in the install.sh step range we're modifying here). Resolves Copilot thread PRRT_kwDOSF9kNM6FAbT8 on line 61.
…er Aaron 2026-05-27 Operator clarification: "the keep credentials options we should declare each credential we need and save and restore so it's not so imparative too." Refines Sub-target 1: cred-persistence operates over a DECLARATIVE MANIFEST (/esp/zeta-creds-manifest.yaml) listing which credentials Zeta tracks. Adding a new cred type = manifest edit, NOT a code change. Composes with B-0854 (Ace migration) at the manifest-shape scope: same declarative discipline applies to cred-tracking as to install-step tracking. Schema candidate covers gh-cli + claude + gemini + codex + ssh-host-keys + ssh-operator-pubkey with persona-scoped + required flags. Also captures turn 10 of conversation arc: operator can wait for next USB to include this + B-0854 substrate; current login-throttle still active; PAT path (Sub-target 2 option 3) becomes immediate unblock.
added 2 commits
May 27, 2026 02:05
…B-0850 to composes_with per P1 + step-numbering consistency sweep per P1 Three Copilot findings on PR #5403: P0: Picker must run BEFORE Step 6.8 so device-flow is conditional on picker choice. Earlier draft said "picker runs AFTER Step 6.8" which defeated the zero-device-flow-on-reboot acceptance criterion (gh-quota burns before restore is offered). Fixed: new Steps 6.75 + 6.76 + 6.77 (detection + banner + 4-option picker) insert BEFORE Step 6.8. Step 6.8 modified to be CONDITIONAL on picker choice — only fires device-flow if option 2 chosen. Step 6.85 NEW for persist-after-successful-auth. P1: depends_on B-0850 → composes_with B-0850. B-0850 is P2; this row is P1; P1-depends-on-P2 is backwards in the priority graph. B-0850 isn't strictly required to implement Phase 1 — cred persistence works single-vendor; multi-vendor systemd is compositional context. P1: Step-numbering swept for consistency — all "Step 6.9 (new)" / "Step 6.95c" / "Step 6.10" references replaced with the new 6.75-6.85 sub-range that doesn't collide with existing Steps 6.8 (gh-auth) + 6.9 (self-registration). Resolves Copilot threads PRRT_kwDOSF9kNM6FAi_B + PRRT_kwDOSF9kNM6FAi_a + PRRT_kwDOSF9kNM6FAi_v on PR #5403.
…ersistence-boot-auth-picker-2026-05-27 # Conflicts: # docs/BACKLOG.md
AceHack
added a commit
that referenced
this pull request
May 27, 2026
…0 substrate for Ace migration trajectory (14 sub-steps; 12 declarative-input categories; substrate-anchor for B-0852/0853/0855/0856 cross-refs) (#5420) * docs(B-0854.1): zeta-install.sh step-state-machine inventory — Phase 0 substrate for Ace migration trajectory B-0854 sub-row .1 (Phase 0; smallest pure-analysis slice). Documents the EXISTING imperative bash state-machine in zeta-install.sh so the B-0854 Phase 2 declarative-Ace-manifest schema can express the same surface. Inventory covers: - Top-level entry (REPO_URL, HOST, ZETA_AUTO_CONFIRM env semantics) - Step-by-step state machine for all 14 sub-steps (1, 2, 3, 4, 5, 6, 6.5, 6.55, 6.6, 6.7, 6.8, 6.9, 6.95, 7) with inputs/outputs/side- effects/failure-modes/declarative-equivalent per step - Cross-cutting: operator-prompt accumulation count (7 prompts today; B-0852 phase-split target = 1 passphrase prompt) - Idempotency surface table — informs B-0855 architectural fix scope - 12 distinct declarative-input categories the Ace manifest must capture (Phase 2 sub-row scope) - Files-generated-during-install table mapping to B-0852.5 cred- manifest entries (6 mapped, 3 candidate-expansion items named) Snapshot date: 2026-05-27 (origin/main 70596a8; PR #5417 cosign merge). Future refreshes should re-snapshot when zeta-install.sh changes substantially. Composes with already-landed substrate-engineering arc: - B-0852 + sub-rows (cred persistence) — PR #5403/#5411/#5414 - B-0853.1 (cosign signing) — PR #5417 + fix-fwd #5419 - B-0855 (self-register architectural fix) — PR #5412 - B-0856 Path A (deferred /tmp coordination) — PR #5413 - B-0854 parent (Ace migration trajectory) — PR #5405 No code change; pure documentation. Doesn't affect ISO substrate; batches into substrate-engineering history independent of next ISO build cycle. * fix(B-0854.1): escape | inside code spans for MD056 table-column-count compliance * fix(B-0854.1): 10 Copilot accuracy corrections — verified against actual zeta-install.sh content PR #5420 Copilot review caught 10 substantive accuracy issues in the B-0854.1 inventory doc. All 10 verified against origin/main 70596a8's actual zeta-install.sh content + corrected. Corrections: - Name attribution → role-ref ("the human maintainer") - Step 1 inputs: actual `lsblk -d -p -n -o NAME,TYPE,RM,RO,TRAN` + awk filter (not made-up NAME,SIZE,MODEL,TRAN,ROTA) - Step 3 side effects: `sgdisk --zap-all` only (not `wipefs -af` too) - Step 4: actual `sgdisk` (NOT `parted`); GPT layout via -n + -t flags; whole-disk longhorn partitions on DATA_DISKS too - Step 6: `nixos-generate-config --root /mnt --force` (NOT --no-filesystems; --force overwrites existing config) - Step 6.5: no MAGIC_NUMBER (didn't exist in script); INJECT_OK gate flag; iter-4 v1 manual-config-edit fallback path - Step 6.9: SELF_REG_OK flag; documented graceful-skip path lines 731+ - nixos-install: actual line ~1004 (NOT 1096-1340); section renamed to "nixos-install (the actual build; ~line 1004)" since the prior range was wrong - Step 7: actual lines 1261-1336 (NOT 1341-1352); banner driven by GH_AUTH_OK/GH_KEY_COUNT/INJECT_OK/SELF_REG_OK (NOT MAGIC_NUMBER); conditional sections listed in declarative equivalent Resolves 10 Copilot threads on PR #5420. Root cause of the inaccuracies: original draft was written from `grep -E "^# ── Step"` summaries + recollection of script behavior, not careful per-step body reads. Discipline lesson: when authoring substrate-anchor docs claiming to inventory existing code, the read must be careful per-line, not skim-grep summary. Composes with .claude/rules/verify-existing-substrate-before-authoring.md at the inventory-substrate scope (verify-content-of-thing-being-inventoried before authoring claims about its content). --------- Co-authored-by: Lior <lior@zeta.dev>
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
/esp/zeta-creds.enc), key bound to USB UUID + operator passphrase via HKDF + AES-256-GCMzeta-install.shStep 6.9) offers: restore from blob / fresh device-flow login / operator-provided PAT / skipComposes with
Phase 1 deliberately narrow
NCI floor preserved
Per .claude/rules/non-coercion-invariant.md HC-8: operator authority over own credentials absolute. No creds baked into ISO image (preserves B-0833 discipline). Encrypted blob is operator-controllable + operator-removable.
Test plan
🤖 Generated with Claude Code