4fd175e0e4
Subscription page: the one-window model can't express prepaid/postpaid, calendar or anniversary anchoring, grace or an expiry notice; and renewal is OFF-BOOK today (a PUT that appends no payment — the same hole closed for the first sale on 2026-06-20). Designed: plan billing rule, per-day pricing so both anchors share one formula, open- ended agreement, subscription_periods where each period is a ledger charge and a renewal = paying the next period, one subscriptionAccess() gate function, expiry notice derived not stored. New decision page party-ledger: a counterparty sub-ledger for who-owes-whom across modules — parties + signed charge / settlement / write_off events, balance derived never stored, aging + statements + CSV; lands postpaid subscriptions, hotel guest-nights, fleet washes on account, supplier/utility bills. Sub-ledger only: no bookkeeping, a statement is not a fiscal invoice, parties per appliance. validation-sponsorship's sponsor table marked superseded; open-questions #17; index. Claude-Session: https://claude.ai/code/session_01FWncR69HgGPuei1dLrW3cU
103 lines
5.9 KiB
Markdown
103 lines
5.9 KiB
Markdown
---
|
||
type: concept
|
||
tags: [parking, domain, business, pricing, validation, design]
|
||
sources: [parksql2017-legacy-schema]
|
||
updated: 2026-09-08
|
||
status: open
|
||
---
|
||
|
||
# Validation & Sponsorship — merchant comps, coupons, postpaid B2B
|
||
|
||
> **Sponsor accounts superseded (2026-09-08).** The `sponsors` table sketched below — a
|
||
> counterparty with a stored `balance_minor` and a billing period — is now a special case of the
|
||
> **[[party-ledger]]** (design): any party (subscriber, hotel, fleet, supplier) with a balance
|
||
> *derived* from signed `charge` / settlement / `write_off` events, never a stored column. A
|
||
> postpaid sponsor = a party; each comped stay = a `charge` against it; the monthly invoice = its
|
||
> statement. The validation *mechanics* (signed validation events on a session) are unchanged
|
||
> and built ([[validation-discounts]]).
|
||
|
||
Builds on [[validation-discounts]] (the signed-event discount mechanism) to add the layer it leaves
|
||
open: **a sponsor account and postpaid B2B billing.** The driving case — **a nearby business with a
|
||
postpaid agreement whose customers enter and exit freely, billed to the business monthly.**
|
||
|
||
> This page owns the **sponsor/account/settlement** model and the **permit-vs-validation
|
||
> distinction**. The *how a discount is applied* mechanics (signed event, `due = max(0, fee −
|
||
> discounts)`, attribution, anti-abuse) live in [[validation-discounts]] — not duplicated here.
|
||
> Status: **design, not built.**
|
||
|
||
## Why this is NOT a permit (the key distinction)
|
||
|
||
| | [[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 |
|
||
| Who pays | The subscriber, out-of-band | A **third party** (merchant/sponsor), or nobody (comp) |
|
||
| Model fit | `permits` + credentials | New: a **validation event** on a session + a **sponsor account** |
|
||
|
||
A permit bypasses tariff computation; a validation **adjusts the computed fee** (or zeroes it). They
|
||
compose — but they are different primitives.
|
||
|
||
## Two economic models (both real)
|
||
|
||
- **Prepaid** — merchant buys a pool of value up front (legacy `BA_Cupons`: printed single-use codes
|
||
worth `DiscMinutes`; City Center research: merchant pre-buys time tickets 15 min→all-day).
|
||
Reconciliation = count used codes against the pool.
|
||
- **Postpaid** (the asked-for case) — merchant signs an agreement; their customers park free or
|
||
discounted; the system **accrues each validation against a sponsor balance** and **invoices monthly**
|
||
(City Center: "billed for the number of tickets validated each month," verified 3-0). No money moves
|
||
at the lane.
|
||
|
||
The legacy system did **only prepaid coupons** — **the postpaid sponsor account is net-new** for this
|
||
project.
|
||
|
||
## Modifier types (extends [[validation-discounts]])
|
||
|
||
The discount-type enum lives in [[validation-discounts]]; legacy `DiscType` (smallint) and research
|
||
(Amano McGann / HUB J4M, abstained-not-refuted) confirm the set: `comp` / `percent` / `fixed` /
|
||
`time-credit` (legacy `DiscMinutes`) / `rate-switch`. **Sponsorship adds one field** to a validation:
|
||
a `sponsorId`. Full-comp + a sponsor = the "free entry/exit, bill the business" case.
|
||
|
||
## The sponsor-liability consequence (anti-fraud)
|
||
|
||
The validation is a signed event ([[validation-discounts]], [[append-only-event-chain]]); what
|
||
**sponsorship** adds is that **free-to-the-parker is not free-to-the-ledger** — it is a *receivable
|
||
from the sponsor*. Under the [[threat-model|operator-as-adversary]] model:
|
||
|
||
- A postpaid sponsor's "enter/exit freely" still **mints signed entry + exit events** (and snapshots)
|
||
— the audit trail is identical to a paying car; only the **settlement target** differs.
|
||
- The **sponsor's period liability = the sum of `sponsorId`-tagged validation events** over the
|
||
period — derivable from the chain, reconcilable like a [[shift|shift Z-report]] and visible to
|
||
[[reconciliation]] (a sponsor comping far more than plausible footfall is an anomaly).
|
||
|
||
## Proposed data shape (illustrative — design only)
|
||
|
||
```
|
||
sponsors id, name, contact, mode {prepaid|postpaid},
|
||
balance_minor (prepaid pool / postpaid accrual), billing_period, active
|
||
validations id, session_id, sponsor_id?, type, amount_minor|minutes,
|
||
code?, operator_id, created_at // append-only; one row per application
|
||
(coupons) code, value_minutes|minor, single_use, used_at? // prepaid pool, optional
|
||
```
|
||
|
||
- 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
|
||
[[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
|
||
- **Prepaid**: pool decrements; alert at low balance; no invoice.
|
||
- **Postpaid**: accrue; **monthly statement** per sponsor (legacy/City Center cadence ~the 10th).
|
||
Statement lines trace to signed validation events → disputes resolvable against the chain.
|
||
|
||
## Open
|
||
- **"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
|
||
always sign it).
|
||
- Invoicing: in-app statement only, or export for external billing? FX if sponsor bills in another
|
||
currency (defer to [[tariff]] FX).
|
||
- Partial-stay sponsorship (merchant covers first 2h, parker pays the rest) — `time-credit` or
|
||
`rate-switch` covers it; confirm.
|