ADR: défense en profondeur contre la fuite de private/ et secrets vers le remote partagé¶
Contexte¶
Le remote partagé (brickssas/bricks-brain, team-internal) reçoit le contenu diffusable à l'équipe. Deux garde-fous existaient : le pre-commit (bloque private/ stagé et les fichiers confidentiality: restricted) et le .gitignore en denylist (issu de l'ADR 2026-06-12).
Deux faiblesses subsistaient :
- La denylist est faillible par défaut. Un nouveau fichier de contenu wiki, non listé dans le
.gitignore, part vers le partagé sans qu'on y pense — même s'il contient une info interne sensible (chiffre business, jugement, incident). - Le pre-commit est contournable (
--no-verify) et ne protège qu'à l'écriture locale — rien côté serveur.
Le déclencheur : brancher des traitements automatisés sur le brain augmente le volume d'écritures et le risque qu'un contenu sensible parte par accident. Il fallait rendre la non-fuite mécanique et multi-couches, pas dépendante d'une seule barrière contournable.
Options envisagées¶
Option A : garder la denylist seule¶
- Description : statu quo, on continue d'ajouter les chemins sensibles au
.gitignore. - Inconvénients : un nouveau fichier sensible part par défaut ; aucune barrière serveur ; contournable.
Option B : allowlist .gitignore pure (/* + ré-inclusions)¶
- Description : tout ignoré par défaut, on ré-inclut explicitement le partageable.
- Inconvénients : fragile sur les dossiers mixtes (
concepts/,decisions/,resources/,people/mêlent partagé et local, granularité au fichier) ; risque de masquer des fichiers déjà partagés ; n'untrack pas l'existant sansgit rm --cached.
Option C : défense en profondeur multi-couches (retenue)¶
- Description : empiler des barrières indépendantes, dont une côté serveur non contournable, et encoder « classer avant de partager » à l'écriture.
- Avantages : la fuite catastrophique (private/, secrets) devient impossible même en
--no-verify; le nouveau contenu wiki doit déclarer sa sensibilité ; aucun chantier de reclassification de l'existant. - Inconvénients : friction légère (classer les nouveaux fichiers) ; le ruleset serveur ne se contourne pas, même admin.
Décision¶
Option C. Quatre couches indépendantes protègent le remote partagé :
- Pre-commit (à l'écriture) — bloque
private/stagé, les fichiersconfidentiality: restricted, et tout nouveau fichier wiki.mdsans classification (voir ci-dessous). - Pre-push (avant l'envoi réseau, hors ligne) — refuse tout push contenant
private/**ou des secrets (.env,credentials.json,secrets.yml,.cursor/mcp.json). - Ruleset serveur GitHub (push ruleset « restricted file paths », enforcement
active, aucun bypass) — GitHub rejette côté serveur tout push touchant ces mêmes chemins. Résiste à--no-verify. - Isolation par construction — le work-tree ne connaît que le remote partagé ; le contenu complet vit dans une couche locale/privée séparée, jamais poussée vers le partagé.
« Classer avant de partager » (private par défaut, sans chantier)¶
Plutôt qu'une allowlist .gitignore fragile, on encode l'intention « ne partager que l'explicitement marqué » à l'écriture : tout nouveau fichier .md sous concepts/, decisions/, resources/, areas/, projects/, people/ doit porter un frontmatter confidentiality: public|internal|restricted, sinon le commit est bloqué. Les fichiers existants ne sont pas concernés (on ne contrôle que les nouveaux arrivants). L'infra (scripts/, .cursor/, plugins/, cloud-agents/…) n'est pas soumise à cette règle.
C'est la mise en œuvre mécanique de la lentille formalisation & confidentialité (« écrire propre à l'entrée ») et un pas vers l'endgame « de la denylist à la classification » évoqué dans AGENTS.md.
Conséquences¶
Positives attendues¶
- Fuite de
private/ou de secrets vers le partagé impossible même en contournant les hooks locaux (barrière serveur). - Un nouveau contenu wiki ne peut plus partir sans décision de sensibilité explicite.
- Aucune reclassification des ~233 fichiers déjà partagés (coût de migration nul).
Négatives acceptées¶
- Le ruleset serveur n'a pas de bypass : personne (même admin) ne peut pousser
private/vers le partagé. Acceptable — ça n'a jamais lieu d'être. - Friction : créer un fichier wiki oblige à le classer.
Reversibilité¶
- Coût d'annulation : bas. Le ruleset se supprime via l'API/UI GitHub ; les hooks se retirent de
.githooks/.
Plan d'implémentation¶
- [x] Pre-push hook (
.githooks/pre-push) — testé (blocage local d'un pushprivate/). - [x] Ruleset serveur GitHub (push, restricted file paths, no bypass) — testé (rejet serveur d'un push
private/). - [x] Extension du pre-commit : garde « classer avant de partager » — testée (4 cas).
- Ownership : romain.
Métriques de succès¶
- Zéro fichier
private/**ou secret présent sur le remote partagé, en continu. - Zéro nouveau fichier wiki partagé sans classification.
Sources¶
- Session de mise en place 2026-07-09 (Romain).
- ADR 2026-06-12 — remote team-internal, partage par défaut (que cet ADR complète côté garde-fous).
- concepts/formalisation-confidentialite.md.
Révisions¶
- 2026-07-09 : créée et acceptée (status: accepted).