Rate limiting (middleware-level):
- 120 requests/minute per IP for all /api/* routes
- Returns 429 with retry-after header when exceeded
- In-memory store (per-container, sufficient for single-instance)
Webhook dispatcher wired to events:
- license.created → fires when a new license is issued
- ticket.created → fires when a support ticket is created
- instance.provisioned → fires when a tenant instance goes live
- Each event includes relevant payload (key, product, URL, etc.)
- Fire-and-forget (doesn't block the response)
- HMAC-SHA256 signed (existing webhook.ts implementation)
Also:
- Ticket creation now sends email notification (sendTicketCreatedEmail)
Edge runtime doesn't have access to AUTH_SECRET env var, so HMAC
verification fails. Instead: just check if the cookie exists and isn't
expired. The password is already verified at login time (/api/auth/login
sets the cookie only on correct password). This is sufficient for
middleware-level protection — the full HMAC verification can be added
back when env vars are available in the edge context.
The login route encodes the payload with base64url but the middleware was
decoding with base64 — mismatch caused session verification to always fail,
making protected APIs return 401 even after successful login.
CRITICAL SECURITY FIXES:
- src/middleware.ts: protects all routes except public ones (health, license check, seed-prod)
Redirects unauthenticated users to /login, returns 401 for API routes
- src/app/login/page.tsx: login page with password input
- src/app/api/auth/login: HMAC-signed session cookie (7-day expiry)
- src/app/api/auth/logout: clears session cookie
- Top bar: Abmelden (logout) button now functional
- .env removed from git tracking (secrets no longer in repo)
- seed-prod: hardcoded admin token replaced with env MCP_API_TOKEN or random UUID
- ADMIN_PASSWORD env var required for login (set in Dokploy env)
Public routes (no auth needed):
/api/health, /api/aos/seed-prod, /api/aos/licenses/check, /api/aos/licenses/validate
/api/v1/* (token-auth'd), /api/mcp (token-auth'd), /login