Stage E amendment: resolve drive_uuid wrinkle via scratch-device mint (FABRIC-3.md §XXXII.2)
Build / build-amd64-iso (push) Waiting to run
Build / build-aarch64-iso (push) Waiting to run
Build / build-riscv64-img (push) Waiting to run

Bob's proposal: mint against a "sim thumbdrive" -- a scratch blkio_dev
from the existing blk_subsys_add_raw_device() mechanism (same one the
kernel ramdrive already uses), then hand-transcribe just drive_uuid +
DER cert as FORTH literals into a normal .4th capsule block.

This dissolves the wrinkle the first pass of Q2 left open:
capsule_mint_identity() runs completely unmodified against the scratch
device (same live Zuse-signing op, same rng_get_bytes() draw for
drive_uuid), so vm_identity_from_cert() needs zero changes -- no
origin-aware variant, no content-hash-derived substitute. "Sim"
describes only where the bytes were written, invisible to verify.

Also corrects an error in the first pass: cert production cannot be
"offline" -- capsule_mint_identity() requires Zuse's live in-kernel
signing key, so minting is inescapably a two-boot runtime operation
(mint on boot N, package by hand, birth on boot N+1).

Punch list updated to match. Still design-only, no code.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BWpNjdwPtFLuVLaAq44L9K
This commit is contained in:
Robert Allan James
2026-09-16 04:01:32 -04:00
co-authored by Claude Sonnet 5
parent 06e2507ce4
commit 60bcdc09a7
+43 -25
View File
@@ -4311,15 +4311,21 @@ seed into a git-committed capsule.
This collapses all four questions:
1. **Packaging -- a new capsule content convention, not a new `mkcapsule` mode or MINT
variant.** No seed means no secret-handling in the build tool at all: the DER cert
(produced offline by the existing `MINT`/`capsule_mint_identity()` path, Zuse-signed, same
as today) becomes part of a normal `(p)` PRODUCTION capsule's own payload, following the
same `Block NNNN` convention every capsule already uses for its personality source.
§XXIV's collision machinery (`check_block_conflicts()`, `mkcapsule --resolve`,
`capsule-reserved.txt`) already covers this -- it's blind to *content*, only to block
numbers, so a cert-carrying capsule is just another capsule to it. No new collision risk,
no change needed to §XXIV's machinery.
1. **Packaging -- a new capsule content convention, not a new `mkcapsule` mode.** Correction
to the first pass of this answer: "produced offline" was wrong.
`capsule_mint_identity()` requires `issuer_vm->zuse_cert_seed` -- Zuse's live in-kernel
private key -- so minting can only happen at runtime, on a booted Hera with Zuse
authenticated, exactly like a human identity today. No host-side build tool can produce
this cert. The real shape is two boots: **mint on boot N, package the output as capsule
source by hand, birth it on boot N+1** once that source has gone through a normal build.
Captain Bob confirmed (2026-09-16) the packaging step is a hand-copy: mint against a
scratch device (item 2 below), then transcribe just `drive_uuid` (16 bytes) + the DER
cert bytes as FORTH literals into a normal `.4th` block -- no binary packaging, no new
`mkcapsule` mode, no change to the build tool at all. §XXIV's collision machinery
(`check_block_conflicts()`, `mkcapsule --resolve`, `capsule-reserved.txt`) already covers
this once it exists as a `.4th` block -- it's blind to *content*, only to block numbers, so
a cert-carrying capsule is just another capsule to it. No new collision risk, no change
needed to §XXIV's machinery.
2. **Birth -- `capsule_birth_baby()`, unmodified, not `capsule_runcap_birth()`.**
`capsule_runcap_birth()` was the wrong tool: its own header says a user's identity source
"never exists at build time" (`capsule_runcap.h:19-20`) -- exactly backwards for a
@@ -4334,14 +4340,21 @@ This collapses all four questions:
`vm_identity_from_cert()` has verified the cert. The unattended path calls
`vm_identity_from_cert()` on the capsule's own embedded DER cert immediately after
`capsule_birth_baby()` returns, then assigns the result the same way.
**One real wrinkle, not silently resolved:** `vm_identity_from_cert()`'s serial-number
check binds the cert to a physical `drive_uuid` (`homeblocks_sig_t`, 16 bytes) -- a
capsule-embedded identity has no physical drive and thus no `drive_uuid` to bind against.
Either the cert-issuing step needs a different binding value for this identity origin (e.g.
the capsule's own content hash, already the system's universal identity primitive) or
`vm_identity_from_cert()` needs a origin-aware variant. **Not designed here -- flagged for
the punch list, needs Bob's call on what an unattended identity's cert should bind to
before implementation.**
**The `drive_uuid` wrinkle flagged in the first pass of this answer is resolved, not
deferred -- Bob's proposal (2026-09-16): mint against a "sim thumbdrive," a scratch
`blkio_dev` obtained from the exact same generic RAM-backed mechanism the kernel's own
ramdrive already uses (`blk_subsys_add_raw_device()`, `capsule_loader.c:100`), sized for
just a sig devblock + cert devblock (no seed devblock -- the no-seed decision above means
`capsule_mint_identity()`'s seed-writing step is simply never reached/read back).
`capsule_mint_identity()` runs against this scratch device completely unmodified -- same
live Zuse-signing operation, same `rng_get_bytes()` draw for `drive_uuid`
(`capsule_mint.c:209-213`) as a real thumbdrive gets. This means `drive_uuid` is a genuine
random draw living in a genuine `homeblocks_sig_t`, not a derived or synthetic value --
"sim" describes only *where* the bytes were written (a throwaway RAM buffer instead of
physical media), a property entirely invisible to the verify path.
**`vm_identity_from_cert()` needs zero changes** -- no origin-aware variant, no
content-hash-derived substitute. This is a strictly better answer than the deferred
"Bob's call" the first pass of this section left open.
3. **ACL-gated console attachment -- checks the attaching human's own credentials, not the
instance's.** Falls directly out of the no-seed decision: an unattended instance can never
prove anything about itself at attach time (it holds no secret to challenge), so the gate
@@ -4358,14 +4371,19 @@ This collapses all four questions:
**Punch list for implementation (not started, needs explicit authorization per this project's
standing "plan approval is not a start signal" rule):**
- Decide what an unattended identity's cert binds to instead of `drive_uuid` (item 2's
wrinkle) -- Bob's call.
- Define the new capsule content convention for an embedded cert (which block(s), what
format) and add build-time production of it (offline `MINT`-equivalent step, not new
runtime code).
- Add the unattended-birth call site: `capsule_birth_baby()` + `vm_identity_from_cert()` +
post-birth `identity` assignment, gated by the explicit invariant already stated above
(never touch `g_wirebind_attached_username`/console-pairing).
- Build the scratch-device mint path: attach a `blk_subsys_add_raw_device()`-backed buffer
sized for sig+cert devblocks only, run `capsule_mint_identity()` against it unmodified
(live, on a booted Hera with Zuse authenticated -- likely a new FORTH word, or a `MINT`
variant that takes a device handle rather than always resolving one from an attach event).
- Hand-transcribe the resulting `drive_uuid` + DER cert bytes out of the scratch buffer as
FORTH literals into a new `.4th` capsule block, following the existing `Block NNNN`
convention -- checked into the repo, picked up by the next `mkcapsule` build like any other
capsule.
- Add the unattended-birth call site: `capsule_birth_baby()` (unmodified) + read the embedded
`drive_uuid`+cert literals back out of the capsule's own arena + `vm_identity_from_cert()`
(unmodified) + post-birth `identity` assignment (`capsule_wirebind.c:272-274`'s pattern),
gated by the explicit invariant already stated above (never touch
`g_wirebind_attached_username`/console-pairing).
- Assign a real `acl_caps` bit for "may attach a console to an unattended instance" and wire
the check into the console-birth + `VM-NAME-REG` path.
- Acceptance: 3-arch clean boot with at least one unattended instance born at boot, no console