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
This commit is contained in:
Robert Allan James
2026-08-27 12:03:53 -04:00
co-authored by Claude Sonnet 5
parent 7957b0497f
commit b47cf3811e
+84 -5
View File
@@ -135,8 +135,11 @@ decisions get added here, not to `FABRIC-2.md`. Follow the same discipline `FABR
`RELOCATE-BLOCK`, `FABRIC-2.md`, commit `36d832f`. This item is about the identity→range
allocation that decides what to relocate blocks* into*, still unbuilt.)*
- [ ] Design the on-drive block-map format (Section U item 4) — what it records (block ranges
claimed? individual block liveness? something else), how it's serialized.
- [x] **SCOPED 2026-08-27 (FABRIC-3.md §F.4).** Design the on-drive block-map format (Section
U item 4). Resolved as: no separate table — repurpose the existing, fully-wired-but-
zero-callers `blk_meta_t`/`blk_get_meta()`/`blk_set_meta()` (`block_subsystem.c`), replacing
its stale POSIX-flavored ownership fields with a pubkey-fingerprint owner + a fast-deny ACL
bit + deliberate reserved slack. Field design done; the actual code edit is not.
- [ ] Implement writing the block-map to a drive.
@@ -1395,7 +1398,7 @@ graph TD
CERTVERIFY["🔓 CA-signed-cert verification path (M3)<br/>UNBLOCKED by M6, not yet built"]
FIRSTTOUCH["❌ First-touch identity→block-range<br/>allocation (M3)"]
BMAPFMT[" On-drive block-map format (M3)<br/>real design decision, not started"]
BMAPFMT[" On-drive block-map format (M3)<br/>SCOPED 2026-08-27 (§F.4) — repurpose blk_meta_t"]
BMAPWRITE["❌ Write block-map to drive (M3)"]
BMAPREAD["❌ Read/validate block-map on insert (M3)"]
MIGSM["🟡 Migration state machine (M3)<br/>partially answered: ACL decides *when*"]
@@ -1452,9 +1455,9 @@ graph TD
classDef open fill:#666,stroke:#333,color:#fff
classDef partial fill:#883,stroke:#333,color:#fff
class M6,PH8,EXPIRE,MSGSHAPE,HOTPLUG done
class W10,STALL,FIRSTTOUCH,BMAPWRITE,BMAPREAD,UNCLEAN,WIREBIND,BINDSTEP,DETACH,MINT blocked
class W10,STALL,FIRSTTOUCH,BMAPWRITE,BMAPREAD,UNCLEAN,WIREBIND,BINDSTEP,DETACH,MINT,BMAPFMT blocked
class CERTVERIFY unblocked
class BMAPFMT,ACLKEY,RUNCAP,MSGMIGRATE,SSDSCOPE,ROUNDTRIP,POLYBLOCK open
class ACLKEY,RUNCAP,MSGMIGRATE,SSDSCOPE,ROUNDTRIP,POLYBLOCK open
class MIGSM partial
```
@@ -1573,6 +1576,82 @@ yes — the *lock itself* being immutable once set at a VM's birth is a differen
"binding stays retargetable," and shouldn't be conflated with decision 3 above) — worth a
dedicated look when this is actually built, not decided in this pass.
### F.4 — `BMAPFMT` (on-drive block-map format)
Worked through conversationally, one step at a time, rather than dumped as a finished design —
each step below only followed once the previous one was grounded in real code, not assumption.
**Step 1 — does a map cell need a state field, not just ownership?** Yes, confirmed against
existing precedent before answering: the internal Artemis BAM entry
(`blk_bam_entry_t{allocated, dirty}`, `block_subsystem.h:257-261`) already conflates ownership
and state in the simplest map this codebase has. More importantly, `MIGSM` and `UNCLEAN` (two
already-identified, currently-blocked graph nodes) have nowhere else to record "this range is
mid-migration" or "this range's flush was interrupted" without a state field — this node was
quietly upstream of both.
**Step 2 — should a cell also carry an ACL?** Yes, and it can't reuse `acl_mode`/`acl_allow`/
`acl_pinned` directly for the same reason `ACLKEY` (F.2) couldn't — those are `DictEntry`
fields. Decided: the owner field and any future ACL grant should share **the same identity
representation** `VMIdentity` already established (a pubkey), not a second encoding — keeps
"identity is one common primitive" (D.5) actually true in practice, not just in name.
**Step 3 — ACL check ordering.** "ACL denial is the fast exit path" — grounded directly
against `vm.c:611-624`'s live word-execution ACL check: a cached `acl_allow` bit is
checked *first*, before any other work, and denial short-circuits immediately. A block cell's
ACL needs the identical shape at its top: one cheap cached allow bit, checked before range/
state/owner logic runs.
**Step 4 — buffering/granularity, and a major discovery.** Confirmed: this kernel already
buffers a whole 4 KiB devblock on any block touch (`LOAD` and friends), and
`BLK_META_PER_BLOCK` (`block_subsystem.h:83`, `341u /* 341×3 ~= 1023, padded to 1024 */`)
already packs **exactly** 3×1 KiB Forth-block metadata slices into that same devblock's spare
1 KiB — the "3-block cluster + 1 KiB metadata" shape volunteered in conversation *already
exists as `blk_meta_t`*, with real, wired, non-stub accessors (`blk_get_meta()`/
`blk_set_meta()`, cached, dirty-tracked, `block_subsystem.c:1175-1207`). **Grepped and
confirmed it has zero callers anywhere in the codebase** — fully built, fully unused. Its
existing "Security & ownership" 40 bytes (`owner_id`/`permissions`/`acl_block`/`signature[2]`)
predate and directly conflict with both the anti-POSIX principle and `VMIdentity`'s
pubkey-based model — flagged, not silently reused.
**Decisions made 2026-08-27:**
1. **`BMAPFMT` is not a new structure — it's repurposing `blk_meta_t`.** No separate on-drive
block-map table gets built. Ownership/ACL/state travel *with* the block itself
(distributed), not in a centralized table (the shape Milestone 3's original wording
pictured). One I/O gets payload and map info together; nothing separate to keep in sync.
2. **Consequence flagged, not silently absorbed:** `homeblocks_sig_t`'s reserved
`blockmap_offset`/`blockmap_devblocks` fields (`homeblocks_sig.h:93-95`) become unnecessary
under this decision — that header reserved space for a centralized table this design no
longer needs. Needs a comment update in that file once this is actually built, not left
silently stale.
3. **Replacement for the 40-byte "Security & ownership" block** (same budget the old
`owner_id`/`permissions`/`acl_block`/`signature[2]` occupied; nothing else in `blk_meta_t`
moves):
```
uint8_t owner_fp[8]; /* truncated fingerprint of owner's VMIdentity pubkey, not the
full 32 bytes -- keeps this cheap per-block; full pubkey
resolves via the drive's own identity record. */
uint8_t acl_allow; /* cached fast-deny bit, checked first -- vm.c:611-624's exact
pattern, applied to a block instead of a word. */
uint8_t acl_reserved[7]; /* explicitly undecided -- deliberate slack per "flexibility
until we understand the recipe," not a placeholder to fill
reflexively. */
uint64_t reserved_future; /* untouched budget, same reasoning. */
```
`flags` (already existing, already generic) does double duty as the **state** field from
Step 1 — no new field, just future-defined bit values (`CLAIMED`/`MIGRATING`/`STALE`/etc.).
Everything else in `blk_meta_t` (`checksum`, timestamps, `content_type`, hash, chain links,
`app_data[15]`) is untouched.
4. **Allocation granularity**: claims quantize to whole devblocks (3 Forth blocks), matching
the existing packing — a cell never needs to describe partial-devblock ranges.
**Not yet scoped (deferred within this node):** the actual allow-list/grant shape beyond the
single fast-deny bit (lands in `acl_reserved`, once designed); the specific `flags` bit
values for each state; whether `blk_get_meta()`/`blk_set_meta()` need new FORTH word wrappers
or stay C-only like `zuse_cert_seed`'s "no FORTH access" precedent; the actual repurposing
edit to `block_subsystem.h`/`.c` itself (this pass produced the field design, not the code
change).
### D.5 — Scope expansion (2026-08-27): identity is common to every VM, not just users
Surfaced while scoping `ACLKEY`, stated directly: *"the whole object is to deliver a