Sales ADR-0053 recovery eligibility and flow-preservation position
Assignment ADR-0053/sales/001; Sales participant 01a0ff07-d3d4-7553-bf28-5314810de63e, host local; coordinator 01a0e095-f279-7fd0-a8ef-92ce8f9547fc, host local. Reviewed Proposed ADR-0053 and its approval request at canonical coordination commit 3225646710eb3073a4e8e5e5f8a6fb9f07eeb1cf, accepted ordering v2.9.0/scheduling v2.0.0 at ADR-0052 package 43cd36bc312cdda3e1e2543215df55a7ace52ab1, and Sales candidate 62c6c0449d8316f38dd33df2e83033208ea0703c based on released f04b37c87775b03cbf37f3131d8ef15c61ddc15b.
Sales supports the bounded architectural direction, but withholds formal acknowledgment until the exact recovery eligibility, digest, admission/tombstone serialization, receipts, authority and compatibility package is reviewable. The proposal deliberately leaves these load-bearing terms open. No acknowledges field is supplied. This memo approves no other owner's position, runtime change or production activation. ADR-0052 implementation work in this chat is held during this explicit bounded handoff; its clean checkout and evidence are preserved.
Source-backed gap and durable Sales identity
The current wire mapper in lib/revenue/sales-ordering-close-client.ts:113-161 sends payment.capture.capture_token for inline capture and capture_id for link capture. Ordering v2.9.0 requires the original inline credential and preserves both motions. Candidate modules/close-orchestration/close-orchestration.service.ts:626 temporarily denies inline capture, and modules/scheduling-admission/repo.ts:10-15 rejects credentials in continuation material. That denial is an inactive, incomplete integration limitation, not a supported product change.
The current soft journal commits only Delivery soft-create identity. Revenue's close key is computed at close-orchestration.service.ts:857 from booking selection and sorted offer parts, then used at the first close send at line 459. It is not an admission-specific close identity, omits the resulting first Lesson and initiating Lead from its key parts, and is not independently journaled with a Revenue request digest before send. The soft-create fingerprint is not a Revenue close fingerprint. Candidate completion only represents reserved/committed with an Order ID (scheduling-admission/repo.ts:84-98, new migration's completion table). It cannot represent permanent noncommit by fabricating an Order or a successful terminal result.
The new Sales record should durably bind the protocol/digest version, operation, exact close key, Sales admission ID, tenant, Organization, canonical Person, originating Lead, original actor, original first Lesson and original soft receipt identity, payment motion, and shared normalized close-request digest before the first Revenue POST. The descriptor is non-secret and immutable; provider credentials, workload proofs, bearers and cookies remain absent. Exact close-send preparation belongs after the original first Lesson is known and the final outbound wire has been constructed, not merely when the earlier soft command was saved. A crash before that commit must leave no authorized close send. A crash after it must retain the same identity and prevent replacement around an unresolved original.
The digest must be specified jointly against Revenue's existing normalization, not copied from Delivery or inferred from the Sales DTO. Ordering already treats offer_items array order as equivalent by sorting normalized offerings. The specification must cover submitted price, amount, currency, offer versus offer-items, historical intent, absent/null/default fields, originating Lead and optional payer fields. Those fields must be derived from the original prepared request, not freshly hydrated Person data on recovery. Canonical bytes, operation/version domain separation, tenant/Organization/key binding, algorithm and positive/negative vectors must be explicit.
Credential identity is a remaining approval detail. Simply deleting capture_token before hashing allows distinct inline handles to share a digest. Require a Revenue-validated commitment to the original handle without keeping the handle or recoverable credential material in Sales. If the chosen construction hashes the original token transiently, specify its security/entropy assumptions and both owners' independent computation; do not introduce an undeclared shared secret or a reusable payment capability. Link capture_id and amount also remain bound to the original request. A digest alone is not evidence of Revenue admission, provider quiescence, current resource authority or payment success.
Eligibility and permanent never-admitted settlement
Sales requires an explicitly recognized new-command protocol and key namespace eligible for the recovery operation. An admission-specific new key can fit the existing up-to-128-character Idempotency-Key header without adding a header name or body field, provided old callers, namespaces, normalization and replay continue unchanged. That compatibility is a proposal to prove, not a declaration that any existing key is safe to settle.
Do not retrofit eligibility onto selection-derived keys, legacy/v1 rows, an incomplete command, an evicted association or a caller's assertion of current absence. Candidate 62c6c04 does not already supply the required pre-close identity/digest. A future eligible record must originate in a valid Sales admission and bind the exact original resources and request commitment. Revenue must specify how it independently validates the descriptor, recognized namespace/version and caller/resource authority without reading Sales tables, trusting a free-prose declaration, or using the four ADR-0052 tokens for a different operation.
Minimal concrete option for owner review: define a new major ordering protocol whose original POST and recovery both carry the same closed, signed, non-secret Sales admission descriptor. Its payload contains only the immutable admission/tenant/Organization/actor/Person/Lead/first-Lesson/soft-receipt association, protocol/digest version, exact original key and request commitment specified above. Persist the descriptor before send. Revenue independently verifies the exact signed bytes, dedicated issuer/key trust and allowed protocol, then computes the original POST digest itself and requires equality before recording admission or preparing a provider request. Recovery verifies the same artifact before admission/tombstone lookup and serialization. A recognized key prefix is routing only; signature, exact claims and shared digest establish the eligible association. The artifact authorizes only reconciliation of that original command, not payment initiation or other keys. Its verification/trust, issuance-after-valid-admission, immutable lifetime and revocation/history rules require explicit Sales/Revenue/Platform review; no existing service JWT, human cookie or ADR-0052 token is repurposed. A mandatory artifact on original POST is a major-version proposal, not an additive change to v2.9.0. If owners prefer an additive alternative, they must supply an equally independent eligibility construction and demonstrate every original writer barrier before approval; the existing source supplies none.
Platform's owner recommendation of POST /api/v1/sales-ordering/close-recoveries, sole revenue.sales-ordering.close.recover scope and Sales subject is a suitable narrow route shape for review. Sales has no route-name objection, provided its selector authorizes neither original close nor generic Order reads and the exact schema/recipient pins are approved. The recommendation is not issued authority. The exact outstanding objection is unseen-key provenance: workload authentication plus prefix/digest/absence cannot establish that the unseen original was independently admitted by Sales under the new protocol. The concrete major-version option above resolves that provenance through an owner-reviewed artifact; no unapproved signature trust is implied.
Original close admission and recovery/settlement must serialize on the same permanent identity before provider preparation, reservation/bind effects or dispatch. Recovery after an admitted original may execute only that durable original attempt, with its stable provider key and protected continuation. Never-admitted settlement must atomically retain an immutable noncommit tombstone that all compatible original-admission paths consult. A delayed original POST, an in-flight obsolete handler, concurrent recovery and duplicate/mismatched settlement must not execute after that tombstone commits. A timeout, 404, disconnected caller, missing Order, failed local projection or currently empty read is not settlement.
Specify tombstone identity/digest, permanent lifetime, exact receipt/reference, request mismatch behavior, transaction linearization, replay, and every writer barrier. An admitted or provider-unknown attempt cannot be tombstoned as never admitted. Both owners need delayed-original-versus-settlement and simultaneous-original-versus-recovery proofs using real handlers and isolated persistence. No changed original terminal outcome or new collection is allowed. Permanent financial noncommit also does not grant Sales cancellation or prove that an earlier unbound soft hold has expired; resource resolution remains Delivery-owned. The new noncommit record must retire only its exact Sales blocker once the approved predicates hold, leaving original command, actor and receipt evidence intact.
Inline/link response loss and operator outcomes
| Original state or cut point | Sales action and required owner result |
|---|---|
| Before durable eligible close identity | No Revenue close send. Retain/reconcile the original soft command independently; do not claim Revenue noncommit. |
| Identity durable, POST may never have reached Revenue | Call the proposed authenticated exact recovery operation. Only a serialized permanent never-admitted receipt can settle absence and fence delayed admission. |
| Revenue admitted, inline/link preparation incomplete or response lost | Resume Revenue's admitted original request/preparation and stable key. Do not obtain another inline handle, consume another link capture or mint a replacement close. |
| Provider or local writeback unknown, including success not yet recorded | Show reconciliation pending and retain protection. No fresh payment, cancellation, new reservation or successful closure is inferred. Genuine financial facts remain Revenue-recordable. |
| Original close success receipt lost | Recover the same immutable reserved/committed result, original IDs and receipt. Later funding of a reserved Order does not rewrite the original close result. Current payment/handoff assessment remains a separate ADR-0049 flow. |
| Definitive original failure | Preserve the original error/terminal interpretation. New work requires exact financial and resource resolution plus fresh independent human admission; failed-close compensation is not Sales-owned. |
| Immutable never-admitted settlement | Display that the original attempt did not commit, keep its receipt/tombstone, and enable replacement only after the exact Sales/resource blockers are resolved. Never describe this as a refund or paid cancellation. |
| Authority unavailable/revoked, resource contradictory, legacy/unknown identity | Block and retain evidence, with an actionable operator reason. A 401/403/404/503 is not permission to discard the original. Human expiry or role/Organization switching after valid admission must not force a new human admission to recover an authorized original. |
Proposed operator wording for uncertainty is “Reconciling the original booking. Do not submit another payment.” Actions that create a replacement are disabled while unresolved; read/reconciliation affordances remain distinct. The actual typed recovery response/UI map must specify pending, original terminal replay, immutable noncommit, mismatch, denied and unavailable cases. These are proposed new recovery outcomes, not new meanings for existing close status codes. Do not fabricate outreach completion or automatically contact customers.
Current onboarding projection (modules/lead-onboarding/service.ts:57-58) distinguishes “Invoice needed,” “Confirm invoice sent,” “Awaiting payment” and “Payment confirmed.” A recovered reserved invoice can restore its exact link/correlation but must not mark the invoice sent or paid. Pending close recovery must not be rendered as proof that no invoice exists. Preserve message/attempt history and exact current-invoice handoff ownership.
Exact candidate flow inventory
The following denials occur only when candidate SALES_SCHEDULING_V2_ENABLED=true; it remains inactive. Existing v1 behavior is retained when inactive. This source inventory is not proof that any denied flow has been migrated or that cutover can remove it.
| Existing customer/operator flow and entry | Candidate denial and compatibility obligation |
|---|---|
Single first-lesson booking, POST /api/close-orchestration/close-offer, closeOfferForOperator |
V2 requires the Sales ordering path. It refuses inline active-charge capture before admission. The legacy reservation-first path cannot run under v2; direct createReservation/holdCreate are also denied. Single close with a saved link or no immediate payment has a candidate adapter, with no complete production/resource/financial proof. Preserve active-charge and reserved/invoice motions, including supported multi-line offers in this one close; do not confuse them with composite multi-lesson booking. |
Multi-lesson composite planner booking, POST /api/composite-offer/submit, submitCompositeCloseOfferForAdmin |
withOnboardingClosureAdmission(..., "composite_booking", ...) rejects before the legacy operation. Atomic-multi reservation/hold-create transports reject independently. AvailabilityPlannerDrawer.tsx:1484 uses this path. Preserve its batch/compensation semantics; a single soft-create adapter is not equivalent. |
Reschedule an existing reservation, POST /api/lead-lesson-bookings/reschedule-reservation, rescheduleReservationForAdmin |
Common admission rejects reschedule_reservation; reservation/hold-create transports also reject. Preserve original reservation/booking correlation and release/replacement rules, not a new purchase. |
Rebook a trial, POST /api/lead-lesson-bookings/rebook-trial, rebookTrialForAdmin |
Common admission rejects rebook_trial; downstream reservation/hold-create reject. Preserve original trial and financial ownership and its independent recovery/compensation behavior. |
Replacement reservation against an existing invoice, POST /api/lead-lesson-bookings/existing-invoice-reservation, createExistingInvoiceReservationForAdmin |
Common admission rejects existing_invoice_reservation, and legacy create transports reject. Existing Order selection/funding is not authority to create another Order/payment. This motion needs a compatible adapter or separately reviewed exact authority, not the new-close recovery route. |
Separate invoice-link credit purchase, POST /api/workbenches/leads/{lead_id}/credit/orders, createWorkbenchCreditOrder |
Generic admission rejects create_invoice at workbench-credit-orders.service.ts:284. This affects supported add-on/top-up purchases after or outside first-lesson reservation, not just onboarding invoices. The catch returns a failed dependency result. The lower-level createInvoiceLinkOrder transport itself was not v2-gated, so do not claim universal transport exclusion or readiness for this flow. |
| Old/direct soft-create or Revenue close helpers without a persisted v2 context; unresolved v1 operations | V2 helpers reject missing context; existing open legacy onboarding operations get separate non-executable quarantine and block replacement. Neither this nor missing journals makes old work recovery-eligible under ADR-0053. |
The common wrapper is modules/onboarding-closure/admission.repo.ts:6-8. Reschedule/rebook/existing-invoice entry points are modules/lead-lesson-bookings/service.ts:644-684; invoice creation is modules/workbenches/workbench-credit-orders.service.ts:213-321. Transport denials are in lib/delivery/scheduling-write-barrier.ts, both hold-create clients and both reservation-create clients. The original close/recovery paths are in modules/close-orchestration/close-orchestration.service.ts:601-674 and the Revenue close client.
Listing/selecting an existing invoice, recording its manual SMS/reminders, reading payment state, separate invoice cancellation, and composite lesson cancellation are not all denied merely by this v2 flag. The common gate does not automatically wrap these paths. Any earlier shorthand “invoice paths denied” must be read as the exact creation/replacement entries above. Ordinary ADR-0052 sender/invalidating-writer inventory and enforceable recipient authority remain incomplete; an env flag and source scan cannot certify all deployed writers.
Boundary between remaining ADR-0052 work and new design
Ordinary remaining ADR-0052 integration includes composing the already accepted four policies with authentic resource/business enforcement, final-source ADR-0049/0050 reconciliation, preserving strict v1 evidence, migration validation, all writer barriers, exact cross-domain concurrency and financial recovery proofs, and a flow-preserving cutover. The 133-unit/typecheck and isolated Prisma/real local issuer results at 62c6c04 do not establish these outcomes. Full history replay also failed in the pre-existing May cadence migration before reaching the additive v2 SQL; no historical source was repaired. That remains a separate migration/integration limit.
The exact Person/Organization service verdict, credential-free close recovery and permanent never-admitted settlement, and Revenue-owned financially quiescent failed-close compensation are actual new authority/design dependencies identified for ADR-0053. Sales supports their separation from the four ADR-0052 selectors. A current-active Person verdict for new writes must be distinguished from authenticated access to an immutable original receipt and reconciliation of genuine historical financial facts; archival/alias changes cannot silently replace command identity or justify a second collection. Platform, Delivery and Revenue own the concrete verdict/compensation rules and acknowledgments.
ADR-0053 does not by itself solve legacy reserved-credit booking, multi-lesson atomic booking, existing-invoice replacement, general reschedule/rebook, or add-on/top-up invoice admission. Some flows may be composed with accepted existing authority after proof. Where that cannot preserve their effects, ownership and atomicity, return a separately bounded design/authority proposal; do not add a generic scheduling/cancellation/payment permission to this ADR. In particular, the proposed exact failed-close compensation cannot be borrowed for Sales' general rescheduling or unpaid Lost closure. Supported flows require an explicit compatibility/coverage matrix before cutover, not silent removal.
Compatibility position and required approval package
An additive separately versioned recovery surface can preserve original ordering v2.9.0 wire if the original POST body, header requirements, optional inputs, normalized equality, statuses, success/error results and legacy replay remain unchanged. A new caller may voluntarily select an approved admission-specific key namespace within the existing string header and persist a local digest; existing callers need no new field/header or key conversion. New recovery outcomes belong to the new surface, with no alteration of original terminal responses. Never-admitted tombstones must be limited to that explicitly opted-in new-command namespace, with all compatible writers enforcing them. We require evidence for this exact distinction before endorsing an additive ordering version.
If Revenue needs a new mandatory field/header/selector on original close, makes existing callers satisfy new request-eligibility rules, changes original normalization or terminal/replay outcomes, or repurposes/deprecates existing keys, use an explicit major ordering version and migration plan. A breaking change is not made additive by exposing a second route. ADR-0053 remains Proposed until affected owners decide the actual interface and versions.
Before formal Sales approval, return the assembled exact route/method/selector and proof/recipient pins; closed command/digest/receipt/tombstone and response schemas; authoritative command eligibility and old-key exclusions; shared normalization/credential commitment vectors; admission/recovery/settlement writer serialization and no-network-lock protocol; noncommit/blocker retirement and protected financial/compensation predicates; typed operator outcomes; and inline/link plus denied-flow compatibility matrix. Include real-handler isolated proofs for response loss at every cut point, provider success/writeback failure, simultaneous/delayed admission versus tombstone, changed digest/resources, auth denial with no effect, immutable terminal replay, and preservation of the supported motions. No unconditional implementation commitment is created by this design response.
Fresh ADR-scoped inbox/ledger reads at 2026-10-03T01:29:16.919Z and 2026-10-03T01:29:17.235Z informed discovery; the mirror does not replace the source-pinned assignment or proposal. No implementation commitment was completed by this review. This local owner memo is prepared in the permitted Sales coordination clone. Root remains the sole publisher/indexer/freshness owner for the reviewed batch. No runtime, schema, fixture, listener, signing key, token issuance, deployment, provider or production change occurred in this review.