# Tâche 2 — SJ-6 : Docker apply / prune / down + socle action_requests > Statut : **implémenté** (2026-06-06). tsc 0 erreur · 91 tests · build OK · boot OK (migrations 0000→0005). > Réf. design : `docs/design/tache2/20-docker.md §4.4-4.6`, `40-contrats-json.md §4`, `70-securite.md §2`, `80-sous-jalons.md` SJ-6. ## Périmètre livré Actions Docker **destructives** (recrée/supprime) protégées par un socle de **validation explicite** (`action_requests`) : Hermes/UI proposent, l'opérateur approuve, l'exécution part en arrière-plan. Aucune de ces actions n'est accessible directement via `POST /:id/actions` (allowlist passive uniquement). ## Composants - **Migration 0005** (`0005_silent_drax.sql`, timestamp monotone) : tables `docker_image_events` (historique pulled/recreated/pruned + bytes) et `action_requests` (pending|approved|rejected|executed|expired). - **Templates** `docker/apply-compose.sh.tpl` (`up -d --remove-orphans`), `docker/prune-images.sh.tpl` (safe par défaut / `<%#aggressive%>` = `-a --filter until=168h`), `docker/down-compose.sh.tpl` (down simple, **`--volumes`/`--rmi` interdits**). - **`server/services/dockerApply.ts`** : - parsers purs (TDD) : `parseDockerApply` (recreated/running/exited via ps json), `parseDockerPrune` (`imagesDeleted` + `Total reclaimed space` → octets), `parseDockerDown` (removed), `parseHumanBytes` (unités décimales Docker). - orchestration : `applyStack` / `pruneImages` / `downStack` — réservées aux stacks `enabled`, insèrent les `docker_image_events`. Erreurs nettoyées (réutilise `cleanDockerError`). - **`server/services/actionRequests.ts`** : `createActionRequest` (refuse une action non destructive, exige `stackId` pour apply/down), `approve` (→ `runAction` en tâche de fond, pose `executionId`/`executed`), `reject`, `get`, `list`. - **Routes** `server/routes/actionRequests.ts` (montées à la racine `/api`) : `POST /machines/:id/action-requests`, `GET …`, `GET/POST /action-requests/:id[/approve|/reject]`. - **`execute.ts`** : `RunActionOpts.aggressive`, branches `docker_compose_apply` / `docker_prune_images` / `docker_compose_down`, helper `archiveExecution` mutualisant le boilerplate (log/rapport/DB/état/event) + `ExecutionResult.docker.up|prune`. ## Sécurité - Destructives **hors API directe** : passent obligatoirement par un `action_request` approuvé. - `down` sans volumes ni rmi (volumes préservés). Prune agressif = risque distinct (champ `aggressive`). - Erreurs Docker nettoyées (URL/token/password) avant UI/MCP. ## Reste tâche 2 SJ-7 (profils Proxmox/RPi + proxy persistent), SJ-8/9 (post-install). UI des boutons validés (Appliquer/Prune/Down) = tâche 3 (frontend, design system).