Обмеження — одна політика для кожної дії, що змінює стан
Агенти в Control Center можуть видаляти файли, надсилати гілки, публікувати pull request і викликати зовнішні API. Кожна з цих дій — це інший різновид ризику, і довгий час політику мала лише одна з них — shell-команди. Обмеження існують, щоб однаково відповідати на одне запитання для кожної дії, що змінює стан, яку може виконати агент, незалежно від того, яке середовище виконання чи інструмент її пропонує: це дозволено, потребує затвердження чи заборонено?
Один рушій, кожна точка перехоплення
Розділ із назвою «Один рушій, кожна точка перехоплення»Є рівно один рушій політик. До нього звертаються в кожній точці, де дія може вийти за межі системи: реєстр інструментів вбудованого harness, шлюз диспетчера MCP на сервері та мутації операцій з репозиторіями. Тому правило, написане один раз, застосовується і до вбудованого середовища виконання, і до зовнішніх CLI агентів — немає другого, тихішого шляху в обхід. Старіша політика команд лише для bash досі працює: правило може збігатися з префіксом команди замість класу дій, і обидві форми співіснують в одному сховищі.
Утім, рушій не замінює пісочницю ОС, а пісочниця не замінює його. Вони
відповідають на різні запитання: обмеження вирішують, чи виклик, який Control
Center бачить, узагалі може відбутися, а пісочниця окреслює, куди може
дістатися породжений процес. cc_server застосовує пісочницю там, де хост
надає бекенд — але Windows не надає жодного, а Linux потребує bwrap і
socat. На таких хостах
обмеження — це найзовнішній рівень примусу, а не політика, що лежить поверх
базового рівня; це варто знати, коли ви вирішуєте, наскільки дозвільними
бути.
ActionClass: навмисно закрита таксономія
Розділ із назвою «ActionClass: навмисно закрита таксономія»Кожен інструмент, що змінює стан, оголошує, до яких ActionClasses він належить, із закритої множини з тринадцяти класів ефектів. П’ять із них за замовчуванням запитують підтвердження; решта дозволяє, і це змінює вже правило.
| Клас | Вбудований стандарт | Що він охоплює |
|---|---|---|
fileDelete |
prompt | Видалення файлу (запис у формі видалення, rm) |
gitPush |
prompt | Надсилання на віддалений git-репозиторій |
prCreate |
prompt | Створення pull request |
prPublish |
prompt | Публікація рецензії, злиття PR |
vendorSyncWrite |
prompt | Запис у зовнішній трекер тікетів (Linear, Jira, синхронізація з GitHub) |
fileWriteOutsideWorktree |
allow | Запис файлу поза ізольованим робочим деревом |
gitCommit |
allow | Створення git-коміту |
networkEgress |
allow | Вихід у мережу (веб-вибірка, довільний HTTP) |
secretAccess |
allow | Читання секрету чи облікових даних |
packageInstall |
allow | Установлення пакета (npm, pip, pub, brew) |
processSpawn |
allow | Запуск процесу (shell і все, що викликає shell) |
workspaceMutation |
allow | Зміна структури робочого простору (репозиторії, простори, агенти) |
enclosureControl |
allow | Керування ізольованим середовищем (rig): завантаження віртуальної машини, надсилання їй введення |
Вісім класів із дозволом за замовчуванням обрано з припущення, що під ними діє
базовий рівень пісочниці. Він діє там, де хост надає бекенд, і не діє у Windows
чи на Linux-машині без bwrap і socat — тож якщо ви хочете поставити
fileWriteOutsideWorktree чи packageInstall під шлюз там, це правило
доведеться написати.
Множина закрита навмисно. Новий інструмент, що змінює стан, який не оголошує жодного класу, не проходить тест храповика, тож таксономія може зростати лише через явне, обґрунтоване рішення — «розростання таксономії — це смерть цієї функції». Тринадцяти класів достатньо, щоб висловити політики, які люди справді пишуть (ніколи не надсилати без запиту, ніколи не видаляти поза робочим деревом, завжди дозволяти читання), і достатньо мало, щоб інтерфейс налаштувань лишався зрозумілим.
Правила та розв’язання областей
Розділ із назвою «Правила та розв’язання областей»Правило відображає (scope, ActionClass | command prefix) → allow | prompt | deny.
Області вкладаються від найконкретнішої до найширшої:
простір > агент > робочий простір > пресет режиму > вбудований стандарт
Розв’язання йде спершу за конкретністю: вирішує перша область із відповідним правилом, і на ній розв’язання зупиняється. Найсуворіше правило — лише розв’язувач нічиєї: між двома однаково конкретними правилами в межах однієї області та під час поєднання кількох класів, які оголошує одна дія. У межах області правило команди збігається з найдовшим префіксом команди. allow ніде не перемагає deny.
Два рішення мають тверді гарантії:
- Запити, закриті за замовчуванням (fail-closed).
promptбез під’єднаного затверджувача розв’язується як denied. Питання без відповіді ніколи не означає «так». - Найсуворіше поєднання. Дія, що охоплює кілька класів, поєднує їх найсуворіше; коли кілька класів запитують підтвердження, одне підтвердження перелічує їх усі.
Навмисно немає фіксатора на хід. Кожен виклик інструмента розв’язує політику заново, тож повторні запити для тієї самої дії обмежує лише власне «запам’ятати це рішення» оператора, а не щось прив’язане до ходу.
Правила на рівні аргументів
Розділ із назвою «Правила на рівні аргументів»Правило може обмежувати АРГУМЕНТИ дії, а не лише її дієслово. «Може
надсилати» і «може надсилати до feature/*» — це різні твердження, і лише
друге є контролем. Шлюз можливостей, який дозволяє саме лише дієслово, — це
форма, що стоїть за більшістю опублікованих інцидентів з агентами.
Обмеження може називати:
- шляхи — glob-шаблони (
repos/**,!**/.env) - refs — git-референси, із запереченням
!(['**', '!main']читається як «будь-яка гілка, крім main») - хости — мережеві призначення, з шаблонами піддоменів (
*.internal) - команди — префікси команд, що збігаються на межі слова
- стелі —
maxCount/maxCents, тож «видалити до 50 файлів» можна висловити
Три властивості випливають із того, що граматика лишається закритою й без циклів, і всі три — це і є сенс: кожне правило читається як речення, яке можна прочитати назад, кожна відмова може назвати обмеження, що збіглося, а всю політику можна перелічити — ви бачите, що агент може робити, перш ніж він запуститься.
Три правила, які мають значення:
- Обмежене правило конкретніше за необмежене в тій самій області, тож
«заборонити надсилання до
main» перемагає «дозволити надсилання», і нікому не треба думати про порядок. - Обмежувальне правило (deny / prompt) застосовується, коли запит торкається будь-якого названого ним значення; дозвільне (allow) застосовується лише коли запит цілком у ньому. Якби обидва читалися однаково, агент міг би відмити заборонений шлях, додавши поруч невинний.
- Правило, яке називає аспект, про який запит нічого не каже, не застосовується й не пропускається: воно ескалює до затвердження. Тихе пропускання зробило б кожне правило захищеної гілки безсилим проти інструмента, який не повідомляє свій ref; тиха відмова відхиляла б кожне надсилання, яке екстрактор не може описати. Без під’єднаного затверджувача наявне правило fail-closed перетворює цю ескалацію на відмову.
Що правило команди може й не може зловити
Розділ із назвою «Що правило команди може й не може зловити»Правило commandPrefix збігається на межі слова: git push охоплює
git push origin main, але не git pushx. Воно не нормалізує shell.
git push (два пробіли), cd sub && git push і GIT_DIR=… git push — це всі
різні рядки, і жоден із них не збігається з правилом про git push.
Це справжнє обмеження, і про нього сказано прямо, а не замасковано: правила
команд — це зручність для оператора, щоб формувати звичайну поведінку агента,
а не межа проти ворожого. Межі — це класи ефектів (які інструмент оголошує
й не може переписати по-іншому), запобіжна мережа команд режиму під сховищем
політик і пісочниця ОС під обома. Правило команди, що розв’язується як allow,
ніколи не послаблює жодну з них — мережа режиму запускається після, і її deny
остаточний.
Постійні затвердження
Розділ із назвою «Постійні затвердження»Відповідь на запит «запам’ятати це» записує справжнє правило політики: з
областю (простір / агент / робочий простір), обмежене аргументами
(затвердження надсилання до feature/login надає feature/**, а не main) і
самоскасоване за явним TTL. Сказати «так» на найближчі кілька годин — це
не те саме, що тихо переписати свою постійну політику, і правила, які воно
записує, потрапляють у те саме сховище з походженням remembered і терміном
дії, тож їх можна скасувати достроково.
Рівні примусу
Розділ із назвою «Рівні примусу»Кожне правило має один із них:
- advisory — дозволити, але зафіксувати, що правило збіглося. Це шлях упровадження: розгорніть суворе правило в режимі advisory, тиждень читайте журнал аудиту, щоб побачити, що воно заблокувало б, а потім підвищте його. Без цього рівня суворі політики ніколи не вмикають.
- soft — заборонити, з можливістю перевизначення для того, хто має відповідний дозвіл, із зафіксованим обґрунтуванням. Саме перевизначення — це подія в журналі аудиту.
- hard (типовий) — заборонити. Ніщо його не перевизначає.
Керований рівень
Розділ із назвою «Керований рівень»Оператор встановлення може закріпити політику, яку жоден адміністратор
робочого простору не може послабити. Керовані правила живуть на сервері й
зливаються найсуворіше з власним ланцюгом кожного робочого простору — вони
не є областю на його чолі, бо керований allow на чолі ланцюга дозволив би
встановленню перевизначити deny робочого простору, тобто протилежне до
призначення обмежувача. Тому кероване правило може лише посилювати.
Якщо вказати CC_SERVER_MANAGED_POLICY на JSON-файл, він цілком переважає
збережені правила — саме це дає оператору змогу закріпити позицію, яку не
перемкне жоден адмін-інтерфейс. Це відповідь на «чи можу я завадити своїм
розробникам вимикати елементи контролю безпеки?».
Регулятор автономності — це профіль, а не паралельна система
Розділ із назвою «Регулятор автономності — це профіль, а не паралельна система»Регулятор автономності для кожного простору — це іменований профіль поверх
того самого сховища політик, а не другий механізм. Його три налаштування
зберігаються й надсилаються як proposeOnly, actWithApproval і actFreely
(форми з дефісами — лише текст інтерфейсу, а autonomy.setForSpace відхиляє
будь-що інше). Невстановлений регулятор поводиться як actWithApproval.
Що кожне з них робить із розв’язаним рішенням:
proposeOnlyвідхиляє кожен інструмент під шлюзом напряму. Агент усе ще може міркувати й відповідати; він просто не може діяти, і його повідомлення каже чому.actWithApproval(і невстановлений стан) — це шлюз затвердження fail-closed, описаний вище.actFreelyзаздалегідь затверджує все, що не розв’язалося як твердеdeny.
Останнє варто сказати прямо, а не пом’якшувати: за actFreely рішення prompt
не ескалює до затверджувача — його дозволяють, і нікого не запитують.
Регулятор переживає лише явне правило deny. Тож actFreely — це свідоме
надання автономності, а не зручність, і правило fail-closed захищає саме той
випадок, де це важливо (actWithApproval, типовий).
Делегування між агентами охороняється в точці перехоплення delegate_task
усіма чотирма охоронцями: обмеженням глибини (типово 3), виявленням циклів,
стелею автономності (делегат ніколи не може діяти з більшою автономністю,
ніж той, хто делегує, — привілеї не можна відмити, передавши роботу вільнішому
агентові) і бюджетними рамками (делегування списує залишок бюджету того,
хто делегує, і не може створити більше). Кожен відмовляє гучно, а причина
охоронця повертається агентові дослівно.
Матриця чесності адаптерів
Розділ із назвою «Матриця чесності адаптерів»Не кожне середовище виконання дозволяє Control Center перехоплювати кожну дію. Зовнішні CLI агентів виконують частину інструментів нативно, всередині процесу, де жоден шлюз не може стояти. Замість вдавати інше, кожен адаптер несе матрицю чесності: для кожного адаптера — чи Control Center фільтрує поверхню інструментів, перехоплює виклики інструментів, спостерігає за контрактом завершення, бачить нативні інструменти раннера і чи покриті внутрішньопроцесні інструменти профілем пісочниці.
Два записи варто прочитати, перш ніж довіряти конфігурації. Вбудований harness
оголошує, що його внутрішньопроцесні файлові інструменти не поміщені в
пісочницю — поверхня інструментів і цей рушій політик є його єдиною межею
файлової системи. Claude Code оголошує, що його власні виклики інструментів
не можна перехопити, бо він запускається з --dangerously-skip-permissions;
Control Center бачить його виклики mcp__* і, через хук, його командні рядки Bash, а його власні інструменти читання, запису та редагування виконуються непомітно.
Екран налаштувань показує цю матрицю, бо єдина непрощенна вада для системи обмежень — заявляти про охоплення, якого немає.
Перевірка політики до того, як вона вкусить
Розділ із назвою «Перевірка політики до того, як вона вкусить»Обмеження живуть за адресою Налаштування → Робочий простір → Дозволи агента
(/workspaces/<id>/settings/workspace/permissions). На екрані є матриця
політик, де пишуть правила, шаблони політик, перевірка «Що якщо?», журнал
аудиту авторизації та матриця чесності адаптерів.
Перевірка приймає клас дії (або команду) та область і показує, яке правило вирішило й чому. Оскільки розв’язання чисте й детерміноване — та сама дія, та сама область, те саме рішення — відповідь перевірки і є відповіддю, яку отримає агент.
Пов’язані поняття
Розділ із назвою «Пов’язані поняття»- Пісочниця та безпека: що насправді обмежує запуск агента і як далеко сягає базовий рівень ОС під цим рушієм
- Спільна робота — ідентичність, членство та присутність: простори, суб’єкти та де живе регулятор автономності
- Налаштувати обмеження: написання й перевірка правил на практиці