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).
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)
Activer le flag, générer une KEK (admin), créer un coffre personnel + un secret.
Octroi + distribution à un consommateur, puis révocation -> 403 au prochain appel.
Rotation secret / DEK / KEK, puis relecture des métadonnées (jamais de valeur réaffichée).
Mode dégradé sans KEK : métadonnées lisibles, distributions refusées.
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.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
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).
Vérifié / non vérifié — à lire avant review
Checklist de test sur instance réelle (avant merge)
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.