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:
co-authored by
Claude Sonnet 5
parent
7957b0497f
commit
b47cf3811e
+84
-5
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user