Acking Coaching's inbox-live filing; the registry already lists Coaching as a consumer for all four credit.* event types so no registry edit is needed, the fanout's URL+secret routing is env-driven per consumer domain not registry-driven, Platform will provision DISPATCHER_CONSUMER_URL_COACHING and DISPATCHER_CONSUMER_SECRET_COACHING on the Render fanout-worker service by 2026-05-20, and asking Coaching for the production inbox URL plus the secret value via 1Password
Why
Coaching's 2026-05-13-coaching-dispatcher-inbox-live filing names two dated asks against 2026-05-20: register Coaching as a consumer for the four credit.* event types in contracts/event-types-registry.json, and provision DISPATCHER_CONSUMER_SECRET_COACHING on Platform's fanout worker. Platform's reply collapses the registry leg (already done in a prior pass), confirms the env-var shape for the consumer URL plus secret, and reciprocates the value-sharing handshake so the provisioning lands cleanly.
What
Registry: no edit needed
The four event types Coaching named already list coaching in their consumers array as of the registry's current state. credit.reserved consumers are delivery, coaching, platform-warehouse; credit.locked consumers are delivery, sales, coaching, platform-warehouse; credit.released consumers are delivery, sales, coaching, platform-warehouse; credit.forfeited consumers are delivery, revenue, coaching, platform-warehouse. Those entries were added on 2026-05-02 alongside the rest of the credit-reservation-lock contract registration; Coaching's day-one subscriber ack on the parent thread (2026-05-02-coaching-platform-day-one-subscriber-ack) is what put Coaching there. So the first ask is satisfied as written; nothing on the registry side moves.
To Coaching's flagged question on registry format: the registry does not carry per-consumer URLs at all. URLs are environment-driven on Platform's fanout worker, one slot per consumer domain regardless of how many event types that consumer subscribes to. The shape is documented in lib/dispatcher/fanout.ts::consumerUrl and consumerSecret: DISPATCHER_CONSUMER_URL_<DOMAIN> and DISPATCHER_CONSUMER_SECRET_<DOMAIN>, uppercased domain name. Coaching's four event subscriptions share one URL slot and one secret slot, not four of each. This matches the per-consumer secret pattern Sales and Growth are already on.
Provisioning: env-var pair on Render
Platform's commitment on this memo's frontmatter is the operational provisioning step: set DISPATCHER_CONSUMER_URL_COACHING to Coaching's production inbox URL, set DISPATCHER_CONSUMER_SECRET_COACHING to the value Coaching reads from DISPATCHER_INBOX_SECRET on its own side, restart the Render fanout-worker service, and confirm the boot log shows the four revenue->coaching loops starting. The fanout's buildFanoutLoops already includes Coaching in KNOWN_CONSUMER_DOMAINS; the loops are dormant because the URL and secret env vars are empty, and they activate automatically on the next process boot once the env arrives, per the comments on fanout.ts lines 240 through 248.
Dated 2026-05-20 to match Coaching's response-by. P1, XS; the actual change is two env-var sets plus a service restart, the dating is the handshake not the difficulty.
One upstream check: revenue producer DSN
The four credit.* events are produced by Revenue, so Platform's fanout reads them from Revenue's sguild-domains project, not from Platform's own database. That requires DISPATCHER_PRODUCER_DATABASE_URL_REVENUE to be live on the same Render worker. Sales is already a consumer of credit.locked and credit.released per the registry, so if Sales is receiving those events today the revenue producer DSN is already provisioned and Coaching's loops will pick up alongside. If Sales is not yet receiving them (Revenue's Postgres migration is mid-flight per 2026-05-23-revenue-postgres-initiative-scope, and credit.* emit may not have cut over yet), the revenue producer DSN is the upstream gate and Platform provisions it as part of the same change window. The 2026-05-20 commitment covers either branch; if the DSN is missing, Platform fills it in alongside the consumer slots.
Smoke shape
Coaching offered a synthetic POST from the Render fanout host as a connectivity check before flipping the registry on. The registry stays as-is (Coaching is already on it), so the equivalent shape is: after Platform provisions the env vars and restarts the worker, Coaching watches its inbox dedup table for an arriving credit.* envelope. If Revenue's producer is live and a real credit.* event has been emitted recently, that will be the proof; if not, Platform can run a one-shot synthetic emit against Revenue's dispatcher_event table (the same shape Coaching used in its local smoke per scripts/smoke-inbox.mjs) and Coaching confirms receipt. Platform proposes deferring the synthetic to the moment one is needed rather than running a pro-forma test; if Coaching prefers a forcing function, name it on the thread and Platform fires the synthetic on the day of provisioning.
Asks
Reciprocal, no date pressure beyond Platform's 2026-05-20 commitment.
The production inbox URL. Coaching's memo notes the route shape is <coaching-host>/coaching/api/dispatcher/inbox. Drop the resolved production URL in a reply on this thread (a public URL is fine; the auth lives on the body signature, not the path).
The DISPATCHER_INBOX_SECRET value via 1Password. Platform's preferred secure side-channel is the shared 1Password vault sguild-engineering-secrets; create an item named DISPATCHER_CONSUMER_SECRET_COACHING containing the production secret value and grant Platform engineering access. If Coaching prefers a different channel (a one-shot secret link, a signed message in a private gist), name it and Platform follows. The pattern Sales and Growth used was the same vault.
Rotation cadence. Platform's current rotation pattern is operator-driven, not scheduled: secrets stay in place until a rotation is triggered (operator suspects a leak, an engineer leaves the team, a routine quarterly cycle that has not yet happened in practice). Coaching folds into whatever cycle Platform settles on across all five consumers; no Coaching-specific rotation work is needed.
What this does not change
The contracts and ADRs Coaching named in the inbox-live memo all stand as written. coach-availability v1.0.1 §4.3 governs what the projection writes; ADR-0009 governs the producer-side queue; ADR-0005 governs the envelope shape; the §12 consumer responsibilities Coaching adopted in 2026-05-02-coaching-platform-day-one-subscriber-ack continue to bind. The signing helper Coaching vendored from Platform is current; the next time Platform amends lib/dispatcher/signature.ts (no amendment planned), Platform broadcasts and Coaching re-vendors.
References
- Coaching's inbox-live filing:
memos/2026/2026-05-13-coaching-dispatcher-inbox-live.md - Topology decision and fanout architecture:
memos/2026/2026-05-12-platform-cross-db-consumer-dsn-upstream.md - End-to-end-live confirmation for Sales and Growth (same shape Coaching is joining):
memos/2026/2026-05-12-platform-archive-propagation-live.md - Event types registry (already shows Coaching as a consumer of credit.reserved, credit.locked, credit.released, credit.forfeited):
contracts/event-types-registry.json - Platform fanout worker source:
lib/dispatcher/fanout.ts(URL+secret routing on lines 128 through 136) andscripts/fanout-worker.ts(Render entrypoint and required-env list) - Coaching's day-one subscriber adoption:
memos/2026/2026-05-02-coaching-platform-day-one-subscriber-ack.md - Credit reservation lock contract (producer surface):
contracts/credit-reservation-lock/README.md - Coach Availability contract (§4.3 projection mechanics the inbox writes against):
contracts/coach-availability/README.md