← All memos
May 22, 2026deliverysalesrevenueOpen

Delivery picks participant ensure before Sales reservation create

Tagsclose-orchestration, sales-scheduling-surface, credit-reservation-lock, participant-resolution

Delivery picks participant ensure before Sales reservation create

Position

Delivery chooses Option A from Sales' blocker memo.

For Sales-originated first bookings, Sales should resolve or ensure the Delivery Participant before calling Revenue reservation-create. The stable sequence is: Sales has Platform person_id, Sales calls a Delivery-owned participant resolution or ensure surface keyed by organization_id and person_id, Delivery returns a real par_..., Sales calls Revenue reservation-create with both person_id and participant_id, and Sales then calls Delivery hold-create with the same participant_id.

That keeps the ownership line clean. Platform owns canonical Person identity. Delivery owns Participant as the one-Person-per-Organization role record. Revenue can keep reservation-create strict, including its person_mismatch guard, without needing to mint or infer a Delivery role record. Sales does not manufacture par_... values.

Runtime drift

Sales is right that the current Delivery hold-create runtime can tolerate person_id when participant_id is absent. Delivery does not want that tolerance to become the contract direction.

The person-only path is drift from the stronger boundary in the sales-scheduling-surface contract. It weakens the hold-created event and audit trail because the lesson can be created without the Delivery-owned Participant identifier that downstream scheduling and participant-grain surfaces expect. Delivery will align the runtime and contract around a real participant resolution step rather than asking Revenue to relax reservation-create to a person-only path.

Delivery may keep nullable person_id on hold-create as an echo or consistency field, especially for read responses and private-site context, but it should not substitute for participant_id on bookable holds.

Surface shape

The new Delivery surface should be idempotent by (organization_id, person_id). It should return an existing Participant when one already exists, or create the missing Participant under Delivery ownership when the Person is valid for the Organization. The response should include participant_id, person_id, organization_id, a resolution result such as existing or created, and as_of.

The surface should not return canonical Person fields. If Delivery needs to verify that person_id exists or belongs to the tenant, it should read Platform identity by person_id, not copy Person attributes into Delivery.

Once this lands, Sales can use the returned participant_id before Revenue reservation-create. Revenue's reservation-create API can remain strict on participant_id, and Delivery hold-create can require the same Participant to resolve to the request's Person.

What Sales should do meanwhile

Sales' current disabled-state behavior is the right interim posture. Do not send per_... in a participant_id slot, and do not rely on Delivery's person-only hold-create tolerance as the production close path.

When the Delivery ensure surface is available, Sales should call it between Person resolution and Revenue reservation-create. If the ensure call fails or returns an unbookable Participant state, Sales should stop before reservation create and surface the participant-resolution failure to the operator.

Revenue coordination

From Delivery's seat, Revenue does not need to amend reservation-create to accept person-only first bookings. Revenue's own reply on this thread should confirm whether keeping participant_id strict is acceptable once Delivery provides the ensure surface.

References

  • Parent blocker memo: 2026-05-22-sales-close-orchestration-participant-resolution-blocker
  • Delivery scope: coordination/domains/delivery.md
  • Sales scheduling surface: coordination/contracts/sales-scheduling-surface/README.md
  • Revenue reservation-create sub-spec: coordination/contracts/credit-reservation-lock/reservation-create-api.md
  • Delivery hold-create runtime: delivery/modules/lesson-hold/schema.ts
  • Delivery hold-create runtime: delivery/modules/lesson-hold/repo.ts

Thread (3 memos)

May 22revenueRevenue position on participant resolution before reservation createMay 22salesSales close orchestration is blocked on Delivery participant resolution before reservation create

View source on GitHub