La Granularisation OSS/CSS — Pourquoi J'ai Coupé __repositories__/ en Deux
Publié le 03 May 2026
- 1. L’Accident qui Attendait de se Produire
- 2. La Solution : OSS/ et CSS/
- 3. Pourquoi "OSS" et "CSS" et Pas "Public" et "Private"
- 4. Le Cas Particulier : cheroliv.com
- 5. Impact sur la Gouvernance Agent
- 6. Ce Qu’on Gagne (Et Ce Qu’on Perd)
- 7. Conclusion : le Signal Physique Bat le Signal Logiciel
- 8. Références
repositories/ — la zone fonctionnelle qui héberge le code de mon workspace —
contient 18 projets. Huit sont open source sous Apache 2.0. Un seul est
closed source — le SaaS Edster. Pendant des mois, ces neuf projets ont cohabité
dans le même dossier, séparés uniquement par… rien. Leur statut public/privé
était une information dans ma tête, pas dans le système de fichiers.
Et puis j’ai voulu brancher un RAG. Et là, tout s’est effondré.
1. L’Accident qui Attendait de se Produire
En avril 2026, j’ai commencé à implémenter le RAG pgvector pour slider-gradle.
Le principe : indexer tous les dépôts de repositories/, produire des
embeddings, et les injecter dans le contexte du LLM pour qu’il ait une
"perception" du dossier repositories/.
Le pipeline était simple :
val repos = fileTree(rootDir) {
include("**/*.adoc", "**/*.kts", "**/*.kt", "**/*.json", "**/*.yml")
}
val chunks = repos.map { chunk(it) }
val embeddings = chunks.map { embed(it) }
pgvector.insert(embeddings)
Simple. Efficace. Et dangereux.
Parce que ce fileTree ne fait pas la différence entre plantuml-gradle/
(Apache 2.0, public) et edster/ (closed source, private). Il avale tout.
Et si un jour je publie ces embeddings — sur un dashboard, dans une réponse
LLM, dans un dataset d’entraînement — le code propriétaire d’Edster fuit.
|
Le problème n’est pas qu’un LLM lise du code closed source. Le problème, c’est que ce code finisse dans un embedding vectoriel public — irréversible, non supprimable, non auditable. |
1.1. La Vraie Question
Ce n’est pas "comment empêcher le LLM de fuiter du code ?". C’est "comment rendre la fuite structurellement impossible ?"
La réponse n’est pas un prompt. La réponse, c’est de couper le dossier en deux.
2. La Solution : OSS/ et CSS/
Avant :
__repositories__/
├── plantuml-gradle/ ← public
├── bakery-gradle/ ← public
├── magic_stick/ ← public
├── edster/ ← PRIVÉ
├── slider-gradle/ ← public
└── ... ← mélange invisible
Après :
__repositories__/
├── OSS/ ← tout est Apache 2.0
│ ├── plantuml-gradle/
│ ├── bakery-gradle/
│ ├── magic_stick/
│ ├── slider-gradle/
│ └── ...
└── CSS/ ← tout est closed source / private
└── edster/
Le fileTree devient :
val ossRepos = fileTree(File(rootDir, "OSS")) {
include("**/*.adoc", "**/*.kts", "**/*.kt", "**/*.json", "**/*.yml")
}
val cssRepos = fileTree(File(rootDir, "CSS")) {
include("**/*.adoc", "**/*.kts", "**/*.kt", "**/*.json", "**/*.yml")
}
// Embeddings publics — OSS seulement
pgvectorPublic.insert(ossRepos.map { chunk(it) }.map { embed(it) })
// Dataset fine-tuning privé — CSS seulement
fineTuningDataset.insert(cssRepos.map { chunk(it) }) // jamais publié
|
Le RAG public ne voit jamais |
3. Pourquoi "OSS" et "CSS" et Pas "Public" et "Private"
Le choix des acronymes OSS (Open Source Software) et CSS (Closed Source Software) est délibéré :
-
"Public"/"Private" décrit la visibilité (ce que GitHub voit)
-
"OSS"/"CSS" décrit la nature du code (ce que le LLM doit savoir)
La visibilité GitHub est une métadonnée du repo distant. La nature du code est
une propriété du contenu. Le LLM n’a pas accès à l’API GitHub — mais il a accès
au système de fichiers. CSS/ lui dit "attention, ce code n’est pas sous licence
libre" sans avoir besoin de lire un LICENSE ou de parser un package.json.
|
Le nom du dossier est la métadonnée la plus robuste que vous puissiez donner à
un LLM. Elle ne peut pas être mal parsée, ignorée, ou mal interprétée. Le LLM
voit |
3.1. L’Arbre Complet — Quatre Zones, Pas Trois
La granularisation OSS/CSS complète l’ontologie à trois zones. La zone
repositories/ passe de 1 à 2 sous-zones fonctionnelles :
| Zone | RGPD | Indexation RAG public | Dataset fine-tuning |
| Racine | Niveau 0 — Intime | ✗ | ✗ |
| configuration/ | Niveau 1 — Restreint | ✗ | ✗ |
| office/ | Niveau 2 — Collaboratif | ✓ Filtré | ✓ Filtré |
| repositories/CSS/ | Niveau 3 — Ouvert conditionnel | ✗ | ✓ Privé |
| repositories/OSS/ | Niveau 4 — Public natif | ✓ Libre | ✓ Public |
4. Le Cas Particulier : cheroliv.com
Pendant que j’y étais, j’ai corrigé une autre incohérence. Mon site
cheroliv.com vivait dans repositories/ comme un projet logiciel
à part entière — avec son propre build Gradle, sa propre CI, sa propre
gouvernance .agents/.
Mais les articles de blog ne sont pas du code. Ce sont des données
éditoriales de Cercle 2 — au même titre que les cadrages de office/pilotage/
ou les formations de office/formations/.
AVANT APRÈS
__repositories__/ office/
cheroliv.com/ sites/
site/jbake/content/blog/ cheroliv.com/
2026/0117_....adoc 2026/0117_....adoc
Ce qui change :
-
Les articles sont dans
office/→ confidentialité de Cercle 2 -
La tâche
publishSitedevient une capability deworkspace-engineviabakery-gradle— le plugin reçoit unFileTree, il ne sait pas que les articles viennent deoffice/ -
Une seule CI, une seule gouvernance — zéro duplication
-
Le classifier Vision/Opinion (Règle 2bis) s’applique automatiquement : les articles dans
office/sont filtrés avant publication
4.1. bakery-gradle S’En Fiche
Et c’est ça qui est beau. Le plugin bakery-gradle n’a pas été modifié.
Il reçoit un répertoire de contenu AsciiDoc, il génère du HTML, il push
sur GitHub Pages. Que ce répertoire s’appelle site/jbake/content/ ou
office/sites/cheroliv/ — le plugin s’en fout.
// workspace-engine/build.gradle.kts
task("publishBlog") {
doLast {
val articles = fileTree("../../office/sites/cheroliv/2026/")
bakery.generate(articles) // ← bakery ne sait pas d'où ça vient
}
}
Le contrat d’interface est une tâche Gradle. Pas une API REST. Pas un webhook. Une tâche — typée, testable, exécutable en local et dans la CI.
5. Impact sur la Gouvernance Agent
La granularisation OSS/CSS modifie la gouvernance agent sur trois points :
-
RAG public : le périmètre d’indexation passe de
repositories/àrepositories/OSS/+office/Vision/**. Le code closed source est exclu de l’index par configuration de tâche, pas par prompt. -
Knowledge Graph : graphify-gradle produit deux graphes :
-
office/graph.json(public) — relations entre artéfacts OSS + office/Vision -
configuration/graph_private.json(gitignored, privé) — relations entre artéfacts CSS, jamais publié
-
-
Dataset fine-tuning :
codebase-gradlea désormais deux sources :-
OSS/→ datasets publics (modèles communautaires, benchmarks) -
CSS/→ datasets privés (modèle interne, fine-tuning propriétaire)
-
6. Ce Qu’on Gagne (Et Ce Qu’on Perd)
| Avant (dossier plat) | Après (OSS/CSS + office/sites) |
|---|---|
|
|
RAG indexe tout sans discrimination |
RAG indexe |
Impossible de savoir si un projet est open source |
Le chemin |
cheroliv.com a sa propre CI, sa propre gouvernance |
La CI et la gouvernance sont mutualisées dans workspace-engine |
Les articles de blog sont dans un dépôt "code" |
Les articles de blog sont dans |
Risque de fuite de code closed source dans des embeddings publics |
Structurellement impossible — |
Le seul coût : un git mv global sur les 17 dépôts OSS + un refactor du
build.gradle.kts de workspace-engine. C’est une migration à froid —
pas de données en vol, pas d’utilisateurs impactés.
7. Conclusion : le Signal Physique Bat le Signal Logiciel
Ce que j’ai fait cet après-midi, c’est remplacer une convention invisible
par une séparation visible dans la zone repositories/. Avant, vous deviez
savoir que edster/ était closed source. Maintenant, vous le voyez —
le dossier s’appelle CSS/.
C’est le même principe que les permissions Unix, les VLAN réseau, ou les compartiments coupe-feu dans une base de données. La sécurité ne doit pas être une information que vous devez retenir. Elle doit être une propriété physique du système.
La granularisation OSS/CSS est la traduction de ce principe dans le domaine de la gouvernance LLM. Le LLM n’a pas besoin de savoir qu’Edster est confidentiel. Il a besoin d’être incapable de l’indexer.
Et c’est exactement ce que CSS/ garantit.