Files
platform/docs/trust-model.md
Yusuf Suleman 4ecd2336b5
Some checks failed
Security Checks / dependency-audit (push) Has been cancelled
Security Checks / secret-scanning (push) Has been cancelled
Security Checks / dockerfile-lint (push) Has been cancelled
fix: complete remaining remediation (#5, #8, #9)
#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
2026-03-29 10:13:00 -05:00

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/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)

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_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 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_connections table, 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_ctx with 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
  • .env files excluded from git
  • Admin credentials required via ADMIN_USERNAME/ADMIN_PASSWORD env vars