FABRIC-3.md: close RUNCAP (Phase D / §F.18)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZGkimpfyh63EZyRkNbkPD
This commit is contained in:
Robert Allan James
2026-08-28 14:30:21 -04:00
co-authored by Claude Sonnet 5
parent e1e839258d
commit 21c143dd28
+60
View File
@@ -1863,6 +1863,8 @@ scoping pass (§F.8, decision 2):** this region's first devblock holds a new
`user_identity_seed_t` record, and the FORTH source itself occupies the remaining devblocks —
narrows "the exact read path" question above, though the read-side code is still unwritten.
**BUILT + VERIFIED 2026-08-28 (§F.18).**
### F.7 — `CERTVERIFY` (Zuse-signed user-cert verification)
Traced against the actual crypto/cert code before assuming D.4's "no new crypto work needed"
@@ -2602,3 +2604,61 @@ instead of direct calls; `common/msg.4th`'s `HERMES-ACK`/`HERMES-NACK` wrappers
obsolete (every VM has its own local `MSG-ACK-LAST`/`MSG-NACK-LAST` — no `VM-EXEC`
indirection needed) but the file itself was left in place, unloaded, rather than deleted
unprompted; `capsules/MANIFEST.md`'s "immutable ABI" claim for block 4055 is now stale.
### F.18 — `RUNCAP` built + verified (the §F.6 prerequisite `MINT` was blocked on)
Implementing `RUNCAP` against §F.6's own trace ("hand that straight to the existing,
unmodified `capsule_birth_baby()`") surfaced two real gaps that trace missed, both closed
before any code shipped:
**Gap 1 — `capsule_birth_baby()`'s signature check is not actually parameterized the way
§F.6 assumed.** It calls `capsule_verify_signature(descs, names, capsule_get_signatures(),
arena, dir->desc_count, idx)` — `descs`/`arena`/`dir` are caller-supplied (fine for a
heap-built directory), but `capsule_get_signatures()` unconditionally returns the
**compile-time-baked global array**, indexed against the *build-time* `capsule_descriptors[]`,
not anything the caller controls. For a RUNCAP-built directory `idx` is always 0, so the
check would compare RUNCAP's own arena bytes against whatever real capsule happens to sit at
slot 0 of the baked array — guaranteed to fail, not a security check. Put to Captain Bob
directly (three options: explicit bypass flag / a signed placeholder slot / defer); decided:
**explicit `skip_pki_sig` flag**, 0 for every existing call site, 1 only for RUNCAP — "easy to
change our minds later," and confirmed real enforcement for user-originated content lives
downstream in the VM's own ACL (`VMIdentity`/`acl_caps`, §F.2), not in this signature check,
which was never meaningful for non-build-time content in the first place. `capsule_birth_baby()`
itself is otherwise unchanged; all 4 existing call sites (`mama_forth_words.c`) pass `0`.
**Gap 2 — `capsule_birth_baby()` never sets the registry entry's own `.name`.**
`vm_registry_alloc()` zero-initializes it, and nothing inside `capsule_birth_baby()` ever
fills it in — every existing caller (`mama_word_birth`, `CONNECT-HERMES`/`-ARTEMIS`) does this
itself afterward via `capsule_vm_registry_set_name()`. Found live, not by inspection: a
RUNCAP-born VM's own registry name stayed empty, which Phase C's idle-loop pump then read as
a zero-length string and refused every tick ("VM name too long or empty") — traced via a live
serial-socket session, not guessed. `capsule_runcap_birth()` now calls
`capsule_vm_registry_set_name()` itself, matching the existing pattern.
**A third, non-blocking discovery while building the live test fixture:** `capsule_exec_payload()`
(`capsule_loader.c`) requires a `"Block NNNN\n"` header on every chunk of IDENTITY content —
without one, `is_block_header()` never matches, the whole payload is treated as
"pre-block/unrecognised" and silently skipped line-by-line, never executed (birth still
reports success — there's simply nothing to run). Not a bug, but load-bearing context for
whoever authors `MINT`'s default personality content (§F.6/§F.8's still-deferred question):
that content needs the same header convention every hand-authored `.4th` capsule already uses,
not bare FORTH text.
**Verified end-to-end, live in QEMU, not just build-clean:** a standalone host-side generator
(mirroring the `CERTVERIFY` host-test precedent, §F.7) wrote a real `homeblocks_sig_t` +
synthetic identity-source content directly into a disposable thumbdrive image's raw devblocks
— no capsule build, no `mkcapsule`, nothing baked in at compile time. Hotplugged via QMP,
recognized as a home-blocks drive, then a diagnostic `RUNCAP-TEST` word (Mama-only,
temporary — not the real call site, that's still `WIREBIND`) called `capsule_runcap_birth()`
against it: a genuinely new VM (`RunCapTest2`) was born, and `VM-EXEC`ing a word defined only
in that thumbdrive's own source printed `424242` — proof the content was actually read,
compiled, and executed, not just accepted. Clean 3-architecture regression boot (no RUNCAP
drive attached) confirms no side effects on normal boot. Commit `e1e8392`.
**Still open:** the real call site is `WIREBIND` (§F.5), still unbuilt — `RUNCAP-TEST` is
diagnostic-only and should not survive into that flow. A RUNCAP-born VM has no
`common:messaging.4th` vocabulary unless its own minted personality content loads it (matches
§F.6/§F.8's already-deferred "default personality content" question, not a new gap — observed
live as the idle pump's expected `MSG-TICK` refusal for `RunCapTest`/`RunCapTest2`, harmless
since these are test-only VMs never present during a normal boot). `MINT` (§F.8) is now
genuinely unblocked.