Files
parking_solution/wiki/concepts/validation-sponsorship.md
T
julian 4fd175e0e4 docs(wiki): subscription recurring billing + party ledger — design only
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
2026-09-09 10:19:09 +02:00

103 lines
5.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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.