docs: remove admin SPA references and update production URLs

The admin SPA (apps/admin/) has been retired. Its functionality now
lives in apps/app/ under /platform/* routes for super_admin users.
Updated all documentation to reflect: 2 SPAs instead of 3, removed
FRONTEND_ADMIN_URL/port 5173 references, changed production URL from
app.crewli.app to crewli.app. Retired admin-specific security audit
findings (A13-2, A13-4, A13-5, A13-7) and APPS-01 backlog item.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-15 08:21:44 +02:00
parent 2933d957a6
commit 945e22f322
13 changed files with 102 additions and 168 deletions

View File

@@ -7,14 +7,13 @@
## 1. Authentication Overview
Crewli uses **stateless token-based authentication** via Laravel Sanctum. Three SPA clients communicate with a single REST API. Tokens are stored exclusively in **httpOnly cookies** set by the server — they are never exposed to JavaScript via response bodies, localStorage, or JS-readable cookies.
Crewli uses **stateless token-based authentication** via Laravel Sanctum. Two SPA clients communicate with a single REST API. Tokens are stored exclusively in **httpOnly cookies** set by the server — they are never exposed to JavaScript via response bodies, localStorage, or JS-readable cookies.
### Client Applications
| App | URL (dev) | URL (prod) | Purpose |
|-----|-----------|------------|---------|
| Admin | localhost:5173 | admin.crewli.app | Super admin / platform management |
| App | localhost:5174 | app.crewli.app | Organiser dashboard |
| App | localhost:5174 | crewli.app | Organiser dashboard + platform admin (`/platform/*` for super_admin) |
| Portal | localhost:5175 | portal.crewli.app | Volunteers, artists, suppliers |
### Access Modes
@@ -30,7 +29,6 @@ The Portal supports two access modes:
| App | Cookie Name | Domain | Secure | httpOnly | SameSite | Max-Age |
|-----|-------------|--------|--------|----------|----------|---------|
| Admin | `crewli_admin_token` | `.crewli.app` (prod) / `localhost` (dev) | Yes (prod) | Yes | Strict | 7 days |
| App | `crewli_app_token` | `.crewli.app` (prod) / `localhost` (dev) | Yes (prod) | Yes | Strict | 7 days |
| Portal | `crewli_portal_token` | `.crewli.app` (prod) / `localhost` (dev) | Yes (prod) | Yes | Strict | 7 days |
@@ -57,7 +55,7 @@ The `CookieBearerToken` middleware (registered before `auth:sanctum` in the API
3. Reads only that cookie and sets `Authorization: Bearer` on the request
4. Sanctum's existing token validation processes the header normally
**Cross-app isolation:** In local development, all three SPAs share `localhost` (different ports). Browsers do not scope cookies by port, so all three app cookies are sent with every API request. The middleware prevents cross-app authentication by only reading the cookie that matches the requesting app's Origin header. Without this, logging into one app would authenticate all apps.
**Cross-app isolation:** In local development, both SPAs share `localhost` (different ports). Browsers do not scope cookies by port, so both app cookies are sent with every API request. The middleware prevents cross-app authentication by only reading the cookie that matches the requesting app's Origin header. Without this, logging into one app would authenticate the other.
If the `Origin` header is absent (e.g. server-to-server requests), the middleware falls back to the first available cookie. If an `Authorization` header is already present (e.g. from the portal token flow), the middleware skips cookie injection entirely.
@@ -170,7 +168,6 @@ Request
| Setting | Location | Purpose |
|---------|----------|---------|
| `SESSION_DOMAIN` | `.env` | Cookie domain (`.crewli.app` in prod, `localhost` in dev) |
| `FRONTEND_ADMIN_URL` | `.env` / `config/app.php` | Admin SPA origin (cookie name resolution + CORS) |
| `FRONTEND_APP_URL` | `.env` / `config/app.php` | App SPA origin |
| `FRONTEND_PORTAL_URL` | `.env` / `config/app.php` | Portal SPA origin |
| `sanctum.expiration` | `config/sanctum.php` | Token TTL (7 days = 10080 minutes) |