Host-provided repos: inject and refresh a checkout from the hypervisor when the guest may not read its remote #62

Closed
opened 2026-10-01 16:26:28 +01:00 by vnprc-agent · 3 comments
Contributor

A dev VM whose forge identity may not read one of its declared repos gets that checkout from the hypervisor, which holds the credential, instead of a guest-side clone that can never succeed.

The framework asserts that every dev VM lists every memory repo (allod/archetypes aef13ef), and the guest bootstrap clones every listed repo with the guest's own forge key under set -e. A deployment whose public-facing dev VM is denied read access to its private memory fork by design cannot satisfy both: listing the repo makes the machine unprovisionable (the bootstrap dies at that clone and verify-vm fails) and leaves the harness memory symlink dangling, while omitting it fails the eval assert. The witness is allod-dev on 2026-10-01 (allod/nexus#71, allod/archetypes#127).

Primary goals:

  • A machine definition can mark a repo host-provided — the marker is per machine and rendered into vm-specs.json; the eval assert stays satisfied because the repo remains in repos.
  • The hypervisor injects and refreshes it — bootstrap-vm skips host-provided repos in the guest clone step and runs a host step that puts the hypervisor's own checkout at the guest's declared path over the host-to-guest ssh channel the scripts already use. The same step is the update path, so verify-vm --repair refreshes it and verify-vm keeps checking that it exists.
  • The guest never holds the credential — the injected checkout has no reachable remote; nothing on the guest fetches or pushes it, and the tools that walk every checkout (pull-all, work-diff, flake-update-cascade) skip it by a rule instead of failing.
  • Direction stays host to guest — no guest gains ssh or git access to the hypervisor for this.

Design notes

Transport is decided in the nexus child: a push from the hypervisor into the guest path with receive.denyCurrentBranch=updateInstead, which refuses a dirty guest tree loudly, or a git bundle over scp, which is the transport deployments already use by hand between the hypervisor and this machine. The injected checkout should be recognizable as host-provided on the guest, for example by carrying no origin, so tools skip it by inspection rather than by a list they would have to keep in sync.

Children

  • allod/nexus#73 — bootstrap-vm host step, skip in the guest step, refresh on repair
  • allod/inventory, to file once the nexus child fixes the field name — the per-machine marker and its vm-specs.json rendering, mirrored by deployments
  • allod/tools, to file once the guest-side marker is fixed — pull-all and the other checkout walkers skip host-provided checkouts
  • deployment side, tracked privately — the machine marks its fork, and a one-off injection by hand repairs the dangling symlink before the mechanism lands

Scope

Tracked separately: rebuild-vm running the verifier after its switch (allod/nexus#71) and a loud activation warning on a missing memory checkout (allod/archetypes#127). Both remain useful once this lands; neither replaces it.

A dev VM whose forge identity may not read one of its declared repos gets that checkout from the hypervisor, which holds the credential, instead of a guest-side clone that can never succeed. The framework asserts that every dev VM lists every memory repo (allod/archetypes aef13ef), and the guest bootstrap clones every listed repo with the guest's own forge key under `set -e`. A deployment whose public-facing dev VM is denied read access to its private memory fork by design cannot satisfy both: listing the repo makes the machine unprovisionable (the bootstrap dies at that clone and `verify-vm` fails) and leaves the harness memory symlink dangling, while omitting it fails the eval assert. The witness is allod-dev on 2026-10-01 (allod/nexus#71, allod/archetypes#127). Primary goals: - **A machine definition can mark a repo host-provided** — the marker is per machine and rendered into `vm-specs.json`; the eval assert stays satisfied because the repo remains in `repos`. - **The hypervisor injects and refreshes it** — `bootstrap-vm` skips host-provided repos in the guest clone step and runs a host step that puts the hypervisor's own checkout at the guest's declared path over the host-to-guest ssh channel the scripts already use. The same step is the update path, so `verify-vm --repair` refreshes it and `verify-vm` keeps checking that it exists. - **The guest never holds the credential** — the injected checkout has no reachable remote; nothing on the guest fetches or pushes it, and the tools that walk every checkout (`pull-all`, `work-diff`, `flake-update-cascade`) skip it by a rule instead of failing. - **Direction stays host to guest** — no guest gains ssh or git access to the hypervisor for this. ### Design notes Transport is decided in the nexus child: a push from the hypervisor into the guest path with `receive.denyCurrentBranch=updateInstead`, which refuses a dirty guest tree loudly, or a git bundle over scp, which is the transport deployments already use by hand between the hypervisor and this machine. The injected checkout should be recognizable as host-provided on the guest, for example by carrying no `origin`, so tools skip it by inspection rather than by a list they would have to keep in sync. ### Children - [ ] allod/nexus#73 — `bootstrap-vm` host step, skip in the guest step, refresh on repair - [ ] allod/inventory, to file once the nexus child fixes the field name — the per-machine marker and its `vm-specs.json` rendering, mirrored by deployments - [ ] allod/tools, to file once the guest-side marker is fixed — `pull-all` and the other checkout walkers skip host-provided checkouts - [ ] deployment side, tracked privately — the machine marks its fork, and a one-off injection by hand repairs the dangling symlink before the mechanism lands ### Scope Tracked separately: `rebuild-vm` running the verifier after its switch (allod/nexus#71) and a loud activation warning on a missing memory checkout (allod/archetypes#127). Both remain useful once this lands; neither replaces it.
Member

All public children are filed and have pull requests open; only the deployment-side child remains, which is tracked privately.

Child Issue Pull request
bootstrap-vm host step, guest-step skip, refresh on repair allod/nexus#73 allod/nexus#75
per-machine marker host_provided_repos, rendered into vm-specs.json allod/inventory#21 allod/inventory#22
pull-all and flake-update-cascade skip a checkout with no origin allod/tools#268 allod/tools#269
rebuild-vm runs verify-vm after the switch (tracked separately) allod/nexus#71 allod/nexus#74
loud activation warning on a missing memory checkout (tracked separately) allod/archetypes#127 allod/archetypes#128

Decisions taken in the children: the marker is host_provided_repos, a list of registry ids that must each appear in the machine's repos; the transport is a git push from the hypervisor into a guest-side git init with receive.denyCurrentBranch=updateInstead, which refuses a dirty tree, guest-local commits, and (by a prep check before the push) a different checked-out branch; the guest copy carries no origin, and that absence is the rule the tools child keys on. The nexus and inventory changes are independent, since bootstrap-vm reads the key as host_provided_repos // []. Each pull request carries its own risk score and validation. This issue stays open for the deployment-side child and for whoever owns it to close.

All public children are filed and have pull requests open; only the deployment-side child remains, which is tracked privately. | Child | Issue | Pull request | | --- | --- | --- | | `bootstrap-vm` host step, guest-step skip, refresh on repair | allod/nexus#73 | allod/nexus#75 | | per-machine marker `host_provided_repos`, rendered into `vm-specs.json` | allod/inventory#21 | allod/inventory#22 | | `pull-all` and `flake-update-cascade` skip a checkout with no `origin` | allod/tools#268 | allod/tools#269 | | `rebuild-vm` runs `verify-vm` after the switch (tracked separately) | allod/nexus#71 | allod/nexus#74 | | loud activation warning on a missing memory checkout (tracked separately) | allod/archetypes#127 | allod/archetypes#128 | Decisions taken in the children: the marker is `host_provided_repos`, a list of registry ids that must each appear in the machine's `repos`; the transport is a `git push` from the hypervisor into a guest-side `git init` with `receive.denyCurrentBranch=updateInstead`, which refuses a dirty tree, guest-local commits, and (by a prep check before the push) a different checked-out branch; the guest copy carries no `origin`, and that absence is the rule the tools child keys on. The nexus and inventory changes are independent, since `bootstrap-vm` reads the key as `host_provided_repos // []`. Each pull request carries its own risk score and validation. This issue stays open for the deployment-side child and for whoever owns it to close.
Member

A second repo on allod-dev is in the same position as the memory fork but cannot be host-provided, because the guest writes and pushes it: the traces repo. Tracked as allod/strategy#63, deployment-side.

A second repo on allod-dev is in the same position as the memory fork but cannot be host-provided, because the guest writes and pushes it: the traces repo. Tracked as allod/strategy#63, deployment-side.
Author
Contributor

All four children have landed: allod/nexus#73 (bootstrap-vm host step), allod/inventory#21 (marker and rendering), allod/tools#268 (checkout walkers skip a no-origin checkout), and the deployment-side child, tracked privately, which marked its fork's private memory repo host-provided, bumped its deploy lock, and ran the repair on the hypervisor. Closing as completed.

All four children have landed: allod/nexus#73 (bootstrap-vm host step), allod/inventory#21 (marker and rendering), allod/tools#268 (checkout walkers skip a no-origin checkout), and the deployment-side child, tracked privately, which marked its fork's private memory repo host-provided, bumped its deploy lock, and ran the repair on the hypervisor. Closing as completed.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
allod/strategy#62
No description provided.