docs: clarify payment finality semantics
This commit is contained in:
@@ -10,7 +10,7 @@ The current payment system covers:
|
||||
- default subscription plan bootstrap
|
||||
- user subscription creation at registration time
|
||||
- invoice creation through a provider adapter
|
||||
- manual admin activation when an invoice is confirmed as paid
|
||||
- manual admin activation after an operator verifies that the provider reported a final successful payment status
|
||||
- quota-cycle reset on successful activation
|
||||
|
||||
The current payment system does not yet cover:
|
||||
@@ -42,6 +42,8 @@ The current payment system does not yet cover:
|
||||
|
||||
### `PaymentInvoice`
|
||||
- stores one provider-facing payment attempt for a subscription
|
||||
- `pending` means the invoice exists, but the payment is not yet considered final or accepted
|
||||
- `paid` means the payment is considered final and safe to activate against
|
||||
- important fields:
|
||||
- local `id`
|
||||
- `subscriptionId`
|
||||
@@ -91,6 +93,13 @@ Current runtime note:
|
||||
5. The returned provider invoice data is persisted as a new local `PaymentInvoice` in `pending`.
|
||||
6. The API returns invoice details, including provider invoice id, amount, address, and expiry time.
|
||||
|
||||
## Payment status semantics
|
||||
- `pending` does not count as paid.
|
||||
- `pending` does not activate the subscription.
|
||||
- `pending` does not reset quota.
|
||||
- The system must treat an invoice as `paid` only after the payment provider reports a final successful status, meaning the funds are accepted strongly enough for access activation.
|
||||
- The current implementation does not fetch or verify that provider-final status automatically yet.
|
||||
|
||||
## Invoice listing flow
|
||||
- `GET /api/billing/invoices` returns the user's invoices ordered by newest first.
|
||||
- This is a read-only view over persisted `PaymentInvoice` rows.
|
||||
@@ -100,8 +109,9 @@ The implemented activation path is manual and admin-driven.
|
||||
|
||||
1. An authenticated admin calls `POST /api/admin/invoices/:id/mark-paid`.
|
||||
2. The web app resolves the admin session and passes actor metadata into the billing store.
|
||||
3. `markInvoicePaid` runs inside one database transaction.
|
||||
4. If the invoice is `pending`, the store:
|
||||
3. This endpoint is intended to be used only after the operator has already verified that the provider reached a final successful payment state.
|
||||
4. `markInvoicePaid` runs inside one database transaction.
|
||||
5. If the invoice is `pending`, the store:
|
||||
- updates the invoice to `paid`
|
||||
- sets `paidAt`
|
||||
- updates the related subscription to `active`
|
||||
@@ -111,7 +121,11 @@ The implemented activation path is manual and admin-driven.
|
||||
- clears `canceledAt`
|
||||
- writes a `UsageLedgerEntry` with `entryType = cycle_reset`
|
||||
- writes an `AdminAuditLog` entry `invoice_mark_paid`
|
||||
5. The API returns the updated invoice.
|
||||
6. The API returns the updated invoice.
|
||||
|
||||
Important constraint:
|
||||
- `mark-paid` is not evidence by itself that a `pending` invoice became payable.
|
||||
- It is only the current manual mechanism for recording that the provider has already given final confirmation outside the app.
|
||||
|
||||
## Idempotency and transition rules
|
||||
`markInvoicePaid` is replay-safe.
|
||||
@@ -156,11 +170,17 @@ Current payment-specific errors surfaced by the web app:
|
||||
|
||||
## Current limitations
|
||||
- The system still depends on manual admin confirmation to activate access.
|
||||
- Because provider-final status is not ingested automatically yet, the app currently relies on operator judgment when calling `mark-paid`.
|
||||
- No provider callback or reconciliation job updates invoice state automatically.
|
||||
- No runtime path currently moves invoices to `expired` or `canceled`.
|
||||
- The provider adapter does not yet verify external status or signatures.
|
||||
- Subscription lifecycle beyond the current `mark-paid` path is still incomplete.
|
||||
|
||||
## Required future direction
|
||||
- Add provider callbacks or polling-based reconciliation.
|
||||
- Persist provider-final status before activating access automatically.
|
||||
- Reduce or remove the need for operator judgment in the normal payment-success path.
|
||||
|
||||
## Code references
|
||||
- `packages/db/src/bootstrap.ts`
|
||||
- `packages/db/src/auth-store.ts`
|
||||
|
||||
Reference in New Issue
Block a user