8 Commits

Author SHA1 Message Date
gilles ff9cfaa9e1 feat(scheduler): automatisations planifiées (cron) — tâche 5
- table schedules (migration 0007) + service scheduler (croner) : CRUD,
  runSchedule avec scope (all/liste), pool de concurrence et verrou par machine,
  mapping actions → refresh/metrics/docker_scan ; reloadSchedules au boot
- worker = reloadSchedules (remplace le refresh 30 min en dur)
- routes /api/schedules (CRUD + :id/run) ; cron invalide rejeté (validation croner)
- UI Paramètres : onglet « Automatisations » (liste, activer/lancer/supprimer, création)

tsc 0 · 113 tests · build OK · boot OK (migration 0007, CRUD vérifié).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 19:25:44 +02:00
gilles e6f4ae470b feat(post-install): moteur de profils + bootstrap + identité/réseau (tâche 2 SJ-8)
- templates custom/bootstrap-root + identity-network (sortie structurée parsable,
  sauvegardes, échec contrôlé, jamais de coupure réseau sans reconnexion)
- postInstall: registre de manifestes (champs typés + defaults/defaultFrom),
  validateProfileValues + maskSecretValues + buildPostInstallResult (TDD),
  renderProfile/previewProfile (masquage secrets), runPostInstall (SSH)
- execute: RunActionOpts.profileId/values + branche post_install (bloc postInstall)
- action_requests: post_install accepté, payload profileId/values transmis à approve
- routes: GET /profiles, POST .../preview (script masqué + validation),
  POST .../run (action_request si requiresConfirmation, sinon direct)

Champs = formulaire (pas de question SSH interactive) ; secrets jamais sérialisés ;
identity_network exige confirmation. tsc 0 · 101 tests · build OK · boot OK.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 08:02:32 +02:00
gilles 2b684da9cd feat(api): profil machine éditable, sonde, et réglages globaux apt-cacher-ng
- machines : updateMachine (PATCH /machines/:id) + POST /machines/:id/probe
  (sonde synchrone → faits + proposition de correction) ; MachineView expose
  machineKind/virtualization ; CreateMachineInput accepte aptProxyMode persistent
- app_settings (clé/valeur, migration 0006) + service appSettings :
  défaut apt-cacher-ng (mode + url) ; applyProxyToAllMachines
- routes /settings : GET, PUT /apt-proxy, POST /apt-proxy/apply-all

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 07:53:47 +02:00
gilles 2c15b8c06b feat(docker): routes de gestion des stacks (settings/roots/scan/list/enable)
Rend le flux Docker déclenchable via l'API (prérequis SJ-5/SJ-6) :
- GET  /machines/:id/docker/settings — settings + racines Compose
- POST /machines/:id/docker/roots    — déclare/active les racines à scanner
- POST /machines/:id/docker/scan     — scan passif (background, WS)
- GET  /machines/:id/docker/stacks   — liste stacks + services
- PATCH /machines/:id/docker/stacks/:stackId — cycle candidate→enabled→ignored

dockerScan: getDockerSettings, listStacks, setStackStatus. Les actions
pull-check/apply/down restent réservées aux stacks enabled.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 06:24:43 +02:00
gilles 47fe952240 feat(settings): backup/restore de la base de données (amelioration #4)
- service dbBackup : createBackup (VACUUM INTO → archive .db cohérente),
  validateSqlite (header + integrity_check + schéma), prepareRestore
  (sauvegarde de sécurité auto + dépôt <db>.incoming)
- swap hors-ligne au démarrage (db/client.ts) : aucune corruption d'une base
  ouverte ; restauration appliquée au redémarrage
- routes GET /system/db/info|backup, POST /system/db/restore
- lib api : dbInfo / dbBackup (download navigateur) / dbRestore (upload)
- SettingsModal : onglet « Base de données » (taille, télécharger, restaurer
  avec confirmation Popup), icônes database/upload, styles DS variables only

Testé end-to-end : backup 184 Ko valide, restore + safety .bak + swap au boot,
fichier invalide rejeté. tsc 0 erreur · 91 tests · build OK.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 06:13:03 +02:00
gilles edb22a59c7 feat(docker): apply/prune/down + socle action_requests (tâche 2 SJ-6)
- migration 0005 : tables docker_image_events + action_requests
- templates apply-compose (up -d --remove-orphans), prune-images (safe/agressif),
  down-compose (sans volumes/rmi)
- dockerApply: parsers TDD (apply recreated/running/exited, prune images+bytes,
  down removed, parseHumanBytes) + orchestration applyStack/pruneImages/downStack
  réservée aux stacks enabled, insère docker_image_events
- actionRequests: create/approve/reject/list — actions destructives validées
  explicitement (Hermes propose, opérateur approuve, run en arrière-plan) ;
  hors API directe (POST /:id/actions reste passif uniquement)
- routes /machines/:id/action-requests + /action-requests/:id[/approve|/reject]
- execute: RunActionOpts.aggressive, branches apply/prune/down, helper
  archiveExecution mutualisant le boilerplate d'archivage

tsc 0 erreur · 91 tests · build OK · boot OK (migrations 0000→0005).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 06:05:59 +02:00
gilles 08919752e3 feat: socle BDD (tâche 1.9 Phase 1-2) + moteur APT (tâche 2 SJ-0→3) + WIP capabilities/auth/Rust
Checkpoint multi-chantiers (arbre vert : tsc 0 erreur, 70 tests, build OK).
- tâche 1.9 Phase 1 : schéma socle (machine_state/events/reports/raw_artifacts/
  hardware/metrics + colonnes étendues) + wiring refresh/execute. Migration 0002.
- tâche 1.9 Phase 2 : machine_credentials + machine_host_keys (non destructif,
  dual-read + backfill). Migration 0003. Fix séquence journal de migration.
- tâche 2 : SJ-0 (types étendus rétro-compatibles, réducteur Docker, resolveTemplate),
  SJ-1 (update-analyze enrichi), SJ-2 (apply + diff dpkg + timeout inactivité SSH),
  SJ-3 (reboot vérifié boot_id).
- WIP parallèle inclus : /api/capabilities, auth/apiTokens/apiClients, system metrics,
  scaffold app_rust, ajustements frontend.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 19:50:25 +02:00
gilles c3584f4ec8 feat: routes HTTP Hono (machines, refresh, actions, executions)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 04:13:15 +02:00