docs: add product overview and engineering documentation
Document architecture, security, deployment, and development for contributors.
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
# Security
|
||||
|
||||
## Authentication and sessions
|
||||
|
||||
| Mechanism | Details |
|
||||
|-----------|---------|
|
||||
| Login | username/email + password + image CAPTCHA |
|
||||
| Access JWT | Short-lived (~15 minutes) |
|
||||
| Refresh | Hashed in DB; remember-me ≈ 30 days, short session ≈ 24 hours |
|
||||
| Browser cookies | `pargar_access` / `pargar_refresh` — `HttpOnly`, `SameSite=Lax`, `Secure` when `PUBLIC_URL` is https |
|
||||
| Frontend storage | Only `user` in `localStorage` (`pargar.auth`); tokens are not persisted |
|
||||
| API | `credentials: "include"`; optional Bearer for tests/clients |
|
||||
| Logout | Revoke refresh + clear cookies |
|
||||
|
||||
Public password recovery (`/api/auth/recovery/*` and `/recovery`) is disabled for students (404). Resets are admin-only and require the target account’s security answer.
|
||||
|
||||
## Secrets
|
||||
|
||||
- Outside `DEV_MODE`, `Validate()` rejects values like `change-me` / `local-dev-only` and JWTs shorter than 32 characters.
|
||||
- Local Helm: generate-once; production: `existingSecret` required.
|
||||
- `ADMIN_PASSWORD` only bootstraps when the admin user is missing; restarts do not overwrite the password.
|
||||
|
||||
## Proxy and CORS
|
||||
|
||||
- Only peers in `TRUSTED_PROXY_CIDRS` are trusted for `X-Forwarded-*` / `X-Real-IP`.
|
||||
- CORS: `FRONTEND_ORIGINS` + `PUBLIC_URL` with `AllowCredentials: true`.
|
||||
|
||||
## Rate limiting
|
||||
|
||||
| Scope | Approximate behavior |
|
||||
|-------|----------------------|
|
||||
| Auth (login/register/captcha/refresh/recovery) | Redis per-IP budget; tighter after failures |
|
||||
| Global `/api/*` | ~240 req/min/IP; 429 + user message + `Retry-After`; does not revoke tokens |
|
||||
| External chat export | ~10/min/IP |
|
||||
| Per-user uploads | Separately limited |
|
||||
|
||||
`/api/health` is excluded from the global ceiling.
|
||||
|
||||
## Uploads
|
||||
|
||||
| Type | Controls |
|
||||
|------|----------|
|
||||
| Admin video | Extension + MIME + magic (MP4/WebM) |
|
||||
| Avatar | JPEG/PNG/WebP via magic only; client Content-Type is not trusted |
|
||||
| Chat | Extension allow-list + sniff for image/video/audio/PDF/Office; raw public zip removed |
|
||||
|
||||
## Certificates and privacy
|
||||
|
||||
- Certificate URLs are unlisted; noindex via API, Traefik, Next, and robots.txt.
|
||||
- Chat-export tokens are single-use, revocable, and redacted from logs/metric labels.
|
||||
|
||||
## Known trade-offs (current model)
|
||||
|
||||
- SameSite=Lax + same-origin instead of a separate CSRF token (adequate for this model; revisit if FE and API split domains).
|
||||
- Donations and physical certificates have no online payment gateway — intentional.
|
||||
- XSS remains dangerous; HttpOnly cookies reduce token theft from localStorage but do not eliminate XSS.
|
||||
Reference in New Issue
Block a user