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:
co-authored by
Claude Sonnet 5
parent
e1e839258d
commit
21c143dd28
+60
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user