Guardraile — jedna polityka dla każdej mutującej akcji
Agenty w Control Center mogą usuwać pliki, wypychać gałęzie, publikować pull requesty i wywoływać zewnętrzne API. Każda z tych akcji to inny rodzaj ryzyka, a przez długi czas politykę miała tylko jedna z nich — polecenia powłoki. Guardraile odpowiadają w jednolity sposób na jedno pytanie, dotyczące każdej mutującej akcji, jaką może podjąć agent, niezależnie od tego, który runtime lub które narzędzie ją proponuje: czy jest dozwolona, czy wymaga zatwierdzenia, albo czy jest odrzucona?
Jeden silnik, każdy punkt kontrolny
Dział zatytułowany „Jeden silnik, każdy punkt kontrolny”Silnik polityki jest dokładnie jeden. Odpytuje się go w każdym punkcie, w którym akcja może opuścić system: w rejestrze narzędzi wbudowanego harnessu, w bramie dyspozytora MCP po stronie serwera i przy mutacjach operacji na repozytoriach. Reguła zapisana raz obowiązuje więc zarówno wbudowany runtime, jak i zewnętrzne CLI agentów — nie ma drugiej, cichszej ścieżki wokół niej. Starsza polityka poleceń tylko dla basha nadal działa: reguła może dopasować prefiks polecenia zamiast klasy akcji, a obie postacie współistnieją w tym samym magazynie.
Silnik nie zastępuje jednak sandboxa systemu operacyjnego i sandbox nie
zastępuje jego. Odpowiadają na różne pytania: guardraile decydują, czy
wywołanie, które Control Center widzi, może w ogóle się wydarzyć, a sandbox
ogranicza, gdzie może dotrzeć powstały proces. cc_server stosuje sandbox
tam, gdzie host oferuje backend — ale Windows nie oferuje żadnego, a Linux
wymaga bwrap i socat. Na takich hostach
guardraile są najzewnętrzniejszą warstwą egzekwowania, a nie polityką
posadowioną na podłodze — warto o tym wiedzieć, decydując, jak liberalne ma
być ustawienie.
ActionClass: celowo zamknięta taksonomia
Dział zatytułowany „ActionClass: celowo zamknięta taksonomia”Każde mutujące narzędzie deklaruje, do których ActionClasses należy, ze zamkniętego zestawu trzynastu klas efektów. Pięć z nich domyślnie daje prompt; pozostałe dają allow, a zmienia to dopiero reguła.
| Klasa | Wbudowana wartość domyślna | Co obejmuje |
|---|---|---|
fileDelete |
prompt | Usuwanie pliku (zapis o kształcie usunięcia, rm) |
gitPush |
prompt | Wypychanie do zdalnego repozytorium git |
prCreate |
prompt | Tworzenie pull requesta |
prPublish |
prompt | Publikowanie recenzji, scalanie PR-a |
vendorSyncWrite |
prompt | Zapis do zewnętrznego systemu zgłoszeń (synchronizacja Linear, Jira, GitHub) |
fileWriteOutsideWorktree |
allow | Zapis pliku poza izolowanym worktree |
gitCommit |
allow | Tworzenie commita git |
networkEgress |
allow | Ruch wychodzący do sieci (pobieranie z sieci, dowolne HTTP) |
secretAccess |
allow | Odczyt sekretu lub danych uwierzytelniających |
packageInstall |
allow | Instalowanie pakietu (npm, pip, pub, brew) |
processSpawn |
allow | Uruchamianie procesu (powłoka i wszystko, co ją wywołuje) |
workspaceMutation |
allow | Zmiana struktury obszaru roboczego (repozytoria, przestrzenie, agenty) |
enclosureControl |
allow | Sterowanie rigiem: uruchamianie VM, przesyłanie do niego danych wejściowych |
Osiem klas z domyślnym allow wybrano przy założeniu, że pod nimi działa
podłoga sandboxa. Działa tam, gdzie host oferuje backend, a nie działa na
Windowsie ani na Linuksie bez bwrap i socat — jeśli więc chcesz mieć tam
kontrolowane fileWriteOutsideWorktree albo packageInstall, tę regułę
musisz napisać sam.
Zestaw jest zamknięty celowo. Nowe mutujące narzędzie, które nie deklaruje żadnej klasy, nie przechodzi testu zapadki, więc taksonomia może rosnąć tylko na podstawie wyraźnej, uzasadnionej decyzji — „rozrost taksonomii to śmierć tej funkcji”. Trzynaście klas wystarcza, by wyrazić polityki, które ludzie naprawdę piszą (nigdy nie wypychaj bez pytania, nigdy nie usuwaj poza worktree, odczyty zawsze dozwolone), a jest ich dość mało, by interfejs ustawień pozostał zrozumiały.
Reguły i rozstrzyganie zakresów
Dział zatytułowany „Reguły i rozstrzyganie zakresów”Reguła mapuje (scope, ActionClass | command prefix) → allow | prompt | deny.
Zakresy zagnieżdżają się od najbardziej do najmniej szczegółowego:
przestrzeń > agent > obszar roboczy > preset trybu > wbudowana wartość domyślna
Rozstrzyganie idzie najpierw według szczegółowości: pierwszy zakres z pasującą regułą decyduje i na nim rozstrzyganie się kończy. Najbardziej restrykcyjny wariant służy tylko jako rozstrzygnięcie remisu — między dwiema równie szczegółowymi regułami w jednym zakresie i przy łączeniu kilku klas, które deklaruje jedna akcja. W obrębie zakresu reguła polecenia dopasowuje się po najdłuższym prefiksie polecenia. Allow nigdzie nie wygrywa z deny.
Dwie decyzje niosą twarde gwarancje:
- Domyślne odrzucanie zapytań.
promptbez podłączonego zatwierdzającego rozstrzyga się jako odmowa. Brak odpowiedzi nigdy nie jest zgodą. - Najbardziej restrykcyjne łączenie. Akcja obejmująca kilka klas łączy je najbardziej restrykcyjnie; gdy o zgodę pyta kilka klas, jedno potwierdzenie wymienia je wszystkie.
Celowo nie ma tu zapadki na jedną turę. Każde wywołanie narzędzia rozstrzyga politykę od zera, więc powtarzanie pytania o tę samą akcję ogranicza wyłącznie własna decyzja operatora „zapamiętaj ten wybór”, a nie cokolwiek związanego z turą.
Reguły na poziomie argumentów
Dział zatytułowany „Reguły na poziomie argumentów”Reguła może ograniczać ARGUMENTY akcji, nie tylko sam jej czasownik. „Może
wypychać” i „może wypychać do feature/*” to różne twierdzenia i tylko drugie
jest kontrolą — bramka możliwości, która autoryzuje sam czasownik, to kształt
stojący za większością opisanych incydentów z agentami.
Ograniczenie może wskazywać:
- ścieżki — wzorce glob (
repos/**,!**/.env) - refy — refy git, z negacją
!(['**', '!main']czyta się jako „dowolna gałąź oprócz main”) - hosty — cele sieciowe, z symbolami wieloznacznymi subdomen
(
*.internal) - polecenia — prefiksy poleceń, dopasowywane na granicy słowa
- pułapy —
maxCount/maxCents, dzięki czemu „usuń maksymalnie 50 plików” da się wyrazić
Z utrzymania gramatyki zamkniętej i bez pętli wynikają trzy właściwości i wszystkie trzy są tu istotą: każda reguła daje się zapisać jako zdanie, które można odczytać, każde odrzucenie umie wskazać pasujące ograniczenie, a całą politykę można wyliczyć — widzisz, co agent może zrobić, zanim ruszy.
Trzy reguły, które mają znaczenie:
- Ograniczona reguła jest bardziej szczegółowa niż nieograniczona w tym
samym zakresie, więc „odmów wypychania do
main” wygrywa z „zezwól na wypychanie”, bez zastanawiania się nad kolejnością. - Reguła restrykcyjna (deny / prompt) działa, gdy żądanie dotyka którejkolwiek wskazanej wartości; permisywna (allow) działa tylko wtedy, gdy żądanie mieści się w całości w niej. Czytanie obu tak samo pozwoliłoby agentowi wyprać zakazaną ścieżkę, dorzucając obok niej niewinną.
- Reguła wskazująca aspekt, o którym żądanie nic nie mówi, nie jest ani stosowana, ani pomijana: eskaluje do zatwierdzenia. Ciche pominięcie uczyniłoby każdą regułę chronionej gałęzi bezużyteczną wobec narzędzia, które nie raportuje swojego refu; ciche odrzucenie odmawiałoby każdego wypchnięcia, którego ekstraktor nie umie opisać. Bez podłączonego zatwierdzającego istniejąca reguła domyślnego odrzucania zamienia tę eskalację w odmowę.
Co reguła polecenia wychwyci, a czego nie
Dział zatytułowany „Co reguła polecenia wychwyci, a czego nie”Reguła commandPrefix dopasowuje na granicy słowa: git push obejmuje
git push origin main, a nie git pushx. Nie normalizuje powłoki.
git push (dwie spacje), cd sub && git push i
GIT_DIR=… git push to różne łańcuchy i żaden z nich nie pasuje do reguły
o git push.
To realne ograniczenie i mówimy o nim wprost, zamiast je zakamuflować: reguły
poleceń to udogodnienie dla operatora do kształtowania zwykłego zachowania
agenta, a nie granica przeciwko agentowi wrogiego. Granicami są klasy
efektów (które narzędzie deklaruje i nie może zapisać inaczej), siatka poleceń
trybu pod magazynem polityki oraz sandbox systemu operacyjnego pod obiema.
Reguła polecenia rozstrzygająca się jako allow nigdy nie poluzowuje żadnej
z nich — siatka trybu działa później, a jej deny jest ostateczne.
Trwałe zatwierdzenia
Dział zatytułowany „Trwałe zatwierdzenia”Odpowiedź na zapytanie przez „zapamiętaj to” zapisuje prawdziwą regułę
polityki: z zakresem (przestrzeń / agent / obszar roboczy), ograniczoną do
argumentów (zatwierdzenie wypchnięcia do feature/login przyznaje
feature/**, a nie main) i samoodwołującą się po upływie wyraźnego TTL.
Zgoda na najbliższe kilka godzin to nie to samo, co ciche przepisanie trwałej
polityki; zapisane reguły trafiają do tego samego magazynu z pochodzeniem
remembered i terminem wygaśnięcia, więc można je odwołać wcześniej.
Poziomy egzekwowania
Dział zatytułowany „Poziomy egzekwowania”Każda reguła ma jeden:
- advisory — zezwól, ale zapisz, że reguła zadziałała. To ścieżka wdrożenia: wdrażasz rygorystyczną regułę w trybie advisory, przez tydzień czytasz dziennik audytu i widzisz dokładnie, co byłaby zablokowała, a potem ją awansujesz. Bez tego poziomu rygorystyczne polityki nigdy się nie włączają.
- soft — odmów, z możliwością nadpisania przez osobę mającą uprawnienie do nadpisania, z zapisanym uzasadnieniem. Samo nadpisanie jest zdarzeniem objętym audytem.
- hard (domyślny) — odmów. Nic tego nie nadpisuje.
Warstwa zarządzana
Dział zatytułowany „Warstwa zarządzana”Operator instalacji może przypiąć politykę, której żaden administrator obszaru
roboczego nie poluzuje. Reguły zarządzane żyją po stronie serwera i są łączone
najbardziej restrykcyjnie z własnym łańcuchem każdego obszaru roboczego —
nie są zakresem na jego czele, bo zarządzane allow na czele łańcucha
pozwoliłoby instalacji nadpisać odmowę obszaru roboczego, czyli odwrotnie, niż
ma działać klamra. Reguła zarządzana może więc wyłącznie zaostrzać.
Ustawienie CC_SERVER_MANAGED_POLICY na plik JSON ma całkowite pierwszeństwo
przed zapisanymi regułami, dzięki czemu operator przypina postawę, której
żaden interfejs administracyjny nie przełączy — odpowiedź na pytanie „czy mogę
powstrzymać moich programistów przed wyłączaniem kontroli bezpieczeństwa?”.
Suwak autonomii to profil, a nie równoległy system
Dział zatytułowany „Suwak autonomii to profil, a nie równoległy system”Suwak autonomii dla przestrzeni to nazwany profil nad tym samym magazynem
polityki, a nie drugi mechanizm. Jego trzy ustawienia są zapisywane i wysyłane
jako proposeOnly, actWithApproval i actFreely (w interfejsie to tylko
teksty „Tylko propozycje”, „Działa po zatwierdzeniu” i „Działa swobodnie”, a
autonomy.setForSpace odrzuca wszystko inne). Stan nieustawiony zachowuje się
jak actWithApproval.
Co każde z nich robi z rozstrzygniętą decyzją:
proposeOnlyodrzuca z góry każde narzędzie objęte bramką. Agent nadal może rozumować i odpowiadać; po prostu nie może działać, a jego komunikat mówi dlaczego.actWithApproval(i stan nieustawiony) to opisana wyżej brama zatwierdzeń z domyślnym odrzucaniem.actFreelyzatwierdza z góry wszystko, co nie rozstrzygnęło się jako twardedeny.
To ostatnie zasługuje na powiedzenie wprost, bez łagodzenia: w trybie
actFreely decyzja prompt nie jest eskalowana do zatwierdzającego —
zostaje dozwolona i nikt nie jest pytany. Suwak przepuszcza tylko wyraźną
regułę deny. actFreely to więc świadome przyznanie autonomii, a nie
ustawienie dla wygody, a reguła domyślnego odrzucania chroni dokładnie ten
przypadek, w którym ma to znaczenie (actWithApproval, domyślny).
Delegowanie między agentami jest chronione w punkcie kontrolnym
delegate_task przez wszystkie cztery zabezpieczenia: limit głębokości
(domyślnie 3), wykrywanie cykli, pułap autonomii (delegat nigdy nie
działa z większą autonomią niż jego delegujący — uprawnień nie da się wyprać,
przekazując pracę swobodniejszemu agentowi) i koperta budżetowa
(delegowanie obciąża pozostały budżet delegującego i nie może wykreować
kolejnego). Każde odmawia głośno, a powód zabezpieczenia wraca do agenta
dosłownie.
Matryca uczciwości adapterów
Dział zatytułowany „Matryca uczciwości adapterów”Nie każdy runtime pozwala Control Center przechwycić każdą akcję. Zewnętrzne CLI agentów uruchamiają część narzędzi natywnie, w swoim procesie, gdzie żadna bramka nie może stanąć. Zamiast udawać inaczej, każdy adapter niesie matrycę uczciwości: dla każdego adaptera mówi, czy Control Center filtruje powierzchnię narzędzi, przechwytuje wywołania narzędzi, obserwuje kontrakt zakończenia, widzi natywne narzędzia runnera i czy narzędzia działające w procesie obejmuje profil sandboxa.
Dwa wpisy warto przeczytać, zanim zaufasz konfiguracji. Wbudowany harness
deklaruje, że jego narzędzia plikowe działające w procesie nie są w
sandboxie — powierzchnia narzędzi i ten silnik polityki to jedyna granica
systemu plików, jaką ma. Claude Code deklaruje, że jego własne wywołania
narzędzi nie dają się przechwycić, bo uruchamia się z
--dangerously-skip-permissions; Control Center widzi jego wywołania mcp__* oraz, przez hook, jego wiersze poleceń Bash, a jego własne narzędzia odczytu, zapisu i edycji działają niezauważone.
Ekran ustawień pokazuje tę matrycę, bo jedyna niewybaczalna porażka systemu guardrailów to twierdzenie o pokryciu, które nie istnieje.
Sprawdź politykę, zanim ugryzie
Dział zatytułowany „Sprawdź politykę, zanim ugryzie”Guardraile znajdują się w Ustawienia → Obszar roboczy → Uprawnienia
agentów (/workspaces/<id>/settings/workspace/permissions). Na ekranie jest
matryca polityki, w której zapisuje się reguły, szablony polityki, sonda „A co
jeśli?”, dziennik audytu autoryzacji i matryca uczciwości adapterów.
Sonda przyjmuje klasę akcji (albo polecenie) i zakres, a następnie pokazuje, która reguła zdecydowała i dlaczego. Rozstrzyganie jest czyste i deterministyczne — ta sama akcja i ten sam zakres dają tę samą decyzję — więc odpowiedź sondy to odpowiedź, którą dostanie agent.
Powiązane koncepcje
Dział zatytułowany „Powiązane koncepcje”- Sandbox i bezpieczeństwo: co tak naprawdę ogranicza uruchomienie agenta i jak daleko sięga podłoga systemu operacyjnego pod tym silnikiem
- Wieloosobowość — tożsamość, członkostwo i obecność: przestrzenie, podmioty i gdzie mieszka suwak autonomii
- Skonfiguruj guardraile: jak w praktyce pisać reguły i je testować