# ENGINE Step 4, ahead of Part A: the identity gate on v4 — Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans (Captain Bob prefers native execution). Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** On bare metal, v4 does what v3 does about identity before its prompt: with no identity drive the system is headless, with no prompt; when Zuse's minted thumbdrive is attached the kernel recognises it, and only then is there a console. Pulling the drive ends the session and the system goes headless again; putting it back brings the prompt back. **Why now (Captain Bob, 2026-10-26):** "Gate first." Step 4's work goes ahead "only if zuse thumbdrive is attached so you have zuse. no identity thumb drive equals headless. when a thumb drive is inserted, only then is there an identity and a console" (2026-10-20, `ENGINE.md` §2). Today the v4 boot cannot meet that: `sk_v4_run()` (`kernel_main.c:580`) never returns, and it runs before USB bring-up (`:823`), the heartbeat (`:915`) and the headless wait (`:1927`), so a drive attached to a v4 boot is never read. The drive exists: `disk/zuse-scratch/` (`1f157e97`), a minted Zuse pair. **Spec:** `ENGINE.md` §2 (the rulings of 2026-10-20, the identity gate), `MACHINE.md` §5.1, the step 4 plan (`2026-10-20-engine-step4-node-in-the-vms-place.md`, "The identity gate"), `V3-PARITY.md` §1 rows 11 and 12. ## What v3 does (read 2026-10-26, `kernel_main.c`, `repl.c`, `capsule_zuse_boot.c`) 1. After POST and the devices: `pci_init`, entropy, Artemis's virtio disk attached, and `capsule_zuse_boot_load_root_pubkey()` reads Zuse's public key from the genesis marker in the disk's metadata fence (`blk_meta_zone_read(0)`). 2. Every xHCI controller is found and brought up (`xhci_find_and_map`, `xhci_bringup`); a drive already in a port is enumerated by the bring-up's port scan. 3. The timer starts, interrupts are enabled ("Heartbeat running."). 4. `sk_repl_headless_wait()`: no banner, no prompt, no input. Every 100 ticks (`sk_repl_idle`): `xhci_poll_events()`; for each mass-storage device whose attach is pending, `blkio_usb_open_msc()`, then `homeblocks_sig_check()`; the device is given to the block subsystem (in v3 by a round trip through the Artemis VM and kernel-Hermes, ending in `BLK-ATTACH-ACK` on Hera); then `capsule_zuse_boot_try_attach()`: - genesis marker present and the drive's identity record (magic, version, CRC-64) carries the marker's public key: "Zuse: identity confirmed from attached thumbdrive"; the cert is installed (one-way), and `ACL-ZUSE-BOOT` sets Hera's `zuse_session`; - no marker and a blank drive: genesis — Zuse is minted onto the drive and the marker written to the disk's fence; - anything else: nothing. The wait ends when `sk_console_identity_present()`: Zuse's session, or a `WIREBIND` user. 5. The banner, then `sk_repl_run()`, which re-checks identity before every prompt and while it waits for a line with nothing typed; when no one is attached it goes back to the headless wait. A drive pulled out: `blk_subsys_detach_device()`, `capsule_zuse_boot_logout()` ("Zuse: session ended -- reattach to re-authenticate"). ## What v4 does instead (Q1 ruled: Hera, Hermes, Artemis are kernel functions) The same steps, done by the kernel for the v4 boot, with no v3 `VM` behind them: - **Artemis is the kernel's**, so the kernel gives an attached drive to the block subsystem itself (`blk_subsys_attach_device`), with no VM round trip. - **Zuse's state is the kernel's**, held for the first node, Hera: session, cert installed (one-way), root public key. Not in the node's memory and not in a v3 `VM`. - **The prompt loop** in `sk_v4_run()` re-checks identity as `sk_repl_run()` does. ## Decisions for Captain Bob **RULED 2026-10-26 (Captain Bob): D1 to D4 as recommended** — split the file; recognise only; `[zuse@Hera] ok>` now; the minted pair the QEMU default. **D1. The identity check without a VM.** `capsule_zuse_boot_try_attach()` takes Hera's `VM *` and ends in `vm_interpret(mama_vm, "ACL-ZUSE-BOOT")`; its readers (`genesis_marker_read`, `read_devblock`, the identity-record checks) are `static`. *Recommend:* split `capsule_zuse_boot.c` into a check that needs no VM — given the device and its signature result, it says "Zuse's drive", "genesis-eligible" or "not hers" and hands back her seed and public key — and v3's `try_attach`, which calls it and does the rest exactly as now. v4 calls the same check. One copy of code that handles Zuse's private key. *Cost:* it is a change to a file on v3's path (the plan's rule is "nothing in v3's own path changes"), with v3's behaviour unchanged; v3 is not part of acceptance, so that is shown by one `system=v3` boot with the minted pair ("identity confirmed", `[zuse@Hera] ok>`). *If not:* a v4 copy of the check, beside v3's, until v3 leaves. **D2. Genesis on v4.** v3 mints Zuse onto a blank drive when the disk has no marker. That writes the marker to Artemis's disk, and the v4 boot does not write the disk until the owner says it may (`sk_v4_block_chain`'s comment; Phase 5). *Recommend:* the gate recognises a minted Zuse only. On v4 a blank pair stays headless, and says so once ("Zuse: no genesis on this disk -- the system stays headless"). Genesis on v4 comes with Artemis's writes (Phase 5). **D3. The prompt.** v3's is `[zuse@Hera] ok>`: the console's line prefix, from the VM name and the user. Banner and prompt are row 12, Phase 6. *Recommend:* in this gate, the console's VM name is set to Hera and its user prefix says `zuse` while her session holds, so the prompt is `[zuse@Hera] ok>` as v3's, from the moment there is an identity. The banner stays Phase 6. Nothing before the first prompt changes. *If not:* `ok>` as today, and the prefix with row 12. **D4. Which disks QEMU boots with.** The gate makes a bare `make ARCH= clean qemu`, with today's defaults (the blank `disk/artemis.img` and `disk/thumbdrives/zuse-thumb-ident.img`), stay headless, so no acceptance boot reaches `ok>`. *Recommend:* `kernel/Makefile`'s defaults become the minted pair, `disk/zuse-scratch/artemis.img` and `zuse-thumb-ident.img`. The acceptance rule to put the disk images back as committed before each ISA then applies to them. `.claude/CLAUDE.md` says so. *If not:* every acceptance boot passes `ARTDISK=` and `ZUSEDISK=` copies, and `.claude/CLAUDE.md` says that instead. **Not in this gate:** `WIREBIND` identities as a way in (Phase 6, with the user's VM born from the drive), `EJECT`, the banner, `ACL-ZUSE-BOOT` and god-mode (Phase 4, ACL on v4), Artemis's writes and genesis (Phase 5). ## Global Constraints As the step 4 plan's, and: - No kernel unit tests; the tests are QEMU sessions typed to over the serial socket and driven over QMP (the serial and QMP sockets `kernel/Makefile`'s `qemu` goal opens), each written before the change and seen to fail. - The drives attached by QMP during a session are copies of `disk/zuse-scratch/`, in a scratch directory; the committed pair is never booted directly. ## Tasks ### Task G0: Record - [ ] **Step 1:** This plan; in the step 4 plan, "The identity gate" points here and the Phases table puts the gate before Part A; `ENGINE.md` §2 one line saying the gate is built first. - [ ] **Step 2:** Commit `docs(v4): the identity gate before Part A`. ### Task G1: The check without a VM (D1) **Files:** `kernel/src/capsule/capsule_zuse_boot.c`, `kernel/include/starkernel/capsule_zuse_boot.h`. **Interfaces:** Produces `zuse_drive_t capsule_zuse_boot_check(struct blkio_dev *dev, homeblocks_sig_result_t sig_rc, const homeblocks_sig_t *sig, uint8_t seed[32], uint8_t pubkey[32]);` with `ZUSE_DRIVE_HERS`, `ZUSE_DRIVE_GENESIS` (no marker, blank drive), `ZUSE_DRIVE_NOT_HERS`; `int capsule_zuse_boot_root_pubkey(uint8_t pubkey[32]);` (0 = the marker read and checked). `try_attach` and `load_root_pubkey` call them; their behaviour and messages do not change. - [ ] **Step 1: Failing test:** a `system=v3` amd64 boot with copies of the minted pair, before the change: record "Zuse: identity confirmed from attached thumbdrive" and `[zuse@Hera] ok>` (the reference; this step is the yardstick, not a failure). - [ ] **Step 2:** Split as above. - [ ] **Step 3:** The same `system=v3` boot after: the same lines. A blank copy pair: "Zuse: genesis minted onto attached thumbdrive", as before. - [ ] **Step 4:** Commit with the two logs. ### Task G2: The gate on the v4 boot **Files:** `kernel/src/v4/sk_v4.c`, `kernel/include/starkernel/v4/sk_v4.h`, `kernel/src/kernel_main.c` (the v4 branch only: what `sk_v4_run` is given), a new `kernel/src/v4/sk_v4_identity.c` + `kernel/include/starkernel/v4/sk_v4_identity.h` (Zuse's state for Hera; the idle beat's USB servicing for the v4 boot). **Interfaces:** Consumes G1. `sk_v4_run(chain)` keeps its signature; after `chain()` it: loads the root public key; brings up every xHCI controller; starts the timer and enables interrupts as v3 does ("Starting heartbeat...", "Heartbeat running."); waits headless; then the prompt loop. - [ ] **Step 1: Failing tests** (amd64 sessions, before the change): - `gate_headless`: booted with no Zuse drive (`ZUSEDISK=`), the log has `POST: PASSED` and no `ok> ` within 60 s of it. Today: FAIL (`ok>` appears). - `gate_zuse`: booted with copies of the minted pair: "Zuse: identity confirmed from attached thumbdrive", then `[zuse@Hera] ok> ` (D3), and `3 4 + .` answers `7 ok`. Today: FAIL. - `gate_hotplug`: booted with no Zuse drive; QMP `blockdev-add` + `device_add usb-storage` of a copy of the minted Zuse drive → identity confirmed → prompt; a line typed; `device_del` → "Zuse: session ended -- reattach to re-authenticate", no further `ok> ` for 30 s; added again → prompt. Today: FAIL. - [ ] **Step 2:** Build the gate. - [ ] **Step 3:** The three sessions pass; the v4 suite passes (`make -C v4 test test-32 sanitize hosted-check`, unchanged: nothing in `v4/` changes). - [ ] **Step 4:** D4 as ruled (`kernel/Makefile` defaults and `.claude/CLAUDE.md`, or the command line). - [ ] **Step 5:** Full acceptance: three `clean qemu` boots with the minted pair, to `[zuse@Hera] ok>`, `PARITY:V4_POST ... fail=0`, `POST: PASSED`, `dict_hash` unchanged and equal (`0xfec8c47cfc6f437f`, word_count 317: nothing on the node changes); `gate_hotplug` on aarch64 and riscv64 too; `make -C v4 test-32`, 0 failures. Commit `feat(v4): no identity drive, headless; Zuse's drive, a console`, then the logs. ## Review Focus 1. **A drive pulled mid-line**: the line in hand finishes; the next prompt is not shown. 2. **A drive that is not Zuse's** (another identity, a blank one, a foreign one): no prompt, no message beyond v3's. 3. **Zuse's seed** is read into kernel memory only, never into a node's memory, and the cert is installed once (one-way, as `vm_zuse_cert_install`). 4. **The idle beat while the node runs a line**: USB servicing happens only at the prompt or in the headless wait, never while the node is mid-line (v3's `g_mama_interpreting` reason). 5. **All three ISAs**: hot attach and detach on aarch64 and riscv64, not only amd64.