#5 Gateway Trust Model: - Removed inventory /test endpoint - Updated docs/trust-model.md with accurate description: - Per-user services (trips, fitness) vs gateway-key services clearly separated - Known limitations documented (no per-user isolation on shared services) - No false claims about per-user auth where it doesn't exist #8 Dependency Security: - Workflow reviewed and confirmed sane - Added .gitea/README.md documenting runner requirement - Status: repo-side complete, operationally blocked on runner setup #9 Performance Hardening: - Budget /transactions/recent: 30s cache (1.1s→41ms on repeat) - Budget /uncategorized-count: 2min cache (1.3s→42ms on repeat) - Both endpoints document Actual Budget per-account API constraint - Budget buildLookups: 2min cache (already in place) - All inventory full scans already eliminated (prior commit)
3.6 KiB
3.6 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) - Registration is disabled (returns 403)
Service-level auth
Services fall into two categories:
Per-user token services — each platform user has their own service credential:
| Service | Auth Type | How Injected | Per-User Data? |
|---|---|---|---|
| Trips | Bearer token | Authorization: Bearer {token} |
No — all users see all trips |
| Fitness | Bearer token | Authorization: Bearer {token} |
Yes — each user has own entries, goals, favorites |
Gateway-key services — a single API key shared by all platform users:
| Service | Auth Type | How Injected | Per-User Data? |
|---|---|---|---|
| Inventory | API key | X-API-Key: {key} |
No — single shared inventory |
| Budget | API key | X-API-Key: {key} |
No — single shared budget |
| Reader | API key | X-Auth-Token: {key} |
No — single shared feed reader |
| Books (Shelfmark) | None | Proxied through gateway | No — single shared download manager |
| Music (Spotizerr) | None | Proxied through gateway | No — single shared music downloader |
Important: Gateway-key services do NOT have per-user data isolation. Any authenticated platform user can access all data in these services. This is by design — the household shares a single budget, inventory, reader, and media library.
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 per-user services (trips, fitness) via Settings page
- Token validation uses a protected endpoint per service type — not health checks
- Unknown services cannot be connected (rejected with 400)
- Tokens stored in
service_connectionstable, per-user
Per-User Navigation
- Each user sees only their configured apps in the navbar
- Configured via
hiddenByUsermap in+layout.server.ts - Apps not in nav are still accessible via direct URL (not blocked)
Internal Network
- All services communicate on Docker internal network via plain HTTP
- No service port is exposed to the host (except frontend-v2 via Pangolin)
- Gateway is the single entry point for all API traffic
- No custom SSL context — all internal calls are plain HTTP
TLS
- External HTTPS (OpenAI, SMTP2GO, Open Library): default TLS verification
- Internal services: plain HTTP (Docker network, no TLS needed)
- Image proxy: default TLS verification + domain allowlist + content-type validation
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 - Service API keys generated per service, stored in
.env
Known Limitations
- Gateway-key services are shared — no per-user access control
- Books and Music services have no auth at all (rely on gateway session only)
- Shelfmark and Spotizerr accept any request from the Docker network
- Per-user nav hiding is cosmetic — direct URL access is not blocked