Commit Graph
60 Commits
Author SHA1 Message Date
Robert Allan JamesandClaude Sonnet 5 3f74ff0f78 FABRIC-3.md: close BINDSTEP + fence-persistence, identity arc done (§F.24)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZGkimpfyh63EZyRkNbkPD
2026-08-28 18:29:26 -04:00
Robert Allan JamesandClaude Sonnet 5 9ee029e7d4 FABRIC-3.md: close WIREBIND, the real attach call site (§F.23)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZGkimpfyh63EZyRkNbkPD
2026-08-28 16:57:45 -04:00
Robert Allan JamesandClaude Sonnet 5 c9cf9b09d9 FABRIC-3.md: close console-VM + user-VM async relay (§F.22)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZGkimpfyh63EZyRkNbkPD
2026-08-28 16:39:43 -04:00
Robert Allan JamesandClaude Sonnet 5 71b6937deb FABRIC-3.md: close emergency-CLI retirement + thumbdrive Zuse (§F.21)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZGkimpfyh63EZyRkNbkPD
2026-08-28 16:11:23 -04:00
Robert Allan JamesandClaude Sonnet 5 33493e23c1 FABRIC-3.md: capture general-purpose console vision + close MINT profile fields (§F.20)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZGkimpfyh63EZyRkNbkPD
2026-08-28 15:33:33 -04:00
Robert Allan JamesandClaude Sonnet 5 ecbc8813d6 FABRIC-3.md: close MINT (Phase E / §F.19)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZGkimpfyh63EZyRkNbkPD
2026-08-28 14:45:53 -04:00
Robert Allan JamesandClaude Sonnet 5 21c143dd28 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
2026-08-28 14:30:21 -04:00
Robert Allan JamesandClaude Sonnet 5 75311967a7 FABRIC-3.md: close Phase C (messaging capsule + idle pump)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZGkimpfyh63EZyRkNbkPD
2026-08-28 13:02:58 -04:00
Robert Allan James 9f6cc24ebb FABRIC-3.md: close D.7's persistence prerequisite
Hermes and Artemis are now session-less fleet foundation, verified live on all three architectures (commit 52eb1bb) -- the real, load-bearing prerequisite D.7 itself identified is done. The rest of D.7 (message-only birth flow, WIREBIND/MSGMIGRATE reconciliation) remains open, not touched here.
2026-08-28 08:45:12 -04:00
Robert Allan James ad79caeeeb FABRIC-3.md: capture birth-by-message-only vision (D.7), universal to Zuse+user VMs
Direct instruction while planning the next goal (mint zuse.img thumbdrive -> (Zuse)ok>): Hera must give birth only by message request, no coupling outside messages, applying universally to user VMs too, not just Zuse -- a sharper commitment to the standing "nothing is done until it's messaging" criterion (D.1) for this specific next flow, since messaging and storage are both genuinely live now.

Traced before capturing anything further: detection ownership moving to a running Artemis VM instance is confirmed a real architecture change from what HOTPLUG/WIREBIND already built/scoped (both currently have Hera deciding and acting directly, not just detecting). Found a real, load-bearing prerequisite this direction depends on: Artemis is not persistently alive today -- every boot log this session confirms she's birthed for her own migration self-test then explicitly killed before the REPL reaches ok>. Capture only, no design commitments yet -- WIREBIND/MSGMIGRATE both need their own reconciliation pass against this.
2026-08-28 08:20:12 -04:00
Robert Allan James c678211d4f FABRIC-3.md: close WRITE(10) as built+verified, record the EMPTY-BUFFERS bug find
WRITE(10) moves from "scoped" (§F.1) to "built and verified" (§F.17) -- the graph's original highest-leverage node and single remaining hard blocker is gone. Updates the §E graph (W10 to done, its outgoing edges from "blocks" to "unblocked"), the M2 punch-list checkbox, and the "what the graph makes visible" summary.

Also records a new standalone bug node (EMPTYBUFBUG, matching PROMPTBUG's precedent) for the EMPTY-BUFFERS mass-zero bug found and reported (not fixed) during WRITE(10) validation -- so it isn't lost track of now that the immediate incident (corrupted then restored disk/artemis.img) is resolved.
2026-08-28 07:21:02 -04:00
Robert Allan James ff67bbdec3 FABRIC-3.md: close SSDSCOPE, ROUNDTRIP, POLYBLOCK, PROMPTBUG -- last four §E nodes
SSDSCOPE and ROUNDTRIP close by cross-referencing decisions already made this session (D.3's "no central registry" statement, and the pool-ownership/EJECT-flush model from F.6/F.10) rather than new tracing -- both turn out to have zero remaining work of their own. POLYBLOCK needed the user's own clarification first (never elaborated beyond one sentence since 2026-08-25): reframes as an architectural principle (the block layer shouldn't know what backs it), confirmed already true of blk_get_buffer()'s live RAM/raw/disk-cache abstraction. PROMPTBUG traced for the literal string and found to be less than described -- no live code prints "zuse)ok>" today, only a doc comment describing not-yet-implemented behavior; correct intended form recorded, comment itself not touched per standing instruction against unrequested code changes.

Also corrects two stale graph classifications noticed while cleaning up: ACLKEY's own node had never been updated despite being fully scoped back in F.2, and the empty "open" classDef bucket is now removed since every §E node is closed or scoped except WRITE(10) itself.
2026-08-27 15:25:38 -04:00
Robert Allan James 87c1bee101 FABRIC-3.md: scope MSGMIGRATE, capture Console-driven interactive mint onboarding vision
Traced the actual Hermes mechanism before scoping: MSG-DELIVER already executes arbitrary FORTH source text on the destination VM via VM-EXEC, not a structured RPC -- migrating an interaction needs no new dispatch machinery, only a routing decision. Noted that every "VM" lives in one kernel address space, not a separate process, so messaging WIREBIND/BINDSTEP/CERTVERIFY is an architectural-discipline choice (uniform heat/audit participation in Compudynamics via Hermes), not a correctness requirement.

Decisions: real target is the Console VM (already real hardware: serial+framebuffer+PS2, not waiting on D.2b), a two-hop flow (Hera->Console reports attach outcome, Console->Hera requests the privileged operation), payload arguments encoded as literals directly in the FORTH text.

Captured a substantial new vision detail surfaced live while scoping this (D.6): blank-media minting is meant to be an interactive Console-driven onboarding form (Full Name/Address/City/State/Country/Metadata), not a bare programmatic MINT call -- connects forward into RUNCAP's deferred "default personality content" question and MINT's own scope. Capture only, not designed in detail, per this arc's own capture-first discipline.
2026-08-27 15:15:54 -04:00
Robert Allan James f84e679a88 FABRIC-3.md: scope STALL -- full BOT-spec recovery designed, closing Milestone 2
Traced the completion-code handling before designing anything: every transfer completion (control or bulk) shares one gate that logs and bails on any non-success code -- STALL isn't distinguished from any other failure, and no recovery exists (no xHCI Reset Endpoint, no CLEAR_FEATURE(ENDPOINT_HALT)). A bounded-timeout safety net in xhci_bot_wait_for_idle() prevents a hang, but the endpoint stays wedged for everything after it. Per direct instruction, designed full recovery now rather than deferring to Milestone 8: new STALL_ERROR completion code, new xHCI Reset Endpoint + Set TR Dequeue Pointer command TRB types (neither exists today), CLEAR_FEATURE(ENDPOINT_HALT) reusing the existing control-transfer plumbing, escalating to a full Bulk-Only Mass Storage Reset on a second stall, bounded via a new retry counter mirroring the existing bot_tur_retries/XHCI_BOT_TUR_MAX_RETRIES precedent exactly. This closes the last open Milestone 2 item.
2026-08-27 14:56:11 -04:00
Robert Allan James 6a3eb5997f FABRIC-3.md: close BMAPREAD as already-built, fix a real devblock-0 header collision
Confirmed the F.12 handoff: cache_load_devblock() already unpacks/validates metadata on load, same "already built" story as BMAPWRITE. But tracing "validate on insertion" surfaced a real, load-bearing conflict unrelated to blk_meta_t: blk_subsys_attach_device() always runs the generic block-subsystem's own STFR/v2 header check at devblock 0, which would always read a home-blocks drive's 'LAHB' magic as "unrecognized" and leave it permanently write-refused (BLK_FMT_PROVISIONAL) -- or, if force-formatted via blk_subsys_confirm_format(), overwrite homeblocks_sig_t outright, since both want the same devblock 0. This was invisible to CERTVERIFY/WIREBIND/RUNCAP/MINT because none of them traced the generic attach path alongside homeblocks_sig_check(). Fixed: homeblocks_sig_t relocates to devblock 1 (a call-site change only, sig_start_fblock was already a plain parameter); MINT must also run the ordinary format-confirm path at devblock 0 so the drive is writable through the normal block-buffer path.
2026-08-27 14:49:52 -04:00
Robert Allan James 198e82a029 FABRIC-3.md: close BMAPWRITE as already-built, correct UNCLEAN's classDef inconsistency
Traced blk_set_meta()/cache_writeback()/blk_flush() before assuming a new write path was needed. BMAPWRITE is already done: BMAPFMT's decision to repurpose the existing blk_meta_t accessors instead of a new table means the flush path that already exists for ordinary block data already covers metadata identically -- real, unstubbed, all the way to dev->write(). The only blocker is WRITE(10) itself, already modeled in the graph. Handoff note for BMAPREAD's own pass: the read side looks like it closes the same way but wasn't confirmed here.

Also corrects a self-inconsistency from the previous commit: UNCLEAN was marked with a "done" checkmark even though its wiring code isn't written yet, unlike BMAPWRITE which really is working code today. Moved UNCLEAN back to the "scoped, not built" bucket alongside BMAPFMT/CERTVERIFY/etc.
2026-08-27 14:44:53 -04:00
Robert Allan James 9c0e583554 FABRIC-3.md: scope FIRSTTOUCH, correct stale g.total_user_lbn wording
Traced g.total_user_lbn and blk_meta_t's chain fields before scoping: the M3 punch-list wording ("claim at g.total_user_lbn") predates BMAPFMT's distributed-ownership decision and doesn't describe a workable mechanism -- total_user_lbn only grows when a whole new device attaches, not when claiming space within one already attached. Real job is scanning Artemis's already-attached device's own blk_meta_t records for unowned devblocks. Also found blk_meta_t already has real, unused prev_block/next_block/chain_length linkage fields, untouched by BMAPFMT's redesign. Decisions: claims are a scattered chain via those fields (fragmentation-immune, free), discovered via full linear scan every time (no cached index, matches BMAPFMT's own no-centralized-table philosophy), fail outright with no partial-claim fallback if the device can't satisfy a request.
2026-08-27 14:41:50 -04:00
Robert Allan James 7f60df3d5c FABRIC-3.md: scope DETACH and close UNCLEAN alongside it, flag a latent KILL bug
Traced capsule_vm_kill() fully -- it's real and complete, so DETACH needs only a caller plus flush/bookkeeping, not new teardown machinery. Found that D.3's "flush before eject" only makes sense as a deliberate pre-removal step, splitting this into a graceful path (new EJECT word) and the abrupt hot-unplug signal already wired -- per direct instruction, scoped both, closing the previously-separate UNCLEAN (M3) node as "same kill path, no flush attempt." Needs one small new piece of state (which VMUuid is attached via the home-blocks path) since BINDSTEP's live-reverify approach doesn't work once the device is already gone. Reports, without fixing, a separate pre-existing bug found while tracing this: capsule_vm_kill() never resets g_repl_active_vm, so plain KILL on a USE'd VM leaves a dangling pointer today.
2026-08-27 14:37:37 -04:00
Robert Allan James c4f9458ad6 FABRIC-3.md: scope BINDSTEP -- extends the live, unguarded USE word
Traced the actual retarget path before assuming new plumbing: USE (mama_forth_words.c:430-480) already looks up a VM by name and calls sk_repl_set_active_vm() directly, completely unguarded. BINDSTEP is concretely "add the ACLKEY comparison to this one call site." Found one real gap: usb_blk_dev/xdev are function-static inside sk_repl_idle(), invisible to USE -- needs a small new accessor mirroring sk_repl_get_active_vm()'s own precedent. Decisions: re-verify the attached drive live on every USE call rather than trust a cached pubkey; VMs with no VMIdentity installed yet (Hera/Hermes/Artemis today) stay freely targetable, no regression; installed=1 targets refuse on no-drive-attached or pubkey mismatch, matching USE's existing refusal style. Zuse's override UX stays deferred per direct instruction.
2026-08-27 14:30:30 -04:00
Robert Allan James a45ea881c9 FABRIC-3.md: scope MINT, drop GPT permanently, confirm single-USB-device is sufficient
Traced two hidden dependencies before scoping: (1) no GPT parser/writer exists anywhere in kernel code, and per direct instruction GPT is dropped entirely rather than deferred -- the raw homeblocks_sig_t-at-devblock-0 layout every other node (CERTVERIFY/WIREBIND/RUNCAP/HOTPLUG) already treated as interim becomes the permanent format. (2) xhci_dev_t's BOT/MSC state is singular, not per-slot, raising a concern about the vision's "mint a second thumb while Zuse is active" implying two simultaneous USB devices -- resolved: Zuse's identity is system-resident (loaded from Artemis's own block-fence at boot), never thumbdrive-based, so MINT only ever needs one attached target drive. Decisions: minted identities get a real keypair (virtio_rng + ed25519_keygen), stored via a new user_identity_seed_t record occupying RUNCAP's identity_src region's first devblock; drive_uuid is a separate random draw; cert construction reuses CERTVERIFY's exact format, signed with Zuse's own seed -- first confirmed need for DER encoding, not just decoding.
2026-08-27 14:22:37 -04:00
Robert Allan James 691c04289b FABRIC-3.md: scope CERTVERIFY, correct D.4's PKI-reuse assumption
Traced x509_ed25519.h and zuse_cert_devblock.h before scoping: a regular user's cert has a fully separate trust root from the capsule-PKI chain (signed by Zuse's own on-device key, not the offline root CA/snakeoil intermediate), so verification is a single ed25519_verify() call, no chain walk. Corrects D.4's earlier "no new crypto work needed" claim -- x509_extract_ed25519_pubkey() deliberately stops at SubjectPublicKeyInfo, so verifying (not just reading) a cert needs new DER-walking code to capture the TBSCertificate byte range and signature. Decisions: X.509/DER format, drive_uuid bound via the cert's serialNumber field (avoids needing extension parsing), revocation deferred, cert lives in homeblocks_sig_t's already-reserved cert_offset/cert_devblocks.
2026-08-27 14:13:00 -04:00
Robert Allan James 8b3e46fa55 FABRIC-3.md: scope WIREBIND (breadcrumb) and RUNCAP, add missing graph edges
WIREBIND traced against live capsule_birth_baby()/dispatch_init_forth() and found to have no real mechanism behind it yet -- depends on CERTVERIFY (identity-authentication) and a new RUNCAP mechanism for per-identity VM content, neither shown in the §E graph before now. Followed the thread into RUNCAP: capsule_birth_baby() is already generic, so RUNCAP needs only a heap-built single-entry capsule directory, not new birth machinery. Repurposes homeblocks_sig_t's now-dead blockmap_offset/blockmap_devblocks fields (per BMAPFMT, §F.4) to point at the identity's init source instead. Also captures a user-pool scope clarification: a thumbdrive is a user's pool by default, uncontested; FIRSTTOUCH's claim logic applies only to system-device extension.
2026-08-27 14:03:42 -04:00
Robert Allan JamesandClaude Sonnet 5 b47cf3811e FABRIC-3.md: scope BMAPFMT as repurposing the dormant blk_meta_t
Fourth node in the iterative Q&A pass, worked conversationally step by
step: state field justified against blk_bam_entry_t precedent and the
MIGSM/UNCLEAN nodes' own needs; ACL ownership tied to the same VMIdentity
pubkey representation decided for ACLKEY; ACL check ordering grounded in
vm.c's live fast-deny word-execution pattern.

Biggest finding: BLK_META_PER_BLOCK's existing 341x3-into-1KiB packing is
exactly the "3-block cluster + 1KiB metadata" shape raised in discussion --
it's blk_meta_t, with real wired accessors (blk_get_meta/blk_set_meta) but
confirmed zero callers anywhere in the codebase, and stale POSIX-flavored
ownership fields (owner_id/permissions/acl_block) that predate the
anti-POSIX principle and the pubkey-based identity model.

Decided: BMAPFMT is not a new structure, it's repurposing blk_meta_t
(distributed ownership/ACL/state per block, not a separate centralized
table) -- flagged that this makes homeblocks_sig_t's reserved
blockmap_offset/blockmap_devblocks fields unnecessary. New field layout
for the 40-byte security/ownership block: an 8-byte owner pubkey
fingerprint, a fast-deny acl_allow bit, and deliberate reserved slack
per "flexibility until we understand the recipe."

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U14ET9CWAtbQMbYqomKgXd
2026-08-27 12:03:53 -04:00
Robert Allan JamesandClaude Sonnet 5 7957b0497f FABRIC-3.md: close HOTPLUG, hand off detection point to WIREBIND
Third node in the iterative Q&A pass: re-checked sk_repl_idle() and the
bot_msc_attach_pending/detach_pending doc comments directly against the
original Milestone 2 punch-list wording. The flag-set-by-xHCI,
flag-consumed-by-sk_repl_idle() pattern isn't literally a registered
callback but achieves the same documented decoupling goal
("keeps xhci.c decoupled from block_subsystem.c"), confirmed live on all
three arches. Closed as written.

Recorded a handoff note for WIREBIND's own future scoping: reuse the
existing homeblocks_sig_check() result as the branch point (recognized
drive -> cert-verify+birth, blank/foreign -> stays plain block storage)
rather than inventing new hotplug detection. Updated the §E graph's
HOTPLUG node from partial to done.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U14ET9CWAtbQMbYqomKgXd
2026-08-27 11:27:38 -04:00
Robert Allan JamesandClaude Sonnet 5 0a65dd7ace FABRIC-3.md: scope ACLKEY (console/VM binding), capture v2.0.0 scope expansion
Second node in the iterative Q&A pass: traced acl_mode/acl_allow/acl_pinned
to DictEntry (per-word, not per-VM) before proposing anything, confirming
"reuse ACL" could only ever mean reuse the pattern, not the data. Decided:
a new VMIdentity type in its own header (mirroring the existing VMUuid
precedent, not another inline VM struct field), Zuse keeps an always-allowed
but explicit-acknowledgment override, and console/VM binding stays freely
retargetable (no one-way pin).

Also captured a scope expansion surfaced during this pass: identity is a
general per-VM primitive needed by Hera/Hermes/Artemis/Console too, not
just user thumbdrives, plus two new standing items (a full codebase
scavenging audit, and v2.0.0 as the eventual release target) in new §D.5.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U14ET9CWAtbQMbYqomKgXd
2026-08-27 11:19:48 -04:00
Robert Allan JamesandClaude Sonnet 5 4c7a39b5c3 FABRIC-3.md: scope WRITE(10), the graph's highest-leverage node
First pass of the iterative Q&A planning loop over §E's dependency graph:
traced the existing READ(10) implementation in xhci.c to establish that
WRITE(10) is a direct mirror (data direction, new SCSI opcode, new BOT
state) rather than new protocol work, then recorded the three scoping
decisions made (read_only flip timing, QEMU disposable-image validation
target, scope boundary excluding MINT/DETACH) in new §F.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U14ET9CWAtbQMbYqomKgXd
2026-08-27 10:14:15 -04:00
Robert Allan JamesandClaude Sonnet 5 ee2018179f Unified punch-list graph (§E) -- the pile as a graph, not a list
No code changes -- per direct request to represent the accumulated
Milestone 2/3/5 punch-list items plus D's Tripod-vision gaps as a graph
rather than flat lists, since several items turn out to be the exact
same open question asked in different places, and several converge on
the same blocker.

Mermaid dependency graph in FABRIC-3.md §E, cross-referencing:
- WRITE(10) (Milestone 2) as a true hub: independently gates the
  block-map write path, the ongoing MINT word, detach/flush-back, and
  all real-hardware testing -- landing it once unblocks four
  separate-looking fronts.
- Milestone 5's "key/lock data shape" and D.4's "ACL bumps and holes"
  gap are literally the same open question, not two separate ones.
- Runtime capsule construction (a D.4 detail) sits on the critical path
  to the MINT word, not a side note.
- Message-bus migration has three currently-unbuilt hardwired
  prerequisites, confirming it's correctly last in this whole area.
- Only 4 of the ~20 nodes are genuinely standalone; everything else
  connects to at least one other open item.

No ordered plan yet -- this is the graph itself, not a sequence.
Documented as the input to the next iterative planning pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U14ET9CWAtbQMbYqomKgXd
2026-08-27 10:00:08 -04:00
Robert Allan JamesandClaude Sonnet 5 1d0df69127 Link Tripod vision to Stadium foundation theory + capture the pentagon
No code changes -- continued design capture, per direct request to
link today's vision into the existing FABRIC.md/FABRIC-2.md material
("the existing pile of dirt") before planning.

Mined FABRIC.md's original Stadium theory (§17.1, §20, §24) and found
the EXPIRE-as-TTL correction wasn't just cleaner once "session=VM"
landed -- it was required from the start: the foundational
patron/departure table already says VMs depart via heat decay (COOL),
never TTL (TTL only ever governed messages/ACLs). §20's outer/inner
Stadium nesting already anticipated "attach = admit a VM" as a case,
so no new Stadium theory is needed, only a new admission trigger.
§24's identity-stability rules don't block session-state round-
tripping across separate attaches either way.

Mined FABRIC-2.md and found real grounding for two more decisions: the
acl_pinned one-way-ratchet was already identified as the right shape
for both Zuse's "burn" and console-session ownership, just never built
past word-execution gating -- and the real Hermes message shape
(MSG-CELLS, 9 fields, out-of-line payload, MSG-ALLOC/CH-ALLOC/
MSG-DELIVER) gives message-bus migration a concrete target instead of
an abstract goal. Confirmed empirically that today's xHCI hotplug
attach chain is 100% hardwired, zero messaging anywhere in it -- the
real baseline to migrate from.

Captured the pentagon topology: "just to get a user, 5 VMs are needed"
-- Hera, Hermes, Artemis, the user's own VM, and the Console, fully
interconnected (K5, a pentagon with every diagonal drawn). Flagged the
Console as a full peer node, not the passive relay D.3's flow
description implied -- reconciling that phrasing against the five-node
picture is new open work.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U14ET9CWAtbQMbYqomKgXd
2026-08-27 09:52:20 -04:00
Robert Allan JamesandClaude Sonnet 5 89d557c678 Capture full Tripod/Zuse identity vision (§D), supersede EXPIRE-as-TTL plan
No code changes -- pure design capture, per direct request ("capture
EVERYTHING first then we'll build a plan").

Core correction: a session IS a VM (Zuse is a player in the Stadium
fabric like any other, not a special boolean flag on Hera). This
supersedes an in-progress plan this session to implement EXPIRE as a
Stadium-TTL sweep on the zuse_session boolean -- caught mid-research,
before any code was written. Session end = VM detach, much closer to
the existing COOL/capsule_vm_kill() path than a new TTL mechanism.

Captured the full attach/mint flow: idle-loop thumbdrive watch,
cert-only auth (no password/username, no central user directory),
runtime capsule construction from drive content, ACL-based console/VM
binding (resolves Milestone 5's "reuse ACL-PIN vs. new primitive"
question in favor of reuse), ongoing MINT, and deferred detach/flush-
back. Standing completion criterion: nothing here is done until
hardwired calls are replaced by real Hermes messages.

Sorted the resulting gaps into answered (chain-of-trust mechanism,
ACL-reuse decision, no-central-directory) vs. genuinely deferred
(runtime capsule construction, exact ACL comparison semantics,
message-bus migration scope, polymorphic block-boundary behavior,
SSD-store scope, session state round-tripping, and the underlying
WRITE(10) hard blocker). Also flagged a small unrelated bug: the
prompt should read (Zuse)ok>, not zuse)ok>.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U14ET9CWAtbQMbYqomKgXd
2026-08-27 09:38:30 -04:00
Robert Allan JamesandClaude Sonnet 5 030a3e6dc0 Milestone 6: hard-refuse flip, scoped to INVALID only -- closes Milestone 6
Before flipping, found CAPSULE_SIG_MISSING (no signature at all) is the
normal state everywhere except this machine -- CI and any other
checkout have no access to the offline key, by design. Refusing on
MISSING the same as INVALID would brick boot everywhere but here.
Decided (on request): enforce ONLY on CAPSULE_SIG_INVALID (a signature
that IS present but doesn't verify -- unambiguous tampering/corruption
evidence). MISSING/NO_ROOT_KEY stay WARN-only permanently.

All three capsule_birth.c call sites now return CAPSULE_RUN_ERR_INVALID
on CAPSULE_SIG_INVALID, after logging the same WARN as before.

Verified on all three architectures, both directions, per the original
rollout commitment: positive case (real signed capsules) reboots clean
with zero warnings on amd64/aarch64/riscv64. Negative case (same
one-byte signature corruption used for the WARN-only proof, on Mama's
own init.4th) now genuinely refuses identically on all three:
"capsule sig: init.4th: INVALID" then "Init: Mama birth FAILED". The
feared "no ok> at all" blast radius didn't materialize -- kernel_main.c
already had graceful error handling for a failed Mama birth (log and
continue, pre-existing code); the kernel reaches a degraded ok> rather
than crashing, on all three architectures. Final acceptance pass (real
signed capsules, tampering reverted) clean on all three.

Milestone 6 is now fully closed except magic-number content-type
detection (shared with Milestone 4, separate scope, not started).
Documented in FABRIC-3.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U14ET9CWAtbQMbYqomKgXd
2026-08-26 22:08:20 -04:00
Robert Allan JamesandClaude Sonnet 5 c640f99211 Milestone 6: BLOCK_MAP.md signature-status column
--manifest mode's file scan is a completely separate code path from
build mode (only ever walks .4th files, never the embedded PKI cert or
font capsule) -- extended it to accept the same optional --sign-key
<path> prefix build mode already has, factoring the key-loading code
into a shared load_sign_key(), so the manifest can report real
per-capsule signing status without touching or requiring a rebuild of
capsule_generated.c.

New "Signed" column on the capsule summary table: yes/no when
--sign-key was given, n/a (with an explanatory footnote) when it
wasn't -- never a bare blank that could be misread as "unsigned".
Makefile.starkernel's manifest-generation call site now passes the same
SIGN_KEY_ARGS the real build uses, so capsules/BLOCK_MAP.md reflects
this machine's actual signed state by default.

Verified: clean compile, BLOCK_MAP.md correctly shows "yes" for all 31
tracked capsules on a real signed build; a quick amd64 boot (no kernel
code touched, host tooling only) confirmed no regression.

This closes every open Milestone 6 item except magic-number
content-type detection (shared with Milestone 4, not started) and the
hard-refuse flip (deliberately deferred). Documented in FABRIC-3.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U14ET9CWAtbQMbYqomKgXd
2026-08-26 21:43:50 -04:00
Robert Allan JamesandClaude Sonnet 5 2fc55f47e1 Milestone 6: mkcapsule signing + capsule_birth.c wiring, WARN-only
First attempt shelled out to `openssl pkeyutl -sign` (fork/execlp, not
system() -- avoided shell string interpolation of the key path).
Corrected on request: no new external host binary dependency when the
repo's own code can do the job -- same standing preference as the
earlier anti-file correction. Rewritten to link ed25519_sign() (already
verified against OpenSSL in Phase B) directly into mkcapsule.

New tools/pkcs8_ed25519.c: a narrow DER walker (same shape as
x509_ed25519.c, deliberately not shared -- small enough that
duplicating a few TLV-walking lines beat threading a header between the
kernel crypto tree and host tooling) extracting the raw seed from the
intermediate's PKCS#8 private key, plus a minimal self-written base64
decoder (PEM is openssl genpkey's default output; no decoder existed
anywhere in the repo). Verified end-to-end before wiring anything in:
the extracted seed's derived pubkey matches the cert's exactly, and a
full self-contained sign+verify round-trip (zero openssl) passes.

CapsuleDesc had no spare bytes, so signatures live in a new parallel
CapsuleSigEntry array, emitted by a new `mkcapsule --sign-key <path>`
flag (omitted/missing key -> has_sig=0 everywhere, graceful, not a
build failure -- CI has no access to the offline key).

New capsule_sig.c/.h: capsule_verify_signature(), a separate function,
not folded into the already-tested capsule_validate(). Finds and caches
the embedded intermediate cert's pubkey once per boot, then verifies
against it. Wired into all three capsule_validate() call sites in
capsule_birth.c via log_message(LOG_WARN, ...) -- never refuses yet,
per the earlier staged-rollout decision.

Verified independently, both directions, live in the real kernel: a
full clean build (38 signed capsules) boots clean on all three
architectures with zero warnings. Separately, hand-corrupted one byte
of Mama's own init.4th capsule's stored signature (not its payload/hash,
which capsule_validate() already catches and would have masked the
test) and rebuilt just the changed object: produced exactly "capsule
sig: init.4th: INVALID -- signature does not verify" on boot, and the
kernel still reached ok> -- proving warn-only doesn't refuse anything
yet. Reverted before the final, untampered 3-arch acceptance pass.

Still open: flipping WARN to hard-refuse (separate, deliberate step)
and the BLOCK_MAP.md signature-status column. Documented in FABRIC-3.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U14ET9CWAtbQMbYqomKgXd
2026-08-26 21:32:29 -04:00
Robert Allan JamesandClaude Sonnet 5 431bcb1f34 Milestone 6: root CA generated, snakeoil intermediate embedded, DER parser
Root CA + snakeoil intermediate generated entirely offline
(/home/rajames/CLionProjects/lithosananke-ca/, outside this repo,
private keys chmod 600) per this milestone's own requirement: Ed25519,
root self-signed 20-year validity, intermediate real-CA-signed
(CA:TRUE, pathlen:0), chain verified via openssl.

Snakeoil intermediate embedded as a capsule (capsules/pki/
snakeoil-intermediate.der) -- confirmed the font-capsule precedent
needed zero new infrastructure, any non-.4th file under capsules/
embeds verbatim already.

New x509_ed25519.c: a from-scratch, narrow DER walker (not general
ASN.1/X.509, per this milestone's design decision) extracting the raw
Ed25519 pubkey from a cert's SubjectPublicKeyInfo -- handles the
optional v3 version field, verifies the AlgorithmIdentifier OID is
Ed25519 rather than assuming, handles both DER length forms. Verified
against ground truth: the extracted key from the real embedded cert
matches openssl's own reported pubkey byte-for-byte; refusal path
checked against truncated/garbage/empty/wrong-algorithm (real RSA cert)
input. Compiles clean on all three architectures.

Still open: mkcapsule signing step, wiring ed25519_verify() into
capsule_birth.c's three validate call sites (landing warn-only first,
per decision -- a bug here could stop every capsule from birthing,
including Mama's own, on all three arches), and the BLOCK_MAP.md
signature-status column. Documented in FABRIC-3.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U14ET9CWAtbQMbYqomKgXd
2026-08-26 20:55:05 -04:00
Robert Allan JamesandClaude Sonnet 5 a8692681a8 Phase 8 C (5/n): Zuse's cert wired to the fence -- first-boot mint works
Replaces the crashed NVRAM approach entirely. New
include/starkernel/zuse_cert_devblock.h: a standalone on-disk record
(magic + version + 32-byte seed + 32-byte pubkey + a real CRC-64/ISO
from day one, same discipline homeblocks_sig_t established) occupying
devblock_from_top=0 of the fence. Its own header, not inlined at the
boot call site, since the still-open MINT word will be a second
consumer of this exact format.

kernel_main.c's mint-or-load logic now reads the fence, installs an
existing valid cert, or mints fresh via virtio_rng+ed25519_keygen and
writes it. Runs right after virtio_rng_init(), before
capsule_birth_mama() -- unlike the crashed NVRAM attempt, raw block I/O
against Artemis's already-proven device has no boot-timing risk, so the
earlier "re-invoke ACL-ZUSE-BOOT after Mama birth" workaround is gone;
ACL.4th's self-activating ACL-ZUSE-BOOT sees a correct cert on its one
ordinary pass.

Verified independently across every real scenario, never trusting the
kernel's own report: fresh mint decodes correctly on disk with a CRC
confirmed by a from-scratch Python re-implementation of the algorithm;
a reboot without reformatting loads back byte-for-byte identical
seed/pubkey (genuinely "mint once, ever"); a pre-fence volume refuses
cleanly (no crash, no silent data loss, honest "not persistent"
reporting); the real, untouched disk/artemis.img exercises the same
graceful-refusal path identically on all three architectures.

Phase 8's core arc is now functionally complete: real entropy -> real
signing -> real anti-file block-native persistence -> a first-boot mint
that survives reboots. Still open: the ongoing MINT word for minting
additional regular users. Documented in FABRIC-3.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U14ET9CWAtbQMbYqomKgXd
2026-08-26 20:40:05 -04:00
Robert Allan JamesandClaude Sonnet 5 6e9c1d3bc2 Phase 8 C (4/n): metadata fence allocator integration + zone I/O
Corrected meta_fence_blocks units from "Forth 1 KiB blocks" to 4 KiB
devblocks (matching bam_devblocks/reloc_devblocks) before anything
depended on the original meaning -- a clean fix, not a migration. This
let the fence fold directly into compute_totals_from_B()'s existing
payload4k formula (total_devblocks - 1 - B - R - F) instead of a
separate user_blocks subtraction: total_blocks/user_blocks/free_blocks
all shrink correctly for free, in both the fresh-format and reload
paths, from one formula change.

New blk_meta_zone_read()/blk_meta_zone_write() -- raw, unpacked 4 KiB
devblock I/O, same shape as the header/BAM/reloc-table regions,
addressed by devblock_from_top counting down from the device's last
physical devblock. Refuses rather than clamps if the index exceeds the
on-disk meta_fence_blocks. C-only, no FORTH word wraps either -- same
discipline as vm_zuse_cert_install(), which will be this zone's first
real tenant.

Verified independently at every step, never trusting the kernel's own
report: capacity math cross-checked against a from-scratch Python
recomputation of the same formula (exact match); accessor correctness
via a temporary probe (written/run/captured/reverted) that wrote a
known pattern and read it back, then independently confirmed via a raw
read of the disk image at the exact expected physical byte offset.
Full 3-arch acceptance boot against the real, untouched disk/artemis.img,
probe code fully reverted -- clean, conservation intact.

Still open: wiring vm_zuse_cert_install() to actually persist through
these accessors, and the MINT word itself. Documented in FABRIC-3.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U14ET9CWAtbQMbYqomKgXd
2026-08-26 19:40:43 -04:00
Robert Allan JamesandClaude Sonnet 5 2035ebeac0 Phase 8 C (3/n): top-of-device metadata fence, step 1 (field round-trip)
Corrected substrate: this OS is anti-POSIX, anti-file by design -- the
prior "dedicated system-identity disk" framing was wrong vocabulary,
caught before any code was written (saved as
feedback_no_files_anti_posix.md). The real primitives are
content-addressed capsules and raw LBN blocks, never a filesystem.

Design (agreed on request): a growable metadata fence at the TOP of a
device's block space, mirroring block_subsystem.c's existing bottom BAM
reservation from the opposite end -- the two grow toward each other,
never colliding, same shape as a stack/heap. Starts at
BLK_META_FENCE_INIT (128 blocks), explicitly never RAM-backed. Reuses
Artemis's already-attached, already-proven virtio-blk device -- no new
device. Rejected reusing BAM's own reserved zone directly: those blocks
are fully claimed by BAM bookkeeping, not free space.

Step 1 only: new meta_fence_blocks field in blk_volume_meta_t, appended
after reloc_devblocks and carved from _pad[] -- identical graceful-
default technique reloc_devblocks already established (a pre-existing
volume reads it back as 0, not a format break). Added a compile-time
_Static_assert on the struct's total size, same discipline
homeblocks_sig.h uses -- caught a real bug immediately: the hand-summed
_pad[] formula was off by 4 bytes (a compiler alignment gap the manual
count missed), found via offsetof() rather than re-deriving by hand.

Worked against disposable clones throughout, never the real
disk/artemis.img (ARTDISK is ?=-overridable) -- artemis-metafence-fresh.img
(blank, fresh-format path) and artemis-metafence-test.img (copy of the
pre-existing artemis.img, graceful-default-on-reload path), kept as
regression fixtures matching disk/README.md's existing convention.
Verified independently via direct byte reads of the disk image, not the
kernel's own log output (log_message(LOG_INFO,...) doesn't reach serial
in this build -- unrelated pre-existing gap): fresh format writes 128 at
header offset 184, a reboot without reformatting preserves it, the old
pre-fence image reads back 0. Full 3-arch acceptance boot against the
real, untouched disk/artemis.img also clean.

Allocator (user_blocks math) and zone read/write accessors both still
open -- next steps, documented in FABRIC-3.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U14ET9CWAtbQMbYqomKgXd
2026-08-26 19:18:21 -04:00
Robert Allan JamesandClaude Sonnet 5 e5cbc71f46 Phase 8 C (2/n): expand cert storage; NVRAM persistence crashed, reverted
Cert storage expanded from the old 16-byte placeholder to a real
32-byte seed + 32-byte pubkey. vm_zuse_cert_install() now has a
kernel-side duplicate in src/starkernel/vm/vm_core.c -- the kernel
build's VM_EXCLUDE list drops src/vm.c entirely (same reason
vm_set_base() already has two independent copies), so the hosted-only
version added earlier this session was never actually linked into the
kernel. FORTH-side ZUSE-CERT-LO@/HI@ replaced with ZUSE-PUBKEY@ (i -- u)
over the public half only; ACL-ZUSE-BOOT now checks
ZUSE-CERT-INSTALLED? before authenticating instead of unconditionally.

Attempted NVRAM-based persistence (GetVariable/SetVariable) for the
first-boot mint flow: page-faulted inside OVMF's variable service
(CR2 in the flash MMIO window). Moving the call site to match the one
proven-safe existing SetVariable call site in this codebase produced
the identical crash -- not a timing issue. Localized with debug
markers (one boot): GetVariable works; SetVariable with real data
never returns. The existing "working" precedent call is actually a
delete-of-nonexistent-variable (size=0, data=NULL), a cheaper path
that never touches flash, so it proved nothing about real writes.
Root cause: this kernel's VMM never maps the region OVMF's variable
service needs for real flash writes -- a genuine gap in UEFI runtime-
services support, not Zuse-specific, and not obviously fixable in a
3-arch-uniform way (flash window location is firmware/arch-specific).

Independently, storing the raw seed in RUNTIME_ACCESS NVRAM would have
been a real security defect regardless of the crash -- readable by any
later-loaded UEFI app or the booted OS.

Reverted to a known-safe state: all NVRAM/mint code removed from
kernel_main.c, init.4th's ACL.4th line back to its documented
commented-out default. Verified clean compile and clean boot on all
three architectures. Cert storage expansion (the part that works)
stays. A dedicated system-identity disk (virtio-blk, already proven
for writes via Artemis) is the recommended next substrate -- not yet
decided or built. Full investigation documented in FABRIC-3.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U14ET9CWAtbQMbYqomKgXd
2026-08-26 15:55:27 -04:00
Robert Allan JamesandClaude Sonnet 5 f223a31cec Phase 8 C (1/n): QEMU harness now preserves NVRAM across runs
Scoping Phase C (the MINT word) surfaced a real blocker: "mint one
Zuse, ever" needs the cert to survive reboots, but the qemu target
copied a fresh, pristine OVMF_VARS.fd on every invocation -- a
UEFI-NVRAM-based cert would never persist under this project's own
normal test workflow. Digging further, aarch64 had no persistent NVRAM
store at all (single -bios arg, no split VARS pflash like amd64/riscv64).

Fixed rather than switching storage substrates: amd64/riscv64 now only
copy the VARS template if the destination doesn't already exist, so
`clean` (which deletes the whole build tree) is the bleach step and a
bare `make qemu` preserves NVRAM -- matching the existing "always clean
before qemu" acceptance convention exactly. aarch64 restructured to
split CODE(ro)/VARS(rw) pflash drives matching the other two, with a
graceful fallback to the old -bios mode on hosts without split firmware.

Also resolves two design questions before any cert code: Zuse doesn't
need Milestone 6's CA (that's the capsule-signing chain, a separate
trust domain -- Zuse is a self-sovereign instance-local root of trust),
and flags that this session's own earlier vm_zuse_cert_install() storage
(16 bytes) is too small for a real Ed25519 keypair.

Verified: all three architectures boot clean to ok> with the new pflash
arrangement, Stadium conservation intact, no panics or guest errors.
Infrastructure-only -- no cert code yet. Documented in FABRIC-3.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U14ET9CWAtbQMbYqomKgXd
2026-08-26 15:18:15 -04:00
Robert Allan JamesandClaude Sonnet 5 53e6c5709f Phase 8 B: real Ed25519 keygen/signing, verified against OpenSSL
Extends the previously verify-only ed25519.c with ed25519_keygen() and
ed25519_sign() per RFC 8032 5.1.5/5.1.6, reusing every point-arithmetic
primitive verify already had -- only seed expansion/clamping and
per-message nonce derivation are new. Signing is deterministic; only
keygen ever touches entropy, via a caller-supplied seed (virtio_rng,
Phase A) -- keygen still generates nothing itself.

New scalar_muladd() (scalar25519.c) for signing's S = (k*a + r) mod L,
the one scalar op verify never needed. Schoolbook multiply into a u128
wide accumulator with one final carry pass -- deliberately the same
shape as fe25519.c's existing multiply, which has a documented history
of a real bug from carrying mid-accumulation instead of in one pass.

Verified against an independent implementation, not self-consistency:
a throwaway host harness against Python's cryptography library (OpenSSL-
backed) across 6 trials (5 random seed/message pairs + the empty-message
case) produced byte-for-byte identical pubkeys and signatures every
time. Clean compile on all three architectures and a full 3-arch QEMU
acceptance boot, conservation intact, no panics or guest errors.

Nothing calls the new functions from the live kernel path yet -- that's
Phase C (the MINT word itself), still open, documented in FABRIC-3.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U14ET9CWAtbQMbYqomKgXd
2026-08-26 14:46:27 -04:00
Robert Allan JamesandClaude Sonnet 5 309e792f07 Phase 8 A: virtio-rng entropy source for real Ed25519 signing
The kernel's ed25519_verify() is deliberately verify-only -- no signing,
no keygen, no entropy source. That conflicts with the on-device MINT
word vision (Zuse signing new user certs live at runtime), so this
reopens that constraint on request rather than reshaping MINT around
verify-only.

vm_uuid.h already found the real gap: amd64 has RDRAND, riscv64 has Zkr,
but QEMU's aarch64 CPU models have neither -- confirmed against QEMU
10.2.1. A deterministic PRNG (fine for VM UUIDs) is not safe for key
generation, so this adds a virtio-rng device instead of a per-arch split:
real host entropy, identical guest-side protocol on all three arches.

New src/starkernel/virtio/virtio_rng.c + include/starkernel/virtio_rng.h,
transport plumbing mirroring the existing virtio_blk.c driver exactly.
Wired into kernel_main.c boot, -device virtio-rng-pci added to all three
QEMU targets.

Verified live (temp probe, written/run/captured/reverted): 16 real bytes
pulled through the full request/notify/poll round trip on all three
arches, three different values confirming real entropy. Final boot
against the reverted, permanent code: clean compile, clean boot to ok>
on amd64/aarch64/riscv64, Stadium conservation intact, no panics or
guest errors.

Ed25519 keygen/signing itself (Phase B) and the MINT word design
(Phase C) remain open, documented in FABRIC-3.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U14ET9CWAtbQMbYqomKgXd
2026-08-26 14:32:20 -04:00
Robert Allan JamesandClaude Sonnet 5 6f5605d479 Phase 8: zuse cert storage moved out of the dictionary (fuse-blow install)
Found that a pinned CONSTANT is not actually tamper-proof: ACL-PIN only
blocks redefinition, not a >BODY-then-store on the word's existing data
field. Moves the Zuse cert value into C-only VM struct fields
(zuse_cert_lo/hi + zuse_cert_installed fuse bit) with a one-time
vm_zuse_cert_install() and read-only ZUSE-CERT-LO@/HI@/INSTALLED? FORTH
accessors, closing the tamper path structurally instead of by convention.
Deletes the now-insecure ZUSE-CERT-LO/HI CONSTANT words from zuse.4th.

vm_zuse_cert_install() has no caller yet -- the real mint flow (Milestone
6 CA, the MINT word) is still open; this is storage + accessors only, not
a stand-in mint. Documented in FABRIC-3.md. Verified: hosted build clean,
mkcapsule --lint clean (31/31), clean boot to ok> on amd64/aarch64/riscv64
with Stadium conservation intact and no panics.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U14ET9CWAtbQMbYqomKgXd
2026-08-26 13:58:22 -04:00
Robert Allan JamesandClaude Sonnet 5 8b2fb448c7 Clarify: home-blocks thumbdrives are not bound to any particular size
Captain Bob's correction. 64MB (disk/zuse.img, usb-thumbdrive-test.img)
was always just an arbitrary QEMU-test convenience size, never a
real-world constraint -- but the docs and script didn't say so
explicitly, and an earlier memory's "16GB reference size" phrasing
(already hedged as tentative) risked reading as a decided target.

Audited the actual format for hardcoded size assumptions: none found.
homeblocks_sig_t already carries its own metadata_devblocks field,
recording whatever size a real drive's partition actually is.

Changes: scripts/bleach_zuse_img.sh gains a --size-mb override (tested
both the override and the unchanged default); disk/README.md's
zuse.img entry and FABRIC-3.md both now state the point explicitly;
the memory file and its MEMORY.md index line corrected to match (the
GPT layout's design point is the *proportions* -- small metadata
partition, everything else block storage -- not any absolute size).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CXjAPTEKrgY2Mrk25KoLDn
2026-08-26 07:56:07 -04:00
Robert Allan JamesandClaude Sonnet 5 35f84d4a45 Add disk/zuse.img + bleach_zuse_img.sh: first-boot mint testing (Phase 8)
Resolves the acl_pinned punch-list item's open question: credential
data (ZUSE-CERT-LO/HI, ACL-CA-KEY-LO/HI) are CONSTANT words, i.e. real
DictEntrys, and acl_pinned's enforcement (vm_create_word()'s
unconditional shadow-refusal for any pinned name) already covers this
generally -- no new flag needed, zuse.4th's ACL-ZUSE-BOOT already pins
both cert constants today.

That investigation surfaced a real gap: ACL-ZUSE-BOOT pins the cert
constants unconditionally on every boot, before any legitimate mint
could ever run, permanently locking in the 0 placeholder on the very
first boot. This directly shaped Captain Bob's next design pass: a
dedicated zuse.img test thumbdrive, "bleachable" back to pristine
state for repeated first-boot testing; a one-time mint-then-pin flow
(fixing the gap above); a separate ongoing S" name" MINT word for
minting additional regular users; and an explicitly-deferred Zuse
recovery path question.

This commit is the first piece: disk/zuse.img (64MB blank, matching
the existing USB-fixture convention) + scripts/bleach_zuse_img.sh
(idempotent reset). Verified live via QMP hotplug -- reads back as
HOMEBLOCKS_SIG_BLANK, correctly simulating a genuine first boot.
Deliberately flat/raw, not GPT-partitioned, matching
homeblocks_sig_check()'s current sig_start_fblock=0 assumption; both
move to a real GPT-relative offset together once a parser exists. No
kernel code touched -- host-side test tooling only, no 3-arch
acceptance boot needed.

Still open: the mint-then-pin boot fix, the MINT word, Zuse recovery.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CXjAPTEKrgY2Mrk25KoLDn
2026-08-26 07:51:44 -04:00
Robert Allan JamesandClaude Sonnet 5 28c1b12c7f Wire homeblocks_sig_check() into USB attach: the warn half (Phase 8)
Wired into sk_repl_idle()'s USB hotplug attach handler, right between
blkio_usb_open_msc() succeeding and blk_subsys_attach_device() -- logs
a distinct message per outcome (recognized / blank-or-foreign /
bad-version / bad-crc / read-error).

The "refuse" half is deliberately not implemented -- there is nothing
real to gate yet. blkio_usb.c has no SCSI WRITE(10) support at all, so
there is no write path today to refuse; attach currently only enables
read-only access, which is also the general-purpose USB block I/O
path this repo already relies on for unrelated testing, not
exclusively a home-blocks identity workflow. Refusing attach on blank
media would break that legitimate use without protecting anything
real -- same "don't build ahead of a real caller" reasoning EXPIRE's
deferral used. Refuse belongs on the write path once WRITE(10) exists.

sig_start_fblock is hardcoded to 0 at the call site -- correct for
today's unpartitioned raw test/real media (no GPT parser exists yet),
flagged in the comment as the one place that changes once a real
GPT-partition-relative lookup exists, isolated from
homeblocks_sig.c's own location-agnostic check logic.

Verified live: hot-attached disk/usb-thumbdrive-test.img (blank media)
through a running amd64 instance's QMP socket (blockdev-add +
device_add usb-storage) -- captured exactly 4 real TUR+READ10 BOT
cycles (matching the header's 4 forth-block span) followed by the
correct "not recognized" warning, then normal attach completing
successfully afterward (no regression). Conservation intact, no
panic. Clean zero-warning compile and clean boot on all three
architectures.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CXjAPTEKrgY2Mrk25KoLDn
2026-08-26 07:14:51 -04:00
Robert Allan JamesandClaude Sonnet 5 2c45744995 Implement homeblocks_sig_check(): the drive signature check (Phase 8)
Real, complete verification logic -- not yet wired to any write path.
homeblocks_sig_check(dev, sig_start_fblock, out_sig) reads the 4
consecutive 1KB blkio forth-blocks the 4KB header spans, verifies
magic -> version -> CRC-64 in order, returns HOMEBLOCKS_SIG_OK/_BLANK/
_BAD_VERSION/_BAD_CRC/_READ_ERROR. Reuses block_subsystem.c's existing
CRC-64/ISO (compute_crc64, previously static/file-local, now exposed
via block_subsystem.h) rather than a second CRC implementation --
same algorithm already proven via per-block checksums. Takes the
header's starting block as a plain parameter rather than resolving it
internally: verifies a signature given a location, finding that
location (GPT-partition-relative) stays the caller's job.

Verified against the actual shipped code, not a reimplementation: a
standalone host test links the real homeblocks_sig.c against a fake
in-memory blkio_dev and exercises all four outcomes -- blank media,
a correctly-minted header (round-trips drive_uuid/minted_time_ns), a
flipped CRC, an unrecognized version. All four pass. A full
QEMU-hotplug live test isn't proportionate yet since nothing calls
this function from the live kernel path -- wiring it into the attach
path is the next punch-list item. Clean zero-warning compile and
clean boot on all three architectures confirms no build/link
regression from exposing compute_crc64 and adding the new source
file to every kernel build.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CXjAPTEKrgY2Mrk25KoLDn
2026-08-26 07:05:37 -04:00
Robert Allan JamesandClaude Sonnet 5 10b96870c5 Add homeblocks_sig.h: drive signature header struct (Phase 8 kickoff)
Implements the design from the previous commit as-is: homeblocks_sig_t
(4096 bytes, magic+version+drive_uuid+timestamp+cert/blockmap offset
reservations+real hdr_crc), HOMEBLOCKS_SIG_PACK/_GET_MAGIC/_GET_VERSION
macros mirroring CAPSULE_MAGIC_PACK's bit layout, and a C99
compile-time size assertion matching stadium.h's own discipline.

Verified standalone (sizeof == 4096, clean under -std=c99 -Wall
-Wextra -Werror) -- nothing consumes this header yet, so no
functional kernel change and no 3-arch acceptance boot needed for this
step.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CXjAPTEKrgY2Mrk25KoLDn
2026-08-26 06:55:59 -04:00
Robert Allan JamesandClaude Sonnet 5 7cbf92ac8f FABRIC-3.md: design the home-blocks drive signature format (Phase 8 kickoff)
Mirrors CAPSULE_MAGIC_PACK's bit-packed magic and blk_volume_meta_t's
magic+version+fields+pad-to-4096 structural convention exactly, per
the punch-list item's own direction. Lives at the first 4KiB devblock
of the ~1GB GPT metadata partition -- format doesn't depend on the
still-missing GPT parser.

Deliberately narrow: identifies/authenticates the drive only, does not
invent the block-map or credential/cert formats -- reserves offset/
size pointers to where they'll live instead of embedding them, since
neither format is designed yet (block-map is Milestone 3, cert format
needs Milestone 6's still-ungenerated real CA). hdr_crc is real from
day one, unlike blk_volume_meta_t's unused placeholder, since this
header's whole job is gating the warn-and-refuse security check.

Design only, not yet implemented as a header file -- presented for
confirmation first.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CXjAPTEKrgY2Mrk25KoLDn
2026-08-26 06:47:52 -04:00
Robert Allan JamesandClaude Sonnet 5 aa6efe4632 FABRIC-3.md: close stale ACL-RWT re-measurement item -- already done in §T
Corrects bookkeeping, not measurement. FABRIC-2.md Sections M-T
(2026-08-19/21) already re-ran this and found the original "ACL-RWT"
name was itself wrong -- the Rolling-Window-of-Truth mechanism it
named was dead code removed 2026-07-08, never reachable. What the
campaign actually measured was the live ACL-TTL mechanism. Final
accepted result: +0.0603% ACL-TTL enforcement overhead,
architecture-independent, CV=0.000% (FABRIC-2.md SS T,
project_acl_ttl_overhead_final.md). The checkbox was simply never
marked done when that work concluded -- no new campaign run.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CXjAPTEKrgY2Mrk25KoLDn
2026-08-26 06:34:00 -04:00
Robert Allan JamesandClaude Sonnet 5 cbe7b49a59 Documentation debt sweep: 5 of 6 items resolved, 1 confirmed accurate
- docs/lithosananke/ROADMAP.md + M7.1.md: fixed stale "Branch: lithosananke"
  (no such branch post-split), M7.1's "Design Complete" status (shipped
  and live, redirected to FABRIC*.md), the M8/success-criteria
  self-contradiction (OBSOLETE marking vs. unqualified live criterion),
  and the stale AHCI/SATA claim for M9 (real implementation is
  virtio_blk.c) -- also corrected BLOCK/BUFFER/UPDATE/FLUSH and block
  device abstraction to [x] since both are confirmed live in
  src/word_source/block_words.c and block_subsystem.c.
- Top-level ROADMAP.md: marked OBSOLETE (Captain Bob's call -- more than
  "stale," the architecture/branch topology/terminology it describes no
  longer exist), pointing to docs/lithosananke/ROADMAP.md and
  FABRIC*.md for current status.
- docs/03-architecture/word-acl/DESIGN.md: fixed the ACL Phase 7
  contradiction -- Phase 7 (LithosAnanke kernel parity) is independently
  verified complete per .claude/CLAUDE.md, not "remaining"; removed the
  stale lithosananke-branch-parity framing.
- VM-FLEET-ATTRACTOR-DESIGN-20260705.md's doe-campaign.4th "broken" claim:
  investigated, ran SMOKE-CAMPAIGN live (completes clean, fleet heat
  conserved) -- initially read as contradicting the claim, corrected
  directly by Captain Bob: a clean execution trace doesn't disprove the
  doc's actual argument (no real controlled-experimental-factor
  mechanism). Confirmed accurate, left untouched.
- Isabelle/HOL pipeline-metrics model/C-struct mismatch: confirmed a real
  proof-modeling gap (pm_last_accuracy_num/den has no analogue in the
  real PipelineGlobalMetrics struct), not stale prose -- tracked here
  rather than fixed, matching the .thy file's own scope boundary and
  this project's standing caution that each Isabelle gap needs its own
  subsystem model.

ACL-RWT DoE overhead re-measurement (the 6th item) intentionally not
started -- a full multi-architecture DoE campaign, not a doc-text fix,
holding for explicit confirmation given the scale.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CXjAPTEKrgY2Mrk25KoLDn
2026-08-26 06:30:36 -04:00
Robert Allan JamesandClaude Sonnet 5 6341b3b3dd FABRIC-3.md: decide EXPIRE's design questions -- defer to Phase 8
Decided directly on request, no code written. "ACLs -> EXPIRE" isn't
wrong in spirit but was aimed at the wrong unit: acl_ttl-hits-zero
always renews (never revokes), so it can't carry EXPIRE's
residency-ending meaning. The unit that actually has a real lifetime
and should be revoked is a zuse superuser session (Phase 8, not yet
built) -- authenticate, hold elevated privilege for a bounded time,
then actually drop back to non-zuse.

Resolves to: admit the session (not a per-word ACL entry, which would
be redundant with item 4.1's existing word patrons) as the Stadium
patron, once Phase 8 exists. Not in scope now -- there is no session
to admit regardless of any other choice, and building Stadium's
missing generic ttl-decrement/reap mechanism ahead of its only real
consumer would be speculative infrastructure, the same shape of
premature build the no-stubs standard exists to prevent, just
inverted. EXPIRE stays explicitly deferred until Phase 8 lands, with
a concrete trigger for revisiting it -- not abandoned, not left
ambiguous.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CXjAPTEKrgY2Mrk25KoLDn
2026-08-26 06:17:56 -04:00