fix: enforce subscription period end

This commit is contained in:
sirily
2026-03-10 18:00:26 +03:00
parent 1b2a4a076a
commit 3b0ce5d62c
7 changed files with 410 additions and 28 deletions

View File

@@ -11,6 +11,7 @@ The current payment system covers:
- user subscription creation at registration time
- invoice creation through a provider adapter
- manual admin activation after an operator verifies that the provider reported a final successful payment status
- automatic expiry of elapsed subscription periods during account and generation access checks
- quota-cycle reset on successful activation
The current payment system does not yet cover:
@@ -154,6 +155,14 @@ If the invoice does not exist, the store returns `invoice_not_found`.
- Approximate quota shown to the user is derived from `generation_success` entries since the current billing cycle start.
- A successful payment activation starts a new cycle by writing `cycle_reset` and moving the subscription window forward.
- Failed generations do not consume quota.
- When a subscription period has elapsed, user-facing quota is no longer shown as an active-cycle quota.
## Subscription period enforcement
- `currentPeriodEnd` is the hard end of paid access.
- At or after `currentPeriodEnd`, the runtime no longer treats the subscription as active.
- During generation access checks, an elapsed `active` subscription is transitioned to `expired` before access is denied.
- During account and billing reads, an elapsed `active` or `past_due` subscription is normalized to `expired` so the stored lifecycle is reflected consistently.
- There is no grace period after `currentPeriodEnd`.
## HTTP surface
- `POST /api/billing/invoices`
@@ -174,7 +183,7 @@ Current payment-specific errors surfaced by the web app:
- 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.
- Subscription lifecycle is still incomplete on the invoice side because provider-driven expiry, cancelation, and reconciliation are not implemented yet.
## Required future direction
- Add provider callbacks or polling-based reconciliation.