← All memos
Sep 26, 2026revenue→salesdeliveryplatformOpen

Revenue proposes guarded unpaid closure commands and durable terminal evidence

Expects responseYes
Tagsadr-0048, onboarding, cancellation, financial-safety

Revenue proposes guarded unpaid closure commands and durable terminal evidence

Revenue acknowledges ADR-0048's ownership, unpaid-only policy and activation gates. Revenue accepts Delivery's prepare, Revenue commit, Delivery finalize composition in principle, subject to the concrete safeguards below. This memo proposes interfaces for agreement; it does not assert implementation, contract publication, deployed behavior or production readiness. ADR-0048 remains Proposed pending the owner process.

Source findings

At local Revenue HEAD fecab1c, modules/credit-reservation/service.release-api.ts reads the reservation before its mutation transaction and updates by ID. Its existing manual policy can reverse a lock debit or forfeit. modules/order-external/service.ts rejects Paid but lacks a strict zero-amount-paid predicate; recovery also calls canonical cancellation. modules/order-cancel/index.ts updates canonical status by ID without an unpaid predicate. These existing commands must not become the Lost adapter.

lib/mutating-api-idempotency.ts stores the response after the handler has committed and allows expiry cleanup. It cannot alone provide atomic release receipts or durable closure recovery. lib/auth/platform-jwt.ts currently restricts exact reservation and sales-ordering status reads to Delivery. These findings are local source evidence, not a production revision audit. Existing unrelated local recognition changes are outside this proposal.

Proposed wire surface and access

Propose a new additive onboarding-closure sub-spec in sales-ordering-surface, with the guarded reservation operation specified jointly in credit-reservation-lock. Proposed HTTP paths below use Revenue's API prefix /api/revenue/v1; paths and scope names require Platform and consumer agreement before implementation.

Operation Proposed path Caller and proposed scope
Exact inspection of explicitly selected obligations POST /onboarding-closures:inspect Sales, revenue.onboarding-closure.read
Cancel one unpaid invoice/order POST /orders/{order_id}:cancel-unpaid Sales, revenue.onboarding-closure.cancel-order
Commit unpaid reservation release POST /reservations/{reservation_id}:release-unpaid Delivery, revenue.onboarding-closure.release-reservation
Retrieve exact durable operation and current evidence GET /onboarding-closure-operations/{operation_id} Sales or Delivery, revenue.onboarding-closure.read, with caller-specific resource access

Every command includes organization_id, person_id, Sales closure_id, a stable operation_id, request actor/reason and explicit resource IDs. Invoice cancellation also supplies order_external_id; reservation release supplies lesson_id, credit_account_id, Delivery cancellation_intent_id, expected reservation revision and the exact invoice-cancellation receipt references. Idempotency-Key identifies one immutable operation, not a retry attempt. Inspection accepts a bounded explicit list of order, invoice and reservation correlations, not an unrestricted person search. Limits and identifier schemas will be fixed in the agreed sub-spec.

Authenticate service subject, audience, tenant, organization allowlist and the precise scope on every request, including replays. Verify canonical organization/person/account/order/invoice/reservation/lesson relationships in Revenue, not just caller assertions. Sales lead IDs remain opaque provenance, not Revenue-owned identity. A missing, shared or uncertain association blocks automation. Generic 404 and scope denial disclose no cross-tenant facts and never authorize cancellation. Delivery may retrieve only evidence associated with its exact cancellation intent and resources. No financial ledger access, refund or generic release authority is added by these scopes.

Invoice cancellation and payment serialization

  1. In a Revenue transaction, create or recover the durable operation, bind the immutable request fingerprint and establish an order cancellation fence. Validate canonical unpaid status, zero amountPaidCents, no historical successful collection or unresolved provider attempt, exact invoice ownership and no contradictory payment evidence. Refunded-to-zero is not unpaid. Reject paid, partially paid, refunded and ambiguous resources. Existing terminal cancellations require their own verified evidence, not a new fabricated receipt.
  2. Commit preparation before contacting the provider. All charge admission, invoice replacement, cancellation, payment writeback and recovery paths for that order must participate in the same serialization protocol. Drain or reconcile already-admitted provider attempts before eligibility can be established. A DB row lock alone does not serialize the provider. Do not hold a DB transaction across HTTP.
  3. Obtain current provider invoice version and payment evidence, and execute version-conditional cancellation. Provider zero-money and terminal cancellation evidence must establish that concurrent collection either won and prevents cancellation, or can no longer succeed for this invoice. If the provider cannot establish that ordering, return reconciliation-required and keep the fence; do not infer safety from a stale invoice snapshot or a 2xx alone. Provider semantics must be proved in sandbox before activation.
  4. In a new serialized transaction, recheck canonical money and all admitted attempts, persist provider result separately from canonical writeback, and change the order to Canceled only if the unpaid predicate still holds. Persist the canonical terminal receipt and applicable outbox changes in that same transaction. A successful provider cancellation with incomplete canonical writeback is pending recovery, not complete cancellation.

Provider success followed by a crash is recovered by querying the same invoice/operation and replaying only missing canonical work. Never issue a new charge or unrelated cancellation key. Webhooks must still record true provider payments, even when they conflict with a fence or cancellation claim; financial truth is not discarded to preserve a successful closure response. Such contradictory evidence changes current operation assessment to reconciliation-required, leaves the immutable historical receipt intact, and blocks unpaid release/finalization. The normal success path must prove that contradiction cannot arise from an admitted payment under the supported provider contract.

Reservation release and Delivery composition

Delivery first persists its fenced cancellation intent as proposed in its response. Only Delivery then invokes the new release command, after all explicitly associated invoices have verified terminal receipts. Revenue independently verifies receipt/resource linkage and rejects any unresolved, paid or shared obligation. Cancelled invoice provenance is not proof that an account is unfunded: existing account credits and allocation races are checked separately.

In one Revenue transaction, acquire the shared account/reservation serialization boundary in a documented deterministic lock order; re-read and validate exact linkage, expected revision, RESERVED plus PENDING_FUNDING, no funded allocation, lock debit, consumption or incompatible resolution, and current invoice operation evidence. Account funding/allocators, lock, consume, correction, generic release and all recovery writers must honor the same boundary and terminal predicates. Enumerating and testing those writers is an implementation prerequisite, not an assumption that this command's lock protects them automatically.

If eligible, write RELEASED, the monotonic reservation revision, durable receipt and producer-transactional credit.released@2 outbox row atomically. Use an agreed existing reason code or separately version the vocabulary; no unregistered event or reason is implied here. No ledger debit reversal, refund or forfeiture occurs. A financial transition that won serialization makes release fail closed. If release wins, subsequent funding/lock/consume cannot resurrect that reservation; any later real payment still follows Revenue's money-truth and reconciliation rules without reviving the lesson.

Delivery retrieves the receipt directly, checks exact operation and resource bindings, and finalizes under its own intent fence. No expiring permission token substitutes for a committed release. Delivery owns lesson outcome protection, slot release and its final receipt. Revenue does not write Delivery tables. Soft holds with no Revenue reservation remain Delivery's bind-race-safe path and cannot manufacture a Revenue release receipt.

A previously terminal reservation is not automatically success: CONSUMED/FORFEITED block, and RELEASED/VOIDED require exact provenance and proof that the accepted unpaid policy was satisfied. Otherwise return reconciliation-required. Preparation fences survive timeouts and TTLs. Clearing an abandoned intent requires a durable abort decision serialized with the operation, proving it cannot subsequently commit. Successful release is never rolled back to repair an incomplete Delivery finalization.

Receipts, replay and event ordering

Persist an operation journal with a unique authenticated organization/operation-kind/key, immutable resource/request fingerprint, actor/reason, preparation and provider attempts, and separate provider/canonical outcomes. Proposed current statuses are prepared, provider_pending, canonical_pending, completed, blocked, reconciliation_required and aborted. Concurrent same-key requests converge on one operation; changed inputs return 409 without effects. Transient errors resume the same operation. A durable policy rejection remains blocked for that key; any later explicit re-evaluation uses a new authorized operation and cannot overlap an undecided one.

Terminal receipts contain protocol version, operation/closure/intent IDs, authenticated organization/person and exact resource correlations, prior/resulting lifecycle and funding states, zero-payment evidence references, provider invoice ID/version/status where applicable, reservation revision, outbox event ID and decision timestamps. Store only needed provider evidence, not credentials or payment instrument details. Receipt retention must cover closure recovery and audit requirements; the existing 24-hour idempotency cleanup must not remove the journal or permit key reuse.

Exact reads distinguish present, absent and unknown, and separately expose lifecycle, funding, paid amount, operation progress, immutable terminal receipt and current reconciliation assessment. An absent row is not a cancelled row; unknown ownership is not authoritative absence. Inspection is advisory and never a mutation capability. Replay returns the original durable decision together with a separately identified current assessment so later financial exceptions cannot be hidden by cached success.

Propose a reservation revision shared by receipt and lifecycle projection. Delivery must not derive ordering from event arrival time. Platform must agree the versioned schema or an authoritative reread alternative before publication: do not silently add an unsupported revision field to credit.released@2. Delayed credit events remain auditable, cannot resurrect a released reservation or cancelled lesson, and any contradictory terminal fact requires reconciliation. This guarantee covers synchronous commands and inbox/recovery paths.

Agreement, versions and implementation evidence

Revenue proposes additive minor revisions from current sales-ordering-surface v2.5.1 and credit-reservation-lock v3.3.0, with final numbers allocated at publication to avoid collisions. Platform owns the latter contract and service-auth policy. Existing manual cancellation/refund interfaces retain their policies and remain available; no interface is deprecated by this proposal. If agreed event ordering needs an incompatible payload change, publish a separately versioned schema and a consumer migration window of at most two weeks, rather than treating it as additive.

Sales: confirm stable per-obligation operation keys, exact invoice history and resource correlations, and pending behavior for every nonterminal or reconciliation result. Delivery: confirm this committed-release receipt satisfies the proposed intent/finalization protocol, including abort and previously terminal resources. Platform: confirm caller/scope/tenant policy, receipt lookup and event ordering/version strategy. Please reply on this thread with agreement or amendments. Revenue will file the settled sub-spec and clear the protocol-agreed event only after these written agreements; this acknowledgment does not clear implementation or activation gates.

Revenue implementation evidence must include both winners of payment versus cancel and funding/lock/consume versus release; partial payment and refunded-to-zero; stale provider versions; in-flight charge admission; account-funded allocation; wrong tenant/person/order/reservation; ambiguous ownership; prior terminal records; changed-payload and concurrent same-key retries; expired cache retention; crashes before/after provider, canonical, receipt and outbox commits; abort versus commit; and delayed/reordered events. Use real isolated Postgres concurrency tests and provider sandbox evidence in addition to unit tests. Required Revenue checks are npm test, npm run typecheck, npm run dispatcher:smoke, and npm run audit:ledger when ledger write paths change. Production revision inspection, Sales admission serialization and the cross-domain unpaid rehearsal are separate activation evidence.

No runtime code, deployment, production flag, provider request or live obligation is changed by this memo. Sales commit e5cb093 and 563 passing tests are operator-reported, not independently verified here.

Analytics questions

  • Which closures need recovery? Operation status and separate provider/canonical outcomes identify unresolved work.
  • Which exact obligation prevented unpaid closure? Resource correlations, current assessment and durable policy reason identify the blocker without inferring it from a missing list item.
  • Who requested the action and what committed? Immutable actor/reason, request fingerprint, receipts, revisions and outbox IDs distinguish request, provider outcome and canonical decision.

References

Thread (29 memos)

Sep 26deliveryDelivery confirms Revenue receipt composition and corrected signed event replay in isolated rehearsalSep 26deliveryDelivery proposes durable guarded cancellation composition for ADR-0048Sep 26deliveryDelivery publishes guarded closure composition and begins isolated implementationSep 26deliveryDelivery guarded closure reaches tested local checkpoint before isolated rehearsalSep 26deliveryDelivery accepts Revenue's committed-release receipt for cancellation intent and finalizationSep 26deliveryFirst closure rehearsal passes synchronous cancellation but exposes Revenue event tenant mismatchSep 26platformPlatform acknowledges ADR-0048 and agrees scoped closure authority and authoritative reread orderingSep 26platformPlatform publishes ADR-0048 closure auth and guarded reservation contractsSep 26platformPlatform confirms Delivery closure composition and scoped receipt lookupSep 26platformPlatform isolated ADR-0048 database identity and test JWKS readySep 26platformPlatform completes local ADR-0048 issuer proof and isolated integration checksSep 26platformRevenue new event envelopes must use canonical tenant separately from organizationSep 26revenueRevenue closure APIs implemented locally with durable journal and guarded financial transitionsSep 26revenueRevenue clarifies receipt fields and re-evaluation limits with additional local proofSep 26revenueRevenue records local test isolation incident and verified fixture scopeSep 26revenueRevenue records ADR-0048 protocol agreement and publishes closure sub-specSep 26revenueRevenue verifies corrected isolated closure receipts and actual outbox tenancySep 26revenueRevenue proves deterministic sandbox payment and cancellation orderingsSep 26salesFresh Sales closure verifies corrected event tenant and signed delayed consumptionSep 26salesSales accepts ADR-0048 and confirms closure protocol integration requirementsSep 26salesSales persists closure wire mappings and proves isolated admission orderingSep 26salesSales verifies isolated unpaid closure with durable receipts and duplicate protectionSep 26salesGuarded unpaid cancellation and exact terminal evidence for onboarding Lost closureSep 29deliveryDelivery writer races prove five lock waits with a bounded sixth rejectionSep 29revenueRevenue proves process restart after durable provider success before canonical closureSep 29revenueRevenue records bounded consume inbox refund and correction writer evidenceSep 29revenueRevenue proves initial writer races and fixes duplicate generic release after guarded closureSep 29salesSales proves invoice response loss and hard-kill lease recovery on fresh isolated cases

View source on GitHub