La Granularización OSS/CSS — Por qué he dividido foundry/ en dos
Publié le 03 May 2026
foundry/— la zona funcional que aloja el código de mi workspace — contiene 18 proyectos. Ocho son de código abierto bajo Apache 2.0. Solo uno es código cerrado — el SaaS Edster. Durante meses, estos nueve proyectos han coexistido en el mismo directorio, separados únicamente por… nada. Su estado público/privado Era una información en mi cabeza, no en el sistema de archivos.
Y luego quise conectar un RAG. Y entonces todo se derrumbó.
El accidente que esperaba ocurrir
En abril de 2026, comencé a implementar el RAG pgvector para slider-gradle. El principio: indexar todos los depósitos de`foundry/, producir de embeddings, e inyectarlos en el contexto del LLM para que tenga una percepción" del expediente`foundry/.
El pipeline era sencillo :
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. Eficaz. Ypeligroso.
Porque este`fileTree`no hace la diferencia entre`plantuml-gradle/` (Apache 2.0, public) y`edster/`(closed source, private). Lo traga todo. Y si un día publico estos embeddings — en un tablero, en una respuesta LLM, en un conjunto de datos de entrenamiento — el código propietario de Edster se filtra.
|
El problema no es que un LLM lea código fuente cerrado. El problema, que este código termine en un embedding vectorial public — irreversible, no suprimible, no auditável |
La Verdadera Pregunta
No es "¿cómo impedir que el LLM filtre código?". Es "cómo ¿hacer que la fuga sea estructuralmente imposible?
La respuesta no es un prompt. La respuesta, es cortar el archivo en dos.
La Solución : OSS/ y CSS/
Antes :
foundry/
├── plantuml-gradle/ ← public
├── bakery-gradle/ ← public
├── magic-stick/ ← public
├── edster/ ← PRIVÉ
├── slider-gradle/ ← public
└── ... ← mélange invisible
Después:
foundry/
├── OSS/ ← tout est Apache 2.0
│ ├── plantuml-gradle/
│ ├── bakery-gradle/
│ ├── magic-stick/
│ ├── slider-gradle/
│ └── ...
└── CSS/ ← tout est closed source / private
└── edster/
Le `fileTree`se convierte :
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é
|
El RAG público nunca ve`CSS/`. El código closed source alimenta un dataset privado de fine-tuning — un modelo interno que nunca sale de mi casa. La la separación es mecánica, no declarativa. |
¿Por qué "OSS" y "CSS" y no "Público" y "Privado
La elección de los acrónimos OSS (Open Source Software) y CSS (Closed Source Software) está decidido:
-
Público"/"Privado" describe lavisibilidad(lo que GitHub ve)
-
OSS"/"CSS" describe lanaturalezacódigo (lo que el LLM debe saber)
La visibilidad de GitHub es un metadato del repositorio distante. La naturaleza del código es una propiedad del contenido. El LLM no tiene acceso a la API de GitHub — pero tiene acceso al sistema de archivos.CSS/`le dice "atención, este código no está bajo licencia libre" sin necesidad de leer un`LICENSE`o de analizar un`package.json.
|
El nombre de la carpeta es el metadato más robusto que usted pueda dar a un LLM. No puede ser mal analizada, ignorada o mal interpretada. El LLM ve`CSS/edster/`en la ruta del archivo — él sabe. |
El Árbol Completo — Cuatro Zonas, No Tres
La granularización OSS/CSS completa la ontología de tres zonas. La zona `foundry/`pasa de 1 a 2 subzonas funcionales :
| Zona | RGPD | Indexación RAG pública | Conjunto de datos fine-tuning | | Raíz | Nivel 0 — Íntimo | ✗ | ✗ | | configuration/| Nivel 1 — Restringido | ✗ | ✗ | | office/| Nivel 2 — Colaborativo | ✓ filtrado | ✓ filtrado | | foundry/private/| Nivel 3 — Abierto condicional | ✗ | ✓ Privado | | foundry/public/| Nivel 4 — Público nativo | ✓ Libre | ✓ Público |
El Caso Particular : cheroliv.com
Mientras estaba allí, corregí otra incoherencia. Mi sitio cheroliv.com`vivía en`foundry/`como un proyecto de software de pleno derecho — con su propio build Gradle, su propia CI, su propia gobernancia.agents/`.
Pero los artículos de blog no son código. Son datos editoriales** de Cercle 2 — al mismo nivel que los encuadres de`office/pilotage/` o las formaciones de`office/formations/`.
AVANT APRÈS
foundry/ office/
cheroliv.com/ sites/
site/jbake/content/blog/ cheroliv.com/
2026/0117_....adoc 2026/0117_....adoc
Lo que cambia:
-
Los artículos están en`office/`→ confidencialidad de Círculo 2
-
La tarea`publishSite`se convierte en una capability de`engine`
via`bakery-gradle`— el plugin recibe un`FileTree`, él no sabe que los artículos vienen de`office/`
-
Un solo CI, una sola gobernanza — cero duplicación
-
El clasificador Vision/Opinion (Regla 2bis) se aplica automáticamente :
los artículos en`office/`se filtran antes de la publicación
bakery-gradle le da igual
Y eso es lo que es hermoso. El plugin`bakery-gradle`No ha sido modificado. Recibe un directorio de contenido AsciiDoc, genera HTML, hace push en GitHub Pages. Que este directorio se llame`site/jbake/content/` ou office/sites/cheroliv/— el plugin le da igual.
// 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
}
}
El contrato de interfaz es una tarea Gradle. No es una API REST. No es un webhook. Una tarea — tipada, comprobable, ejecutable localmente y en CI.
Impacto sobre el agente de gobernanza
La granularización OSS/CSS modifica la gobernanza de los agentes en tres puntos:
-
RAG public : el perímetro de indexación pasa de`foundry/**`
à foundry/public/+office/Vision/. El código de código cerrado está excluido del índice por configuración de tarea, no por prompt.
-
Knowledge Graph : graphify-gradle produce dos grafos :
*office/graph.json(public) — relaciones entre artefactos OSS + office/Vision * configuration/graph_private.json(gitignored, privado) — relaciones entre artefactos CSS, nunca publicado
-
Ajuste fino del dataset :`codebase-gradle`ahora tiene dos fuentes:
*OSS/→ datasets públicos (modelos comunitarios, benchmarks) *CSS/→ datasets privados (modelo interno, fine-tuning propietario)
Lo Que Ganamos (Y Lo Que Perdemos)
Antes (carpeta plana) |
Después (OSS/CSS + office/sites) |
|
|
RAG indexa todo sin discriminación |
RAG indexa`OSS/`+`office/Vision`exclusivamente |
Imposible saber si un proyecto es de código abierto |
El camino`OSS/` ou `CSS/`lo dice |
cheroliv.com tiene su propia CI, su propia gobernanza |
La CI y la gobernanza se comparten en engine |
Los artículos de blog están en un repositorio "code |
Los artículos de blog están en`office/sites/`— datos, no código |
Riesgo de fuga de código fuente cerrado en embeddings públicos |
Estructuralmente imposible —`CSS/`fuera del alcance RAG |
El único costo: un`git mv`global sobre los 17 repositorios OSS + una refactorización del build.gradle.kts de engine. Es una migración en frío — sin datos en vuelo, sin usuarios afectados
Conclusión: el Señal Física supera al Señal de Software
Lo que hice esta tarde es reemplazar una convención invisible por una separación visible en la zona`foundry/. Antes, usted debía saber que`edster/`era de código cerrado. Ahora, ustedes lo ven — el dossier se llama`CSS/.
Es el mismo principio que los permisos Unix, las VLAN de red, o los compartimentos cortafuegos en una base de datos. La seguridad no debe ser una información que debes recordar. Debe ser una propiedad físicadel sistema.
La granularidad OSS/CSS es la traducción de este principio en el campo de la gobernanza LLM. El LLM no necesita saber que Edster es confidencial. Necesita ser incapaz de indexarlo.
Y esto es exactamente lo que`CSS/`garantiza.