feat(subscription): rename permit→subscription + monthly pricing
The "permit/lejet" feature is really a subscription. Full rename of the mutable master data, plus a recurring monthly price. - DB (migration 0004, data-preserving ALTER RENAME): permits→subscriptions, permit_credentials/_plates→subscription_*, sessions.permit_id→subscription_id. - Pricing: per-subscription priceMinor + period(monthly) + currency, with a site default (site_config.subscription_monthly_price_minor) pre-filling the form. - Server: subscription-flow.ts (SubscriptionFlow), routes/subscriptions.ts (/api/subscriptions). Web: SubscriptionManager, route, i18n (sq Abonimet/en). - The signed ledger `permitId` payload is intentionally kept — immutable hash-chained history; renaming it would break verification of past events. Deferred (wiki notes): fee collection into the ledger/shift (a shift-attributed payment), LPR/ANPR plate source, time-of-day access windows (overnight subscriber). Also carries the device-footer UI surface (api DeviceStatus, router mount, i18n devices) due to shared-file overlap with the preceding footer commit. Verified end-to-end on a fresh DB and migration on a live-DB copy (sessions preserved). Live DB migrated. Full monorepo builds clean. Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
This commit is contained in:
@@ -19,7 +19,7 @@ postpaid agreement whose customers enter and exit freely, billed to the business
|
||||
|
||||
## Why this is NOT a permit (the key distinction)
|
||||
|
||||
| | [[permit]] | Validation / sponsorship |
|
||||
| | [[subscription]] | Validation / sponsorship |
|
||||
| --- | --- | --- |
|
||||
| Subject | Known in advance; carries a credential (card/QR/plate) | Anonymous walk-in; identified only by the **ticket they were issued** |
|
||||
| When applied | At entry (credential opens the lane) | **After entry**, against an existing session — at a pay station, by a code, or by a sponsor rule |
|
||||
@@ -74,7 +74,7 @@ validations id, session_id, sponsor_id?, type, amount_minor|minutes,
|
||||
- A **postpaid** sponsor: each full-comp validation appends a row and accrues `amount` to the
|
||||
sponsor; monthly invoice = sum over the period; exit is free at the lane.
|
||||
- **Free entry/exit "freely"**: either the sponsor issues credentials (then it's closer to a
|
||||
[[permit]] — pick that path), or customers take a normal ticket and a sponsor rule / merchant code
|
||||
[[subscription]] — pick that path), or customers take a normal ticket and a sponsor rule / merchant code
|
||||
comps it at exit. The agreement wording decides which; **both are expressible.**
|
||||
|
||||
## Reconciliation & settlement
|
||||
@@ -83,7 +83,7 @@ validations id, session_id, sponsor_id?, type, amount_minor|minutes,
|
||||
Statement lines trace to signed validation events → disputes resolvable against the chain.
|
||||
|
||||
## Open
|
||||
- **"Enter/exit freely" mechanism**: sponsor-issued credentials ([[permit]]-like) vs. ticket +
|
||||
- **"Enter/exit freely" mechanism**: sponsor-issued credentials ([[subscription]]-like) vs. ticket +
|
||||
comp-at-exit. Likely offer both; confirm the operator's actual deal shape.
|
||||
- Prepaid coupon format: printed codes (legacy) vs. QR vs. merchant web-validation portal.
|
||||
- Who may apply a validation, and the **per-operator cap** (a comp is a fraud vector — bound it and
|
||||
|
||||
Reference in New Issue
Block a user