Proposal · v0.32.0
TPS mobile <-> Setpoint admin — publish open matches & priced programs to the app
Court bookings and coach lessons already sync both ways between the TPS app and Setpoint admin over OpenRally. Open matches and programs don't — and both features sit parked in Setpoint admin today. This proposal revives them and extends the exact same plumbing: a Setpoint club publishes an open match or a program, TPS players discover and join it (paying on join, like a court booking), and the roster stays in sync on both sides. One new, neutral bookable type on the wire — nothing reinvented.
The gap today
Why it matters: Open matches and programs are core engagement and revenue for a padel club — the natural next step after courts and coaching. Until they flow over OpenRally, every match or clinic a TPS player wants to join is manual coordination, and the parked Setpoint features deliver no value.
Outcome
The one prerequisite
Setpoint's join/enrol flow today marks a seat as paid the instant the card intent is created — before the payment actually clears — and nothing reconciles it afterwards. It's harmless right now only because Setpoint runs Stripe in test mode. The moment a TPS player joins with a real card, that becomes real money with no safety net.
Resolution: Phase A rewrites join to a hold-seat -> pay -> confirm lifecycle (a seat only counts once payment clears) and adds the missing reconciliation. This is a hard go/no-go gate: no paid match or program is exposed over OpenRally until it passes.
Already decided
Is 'Events' a new feature to build?
Decision: No. 'Events' is just the display label for Setpoint's existing Matches feature (an open match). There's no separate entity — we revive Matches and surface it under the Event label.
Why: Verified in the code: the 'Event' badge maps directly to a match. Building a new entity would duplicate what already exists.
How do matches and programs appear on the OpenRally wire?
Decision: As ONE neutral, capacity-bearing bookable type (a 'session') carrying an opaque category tag. The protocol never learns the words 'match' or 'program'.
Why: Keeps OpenRally consumer-agnostic — it must never know about TPS or Setpoint's internal feature names. TPS routes on the opaque tag to its own native screens. Dominant industry pattern (generic object + classifier).
Where do Setpoint matches/programs show up in the TPS app?
Decision: Natively. A Setpoint open match renders in the existing TPS open-match rail; a Setpoint program renders in the existing TPS events (paid-join + waitlist) rail. No new 'OpenRally' screen.
Why: Native-equivalence: a Setpoint-origin item must look and behave like a TPS-native one. No separate tab, no parallel UX.
Who charges the player, given Setpoint runs test Stripe keys and TPS charges real cards?
Decision: TPS owns the charge (real Stripe, in-app). Setpoint records the payment as consumer-settled via OpenRally's payment block. Setpoint never charges the card.
Why: Matches how court + coaching payments already work across the boundary, and keeps the Setpoint live-keys cutover decoupled from this feature.
Is this a rebuild of the parked Setpoint features?
Decision: No — it's a revive. The schema and most code are current; the one genuinely unfinished piece is the pay-on-join path. All database changes are additive only.
Why: Verified against the live schema: no drift to chase. A rebuild would fork the match data TPS would consume.
How it works
TPS player finds an open match or clinic
The player browses Pad Thai open matches and programs in the app. OpenRally lists each one with its price and spots remaining, drawn live from Setpoint.
Their seat is held while they pay
Tapping 'Join' reserves a seat for a few minutes so nobody else takes the last spot mid-checkout — the same hold mechanism courts and lessons already use.
Player pays in TPS
The player pays in the TPS app with a real card (or PromptPay), exactly like a court booking. Setpoint records the payment; it never charges the card itself.
Roster updates in Setpoint
On successful payment, OpenRally confirms the seat: the TPS player joins the match/program roster in Setpoint admin, the spot count drops, and the player sees it in their TPS bookings.
Operator creates a match or program in Setpoint admin
The revived Matches/Programs screens — operator sets type, capacity, price, time, court (optional for socials), and waitlist. Nothing new to learn versus today's booking screens.
It publishes to OpenRally automatically
The moment it's saved, it appears to TPS as a joinable session with its capacity and price. TPS players see it in the Play feed with 'X spots left'.
Changes and cancellations stay in sync
If the operator cancels or capacity changes, OpenRally notifies TPS. Players who joined through TPS see the update in their bookings automatically.
Rollout
| Phase | Scope | Operator sees | Player sees |
|---|---|---|---|
| Phase A — GATE | Setpoint — fix the pay-on-join path (hold -> pay -> confirm + payment reconciliation). No-go gate for everything paid below. | Nothing visible yet | Nothing yet |
| Phase B | Setpoint — additive producer schema: capacity + seat-hold, court-less matches, external-payment recording, program events, webhook auto-provisioning. | Matches/Programs prepared behind the scenes (still hidden) | Nothing yet |
| Phase C | OpenRally — add the neutral 'session' bookable type (discover, hold, join, cancel, events), modelled on the existing lesson endpoints. | Nothing (protocol-only) | Nothing yet |
| Phase D | TPS backend — consume sessions: inbound webhook + join/confirm/cancel, writing back to TPS's own match/event tables. | TPS-joined players now appear on the Setpoint roster | Nothing yet (backend only) |
| Phase E | TPS app — render Setpoint matches in the open-match rail and programs in the event paid-join rail, behind a feature flag. | No change | Can discover + join Pad Thai matches and programs end-to-end, same UX as courts |
Needs your call
Does going live trigger Setpoint's real-Stripe cutover?
TPS charges real cards regardless. The question is whether Setpoint also flips from test to live keys now, or stays in test mode for launch. The payment-path fix (Phase A) is required either way.
Matches and programs together, or matches first?
They share the same engine and the same payment fix. Shipping both together is little extra; matches-first is a smaller first cut.
Confirm the go-ahead to un-park Matches & Programs.
They were parked with only a 'known issues' note — no recorded reason. We'd log the revive decision before building.
Do open matches need a waitlist?
Programs already have one; matches don't today. A waitlist for matches is net-new scope on whichever base we pick.
Programs render via the TPS event rail, not the academy screen — confirm?
The TPS academy 'Program' screen is a dead brochure. The live home for a paid, capacity-bearing program is the TPS event (paid-join + waitlist) rail.
Next
Demo
Test club: Sandbox Pad Thai Padel (TPS production, connected to a Setpoint facility)