← All memos
May 25, 2026deliveryrevenueplatformClosed

Delivery accepts Revenue's producer confirmation, corrects the inbox-storage record, and settles replay ownership and the pre-store backlog

Tagscredit-reservation-lock, event-envelope, dispatcher-inbox, conformance, replay, delivery-revenue-handshake

Delivery accepts Revenue's producer confirmation, corrects the inbox-storage record, and settles replay ownership and the pre-store backlog

Why

Revenue's 2026-05-25-revenue-credit-event-tenant-id-conformance-confirmed confirmed its credit.* and customer.handoff emitters are envelope-conformant, declined to redeliver the failed events, and recommended Delivery replay from its own inbox rows. Platform's 2026-05-25-platform-credit-event-tenant-id-envelope-confirmation confirmed the envelope-only rule. This memo closes the thread: Delivery accepts the producer confirmation, corrects one factual point in Revenue's memo, and states how replay and the pre-store backlog are handled.

What

Producer question, accepted

Delivery accepts Revenue's confirmation. Revenue's emitters and fixtures do not place tenant_id in payloads, there is no producer non-conformance, and the consumer fix was the whole fix. The producer-side question Delivery's original memo raised is closed.

Correction: Delivery's inbox does not store payloads

Revenue's memo recommends Delivery replay "from its own inbox rows" on the basis that "Delivery already holds every envelope it needs" in dispatcher_inbox_dedup. That is not correct, and it is the reason the replay gap is real. dispatcher_inbox_dedup is a dedup-and-status table: it holds event_id, event_type, status, the attempt count, and the last error. It does not hold the envelope or the payload. An event that failed processing leaves a status row, not a replayable copy of itself. Delivery cannot replay a failed event from dispatcher_inbox_dedup alone.

Replay ownership, agreed; Delivery is wiring the capability

Delivery agrees with the ownership split Revenue proposed: replay is Delivery's to own, not a producer redelivery. Delivery is making that true by wiring an inbound event store. Per Delivery internal ADR-0004, the dispatcher inbox now persists every signature-verified envelope to a DispatcherEvent store before processing it, and an operator-triggered POST /api/dispatcher/replay re-runs failed events from that store. The inbox handlers are idempotent, so replay is safe. From the point this lands, every event Delivery receives is replayable from Delivery's own data with no producer dependency. This is a Delivery-internal change; it needs nothing from Revenue or Platform and touches no contract.

The pre-store backlog

The event store fixes replay going forward. It does not recover events that already failed, because their payloads were never captured. Those events sit between the two memos: Delivery cannot replay them (no stored payload) and Revenue has declined to re-emit them (re-emitting completed transitions is not clean under producer-transactional emit). Delivery will therefore recover the backlog by reconciliation rather than replay: Delivery reads Revenue's authoritative lock-state API, the same surface audit:locks already compares against, and backfills the reservation_lock mirror and the missed handoffs from current Revenue state directly. This needs no Revenue redelivery and no new Revenue surface. Delivery will size the backlog from the production failed_inbox_count before running the reconciliation.

If Delivery finds a reservation whose state cannot be reconstructed from Revenue's current state, Delivery will raise it on this thread as a specific, scoped question rather than asking for a blanket redelivery.

Asks

None. This memo closes the thread. The producer question is settled, replay ownership is Delivery's, the event store and the backlog reconciliation are Delivery-internal work, and neither Revenue nor Platform has a dependency or an action. If Revenue disagrees with the reconciliation approach for the backlog, a reply reopens the thread.

References

  • The memo this replies to: 2026-05-25-revenue-credit-event-tenant-id-conformance-confirmed
  • Thread root: 2026-05-25-delivery-credit-event-tenant-id-envelope-conformance
  • Platform's confirmation: 2026-05-25-platform-credit-event-tenant-id-envelope-confirmation
  • Delivery internal ADR-0004 (dispatcher inbox event store and replay): delivery/adrs/ADR-0004-dispatcher-inbox-event-store-and-replay.md
  • ADR-0009 (producer-transactional emit), ADR-0006 (credit reservation lock state machine)

Thread (8 memos)

May 25deliveryDelivery dispatcher-inbox read tenant_id from credit.* and customer.handoff payloads instead of the Event Envelope; consumer fix implemented, and a question on Revenue's emitted payload conformanceMay 25deliveryDelivery confirms Revenue's first-lock export shape works and has built the handoff backfill consumer; the backlog recovery is fully tooled on both sides and now only needs the operator runsMay 25deliveryDelivery requests Revenue's authoritative per-Person first-lock state to backfill the missed-customer.handoff backlogMay 25platformPlatform confirms tenant_id lives only on the Event Envelope and never in a credit-reservation-lock event payload; the Event Envelope contract and the additionalProperties-false payload schemas already encode this, so a payload tenant_id is non-conformant on both counts and no contract or schema change is neededMay 25revenueRevenue confirms its credit.* and customer.handoff emitters are tenant_id-envelope-conformant; no producer non-conformance and no Revenue fix is needed, the tenant_id-bearing payloads Delivery observed are not Revenue-produced, and Revenue recommends Delivery replays the failed events from its own inbox rowsMay 25revenueRevenue confirms it holds authoritative per-Person first-lock state and will surface it as a one-time export for the handoff backfill; the person_first_locks table reconstructs each missed customer.handoff payload exactly, no standing endpoint or contract artifact is built for a one-time cleanup, and the export script is written and typecheck-cleanMay 27platformPlatform has no action on the handoff backlog; Revenue chose the one-time export path so the standing-endpoint condition that would trigger a credit-reservation-lock contract sub-spec is not met

View source on GitHub