- credential-manager.js: add diagnose(key) method that distinguishes
ok | missing | unreadable | corrupt instead of silently returning null
- crypto-utils.js: silent fallback to .encryption-key.bak when primary
can't decrypt existing credentials; first-run bootstrap writes .bak;
rotateKey() backs up old key before swap
- routes/auth/totp.js: new public /api/v1/totp/recovery-info endpoint
returns {status, isSetUp, hint} so UI can show meaningful errors
- middleware.js: add /totp/recovery-info to PUBLIC_ROUTES so the
locked-out user can read the diagnostic without being logged in
- Set Domain=.sami on session + CSRF cookies so browsers send them to all subdomains
- This fixes Caddy forward_auth returning 401 for radarr/sonarr/prowlarr
- Fix login URL concatenation bug (radarr.samilogin -> radarr.sami/login)
- Fix getSetCookie() missing from _httpsFetch/_httpFetch response objects
- Fix array/string handling for set-cookie header in session-handlers fallback
- Refactor csrf-protection to createCSRFMiddleware() factory with cookieDomain support
- Pass renewCSRFToken through middleware deps chain to TOTP route
- Fix service edit double-write bug (was creating duplicate entries)
- Add editable display name field to service edit modal
- Backend update endpoint now accepts name, logo, and recalculates url
- Fix CSRF token regeneration breaking all POST requests (nonce was
being regenerated on every request, invalidating cached tokens)
- CSRF nonce now persists across requests, rotated only on TOTP login
- Frontend secureFetch auto-retries on CSRF failure with fresh token
- Restore lifetime license activation on DNS2
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Full codebase including API server (32 modules + routes), dashboard frontend,
DashCA certificate distribution, installer script, and deployment skills.