chore(git): garde-fou gitleaks, hygiène .gitignore et docs à jour #36

Merged
kevin merged 5 commits from chore/hygiene-git into main 2026-07-27 22:27:47 +00:00
Owner

Passe d'hygiène git + docs, suite au scan sécurité du 2026-07-26.

Garde-fou secrets (le fond du sujet)

Trois clés provider (OpenRouter, Google, ElevenLabs) ont été commitées en clair dans data/config.json début 2026 et sont restées récupérables dans l'historique des trois remotes. Vérification du 2026-07-26 : les trois sont aujourd'hui révoquées (OpenRouter HTTP 401, Google API_KEY_INVALID, ElevenLabs révoquée manuellement). Mais rien n'empêchait un troisième épisode.

Un job secret-scan est ajouté aux deux CI (GitHub + Forgejo), gitleaks pinné en 8.30.1 :

  • scan de tout l'historique (fetch-depth: 0, et pas de --depth 1 côté Forgejo) — un secret introduit puis retiré dans la même PR ne doit pas passer ;
  • --redact, parce que les logs CI sont eux-mêmes un canal de fuite ;
  • .gitleaks.toml allowliste les deux commits de la fuite historique — sans ça la CI serait rouge en permanence pour des clés mortes, et un garde-fou toujours rouge finit ignoré ;
  • les deux tests qui vérifient le masquage des secrets sont allowlistés nominativement, pas backend/tests/ en entier : un vrai secret commité par erreur ailleurs doit continuer à faire échouer la CI.

Vérifié localement dans les deux sens : 1453 commits scannés sans détection, et deux fausses clés à entropie réaliste bien attrapées.

Corrections de documentation

  • SECURITY.md annonçait la 3.x comme ligne supportée alors que l'app est en 5.135.0. C'est la politique publique : elle indiquait à un chercheur externe qu'un rapport sur la 5.x était hors scope.
  • CLAUDE.md se contredisait sur le compte de clés i18n — 3682 ligne 211, 3622 ligne 367 — et les deux étaient faux (réel : 3853). Le résidu de chaînes en dur passe de « ~60 » à 76 sur 15 fichiers, dont 35 concentrées dans plugins/valkyrie/index.tsx. Chiffres relevés en exécutant la jauge.
  • COMPARATIF.md supprimé : figé à mai 2026 et classant les alternatives par étoiles GitHub. Sa ligne devenue morte dans .dockerignore part avec. Les mentions dans le CHANGELOG sont conservées — ce sont des entrées historiques.

Hygiène

data/ est énuméré fichier par fichier dans .gitignore, donc chaque nouveau répertoire runtime repollue git status. data/channels/, data/consciousness_snapshots/ et les sauvegardes horodatées data/*.bak.* traînaient en untracked depuis des semaines.

C'est le même motif que la denylist d'env_sandbox relevée par l'audit : une liste nominative rate toujours le nom suivant. Passer data/ en tout-ignoré avec exceptions serait plus robuste, mais c'est un changement de convention à trancher séparément.


Hors PR, dans le même passage : main suivait origin (GitHub, gelé au 30 juin, 88 commits de retard) et suit désormais forgejo/main — même bug que celui corrigé sur Morrigan le 26 juillet. 14 branches locales absorbées supprimées (SHA notés pour restauration), 20 références de suivi périmées élaguées.

🤖 Generated with Claude Code

https://claude.ai/code/session_01XgvmDvw4ZGuUVkSkoMtEn7

Passe d'hygiène git + docs, suite au scan sécurité du 2026-07-26. ## Garde-fou secrets (le fond du sujet) Trois clés provider (OpenRouter, Google, ElevenLabs) ont été commitées en clair dans `data/config.json` début 2026 et sont restées récupérables dans l'historique des trois remotes. **Vérification du 2026-07-26 : les trois sont aujourd'hui révoquées** (OpenRouter HTTP 401, Google `API_KEY_INVALID`, ElevenLabs révoquée manuellement). Mais rien n'empêchait un troisième épisode. Un job `secret-scan` est ajouté aux **deux** CI (GitHub + Forgejo), gitleaks pinné en 8.30.1 : - scan de **tout l'historique** (`fetch-depth: 0`, et pas de `--depth 1` côté Forgejo) — un secret introduit puis retiré dans la même PR ne doit pas passer ; - `--redact`, parce que les logs CI sont eux-mêmes un canal de fuite ; - `.gitleaks.toml` allowliste les **deux commits de la fuite historique** — sans ça la CI serait rouge en permanence pour des clés mortes, et un garde-fou toujours rouge finit ignoré ; - les deux tests qui vérifient le masquage des secrets sont allowlistés **nominativement**, pas `backend/tests/` en entier : un vrai secret commité par erreur ailleurs doit continuer à faire échouer la CI. Vérifié localement dans les deux sens : **1453 commits scannés sans détection**, et deux fausses clés à entropie réaliste bien attrapées. ## Corrections de documentation - **`SECURITY.md`** annonçait la **3.x** comme ligne supportée alors que l'app est en 5.135.0. C'est la politique publique : elle indiquait à un chercheur externe qu'un rapport sur la 5.x était hors scope. - **`CLAUDE.md`** se contredisait sur le compte de clés i18n — 3682 ligne 211, 3622 ligne 367 — et les deux étaient faux (réel : **3853**). Le résidu de chaînes en dur passe de « ~60 » à **76 sur 15 fichiers**, dont 35 concentrées dans `plugins/valkyrie/index.tsx`. Chiffres relevés en exécutant la jauge. - **`COMPARATIF.md` supprimé** : figé à mai 2026 et classant les alternatives par étoiles GitHub. Sa ligne devenue morte dans `.dockerignore` part avec. Les mentions dans le CHANGELOG sont conservées — ce sont des entrées historiques. ## Hygiène `data/` est énuméré fichier par fichier dans `.gitignore`, donc chaque nouveau répertoire runtime repollue `git status`. `data/channels/`, `data/consciousness_snapshots/` et les sauvegardes horodatées `data/*.bak.*` traînaient en untracked depuis des semaines. C'est le même motif que la denylist d'`env_sandbox` relevée par l'audit : une liste nominative rate toujours le nom suivant. Passer `data/` en tout-ignoré avec exceptions serait plus robuste, mais c'est un changement de convention à trancher séparément. --- Hors PR, dans le même passage : `main` suivait `origin` (GitHub, gelé au 30 juin, 88 commits de retard) et suit désormais `forgejo/main` — même bug que celui corrigé sur Morrigan le 26 juillet. 14 branches locales absorbées supprimées (SHA notés pour restauration), 20 références de suivi périmées élaguées. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01XgvmDvw4ZGuUVkSkoMtEn7
Trois clés provider (OpenRouter, Google, ElevenLabs) ont été commitées en
clair dans data/config.json début 2026 et sont restées récupérables dans
l'historique des trois remotes. Vérification du 2026-07-26 : les trois sont
aujourd'hui révoquées, mais rien n'empêchait un troisième épisode.

Le job échoue si un secret de forme connue entre dans un commit. Il scanne
tout l'historique (fetch-depth: 0, pas de --depth 1 côté Forgejo) : un secret
introduit puis retiré dans la même PR ne doit pas passer. --redact car les
logs CI sont eux-mêmes un canal de fuite.

.gitleaks.toml allowliste les deux commits de la fuite historique — sans ça
la CI serait rouge en permanence pour des clés mortes, et un garde-fou
toujours rouge finit ignoré. Les deux tests qui vérifient le masquage des
secrets sont allowlistés nominativement, PAS backend/tests/ en entier.

Vérifié localement : 1453 commits scannés sans détection, et deux fausses
clés à entropie réaliste bien attrapées.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XgvmDvw4ZGuUVkSkoMtEn7
data/ est énuméré fichier par fichier dans .gitignore, donc chaque nouveau
répertoire créé par l'app repollue `git status` en permanence :
data/channels/, data/consciousness_snapshots/ et les sauvegardes
horodatées data/*.bak.* traînaient en untracked depuis des semaines.

Même motif que la denylist d'env_sandbox relevée par l'audit sécu : une
liste nominative rate toujours le nom suivant. Passer data/ en tout-ignoré
avec des exceptions serait plus robuste, mais c'est un changement de
convention à trancher séparément.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XgvmDvw4ZGuUVkSkoMtEn7
Le tableau des versions supportées n'avait pas bougé depuis deux majeures :
il annonçait 3.x alors que l'app est en 5.135.0. C'est la politique de
sécurité publique — elle indiquait à un chercheur externe que la branche
maintenue était la 3.x, donc qu'un rapport sur la 5.x était hors scope.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XgvmDvw4ZGuUVkSkoMtEn7
Le fichier annonçait deux comptes de clés différents pour la même source FR
— 3682 ligne 211, 3622 ligne 367 — et les deux étaient faux : la jauge en
mesure 3853. Le résidu de chaînes en dur était donné à « ~60 » à deux
endroits alors qu'il est de 76 sur 15 fichiers, dont 35 concentrées dans
plugins/valkyrie/index.tsx (l'info utile pour qui voudra les résorber).

Chiffres relevés en exécutant frontend/scripts/i18n-coverage.mjs, pas
recopiés.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XgvmDvw4ZGuUVkSkoMtEn7
docs: retirer COMPARATIF.md, figé à mai 2026
All checks were successful
CI / Backend — pytest (pull_request) Successful in 1m0s
CI / i18n — usage → locales (pull_request) Successful in 45s
CI / Secrets — gitleaks (pull_request) Successful in 21s
e524bef973
Le comparatif concurrentiel datait de mai et classait les alternatives par
nombre d'étoiles GitHub — une métrique qui bouge tous les mois. Un
instantané concurrentiel périmé dans le dépôt informe moins qu'il n'induit
en erreur.

La ligne correspondante de .dockerignore devient morte et part avec. Les
mentions dans CHANGELOG.md sont conservées : ce sont des entrées
historiques, elles décrivent ce qui s'est passé à l'époque.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XgvmDvw4ZGuUVkSkoMtEn7
kevin merged commit 0b12915c40 into main 2026-07-27 22:27:47 +00:00
kevin deleted branch chore/hygiene-git 2026-07-27 22:27:47 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
kevin/Gungnir!36
No description provided.