temporality
Изменить страницу↗
Инженерные документы

ТЗ: Policy-based Filesystem Access и изоляция параллельной разработки в Temporality

#1. Цель

Реализовать единую файловую систему проекта с централизованным управлением доступом на основании действующих политик Temporality.

Основные принципы:

  1. Все агенты работают с одной канонической структурой файлов и каталогов проекта.
  2. Файловые полномочия определяются пользователем, инициировавшим запуск, а не типом агента, его ролью или местом в дереве делегирования.
  3. Ограничения доступа задаются через существующую модель Org Policies и наследуются по существующим правилам EffectivePolicy.
  4. Ограничения должны обеспечиваться технически, а не только инструкциями в system prompt.
  5. Параллельная разработка должна поддерживать независимые изменения одного проекта, включая изменения пересекающихся участков кода.
  6. Координация параллельной работы не должна требовать от агентов самостоятельного изобретения структуры каталогов и соглашений о расположении файлов.

Не создавать отдельные файловые пространства для Org Units, команд, ролей и агентов.

#2. Термины и разделение ответственности

В системе должны быть чётко разделены три механизма.

Механизм Назначение
Filesystem Policy Определяет, что пользователь вправе читать и изменять
Workspace Единая каноническая файловая система проекта
Task Isolation Предотвращает конфликты параллельной разработки и управляет интеграцией изменений

Filesystem Policy отвечает за авторизацию. Task Isolation отвечает за координацию изменений. Ни один из этих механизмов не должен подменять другой.

#3. Модель файловых полномочий

#3.1. Субъект авторизации

Основной субъект авторизации — инициатор запуска (actor_id).

Для обычного пользовательского запуска полномочия определяются через:

Для автоматических запусков через webhook, scheduler и triggers использовать соответствующую Execution Identity и существующий механизм определения её полномочий.

При делегировании дочерний запуск наследует security context исходного инициатора.

Запрещено:

#3.2. Набор операций

Предусмотреть два уровня доступа:

Отдельное право delete не вводить. Удаление является операцией изменения состояния и входит в write.

#3.3. Структура правил

Расширить существующую сущность workspace.Policy.

Предлагаемая структура:

{
  "filesystem": {
    "read": [
      "**"
    ],
    "write": [
      "src/**",
      "tests/**",
      "docs/**"
    ],
    "deny": [
      "secrets/**",
      "deploy/production/**"
    ]
  }
}

Семантика:

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. Стабильность путей

Путь к файлу должен иметь одинаковое значение для всех участников работы.

Если агент создал или изменил файл, другой агент должен иметь возможность найти его по тому же пути в пределах своих полномочий.

Необходимо исключить ситуации, когда:

#4.3. Scratch

Существующий scratch можно сохранить для временных данных и технических артефактов конкретного запуска.

Scratch не должен становиться альтернативным постоянным хранилищем проектных файлов.

Пути и ссылки на scratch-артефакты должны быть доступны участникам соответствующей работы и сохранять однозначность.

#5. Enforcement файловых полномочий

#5.1. Общие требования

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

Запрещённая операция должна завершаться отказом независимо от того, каким инструментом агент пытается её выполнить.

Нельзя ограничиваться проверками встроенных read_file и write_file: агент может использовать run_command, Python, shell, git и другие программы.

#5.2. Kernel filesystem gateway

Встроенные файловые инструменты должны проверять эффективную файловую политику до выполнения операции.

Проверять:

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

Не допускать обхода через:

#5.3. Docker sandbox и Landlock

Рассмотреть Landlock как основной механизм ограничения файловых операций внутри Linux sandbox.

Цель — оставить единое дерево /workspace, но ограничить операции процесса на уровне ОС.

Требования:

  1. Landlock должен применяться к процессу sandbox до запуска пользовательской команды.
  2. Ограничения должны наследоваться дочерними процессами.
  3. Политика должна разрешать чтение и запись только в соответствующих областях.
  4. Запрещённые области должны оставаться физически доступными в общем дереве, но недоступными для запрещённых операций.
  5. Проверить совместимость с используемыми версиями Linux kernel и Docker.
  6. Если Landlock недоступен или не поддерживает необходимую семантику на целевой платформе, запуск должен завершаться безопасным отказом либо использовать явно определённый альтернативный механизм enforcement. Не допускать незаметного запуска без ограничений.

Исследовать следующие операции и особенности:

Отдельно определить права на технические каталоги, необходимые для работы 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. Изменение политик во время выполнения

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

Предпочтительный вариант:

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

#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 используются для:

Отсутствие 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

Если области пересекаются:

Не считать отсутствие совпадения строковых префиксов доказательством отсутствия конфликта. Учитывать 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. Интеграция

Результаты задач интегрируются в общий проект только после проверки.

Предусмотреть:

Если интеграция невозможна, задача возвращается на rework либо передаётся Lead для разрешения конфликта.

Не выполнять автоматическую перезапись изменений другой задачи.

#7.7. Общие файлы и неизбежные конфликты

Если несколько задач должны изменить один и тот же файл, система не должна пытаться скрыть этот факт созданием дополнительных каталогов.

Lead должен определить способ координации:

Последний вариант допустим, но не гарантирует бесконфликтную интеграцию.

Для не-Git проектов предусмотреть отдельный механизм изоляции изменений. Не имитировать Git worktree копированием файлов без контроля конфликтов и происхождения изменений.

#8. Журналирование и аудит

Фиксировать значимые операции:

Для больших файлов и частых операций не записывать содержимое в Journal. Достаточно метаданных, размеров, checksum и ссылки на артефакт, когда это необходимо.

Отдельно журналировать:

Сохранять причинные связи с событиями соответствующего run/task.

#9. Тестирование

#9.1. Filesystem Policy

Проверить:

#9.2. Идентичность

Проверить:

#9.3. Sandbox

Проверить обходы через:

Обязательно проверить, что запрет, работающий в read_file/write_file, также работает при выполнении эквивалентной операции из run_command.

#9.4. Параллельная разработка

Проверить сценарии:

  1. Две задачи изменяют независимые каталоги — параллельное выполнение и успешная интеграция.
  2. Две задачи изменяют один каталог, но разные файлы — параллельное выполнение.
  3. Две задачи изменяют один файл — обнаружение конфликта и контролируемая интеграция.
  4. Одна задача изменяет общий файл, другая зависит от результата — корректное выполнение через DAG.
  5. Одна задача завершилась ошибкой — остальные не теряют свои изменения.
  6. Lead не указал claims — система не выдаёт неограниченные полномочия и использует безопасную стратегию координации.

#10. Этапы реализации

#P0. Модель полномочий

#P1. Enforcement

#P2. Параллельная разработка

#P3. Расширение

#11. Критерии приёмки

  1. В проекте существует единая каноническая структура файлов.
  2. Агенты не создают отдельные постоянные копии файлов из-за различий в их организационной принадлежности или роли.
  3. Файловые полномочия определяются инициатором и действующими политиками.
  4. Делегирование не расширяет полномочия исходного пользователя.
  5. Ограничения невозможно обойти через run_command или альтернативные инструменты.
  6. Landlock либо эквивалентный механизм обеспечивает enforcement на уровне ОС.
  7. Отсутствие отдельного права delete не создаёт неоднозначности: удаление относится к write.
  8. Параллельные задачи могут работать в независимых worktree.
  9. Пересекающиеся изменения обнаруживаются и не приводят к молчаливой потере данных.
  10. Интеграция результатов проходит через проверяемый процесс с журналированием.
  11. Существующие проекты и запуски сохраняют совместимость с прежней моделью доступа.

#12. Архитектурное ограничение

Не реализовывать:

Итоговая модель: одна файловая система, один набор канонических путей, полномочия от инициатора через Org Policies, enforcement на уровне Kernel и ОС, отдельная координация параллельных изменений через claims и Git worktree.