Guardrail-uri — o politică pentru fiecare acțiune care modifică starea
Agenții din Control Center pot șterge fișiere, pot face push pe ramuri, pot publica pull request-uri și pot apela API-uri externe. Fiecare dintre acestea este un alt tip de risc, iar multă vreme doar unul dintre ele — comenzile shell — avea o politică. Guardrail-urile există ca să răspundă uniform la o singură întrebare, pentru fiecare acțiune care modifică starea pe care o poate face un agent, indiferent de runtime-ul sau instrumentul care o propune: este permisă, are nevoie de o aprobare sau este refuzată?
Un motor, fiecare punct de control
Secțiune intitulată „Un motor, fiecare punct de control”Există exact un motor de politică. El este consultat în fiecare punct în care o acțiune poate ieși din sistem: registrul de instrumente al harness-ului încorporat, poarta dispecerului MCP de pe server și mutațiile operațiunilor pe repo. O regulă scrisă o dată se aplică deci atât runtime-ului încorporat, cât și CLI-urilor de agent externe — nu există o a doua cale, mai tăcută, pe lângă ea. Politica mai veche, doar pentru comenzi bash, încă funcționează: o regulă poate potrivi un prefix de comandă în loc de o clasă de acțiune, iar cele două forme coexistă în același depozit.
Motorul nu este însă un substitut pentru sandbox-ul sistemului de operare, iar
sandbox-ul nu este un substitut pentru el. Ele răspund la întrebări diferite:
guardrail-urile decid dacă un apel pe care Control Center îl poate vedea are
voie să se întâmple, în timp ce sandbox-ul limitează unde poate ajunge procesul
rezultat. cc_server aplică sandbox-ul acolo unde gazda oferă un backend — dar
Windows nu oferă niciunul, iar Linux are nevoie de bwrap și socat. Pe acele gazde,
guardrail-urile sunt stratul de aplicare cel mai exterior, nu o politică
așezată deasupra unui prag, ceea ce merită știut când decizi cât de permisiv
să fii.
ActionClass: o taxonomie închisă în mod deliberat
Secțiune intitulată „ActionClass: o taxonomie închisă în mod deliberat”Fiecare instrument care modifică starea declară căror ActionClasses aparține, dintr-un set închis de treisprezece clase de efect. Cinci dintre ele întreabă întâi din start; restul permit, iar o regulă este ce schimbă asta.
| Clasă | Implicit încorporat | Ce acoperă |
|---|---|---|
fileDelete |
întreabă întâi | Ștergerea unui fișier (o scriere de tip ștergere, rm) |
gitPush |
întreabă întâi | Push către un remote git |
prCreate |
întreabă întâi | Crearea unui pull request |
prPublish |
întreabă întâi | Publicarea unei revizuiri, îmbinarea unui PR |
vendorSyncWrite |
întreabă întâi | Scrierea către un furnizor extern de tichete (Linear, Jira, sincronizare GitHub) |
fileWriteOutsideWorktree |
permite | Scrierea unui fișier în afara worktree-ului izolat |
gitCommit |
permite | Crearea unui commit git |
networkEgress |
permite | Ieșire în rețea (preluare web, HTTP arbitrar) |
secretAccess |
permite | Citirea unui secret sau a unei acreditări |
packageInstall |
permite | Instalarea unui pachet (npm, pip, pub, brew) |
processSpawn |
permite | Pornirea unui proces (shell și orice apelează shell-ul) |
workspaceMutation |
permite | Modificarea structurii spațiului de lucru (repo-uri, spații, agenți) |
enclosureControl |
permite | Conducerea unui mediu izolat (stație): pornirea unei VM, trimiterea de input către ea |
Cele opt clase permise implicit au fost alese pornind de la premisa că pragul
sandbox-ului se aplică sub ele. Se aplică acolo unde gazda oferă un backend și
nu se aplică pe Windows sau pe o mașină Linux căreia îi lipsesc bwrap și
socat — așa că, dacă vrei ca fileWriteOutsideWorktree sau packageInstall
să fie controlate acolo, este o regulă pe care trebuie să o scrii.
Setul este închis în mod deliberat. Un instrument nou care modifică starea și nu declară nicio clasă pică testul cu clichet, așa că taxonomia poate crește doar printr-o decizie explicită și argumentată — „inflația taxonomiei este moartea acestei funcții”. Treisprezece clase sunt destule ca să exprime politicile pe care oamenii chiar le scriu (niciodată push fără să întrebi, niciodată ștergere în afara unui worktree, permite mereu citirile) și destul de puține ca interfața de setări să rămână comprehensibilă.
Reguli și rezolvarea domeniilor de aplicare
Secțiune intitulată „Reguli și rezolvarea domeniilor de aplicare”O regulă mapează (scope, ActionClass | command prefix) → allow | prompt | deny.
Domeniile se imbrică de la cel mai specific la cel mai puțin specific:
spațiu > agent > spațiu de lucru > presetare de mod > implicit încorporat
Rezolvarea este întâi după specificitate: primul domeniu cu o regulă potrivită decide, iar rezolvarea se oprește acolo. Cea mai restrictivă este doar o departajare — între două reguli la fel de specifice din același domeniu și la combinarea mai multor clase pe care le declară o singură acțiune. În interiorul unui domeniu, o regulă de comandă se potrivește pe cel mai lung prefix de comandă. Permiterea nu învinge refuzul nicăieri.
Două decizii au garanții stricte:
- Întrebări închise la eșec. Un
promptfără niciun aprobator conectat se rezolvă în refuz. O întrebare fără răspuns nu este niciodată un da. - Combinare cât mai restrictivă. O acțiune care acoperă mai multe clase le combină cât mai restrictiv; când mai multe clase întreabă, o singură confirmare le enumeră pe toate.
Nu există în mod deliberat nicio zăvorâre pe durata unei ture. Fiecare apel de instrument re-rezolvă politica de la zero, așa că întrebarea repetată pentru aceeași acțiune este limitată de „reține această decizie” al operatorului, nu de ceva legat de tură.
Reguli la nivel de argumente
Secțiune intitulată „Reguli la nivel de argumente”O regulă poate constrânge ARGUMENTELE unei acțiuni, nu doar verbul ei. „Poate
face push” și „poate face push către feature/*” sunt afirmații diferite, iar
doar a doua este un control — o poartă de capabilitate care autorizează doar
verbul este forma din spatele majorității incidentelor publicate cu agenți.
O constrângere poate numi:
- căi — șabloane glob (
repos/**,!**/.env) - referințe — referințe git, cu negație
!(['**', '!main']se citește ca „orice ramură în afară de main”) - gazde — destinații de rețea, cu wildcard-uri de subdomeniu (
*.internal) - comenzi — prefixe de comandă, potrivite pe o limită de cuvânt
- plafoane —
maxCount/maxCents, așa încât „șterge până la 50 de fișiere” devine exprimabil
Trei proprietăți decurg din păstrarea gramaticii închise și fără bucle, și toate trei sunt scopul: fiecare regulă se redă ca o propoziție pe care o poți citi înapoi, fiecare refuz poate numi constrângerea care s-a potrivit, iar întreaga politică poate fi enumerată — poți vedea ce poate face un agent înainte ca el să ruleze.
Trei reguli care contează:
- O regulă cu constrângeri este mai specifică decât una fără constrângeri
în același domeniu, așa că „refuză push către
main” învinge „permite push” fără ca cineva să se gândească la ordonare. - O regulă restrictivă (refuză / întreabă) se aplică atunci când cererea atinge oricare valoare pe care o numește; una permisivă (permite) se aplică doar atunci când cererea este în întregime în interiorul ei. Citirea ambelor la fel ar lăsa un agent să spele o cale interzisă punând una inofensivă alături.
- O regulă care numește o fațetă despre care cererea nu spune nimic nici nu se aplică, nici nu se sare peste ea: ea escaladează la o aprobare. Săritul în silențiu ar face fiecare regulă de ramură protejată inertă în fața unui instrument care nu își raportează referința; refuzul în silențiu ar refuza fiecare push pe care extractorul nu îl poate descrie. Fără un aprobator conectat, regula de închidere la eșec existentă transformă acea escaladare într-un refuz.
Ce poate și ce nu poate prinde o regulă de comandă
Secțiune intitulată „Ce poate și ce nu poate prinde o regulă de comandă”O regulă commandPrefix se potrivește pe o limită de cuvânt: git push
acoperă git push origin main, dar nu git pushx. Ea nu normalizează
shell-ul. git push (două spații), cd sub && git push și
GIT_DIR=… git push sunt șiruri diferite și niciunul nu se potrivește cu o
regulă despre git push.
Aceasta este o limită reală și este declarată, nu mascată: regulile de comandă
sunt o comoditate pentru operator, ca să modeleze comportamentul obișnuit al
agenților, nu o graniță împotriva unui comportament advers. Granițele sunt
clasele de efect (pe care un instrument le declară și nu le poate rescrie),
plasa de comenzi a modului de sub depozitul de politici și sandbox-ul
sistemului de operare de sub ambele. O regulă de comandă care se rezolvă în
allow nu slăbește niciuna dintre ele — plasa modului rulează după aceea, iar
deny-ul ei este final.
Aprobări permanente
Secțiune intitulată „Aprobări permanente”Răspunsul la o întrebare cu „reține asta” scrie o regulă de politică reală: cu
domeniu (spațiu / agent / spațiu de lucru), cu constrângeri pe argumente
(aprobarea unui push către feature/login acordă feature/**, nu main) și
auto-revocabilă după un TTL explicit. A spune da pentru următoarele câteva
ore nu este același lucru cu a-ți rescrie în tăcere politica permanentă, iar
regulile pe care le scrie ajung în același depozit cu proveniența remembered
și o expirare, așa că pot fi revocate mai devreme.
Niveluri de aplicare
Secțiune intitulată „Niveluri de aplicare”Fiecare regulă poartă unul:
- consultativ — permite, dar înregistrează că regula s-a potrivit. Aceasta este calea de adoptare: lansează o regulă strictă în mod consultativ, citește urma de audit o săptămână ca să vezi exact ce ar fi blocat, apoi promoveaz-o. Fără acest nivel, politicile stricte nu sunt niciodată activate.
- flexibil — refuză, cu posibilitate de suprascriere de către cineva care deține permisiunea de suprascriere, cu o justificare înregistrată. Suprascrierea este ea însăși un eveniment auditat.
- strict (implicit) — refuză. Nimic nu îl suprascrie.
Nivelul administrat
Secțiune intitulată „Nivelul administrat”Un operator de instalare poate fixa politici pe care niciun administrator de
spațiu de lucru nu le poate slăbi. Regulile administrative trăiesc pe server și
sunt îmbinate cât mai restrictiv cu lanțul propriu al fiecărui spațiu de
lucru — ele nu sunt un domeniu în fruntea lui, pentru că o regulă
administrativă de tip allow aflată în fruntea lanțului ar lăsa instalarea să
încalce refuzul unui spațiu de lucru, opusul scopului unui limitator. O regulă
administrativă nu poate deci decât să strângă.
Setarea CC_SERVER_MANAGED_POLICY către un fișier JSON are prioritate absolută
în fața regulilor stocate, ceea ce permite unui operator să fixeze o postură pe
care nicio interfață de administrare nu o poate răsturna — răspunsul la „pot
să-mi opresc dezvoltatorii să dezactiveze controalele de siguranță?“.
Cadranul de autonomie este un profil, nu un sistem paralel
Secțiune intitulată „Cadranul de autonomie este un profil, nu un sistem paralel”Cadranul de autonomie pe spațiu este un profil numit peste același depozit de
politici, nu un al doilea mecanism. Cele trei setări ale sale sunt stocate și
trimise ca proposeOnly, actWithApproval și actFreely (formele cu cratime
sunt doar text de interfață, iar autonomy.setForSpace respinge orice
altceva). Dacă îl lași nesetat, se comportă ca actWithApproval.
Ce face fiecare unei decizii rezolvate:
proposeOnlyrefuză direct fiecare instrument controlat. Agentul poate încă să raționeze și să răspundă; pur și simplu nu poate acționa, iar mesajul lui spune de ce.actWithApproval(și nesetat) este poarta de aprobare cu închidere la eșec descrisă mai sus.actFreelypre-aprobă orice nu s-a rezolvat într-undenystrict.
Ultimul merită spus pe față, nu înmuiat: sub actFreely, o decizie prompt
nu este escaladată către un aprobator — este permisă și nu este întrebat
nimeni. Doar o regulă deny explicită supraviețuiește cadranului. Așadar
actFreely este o acordare deliberată de autonomie, nu o setare de confort,
iar regula de închidere la eșec protejează exact cazul în care contează
(actWithApproval, implicitul).
Delegarea între agenți este păzită la punctul de control delegate_task de
toate cele patru garduri: un plafon de adâncime (implicit 3), detectarea
ciclurilor, un plafon de autonomie (un delegat nu poate acționa niciodată
cu mai multă autonomie decât delegantul lui — privilegiul nu poate fi spălat
prin înmânarea muncii către un agent mai liber) și o anvelopă bugetară
(delegarea facturează bugetul rămas al delegantului și nu poate crea mai mult).
Fiecare este refuzat cu zgomot, cu motivul gardului returnat agentului textual.
Matricea de onestitate a adaptoarelor
Secțiune intitulată „Matricea de onestitate a adaptoarelor”Nu orice runtime îi permite Control Center să intercepteze fiecare acțiune. CLI-urile de agent externe rulează unele instrumente nativ, în proces, unde nicio poartă nu poate sta. În loc să pretindă altfel, fiecare adaptor poartă o matrice de onestitate: pe adaptor, dacă Control Center filtrează suprafața de instrumente, interceptează apelurile de instrumente, observă contractul de finalizare, poate vedea instrumentele native ale runner-ului și dacă instrumentele din proces sunt acoperite de un profil de sandbox.
Două intrări merită citite înainte să ai încredere într-o configurație.
Harness-ul încorporat declară că instrumentele lui de fișiere din proces nu
sunt în sandbox — suprafața de instrumente și acest motor de politică sunt
singura graniță de sistem de fișiere pe care o are. Claude Code declară că
propriile apeluri de instrumente nu sunt interceptabile, pentru că este
lansat cu --dangerously-skip-permissions; Control Center vede apelurile lui mcp__* și, printr-un hook, liniile lui de comandă Bash, în timp ce instrumentele lui de citire, scriere și editare rulează nevăzute.
Ecranul de setări arată această matrice, pentru că singurul eșec de neiertat pentru un sistem de guardrail-uri este să pretindă o acoperire care nu există.
Sondarea politicii înainte să muște
Secțiune intitulată „Sondarea politicii înainte să muște”Guardrail-urile se află la Setări → Spațiu de lucru → Permisiuni agent
(/workspaces/<id>/settings/workspace/permissions). Ecranul are matricea de
politici unde se scriu regulile, șabloane de politică, o sondă de tip „ce-ar fi
dacă”, urma de audit a autorizării și matricea de onestitate a adaptoarelor.
Sonda primește o clasă de acțiune (sau o comandă) și un domeniu și arată ce regulă a decis și de ce. Pentru că rezolvarea este pură și deterministă — aceeași acțiune, același domeniu, aceeași decizie — răspunsul sondei este răspunsul pe care îl va primi agentul.
Concepte conexe
Secțiune intitulată „Concepte conexe”- Sandbox și securitate: ce constrânge de fapt o rulare de agent și cât de departe ajunge pragul sistemului de operare de sub acest motor
- Multiplayer — identitate, apartenență și prezență: spații, principalii și unde se află cadranul de autonomie
- Configurează guardrail-urile: scrierea și testarea regulilor în practică