время чтения : 10 minutes

foundry/— функциональная зона в которой находится код моего рабочего пространства — Содержит 18 проектов. Восемь из них находятся под лицензией открытого кода Apache 2.0. Один только Закрытый исходный код — это SaaS Edster. В течение месяцев эти девять проектов сосуществовали. в той же папке, разделены только… ничем. Их статус публичный/приватный Это была информация в моей голове, а не в файловой системе.

И потом я захотел подключить RAG. И там всё рухнулось.

Авария, которая ожидала случиться

В апреле 2026 года я начал внедрять RAG pgvector для slider-gradle. Принцип : индексировать все репозитории de`foundry/, производить некоторые embeddings, и внедрить их в контекст LLM, чтобы у него было восприятие" дела`foundry/.

Конвейер был прост :

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)

Просто. Эффективно. Иопасный.

Потому что это`fileTree`не делает различия между`plantuml-gradle/` (Apache 2.0, публичная) и`edster/`(closed source, private). Он проглатывает всё. И если однажды я опубликую эти эмбеддинги—на дашборде, в ответе LLM, в наборе данных для обучения — собственный код Edster утекает.

Проблема не в том, что LLM читает закрытый исходный код. Проблема, это значит, что этот код окажется в публичном векторном эмбеддинге. необратимый, неудалимый, непроверяемый.

Настоящий вопрос

Это не "как предотвратить утечку кода из LLM?". Это "как Сделать бегство структурно невозможным ?

Ответ не является запросом. Ответ — это разделить папку пополам.

Решение: OSS/ и CSS/

До :

foundry/
├── plantuml-gradle/       ← public
├── bakery-gradle/         ← public
├── magic-stick/           ← public
├── edster/                ← PRIVÉ
├── slider-gradle/         ← public
└── ...                    ← mélange invisible

После:

foundry/
├── OSS/                   ← tout est Apache 2.0
│   ├── plantuml-gradle/
│   ├── bakery-gradle/
│   ├── magic-stick/
│   ├── slider-gradle/
│   └── ...
└── CSS/                   ← tout est closed source / private
    └── edster/

Le `fileTree`становится :

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é

Публичный RAG никогда не видит`CSS/`. Закрытый исходный код формирует набор данных без дообучения — внутренняя модель, которая никогда не выходит из моего дома. La разделение механическое, не декларативное.

Почему "OSS" и "CSS" и Не "Public" и "Private" ?

Выбор аббревиатур OSS (Open Source Software) и CSS (Closed Source Software) обсуждается:

  • Public"/"Private" описывает laвидимость(что видит GitHub)

  • OSS"/"CSS" описываетприродакода (что LLM должен знать)

Видимость на GitHub является метаданными удалённого репозитория. Природа кода Свойство контента. У LLM нет доступа к API GitHub — но у него есть доступ. к файловой системе.CSS/`Он говорит ему "Внимание, этот код не находится под лицензии свободно" без необходимости читать один`LICENSE`или разобрать один`package.json.

Имя папки является наиболее надежной метаданной, которую вы можете дать одна LLM. Она не может быть неправильно обработана, проигнорирована или неправильно интерпретирована. Эта LLM видит`CSS/edster/`в пути к файлу — он знает

Полное дерево — четыре зоны, а не три

Гранулярность OSS/CSS дополняет онтологию из трёх зон. Зона `foundry/`переходит с 1 до 2 функциональных подзон:

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam wrapWidth 260

title Организация foundry/ — гранулирование OSS/CSS
package "foundry/" {

  package "Круг 0 — Корень" #FFCCCC {
    rectangle "PICTURE_ME_ROLLIN_*.adoc" as STIM
    rectangle "WORKSPACE_*.adoc" as VISION_DOC
    note right of STIM
Мозговой дамп свободный
Никогда не версионирован
[LLM : interdit d'indexer]
    end note
  }

  package "Круг 1 — конфигурация/" #FFD9CC {
    rectangle "Секреты, токены" as SECRETS
    rectangle "Spring Cloud Config" as SCC
    note right of SECRETS
Приватный-CVS, только доступ
[LLM : INTERDIT]
    end note
  }

  package "Круг 2 — офис/" #FFFFCC {
    rectangle "Статьи, планирование" as DATA
    rectangle "Обучение, SPG/SPD" as FORM
    note right of DATA
Частный-CVS [LLM : filtré Vision/Opinion]
    end note
  }

  package "Круг 3 — foundry/" #CCE5FF {
    package "OSS/ — Apache 2.0" #CCFFCC {
      rectangle "Плагины Gradle" as PLUGINS
      rectangle "engine" as ENGINE
    }
    package "CSS/ — Закрытый исходный код" #CCDDFF {
      rectangle "edster/" as EDSTER
    }
  }
}

@enduml

| Зона | RGPD | Публичная индексация RAG | Тонкая настройка датасета | | Корень | Уровень 0 — интимный | configuration/`Уровень 1 — Ограниченный | `office/| Уровень 2 — Совместный | ✓ Отфильтровано | ✓ Отфильтровано | | foundry/private/| Уровень 3 — Условно открыто | ✗ | ✓ Приватно (empty)`foundry/public/`Уровень 4 — Аудитория носителей | ✓ Бесплатно | ✓ Публичный

Особый случай : cheroliv.com

Пока я был там, я исправил другую несогласованность. Мой сайт cheroliv.com`жил в`foundry/`как программный проект полноценный — со своей собственной сборкой Gradle, своей CI, своей управление.agents/`.

Но сообщения в блоге не являются кодом. Это данные редакционные** Cercle 2 — наряду с кадрированием de`office/pilotage/` или тренировки`office/formations/`.

AVANT                            APRÈS
foundry/                office/
  cheroliv.com/                    sites/
    site/jbake/content/blog/         cheroliv.com/
      2026/0117_....adoc               2026/0117_....adoc

Что меняется :

  • Статьи находятся в`office/`конфиденциальность круга 2

  • Задача`publishSite`становится возможностью`engine`

через`bakery-gradle`— плагин получает`FileTree`, он не знает что статьи приходят из`office/`

  • Одна единственная CI, одна управляющая структура — отсутствие дублирования

  • Классификатор Vision/Opinion (Правило 2bis) применяется автоматически :

статьи в`office/`фильтруются перед публикацией

bakery-gradle всё равно

И это прекрасно. Плагин`bakery-gradle`Он не был изменён. Он получает каталог содержимого AsciiDoc, он генерирует HTML, он пушит. на GitHub Pages. Что этот каталог называется`site/jbake/content/` ou office/sites/cheroliv/— плагин всё равно

// 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
    }
}

Контракт интерфейса — это задача Gradle. Не API REST. Не вебхук. Одна задача — типизированная, тестируемая, исполняемая локально и в CI.

Влияние на Gouvernance Agent

Грануляция OSS/CSS меняет управление агентом на трёх пунктах:

  1. RAG public : Область индексации переходит от`foundry/**`

à foundry/public/(empty)office/Vision/. Закрытый исходный код Исключен из индекса по настройке задачи, а не промптом.

  1. Knowledge Graph : graphify-gradle производит два графа :

*office/graph.json(public) — отношения между артефактами OSS + офис/Видение *configuration/graph_private.json(gitignored, приватный) — отношения между артефакты CSS, никогда не опубликован

  1. Тонкая настройка датасета :`codebase-gradle`Теперь у него два источника:

*OSS/→ общедоступные наборы данных (модели сообщества, бенчмарки) *`CSS/`частные наборы данных (внутренняя модель, проприетарное дообучение)

Что мы получаем (и что теряем)

Перед (плоский файл) После (OSS/CSS + office/sites)

ls foundry/→ смесь публичного/частного

ls foundry/public/→ всё можно публиковать

RAG индексирует всё без дискриминации

RAG индексирует`OSS/` + `office/Vision`исключительно

Невозможно узнать, является ли проект открытым исходным кодом.

Путь`OSS/` ou `CSS/`говорит

У cheroliv.com есть своя CI, своё управление.

CI и управление объединены в engine

Статьи блога находятся в репозитории "code

Статьи блога находятся в`office/sites/`— данные, не код

Риск утечки закрытого исходного кода в публичных эмбеддингах

Структурно невозможно —`CSS/`вне области RAG

Единственная стоимость: один`git mv`глобальный для 17 репозиториев OSS + рефакторинг du build.gradle.kts de engine. Это холодная миграция — нет данных в полёте, нет затронутых пользователей.

Вывод: физический сигнал бьёт логический сигнал

То, что я сделал этим после обеда, это заменил невидимую конвенцию. через видимое разделение в зоне`foundry/. Раньше вам нужно было знать что`edster/`был закрытым исходным кодом. Теперь вы его видите — Папка называется`CSS/.

Это тот же принцип, что у разрешений Unix, сетевых VLAN или противопожарные отсеки в базе данных. Безопасность не должна быть информацией, которую вы должны запомнить. Она должна быть физикасистемы

Гранулирование OSS/CSS — это перевод данного принципа в область Управление LLM. LLM не нужно знать, что Edster конфиденциальный. Ему нужно быть неспособным его индексировать.

И это именно то, что`CSS/`гарантирует.

Похожие статьи