fix: enforce subscription period end (#19)
Closes #3 ## Summary - enforce `currentPeriodEnd` as a hard access boundary for generation requests - transition elapsed `active` and `past_due` subscriptions to `expired` during runtime reads - stop showing active-cycle quota for non-active subscriptions and document the current lifecycle behavior - add DB tests for post-expiry generation rejection and expired account-view normalization ## Testing - built `infra/docker/web.Dockerfile` - ran `pnpm --filter @nproxy/db test` inside the built container - verified `@nproxy/db build` and `@nproxy/web build` during the image build Co-authored-by: sirily <sirily@git.shararam.party> Reviewed-on: #19
This commit was merged in pull request #19.
This commit is contained in:
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user