diff --git a/obsidian/Crussell/Technical Manual.md b/obsidian/Crussell/Technical Manual.md index 6d4ddf1..8647ca3 100644 --- a/obsidian/Crussell/Technical Manual.md +++ b/obsidian/Crussell/Technical Manual.md @@ -273,6 +273,7 @@ CORS uses `*` in local dev. In production behind Cloudflare, nginx handles CORS. | Method | Path | Auth | Rate Limit | Description | |--------|------|------|------------|-------------| | GET | `/api/services` | Optional | 120/min | List active services (eligibility for authenticated) | +| GET | `/api/services/popular` | Optional | 120/min | List active services sorted by booking popularity (last 6mo), then price desc | | GET | `/api/services/eligible-for/{user_id}` | Admin | 120/min | Services filtered by user's age/patch test | | POST | `/api/register` | None | 10/min | Create user account (optional `referralCode` field) | | POST | `/api/login` | None | ProgressiveRateLimit + RateLimit(10, 1min) | Authenticate, receive JWT + refreshToken. Account lockout after 5 failures (15min→30min→1h→2h). | @@ -1033,6 +1034,7 @@ A record is only deleted when **both** applicable conditions are met — the 7-y **Admin vs. Customer:** - `/api/services` — returns services with eligibility for authenticated users +- `/api/services/popular` — returns services sorted by booking popularity (last 6mo), then price descending (used by the prices page) - `/api/services/eligible-for/{user_id}` — admin-only, returns services for specific user (used in admin booking flows) ---