§H.12 steps 10-11: creator-ceiling enforcement, birth-time ACL snapshot

dictionary_snapshot_acl_from_parent(child, parent): walks the child's
dictionary, copies acl_allow/acl_mode/acl_pinned/acl_ttl from the
parent's matching word (by name, via vm_find_word() -- FIND's own
lookup, not modified) onto the child's entry. One-time snapshot at
birth, no live sync, matching H.3's decided rationale (a program
developed against one ACL set must not have it silently changed by
later parent changes).

Called once, after dict_hash/parity logging rather than before -- the
snapshot depends on the parent's current ACL state, which can vary
run-to-run once Zuse elevations exist, so applying it earlier would
break the "same capsule twice produces the same dict hash" determinism
invariant.

Verified 3-arch boot to ok> (amd64/aarch64/riscv64).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Robert Allan James
2026-09-03 06:44:58 -04:00
co-authored by Claude Opus 5
parent ed86a759e1
commit a268abe925
10 changed files with 27624 additions and 6 deletions
+41
View File
@@ -104,6 +104,33 @@ static VMRegistryEntry *vm_find_entry_ptr(VMUuid vm_id) {
return (void *)0;
}
/* FABRIC-3.md §H.12 step 10: creator-ceiling enforcement, birth-time
* snapshot only, no live sync (§H.3, decided 2026-09-03 -- "if something
* was developed with a particular set of ACLs, it should remain at
* that... otherwise parent changes break the child's program"). For
* every word in child's dictionary also present, by name, in parent's,
* copy parent's CURRENT acl_allow/acl_mode/acl_pinned/acl_ttl onto
* child's matching entry -- caps the child at whatever the parent
* allowed at this exact moment, once, never re-applied afterward. Words
* the child has that the parent doesn't (baby-specific vocabulary) are
* left untouched -- there's nothing to cap them against. vm_find_word()
* is the same C-level lookup FIND itself uses; not modifying FIND, just
* calling the same lookup it does (CLAUDE.md: "FIND is a proven, tested,
* registered word. Never modify it" -- this doesn't). */
static void dictionary_snapshot_acl_from_parent(VM *child, VM *parent) {
DictEntry *ce;
if (!child || !parent) return;
for (ce = child->latest; ce != NULL; ce = ce->link) {
DictEntry *pe = vm_find_word(parent, ce->name, ce->name_len);
if (!pe) continue;
ce->acl_allow = pe->acl_allow;
ce->acl_mode = pe->acl_mode;
ce->acl_pinned = pe->acl_pinned;
ce->acl_ttl = pe->acl_ttl;
}
}
void capsule_vm_registry_init(void *mama_vm_ptr) {
uint32_t i;
vm_node_t *node;
@@ -674,6 +701,20 @@ CapsuleRunResult capsule_birth_baby(
capsule_parity_log_birth(vm_id, cap->capsule_id, cap->content_hash, dict_hash);
/* §H.12 step 11: applied AFTER dict_hash/parity logging above, not
* before -- a runtime ACL snapshot depends on the parent's CURRENT
* state (which can vary run-to-run once Zuse-granted elevations
* exist), so applying it before the hash would make birth_dict_hash
* no longer a pure function of capsule content, breaking the "same
* capsule booted twice produces the same dict hash" determinism
* invariant this codebase relies on elsewhere. */
{
VMRegistryEntry *parent_entry = vm_find_entry_ptr(parent);
if (parent_entry && parent_entry->vm_ptr) {
dictionary_snapshot_acl_from_parent(new_vm, (VM *)parent_entry->vm_ptr);
}
}
if (out_vm_id) *out_vm_id = vm_id;
if (out_vm_ctx) *out_vm_ctx = new_vm;