Add recoverable Pi provider lifecycle command #26
No reviewers
Labels
No labels
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
allod/nexus!26
Loading…
Reference in a new issue
No description provided.
Delete branch "agent/pi-provider-lifecycle"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
This adds a Nexus-only
pi-providercommand for safely adding, sharing, retargeting, rotating, retiring, and recovering Pi provider credentials.Bearer values enter through a hidden prompt, flow only to Age over stdin, and never enter Git, argv, the environment, logs, or persistent plaintext files.
The command edits only the profiles/secrets registries and Age ciphertext; it does not commit, rebuild, test a real endpoint, or revoke a remote token.
Dry runs need no token and change nothing; interrupted writes retain a path-scoped recovery journal and refuse unsafe recovery.
Existing Nexus provisioning behavior is unchanged until the command is deliberately run.
If this is wrong, leave the PR unmerged; no private deployment pin consumes it yet.
Refs allod/strategy#34
Depends on the data contracts in allod/profiles#6, allod/secrets#13, and the rebuilt-host workspace in allod/inventory#12.
Risk
R3 High. This command accepts authentication material and coordinates recoverable writes across two repositories. Review should focus on the stdin-only secret boundary, recipient derivation, shared-credential impact, and recovery confinement.
Validation
nix build .#checks.x86_64-linux.provisioning-contract -Lshellcheck,bash -n, andgit diff --checkpass through the aggregate check.Real inference, private migration, VM rebuilds, and provider-side token revocation remain gated to the later private rollout.
Independent read-only review of HEAD
042e215found four concrete gaps:restore_journalwrites tracked bytes through.pi-provider-recover-<basename>(scripts/pi-provider:604-612), but that path is neither preflighted nor included inTOUCHED_SPECS. An ignored pre-existing symlink there is absent fromassert_dirt_confined, so shell redirection overwrites its external target andmvthen installs the symlink as the registry/ciphertext path. This contradicts path-confined exact recovery. Record and preflight the recovery temp alongside each transaction temp (and allow it insafe_journal_path), or create a guaranteed-new regular file withmktempand safely clean/refuse leftovers.retargetomits the approved per-VM impact report. Its output names all providers and the replacement target list (scripts/pi-provider:677-680) but does not compute old/new target differences or say which shared providers are added to and removed from each VM. The witness only matchesShared providers(tests/pi-provider.sh:257-260). Print and test the provider set for every added/removed VM before secret input.--credentialcan silently replace the positional retarget credential. Parsingretarget expected --credential shared --target dev-boverwritesCREDENTIAL_IDat lines 93-104, while retarget validation cannot distinguish the flag and proceeds againstshared. Track whether--credentialwas supplied and reject it outsideadd. The same strictness check should reject--api/--rotation-strategyonrecover, which currently ignores them.tests/pi-provider.sh:302-328) covers before only the first addmv, after each add destination, and post-validation; it does not leave the second/third transaction temp before their moves, exercise retirement deletion, or prove unrelated-dirt refusal (only changed-HEAD refusal is tested). Expand the boundary/unsafe-state matrix, including unrelated dirt with journal preservation, or narrow the PR claim.I independently reran
nix build .#checks.x86_64-linux.provisioning-contract --no-link -L,bash tests/pi-provider.sh(53 passing assertions), andgit diff --check. The current checks pass; these findings are contract/coverage gaps not reported test failures.Follow-up verification of the four findings against HEAD
dc503fa: all are resolved.retargetcomputes the old/new target difference before secret input and names every shared provider added to or removed from each VM.--credentialcan no longer replace the positional retarget ID, andrecoverrefuses provider-definition flags.Independent reruns passed:
bash tests/pi-provider.sh(82 assertions), the aggregate provisioning check, andgit diff --check. No findings remain from this review.The owner requested that this PR be rebased after a batch of changes landed on
master. This branch is one base commit behind. I will rebase it first because archetypes and deploy pin its exact feature head, rerun the aggregate lifecycle gate, then update those downstream pins to the rewritten commit.The repository's public-history policy rejected the force-push required by a literal rebase, so this branch was refreshed with a merge from current
masterinstead. Merge head:18c64d059688928694e8ff71c25cd17656efd230.The merged tree is byte-identical to the clean local rebase result. The aggregate provisioning contract passed, the standalone Pi lifecycle witness passed all 82 assertions, and
git diff --checkis clean. Archetypes and deploy will pin this new reachable head.