2a30212bd362b27a042ff742ca2ecb305e6ba074
9
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
cd2fda4351 |
Add mkcapsule --resolve: build-time claim registry for capsule block collisions (FABRIC-3.md §XXIV)
Traced what a "Block NNNN" collision actually means before designing a fix for it: capsule_loader.c's block-write path routes through the generic block-subsystem API, which kernel_main.c registers as two devices in a fixed order -- the volatile ramdrive first (LBN 2048-3071), then Artemis's real virtio-blk device immediately after (LBN 3072+, backed by disk/artemis.img). Every capsule this project has lands in Artemis's persistent range, not the ramdrive, and blk_update()'s dirty-marking + repl.c's idle-loop flush write that content through to the real disk file on every boot. A block-number collision is therefore a silent, persistent overwrite of real disk content surviving reboots, not a transient RAM mixup. The existing collision gate (check_block_conflicts(), already a hard non-interactive build failure) already catches capsule-vs-capsule collisions across the whole flat range. The real gap: zero visibility into blocks something other than a capsule owns (Artemis's own non-capsule persistent data), and no device-boundary/capacity awareness at all. Added, scoped step by step before writing any code: - tools/capsule-claims.txt -- derived, auto-created/regenerated, git-ignored. Lets --resolve tell "this capsule's own content changed" apart from "genuinely new collision with something else." - tools/capsule-reserved.txt -- human-authored, git-tracked, seeded with nothing yet rather than guessed at. Checked by both the plain build gate (new check_reserved_conflicts()) and --resolve. - tools/patches/ -- git-tracked, one file per accepted interactive renumber; a structured old->new block list, not a generic diff, since that's the only thing a renumber ever changes. - mkcapsule --resolve <dir> -- the only interactive mkcapsule mode, a deliberate separate invocation from the plain build path (which stays non-interactive so CI never blocks on a prompt). Suggests a renumbering that preserves a capsule's own existing block spacing, prompts y/N, rewrites the .4th source in place on acceptance. Found and fixed a real bug during verification: the registry's empty-block-list case (workload-5.4th, zero Block headers) serialized with a stray trailing space that the reader parsed back as a phantom block 0, causing spurious re-registration every run -- caught by testing idempotency directly, not assuming a clean first run meant it worked. Verified: isolated collision tests confirm both accept and reject paths, confirm a resolved collision doesn't re-prompt the other side, confirm reserved-range collisions are caught by both --resolve and the plain build gate. Full 3-architecture rebuild via the real Makefile.starkernel succeeded clean; amd64 boots with an unchanged dict_hash/capsule_hash from every prior boot this session. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EXieurDfDSsDFdnSyusuWo |
||
|
|
5c1b31669e |
Rename init-0.4th..init-9.4th to workload-0.4th..workload-9.4th; fix stale WL-HI/WL-LO doc
These are alternate boot personality capsules, not files doe.4th dispatches from -- confirmed by reading doe.4th itself (it generates its own synthetic workload internally, DOE-WORK) and mkcapsule.c (only the exact filename "init.4th" is special-cased as the active MAMA_INIT capsule). "workload-N.4th" names them for what they are without colliding with that reserved name. Renamed the 10 files (git mv, preserving history) and their own self-referential header comments (also fixed a pre-existing typo, "init-4.th" -> "workload-4.4th"), updated capsules/README.md, capsules/MANIFEST.md (21 references), .claude/CLAUDE.md, and a tools/mkcapsule.c comment. Also fixed experiments/bare_metal/README.md's "Adding a Custom Workload Capsule" section, discovered stale while doing this rename: it documented a WL-HI/WL-LO dispatch table and a wl_id CSV column that don't exist anywhere in the current capsules/ tree or doe.4th's own CSV header -- corrected to describe what's actually there (no pluggable workload dispatch; a custom workload is run by substituting it in as the boot's own init.4th). Verified: mkcapsule --lint clean (35 files, 0 violations), all 3 architectures build with zero new warnings, amd64 boots to zuse)ok> with an unchanged dict_hash/capsule_hash from every prior boot this session (0xc8f4b09e36f4fc4a / 0x1ef4939ed32ec1e6) and zero faults. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EXieurDfDSsDFdnSyusuWo |
||
|
|
b031b802e3 |
Rename FABRIC series: FABRIC.md->0, FABRIC-2.md->1, FABRIC-3.md->2, FABRIC-4.md unchanged
FABRIC.md -> FABRIC-0.md FABRIC-2.md -> FABRIC-1.md FABRIC-3.md -> FABRIC-2.md (the current/living document) FABRIC-4.md unchanged (new #3 to follow separately) Every cross-reference repo-wide updated to match, including doc-comment citations inside kernel source (.c/.h) files -- done via an ordered placeholder substitution (FABRIC-3.md->placeholder2, FABRIC-2.md-> placeholder1, FABRIC.md->placeholder0, then placeholders resolved to final names) in a single pass per file to avoid double-shifting already-renamed references. One line in capsules/font.4th grew past the 64-char block-format limit as a side effect of the longer filename; shortened it and reverified with mkcapsule --lint (34/34 pass) before rebuilding. Verified 3-arch boot to ok> (amd64/aarch64/riscv64, each in the foreground) after the fix; logs and DoE CSVs from this session's verification runs included per this repo's own audit-artifact convention. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var |
||
|
|
eeceec21a5 |
FABRIC-3.md §I.5: Milestone 7 trust tiers (QEMU-vs-real-hardware), closing it
Closes the contributor-capsule/trust-tier punch-list item. Decided direction: QEMU-vs-real-hardware conditional enforcement. Found before building on that decision: the obvious mechanism (expose TimerInfo.vm_mode) only works on amd64 -- aarch64 and riscv64 both had vm_mode hardcoded to 1 unconditionally, meaning they'd always report "running under QEMU" even on real hardware. Built real detection for both instead of shipping that: aarch64 checks the ACPI RSDP's OEM ID for QEMU's "BOCHS " SeaBIOS-heritage signature; riscv64 checks the devicetree root compatible property for "qemu". Confirmed vm_mode was otherwise unread anywhere else in either file first -- zero risk to existing timing behavior. CAPSULE_FLAG_CONTRIB (mkcapsule.c: FLAG_CONTRIB) path-matches on capsules/contrib/, mirroring FLAG_MAMA_INIT's exact-match pattern. contrib_capsule_refused() (capsule_birth.c) enforces: no additional check under QEMU (same WARN-only as everything else); on real hardware, a contrib capsule additionally requires CAPSULE_SIG_OK, since it has no other provenance to fall back on. Wired into capsule_birth_baby() and capsule_run_experiment(). Also updates §I.7 (Milestone 9): its stated precondition (Milestone 7 closing) is now met, flagged as stale rather than treated as a green light to design networking from nothing. Verified 3-arch boot to ok> (amd64/aarch64/riscv64, each in the foreground) -- compile/boot verification only; the real-hardware enforcement branch is unverifiable from this environment, same as all of §I.6. logs and DoE CSVs from this session's verification runs included per this repo's own audit-artifact convention. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var |
||
|
|
5567d03c12 |
FABRIC-3.md §I.4: magic-number content-type detection, closing Milestone 6
Closes both remaining Milestone 6 (PKI) punch-list items. Signature-status column: doc-only closure -- the underlying need was already redirected to capsules/BLOCK_MAP.md's real Signed column (2026-08-26); checking the box off as moot-as-worded rather than leaving an accurate-but-permanently-unchecked marker. Magic-number content-type detection (Section U item 14): built in tools/mkcapsule.c. detect_content_type() classifies a file's actual leading bytes (TTF/OpenType sfnt tags, DER's 0x30 SEQUENCE tag, or a printable-ASCII/TAB/CR/LF heuristic for text) against expected_type_from_ext()'s .4th/.md/.der/.ttf mapping; process_file() warns on mismatch, never refuses -- same WARN-first rollout this project already used for capsule signing. Verified against every real capsule in the repo (38 files) with zero false positives. This is the shared primitive Milestone 7's contrib-capsule validation can reuse next. Verified 3-arch boot to ok> (amd64/aarch64/riscv64, each in the foreground); logs and DoE CSVs from this session's verification runs included per this repo's own audit-artifact convention. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var |
||
|
|
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 |
||
|
|
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 |
||
|
|
1a2ec565e8 |
Zero C-compiler warnings on all three architectures; fix real restore_vm_state() bug
Maintainability sweep (prompted by "this is getting hard to maintain"): fixed the remaining three warning classes after the missing-field- initializers commit -- 2x -Wsign-compare (control_words.c, cast at the comparison site rather than changing cf_last_mode's type, which deliberately holds a -999 sentinel outside vm_mode_t's valid range), 2x -Wstringop-truncation (mkcapsule.c, strncpy+manual-null-terminate replaced with the idiomatic snprintf equivalent), and 26x -Wunused-parameter (mostly documented stubs, silenced with the repo's existing (void)param; idiom). One of the unused-parameter warnings was not a deliberate stub -- a real bug. restore_vm_state() (test_common.c) is named, documented, and called by nine real call sites (acl_words_test.c x8 plus its own internal use) as "restore saved VM state", but ignored all four of its parameters and hard-reset to a fixed baseline instead, silently not restoring what any caller actually saved. Fixed to actually assign the passed-in dsp/rsp/error/mode. Found while fixing warnings, reported before touching it, fixed/tested/documented/committed on explicit instruction. Verified: all three architectures build with zero C-compiler warnings (amd64: 3040 -> 0; aarch64's one remaining note is lld-link's own unrelated linker warning, not a C warning). Full amd64 acceptance boot post-fix: POST 1003/965/0/0/38 (total/passed/failed/errors/stubs), "ALL IMPLEMENTED TESTS PASSED!", contract checks (A4'/A1) all passed, dict_hash=0x24b4279f0670aa3a -- an exact match to this document's own previously-recorded baseline hash. .claude/CLAUDE.md corrected to describe the real -Wno-error= exemption list instead of the "-Wall -Werror" oversimplification. FABRIC-2.md Section J records the full sweep, including doc-tree staleness findings flagged but not fixed this pass (docs/lithosananke/ROADMAP.md branch topology, docs/03-architecture/word-acl/DESIGN.md's Phase 7 claim contradicting CLAUDE.md, top-level ROADMAP.md's stale StarForth-era status, the Isabelle pipeline-metrics model mismatch). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
a5ed8c3d87 | Initial commit — LithosAnanke kernel |