Le CORE est autonome — les modules externes ne doivent pas être
des dépendances Go compilées dans le binaire. Retour au Dockerfile
et docker-compose.yml originaux (context: ./backend).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Supprime la dépendance au contexte parent (context: ..).
Le Dockerfile clone viewLogs et viewServices depuis git pendant le build,
dans /workspace/ pour correspondre aux replace directives go.mod (../../).
docker-compose.yml revient à context: ./backend — fonctionne quelle que
soit la structure de répertoires sur le serveur.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Supprimer les modules services et logs du CORE (déplacés dans viewServices et viewLogs)
- Enrichir modules/module.go : interface Registry avec NavItemDef, RunOnTarget, StreamOnTarget
- Réécrire modules/loader.go : NewLoader accepte *db.DB, *sshpool.Pool, *crypto.Encryptor
- Ajouter migration 005 : colonnes nav_* sur la table modules + suppression services/logs DB
- Mettre à jour db.go (repairSchema) pour ajout idempotent des colonnes nav_*
- Mettre à jour settings.go : GetModules retourne les champs nav, ajout GetRegistryModules et InstallRegistryModule
- Mettre à jour main.go : NewLoader avec les bons arguments, ajout routes /api/registry/modules
- Mettre à jour modules.html : section Store avec liste des modules Forgejo
- Mettre à jour app.js : sidebar dynamique (nav_href depuis DB), modulesPage avec store
- Mettre à jour pages.css : styles pour store de modules
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
INSERT OR IGNORE in migration 003 was silently skipped because
logs/services rows already existed in the DB with is_enabled=0.
Migration 004 uses ON CONFLICT DO UPDATE to ensure is_enabled=1.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Backend:
- modules/services: list, status, start/stop/restart systemctl services
with pct exec support for LXC targets
- modules/logs: journalctl unit listing + WebSocket live streaming
(direct SSH connection, journalctl -f, graceful teardown on WS close)
- migrations/003: seed services and logs modules in DB
- main.go: register services.New() and logs.New() in module loader
Frontend:
- services.html: target selector, search/filter, services table with
active state indicators and start/stop/restart buttons
- logs.html: target + unit selectors, live follow toggle, scrollable
terminal output with 3000-line cap
- app.js: servicePage() and logsPage() Alpine components + navItems
- locales: services and logs i18n keys (fr + en)
- pages.css: services table, state dots, logs output styles
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- GetSessions: retourne is_current=true pour la session correspondant au cookie courant
- GetSessions: select token_hash pour la comparaison (non exposé dans le JSON)
- profile.html: badge "Session actuelle" + désactive révoquer pour la session courante
(utiliser le bouton Déconnexion à la place)
- app.js: revokeSession utilise finally pour reset + isRevoking() helper
- pages.css: styles .badge-current + .session-current
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Scan des colonnes datetime via sql.NullString au lieu de time.Time pour éviter
les échecs silencieux dus aux formats mixtes SQLite (CURRENT_TIMESTAMP vs RFC3339)
- Log explicite si un scan échoue (au lieu du continue silencieux)
- formatDate frontend adapte le format SQLite "YYYY-MM-DD HH:MM:SS" en ISO pour new Date()
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- auth.go: upsertUser utilise toujours SELECT explicite au lieu de LastInsertId()
qui retournait un rowid obsolète pour ON CONFLICT DO UPDATE sur ligne existante
- auth.go: vérifier l'erreur de l'INSERT refresh_tokens (était silencieusement ignorée)
- auth.go: logs détaillés dans Refresh handler pour diagnostiquer les 401
- db.go: repairSchema() ajoute les colonnes manquantes (ip, last_used_at) dans les
bases où migration 002 était partiellement appliquée (ancien bug multi-statements)
- app.js: tryRefresh et fetchMe affichent le vrai message d'erreur du backend
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- auth store fetchMe(): sync theme/sidebar_position/lang from DB to localStorage+stores on login/refresh
- profilePage setters: PATCH /api/auth/preferences on every preference change
- updatesPage: add history tab (GET /api/updates/history) with job list, click to view output
- dashboardPage: load shortcuts from settings API, fall back to defaults if none configured
- settingsPage: new Raccourcis tab to add/remove/configure dashboard shortcuts (saved as JSON)
- settings.go: expose dashboard_shortcuts in publicSettings for GET/PUT access
- pages.css: add .history-table, .shortcut-row styles
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
Tous les appels pct passent par sudo -n pour les sessions SSH non-root.
GetPackages est résilient : utilise l'output même si exit code != 0.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
pct n'est pas dans le PATH SSH par défaut (exit 127).
Corrigé dans GetPackages, GetTargets et executeUpdate.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Backend: GET /api/updates/targets (pct list via SSH)
- Backend: GET /api/updates/packages?target= (apt list --upgradable)
- Frontend: grille de cards par cible (host + chaque LXC)
- Bouton Check/Update par card, liste paquets dépliable (version actuelle → nouvelle)
- Boutons globaux "Tout vérifier" et "Tout mettre à jour"
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Session F5 :
- auth.store: restoreSession() essaie fetchMe() avec le token existant
(< 15 min → fonctionne sans cookie), puis tryRefresh() en fallback
- router: appelle restoreSession() au premier chargement au lieu de tryRefresh()
Paramètres infrastructure :
- Champs ssh_password et proxmox_token en write-only (vide = pas de changement)
- SettingsHandler: accepte les clés chiffrées, chiffre avant stockage
- Permet de corriger le token Proxmox invalide sans réinstallation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- router: tryRefresh() au premier chargement → plus besoin de se
reconnecter après F5 (user restauré depuis le cookie refresh)
- migration 003: terminal marqué is_core=1 + is_enabled=1
- proxmox.go: logs pour diagnostiquer l'erreur 502 (visible dans
Paramètres → Logs)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Sidebar : retrait des liens files, logs, services (non implémentés)
- Migration 001 : suppression des inserts files/logs/services
- Migration 002 : DELETE des modules inexistants en DB existante
- logbuffer : ring buffer mémoire branché sur log.SetOutput
- GET /api/settings/logs : retourne les 300 dernières lignes de log
- Settings : onglet Logs avec auto-refresh (5s/10s/30s/60s/désactivé, défaut 10s)
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>
- install.go : detectPublicURL utilise https pour tout domaine public
même si Traefik envoie X-Forwarded-Proto: http en interne
- fr.json / en.json : échappe le @ dans proxmoxTokenHint avec {'@'}
(vue-i18n interprétait @realm comme un linked message → SyntaxError)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- helpers.go : corrige le cas r.Body == nil (panic → erreur explicite)
- install.go : ajout logs étape par étape pour TestSSH (TCP, auth SSH)
sans jamais logger le mot de passe (longueur uniquement)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>