- fetchMe: handle ALL non-ok responses (not just 401) by calling tryRefresh
→ avoids user=null when backend returns 404/500/any error
- DOMContentLoaded guard: check isAuthenticated instead of localStorage token
→ immediate redirect if fetchMe+tryRefresh both fail, no more flash of dashboard
- Cookie Secure flag: check X-Forwarded-Proto header for Traefik/proxy setup
→ cookie gets Secure=true when behind TLS-terminating reverse proxy
- db.go migrate(): split SQL by ; and exec each statement separately
→ fixes SQLite multi-statement limitation (only first stmt was executed)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Backend: migration 002 adds user_agent/ip/last_used_at to refresh_tokens
- Backend: GET /api/auth/sessions + DELETE /api/auth/sessions/{id} endpoints
- Frontend: profile page — sessions section (browser, IP, datetime, revoke)
- Frontend: web manifest + SVG icon for PWA support
- Frontend: remove language selector from all navbars (moved to profile page)
- Frontend: neu-btn--icon-sm class for square icon-only buttons (theme/logout/edit)
- Frontend: manifest link added to all 9 HTML pages
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bug principal : l'SSHAuthenticator est créé au démarrage avec host=""
(DB vide avant installation). Après configure, il gardait host vide.
Le login lisait maintenant le ssh_host depuis la DB à chaque requête.
Logs ajoutés :
- ssh_auth.go : dial SSH, succès, échec avec détail d'erreur
- auth.go : host SSH utilisé, résultat auth à chaque login
- updates.go : credentials SSH, démarrage/fin de job
- terminal.go : ouverture/échec session SSH
Frontend :
- auth.store.ts : gère les réponses non-JSON sur erreur HTTP
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>