§H.12 steps 21-22: ELEVATE-REQUEST + ELEVATE-GRANT + SEND-ELEVATE-REQUEST

Phase 7 complete, closing out §H.12's punch list. MSG-DELIVER turned out
to VM-EXEC payload text directly rather than dispatching by type, so the
"handler" is ELEVATE-GRANT, a word the delivered text calls. New Hera-only
C primitives (ZUSE-ELIGIBLE?, NAME>XT, ELEVATE-PUBKEY-UNPACK) stay plain
and unconditional; capsules/zuse-eligibility.4th composes the actual
eligibility check + ACL-ALLOW!/ACL-TTL! grant in FORTH.
SEND-ELEVATE-REQUEST (common:messaging.4th) builds the payload text and
sends it via the item-20-gated CH-REQUEST.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QgooKd5hJNtTYqB6CyK5f9
This commit is contained in:
Robert Allan James
2026-09-03 13:15:40 -04:00
co-authored by Claude Sonnet 5
parent cb6e079a73
commit 2b9fa02354
10 changed files with 27815 additions and 46 deletions
+95
View File
@@ -935,6 +935,95 @@ static void mama_word_zuse_eligibility_add(VM *vm)
vm_push(vm, 1);
}
/**
* @brief ZUSE-ELIGIBLE? ( c-addr -- flag )
* Membership check over Zuse's elevation eligibility list (FABRIC-3.md
* §H.5/§H.12 item 21). Plain, unconditional wrapper over
* zuse_eligibility_is_member() -- same "no bespoke gate" convention as
* ZUSE-ELIGIBILITY-ADD above; is_member() itself is already fail-closed.
*/
static void mama_word_zuse_eligible_query(VM *vm)
{
if (vm->dsp < 0) {
vm->error = 1;
vm_push(vm, 0);
return;
}
cell_t caddr = vm_pop(vm);
const uint8_t *pubkey = vm_ptr(vm, (vaddr_t)caddr);
if (!pubkey) {
vm->error = 1;
vm_push(vm, 0);
return;
}
vm_push(vm, zuse_eligibility_is_member(pubkey) ? -1 : 0);
}
/**
* @brief NAME>XT ( c-addr u -- xt|0 )
* Dynamic dictionary lookup for a name already sitting in a data buffer
* (e.g. a message payload's argument), as opposed to `FIND`/`'` which
* parse the next word from the live input stream -- FIND itself is never
* modified, per this project's standing rule; this is a separate,
* mechanism-only primitive for the same lookup from a data-stack string.
* Miss (word not found) is not an error: pushes 0, matching FIND's own
* "miss is NOT an error" convention.
*/
static void mama_word_name_to_xt(VM *vm)
{
if (vm->dsp < 1) {
vm->error = 1;
vm_push(vm, 0);
return;
}
cell_t u = vm_pop(vm);
cell_t caddr = vm_pop(vm);
if (u < 0 || u > 127) {
vm_push(vm, 0);
return;
}
const uint8_t *name = vm_ptr(vm, (vaddr_t)caddr);
if (!name) {
vm->error = 1;
vm_push(vm, 0);
return;
}
DictEntry *e = vm_find_word(vm, (const char *)name, (size_t)u);
vm_push(vm, (cell_t)(uintptr_t)e);
}
/**
* @brief ELEVATE-PUBKEY-UNPACK ( pk0 pk1 pk2 pk3 buf-addr -- )
* Reconstructs a 32-byte Ed25519 pubkey from 4 cells into the 32-byte
* buffer at buf-addr, matching ZUSE-PUBKEY@'s own convention exactly:
* chunk i (0..3) is the 8-byte little-endian encoding of pubkey bytes
* [i*8 .. i*8+7] -- this is that packing's inverse, so a pubkey sent as
* 4 cells (see common:messaging.4th's SEND-ELEVATE-REQUEST) round-trips
* byte-exact regardless of any individual chunk's sign bit.
*/
static void mama_word_elevate_pubkey_unpack(VM *vm)
{
if (vm->dsp < 4) {
vm->error = 1;
return;
}
cell_t buf_addr = vm_pop(vm);
cell_t pk[4];
for (int i = 3; i >= 0; i--) pk[i] = vm_pop(vm);
uint8_t *buf = vm_ptr(vm, (vaddr_t)buf_addr);
if (!buf) {
vm->error = 1;
return;
}
for (int i = 0; i < 4; i++) {
uint64_t chunk = (uint64_t)pk[i];
for (int b = 0; b < 8; b++) {
buf[i * 8 + b] = (uint8_t)(chunk >> (8 * b));
}
}
}
/**
* @brief RUNCAP-TEST ( caddr u -- ok? rc )
* Diagnostic-only word (FABRIC-3.md §F.6/§F.18): calls
@@ -1415,6 +1504,9 @@ void register_mama_forth_words(VM *vm)
register_word(vm, "CAPSULE-RUN", mama_word_capsule_run);
register_word(vm, "MINT", mama_word_mint);
register_word(vm, "ZUSE-ELIGIBILITY-ADD", mama_word_zuse_eligibility_add);
register_word(vm, "ZUSE-ELIGIBLE?", mama_word_zuse_eligible_query);
register_word(vm, "NAME>XT", mama_word_name_to_xt);
register_word(vm, "ELEVATE-PUBKEY-UNPACK", mama_word_elevate_pubkey_unpack);
register_word(vm, "RUNCAP-TEST", mama_word_runcap_test);
register_word(vm, "PAIR-TEST", mama_word_pair_test);
register_word(vm, "MAMA-VM-ID", mama_word_mama_vm_id);
@@ -1448,6 +1540,9 @@ void register_mama_forth_words(VM *vm)
register_word(vm, "CAPSULE-RUN", mama_word_capsule_run);
register_word(vm, "MINT", mama_word_mint);
register_word(vm, "ZUSE-ELIGIBILITY-ADD", mama_word_zuse_eligibility_add);
register_word(vm, "ZUSE-ELIGIBLE?", mama_word_zuse_eligible_query);
register_word(vm, "NAME>XT", mama_word_name_to_xt);
register_word(vm, "ELEVATE-PUBKEY-UNPACK", mama_word_elevate_pubkey_unpack);
register_word(vm, "RUNCAP-TEST", mama_word_runcap_test);
register_word(vm, "PAIR-TEST", mama_word_pair_test);
register_word(vm, "MAMA-VM-ID", mama_word_mama_vm_id);