fix(b-0852.3b-supersede2): narrow passphrase env-exposure window + Step 6.56 prompt (supersedes #5643 which went DIRTY post-#5644 merge)#5650
Merged
AceHack merged 1 commit intoMay 27, 2026
Conversation
…ep 6.56 cred-blob prompt + non-exported var + unconditional unset + comment alignment (supersedes #5643 which went DIRTY post-#5644 merge) #5643 (passphrase env-exposure supersede) went DIRTY when #5644 (blob-path fix-fwd) merged because #5644 modified the same picker block. This is the supersede-via-new-branch reland off current main. What this PR does (cumulative of #5643 + #5643 fixup): Step 6.56 (NEW — cred-blob passphrase prompt): - Operator-typed passphrase captured into NON-EXPORTED shell variable ZETA_CREDS_PASSPHRASE_VAL - Bash shell variables without `export` live in shell's own variable table but are NOT copied into /proc/<pid>/environ - Same operator-typed-once-on-console pattern as iter-5.3 password (constitutional rail line 452) Step 6.95-picker (modified): - Gate check uses ZETA_CREDS_PASSPHRASE_VAL (non-exported var) - sudo invocation uses inline env-set: `ZETA_CREDS_PASSPHRASE="$ZETA_CREDS_PASSPHRASE_VAL" sudo --preserve-env=ZETA_CREDS_PASSPHRASE ...` — exports env var only into sudo subprocess - `unset ZETA_CREDS_PASSPHRASE_VAL` moved OUTSIDE if/else block so it fires in BOTH picker-ran AND picker-skipped branches (prior bug: unset only in picker-ran branch left passphrase live when picker was skipped) Comment alignment (from #5643 fixup): - Step 6.56 doc: semantic two-step-lifecycle description (no hard-coded line numbers — would drift as script evolves) - Step 6.95-picker doc: references ZETA_CREDS_PASSPHRASE_VAL as the precondition (matches actual gate check) - SECURITY block: documents the full 2-stage discipline (non-exported parent shell var + inline-set into sudo only) Preserves #5644's substrate (picker --output /mnt/boot/zeta-creds.enc + all the mount-path comment block) intact — this commit only touches the env-var lifecycle, not the path lifecycle. Validation: - bash -n syntax check passed - bun tools/ci/audit-installer-substrate.ts PASS - Docker harness passed in 15s Closes #5643 (the DIRTY supersede) with both Copilot findings addressed + #5644's path substrate preserved. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
5 tasks
AceHack
pushed a commit
that referenced
this pull request
May 27, 2026
…D018 fix (Copilot 6 threads on #5648) Comprehensive accuracy rewrite addressing all 6 Copilot findings: 1. "no more re-entering" overclaim — passphraseMode=interactive DOES prompt every boot via systemd-ask-password. Reframed accurately: N per-tool login flows → ONE cred-blob passphrase. The improvement is atomicity, not zero typing. 2. Install log lines mismatch — restored to match actual zeta-install.sh output (Step 6.56 + Step 6.95-picker actual strings). 3. /boot path correctness — preserved (#5644 already fixed producer/consumer alignment to /mnt/boot ↔ /boot). 4. Manifest coverage — included gemini + codex paths (~/.gemini/oauth_creds.json, ~/.codex/auth.json) plus the full default-manifest table. 5. Second-reboot expectation — corrected: interactive mode prompts every boot by design. Operator who wants no-prompt-at-boot can switch to passphraseMode="file" (with security tradeoff named). 6. Filename reference — zeta-creds-cli.ts → zeta-creds-manifest.ts (actual canonical location of defaultManifest). Also fixes MD018 lint failure: line "#5639 + #5640 + #5643 + #5644 +" was being parsed as an ATX heading because # was at column 1. Replaced the line-wrapped PR-number prose with the default-manifest table (more useful + no MD018 trigger). Composes with: - B-0852 cred-persistence cascade (PRs that ACTUALLY ship: #5635, #5637, #5639, #5640, #5641, #5642, #5644, #5645, #5646, #5648, #5649, #5650; #5638 + #5643 were superseded → closed without merge) - common.nix passphraseMode=interactive default (PR #5640) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Reland of the passphrase env-exposure narrowing for the cred-blob picker (supersede of #5643 which went DIRTY when #5644 merged the picker block). Introduces an interactive passphrase prompt at Step 6.56 that captures into a non-exported shell variable, and rewires Step 6.95-picker to inline-set the env var only into the sudo subprocess and to unset the holder variable in both picker-ran and picker-skipped branches. Preserves the /mnt/boot/zeta-creds.enc output path established by #5644.
Changes:
- Add Step 6.56 prompt capturing the passphrase into the non-exported
ZETA_CREDS_PASSPHRASE_VAL(with confirm-mismatch fallback to skip). - Switch Step 6.95-picker gate + skip-reason from
ZETA_CREDS_PASSPHRASEtoZETA_CREDS_PASSPHRASE_VAL, and inline-setZETA_CREDS_PASSPHRASE=...only on the sudo invocation. - Move
unset ZETA_CREDS_PASSPHRASE_VALoutside the picker if/else so it runs whether the picker ran or was skipped.
Comment on lines
+1468
to
+1476
| # B-0852.3b-supersede discipline: unset ZETA_CREDS_PASSPHRASE_VAL | ||
| # UNCONDITIONALLY after the picker block — fires in BOTH the | ||
| # picker-ran branch AND the picker-skipped branch. Prior code only | ||
| # unset inside the picker-ran branch, leaving the passphrase live | ||
| # in the installer shell for the rest of execution whenever | ||
| # ZETA_CREDS_PICKER=0 / /etc/zeta/no-picker / usb-uuid-missing path | ||
| # was taken. | ||
| unset ZETA_CREDS_PASSPHRASE_VAL | ||
| echo "[iter-5.5.0] ZETA_CREDS_PASSPHRASE_VAL unset from installer shell (post-picker block; fires in both branches)" |
AceHack
added a commit
that referenced
this pull request
May 27, 2026
…o-end verification checklist for operator) (#5648) * docs(provisioning): add cred-restore smoke-test section — first-boot + post-reboot + second-reboot verification + troubleshooting table (B-0852 end-to-end) The B-0852 cred-persistence cascade (PRs #5635 + #5637 + #5638 + #5639 + #5640 + #5643 + #5644 + #5646) closes the operator's 'don't re-enter creds over and over' pain point. This docs addition gives operators a concrete checklist to verify the full path works after a fresh USB install: - First-boot verification: what install log lines to look for - Post-reboot verification: systemctl + ls + auth-status commands - Second-reboot verification: confirm no re-entry needed - Troubleshooting table: 4 common symptoms with likely causes Closes the gap between 'cascade is shipped' and 'operator can confirm cascade works on their hardware'. The operator no longer has to figure out which systemd unit to query or which paths to check — the checklist names them. Composes with: - PROVISIONING.md (existing operator-facing install doc) - B-0852 cred-persistence substrate - The audit-extension PR (separate; catches drift at CI time) Substrate-honest scope: this is operator docs, not a TS tool. A follow-on TS smoke-test runner (run on the installed system to auto-verify the checklist) is a candidate for follow-up work but out of scope for this commit. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fixup(docs): rewrite cred-restore smoke-test section for accuracy + MD018 fix (Copilot 6 threads on #5648) Comprehensive accuracy rewrite addressing all 6 Copilot findings: 1. "no more re-entering" overclaim — passphraseMode=interactive DOES prompt every boot via systemd-ask-password. Reframed accurately: N per-tool login flows → ONE cred-blob passphrase. The improvement is atomicity, not zero typing. 2. Install log lines mismatch — restored to match actual zeta-install.sh output (Step 6.56 + Step 6.95-picker actual strings). 3. /boot path correctness — preserved (#5644 already fixed producer/consumer alignment to /mnt/boot ↔ /boot). 4. Manifest coverage — included gemini + codex paths (~/.gemini/oauth_creds.json, ~/.codex/auth.json) plus the full default-manifest table. 5. Second-reboot expectation — corrected: interactive mode prompts every boot by design. Operator who wants no-prompt-at-boot can switch to passphraseMode="file" (with security tradeoff named). 6. Filename reference — zeta-creds-cli.ts → zeta-creds-manifest.ts (actual canonical location of defaultManifest). Also fixes MD018 lint failure: line "#5639 + #5640 + #5643 + #5644 +" was being parsed as an ATX heading because # was at column 1. Replaced the line-wrapped PR-number prose with the default-manifest table (more useful + no MD018 trigger). Composes with: - B-0852 cred-persistence cascade (PRs that ACTUALLY ship: #5635, #5637, #5639, #5640, #5641, #5642, #5644, #5645, #5646, #5648, #5649, #5650; #5638 + #5643 were superseded → closed without merge) - common.nix passphraseMode=interactive default (PR #5640) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Lior <lior@zeta.dev> Co-authored-by: Claude <noreply@anthropic.com>
AceHack
added a commit
that referenced
this pull request
May 27, 2026
…re the just-written blob at install time (operator catches bad blob BEFORE reboot, not at first boot) (#5655) Adds opt-in --verify flag to zeta-creds-picker.ts. When set, after zeta-creds-persist succeeds, the picker spawns zeta-creds-restore.ts with --dry-run + the same passphrase source + a tmpdir as --target-root. If restore-dry-run exits 0, the blob is confirmed cryptographically valid + manifest-parseable. If non-zero, the operator sees an actionable error at install time + can re-run the picker to retry. Operator-experience improvement: without --verify, a corrupt blob (wrong passphrase captured, disk write error, persist bug) only surfaces at first reboot when zeta-creds-restore.service fails its ConditionPathExists or scrypt-decrypt step. At that point the operator must reboot back into the live USB + re-run the install. With --verify, the same failure surfaces SECONDS after persist, inside the running install flow, with the live USB still mounted. New exit code 5 for verify-failed (distinct from persist-failed=4). API addition: - PickerArgs gains `verify: boolean` (default false; opt-in) - New export buildVerifyArgs(parsed, tmpTargetRoot) — pure composer of the restore-CLI argv list; testable in isolation Tests added (3 new + 2 parseArgs-extension): - --verify flag default false - --verify flag parsed when passed - buildVerifyArgs composes restore-CLI args with --dry-run + tmpdir - buildVerifyArgs propagates --passphrase-file when picker used file - buildVerifyArgs propagates --persona when set 21 pass / 0 fail (was 16; +5). Substrate-honest scope: opt-in only. Future PR can flip default-on after operator empirical testing confirms verify doesn't introduce new failure modes (e.g., tmpdir permission, restore-CLI changes). zeta-install.sh Step 6.95-picker currently does NOT pass --verify; that flip can land in a follow-up after operator tests. Composes with: - B-0852 cred-persistence cascade (#5635 + #5637 + #5639 + #5640 + #5642 + #5644 + #5645 + #5646 + #5648 + #5649 + #5650) - tools/installer/zeta-creds-restore.ts (existing --dry-run mode) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Lior <lior@zeta.dev> Co-authored-by: Claude <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
PR #5643 (passphrase env-exposure supersede) went DIRTY when #5644 (blob-path fix-fwd) merged because both touched the same picker block. This is the supersede-via-new-branch reland off current main.
What this PR does
Step 6.56 (NEW):
Step 6.95-picker (modified):
Preserves #5644 substrate:
Test plan
Closes
Closes #5643 (the DIRTY supersede) with both Copilot P1 findings + #5644's path substrate preserved.
🤖 Generated with Claude Code