diff --git a/FABRIC-3.md b/FABRIC-3.md index 6597ae3..e07c612 100644 --- a/FABRIC-3.md +++ b/FABRIC-3.md @@ -2807,3 +2807,86 @@ first-boot mint routed through `MINT` onto a thumbdrive, block-fence flow retire CLI removed) is scoped in direction but not yet traced against the actual boot-sequence code the way `RUNCAP`/`MINT` themselves were before being built (§F.18/§F.19's own discipline) — that trace-first pass is the next step, not this one. + +**Update:** `disk/zuse.img`/`disk/user1.img` committed after this section closed, per direct +instruction. The bigger swap traced and built in §F.21, same pass. + +### F.21 — emergency CLI retired; Zuse goes thumbdrive-resident; ACL.4th activated + +The trace §F.20 asked for, done before touching code (same discipline as §F.18/§F.19): +`vm->emergency_console` is not a boot-time flag, it's recomputed on *every* REPL iteration +(`repl.c`, both `sk_repl_step` and `sk_repl_run`): `is_hera && !zuse_session → 1`, and when +set it skips ACL enforcement entirely at both the colon-word dispatch point and the outer +EXECUTE path (`vm_core.c`). A real finding this trace surfaced: `capsules/init.4th` had +`ACL.4th`'s own load commented out all session — ACL enforcement was **inactive**, bypass or +no bypass, the whole time, because the policy engine that would ever deny anything had never +loaded. Removing the bypass alone would have changed nothing observable. + +**Design, confirmed with Captain Bob before building:** system-resident storage keeps only +Zuse's *public* key, never her seed — the fence remembers "a root identity exists" and what +its pubkey is; the private key lives exclusively on her own minted thumbdrive. New +`zuse_genesis_marker_t` (magic/version/`zuse_pubkey[32]`/crc) takes over the fence's +devblock 0 slot `zuse_cert_devblock_t` used to occupy; that type is kept in the repo, header +marked superseded, no longer written by any path. + +**Genesis can't use regular `MINT`** — there's no existing Zuse to sign a cert with yet. +`capsule_mint_identity()` grows a genesis mode: `issuer_vm=NULL` skips the cert build/write +entirely (`cert_offset`/`cert_devblocks` stay 0) and skips the `zuse_cert_installed` check. +Two new optional out-params, `out_pubkey`/`out_seed`, let the caller (genesis's only caller) +install the cert immediately after minting — the seed otherwise never leaves the thumbdrive. + +**A real boot-ordering constraint, not assumed away:** `virtio_rng_init()` already precedes +the old Zuse block, and `xhci_bringup()` already precedes `sk_repl_run()` — no reorder was +actually needed. What matters instead: USB attach detection only ever happens inside +`sk_repl_idle()`'s own polling, which doesn't exist yet at kernel_main.c's old one-shot mint +point. So the genesis/attach logic can't be a boot-time step at all, regardless of ordering — +it has to live in the idle loop. New `capsule_zuse_boot_try_attach()` (`capsule_zuse_boot.c`), +called from `sk_repl_idle()` on every fresh attach: no-ops if Zuse already has a cert this +boot; no marker + `HOMEBLOCKS_SIG_BLANK` → genesis-mint, write the marker; marker present + +`HOMEBLOCKS_SIG_OK` + matching pubkey → read the drive's own `user_identity_seed_t`, install +the cert. Either path ends the same way: `vm_zuse_cert_install()` then +`vm_interpret(mama_vm, "ACL-ZUSE-BOOT")` — re-running the *existing* self-activation word +rather than adding new C-side auth logic (`ACL-PIN` only blocks redefinition, not +re-execution, so calling the same policy word again later is the correct, already-designed +way to activate `zuse_session` once a cert exists later than boot). + +**A real, previously-dormant bug, found the moment `ACL.4th` actually loaded for the first +time:** `zuse.4th`'s `ACL-ZUSE-BOOT` tried `['] ACL-ZUSE-BOOT ACL-PIN` from *inside its own +still-compiling definition* — the word isn't findable via `['] ` at that point (mid-compile), +so the whole colon-definition silently failed to compile, every boot, for as long as +`ACL.4th` has existed in this repo — just never noticed because nothing ever loaded it. +Fixed: pin *after* the definition closes (`: ACL-ZUSE-BOOT ... ;` then, separately, `['] +ACL-ZUSE-BOOT ACL-PIN`) — it only ever needs to run once anyway, and pinning doesn't block +the re-invocation genesis/attach depends on. + +**The bypass itself, removed:** the `emergency_console = is_hera ? ... : 0` assignment +deleted from both `repl.c` call sites. Every word run from Hera's own bare prompt now goes +through ordinary ACL enforcement. `emergency_console` the *field* still exists and is still +set, briefly, by the genuine C-level VM fault handler (`EMERGENCY_CONSOLE_ENABLED`) — a +distinct, narrower mechanism this REPL no longer touches. + +**Verified end-to-end, live, not just build-clean:** added `ZUSE-SESSION?` (read-only +diagnostic, matches `ZUSE-PUBKEY@`'s own precedent) to check the chain directly rather than +by inference. Fresh boot, no thumbdrive attached: `ZUSE-SESSION?` reads `0`. Attach a +genuinely blank drive via QMP: genesis mint fires automatically, no typing, console confirms +it; `ZUSE-SESSION?` then reads `-1` (true) — the complete chain (genesis mint → cert install +→ `ACL-ZUSE-BOOT` re-run → `ZUSE-AUTHENTICATE` → `zuse_session=1`) verified working, not +assumed. Clean 3-architecture regression: Hermes/Artemis both birth live, zero ACL denials, +zero `UNKNOWN WORD` beyond the deliberate POST self-test cases (`NOSUCH`/`NONEXISTENT`/ +`__acl_deny_test__`) — the first time this whole session `ACL.4th` has actually been +enforcing anything, and nothing broke. Commit `cc9521d`. + +**Still open, deliberately not chased in this pass:** the fence marker write itself still +fails ("fence marker write FAILED (not persistent)") — the same pre-existing, already-flagged +anomaly this session has seen with the old block-fence write path too (§ various), now +manifesting through the new marker write instead. Doesn't block same-boot activation (that +reads the freshly-generated data in memory, not the fence), but means the "already minted" +marker doesn't actually survive a reboot in this QEMU test environment yet — the +attach-authenticate path (marker present, matching drive reattached later) is designed and +built but not yet live-verified across a real reboot, blocked on this separate write-path +issue. A second, unrelated, general finding while testing: `LOG-INFO"` output from *any* +FORTH-defined colon-word body (tested standalone, unrelated to Zuse) doesn't appear on the +console at all in this build — `(do-log-info)` compiles and runs without error, just prints +nothing visible. Not chased; didn't block verification since `ZUSE-SESSION?` gave a direct +answer instead of needing the log line. With this closed, the console-VM + user-VM pair +(§F.20's own opening vision) is unblocked.