#5 Gateway Trust Model: - Token validation now uses protected endpoints, not health checks - Unknown services rejected (no fallback to unprotected endpoint) - Trust model documented in docs/trust-model.md #8 CI Enforcement: - Added .gitea/workflows/security.yml with: - Dependency audit (npm audit --audit-level=high for budget) - Secret scanning (checks for tracked .env/.db, hardcoded secrets) - Dockerfile lint (non-root USER, HEALTHCHECK presence) #9 Performance Hardening: - Budget /summary: 1-minute in-memory cache (avoids repeated account fan-out) - Gateway /api/dashboard: 30-second per-user cache (50x faster on repeat) - Inventory health endpoint added before auth middleware Closes #5, #8, #9
2.3 KiB
2.3 KiB
Gateway Trust Model
Architecture
All frontend requests go through: Browser → Pangolin → frontend-v2 (SvelteKit hooks) → gateway → backend services.
Authentication Layers
Gateway (platform auth)
- Users authenticate via
/api/auth/loginwith username/password (bcrypt) - Session stored as
platform_sessioncookie (HttpOnly, Secure, SameSite=Lax) - All
(app)routes require valid session (checked in+layout.server.ts)
Service-level auth
Each backend service has its own auth mechanism. The gateway injects credentials when proxying:
| Service | Auth Type | Injected By Gateway | Validated Against |
|---|---|---|---|
| Trips | Bearer token | Authorization: Bearer {token} |
/api/trips (protected endpoint) |
| Fitness | Bearer token | Authorization: Bearer {token} |
/api/user (protected endpoint) |
| Reader | API key | X-Auth-Token: {key} |
/v1/feeds/counters |
| Inventory | API key | X-API-Key: {key} |
/summary |
| Budget | API key | X-API-Key: {key} |
/summary |
| Books (Shelfmark) | None (proxied) | — | Gateway auth only |
| Music (Spotizerr) | None (proxied) | — | Gateway auth only |
Frontend hooks auth (SvelteKit)
- Immich proxy: validates
platform_sessioncookie before proxying - Karakeep proxy: validates
platform_sessioncookie before proxying - Legacy trips Immich: validates
platform_sessioncookie before proxying
Service Connections
- Users connect services via Settings page
- Token validation uses a protected endpoint, not health checks
- Unknown services cannot be connected (rejected with 400)
- Tokens stored in
service_connectionstable, per-user
Internal Network
- All services communicate on Docker internal network
- No service port is exposed to the host (except frontend-v2 via Pangolin)
- Gateway is the single entry point for all API traffic
TLS
- External HTTPS: default TLS verification (certificate + hostname)
- Internal services:
_internal_ssl_ctxwith verification disabled (Docker services don't have valid certs) - Image proxy: default TLS verification + domain allowlist
Secrets
- All secrets loaded from environment variables
- No hardcoded credentials in code
.envfiles excluded from git- Admin credentials required via
ADMIN_USERNAME/ADMIN_PASSWORDenv vars