The OSS/CSS Granularization — Why I Split foundry/ Into Two
Published on 03 May 2026
foundry/— the functional area that hosts the code of my workspace — contains 18 projects. Eight are open source under Apache 2.0. One is closed source — the SaaS Edster. For months, these nine projects coexisted. in the same folder, separated only by… nothing. Their public/private status It was information in my head, not in the file system.
And then I wanted to hook up a RAG. And then everything fell apart.
The Accident Waiting to Happen
In April 2026, I started implementing the pgvector RAG for slider-gradle. The principle: indexing all repositories of`foundry/, producing some embeddings, and inject them into the LLM context so that it has a perception" of the file`foundry/}.
The pipeline was 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. Effective. Anddangerous.
Because this`fileTree`does not distinguish between`plantuml-gradle/` (Apache 2.0, public) and`edster/`(closed source, private). He eats everything. And if one day I publish these embeddings — on a dashboard, in a response LLM, in a training dataset — Edster’s proprietary code is leaking.
|
The problem isn’t that an LLM reads closed-source code. The problem, It’s that this code ends up in a public vector embedding — irreversible, non-deletable, non-auditable |
The True Question
It is not "how to prevent the LLM from leaking code?". It is "how make escape structurally impossible?
The answer is not a prompt. The answer is to cut the folder in half.
The Solution: OSS/ and CSS/
Before:
foundry/
├── plantuml-gradle/ ← public
├── bakery-gradle/ ← public
├── magic-stick/ ← public
├── edster/ ← PRIVÉ
├── slider-gradle/ ← public
└── ... ← mélange invisible
After:
foundry/
├── OSS/ ← tout est Apache 2.0
│ ├── plantuml-gradle/
│ ├── bakery-gradle/
│ ├── magic-stick/
│ ├── slider-gradle/
│ └── ...
└── CSS/ ← tout est closed source / private
└── edster/
Le `fileTree`becomes :
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é
|
Public RAG never sees`CSS/`. The closed-source code feeds a dataset deprived of fine-tuning — an internal model that never leaves my home. The The separation is mechanical, not declarative. |
Why "OSS" and "CSS" and Not "Public" and "Private
The choice of the acronyms OSS (Open Source Software) and CSS (Closed Source Software) it is resolved:
-
Public"/"Private" describes thevisibility(what GitHub sees)
-
OSS"/"CSS" describes thenaturecode (what the LLM must know)
GitHub visibility is metadata for the remote repository. The nature of the code is a property of the content. The LLM does not have access to the GitHub API — but it has access to the file system.CSS/`he said to him, "Attention, this code is not under license free" without needing to read a`LICENSE`or to parse a`package.json.
|
The folder name is the most robust metadata you can give to an LLM. It cannot be mis-parsed, ignored, or misinterpreted. The LLM sees`CSS/edster/`in the file path — it knows. |
The Complete Tree — Four Zones, Not Three
The OSS/CSS granularization complements the three-zone ontology. The zone `foundry/`goes from 1 to 2 functional sub-zones:
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam wrapWidth 260
title Organization of foundry/ — Granularization OSS/CSS
package "foundry/" {
package "Circle 0 — The Root" #FFCCCC {
rectangle "PICTURE_ME_ROLLIN_*.adoc" as STIM
rectangle "WORKSPACE_*.adoc" as VISION_DOC
note right of STIM
Brain dump libre
Jamais versionné
[LLM : interdit d'indexer]
end note
}
package "Circle 1 — configuration/" #FFD9CC {
rectangle "Secrets, tokens" as SECRETS
rectangle "Spring Cloud Config" as SCC
note right of SECRETS
Privé-CVS, solo access
[LLM : INTERDIT]
end note
}
package "Circle 2 — office/" #FFFFCC {
rectangle "Articles, framing" as DATA
rectangle "Trainings, SPG/SPD" as FORM
note right of DATA
Privé-CVS
[LLM : filtré Vision/Opinion]
end note
}
package "Circle 3 — foundry/" #CCE5FF {
package "OSS/ — Apache 2.0" #CCFFCC {
rectangle "Gradle plugins" as PLUGINS
rectangle "engine" as ENGINE
}
package "CSS/ — Closed Source" #CCDDFF {
rectangle "edster/" as EDSTER
}
}
}
@enduml
| Zone | GDPR | Public RAG indexing | Dataset fine-tuning | | Root | Level 0 — Intimate | ✗ | ✗ | |configuration/| Level 1 — Restricted | ✗ | ✗ | (empty)office/| Level 2 — Collaborative | ✓ Filtered | ✓ Filtered | | foundry/private/| Level 3 — Conditional open | ✗ | ✓ Private | |foundry/public/| Level 4 — Native audience | ✓ Free | ✓ Public |
The Special Case: cheroliv.com
While I was at it, I fixed another inconsistency. My site cheroliv.com`lived in`foundry/`as a software project fully-fledged — with its own Gradle build, its own CI, its own governance.agents/`.
But blog posts are not code. They are data editorials** of Cercle 2 — on an equal footing with the framings of`office/pilotage/` or the training of`office/formations/`.
AVANT APRÈS
foundry/ office/
cheroliv.com/ sites/
site/jbake/content/blog/ cheroliv.com/
2026/0117_....adoc 2026/0117_....adoc
What changes:
-
The articles are in`office/`→ confidentiality of Circle 2
-
The task`publishSite`becomes a capability of`engine`
via`bakery-gradle`— the plugin receives a`FileTree`, he does not know that the articles come from`office/`
-
One CI, one governance — zero duplication
-
The Vision/Opinion classifier (Rule 2bis) applies automatically:
the articles in`office/`are filtered before publishing
bakery-gradle doesn’t care
And that’s what’s beautiful. The plugin`bakery-gradle`has not been modified. It receives an AsciiDoc content directory, it generates HTML, it pushes on GitHub Pages. That this directory is called`site/jbake/content/` ou office/sites/cheroliv/— the plugin doesn’t care.
// 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
}
}
The interface contract is a Gradle task. Not a REST API. Not a webhook. A task — typed, testable, executable locally and in CI.
Impact on Governance Agent
The OSS/CSS granularization modifies the agent governance on three points:
-
RAG public : the indexing scope changes from`foundry/**`
à foundry/public/ + office/Vision/. The code closed source is excluded from the index by task configuration, not by prompt.
-
Knowledge Graph : graphify-gradle produces two graphs :
*office/graph.json(public) — relations between OSS artifacts + office/Vision *configuration/graph_private.json(gitignored, private) — relations between CSS artifacts, never published
-
Dataset fine-tuning:`codebase-gradle`now has two sources :
*OSS/→ public datasets (community models, benchmarks) *CSS/→ private datasets (internal model, proprietary fine‑tuning)
What We Gain (And What We Lose)
Front (flat file) |
After (OSS/CSS + office/sites) |
|
|
RAG indexes everything without discrimination |
RAG indexes`OSS/`+`office/Vision`exclusively |
Impossible to know if a project is open source |
The path`OSS/` ou `CSS/`the said |
cheroliv.com has its own CI, its own governance |
CI and governance are pooled in engine |
Blog posts are in a 'code' repository |
Blog posts are in`office/sites/`— data, not code |
Risk of leaking closed-source code in public embeddings |
Structurally impossible —`CSS/`out of scope RAG |
The only cost: a`git mv`overall across the 17 OSS repositories + a refactor of the build.gradle.kts de engine. This is a cold migration — no data in flight, no users impacted.
Conclusion: The Physical Signal Beats the Software Signal
What I did this afternoon was replace an invisible convention by a visible separation in the area`foundry/. Before, you had to to know that`edster/`was closed source. Now you see it — the folder is called`CSS/.
It’s the same principle as Unix permissions, network VLANs, or the Fire compartments in a database. Safety must not be information that you must remember. It must be a property physicsof the system.
OSS/CSS granularization is the translation of this principle into the field of LLM governance. The LLM does not need to know that Edster is confidential. It needs to be unable to index it.
And that’s exactly what`CSS/`guarantees.