FABRIC-3.md §I.3/§I.8: WIREBIND EJECT/detach + EXPIRE re-scoped as logout

Closes §I.3 (Milestone 5 remainder): WIREBIND now tracks which VM is
attached via the home-blocks USB path, and a new EJECT word plus the
existing hot-unplug signal both flush/reset-console/kill through it
(FABRIC-3.md §F.10).

Closes §I.8 (EXPIRE/ACL), re-scoped: the original "admit the zuse
session as a Stadium patron and reap on TTL" plan was invalidated a
second time -- Zuse authenticates directly onto Hera, who is patron
zero and permanently pinned, so there is no patron for a reap sweep to
ever find. Built instead as a detach-triggered logout
(capsule_zuse_boot_logout()), the same trigger EJECT/hot-unplug use for
regular WIREBIND users, so neither identity is a special case. Required
a companion fix: install_and_activate() used to skip re-running
ACL-ZUSE-BOOT whenever the cert was already installed, which made a
logout permanent for the rest of the boot; the outer re-attach gate now
checks zuse_session (clears on logout) instead of zuse_cert_installed
(a deliberate permanent one-way ratchet, left untouched).

Verified 3-arch boot to ok> (amd64/aarch64/riscv64, each in the
foreground) after both steps; logs and DoE CSVs from this session's
verification runs included per this repo's own audit-artifact
convention.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var
This commit is contained in:
Robert Allan James
2026-09-04 09:21:01 -04:00
co-authored by Claude Sonnet 5
parent 34203613bb
commit 60d9c2520e
40 changed files with 165701 additions and 16 deletions
+36 -2
View File
@@ -21,6 +21,14 @@
#include <string.h>
#include <stddef.h>
/* FABRIC-3.md §I.8 (re-scoped 2026-09-04): tracks whether the currently
* home-blocks-attached device is Zuse's own -- the single-USB-device
* constraint (§F.8) means capsule_zuse_boot_logout() only needs one flag,
* not a device/uuid comparison, to know a detach event is hers to act on
* (a regular WIREBIND user occupying the one slot instead is tracked
* separately, in capsule_wirebind.c -- the two paths never overlap). */
static int g_zuse_attached_this_device = 0;
/* Read exactly one devblock (4096 bytes) at devblock offset `devblock`,
* as 4 consecutive 1KiB forth-block reads -- mirrors capsule_runcap.c's
* and homeblocks_sig_check()'s own read convention. */
@@ -45,7 +53,17 @@ static int genesis_marker_read(zuse_genesis_marker_t *out) {
}
static void install_and_activate(VM *mama_vm, const uint8_t seed[32], const uint8_t pubkey[32]) {
if (vm_zuse_cert_install(mama_vm, seed, pubkey) != 0) return;
/* vm_zuse_cert_install() is deliberately one-way (returns -1, no-op,
* once vm->zuse_cert_installed is already 1) -- that's a real
* security property (the cert/pubkey must never be re-installed or
* swapped) and stays untouched here. Its return is NOT used to gate
* ACL-ZUSE-BOOT below anymore (FABRIC-3.md §I.8, re-scoped
* 2026-09-04): re-authenticating after capsule_zuse_boot_logout()
* needs ACL-ZUSE-BOOT to re-run and re-set zuse_session even when
* the cert itself was already installed from an earlier boot-time
* attach -- gating it on install's success/failure made re-login
* impossible, since a second install always fails by design. */
vm_zuse_cert_install(mama_vm, seed, pubkey);
/* zuse.4th's ACL-ZUSE-BOOT self-activated once already at Mama's own
* birth, when no cert was installed yet (the thumbdrive wasn't
* attached at that early, one-shot point) -- ACL-PIN only blocks
@@ -55,6 +73,7 @@ static void install_and_activate(VM *mama_vm, const uint8_t seed[32], const uint
* logic; policy stays in ACL.4th/zuse.4th per this project's own
* convention. */
vm_interpret(mama_vm, "ACL-ZUSE-BOOT");
g_zuse_attached_this_device = 1;
}
void capsule_zuse_boot_try_attach(struct blkio_dev *dev,
@@ -62,7 +81,13 @@ void capsule_zuse_boot_try_attach(struct blkio_dev *dev,
const homeblocks_sig_t *sig,
VM *mama_vm) {
if (!dev || !mama_vm) return;
if (mama_vm->zuse_cert_installed) return; /* already have Zuse this boot */
/* FABRIC-3.md §I.8, re-scoped 2026-09-04: gate on zuse_session, not
* zuse_cert_installed. zuse_cert_installed never clears (one-way,
* see install_and_activate()'s own comment) and would permanently
* block re-authentication after a logout; zuse_session does clear
* (capsule_zuse_boot_logout()), which is exactly the "already have
* Zuse THIS SESSION" check this early-return is actually for. */
if (mama_vm->zuse_session) return;
zuse_genesis_marker_t marker;
int have_marker = (genesis_marker_read(&marker) == 0);
@@ -117,3 +142,12 @@ void capsule_zuse_boot_try_attach(struct blkio_dev *dev,
console_println("Zuse: identity confirmed from attached thumbdrive");
install_and_activate(mama_vm, idrec.seed, idrec.pubkey);
}
void capsule_zuse_boot_logout(VM *mama_vm) {
if (!mama_vm || !g_zuse_attached_this_device) return;
mama_vm->zuse_session = 0;
g_zuse_attached_this_device = 0;
console_println("Zuse: session ended -- reattach to re-authenticate");
}