Repository navigation
fix(native): repair a changed provider tree and let a stopped runtime go down - #643
Conversation
… go down A stopped pool's `runtime down` runs nothing from the prepared provider tree, so it no longer verifies it; any other pool still verifies before stopping. Every start still refuses a changed tree, and the refusal now names the repair. `runtime repair-provider-tree` re-prepares the SmolVM and Docker engine trees of a stopped runtime from the archives preparation kept: the record must match the pins, the kept archive must be owned with the pinned SHA-256, and the fresh extraction must hash to the recorded tree digest. The changed tree is renamed aside and kept; runtime state and volumes are untouched. Refs HACK-1950 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
Codex Review Summary: ✅ CompletedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Codex Review: Didn't find any major issues. Nice work! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
Linux clippy flagged prepared_smolvm as dead code because only the macOS-gated provider repair tests call it. Refs HACK-1950 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Problem
When something outside Hack changes the prepared SmolVM provider tree (the real-world trigger was a cleanup tool that pruned every empty directory, such as
agent-rootfs/dev,proc,tmp,etc/init.d), every runtime command failed withartifact_digest_mismatch, includingruntime downon an already stopped runtime. The candidate installer's quiescence check (status,down,status) then failed andupgradewas blocked, and there was no supported way to re-prepare the tree from the archive preparation had already kept.Final behavior
runtime downon a stopped pool runs nothing from the provider tree, so it no longer verifies it. "Stopped" is the existing condition: a phase written only before a start or after proven provider absence (stopped,stopped-before-engine,stopped-after-engine-failure,recovered-unclean) and no live provider. For any other pool,downstill verifies the tree before the hostname-authority and publication steps, exactly as before.runtime statusalready read no tree; a regression test now covers it.upand every other path that runs the provider still callverify. Its fixed message now names the repair: "With the runtime stopped, run runtime repair-provider-tree to re-prepare it from the verified retained archive; runtime state and volumes are kept." The Docker engine tree gets the same message.runtime repair-provider-tree [--json]. It holds the provider lock and requires a stopped (or uninitialized) pool with no active image build. For each prepared tree (SmolVM, and the Docker engine, which has the same shape):repaired: falseand left alone;providers/smolvm-installing/release.tar.gz,providers/docker-installing/release.tgz) must be an owned regular file, with one link, in an owned directory, with the pinned SHA-256;-repairing-staging directory and hashed again, extracted, signature-checked (SmolVM, as preparation does), and the fresh tree must hash to the digest recorded at preparation;<tree>-changed-<id>(kept, never deleted) and the fresh tree renamed into place, then verified again.Runtime state, disks and volumes under
run/are not touched. A repair that fails a check changes no tree and keeps its staging. Without a kept archive it refuses withprovider_repair_unavailable.Validation
artifact::tests::a_tree_pruned_of_empty_directories_is_repaired_from_its_retained_archive: a pinned fixture archive with nested empty directories, a symlink and an executable is prepared the same way preparation lays out state. Pruning its empty directories makesverifyrefuse. The repair restores the recorded digest, keeps the changed tree and the kept archive, leaves no staging, and an intact tree is not replaced (same inode).artifact::tests::repair_refuses_without_a_verified_archive_or_a_matching_extraction: covers an unprepared tree, a wrong archive digest, a missing archive, a symlinked archive, a record no extraction can match (the tree is unchanged and the staging is kept), and a record for another version.lifecycle::provider_repair_tests(macOS): on a stopped pool with a pruned SmolVM tree under the real pins,status,downandstatusall succeed (the installer's sequence) whileverifystill refuses and names the repair. The repair then fixes the fixture tree, and the owner, machine and phase are unchanged. On a pool that is not proven stopped,downstill refuses withartifact_digest_mismatchand the repair refuses withprovider_repair_requires_stopped_runtime. A home with nothing prepared creates no state.origin/nexte19e0b1):artifact::tests,provider_repair_tests).RUSTUP_TOOLCHAIN=1.97.1 bun run check:local(cargo fmt --checkplus clippy--all-targets -D warnings): pass.RUSTUP_TOOLCHAIN=1.97.1 bun run test:local: 1559 passed, 0 failed, 115 ignored across 23 test binaries. This ran from a short-path worktree becausenode_contractneeds socket paths underSUN_LEN. From the long scratch path, onlynode_contractfailed, with the known SUN_LEN error.bun run --cwd packages/cli typecheckshows only the existingtests/fixtures/atomic-write-foreign-owner-worker.ts(39,25)error, which is identical onorigin/next.gitleaks protect --stagedandgitleaks detect --log-opts=origin/next..HEAD: no leaks.Remaining gaps
downmust verify before it runs the provider) nor repaired (repair requires a stopped pool). That case is unchanged.Refs HACK-1950
🤖 Generated with Claude Code
Open in [code]smith · Need help on this PR? Tag
@codesmith-botwith what you need.