Files
rose-ash/lib/host/ta.sx
giles 39e5f906f2 host TA: the fed-sx transport adapter — federation loop proven at the seam
lib/host/ta.sx — a seam transport {:emit :deliver} over a DIRECTIONAL wire (out = outbox→followers,
in = inbox←follows). The transport is the SERIALIZATION boundary: activities cross the wire as
SX-source strings (host/ta--serialize/deserialize map the keyword-keyed activity ↔ a flat
string-keyed wire form of the P2 activity fields). host/ta--make-transport(out-wire, in-wire) +
host/ta--make-mem-wire (an in-memory directional queue for tests).

Proven (ta 5/5): content + relation activities round-trip through the wire; the FEDERATION LOOP —
instance A emits an activity → the wire carries it → instance B's behavior/pump delivers + processes
it → B's engine fires ITS behavior on A's activity; DIRECTIONAL (B re-emits to its own outbox, not
back into the inbox — no loop). 'Everything works over fed-sx', proven at the seam.

TA-live (deferred, same shape as RA-live): swap the mem-wire for the real next/ delivery wire —
needs a PERSISTENT next/ kernel (gen_servers don't survive across erlang-eval-ast calls) + the ACTOR
MODEL (peer_actors/follower_graph decide who the out-wire delivers to) + pushing /activities onto it.

Full host conformance green (+ta 5).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 16:48:30 +00:00

42 lines
2.4 KiB
Plaintext

;; lib/host/ta.sx — TA: the fed-sx TRANSPORT ADAPTER (plans/business-logic-fed-flows.md). A seam
;; transport {:emit :deliver} (behavior.sx) over a directional WIRE, so an activity emitted on one
;; instance reaches another instance's engine and fires ITS behaviors — federation.
;;
;; The transport is the SERIALIZATION boundary: activities cross the wire as SX-source strings
;; (string-keyed for persist/wire safety, reconstructed on arrival). The wire is dumb string
;; transport {:send :recv}; the REAL wire is next/ delivery (outbox→peers / inbox), DEFERRED to
;; TA-live (same persistent-kernel prerequisite as RA-live); a mem-wire drives the tests.
;;
;; DIRECTIONAL: :emit → an OUT wire (this instance's outbox → followers); :deliver → an IN wire
;; (its inbox ← those it follows). Separate channels, so processing a delivered activity (which the
;; seam re-emits to log it) goes to THIS instance's outbox, NOT back into the inbox — no loop.
;; canonical activity (keyword-keyed) <-> the flat string-keyed WIRE form (persist/serialise-safe).
(define host/ta--activity->wire
(fn (a)
{"verb" (get a :verb) "actor" (get a :actor) "object" (get a :object)
"type" (get a :object-type) "slug" (get a :slug) "category" (get a :category)
"relation" (get a :relation) "target" (get a :target)
"delta" (get a :delta) "id" (get a :id)}))
(define host/ta--wire->activity
(fn (w)
{:verb (get w "verb") :actor (get w "actor") :object (get w "object")
:object-type (get w "type") :slug (get w "slug") :category (get w "category")
:relation (get w "relation") :target (get w "target")
:delta (get w "delta") :id (get w "id")}))
(define host/ta--serialize (fn (a) (serialize (host/ta--activity->wire a))))
(define host/ta--deserialize (fn (s) (host/ta--wire->activity (parse-safe s))))
;; the transport: emit serialises to the OUT wire; deliver deserialises from the IN wire.
(define host/ta--make-transport
(fn (out-wire in-wire)
{:emit (fn (a) ((get out-wire :send) (host/ta--serialize a)))
:deliver (fn () (map host/ta--deserialize ((get in-wire :recv))))}))
;; an in-memory directional wire {:send :recv} (a captured mutable queue) — the test substrate.
(define host/ta--make-mem-wire
(fn ()
(let ((q (list)))
{:send (fn (s) (set! q (concat q (list s))))
:recv (fn () (let ((batch q)) (begin (set! q (list)) batch)))})))