FABRIC-3.md §H: session refactor capture -- struct shape + identity/ACL cards

Design capture from today's session-refactor discussion, back to Hera:
session-as-Stadium-patron struct shape (references the patron by VMUuid,
pin-authoritative, identity embedded), and the identity ACL "stack of
cards" model with all four named dimensions scoped so far (VM, word,
block, message) plus the PubSub/topics messaging-protocol groundwork the
message card depends on. Closes with a numbered gap-analysis list (§H.9)
of everything still explicitly open.

Capture-only, matching this document's own established discipline -- no
struct written, no code changed. Mirrors §D's Tripod-vision capture in
style and structure.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Robert Allan James
2026-09-02 18:08:35 -04:00
co-authored by Claude Opus 5
parent f81e9c92bc
commit 1349e783aa
+181
View File
@@ -3527,3 +3527,184 @@ by refiling after lapse), so #1 is on a hard clock; **#2 (full StarshipOS) is th
deliverable** that keeps the flagship covered — and, pending counsel confirmation, may be the
conversion vehicle for #1. Authoritative form in `ROADMAP.md` "IP framing of the three
products".
---
## H. Session refactor, back to Hera — session struct shape + identity/ACL card model (capture, 2026-09-02)
Captain Bob announced a major refactor reaching all the way back to Hera's own boot sequence:
formally introduce **session** as a first-class concept at the root of the system, rather than
bolted on later. This sharpens and extends D.2's 2026-08-27 correction ("a session is any VM
client running in the Stadium fabric... Zuse is a player like any other") into a concrete
struct shape and, from there, into a full identity/ACL model. **Capture-only pass, matching
this document's own established discipline** ("capture EVERYTHING first then we'll build a
plan," D's own intro) — nothing here is scoped into implementable items yet.
### H.1 — Session = Stadium patron, admission restated
- Hera defines what a session *is* (the concept/type itself). At boot, Hera registers
**herself** into her own session first. When Hera births a child VM (Hermes, then Artemis),
she also stands up a session for that child at birth time.
- **A session is a Stadium patron** — registering a session = admitting a patron to the
Stadium, not a new parallel bookkeeping structure. This is the same correction D.2 already
made ("a session IS a VM"), now traced down to the concrete admission mechanism already
live in `src/starkernel/vm/stadium.c`: `StadiumPatronHeader` (64 bytes — identity, heat,
ttl, link, contains, mass, flags [bit 0 = `STADIUM_FLAG_PIN`], behaviour, 32-byte inline
payload) and `stadium_birth_hera()`, which already admits Hera as patron zero, pinned, via
`stadium_admit(vm_uuid_hera(), &candidate)`. No `stadium_birth_hermes()`/`_artemis()`
equivalent exists yet — Hera is the only admitted patron today.
- **Pinned** sessions (Hermes, Artemis — the VMs Hera births at boot) are patrons exempt from
the normal departure path (heat decay / `COOL`): they never leave, permanently.
- Core unifying principle, in the user's own words: **"a process and a virtual machine are
going to be exactly the same thing"** inside this OS — VM identity, process identity, and
session become one concept, not three.
- **A session is a Stadium patron** *(Captain Bob, confirming): "Oh, yeah. God. This is...
this becomes a patron of the stadium, I believe, session, that is."* Pinned patrons are
exempt from the normal departure path (heat decay / `COOL`) — they never leave.
- **Open, not yet stated:** whether a *non-pinned* session (an ordinary Stadium patron subject
to `COOL`) is where a future ephemeral user VM's session would land. The pinned/patron
framing is confirmed; this specific mapping is not — don't assume it.
### H.2 — Session struct shape
Confirmed: **a session is a NEW structure, separate from `StadiumPatronHeader`, that
references the patron by `VMUuid`** — not the patron header itself, and not indexed by
Stadium cell index. Gets its own header file, same precedent as `VMUuid`/planned-`VMIdentity`
(never grow `struct VM` or `StadiumPatronHeader` with inline fields for this).
Confirmed session fields so far:
- `vm_id` (`VMUuid`) — the patron this session references.
- `pinned`**session is authoritative**; Stadium's `STADIUM_FLAG_PIN` bit follows the
session's value, not the other way around.
- `parent` (`VMUuid`) — who birthed this session (Hera → Hermes/Artemis). *Proposed by the
model, not yet explicitly confirmed word-for-word* — flag before building on it.
- `name` — canonical human-readable name (feeds `console.c`'s `g_active_vm_name` prefix,
doesn't replace the console-binding mechanism itself). *Also model-proposed, not confirmed.*
- `identity` — lives directly embedded in the session struct (confirmed). Contents: the
ACL "stack of cards" model, H.3 onward.
**User's own framing, explicit and important**: "the floor was, who knows? We're gonna be
revisiting this part of it around and around for a while." Treat this field list as a live,
expected-to-churn working draft, not a locked shape.
### H.3 — Identity model: ACL "stack of cards"
Identity carries the VM's/word's ACL as a **stack of cards, each with pinholes punched through
it** — user's own framing: "a stack of cards... got pinholes going through it, and those
pinholes drop all the way down through and give the permission for whatever we're
work[ing on]... a set of graduated sieves." Confirmed accurate by the user.
**Each card is one permission dimension**, not a redundant extra layer of the same check —
named dimensions so far: VM, word, block, message. A compound action (e.g. "execute word X,
which touches block Z and sends message M") passes through the word card, the block card, and
the message card at once — one card per relevant axis. **Confirmed: an action only consults
the cards for the dimensions it actually touches** — a pure VM-level operation only checks the
VM card, not the full stack every time.
Whether/how the existing word-level ACL (`acl_ttl`/`acl_allow`/`acl_mode`/`acl_pinned` on
`DictEntry`, see `.claude/CLAUDE.md`'s "Word-Level ACL System") folds into or reconciles with
this new stack-of-cards model is unresolved — the word card (H.5) explicitly reuses one piece
of it (`ACL-TTL`), but the rest is open.
### H.4 — VM card
Narrow by design: a single base gate ("who owns / can-touch this VM at all") that other, finer
checks sit on top of. Does not itself enumerate operations (birth/kill, console attach,
retarget, quota grant, etc.) — those are finer-grained checks built elsewhere.
- **Zuse is entirely outside the card stack**: "forget Zeus [Zuse]. Zeus will always have 100
percent authority" — unconditional, not modeled as an always-allowed path *through* the VM
card the way the earlier `ACLKEY` pass (§F.2) had framed it. Zuse bypasses the card stack
entirely, full stop.
- **Single owner, for now**: exactly one `owner_pubkey` per VM at this gate (match or no
match), not a list of authorized identities — "single owner for now," multi-owner
explicitly deferred, not in scope.
- Matches the `VMIdentity{owner_pubkey[32], installed}` shape already decided in the earlier
`ACLKEY` pass (§F.2) — the VM card is effectively that ownership check, non-Zuse case only.
### H.5 — Word card
- **Default-permissive baseline**: "will have to pretty much admit any word" — not a
default-deny gate that has to explicitly enumerate everything.
- **Dynamic, not fixed**: ACLs at this card are "additive/subtractive dynamic entities" — the
permission set can grow or shrink over the session's lifetime, not a static list decided
once at creation.
- **Hard ceiling invariant**: "they can never exceed the creator's permissions" — a session's
word permissions can never exceed what its own creator/parent had. Delegation is capped by
the parent's own permission set — presumably where H.2's `parent` field earns its keep.
- **Escape hatch, mechanism confirmed reused**: the only way to temporarily exceed that
creator-ceiling is "some kind of temporary Zuse power" — **confirmed reuse of the existing,
already-built-and-measured `ACL-TTL` mechanism** (`acl_ttl` field on `DictEntry`), not a new
parallel temporary-grant mechanism. **Explicitly still undecided: the trigger/path for *how*
a session actually reaches that elevated state** — only the underlying TTL mechanism itself
is settled as reused, not the invocation flow.
### H.6 — Block card
**Confirmed: reuses the already-decided `BMAPFMT` design** from §F.4 — distributed per-block
ownership, not a new mechanism. Repurposes the dormant, fully-wired, zero-caller `blk_meta_t`
struct: 8-byte owner-pubkey fingerprint + 1-byte fast-deny `acl_allow`, with deliberate
reserved slack in the 40-byte block ("flexibility until we understand the recipe"). No
separate centralized block-ownership table (makes `homeblocks_sig_t`'s reserved
`blockmap_offset`/`blockmap_devblocks` fields unnecessary, already flagged for cleanup).
`BMAPFMT`'s field design was done as of the §F.4 pass but **the code change was never made**
this refactor is presumably where it finally lands.
### H.7 — Messaging protocol groundwork (prerequisite to the message card)
- **PubSub, decided.** Terminology is **"topics"** — not "channels." Likely reconciles with
the existing `CH` field / `CH-ALLOC` API already on record in D.4's message shape
(`MSG-CELLS` = `TYPE, FROM, TO, PADDR, PLEN, STADIUM-CELL, SEQ, CH, ORIG-TYPE`) — `CH` is
likely the topic identifier, terminology now formalized as "topic."
- **Every VM always subscribes to one well-known "common" topic** — a standing prerequisite,
not something set up per-conversation. This is the rendezvous point.
- **Handshake flow**: VM A posts a message on `common` addressed to VM B — "I would like to
commune with you." VM B, already listening on `common`, responds okay. That handshake
causes a **new private topic** to be created, which A and B then use directly instead of
`common`.
- **ACK/NACK confirmed as a general reliability mechanism**, applied to every message on any
topic (private or `common`) — not specific to the handshake step.
### H.8 — Message card
**Scope confirmed narrow and one-sided**: gates only "who's allowed to post on `common`
requesting a commune" — the *initiating* side of the H.7 handshake. The receiving VM's
decision to accept/ACK is **not** gated by this card. Not yet stated: whether traffic on an
established private topic (post-handshake) is gated by this card, a different mechanism, or
left ungated.
### H.9 — Gap analysis (as of 2026-09-02)
Explicitly open items surfaced during this capture pass, none decided yet:
1. **Non-pinned session mapping (H.1).** Does an ephemeral user VM's session land as a
non-pinned (normal-departure, `COOL`-subject) Stadium patron? Framing confirmed, this
specific mapping is not.
2. **`parent` and `name` session fields (H.2).** Proposed by the model, never explicitly
confirmed by Captain Bob — the field list is stated as a live, expected-to-churn draft
("we're gonna be revisiting this part of it around and around for a while").
3. **Word-level ACL reconciliation (H.3).** How (or whether) the existing
`acl_ttl`/`acl_allow`/`acl_mode`/`acl_pinned` `DictEntry` fields fold into the stack-of-
cards model, beyond the one confirmed reuse (`ACL-TTL` as the word card's escape hatch,
H.5).
4. **Temporary-elevation invocation path (H.5).** The `ACL-TTL` mechanism itself is confirmed
reused; *how* a session actually reaches that elevated state (who/what invokes it, under
what condition, what Zuse has to do) is explicitly undecided.
5. **`BMAPFMT` code change (H.6).** Field design was finished in the §F.4 pass but the actual
code edit to `blk_meta_t` was never made — a real, concrete implementation gap, not just an
open question.
6. **Topic/`CH` reconciliation (H.7).** "Topic" is the newly formalized term; whether it maps
1:1 onto the existing `CH` field in `MSG-CELLS` or needs its own representation is inferred
by the model, not explicitly confirmed.
7. **Private-topic traffic gating (H.8).** Whether messages on an established private topic
(as opposed to the initiating `common` post) are gated by the message card, some other
mechanism, or left ungated entirely.
8. **The `EXPIRE`/D.2 relationship.** D.2 already established "session ending = VM detach,
reuse `COOL`" — H.1's pinned/non-pinned framing should be read as refining that, not
replacing it, but the two have not been explicitly reconciled in one pass.
9. **Every other card beyond the four named** (VM, word, block, message) — the model list is
confirmed as the *named-so-far* set, not stated as closed/exhaustive.
10. **No implementation has started.** Every item above, and every card definition in
H.4H.8, is design capture only — no struct has been written, no `stadium_birth_hermes()`/
`_artemis()` exists, no `Session` header exists. Standard for this document's own
discipline (see D's intro), but worth stating plainly given the size of this section.