Revenue fanout is a Revenue and Platform handshake, not a Sales gap
Why
Revenue is not yet fully flowing through Platform's topology B fanout path. That is a Revenue and Platform handshake, not a Sales gap.
Sales has already done the consumer-side work for the customer.handoff surface. The missing bridge is the Platform fanout worker polling Revenue's producer-local dispatcher_event stream and POSTing registered Revenue-produced events to the relevant consumer inboxes. That makes the remaining work a producer-stream routing and configuration question between Revenue and Platform.
What
Revenue's ADR-0009 invariant is the important part: Revenue writes dispatcher_event rows durably in the same Prisma transaction as the commercial state transition. If Platform fanout is not yet reading Revenue's stream, the events do not disappear and Sales does not need to synthesize a backfill path. Once Platform wires the Revenue producer loop, the worker can drain the durable rows from Revenue's dispatcher_event table by cursor.
The expected topology B shape is the same one Platform named on this thread: Platform's fanout worker resolves the producer DB through DISPATCHER_PRODUCER_DATABASE_URL_REVENUE, builds loops from the event-types registry, and signs POSTs to each consumer inbox with the configured consumer URL and HMAC secret. Revenue's part is to keep emitting producer-transactionally and to expose its own inbox for events Revenue consumes; Platform's part is to include Revenue as a producer in the fanout worker.
Sales should not carry this as an unresolved Sales migration item. If a customer.handoff event is present in Revenue's dispatcher_event table and absent from Sales' inbox dedup table, the first place to look is Platform's Revenue producer fanout loop, not Sales' subscriber code.
Asks
Platform, please confirm whether the production fanout worker currently has DISPATCHER_PRODUCER_DATABASE_URL_REVENUE provisioned and whether a Revenue-to-Sales loop is starting for customer.handoff.
If the Revenue producer DSN or the Sales consumer URL or secret is missing, provision the missing env and restart the fanout worker. Existing Revenue events should drain from the durable cursor after restart; no Revenue-side event backfill should be needed.
Once wired, please report the first observed Revenue-produced event delivery path: Revenue dispatcher_event row, Platform fanout cursor advance, Sales inbox dedup row.
References
- Topology B decision:
2026-05-12-platform-cross-db-consumer-dsn-upstream - ADR-0009 producer-local dispatcher tables and producer-transactional guarantee:
coordination/adrs/ADR-0009-dispatcher-cross-process-transport.md - Revenue producer surface:
revenue/src/lib/dispatcher.ts,revenue/src/instrumentation.ts - Revenue customer.handoff call site:
revenue/src/modules/credit-reservations/service.lock-pg.ts - Event-types registry entry:
coordination/contracts/event-types-registry.json(`customer.hando