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>
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
# Tâche 2 — SJ-8 : Post-install (moteur de profils + bootstrap + identité/réseau)
|
||||
|
||||
> Statut : **backend implémenté** (2026-06-06). tsc 0 · 101 tests · build OK · boot OK.
|
||||
> Réf. design : `docs/design/tache2/30-scripts-custom.md`, `40-contrats-json.md §4`, `80-sous-jalons.md` SJ-8.
|
||||
> Non testé en live (post-install destructif : modifie sudo/réseau d'une vraie machine).
|
||||
|
||||
## Périmètre livré
|
||||
|
||||
Moteur de profils post-install non interactif : tout choix devient un **champ de
|
||||
formulaire** validé côté backend ; preview avec **masquage des secrets** ; exécution
|
||||
SSH + parsing `PostInstallResult` ; confirmation explicite (`action_request`) pour les
|
||||
profils à risque.
|
||||
|
||||
## Composants
|
||||
|
||||
- **Templates** `templates/custom/bootstrap-root.sh.tpl` (sudo + ca-certificates + curl,
|
||||
ajout groupe sudo) et `identity-network.sh.tpl` (hostname + IP statique, sauvegarde des
|
||||
fichiers, jamais de coupure sans reconnexion planifiée). Sortie structurée parsable
|
||||
(`PKG_INSTALLED=`, `FILE_MODIFIED=`, `OLD/NEW_ENDPOINT=`, `REBOOT_REQUESTED=1`, `ERR=`).
|
||||
- **`server/services/postInstall.ts`** :
|
||||
- registre `PROFILES` (manifestes : `id`, `label`, `risk`, `requiresConfirmation`,
|
||||
`fields[]` avec types `string|hostname|ipv4|ipv4_cidr|ipv4_list|select|bool|int|path|secret`,
|
||||
`default`/`defaultFrom`).
|
||||
- `validateProfileValues` (requis + formats IPv4/CIDR/hostname) — TDD.
|
||||
- `maskSecretValues` (champs `secret` → `********`) — TDD ; `previewProfile` masque avant rendu.
|
||||
- `buildPostInstallResult` (parse → filesModified/packagesInstalled/networkChange/reboot/errors) — TDD.
|
||||
- `renderProfile` / `runPostInstall` (valide puis SSH, statut ok/error).
|
||||
- **`execute.ts`** : `RunActionOpts.profileId/values`, branche `post_install`
|
||||
(archiveExecution + bloc `postInstall`).
|
||||
- **`actionRequests.ts`** : `post_install` accepté ; payload transporte `profileId`/`values` ;
|
||||
`approve` les repasse à `runAction`.
|
||||
- **Routes** : `GET /api/profiles`, `POST /machines/:id/profiles/:id/preview`
|
||||
(script masqué + validation), `POST /machines/:id/profiles/:id/run`
|
||||
(→ `action_request` si `requiresConfirmation`, sinon exécution directe).
|
||||
|
||||
## Sécurité / invariants
|
||||
|
||||
- Aucune question interactive SSH ; échec contrôlé si décision manquante.
|
||||
- Secrets jamais sérialisés : `previewProfile` masque, `variablesUsed` = non sensible only.
|
||||
- `identity_network` (network_change) exige confirmation explicite via `action_request`.
|
||||
- Reconnexion réseau : `OLD/NEW_ENDPOINT` + `RECONNECT_REQUIRED` remontés ; reboot via `reboot_verified` (futur).
|
||||
|
||||
## Reste (SJ-9 + tâche 4)
|
||||
|
||||
SJ-9 : profils `base_tools`, `network_tools`, `docker_official`, `sharing`, `vm_guest_tools`
|
||||
(+ `install-package-groups`). Persistance `install_profiles`/`machine_profile_state`/
|
||||
`script_variables_presets` et catalogue détaillé = tâche 4. UI (formulaires de profils,
|
||||
preview) = tâche 3.
|
||||
Reference in New Issue
Block a user