ACK/NACK and private-channel negotiation -- FABRIC-3.6.md task 3.6
Extracted sk_hermes_send_one() from sk_hermes_publish()'s own
per-subscriber body -- one code path for both point-to-point and
fan-out delivery, so the ledger can never diverge between them.
Point-to-point addressing turned out to be load-bearing, not
incidental: sk_hermes_publish()'s fan-out sets msg->to to whichever
member it is iterating, so a negotiation message "published" to the
common channel would spuriously reach every member, not just the real
target (checked with advisor() before building the naive version).
"Over the common channel" means every VM is reachable from birth (task
3.2), not that the exchange itself fans out -- messaging.4th's own
CH-REQUEST carried an explicit `to` for the same reason.
sk_hermes_channel_request/respond/close build the mechanics: request ->
grant (creates a private channel, subscribes both parties, sends
CH_GRANT + one ACK) or NACK ("a deny is a NACK", SXLV.1 -- no separate
type); close authorized by membership alone. The grant/deny decision is
a plain caller-supplied `approved` bool -- task 3.7 replaces the call
site that produces it with a real ACL.4th query, not this signature.
Self-test covers the task's own three checks plus a sibling advisor()
flagged: an approved respond() whose channel creation itself fails
(table exhausted) must still fall through to NACK, not a silent false
grant or half-open channel -- verified by exhausting the whole channel
table and confirming the fallback.
Bug found and fixed before this was called done: the first draft
dropped a message via pending_pop() alone, without releasing it first,
leaking its Stadium heat and failing the self-test's own ledger
baseline check (logs/20260922-065946/amd64/, kept as audit trail).
Fixed and re-verified PASS on all three architectures.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
8a2ee0fdad
commit
205a49ecd0
+42
-1
@@ -938,11 +938,52 @@ ruling]** cannot be written precisely until Captain Bob settles the named sub-it
|
||||
byte-exact against the original. Ledger audit and `stadium_conserved()` hold before and
|
||||
after. `dict_hash` for Hermes/Hestia unmoved and identical across all three architectures
|
||||
(this task touches no capsule).
|
||||
- [ ] **3.6** — **ACK/NACK and private-channel negotiation** (B1) **[needs ruling 3.0a]**.
|
||||
- [x] **3.6** — **ACK/NACK and private-channel negotiation** (B1) **[needs ruling 3.0a]**.
|
||||
`request` → `grant`/`deny` on the common channel; a grant creates a private topic;
|
||||
close tears it down. ACK/NACK are message types on the existing allocator.
|
||||
*Check:* grant path, deny path, close path; heat conserved (ledger + `stadium_conserved()`)
|
||||
across all three; a NACK'd request leaves no topic behind.
|
||||
2026-09-22 · `logs/20260922-070455/amd64/`, `logs/20260922-071004/aarch64/`,
|
||||
`logs/20260922-071525/riscv64/` (the successful runs; `logs/20260922-065946/amd64/` is a
|
||||
genuine first attempt that hit a real bug, caught by the self-test itself before this task
|
||||
was called done -- kept, not deleted, per the never-delete-logs convention) — all three
|
||||
reach `[zuse@Hera] ok>`, zero `UNKNOWN WORD`, `mkcapsule --lint capsules/` clean (38 files,
|
||||
0 violations, unchanged -- no capsule touched).
|
||||
**Design finding (checked with `advisor()`):** the ruling's "over the common channel"
|
||||
cannot mean `sk_hermes_publish()`-style fan-out -- that sets `msg->to` to whichever member
|
||||
it is iterating, so every common-channel member would receive its own copy of a request
|
||||
believing it was the addressee, drawing heat for a message only one VM should ever see.
|
||||
`messaging.4th`'s own `CH-REQUEST ( type from to paddr plen -- )` carried an explicit `to`
|
||||
for the same reason -- point-to-point addressing was in the original protocol from the
|
||||
start; "over the common channel" means every VM is reachable from birth (task 3.2), not
|
||||
that the exchange itself fans out. Extracted `sk_hermes_send_one()` from
|
||||
`sk_hermes_publish()`'s own per-subscriber body (alloc/set-fields/find-or-create-queue/
|
||||
push/roll-back-on-refusal) so both callers share one code path and the ledger can never
|
||||
diverge between them -- `sk_hermes_publish()` now just loops it per member.
|
||||
Message types: `CH_REQUEST`/`CH_GRANT`/`ACK`/`NACK`/`CH_CLOSE`, chosen clear of
|
||||
`messaging.4th`'s own live/reserved type space (2/3/4/7/8/9/253/255), not itself a ruling.
|
||||
"A deny is a NACK" (SXLV.1) -- no separate `CH_DENY` type. ACK sent once, for the ruled
|
||||
channel-open+delivery moment. The grant/deny *decision* is a plain caller-supplied
|
||||
`approved` bool (named for what it is, not `allow`) -- task 3.7 replaces the call site that
|
||||
produces it with a real `ACL.4th` query, not this function's signature. Close authority is
|
||||
membership alone (either party may close a channel it belongs to) -- narrowest defensible
|
||||
rule given both are already trusted members, not itself a ruling.
|
||||
**Sibling case `advisor()` flagged as the one a green boot would hide**, beyond the task's
|
||||
own three checks: an `approved==1` respond() whose channel creation itself fails (table
|
||||
exhausted) must still fall through to NACK, not a silent false grant or a half-open
|
||||
channel -- self-test exhausts the entire channel table, confirms the fallback, then
|
||||
restores capacity.
|
||||
**Bug found and fixed before this was called done:** the first self-test draft
|
||||
(`logs/20260922-065946/amd64/`, `FAIL`) called `sk_hermes_pending_pop()` directly on the
|
||||
deny path's dropped request copy without releasing it first -- `pending_pop()` only
|
||||
advances the queue per its own doc comment, so the message's Stadium heat was never
|
||||
returned, leaking held heat and failing the self-test's own `held0`/`held1` baseline check.
|
||||
Fixed to peek+release+pop, matching every other drain in the same self-test; re-verified
|
||||
PASS on all three architectures after the fix.
|
||||
`dict_hash` for Hermes/Hestia unmoved and identical across all three architectures (this
|
||||
task touches no capsule). Artemis's own `dict_hash` differs run-to-run as already
|
||||
documented (task 3.1's own finding) -- shared `disk/artemis.img` state accumulated across
|
||||
this session's many prior boots, not an architecture divergence.
|
||||
- [ ] **3.7** — **Channel-open policy hook** **[needs ruling 3.0b]**. Kernel-Hermes asks
|
||||
`ACL.4th`, never decides in C, never gates on `zuse_session`. *Check:* a denied open is
|
||||
denied by FORTH policy, with the C unchanged when the policy changes.
|
||||
|
||||
Reference in New Issue
Block a user