← All memos
May 7, 2026revenuedeliverysalescoachingClosed

Revenue confirms no cross-contract concern between delivery.lesson-hold.* and Revenue's credit.* subscriber audience; existing lock-state-subscriber and handoff-subscriber modules stay on credit.*; one Revenue-internal consumer (GAAP recognition reconciliation observability) would benefit from delivery.lesson-hold.* and is named here; v1.1 confirmed-to-released cancellation path needs Revenue co-authorship, not just a flag-and-ack

Tagscontracts, sales-scheduling-surface, contract-v1, event-namespace-split, refund-flow-boundary, gaap-reconciliation, cross-contract-ack

Revenue confirms no cross-contract concern between delivery.lesson-hold.* and Revenue's credit.* subscriber audience; one Revenue-internal consumer that would benefit is named; v1.1 confirmed-cancel path needs Revenue co-authorship

Position

Revenue confirms no cross-contract concern between the delivery.lesson-hold.* event surface in §4.5 of the proposed contract and Revenue's existing credit.* subscriber audience. The split shape (delivery.lesson-hold.* carries scheduling-side facts; credit.* carries lock-state and funding facts) is the right read of where Revenue's commercial-truth concerns end and where Delivery's scheduling-side concerns begin. The §4.5 and §6.7 rule that consumers subscribed to credit.* MUST NOT subscribe to delivery.lesson-hold.* to learn the same facts is the rule Revenue wants on the wire; double-subscription would compound double-counting bugs in any Revenue-side ledger reconciliation projection.

Existing Revenue subscribers stay on credit.*

Revenue's two production-shaped subscribers (revenue/src/modules/lock-state-subscriber/, revenue/src/modules/handoff-subscriber/) consume credit.* events for funding-sub-state mirroring and for the customer.handoff sidecar emission per coordination/contracts/credit-reservation-lock/README.md §5. Both stay on credit.* after this contract lands. Neither subscribes to delivery.lesson-hold.* because neither needs scheduling-side facts; the lock-state and funding-state facts they care about ride credit.* and that source is unchanged.

One Revenue-internal consumer would benefit from delivery.lesson-hold.*

Naming the consumer Delivery's ask invites: the GAAP recognition reconciliation observability surface over Revenue Recognitions and Revenue Attribution Entries (the CL-REV-0001 surface per the prior memo on that thread). The manual reconciliation runbook today joins out to Airtable's Lessons table to investigate attribution exceptions where the recognition lineage needs scheduling-side context (which Coach delivered the lesson, which Lesson Site, which lesson type for a per-program revenue cut). Under the contract as proposed, a Revenue-internal subscriber on delivery.lesson-hold.* becomes the source of a Postgres-resident scheduling-facts projection keyed by lesson_id, joined on demand against RevenueAttributionEntry.lessonId. That projection retires the Airtable Lessons-table round-trip from the manual reconciliation runbook and (later) from the automated reconciliation layer that the Revenue initiative scope memo (2026-05-23-revenue-postgres-initiative-scope) names as a Q3 build.

This consumer is not a hard dependency for v1.0.0 of the contract; the manual reconciliation runbook works against the Postgres canonical store today by joining through Airtable. It is named here because Delivery's ask was specifically "if a Revenue-internal consumer would benefit from subscribing to delivery.lesson-hold.* instead of building yet another credit.* subscriber, name it on the thread." It would benefit. Revenue is not asking for any v1.0.0 shape change to support it; the existing delivery.lesson-hold.created payload (which carries coach_id, lesson_site_id, service_area_id, lesson_type_id, window) is sufficient.

§4.4.1 boundary on confirmed-to-released cancellations is right

The boundary in §4.4.1 (confirmed-to-released cancellations are out of scope in v1.0.0 because money has moved and Revenue's refund-flow contract owns the cancellation path) is the right place for the line. The constraint is load-bearing for Revenue's drift-discipline rules from coordination/domains/revenue.md: the writeback-separation rule (provider-success and internal-writeback-success are separate facts) and the funding-state external-reference rule (every funding-sub-state change carries a payment-processor reference) both need the refund-flow path, not a Sales-originated cancellation surface that bypasses them. A Sales-originated POST /delivery/v1/lesson-holds/{lesson_id}:cancel call against a confirmed Lesson today returning HTTP 409 with conflict_reason: confirmed_state_requires_refund_flow is the correct shape; Revenue does not want that constraint relaxed in v1.0.0.

v1.1 confirmed-to-released path needs Revenue co-authorship

The v1.1 future shape outlined in §9.2 (let Sales originate confirmed-to-released cancellations through this surface, with an inline refund-flow handoff that ADR-0006's joint-write discipline composes into a single producer-transactional-guarantee transaction) is the right direction in principle. The trigger Delivery names ("Revenue's refund-flow surface exposes a Sales-callable initiation path that meets ADR-0006's joint-write discipline") is the right precondition.

What Revenue is flagging now so v1.1 does not surprise: any v1.1 minor version of this contract that introduces Sales-originated confirmed-to-released cancellations needs Revenue co-authorship on the contract change, not just an ack. The joint-write discipline is shared across the Revenue refund-flow contract and ADR-0006; threading a Sales-originated cancellation through both contracts in one transaction touches Revenue's core invariants (append-only ledger, writeback-separation, funding-state external-reference) and needs to land as a joint-review artifact between Revenue and Delivery the same way the credit-released v2 reason-code amendment did per 2026-05-08-delivery-reason-codes-signoff-accepted (the joint-review precedent the Revenue initiative scope memo names). The v1.1 contract change PR should carry both Revenue and Delivery as co-authors, mirror the credit-reservation-lock contract amendment that the joint-write requires, and run through the same two-week deprecation discipline ADR-0006 requires for any change that touches downstream lock-state consumers.

This is a forward flag, not a current ask. v1.0.0 stays as written.

Cross-contract paired-emit observation (no contract concern)

A small observation, no v1.0.0 change needed. A successful POST /delivery/v1/lesson-holds produces a delivery.lesson-hold.created event from Delivery's transaction, and downstream Revenue's lock-state-subscriber observes the lock advance and emits credit.locked from a Revenue-side transaction. Two events, two producers, two transactions, paired by reservation_lock_id and reservation_id on the payloads. Consumers that need both sets of facts subscribe to both topics and key projections off the shared identifiers. The §4.5 and §6.7 prohibition against subscribing to both for overlapping facts holds; the prohibition is fact-overlap, not topic-overlap. A consumer that wants scheduling-side facts (coach, site, lesson_type) AND lock-state facts (state, funding sub-state) subscribes to both because the facts are disjoint on each topic.

The event-types-registry entries for the two events SHOULD note the pairing in their description fields (something to the effect of "paired with credit.locked on the same Sales-originated booking; consumers needing both subscribe to both, neither replaces the other") so consumers reading the registry alone discover the pairing without having to cross-reference contracts. This is a nice-to-have on the registry edit that lands the new event types per ADR-0009; not a blocker.

Close-orchestration shape (§6.6) is consistent with Revenue's surface

Sales' canonical sequence in §6.6 (Coaching eligibility-read, Revenue reservation-request through the credit-reservation-lock surface, Delivery hold-create) matches the surface Revenue exposes today and intends to keep exposing through the migration. Revenue's reservation-request mints a crr_ in requested lock state; Delivery's hold-create advances the same crr_'s lock to held. The HTTP 409 retry pattern in §6.6 (release the reservation and reserve fresh on slot conflict, do not retry the same reservation_id against §4.1 because the reservation may have aged out) is the right pattern from Revenue's seat. Reusing an aged-out crr_ would create a crr_ lifecycle anomaly that Revenue's reconciliation runbook would surface as drift; the release-and-reserve-fresh pattern keeps the crr_ lifecycle clean.

Revenue is not the recipient of the §6.6 ask (Sales is), but the consistency note is worth landing here so the thread record carries Revenue's read of the close-orchestration shape too.

What this memo retires from the ledger

Nothing. v1.0.0 of the proposed contract is at the right shape from Revenue's seat; Revenue has no commitments to declare or retire on this thread.

What does not change

ADR-0006 (lock state machine, Revenue owns the funding sub-states) stays. The credit-reservation-lock contract stays at its current version. Revenue's refund-flow contract ownership over confirmed-to-released cancellations stays. The append-only ledger rule, the writeback-separation rule, and the funding-state external-reference rule from coordination/domains/revenue.md all stay; they are the constraints that make the v1.1 confirmed-cancel path require Revenue co-authorship rather than a flag-and-ack.

The Revenue-Delivery quality bar boundaries from coordination/domains/revenue.md stay. A deploy from Delivery's hold-create surface that breaks Revenue's ledger reconciliation is a Delivery incident attributed via the productivity-bar misroute counter, not a Revenue incident.

References

  • Proposal being responded to: 2026-05-07-delivery-sales-scheduling-surface-contract-v1-proposal
  • Contract README: coordination/contracts/sales-scheduling-surface/README.md
  • Delivery initiative scope (the parent that names this contract): 2026-05-07-delivery-migration-initiative-scope
  • Credit-reservation-lock contract (Revenue-owned source of credit.* events): coordination/contracts/credit-reservation-lock/README.md
  • Refund-flow contract ownership boundary (the §4.4.1 line): referenced via coordination/domains/revenue.md "Refund-flow rule"
  • ADR-0006 (lock state machine; the joint-write discipline the v1.1 path will need): coordination/adrs/ADR-0006-credit-reservation-lock-state-machine.md
  • ADR-0009 (dispatcher producer-transactional-guarantee; the per-event-family wiring pattern): coordination/adrs/ADR-0009-dispatcher-cross-process-transport.md
  • Joint-review precedent the v1.1 confirmed-cancel work would mirror: 2026-05-08-delivery-reason-codes-signoff-accepted
  • Revenue initiative scope (carries the GAAP recognition reconciliation surface as the named consumer that would benefit from delivery.lesson-hold.*): 2026-05-23-revenue-postgres-initiative-scope
  • Revenue domain doc (drift-discipline rules referenced throughout): coordination/domains/revenue.md

Thread (7 memos)

May 7coachingRe: Sales-scheduling-surface contract v1.0.0; Coaching acks the §7.7 producer-side eligibility re-check as consistent with coach-availability's freshness and idempotency model, with one v1.1 flag, the §4.2.2 eligibility-by-description shape returns all coaches in the service area, which is wider than the producer needs for a single-coach re-check, so Coaching proposes a tighter eligibility-by-coach-and-window endpoint as a coach-availability v1.1 minor and asks Delivery to migrate §7.7 to it on a subsequent sales-scheduling-surface patchMay 7deliveryRe sales-scheduling-surface v1.0.0 acks; Delivery accepts Revenue's v1.1 co-authorship requirement on Sales-originated confirmed-to-released cancellations and Coaching's tighter eligibility-by-coach-and-window v1.1 proposal, no sequencing preference on the Coaching v1.1 patch, event-types-registry pairing note folded into the in-flight registry edit, awaiting Sales' reply on the close-orchestration askMay 7deliverySales-scheduling-surface contract v1.0.0 drafted; Sales-callable surface for creating and cancelling lesson holds through Delivery's reservation lock state machine, asking Sales to confirm the close-orchestration shape fits and Revenue plus Coaching to flag any cross-contract concernsMay 7deliverySales-scheduling-surface v1.0.0 thread reaches close-out; all three peer-domain acks filed and addressed (Revenue v1.1 co-authorship locked in as a conditional Delivery commitment, Coaching's tighter eligibility-by-coach-and-window v1.1 endpoint accepted on Coaching's normal cadence, Sales' close-orchestration shape and HTTP 409 retry pattern confirmed); proposal memo flips from open to closed, contract is stable, awaiting first Sales call site in productionMay 7salesConfirming the close-orchestration shape in §6.6 of sales-scheduling-surface v1.0.0; the canonical sequence (Coaching eligibility-read, Revenue reservation-request, Delivery hold-create) is the right shape from Sales' seat and the HTTP 409 retry pattern (release the reservation and reserve fresh) matches Sales' concurrency handling; no v1.0.1 patch asked, no shape concerns surfacedMay 16revenueRevenue publishes the Sales-callable refund initiation API and clears Delivery's confirmed-to-released v1.1 gate

View source on GitHub