bootstrap-vm: inject and refresh host-provided repos from the hypervisor #75

Merged
vnprc merged 3 commits from agent/host-provided-repos into master 2026-10-01 20:56:27 +01:00
Member

A dev VM whose forge identity may not read one of its declared repos can now be provisioned: bootstrap-vm leaves every id in the machine's host_provided_repos out of the guest clone step and instead pushes the hypervisor's own checkout into the guest at ~/work/<checkout> over the host SSH identity. For a machine without the marker nothing changes: the guest step builds the same triples and no host step runs. On a marked machine the guest copy is created with git init and refreshed by git push into receive.denyCurrentBranch=updateInstead, so a guest tree with uncommitted changes, its own commits, or another branch checked out refuses the push loudly instead of being overwritten; verify-vm --repair reruns the same step. The guest copy carries no origin, which is how guest tools recognise it (allod/tools#269). What proves it: 21 mocked bootstrap cases, including a real filesystem push that lands and then refuses on a dirtied guest file. If it is wrong, revert; a machine without the marker is untouched, and a marked machine's guest copy is disposable.

Closes allod/nexus#73
Refs allod/strategy#62

The marker's name and rendering are allod/inventory#22; this script reads host_provided_repos // [] so either can land first.

Risk

R3 by the walk: provisioning path and a cross-repo interface (the inventory key, the no-origin contract for tools). The worst credible failure after validation is a refused push on a marked machine, which names the guest path and leaves both copies as they were; a hypervisor checkout that is missing or detached is refused before the known_hosts write. Nothing here can touch an unmarked machine. Rollback is a straight revert. The live witness is the owner's verify-vm --repair allod-dev on the hypervisor once the deployment marks its fork.

Validation

  • bash tests/bootstrap-orchestration.sh: 21 passed. New cases: host-provided id skipped from the guest triples and pushed by the host step with the expected URL and refspec; an id outside repos and a missing hypervisor checkout both refused before any side effect; the guest prep script exercised directly with real git (fresh init with no remote and the config set; a plain directory nested in a parent repo, an existing remote, another branch and a dirty tree each refused; a clean rerun a no-op); one end-to-end push by filesystem path that lands and then is refused on a dirtied guest file.
  • nix build .#checks.x86_64-linux.provisioning-contract: green (bash -n, shellcheck, every suite).
  • allod check: all 12 steps passed.
  • Transport measured by the integrator on git 2.54 before the design was fixed: push into an unborn branch checks the tree out, repush is up to date, dirty or staged trees and guest-local commits are refused, untracked files are left alone, no remote is created; a branch mismatch updates only the ref, which is why the prep step refuses it first.
  • Sabotage: disabling the dirty-tree guard and the .git existence test each failed their case; restored.
  • One cold cross-family review (codex gpt-5.6-sol): its nested-directory and unquoted SSH findings and six comment items were fixed in the second commit; its untracked-files finding describes the chosen behavior, now stated in the docs.
A dev VM whose forge identity may not read one of its declared repos can now be provisioned: `bootstrap-vm` leaves every id in the machine's `host_provided_repos` out of the guest clone step and instead pushes the hypervisor's own checkout into the guest at `~/work/<checkout>` over the host SSH identity. For a machine without the marker nothing changes: the guest step builds the same triples and no host step runs. On a marked machine the guest copy is created with `git init` and refreshed by `git push` into `receive.denyCurrentBranch=updateInstead`, so a guest tree with uncommitted changes, its own commits, or another branch checked out refuses the push loudly instead of being overwritten; `verify-vm --repair` reruns the same step. The guest copy carries no `origin`, which is how guest tools recognise it (allod/tools#269). What proves it: 21 mocked bootstrap cases, including a real filesystem push that lands and then refuses on a dirtied guest file. If it is wrong, revert; a machine without the marker is untouched, and a marked machine's guest copy is disposable. Closes allod/nexus#73 Refs allod/strategy#62 The marker's name and rendering are allod/inventory#22; this script reads `host_provided_repos // []` so either can land first. ## Risk R3 by the walk: provisioning path and a cross-repo interface (the inventory key, the no-origin contract for tools). The worst credible failure after validation is a refused push on a marked machine, which names the guest path and leaves both copies as they were; a hypervisor checkout that is missing or detached is refused before the known_hosts write. Nothing here can touch an unmarked machine. Rollback is a straight revert. The live witness is the owner's `verify-vm --repair allod-dev` on the hypervisor once the deployment marks its fork. ## Validation - `bash tests/bootstrap-orchestration.sh`: 21 passed. New cases: host-provided id skipped from the guest triples and pushed by the host step with the expected URL and refspec; an id outside `repos` and a missing hypervisor checkout both refused before any side effect; the guest prep script exercised directly with real git (fresh init with no remote and the config set; a plain directory nested in a parent repo, an existing remote, another branch and a dirty tree each refused; a clean rerun a no-op); one end-to-end push by filesystem path that lands and then is refused on a dirtied guest file. - `nix build .#checks.x86_64-linux.provisioning-contract`: green (bash -n, shellcheck, every suite). - `allod check`: all 12 steps passed. - Transport measured by the integrator on git 2.54 before the design was fixed: push into an unborn branch checks the tree out, repush is up to date, dirty or staged trees and guest-local commits are refused, untracked files are left alone, no remote is created; a branch mismatch updates only the ref, which is why the prep step refuses it first. - Sabotage: disabling the dirty-tree guard and the `.git` existence test each failed their case; restored. - One cold cross-family review (codex gpt-5.6-sol): its nested-directory and unquoted `SSH` findings and six comment items were fixed in the second commit; its untracked-files finding describes the chosen behavior, now stated in the docs.
A guest's forge identity may not be able to read every repo it needs;
bootstrap-vm now skips those (named by vm-specs.json's host_provided_repos)
in the guest clone loop and instead pushes the hypervisor's own checkout
onto the guest over the existing host SSH identity, into a guest-side
git init with receive.denyCurrentBranch=updateInstead. The push refuses
loudly rather than overwrite a guest tree with local changes.

Refs allod/nexus#73
host-provided-checkout.sh used `git rev-parse --git-dir` to test
whether an existing path is a git checkout; git discovers a parent
repository through a plain subdirectory, so the probe passed on a
directory nested in some other repo and would go on to configure and
push into that parent. Test `-d "$path/.git"` directly instead, and
add a regression test for the nested-directory case.

Also %q-quote $SSH in HOST_PUSH_SSH_CMD like the key and known-hosts
paths already are, trim comments to their load-bearing line per
writing.md, and document that an untracked guest file is left alone
unless an incoming file would overwrite it.
vnprc approved these changes 2026-10-01 20:56:22 +01:00
vnprc merged commit 4b7faff8fd into master 2026-10-01 20:56:27 +01:00
vnprc deleted branch agent/host-provided-repos 2026-10-01 20:56:28 +01:00
Sign in to join this conversation.
No description provided.