[Coffre Secrets] Phase 1 complète : chiffrement, API et UI (1a + 1b + 1c) #25

Merged
bruno merged 12 commits from feat/coffre-secrets-phase1 into main 2026-10-27 22:29:10 -04:00
Owner

Concerne #17, #18, #19 — ne ferme aucune issue (fermeture = décision de Bruno, avec kanban:done pour le suivi Kanbante).

Périmètre

Phase 1 du coffre de secrets ObsiGate, sur une branche dédiée, sans toucher au thème Spark (branche feat/theme-spark séparée, issue #24).

  • 1a — Chiffrement par enveloppe (AES-256-GCM) : backend/coffre_crypto.py (KEK via env ou fichier 0600 strict, DEK par coffre chiffrée par la KEK, AAD = id coffre / secret_id:version, rotations secret/DEK/KEK, mode dégradé sans KEK = 503, pas de repli en clair), backend/coffre_store.py (data/coffres.json + data/coffres_valeurs.json, 0600, écriture atomique, consommateurs en hash SHA-256, seule la version courante est distribuable).
  • 1b — API /api/coffres : backend/routers/coffres.py (coffres, secrets, rotation, suppression, octrois, journal, POST /api/coffres/distribuer ; lectures = métadonnées seules), backend/main.py (+2 lignes, include_router à côté de config_router), backend/requirements.txt (cryptography>=44.0), backend/audit.py (log_coffre_event, sans valeur).
  • 1c — UI : frontend/js/coffres.js (nouveau, 1 070 lignes), frontend/js/sidebar.js (nœud virtuel Secrets 🔐 sous home- seulement, patron « Partage », sans dossier sur disque), frontend/style.css (bloc .coffres-), frontend/locales/fr.json + en.json (91 clés coffres.).
  • Tests : tests/test_coffre_secrets.py — 26/26 en local (venv, pytest --noconftest) : chiffrement, tag/AAD altérés refusés, rotations, mode dégradé, matrice d'autorisation, distribution puis révocation, expiration, audit sans valeur.

Vérifié / non vérifié — à lire avant review

  • Vérifié : fichiers présents sur la branche et re-téléchargés (sha256 identiques pour coffres.js et sidebar.js), node --check OK, JSON locales valides, routes UI = routes réelles du routeur, main inchangée pour ces fichiers.
  • NON vérifié : suite complète du dépôt, tests routeur avec le vrai middleware (auth factice + dependency_overrides), rendu/clic/création sur instance réelle, run CI (cette PR le déclenche : lint ruff/mypy + frontend, pytest tests/, security bandit/pip-audit).
  • Écarts connus : coffre personnel créé paresseusement à la première ouverture de la vue Secrets (slug personnel-, pas dans ensure_user_home) ; copie manuelle réservée aux admins via consommateur temporaire, en attente d'un endpoint dédié par session ; détail = version courante seule ; vue Secrets hors TabManager ; feature flag OBSIGATE_SECRETS_ENABLED (défaut désactivé -> 503 secrets_desactives).

Checklist de test sur instance réelle (avant merge)

  1. Activer le flag, générer une KEK (admin), créer un coffre personnel + un secret.
  2. Octroi + distribution à un consommateur, puis révocation -> 403 au prochain appel.
  3. Rotation secret / DEK / KEK, puis relecture des métadonnées (jamais de valeur réaffichée).
  4. Mode dégradé sans KEK : métadonnées lisibles, distributions refusées.
  5. Clic sur le nœud Secrets, création en 5 étapes, effacement immédiat de la valeur.

Merge

Uniquement après CI verte + test réel ci-dessus + go explicite de Bruno. Phases suivantes (#20 migration/sauvegarde, #21 Spark, #22 consommateurs, #23 tests/déploiement) après ce merge.

Concerne #17, #18, #19 — ne ferme aucune issue (fermeture = décision de Bruno, avec kanban:done pour le suivi Kanbante). ## Périmètre Phase 1 du coffre de secrets ObsiGate, sur une branche dédiée, sans toucher au thème Spark (branche feat/theme-spark séparée, issue #24). - **1a — Chiffrement par enveloppe (AES-256-GCM)** : backend/coffre_crypto.py (KEK via env ou fichier 0600 strict, DEK par coffre chiffrée par la KEK, AAD = id coffre / secret_id:version, rotations secret/DEK/KEK, mode dégradé sans KEK = 503, pas de repli en clair), backend/coffre_store.py (data/coffres.json + data/coffres_valeurs.json, 0600, écriture atomique, consommateurs en hash SHA-256, seule la version courante est distribuable). - **1b — API /api/coffres** : backend/routers/coffres.py (coffres, secrets, rotation, suppression, octrois, journal, POST /api/coffres/distribuer ; lectures = métadonnées seules), backend/main.py (+2 lignes, include_router à côté de config_router), backend/requirements.txt (cryptography>=44.0), backend/audit.py (log_coffre_event, sans valeur). - **1c — UI** : frontend/js/coffres.js (nouveau, 1 070 lignes), frontend/js/sidebar.js (nœud virtuel Secrets 🔐 sous home-<utilisateur courant> seulement, patron « Partage », sans dossier sur disque), frontend/style.css (bloc .coffres-*), frontend/locales/fr.json + en.json (91 clés coffres.*). - **Tests** : tests/test_coffre_secrets.py — 26/26 en local (venv, pytest --noconftest) : chiffrement, tag/AAD altérés refusés, rotations, mode dégradé, matrice d'autorisation, distribution puis révocation, expiration, audit sans valeur. ## Vérifié / non vérifié — à lire avant review - Vérifié : fichiers présents sur la branche et re-téléchargés (sha256 identiques pour coffres.js et sidebar.js), node --check OK, JSON locales valides, routes UI = routes réelles du routeur, main inchangée pour ces fichiers. - NON vérifié : suite complète du dépôt, tests routeur avec le vrai middleware (auth factice + dependency_overrides), rendu/clic/création sur instance réelle, run CI (cette PR le déclenche : lint ruff/mypy + frontend, pytest tests/, security bandit/pip-audit). - Écarts connus : coffre personnel créé paresseusement à la première ouverture de la vue Secrets (slug personnel-<utilisateur>, pas dans ensure_user_home) ; copie manuelle réservée aux admins via consommateur temporaire, en attente d'un endpoint dédié par session ; détail = version courante seule ; vue Secrets hors TabManager ; feature flag OBSIGATE_SECRETS_ENABLED (défaut désactivé -> 503 secrets_desactives). ## Checklist de test sur instance réelle (avant merge) 1. Activer le flag, générer une KEK (admin), créer un coffre personnel + un secret. 2. Octroi + distribution à un consommateur, puis révocation -> 403 au prochain appel. 3. Rotation secret / DEK / KEK, puis relecture des métadonnées (jamais de valeur réaffichée). 4. Mode dégradé sans KEK : métadonnées lisibles, distributions refusées. 5. Clic sur le nœud Secrets, création en 5 étapes, effacement immédiat de la valeur. ## Merge Uniquement après CI verte + test réel ci-dessus + go explicite de Bruno. Phases suivantes (#20 migration/sauvegarde, #21 Spark, #22 consommateurs, #23 tests/déploiement) après ce merge.
bruno added 12 commits 2026-10-27 22:20:16 -04:00
bruno merged commit ba81f22d40 into main 2026-10-27 22:29:10 -04:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Projets/ObsiGate#25