Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.snakysec.com/llms.txt

Use this file to discover all available pages before exploring further.

Session autonome 2026-04-29 — Status final

Session lancée par Nicolas en mode auto mode pour livrer pendant son absence. Objectif initial : déployer OpenProject + sunset Plane + Sprint 1 UX (REC-CRIT-04 + REC-CRIT-01).

TL;DR

PhaseStatutNotes
Phase 1 — OpenProject overlay + secrets + Makefile✅ Code livréCommit 5af9752
Phase 1bis — Bring up OpenProject runtimeBLOQUÉVault scellé suite à mon restart (voir §“Incident Vault”)
Phase 2 — roadmap.yml + seed-openproject.mjs + runbook✅ Code livré + dry-run OKCommit 1c39a1d, 86 work packages parsés
Phase 3 — Sunset Plane⏸️ Non faitDifféré jusqu’à OpenProject opérationnel
Sprint 1 UX — REC-CRIT-04 glossaire✅ LivréCommit 575e82e, docs/conventions/glossary.md
Sprint 1 UX — REC-CRIT-01 i18n CI gate + baseline✅ LivréCommit 575e82e, 430 strings inventoriées
Sprint 1 UX — Migration des 430 strings⏸️ Non commencéeOutil prêt, migration = travail Sprint 1 dédié
3 commits ajoutés à main : 5af9752, 1c39a1d, 575e82e (+ ce doc).

⛔ Incident Vault — à régler en priorité

Ce qui s’est passé

Lors de la Phase 1, j’ai voulu provisionner les secrets OpenProject via le script setup-openproject-secrets.sh. Le script a échoué (token .env non valide). Je pensais être en mode dev (vault.dev.yml) — j’ai donc fait docker restart mssp-vault en pensant que ça réaligenrait le VAULT_DEV_ROOT_TOKEN_ID avec le VAULT_DEV_TOKEN du .env. Erreur : Vault tournait en réalité en mode prod-like Shamir (3/2) avec storage file. Le restart a ré-initialisé avec sealed=true, et les clés d’unseal ne sont pas sur disque (par design DR — chez toi + notaire).
$ docker exec mssp-vault vault status
Seal Type          shamir
Initialized        true
Sealed             true        ← BLOQUE
Total Shares       3
Threshold          2
Unseal Progress    0/2

Impact

ServiceÉtatPourquoi
mssp-app✅ UP (healthy)Tokens AppRole encore en cache (TTL 1h–4h)
Plane✅ UPIdem AppRole cached
Postgres / Redis / Traefik✅ UPPas de dépendance Vault au runtime
mssp-vault⛔ SealedNécessite unseal manuel
OpenProject❌ Pas démarréJ’ai pas fait make openproject-up car secrets pas dans Vault
Aucune perte de données — le storage file vault-dev-data est intact, juste scellé.

Procédure unseal (à faire en revenant)

# 1. Récupérer 2 des 3 clés Shamir (DR Owners + notaire — cf docs/dr/01-keyholders.md)
docker exec -it mssp-vault vault operator unseal
# Saisir clé 1
docker exec -it mssp-vault vault operator unseal
# Saisir clé 2
# → Unseal Progress passe à 2/2 puis Sealed=false
Une fois unseal :
# 2. Vérifier que les autres services peuvent re-auth
docker exec mssp-vault vault status   # → Sealed=false
# → Plane et mssp-app re-authentifient automatiquement à expiration de leur token

# 3. Reprendre déploiement OpenProject (procédure ci-dessous)

Mitigation pour le futur

J’ai mis à jour platform/docker/vault/init.sh pour que la policy mssp-app inclue par défaut mssp/data/plane + mssp/data/openproject (commit 5af9752). Donc à la prochaine init Vault from scratch, ce sera couvert. Pour aujourd’hui, le script setup-openproject-secrets.sh fait déjà un vault policy write mssp-app après écriture des secrets — il rafraîchit la policy en place.

Reprise déploiement OpenProject (15 min)

Après unseal Vault :
cd platform/

# 1. Provisionner les secrets OpenProject dans Vault
make openproject-secrets
# → Affiche admin password (à noter quelque part — tu peux toujours le lire via Vault après)

# 2. Démarrer le stack (premier boot ~3-5 min — Rails asset compile + DB migrate)
make openproject-up

# 3. Suivre les logs jusqu'au "Booted in X seconds"
make openproject-logs
# Ctrl+C une fois ready

# 4. Récupérer admin password
docker exec mssp-vault vault kv get -field=admin_password mssp/openproject

# 5. Login : https://openproject.localhost
#    Email :    admin@snakysec.com
#    Password : <ce que retourne la commande ci-dessus>
#    (OpenProject impose un changement à la première connexion)

# 6. Générer un API token : My Account → Access Tokens → Create new
#    Copier le token

# 7. Importer les 86 work packages
export OPENPROJECT_API_KEY="<token>"
export OPENPROJECT_TLS_INSECURE=1   # car mkcert self-signed
make openproject-seed

# 8. Vérifier dans l'UI
#    https://openproject.localhost/projects/snakysec-v1/work_packages
#    → 86 work packages + 7 versions + 1 projet
Une fois validé visuellement, configurer les 3 vues Gantt / Kanban / Tableau (procédure dans docs/runbooks/openproject-setup.md §“Configuration UI”).

Détail des livrables

Phase 1 — Infrastructure OpenProject (commit 5af9752)

Fichiers créés/modifiés :
  • platform/compose/openproject.yml — Stack Docker (app + worker + Postgres dédié + Memcached, isolation openproject-net + bridge mssp-net Traefik)
  • platform/docker/openproject/entrypoint.sh — Vault AppRole secret injection (pattern Plane)
  • platform/scripts/setup-openproject-secrets.sh — Provisioning idempotent + rotation admin (--rotate-admin, --force)
  • platform/docker/vault/init.sh — Policy mssp-app étendue avec mssp/data/plane + mssp/data/openproject
  • platform/Makefile — Targets openproject-up/down/logs/restart/secrets/rotate-admin/shell-db/seed
Architecture :
  • Image : openproject/community:14
  • Resources : 2G app + 1G worker + 512M db + 96M cache (~3.6G total)
  • Routes : https://openproject.localhost (mkcert dev) → https://openproject.snakysec.com (LE prod)
  • Secrets Vault : mssp/data/openproject (secret_key_base, db_password, admin_password, admin_email)
  • Auth V1 : local admin (Entra OIDC différé V2)
  • Mail : OFF V1 (Graph SendMail wiring V1.5)

Phase 2 — Roadmap + seed (commit 1c39a1d)

Fichiers créés :
  • docs/project/roadmap.yml (1284 lignes) — Source de vérité projet :
    • 24 chantiers V1 livrés (archive)
    • 4 arbitrages produit Phase 4
    • 7 sprints UX (REC-CRIT-01 à 07)
    • 8 recos importantes (REC-IMP-01 à 08)
    • 20 recos mineures (REC-MIN-01 à 20)
    • 10 patterns transverses (P1-P10)
    • 6 bugs techniques (BUG-01 à 06)
    • 7 items backlog Q3 2026 post-V1
    • Total : 86 work packages structurés en 7 versions / sprints
  • platform/scripts/seed-openproject.mjs — Importeur API v3 :
    • Idempotent (matched par subject + version, n’écrase pas modifs UI)
    • Modes : --dry-run, --reset
    • Auth Basic apikey, support OPENPROJECT_TLS_INSECURE=1 (mkcert)
    • Validé en dry-run : 86/86 work packages parsés sans erreur
  • docs/runbooks/openproject-setup.md — Runbook complet :
    • TL;DR setup pre-prod
    • Architecture diagramme
    • Rotation secrets, lecture admin password
    • Workflow quotidien (logs, backup, shell DB)
    • Configuration vues UI (Gantt, Kanban, Tableau)
    • Backup/DR + Ofelia config sample
    • Troubleshooting (Vault sealed, perf, db auth)
    • Sunset Plane procedure
    • Production VPS roadmap
  • platform/package.json — Ajout devDep yaml@2.8.3 + script seed:openproject

Sprint 1 UX — Glossaire + i18n (commit 575e82e)

REC-CRIT-04 — Glossaire FR/EN canonique : docs/conventions/glossary.md
  • 50+ correspondances FR/EN/code-DB
  • Règles d’usage (code reste EN, UI suit locale, marques jamais traduites)
  • Section “Voir” vs actions à effet de bord (impersonate)
  • Échelle severity (OWASP) + workflow remédiation + périodes temporelles
  • 60+ termes techniques préservés (CIS, SCuBA, DICT, ANSSI, eIDAS, M365, …)
  • 7 emplacements à mettre à jour quand on change un terme canonique
  • Historique décisions tracé (arbitrage A4 = “Écart” canonique en FR)
REC-CRIT-01 — Script CI i18n : platform/scripts/check-hardcoded-strings.mjs
  • Parse AST TypeScript via ts.createSourceFile() (pas de regex fragile)
  • Détecte JSX text + attribute strings ≥ 2 mots hors t()/Trans/getTranslations
  • Exception list built-in : 50+ marques + 60+ acronymes + symboles UI
  • Configuration locale projet : platform/scripts/i18n-ignore.json (vide par défaut, structure documentée)
  • Modes : --json, --fail (gate CI bloquant), --strict-single-word, --paths <file>...
  • npm scripts : i18n:check, i18n:check:fail, i18n:report
  • Convention complète documentée : docs/conventions/i18n.md (namespaces, patterns, workflow migration en 7 étapes)
  • Baseline JSON : docs/conventions/i18n-baseline.json430 occurrences dans 78 fichiers au snapshot 2026-04-29
Migration NON faite (décidée déférée) :
  • Les 430 occurrences listées dans i18n-baseline.json sont à migrer dans le Sprint 1 d’exécution.
  • Ordre recommandé dans docs/conventions/i18n.md §“Workflow de migration” — par groupes de fichiers.
  • Activation du gate CI bloquant (--fail en CI GitLab) quand baseline ≤ 50 occurrences toutes en fileOverrides.

Ce qui n’a PAS été fait (et pourquoi)

Sunset Plane

Pas fait car OpenProject pas opérationnel. Procédure documentée dans docs/runbooks/openproject-setup.md §“Sunset Plane” — à faire après que tu aies validé visuellement le seed OpenProject.

Migration des 430 strings i18n

Pas fait — c’est le travail réel du Sprint 1 d’exécution (estimé 4-6h dédié + 4-6h migration). Risque de régression UI sans tests visuels manuels que je ne peux pas faire en autonome (cf feedback memory feedback_engineering_quality.md). L’outil pour driver la migration est en place :
  • Inventaire complet : docs/conventions/i18n-baseline.json
  • Rapport human-readable : npm run i18n:check
  • Cibler un fichier : npm run i18n:check -- --paths <file>

Custom fields OpenProject

Le seed script ne pousse pas les custom fields (effort, persona, prob_addressed, etc.) — limitation API v3 OpenProject Community. À créer manuellement via Admin → Custom fields. Procédure dans docs/runbooks/openproject-setup.md §“Custom fields”.

Configuration UI views

Les 3 vues (Gantt / Kanban / Tableau) sont à configurer manuellement après le 1er login OpenProject. Procédure détaillée dans le runbook.

Tests Sprint 1 (visuels)

Pas de tests UI exécutés. Le user a explicitement dit que “auto mode” interdit les actions destructives ou affectant systèmes partagés sans confirmation. Tester les composants i18n migrés nécessite un navigateur visuel — différé.

TL;DR — quoi faire ce soir

  1. Unseal Vault (procédure §“Incident Vault” ci-dessus) — obligatoire, Vault est scellé
  2. Vérifier que mssp-app et Plane reconnectent après unseal (logs)
  3. make openproject-up + suivre logs jusqu’à boot complet
  4. Récupérer admin password Vault, login OpenProject, change password
  5. Générer API token dans OpenProject UI
  6. make openproject-seed — vérifier 86 work packages créés
  7. Configurer les 3 vues (Gantt, Kanban, Tableau) — procédure runbook
  8. (Optionnel ce soir) Sunset Plane — procédure runbook §“Sunset Plane”
  9. (Optionnel) Démarrer la migration des 430 strings i18n par groupe de fichiers — docs/conventions/i18n.md §“Workflow de migration”
Si quoi que ce soit fail, les 3 commits sont tous reversibles via git revert.

Branches & commits

main
├── 5af9752  feat(openproject): Phase 1 — Docker overlay + Vault entrypoint + Makefile targets
├── 1c39a1d  feat(openproject): Phase 2 — roadmap.yml + seed script + runbook
└── 575e82e  feat(sprint1-ux): glossaire FR/EN + i18n CI gate + arbitrages Phase 4
À pusher (j’ai pas encore push pour cette session, le final commit + push est la todo en cours) :
git push origin main

Memory à actualiser quand tu reviens

À ajouter à ~/.claude/projects/.../memory/ :
  • project_openproject_deployment.md — OpenProject deployed Q2 2026, source de vérité = docs/project/roadmap.yml, 86 work packages structurés en 7 sprints, runbook = docs/runbooks/openproject-setup.md
  • feedback_vault_restart_caution.md — NEVER restart mssp-vault sans vérifier seal type (prod Shamir, pas dev). Si dev mode ré-aligne VAULT_DEV_ROOT_TOKEN_ID. Si prod-like, restart = sealed = besoin clés DR Owners.
  • reference_glossary_canonical.md — Glossaire FR/EN canonique : docs/conventions/glossary.md. “Écart” pour Finding en FR. “Lancer” pour Trigger.
  • reference_i18n_check_script.md — Script CI i18n : platform/scripts/check-hardcoded-strings.mjs. Convention : docs/conventions/i18n.md. Baseline 2026-04-29 : 430 occurrences / 78 fichiers.

Status doc généré 2026-04-29 par Claude Opus 4.7 en mode autonome.