#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)
77 lines
3.6 KiB
Markdown
77 lines
3.6 KiB
Markdown
# 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/login` with username/password (bcrypt)
|
|
- Session stored as `platform_session` cookie (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_session` cookie before proxying
|
|
- Karakeep proxy: validates `platform_session` cookie before proxying
|
|
- Legacy trips Immich: validates `platform_session` cookie 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_connections` table, per-user
|
|
|
|
## Per-User Navigation
|
|
- Each user sees only their configured apps in the navbar
|
|
- Configured via `hiddenByUser` map 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
|
|
- `.env` files excluded from git
|
|
- Admin credentials required via `ADMIN_USERNAME`/`ADMIN_PASSWORD` env 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
|