§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:
co-authored by
Claude Sonnet 5
parent
cb6e079a73
commit
2b9fa02354
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user