# Security & Technical Debt Items identified during code review that should be addressed before production. ## High Priority ### Token refresh logic in SvelteKit (`apps/dashboard/src/auth.ts`) The JWT callback stores `expiresAt` and `refreshToken` but never checks expiry or initiates a refresh. Auth.js does not auto-refresh tokens. Without this, users get silently logged out when their access token expires (typically 5-15 minutes for Zitadel). **Fix:** Add expiry check in the `jwt` callback and use `refreshToken` to obtain a new access token when expired. ### JWKS cache thundering herd (`crates/pvm-auth/src/jwks.rs`) When the cache expires, every concurrent request sees stale cache and calls `refresh()` simultaneously. The `RwLock` serializes writes but each request still makes an HTTP call before acquiring the lock. **Fix:** Add a "refresh-in-progress" flag or use double-checked locking so only one request triggers the refresh while others wait. ### Social login providers (Zitadel IDP configuration) Configure external identity providers in Zitadel so users can sign in with social accounts. Each requires creating OAuth2 credentials with the respective provider and registering them in Zitadel Console → Settings → Identity Providers. 1. **Google** — Google Cloud Console OAuth 2.0 Client ID 2. **Apple** — Apple Developer Sign in with Apple service ID + key 3. **Facebook** — Meta for Developers app with Facebook Login product No code changes needed in the SvelteKit app — Zitadel's login page shows social buttons automatically once IDPs are configured. ## Medium Priority ### `trustHost: true` in auth.ts Disables CSRF origin check in Auth.js. Required for local dev behind localhost, but must be removed or made conditional for production. ### `devMode: true` in OIDC app config (`docker/setup-zitadel.sh`) Disables redirect URI validation in Zitadel. The setup script is dev-only, but if a similar script is used for production, this must be `false`. ### Custom login UI Replace the default Zitadel login v1 UI with a fully custom login/signup flow built into the SvelteKit dashboard using Zitadel's Session API. Includes: login, signup, password reset, 2FA flows. Must match PVM visual design. ## Low Priority ### Shell script JSON parsing (`docker/setup-zitadel.sh`) Uses `grep -o` and `cut` to extract JSON fields. Fragile if JSON format changes. Consider using `jq` with a fallback. ### PAT expiration Machine user PAT expires 2030-01-01. Fine for dev, but production should use shorter-lived credentials. ### Running Zitadel as root (`docker-compose.dev.yml`) `user: "0"` is required for `start-from-init` to write the PAT file. Dev-only concern — production deployment should use proper volume permissions.