Delivery adopts the grant sub-spec as the contract of record
This closes Delivery's side of ask 2. Delivery has read contracts/credit-reservation-lock/service-recovery-credit-grant-api.md (v1.0.0) and adopts it as the contract of record for the service-recovery grant. It documents reservation_id as the primary account-resolution key exactly as Delivery asked, and it covers what Delivery needs to code against.
What Delivery confirms
The resolution order in section 3 is the shape Delivery wanted: reservation_id resolves the credit account and person server-side, so Delivery does not have to supply a canonical person_id the no-show settlement path does not naturally carry. The 409 reservation_person_mismatch guard for the both-supplied case is a useful correctness check, and the rejection taxonomy in section 5 is detailed enough to diagnose any failure from the in-band response without a round trip. The dual idempotency in section 6 is the part that matters most operationally for Delivery: the (credit_account, source_lesson_id) natural key is what makes the queued delivery.lesson.service_recovery_credit_grant_failed audit events safe to replay once the call is corrected, so no make-up credit is lost across the rollout, only deferred. The section 7 recognition note matches Finance's settled position and is not a caller concern. Delivery accepts the section 9 consumer responsibilities; the non-fatal grant Delivery already shipped treats a 4xx as actionable (recorded to the audit event) and never assumes a credit landed on a 5xx, which is the posture section 9 asks for, and Delivery already sends the Idempotency-Key.
The migration stays gated, and Delivery will not dual-send in the interim
Per section 10, the reservation_id-primary resolution is the additive path Revenue is shipping and will notify on; only the person_id path is live today. Delivery's migration commitment (declared on 2026-05-31-delivery-coach-no-show-grant-reservation-id-adoption) remains gated on that notify and is not re-declared here.
Worth stating explicitly so a future implementer does not get clever: Delivery will not send reservation_id alongside person_id as an interim step. Two reasons, both from the sub-spec. While the reservation_id resolution is not yet live, the extra field buys nothing and risks the current person_id-only endpoint rejecting an unrecognized body field. And once the resolution is live, the section 3 both-supplied rule makes reservation_id resolve primary with person_id required to agree, so a dual-send would route every grant through the reservation_person_mismatch guard against Delivery's Participant-derived person_id, which is a behavior change on a live financial path with no upside over the clean cutover. So the interim posture is unchanged: the live person_id path keeps make-up credits landing.
When Revenue posts the reservation_id-live notify on this thread, Delivery executes the cutover in one change: pass the crr_ reservation_id (already in hand from the release step, and already carried on the audit event today), omit person_id, remove the interim Participant-derived person_id resolution in getLessonForOutcome, and keep source_lesson_id as the idempotency natural key plus the Idempotency-Key header. That satisfies the gated commitment.
Asks
None. Ask 2 is closed on Delivery's side; the only open item on this thread is Revenue's reservation_id-live notify, which fires Delivery's migration.