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
This commit is contained in:
2026-09-09 10:19:09 +02:00
parent 535244209a
commit 4fd175e0e4
5 changed files with 290 additions and 10 deletions
+3 -2
View File
@@ -102,7 +102,7 @@ Counts: 4 sources · 19 entities · 47 concepts · 8 decision records.
- [[site-metadata]] — optional park identity (name, operator, VAT, address, contact) in site_config; feeds the ticket header.
- [[valet-overcapacity]] — "full" is soft: operator may valet-accept over capacity (keys handed over, custody). Manned, deferred.
- [[validation-discounts]] — BUILT (2026-07-13): in-park merchant (bar/lavazh) users scan-and-validate on their device (signed event, program↔user binding); booth settles NET + prints gross/discount/net; comp/time-credit/fixed/percent, caps, /setup/site panel, /validate screen.
- [[validation-sponsorship]] — design: sponsor accounts + postpaid B2B (customers park free, business billed monthly); not a permit.
- [[validation-sponsorship]] — design: postpaid B2B sponsorship (customers park free, business billed monthly); its sponsor-account sketch is superseded by [[party-ledger]].
- [[reporting-analytics]] — revenue/occupancy/stay reports + plate-search, all projections over the signed log.
- [[clock-integrity]] — fees depend on the host clock; detect/flag backdating on an offline box.
- [[ticket-encoding]] — transient ticket id (11-digit numeric + Luhn) as Code128; printed at entry, scanned at pay station + exit; barcode geometry must fit paper width (KP-300H overflow); plate-as-ticket alt.
@@ -110,7 +110,7 @@ Counts: 4 sources · 19 entities · 47 concepts · 8 decision records.
- [[device-events]] — unsigned hardware telemetry (relay/printer/camera/reader/input); separate from the signed ledger.
- [[app-logs]] — the third stream: diagnostic logs (backend warn+ pino sink + frontend errors) → app_logs; log:read viewer; pruned by age+row cap.
- [[soft-delete]] — BUILT: accidental admin deletes of master data (users/roles/subs/plans/tariffs) are soft (deleted_at) + recoverable from a recycle bin; auto-purge after N days; signed ledger out of scope.
- [[subscription]] — recurring plan (e.g. 10,000 ALL/month); RF/QR or plate identity, car-count + max-concurrent, host-in-loop; short-circuits payment. (Renamed from "permit"; time-of-day windows noted, deferred.)
- [[subscription]] — recurring plan (e.g. 10,000 ALL/month); RF/QR or plate identity, car-count + max-concurrent, host-in-loop; short-circuits payment. Plan catalog + tariff bridge built. 2026-09-08: **renewal found off-book**; recurring billing (prepaid/postpaid, calendar/anniversary, grace, expiry notice, billing periods as ledger charges) designed, not built.
- [[opencv-anpr-service]] — host-side vision microservice: ANPR (plate identity) + vehicle verification (anti-plate-spoofing witness); fast-alpr (MIT, YOLOv9+CCT/ONNX) the evaluated recognizer baseline.
- [[lane-presence-and-anpr-entry]] — camera vehicle detection → (BUILT) advisory lane busy/free booth lights + (BUILT) the ANPR "bridge" (`anpr-entry.ts`): a subscriber's plate read at the lane admits them via the existing gated subscription flow (match-before-emit; subscriber-only). Measured camera limits; rejected the queue-tracking/livestream ideas.
- [[vision-service-hardening]] — fix/hardening backlog for `apps/vision/` (2026-07-02 reviews): DoS (body-cap, pixel-bomb, event-loop-blocking inference), unauthenticated + operator-writable model weights, `0.0.0.0` default bind, + correctness/hygiene items. Not yet fixed — the to-do list.
@@ -137,6 +137,7 @@ Counts: 4 sources · 19 entities · 47 concepts · 8 decision records.
- [[vision-service-packaging]] — the vision service lives in this monorepo (apps/vision/), separate process, wired into Turbo via a package.json shim; uv-managed Python.
- [[event-streams-split]] — split the signed business ledger (ledger_events) from unsigned device telemetry (device_events).
- [[desktop-shell-tauri]] — ✅ Tauri v2 chosen over Electron for the desktop kiosk shell; thin wrapper, server keeps all logic. Best case Ubuntu 26.04 LTS (resolves WebKitGTK); worst case Windows+WSL → kiosk browser, no native shell. Auto-updater mirrors signed releases to public `mca/public_releases` (source repo is private — field appliances have no Gitea creds).
- [[party-ledger]] — 🟡 DESIGN (2026-09-08, not built): 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, statements are not fiscal invoices, parties per appliance.
- [[venue-modules]] — 🟡 OPEN: optional per-site modules (Car Wash, Bar/Restaurant) with Parking as a peer module on a venue POS/audit core; manifest registry, entitled ∩ activated enablement (vendor env + site-admin config), validation kept for the Bar (Lavazh station retires with Car Wash), name stays parking-system, vision vehicle-category as an advisory anomaly flag.
- [[container-deployment]] — Docker images for the non-desktop apps: parking-server (Fastify API + bundled SPA via @fastify/static) + parking-vision (Python/uv ANPR); branch+SHA tags, per-env compose, Gitea registry, build-images.yml CI; pnpm deploy (not prune) for native better-sqlite3; migrate-at-boot.
- [[fleet-deployment-komodo]] — fleet control plane: Komodo Periphery on each booth, driven by Komodo Core over a NetBird mesh, running the same compose files. Deploys manual + pinned to dev-<sha> (no webhook); secrets Komodo-managed per-booth+unique; booth.sh demoted to break-glass. Threat-model caveats: Periphery is a root agent (mesh-bound only), EVENT_SIGNING_KEY-in-Core is a fraud-root blast radius until ATECC608 signs. komodo/ is infra-as-code.