cross-domain slice 1: events as a fed-sx peer + allocate-a-post-to-a-calendar (LIVE)

The first cross-domain federated workflow — behaviors defined by TYPES, across domains.

- events.rose-ash.com is now a fed-sx PEER: a lib/host instance with SX_DOMAIN=events whose 'calendar'
  TYPE declares an on-allocate behavior. Replaces the Python events service (no strangler). serve.sh
  gates domain types/behaviors on SX_DOMAIN (blog=article publish/digest; events=calendar+allocate).
- DIRECTED cross-domain delivery: an activity with :to <peer-base> is delivered to that peer's inbox
  (∪ followers). The wire gains 'to'. So 'allocate' targets the events peer specifically.
- host/blog--allocate-activity/allocate! + POST /:slug/allocate?calendar=<id>; the events calendar
  type's allocate-link DAG (an execute-fold effect) fires on receipt.
- docker-compose: the sx_events service (own store, shared SX_FED_SECRET, externalnet for a future
  events.rose-ash.com Caddy route).

LIVE PROOF: publish 'Gig Night' on blog.rose-ash.com → POST /gig-night/allocate?calendar=main → the
events peer RECEIVES the directed, signed activity (/activities: 'allocate article gig-night') and
its calendar type's on-allocate behavior FIRES (/flows: 'linked gig-night'). blog 218/218, full
conformance green.

NEXT: events runs lib/events (real calendars/recurrence/ticketing); link event→post; shop
(lib/commerce) sells tickets — same federated, type-declared shape.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-02 20:25:37 +00:00
parent 43c085e8e8
commit 355bcbefdc
5 changed files with 85 additions and 32 deletions

View File

@@ -222,14 +222,33 @@ EPOCH=1
echo "(epoch $EPOCH)"
echo "(eval \"(host/blog--register-dag! \\\"blog-digest\\\" {:erl-flow \\\"blog_digest\\\" :needs (list \\\"effect\\\" \\\"branch\\\" \\\"suspend\\\")})\")"
EPOCH=$((EPOCH+1))
echo "(epoch $EPOCH)"
echo "(eval \"(host/blog--set-type-behavior! \\\"article\\\" (list {\\\"verb\\\" \\\"create\\\" \\\"type\\\" \\\"article\\\" \\\"dag\\\" \\\"publish\\\"} {\\\"verb\\\" \\\"update\\\" \\\"type\\\" \\\"article\\\" \\\"dag\\\" \\\"blog-digest\\\"}))\")"
EPOCH=$((EPOCH+1))
# Give the article type a "category" field so the edit form can set newsletter/urgent — the
# branch the durable kernel flow keys on (newsletter suspends until resumed).
echo "(epoch $EPOCH)"
echo "(eval \"(host/blog--set-fields! \\\"article\\\" (list {:name \\\"category\\\" :type \\\"text\\\"}))\")"
EPOCH=$((EPOCH+1))
# DOMAIN-SPECIFIC types + behaviors — behaviors are declared on TYPES; SX_DOMAIN picks which.
if [ "${SX_DOMAIN:-blog}" = "events" ]; then
# The EVENTS domain: a "calendar" type whose ON-ALLOCATE behavior links a post federated from
# blog. When a directed "allocate" activity arrives at /inbox, the calendar behavior fires the
# allocate-link DAG (an execute-fold effect). This is a cross-domain, type-declared reaction.
echo "(epoch $EPOCH)"
echo "(eval \"(host/blog-seed! \\\"calendar\\\" \\\"Calendar\\\" \\\"(article (h1 \\\\\\\"Calendar\\\\\\\") (p \\\\\\\"Posts allocated to this calendar.\\\\\\\"))\\\" \\\"published\\\")\")"
EPOCH=$((EPOCH+1))
echo "(epoch $EPOCH)"
echo "(eval \"(host/blog--register-dag! \\\"allocate-link\\\" (quote (effect linked (field \\\"slug\\\"))))\")"
EPOCH=$((EPOCH+1))
echo "(epoch $EPOCH)"
echo "(eval \"(host/blog--set-type-behavior! \\\"calendar\\\" (list {\\\"verb\\\" \\\"allocate\\\" \\\"type\\\" \\\"article\\\" \\\"dag\\\" \\\"allocate-link\\\"}))\")"
EPOCH=$((EPOCH+1))
else
# The BLOG domain: article create→publish (sync) + update→blog-digest (durable kernel) + a
# "category" field for the edit form; and point at the events peer for cross-domain allocate.
echo "(epoch $EPOCH)"
echo "(eval \"(host/blog--set-type-behavior! \\\"article\\\" (list {\\\"verb\\\" \\\"create\\\" \\\"type\\\" \\\"article\\\" \\\"dag\\\" \\\"publish\\\"} {\\\"verb\\\" \\\"update\\\" \\\"type\\\" \\\"article\\\" \\\"dag\\\" \\\"blog-digest\\\"}))\")"
EPOCH=$((EPOCH+1))
echo "(epoch $EPOCH)"
echo "(eval \"(host/blog--set-fields! \\\"article\\\" (list {:name \\\"category\\\" :type \\\"text\\\"}))\")"
EPOCH=$((EPOCH+1))
echo "(epoch $EPOCH)"
echo "(eval \"(host/blog--set-events-base! \\\"${SX_EVENTS_BASE:-}\\\")\")"
EPOCH=$((EPOCH+1))
fi
# P1: gather the types' declared :behavior bindings into the registry the trigger match
# consults (so publishing an article fires its declared on-publish DAG, runner derived).
echo "(epoch $EPOCH)"