ТЗ: Policy-based Filesystem Access и изоляция параллельной разработки в Temporality
#1. Цель
Реализовать единую файловую систему проекта с централизованным управлением доступом на основании действующих политик Temporality.
Основные принципы:
- Все агенты работают с одной канонической структурой файлов и каталогов проекта.
- Файловые полномочия определяются пользователем, инициировавшим запуск, а не типом агента, его ролью или местом в дереве делегирования.
- Ограничения доступа задаются через существующую модель Org Policies и наследуются по существующим правилам
EffectivePolicy. - Ограничения должны обеспечиваться технически, а не только инструкциями в system prompt.
- Параллельная разработка должна поддерживать независимые изменения одного проекта, включая изменения пересекающихся участков кода.
- Координация параллельной работы не должна требовать от агентов самостоятельного изобретения структуры каталогов и соглашений о расположении файлов.
Не создавать отдельные файловые пространства для Org Units, команд, ролей и агентов.
#2. Термины и разделение ответственности
В системе должны быть чётко разделены три механизма.
| Механизм | Назначение |
|---|---|
| Filesystem Policy | Определяет, что пользователь вправе читать и изменять |
| Workspace | Единая каноническая файловая система проекта |
| Task Isolation | Предотвращает конфликты параллельной разработки и управляет интеграцией изменений |
Filesystem Policy отвечает за авторизацию. Task Isolation отвечает за координацию изменений. Ни один из этих механизмов не должен подменять другой.
#3. Модель файловых полномочий
#3.1. Субъект авторизации
Основной субъект авторизации — инициатор запуска (actor_id).
Для обычного пользовательского запуска полномочия определяются через:
- организационную принадлежность пользователя;
- членство в проекте;
- связи проекта с Org Units;
- действующие глобальные и локальные Org Policies.
Для автоматических запусков через webhook, scheduler и triggers использовать соответствующую Execution Identity и существующий механизм определения её полномочий.
При делегировании дочерний запуск наследует security context исходного инициатора.
Запрещено:
- использовать Agent ID как субъект файловой авторизации;
- повышать полномочия при делегировании;
- пересчитывать полномочия от имени агента, которому делегирована задача;
- считать роль Lead, Coder, Reviewer или QA основанием для предоставления файловых полномочий.
#3.2. Набор операций
Предусмотреть два уровня доступа:
read— чтение файлов и получение информации о содержимом и структуре файловой системы;write— любое изменение файловой системы, включая создание, перезапись, изменение, обнуление, переименование и удаление файлов, создание и удаление каталогов.
Отдельное право delete не вводить. Удаление является операцией изменения состояния и входит в write.
#3.3. Структура правил
Расширить существующую сущность workspace.Policy.
Предлагаемая структура:
{
"filesystem": {
"read": [
"**"
],
"write": [
"src/**",
"tests/**",
"docs/**"
],
"deny": [
"secrets/**",
"deploy/production/**"
]
}
}
Семантика:
read— разрешённые области чтения;write— разрешённые области изменения;deny— абсолютные запреты на любые операции с указанными областями, включая чтение и запись.
deny имеет приоритет над всеми разрешениями и не может быть отменён дочерней политикой.
Пустое или неустановленное значение должно сохранять семантику существующей модели политик: отсутствие ограничения не должно случайно интерпретироваться как запрет всего.
Необходимо явно определить и протестировать семантику nil, пустого списка и wildcard.
#3.4. Наследование и объединение
Использовать существующий EffectivePolicy(unitIDs...) и его модель рестриктивного объединения.
Для файловых правил реализовать семантическое пересечение областей путей.
Пример:
Global:
write: **
Org Unit:
write: src/**
Project:
write: src/backend/**
Effective:
write: src/backend/**
Если на любом уровне присутствует запрет:
Org Unit:
deny: src/backend/generated/**
то область остаётся запрещённой независимо от разрешений нижестоящих политик.
Для файловых масок использовать нормализованные относительные пути с / в качестве разделителя.
Необходимо учитывать вложенность glob-масок. Простое пересечение строковых значений недостаточно.
#3.5. Значения по умолчанию
Сохранить совместимость с существующими проектами и политиками.
Отсутствие файловых правил в ранее созданной политике не должно автоматически лишать пользователя доступа к существующим файлам.
Глобальная политика установки должна иметь возможность ограничить файловые полномочия для всех пользователей.
#4. Единая файловая система
#4.1. Каноническое пространство
Сохранить одну файловую систему проекта (хост: KERNEL_SANDBOX_ROOT/projects/ <project-id>, внутри песочницы монтируется как /workspace — пути проекта
одинаковы для всех агентов и ранов):
/workspace/
src/
tests/
docs/
deploy/
artifacts/
...
Структура проекта определяется самим проектом и его инструментами разработки.
Не вводить обязательную структуру вида:
/workspace/org/<org-unit>/
/workspace/teams/<team-id>/
/workspace/agents/<agent-id>/
Не создавать копии одних и тех же файлов для разных агентов и подразделений.
Все агенты одного проекта используют единые канонические пути.
#4.2. Стабильность путей
Путь к файлу должен иметь одинаковое значение для всех участников работы.
Если агент создал или изменил файл, другой агент должен иметь возможность найти его по тому же пути в пределах своих полномочий.
Необходимо исключить ситуации, когда:
- агенты создают дублирующие копии одного артефакта;
- разные делегации используют собственные варианты расположения одного результата;
- передача задачи требует пересылки файлов между изолированными каталогами;
- Lead вынужден вручную объяснять, где искать результаты предыдущей работы.
#4.3. Scratch
Существующий scratch можно сохранить для временных данных и технических артефактов конкретного запуска.
Scratch не должен становиться альтернативным постоянным хранилищем проектных файлов.
Пути и ссылки на scratch-артефакты должны быть доступны участникам соответствующей работы и сохранять однозначность.
#5. Enforcement файловых полномочий
#5.1. Общие требования
Проверка доступа должна выполняться на уровне исполнения операции, а не на уровне текстовых инструкций модели.
Запрещённая операция должна завершаться отказом независимо от того, каким инструментом агент пытается её выполнить.
Нельзя ограничиваться проверками встроенных read_file и write_file: агент может использовать run_command, Python, shell, git и другие программы.
#5.2. Kernel filesystem gateway
Встроенные файловые инструменты должны проверять эффективную файловую политику до выполнения операции.
Проверять:
- чтение файлов;
- поиск и перечисление файлов;
- запись и перезапись;
- создание каталогов;
- переименование;
- удаление;
- операции с временными файлами.
Проверка должна выполняться на нормализованном пути относительно корня проекта.
Не допускать обхода через:
..;- абсолютные пути;
- символьные ссылки;
- альтернативные представления путей;
- ссылки за пределы workspace.
#5.3. Docker sandbox и Landlock
Рассмотреть Landlock как основной механизм ограничения файловых операций внутри Linux sandbox.
Цель — оставить единое дерево /workspace, но ограничить операции процесса на уровне ОС.
Требования:
- Landlock должен применяться к процессу sandbox до запуска пользовательской команды.
- Ограничения должны наследоваться дочерними процессами.
- Политика должна разрешать чтение и запись только в соответствующих областях.
- Запрещённые области должны оставаться физически доступными в общем дереве, но недоступными для запрещённых операций.
- Проверить совместимость с используемыми версиями Linux kernel и Docker.
- Если Landlock недоступен или не поддерживает необходимую семантику на целевой платформе, запуск должен завершаться безопасным отказом либо использовать явно определённый альтернативный механизм enforcement. Не допускать незаметного запуска без ограничений.
Исследовать следующие операции и особенности:
openс различными флагами доступа;truncate;rename;unlink;- создание и удаление каталогов;
- hard links;
- symlinks;
- временные файлы;
- atomic writes;
- git checkout, merge, rebase и другие операции, меняющие дерево;
- доступ к
/tmp,/scratchи другим writable mount points.
Отдельно определить права на технические каталоги, необходимые для работы sandbox и инструментов. Они не должны становиться способом обхода проектной политики.
#5.4. Общая политика для всех способов доступа
Kernel filesystem gateway и Landlock должны получать одну и ту же эффективную политику.
Не реализовывать независимые правила для shell и встроенных файловых инструментов.
Для каждого запуска политика должна быть разрешена один раз и передаваться через неизменяемый security context.
#6. Контекст полномочий запуска
#6.1. Security context
Ввести или расширить структуру контекста запуска, содержащую:
type FilesystemPolicy struct {
Read []string
Write []string
Deny []string
}
// Фактический wire-тип слоёный (kernel/sandbox/policy.go): Read/Write —
// слои AND поверх OR-масок (точное семантическое пересечение областей),
// Deny — объединение:
type EffectiveFilesystem struct {
Read [][]string
Write [][]string
Deny []string
}
type RunSecurityContext struct {
ActorID string
ExecutionIdentityID string
ProjectID string
Filesystem FilesystemPolicy
PolicyVersion string
}
Структура приведена концептуально. Использовать существующие типы и соглашения проекта, избегая дублирования данных.
#6.2. Делегирование
Дочерние запуски получают security context исходного запуска.
Все участники дерева делегирования используют одни и те же файловые полномочия инициатора.
Делегирование не может расширить доступ.
#6.3. Изменение политик во время выполнения
Определить предсказуемую семантику изменения политик.
Предпочтительный вариант:
- эффективная политика фиксируется при старте run;
- изменения политики не повышают полномочия уже запущенного процесса;
- критическое ужесточение политики должно позволять принудительно остановить или пересоздать sandbox;
- новые запуски используют актуальную политику.
В журнале должна сохраняться версия или идентификатор снимка политики, по которому был авторизован запуск.
#7. Изоляция параллельной разработки
#7.1. Назначение
Filesystem Policy не решает конфликты параллельной записи.
Для независимой разработки нескольких задач использовать Git worktree и механизм task claims.
При этом worktree — технический механизм изоляции изменений, а не отдельная файловая система для каждой роли или подразделения.
#7.2. Ответственность Lead
Lead отвечает за декомпозицию работы и определение зависимостей между задачами.
Когда задачи могут изменять пересекающиеся участки проекта, Lead должен определить границы работы или порядок выполнения.
Не требуется от Lead:
- создавать произвольные каталоги для каждой делегации;
- придумывать соглашения о расположении файлов;
- вручную копировать результаты между каталогами;
- объяснять каждому агенту альтернативные пути к одним и тем же файлам.
Требуется от Lead:
- определить ожидаемые области изменений;
- указать зависимости между задачами;
- обозначить задачи, которые могут конфликтовать;
- определить порядок интеграции, если параллельная работа небезопасна.
Система должна помогать выявлять конфликты и обеспечивать техническую изоляцию.
#7.3. Workspace claims
Расширить описание задач планировщика необязательными claims:
{
"workspace_claims": [
{
"path": "src/backend/",
"access": "write"
},
{
"path": "src/shared/",
"access": "read"
}
]
}
Claim описывает предполагаемую область работы задачи, а не полномочия пользователя.
Claims используются для:
- обнаружения пересекающихся областей записи;
- определения возможности параллельного исполнения;
- назначения worktree;
- выявления потенциальных конфликтов;
- сериализации задач, если изоляция невозможна или нежелательна.
Отсутствие claim не должно давать дополнительных файловых полномочий.
#7.4. Обнаружение конфликтов
При создании плана или запуске параллельной волны сравнивать write claims задач.
Пример:
Task A:
write src/backend/auth/
Task B:
write src/backend/payments/
Result:
Can execute in parallel
Task C:
write src/backend/
Result:
Conflicts with A and B
Если области пересекаются:
- система предупреждает Lead;
- предлагает уточнить границы задач или определить зависимости;
- при отсутствии безопасного решения сериализует исполнение.
Не считать отсутствие совпадения строковых префиксов доказательством отсутствия конфликта. Учитывать glob, вложенные пути и общие файлы.
#7.5. Git worktree
Для параллельных задач, изменяющих общий Git-проект, предусмотреть автоматическое создание отдельных worktree и веток.
Например:
Canonical project:
main
Task A:
branch agent/task-a
worktree .worktrees/task-a
Task B:
branch agent/task-b
worktree .worktrees/task-b
Все worktree принадлежат одному Git-репозиторию и используют единые канонические пути внутри соответствующей рабочей копии.
Важно: worktree не должен рассматриваться как security boundary. Filesystem Policy должна применяться к каждому worktree и не позволять обойти ограничения через доступ к основному checkout или соседним worktree.
#7.6. Интеграция
Результаты задач интегрируются в общий проект только после проверки.
Предусмотреть:
- проверку актуальности базового commit;
- проверку пересечения изменённых файлов;
- merge/rebase;
- автоматическое выявление конфликтов;
- запуск тестов;
- review/acceptance gate;
- фиксацию результата интеграции в Journal.
Если интеграция невозможна, задача возвращается на rework либо передаётся Lead для разрешения конфликта.
Не выполнять автоматическую перезапись изменений другой задачи.
#7.7. Общие файлы и неизбежные конфликты
Если несколько задач должны изменить один и тот же файл, система не должна пытаться скрыть этот факт созданием дополнительных каталогов.
Lead должен определить способ координации:
- одна задача владеет изменением файла, остальные предоставляют требования или патчи;
- задачи выполняются последовательно;
- изменения разрабатываются параллельно в отдельных worktree и интегрируются с обязательным разрешением конфликтов.
Последний вариант допустим, но не гарантирует бесконфликтную интеграцию.
Для не-Git проектов предусмотреть отдельный механизм изоляции изменений. Не имитировать Git worktree копированием файлов без контроля конфликтов и происхождения изменений.
#8. Журналирование и аудит
Фиксировать значимые операции:
- разрешённые изменения файлов;
- отказы по файловой политике;
- инициатора;
- project ID;
- run ID;
- task ID;
- путь;
- операцию;
- применённую версию политики;
- результат операции.
Для больших файлов и частых операций не записывать содержимое в Journal. Достаточно метаданных, размеров, checksum и ссылки на артефакт, когда это необходимо.
Отдельно журналировать:
- создание и освобождение workspace claims;
- создание и удаление worktree;
- конфликты claims;
- merge/rebase;
- конфликты интеграции;
- успешное и неуспешное принятие изменений.
Сохранять причинные связи с событиями соответствующего run/task.
#9. Тестирование
#9.1. Filesystem Policy
Проверить:
- разрешение чтения;
- запрет чтения;
- разрешение записи;
- запрет записи;
- создание и удаление файлов;
- переименование;
- glob-пересечения;
- наследование Org Policies;
- глобальные запреты;
- пересечение политик нескольких Org Units;
- отсутствие обхода через symlink и
...
#9.2. Идентичность
Проверить:
- пользовательский run;
- делегированный run;
- несколько уровней делегирования;
- запуск через Execution Identity;
- невозможность расширения полномочий при делегировании;
- невозможность подмены
actor_idиз пользовательских данных; - применение актуального снимка политики.
#9.3. Sandbox
Проверить обходы через:
- shell;
- Python;
sed;perl;git;- произвольные дочерние процессы;
- symlinks;
- hardlinks;
- rename;
- atomic write;
- временные каталоги.
Обязательно проверить, что запрет, работающий в read_file/write_file, также работает при выполнении эквивалентной операции из run_command.
#9.4. Параллельная разработка
Проверить сценарии:
- Две задачи изменяют независимые каталоги — параллельное выполнение и успешная интеграция.
- Две задачи изменяют один каталог, но разные файлы — параллельное выполнение.
- Две задачи изменяют один файл — обнаружение конфликта и контролируемая интеграция.
- Одна задача изменяет общий файл, другая зависит от результата — корректное выполнение через DAG.
- Одна задача завершилась ошибкой — остальные не теряют свои изменения.
- Lead не указал claims — система не выдаёт неограниченные полномочия и использует безопасную стратегию координации.
#10. Этапы реализации
#P0. Модель полномочий
- Расширить
workspace.Policy. - Добавить файловые правила read/write/deny.
- Реализовать семантическое объединение glob-областей.
- Расширить эффективный security context запуска.
- Обеспечить наследование контекста при делегировании.
- Добавить тесты идентичности и наследования.
#P1. Enforcement
- Встроить проверку политики в файловые инструменты Kernel.
- Исследовать и реализовать Landlock в Linux sandbox.
- Обеспечить одинаковую семантику для встроенных инструментов и shell.
- Добавить защиту от обхода через ссылки и альтернативные пути.
- Добавить аудит отказов.
#P2. Параллельная разработка
- Ввести workspace claims.
- Добавить обнаружение пересечений.
- Автоматизировать создание Git worktree и веток.
- Реализовать контролируемую интеграцию.
- Добавить conflict handling и журналирование.
#P3. Расширение
- Поддержать аналогичную модель для не-Git проектов.
- Добавить UI для редактирования файловых правил Org Policies.
- Добавить отображение эффективных файловых полномочий пользователя.
- Добавить диагностику конфликтов параллельных задач.
#11. Критерии приёмки
- В проекте существует единая каноническая структура файлов.
- Агенты не создают отдельные постоянные копии файлов из-за различий в их организационной принадлежности или роли.
- Файловые полномочия определяются инициатором и действующими политиками.
- Делегирование не расширяет полномочия исходного пользователя.
- Ограничения невозможно обойти через
run_commandили альтернативные инструменты. - Landlock либо эквивалентный механизм обеспечивает enforcement на уровне ОС.
- Отсутствие отдельного права
deleteне создаёт неоднозначности: удаление относится кwrite. - Параллельные задачи могут работать в независимых worktree.
- Пересекающиеся изменения обнаруживаются и не приводят к молчаливой потере данных.
- Интеграция результатов проходит через проверяемый процесс с журналированием.
- Существующие проекты и запуски сохраняют совместимость с прежней моделью доступа.
#12. Архитектурное ограничение
Не реализовывать:
- отдельные файловые пространства для агентов;
- каталоги, привязанные к Org Units как механизм ограничения доступа;
- индивидуальные ACL по Agent ID;
- файловые полномочия на основании ролей Lead/Coder/Reviewer/QA;
- отдельные копии проектных артефактов для передачи между делегациями;
- enforcement только на уровне system prompt;
- анализ shell-команд как единственный способ контроля файловых операций.
Итоговая модель: одна файловая система, один набор канонических путей, полномочия от инициатора через Org Policies, enforcement на уровне Kernel и ОС, отдельная координация параллельных изменений через claims и Git worktree.