Memo: Refund-against-canceled-lesson policy formalization
Date: 2026-04-28 From: Revenue To: Delivery Status: Open. Today the policy falls back to manual reconciliation, which is a P2 incident class waiting to become a P1 once volume scales.
Why
The current refund flow rule says: a refund initiated against a confirmed lock requires Delivery to transition the lock to released first or in the same transaction. Reservation refunded without a released lock is drift.
The unwritten part: when does Delivery transition the lock to released? Today the answer is "when Delivery's operator decides the lesson is canceled." For some cancellation reasons that decision is automatic (the entire lesson site closed, the coach is unavailable and reschedule failed). For others it is human (customer requested, bad weather, policy exception). Without an enumerated rule, Revenue's refund queue stalls behind Delivery's decision rate.
The refund-cycle completion time metric is Revenue's responsibility but is gated on Delivery's transition rate, which is fine when the rule is shared and unambiguous, and bad when the rule is implicit.
What
Recommendation: enumerate cancellation reasons that auto-release the lock, and enumerate the ones that require explicit operator action. Map the auto-release reasons to a lock.released event with a reason_code carrying the cancellation cause. The ledger consumes the same reason code for the refund's purpose-of-record.
Auto-release candidates: lesson-site closure, coach-unavailable-and-reschedule-failed, force-majeure-class events declared by Delivery. Explicit-operator candidates: customer-requested cancellation (requires confirming refund eligibility against the program's cancellation window), policy exception, bad-debt write-off.
The lock contract change is small (a reason_code enum on lock.released). The bigger work is the policy itself, which is Delivery-stewarded with Revenue input.
Asks
Confirm Delivery is willing to enumerate the cancellation reasons and stand up the auto-release path for the auto-eligible ones. Revenue will draft the corresponding refund-flow changes against the new reason codes.
If the policy work needs more time than the contract change, separate them: ship the reason_code field on lock.released first (with a permissive enum that captures current operator behavior), then narrow the enum as policy lands. ADR-0006 amendment for the contract change is required either way.
References
- ADR-0006 (credit reservation lock state machine)
coordination/contracts/credit-reservation-lock/coordination/domains/revenue.md— refund flow rulescoordination/domains/delivery.md— lock-contract change rule