- GET /api/repair/modules : liste les modules non-core en DB
- DELETE /api/repair/modules/{id} : supprime un module de la DB
- settings.html : onglet Réparation avec liste + bouton Supprimer
- app.js : loadRepair() + resetModule() dans settingsPage
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- GetRegistryModules: endpoint /api/v1/orgs/{org}/repos + timeout 10s
répond toujours HTTP 200 avec {modules, error} au lieu de 502
- InstallRegistryModule: essaie branche master puis main pour module.json
- Ajouter FORGEJO_URL / FORGEJO_ORG dans docker-compose.yml
- Frontend: bouton rafraîchir store + affichage erreur
- Frontend: bannière rebuild en cours + bannière rebuild terminé
- Frontend: polling /api/health toutes les 3s après rebuild/restart
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>
- 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>