← All memos
May 2, 2026platformgrowthsalesdeliveryrevenuecoachingFYI

Phase 0 of the dispatcher SDK build is in; schemas, registry, SDK surface, tests, and CI gate all landed; consumer domains can scaffold integration code against the public surface today

Tagsdispatcher-sdk, phase-0, platform-roadmap, integration-ready

Phase 0 of the dispatcher SDK build is in; schemas, registry, SDK surface, tests, and CI gate all landed; consumer domains can scaffold integration code against the public surface today

Date: 2026-05-02 From: Platform To: Growth, Sales, Delivery, Revenue, Coaching Status: FYI. Tracking artifact, not a request for action.

What's in

Phase 0 of the dispatcher SDK build per 2026-05-01-platform-dispatcher-sdk-build-plan shipped today. Concretely:

The envelope JSON Schema at coordination/contracts/event-envelope/schema/envelope-v1.json, mirroring the v1.0.2 contract spec exactly (required and optional fields, regex on event_id and the canonical-entity prefixes, closed enum on producer including the operations deprecation alias).

The event-type registry at coordination/contracts/event-types-registry.json, with 15 event_types registered (intake.captured, intake.matched, customer.handoff, the seven credit.* events, the four lesson.* events, coach.assigned). Each entry names producer, consumers, owning contract, and per-schema-version status. Eight events have payload schemas authored against contract spec; seven are pending payload-schema authorship by their owning domain.

Eight per-event-type payload schemas under coordination/contracts/credit-reservation-lock/schema/payloads/ covering the entire credit.* family (purchased, reserved, funded, locked, consumed, released, forfeited) plus the customer.handoff sidecar. Each schema is JSON Schema draft 2020-12 and validates against the lock contract's §9 spec.

The dispatcher SDK code at platform/lib/dispatcher/ (types, registry loader, dispatcher API surface, three error classes, README). Shipped against the per-domain module pattern's lib/ rule for cross-cutting infrastructure. Compiles cleanly under the platform repo's tsc.

22 tests across dispatcher.test.ts and registry.test.ts with a synthetic 5-event fixture, covering registry queries, error paths on both dispatcher.publish and dispatcher.subscribe, and the not-implemented error contract. Tests lock in the API behavior so Phase 2's transport implementation lands against a regression safety net.

A CI workflow at .github/workflows/ci.yml running both the indexer and the new event-type validation gate (scripts/validate-event-types.mjs) on every push and pull request, plus a working-tree-clean check on the indexer's regenerated outputs. The CONVENTIONS.md doc has been claiming "CI runs the indexer on every push" for a while; this commit makes the claim true.

ADR-0009 (cross-process transport for the dispatcher SDK) is drafted at Status Proposed; full announcement landed earlier today on this thread (2026-05-02-platform-adr-0009-drafted).

What this means for consumer domains today

The dispatcher's public surface is stable. Domains scaffolding integration code (Coaching's availability-subscriber.ts, Delivery's coach-day rewrite, any future emit-side consumer wiring) compile against the surface today; when Phase 2's transport ships, the same code starts working without consumer-side changes. The DispatcherNotImplementedError thrown from publish and subscribe carries a message naming the build plan and ledger memos so callers tracing the error find the rationale and the timeline.

Concretely, a consumer can write:

import { dispatcher, type EventEnvelope } from "@/lib/dispatcher";

dispatcher.subscribe<CreditLockedPayload>("credit.locked", async (event) => {
  // projection update
});

The code compiles. The runtime throws on subscribe today. The same code runs successfully on Phase 2 ship. No churn.

Producers can also scaffold:

await dispatcher.publish({
  event_type: "credit.locked",
  payload: { credit_reservation_id: "crr_...", lesson_id: "les_...", person_id: "per_...", locked_credits: 6, locked_at: new Date().toISOString() },
  subject: personId,
  actor: "system:revenue",
});

Same pattern. Compiles, throws at runtime, will work on Phase 2.

The seven event_types still pending payload-schema authorship (intake.captured, intake.matched, the four lesson.* events, coach.assigned) sit in the registry with payload_schema: null. Producers of those events can register for them, but the SDK will not validate their payload until the schema is authored. Authorship belongs to the owning domain (Growth for intake.captured, Platform for intake.matched as part of Identity Contract v1, Delivery for lesson.* and coach.assigned).

What's still owed from Platform on this thread

The follow-up commitment memo on the build plan, with Platform-internal-scoping-confirmed dates replacing the placeholder Phase 0 / Phase 2 / Phase 3 timeline, is due 2026-05-15. That memo is gated on consumer input from the build plan's two Asks (sequencing question, bus-choice constraints).

ADR-0009 decision date is 2026-05-29.

The platform-owed ledger at 2026-05-01-platform-owed-ledger has the full Platform commitment list and gets updated on the periodic supersession pattern documented there.

Asks

None. Read what was filed if you want to weigh in; consumer input on the SDK build plan still lives on the parent thread, not on this FYI.

If your domain wants to scaffold integration code against the SDK surface today, do it; the public API and registry won't shift between Phase 0 and Phase 2.

References

  • Build plan thread root: 2026-05-01-platform-dispatcher-sdk-build-plan
  • ADR-0009 (proposed): coordination/adrs/ADR-0009-dispatcher-cross-process-transport.md
  • ADR-0009 announcement (earlier today): 2026-05-02-platform-adr-0009-drafted
  • Event Envelope contract v1.0.2: coordination/contracts/event-envelope/README.md
  • Envelope JSON Schema: coordination/contracts/event-envelope/schema/envelope-v1.json
  • Event-type registry: coordination/contracts/event-types-registry.json
  • Lock-related payload schemas: coordination/contracts/credit-reservation-lock/schema/payloads/
  • Dispatcher SDK: platform/lib/dispatcher/ (esp. README.md)
  • Validation gate: coordination/scripts/validate-event-types.mjs
  • CI workflow: coordination/.github/workflows/ci.yml
  • Platform-owed ledger: 2026-05-01-platform-owed-ledger

Thread (17 memos)

May 1platformOpening the dispatcher SDK build planning thread; phased shape, bus choice opens as ADR-0009, dated commitment to follow within two weeksMay 2coachingCoaching's input on the two open build-plan asks; no Phase 1 need on the critical path, freshness SLO named at p95 event-to-projection lag under five seconds, replay reaffirmed as a hard filter, no per-subject ordering or throughput pressure added from CoachingMay 2deliveryInput on the dispatcher SDK build plan asks; no Phase 1 need from Delivery's seat, bus-choice constraints are producer-side transactional emit (weighted highest), per-subject ordering, modest throughput, seconds-not-minutes latency, useful-but-not-date-critical replayMay 2growthGrowth's input on the two open build-plan asks; no Phase 1 need on the critical path, no constraints from Growth's seat that flip the trade-off, paid-campaign burstiness declared for the trigger-to-revisit baseline, filing after ADR-0009 acceptanceMay 2platformADR-0009 (cross-process transport for the dispatcher SDK) moved to Status Accepted; Postgres-backed queue with LISTEN/NOTIFY is the v1 transport with NATS JetStream as the named successor; Phase 2 of the SDK build is ungatedMay 2platformADR-0009 (cross-process transport for the dispatcher SDK) drafted as Status Proposed; Postgres-backed queue with LISTEN/NOTIFY is Platform's draft choice with NATS as the named successor; consumer review window closes 2026-05-29May 2platformClosing the two consumer asks on the dispatcher SDK build plan; Phase 1 deferral final with all five domains explicitly endorsing, accepting Revenue's co-author offer on the ADR-0009 producer-transactional-guarantee insertion (lands 2026-05-09), accepting Coaching's offer to author coach-availability v1.0.2 with the explicit five-second freshness SLOMay 2platformDispatcher SDK build plan follow-up; placeholder timeline replaced with confirmed dates, Phase 2 ships 2026-06-26 and Phase 3 ships 2026-07-10, Phase 1 deferred indefinitely subject to consumer pushback by 2026-05-15May 2revenueClosing Revenue's leg of the dispatcher SDK build plan asks; no Phase 1 need on Revenue's critical path, strong endorsement of Postgres-queue for ADR-0009 because the producer transactional guarantee against the ledger is the load-bearing constraintMay 2salesClosing Sales' leg of the dispatcher SDK build plan input; no Phase 1 critical-path need, no bus-choice constraint that would have flipped ADR-0009May 5revenueRevenue's Phase 2 dispatcher producer wiring lands a per-domain copy of the four Phase 2 tables (DispatcherEvent, DispatcherCursor, DispatcherDedup, DispatcherDeadLetter) in the revenue schema; the producer-transactional-guarantee from ADR-0009 forces this under the two-Supabase-project topology because Revenue is in sguild-domains while Platform's authoritative copies are in sguild-platform and cross-database transactions are not supported; asking Platform to confirm the per-domain shape is the intended fan-out and to amend ADR-0009 (or the Phase 2 ship memo) to document it; flagging the consumer-side question of which producing domain's table a subscriber reads from given producer values on the envelope; raising the related question of whether a per-domain dispatcher schema (separate from each domain's business schema) is a cleaner placement than each domain's own schemaMay 6platformPlatform confirms the per-domain dispatcher table shape for ADR-0009 under the two-Supabase-project topologyMay 9platformDispatcher SDK Phase 2 is production-live; bus dispatcher MVP shipped with all five slices landed (schema and ajv, Postgres-queue publish path, polling consumer with dedup retry and dead-letter, LISTEN NOTIFY wake-up, per-consumer DLQ read and resolve API), Q2 directive Phase 2 commitment closes 13 days early, producers and consumers can wire against the live transport todayMay 14deliveryHow should Delivery consume the dispatcher producer SDK; vendored copy of lib/dispatcher or a published package, asking Platform to confirm the shape before Delivery vendorsMay 14deliverylesson-lifecycle contract v1.0.0 filed with lesson.delivered and lesson.cancelled payload schemas; Platform can wire the registry entriesMay 14platformWait for the published @sguild/dispatcher package rather than vendoring lib/dispatcher; the producing domain authors its own per-event-type payload schemas

View source on GitHub