# RTSport — Product Roadmap & State of the Build > 2026-05-08 | Compiled by Wadsworth 📋 --- ## Current Architecture (what actually exists) ### Layer 1: RTSport Standalone API (port 8001) **Status: ✅ Core backend built and running** ``` Location: ~/.openclaw/shared/build-20260501/backend/ Framework: FastAPI + SQLAlchemy Database: SQLite (rtsport_test.db) with PostgreSQL migration path Auth: JWT with role-based access (at/coach/parent/admin) ``` | Component | File | Lines | State | |-----------|------|-------|-------| | Database models | `app/models.py` | 285 | ✅ Complete — User, School, Athlete, Case, Milestone, Event | | Pydantic schemas | `app/schemas.py` | 316 | ✅ Complete | | JWT Auth | `app/auth.py` | 191 | ✅ Complete — login, token creation/verification, role guards | | Auth endpoints | `app/api/auth.py` | 168 | ✅ Complete — /login (OAuth2), /login/json, /me | | Athletes API | `app/api/athletes.py` | 321 | ✅ Complete | | Cases API | `app/api/cases.py` | 544 | ✅ Complete — CRUD, milestones | | Roster API | `app/api/roster.py` | 328 | ✅ Complete — role-gated (at/coach only) | | Events API | `app/api/events.py` | 409 | ✅ Complete — sideline entry, general events | | Dashboard API | `app/api/dashboard.py` | 892 | ✅ Largest module — AT/Coach/Parent/AD dashboards | | Admin API | `app/api/admin.py` | 320 | ✅ Complete — stats, roster management | | Seed data | `seed_data.py` | — | ⚠️ Only seeds parent@example.com | | Tests | `tests/` | — | ✅ test_auth.py, generate_test_data.py | **25 live endpoints**, role-based access control enforced. ### Layer 2: HoffDesk Proxy Layer (port 8000) **Status: ✅ Partial proxy with mock fallbacks** ``` Location: ~/.openclaw/workspace-socrates/hoffdesk-api/ ``` | Component | File | What it does | State | |-----------|------|--------------|-------| | Static mock router | `rtsport_mock.py` | Serves static HTML/CSS/JS for all dashboards | ✅ Live via RTS_BASE → shared/current/frontend | | API proxy | `rtsport_api_proxy.py` | Forwards /api/v1/rtsport/* → port 8001 | ✅ Live | | Coach API (mock) | `rtsport_coach_api.py` | In-memory mock data, 8 endpoints, shares MESSAGES with parent API | ✅ Live, bypasses port 8001 | | Parent API (mock) | `rtsport_parent_api.py` | In-memory mock data, 6 endpoints, linked to coach API | ✅ Live, bypasses port 8001 | | Login router | `login_router.py` | Serves /rtsport/login page | ✅ Live | | Unified auth | `auth/router.py` | Session cookies for admin, Bearer for API | ✅ Live (HoffDesk family, not RTSport-specific) | ### Layer 3: Frontend (served as static files) **Status: ✅ All role dashboards built** | Dashboard | File | Lines | Features | |-----------|------|-------|----------| | AT Dashboard | `templates/at/dashboard.html` | — | Roster, case management, sideline entry | | Coach Dashboard | `templates/coach/dashboard.html` | ~1550 | Roster cards, status filter, injury breakdown, timeline, messages | | Parent Dashboard | `templates/parent/dashboard.html` | ~1200 | Child selector, case milestones, restrictions, care team, messages | | AD Dashboard | `templates/ad/dashboard.html` | — | Admin stats, school-wide overview | | Login | `templates/login.html` | 67 | Dark theme, role-based redirect | | Shared components | `templates/components/` | — | Athlete detail, notifications, timeline | | CSS | 5 files | ~2936 lines | Dark theme, mobile-first, role-specific styles | | JS | 5 files | ~2726 lines | Tab logic, API clients, auto-login, mock data | --- ## The Two Systems Problem Right now RTSport runs as **two parallel systems**: ``` User → https://hoffdesk.com/rtsport/coach → rtsport_mock.py serves coach/dashboard.html → dashboard.html JS calls /api/v1/dashboard/coach/status?school_id=schl_001 → This routes to rtsport_coach_api.py (IN-MEMORY MOCK DATA) → NOT the real RTSport API at port 8001 Meanwhile: RTSport API at port 8001 has full CRUD, real DB, role guards → But the frontend doesn't call it directly → The proxy at port 8000 → 8001 only handles /api/v1/rtsport/* paths → Coach/Parent dashboard endpoints are LOCAL_PATHS (not proxied) ``` **Root cause:** The coach and parent dashboard API endpoints are deliberately excluded from the proxy (`LOCAL_PATHS` in `rtsport_api_proxy.py`) because they have mock implementations in `rtsport_coach_api.py` and `rtsport_parent_api.py`. The real API at 8001 has its own `/dashboard/coach` and `/dashboard/parent` endpoints, but they're unreachable from the frontend. --- ## Auth State — What Works, What Doesn't | Flow | Status | Detail | |------|--------|--------| | Login page | ✅ | /rtsport/login serves dark theme login form | | Login API call | ✅ | POST /api/v1/auth/login/json → returns JWT + role + school_id | | Role-based redirect | ✅ | JS routes to correct dashboard based on role | | Token storage | ✅ | localStorage: rtsport_token, rtsport_role, rtsport_school_id | | Auto-login (dashboard direct access) | ⚠️ Works, but insecure | Hardcoded credentials in dashboard.html: `email: 'parent@example.com', password: 'testpass123'` | | Auth guard on dashboard | ❌ Missing | No redirect to login if token invalid/missing — API calls fail silently | | Auth guard on API | ⚠️ Partial | Port 8000 mock APIs accept any non-empty token (no real validation). Port 8001 has real JWT validation + role guards. | | Role-based API access | ✅ Port 8001 | "Access denied. Required role: one of ['at', 'coach']" | | Password hashing | ✅ | bcrypt via passlib in port 8001 auth.py | | Session management | ✅ Admin only | Cookie-based for HoffDesk admin, not used for RTSport | --- ## Database: Multi-Tenant Design (already built) ``` Schema: Single database, school_id on every table Already implemented in models.py ``` | Table | Multi-tenant column | Indexed | |-------|-------------------|---------| | schools | id (PK) | domain | | users | school_id | ✅ school_id, email, role | | athletes | school_id | ✅ school_id, current_status, sports, team | | cases | school_id, athlete_id | ✅ school_id, athlete_id, status, opened_at | | milestones | school_id, case_id | — | | events | school_id, case_id | — | **Scale model:** - 1 database, ~10 tables, school_id column on every query - SQLite for dev/small deployments (<100 schools), PostgreSQL for production - Indexed by school_id on every table — fast multi-tenant queries - JWT encodes school_id so a user can't query another school's data **Seed data gap:** Only `parent@example.com` is seeded in the real database. Coach, AT, and admin accounts exist only in the mock Python dicts. --- ## Blockers & Prioritized Work ### 🔴 Blocking Go-To-Market | # | Blocker | Impact | Effort | |---|---------|--------|--------| | 1 | **Unify the two API systems** — frontend calls real API at 8001, not mock dicts | Users see inconsistent/empty data. Mock data doesn't persist. | Medium (1-2 days) | | 2 | **Seed full test data** — coach, AT, admin accounts + realistic athlete roster in the real DB | Can't demo multi-role flows end-to-end | Small (2-4 hours) | | 3 | **Auth guard on dashboards** — redirect to login if no valid token | Direct dashboard access shows broken pages | Small (1-2 hours) | | 4 | **Remove hardcoded credentials** from dashboard.html | Security risk, even for demo | Small (1 hour — just rely on login page) | ### 🟡 Needed Before Beta | # | Item | Detail | |---|------|--------| | 5 | AT Dashboard: case creation form → real API | Currently uses mock data | | 6 | Sideline entry → real event creation API | Endpoint exists, frontend not wired | | 7 | Message persistence — currently in-memory, lost on restart | Port 8001 needs message table + endpoints | | 8 | Role-based UI — hide elements based on role | Coach shouldn't see AT-only actions | ### 🟢 Post-Beta / v1.1 | # | Item | Detail | |---|------|--------| | 9 | PostgreSQL migration | SQLite works for beta, PG needed for concurrent users | | 10 | Admin onboarding flow — create school, invite users | Currently manual DB inserts | | 11 | Email notifications | Case updates, milestone completions | | 12 | Mobile app shell | PWA wrapper around existing responsive HTML | --- ## Go-To-Market Estimate ### What's Done - ✅ Full database schema with multi-tenant design - ✅ JWT auth with role-based access (bcrypt, token refresh ready) - ✅ 25 API endpoints with role guards - ✅ All 5 role dashboards (AT, Coach, Parent, AD, Login) - ✅ Mobile-first responsive CSS (~3000 lines) - ✅ Coach dashboard: status cards, injury breakdown, recovery timeline, athlete messages - ✅ Parent dashboard: child selector, milestones, restrictions, care team, activity feed - ✅ AT dashboard: roster view, case management UI - ✅ AD dashboard: admin stats (mock) - ✅ Sideline entry form (frontend) - ✅ Shared components (athlete detail, notifications, timeline) - ✅ HTTPS via Cloudflare, secure in production posture ### What Remains - 🔴 Unify APIs (1-2 days) - 🔴 Seed data + auth hardening (1 day) - 🟡 Wire frontend to real API (2-3 days) - 🟡 Message persistence (1 day) - 🟡 Polish + bug fixes (1-2 days) ### Timeline Estimate | Milestone | Effort | Target | |-----------|--------|--------| | **Demo-ready** (all roles work, real data) | 1 week | May 15 | | **Beta-ready** (persistent messages, polished UI) | 2-3 weeks | May 22-29 | | **Production MVP** (PG migration, onboarding) | +2 weeks | June 12 | --- ## Immediate Recommended Actions 1. **Unify APIs** — Remove LOCAL_PATHS exclusion in proxy, have coach/parent dashboards call real port 8001 endpoints. Delete mock coach/parent API files. 2. **Seed database** — Add coach@, at@, admin@ accounts + 10-15 athletes with real cases to rtsport_test.db. 3. **Auth guard** — Add 10 lines of JS to each dashboard: `if (!getAuthToken()) window.location = '/rtsport/login'` 4. **Kill auto-login** — Remove hardcoded credential block from dashboard HTML files.