Setpoint Academy proposal · DocumentAll deliverables · Scope · Mockups

00 · Context: what was read, what was confirmed, what was not

Proposal package for Nestor, prepared 16 September 2026 on Alvaro's brief. Nothing in ~/cowork/setpoint was changed; local Supabase was started for read-only schema queries only; the production env file was never read.

What was read

Ground truth carried forward (not re-audited):

Repo, by three read-only readers (findings in _research-*.md, every claim with file:line):

Data shape: the 10 September 2026 exports in ptp-academy-control/data/raw/ (Setpoint admin API pulls of packages, classes, students with package history, lessons 1 Aug–11 Sep with rosters, group schedule, POS payments, the Sheet tabs) and outputs/academy-control-data.json (audited fixture).

What was confirmed in code or schema

Local Supabase (supabase start on CLI 2.116.0, 177 public tables, all migrations applied, seed data only):

Fact Where
Ledger reasons today: purchase_grant, consume, refund, admin_adjust, backfill_balance, renewal_reset, expiry_forfeit, cancellation_forfeit; balance_after >= 0; source live/backfill package_session_transactions CHECKs
Sessions are deducted when a lesson is created: create_lesson_atomic is the only SQL caller of consume_package_session; adding a player later goes through the lessons PATCH route; removals refund through cancel-lesson-cascade.ts pg_proc search + _research-ledger-billing.md §2
lesson_players.status = confirmed / held / cancelled; checked_in_at and attended exist and never touch the ledger schema + research §2
lessons.status = scheduled / completed / cancelled / no_show schema
player_packages.status = active / exhausted / expired / cancelled; billing_mode, next_billing_date, billing_anchor_day, current_period_start/end, stripe_subscription_id, stripe_payment_intent_id schema
Counters live on player_package_sessions (sessions_remaining, sessions_used), not on player_packages schema
process-package-billing creates payment_requests and queues reminders; grants no sessions; mints no Stripe link; skips packages with stripe_subscription_id; hourly cron function + research §4
academy_payment_settings: enabled (false), reminder_offsets {-3,0,3,7}, channels {email}, send_hour_local 9, default_due_days 7, pay_at_club_instructions. No day-26, past-due, freeze or grace settings exist schema
cancellation_policies.applies_to_lessons exists; students still have no lesson-cancel route (api/v1/me/lessons/[id] is GET only) schema + research
payments.payment_method = stripe / cash / credits / pending / other / package / external; POS bridge trigger record_academy_payment_in_pos on payments schema
WhatsApp: manual wa.me lane with status sent_manual; Cloud provider throws by design (DEC-323: Meta verification, number, templates) apps/admin/src/lib/messaging/providers/*
No lead/prospect entity; facility_customers is not in production (two migration headers say so) research §1
No requireRole helper; ~20 files re-declare role constants with inconsistent meaning; team routes have no role gate research §3
No admin-wide audit log; POS activity log swallows errors by design and a decision entry rejects that pattern for anything with stakes research §4
dnd-kit v6 already a dependency (court-images dialog only); PATCH /api/admin/lessons/[id] moves a lesson with conflict checks (409); bookings PATCH refuses lesson legs research planning §1
Groups have no link to classes or lessons (migration header says so) 20260722032430
availability_override is dropped by the lessons PATCH route (editableFields omits it) research planning §4
Coach PWA (Flutter) has no push capability; no push anywhere research planning §6
Highest e2e spec is tc-283; Academy Health takes tc-284 research §8
Docs: latest version v0.51.0, latest decision DEC-329; monthly-planning stale at April 2026 research crm §6

Real shape from the exports (Pad Thai Padel, 10–11 Sep 2026): 16 lesson packages (Essential and Performance recurring monthly; Growth session_bank with billing_period='monthly'; 13 session banks with 90 or 365 days), all billing_mode='manual'; 18 classes (11 group max 4); 112 students with package history, 96 active packages, 9 students with more than one active package, 62 packages with expires_at null; 469 lessons 1 Aug–11 Sep (248 scheduled, 221 cancelled); 698 roster seats, 52 check-ins, 5 attended flags, 1 seat with paid_amount > 0.

What could not be confirmed