Barandillas — una política para cada acción mutadora
Los agentes de Control Center pueden eliminar archivos, enviar ramas, publicar pull requests y llamar a API externas. Cada una de esas cosas es un tipo distinto de riesgo y, durante mucho tiempo, solo una de ellas —los comandos de shell— tenía política. Las barandillas existen para responder de forma uniforme a una única pregunta, para cada acción mutadora que pueda emprender un agente, sea cual sea el entorno de ejecución o la herramienta que la proponga: ¿se permite, requiere una aprobación o se deniega?
Un solo motor, todos los puntos de control
Sección titulada «Un solo motor, todos los puntos de control»Hay exactamente un motor de políticas. Se consulta en todos los puntos por los que una acción puede salir del sistema: el registro de herramientas del arnés integrado, la puerta del despachador MCP del lado del servidor y las mutaciones de operaciones de repositorio. Una regla escrita una vez se aplica, por tanto, tanto al entorno de ejecución integrado como a los CLIs de agentes externos: no hay una segunda vía, más silenciosa, que la eluda. La antigua política de comandos, limitada a bash, sigue funcionando: una regla puede coincidir con un prefijo de comando en lugar de con una clase de acción, y ambas formas conviven en el mismo almacén.
El motor no sustituye, sin embargo, al entorno aislado del sistema operativo,
ni el entorno aislado lo sustituye a él. Responden a preguntas distintas: las
barandillas deciden si una llamada que Control Center puede ver llega a
producirse, mientras que el entorno aislado acota hasta dónde puede llegar el
proceso resultante. cc_server aplica el entorno aislado allí donde el host
ofrece un backend, pero Windows no ofrece ninguno y Linux
necesita bwrap y socat. En esos hosts, las
barandillas son la capa de aplicación más externa en lugar de una política
sentada sobre un suelo, algo que conviene saber cuando decides cuán permisivo
ser.
ActionClass: una taxonomía deliberadamente cerrada
Sección titulada «ActionClass: una taxonomía deliberadamente cerrada»Cada herramienta mutadora declara a qué ActionClasses pertenece, dentro de un conjunto cerrado de trece clases de efecto. Cinco de ellas preguntan de serie; el resto permiten, y es una regla lo que cambia eso.
| Clase | Valor predeterminado | Qué cubre |
|---|---|---|
fileDelete |
prompt | Eliminar un archivo (una escritura con forma de borrado, rm) |
gitPush |
prompt | Enviar a un remoto de git |
prCreate |
prompt | Crear una pull request |
prPublish |
prompt | Publicar una revisión, fusionar una PR |
vendorSyncWrite |
prompt | Escribir en un proveedor externo de tickets (Linear, Jira, sincronización con GitHub) |
fileWriteOutsideWorktree |
allow | Escribir un archivo fuera del worktree aislado |
gitCommit |
allow | Crear un commit de git |
networkEgress |
allow | Salida a la red (obtención web, HTTP arbitrario) |
secretAccess |
allow | Leer un secreto o una credencial |
packageInstall |
allow | Instalar un paquete (npm, pip, pub, brew) |
processSpawn |
allow | Lanzar un proceso (shell y cualquier cosa que invoque un shell) |
workspaceMutation |
allow | Modificar la estructura del espacio de trabajo (repos, espacios, agentes) |
enclosureControl |
allow | Controlar un recinto (rig): arrancar una VM, enviarle entrada |
Las ocho clases permitidas de forma predeterminada se eligieron partiendo de la
premisa de que bajo ellas actúa el suelo del entorno aislado. Así ocurre allí
donde el host ofrece un backend, y no ocurre en Windows ni en una máquina Linux
a la que le falten bwrap y socat; por eso, si quieres que
fileWriteOutsideWorktree o packageInstall queden restringidas ahí, esa es
una regla que tienes que escribir.
El conjunto es cerrado a propósito. Una nueva herramienta mutadora que no declare ninguna clase no supera el test de trinquete, de modo que la taxonomía solo puede crecer mediante una decisión explícita y argumentada: «la dispersión de la taxonomía es la muerte de esta función». Trece clases bastan para expresar las políticas que la gente escribe de verdad (no enviar nunca sin preguntar, no eliminar nunca fuera de un worktree, permitir siempre las lecturas) y son lo bastante pocas para que la interfaz de ajustes siga siendo comprensible.
Reglas y resolución de ámbitos
Sección titulada «Reglas y resolución de ámbitos»Una regla asigna (scope, ActionClass | command prefix) → allow | prompt | deny.
Los ámbitos se anidan de más específico a menos:
espacio > agente > espacio de trabajo > preajuste del modo > valor predeterminado del sistema
La resolución va primero por especificidad: decide el primer ámbito con una regla coincidente y la resolución se detiene ahí. Lo más restrictivo solo sirve de desempate —entre dos reglas igual de específicas dentro de un mismo ámbito y al combinar las diversas clases que declara una misma acción—. Dentro de un ámbito, una regla de comando coincide según el prefijo de comando más largo. Permitir no gana a denegar en ningún sitio.
Dos decisiones conllevan garantías firmes:
- Los avisos deniegan por defecto. Un
promptsin ningún aprobador conectado se resuelve como denegado. Una pregunta sin respuesta nunca es un sí. - Combinación más restrictiva. Una acción que abarca varias clases las combina del modo más restrictivo; cuando varias clases preguntan, una sola confirmación las enumera todas.
Deliberadamente no hay ningún enclavamiento por turno. Cada llamada a una herramienta vuelve a resolver la política desde cero, de modo que la repetición de avisos para una misma acción está acotada por el propio «recuerda esta decisión» del operador, y no por nada ligado al turno.
Reglas a nivel de argumentos
Sección titulada «Reglas a nivel de argumentos»Una regla puede restringir los ARGUMENTOS de una acción, no solo su verbo.
«Puede enviar» y «puede enviar a feature/*» son afirmaciones distintas, y
solo la segunda es un control: una puerta de capacidad que autoriza únicamente
el verbo es la forma que hay detrás de la mayoría de los incidentes publicados
con agentes.
Una restricción puede nombrar:
- rutas — patrones glob (
repos/**,!**/.env) - refs — referencias de git, con negación
!(['**', '!main']se lee como «cualquier rama excepto main») - hosts — destinos de red, con comodines de subdominio (
*.internal) - comandos — prefijos de comando, que coinciden en un límite de palabra
- topes —
maxCount/maxCents, de modo que «eliminar hasta 50 archivos» es expresable
Tres propiedades se derivan de mantener la gramática cerrada y sin bucles, y las tres son el objetivo: toda regla se representa como una frase que puedes leer tal cual, toda denegación puede nombrar la restricción que coincidió y el conjunto de la política se puede enumerar: puedes ver qué puede hacer un agente antes de que se ejecute.
Tres reglas que importan:
- Una regla restringida es más específica que una sin restricciones en el
mismo ámbito, así que «denegar el envío a
main» gana a «permitir el envío» sin que nadie tenga que pensar en el orden. - Una regla restrictiva (denegar / preguntar) se aplica cuando la solicitud toca cualquier valor que nombre; una permisiva (permitir) solo se aplica cuando la solicitud está enteramente dentro de ella. Leer ambas del mismo modo permitiría a un agente blanquear una ruta prohibida colocando otra inocente a su lado.
- Una regla que nombra una faceta de la que la solicitud no dice nada ni se aplica ni se omite: escala a una aprobación. Omitirla en silencio dejaría inerte cualquier regla de rama protegida frente a una herramienta que no informa de su ref; denegarla en silencio rechazaría todos los envíos que el extractor no sabe describir. Sin ningún aprobador conectado, la regla existente de denegación por defecto convierte esa escalada en una denegación.
Qué puede detectar una regla de comando y qué no
Sección titulada «Qué puede detectar una regla de comando y qué no»Una regla commandPrefix coincide en un límite de palabra: git push cubre
git push origin main y no git pushx. No normaliza el shell.
git push (dos espacios), cd sub && git push y
GIT_DIR=… git push son cadenas distintas y ninguna coincide con una regla
sobre git push.
Ese es un límite real y se expone en lugar de disimularse: las reglas de comando
son una comodidad para el operador a la hora de modelar el comportamiento
habitual de un agente, no una frontera frente a un agente adversario. Las
fronteras son las clases de efecto (que una herramienta declara y no puede
reescribir), la red de comandos del modo que hay bajo el almacén de políticas y
el entorno aislado del sistema operativo bajo ambos. Una regla de comando que
se resuelve como allow nunca relaja ninguna de esas dos capas: la red del modo
se ejecuta después y su deny es definitivo.
Aprobaciones permanentes
Sección titulada «Aprobaciones permanentes»Responder a un aviso con «recuerda esto» escribe una regla de política real: con
ámbito (espacio / agente / espacio de trabajo), restringida por argumentos
(aprobar un envío a feature/login concede feature/**, no main) y
autorrevocable según un TTL explícito. Decir sí durante las próximas horas
no es lo mismo que reescribir en silencio tu política permanente, y las reglas
que escribe acaban en el mismo almacén con procedencia remembered y una
caducidad, de modo que se pueden revocar antes de tiempo.
Niveles de aplicación
Sección titulada «Niveles de aplicación»Cada regla lleva uno:
- advisory — se permite, pero se registra que la regla coincidió. Esta es la vía de adopción: despliega una regla estricta en modo advisory, consulta el registro de auditoría durante una semana para ver exactamente qué habría bloqueado y luego asciéndela. Sin este nivel, las políticas estrictas nunca llegan a activarse.
- soft — se deniega, con posibilidad de anulación por quien tenga el permiso de anulación y una justificación registrada. La anulación es en sí misma un evento auditado.
- hard (el valor predeterminado) — se deniega. Nada lo anula.
El nivel gestionado
Sección titulada «El nivel gestionado»El operador de una instalación puede fijar políticas que ningún administrador de
espacio de trabajo pueda relajar. Las reglas gestionadas viven en el servidor y
se combinan del modo más restrictivo con la cadena propia de cada espacio de
trabajo; no son un ámbito a la cabeza de esa cadena, porque un allow gestionado
a la cabeza de la cadena permitiría que la instalación anulara una denegación de
un espacio de trabajo, lo contrario de para lo que sirve un tope. Una regla
gestionada solo puede, por tanto, apretar.
Definir CC_SERVER_MANAGED_POLICY con un archivo JSON prevalece por completo
sobre las reglas almacenadas, y eso es lo que permite a un operador fijar una
postura que ninguna interfaz de administración puede cambiar: la respuesta a
«¿puedo impedir que mis desarrolladores desactiven los controles de seguridad?».
El dial de autonomía es un perfil, no un sistema paralelo
Sección titulada «El dial de autonomía es un perfil, no un sistema paralelo»El dial de autonomía por espacio es un perfil con nombre sobre este mismo
almacén de políticas, no un segundo mecanismo. Sus tres ajustes se almacenan y
se envían como proposeOnly, actWithApproval y actFreely (las formas con
guion son solo texto de la interfaz y autonomy.setForSpace rechaza cualquier
otra cosa). Dejarlo sin definir se comporta como actWithApproval.
Qué hace cada uno a una decisión ya resuelta:
proposeOnlydeniega sin más toda herramienta sometida al control. El agente aún puede razonar y responder; simplemente no puede actuar, y su mensaje dice por qué.actWithApproval(y sin definir) es la puerta de aprobación que deniega por defecto descrita más arriba.actFreelypreaprueba todo lo que no se haya resuelto como undenyfirme.
Esa última merece decirse con claridad en lugar de suavizarse: bajo actFreely,
una decisión prompt no escala a un aprobador: se permite y no se pregunta a
nadie. Solo una regla deny explícita sobrevive al dial. Así que actFreely es
una concesión deliberada de autonomía, no un ajuste de comodidad, y la regla de
denegación por defecto protege exactamente el caso en el que importa
(actWithApproval, el valor predeterminado).
La delegación entre agentes está protegida en el punto de control de
delegate_task por los cuatro controles: un tope de profundidad (3 de forma
predeterminada), la detección de ciclos, un techo de autonomía (un delegado
nunca puede actuar con más autonomía que su delegador: el privilegio no se puede
blanquear pasando trabajo a un agente más libre) y una envolvente de
presupuesto (la delegación se carga al presupuesto restante del delegador y no
puede acuñar más). Cada rechazo es explícito, con el motivo del control devuelto
al agente tal cual.
La matriz de honestidad de los adaptadores
Sección titulada «La matriz de honestidad de los adaptadores»No todos los entornos de ejecución permiten que Control Center intercepte todas las acciones. Los CLIs de agentes externos ejecutan algunas herramientas de forma nativa, dentro de su propio proceso, donde no cabe ninguna puerta. En lugar de fingir lo contrario, cada adaptador lleva una matriz de honestidad: por adaptador, si Control Center filtra la superficie de herramientas, intercepta las llamadas a herramientas, observa el contrato de finalización, puede ver las herramientas nativas del ejecutor y si las herramientas en proceso están cubiertas por un perfil de entorno aislado.
Merece la pena leer dos entradas antes de fiarte de una configuración. El arnés
integrado declara que sus herramientas de archivo en proceso no están
aisladas: la superficie de herramientas y este motor de políticas son su único
límite del sistema de archivos. Claude Code declara que sus propias llamadas a
herramientas no se pueden interceptar, porque se lanza con
--dangerously-skip-permissions; Control Center ve sus llamadas mcp__* y, mediante un hook, sus líneas de comandos de Bash, mientras que sus propias herramientas de lectura, escritura y edición se ejecutan sin ser vistas.
La pantalla de ajustes muestra esta matriz, porque el único fallo imperdonable de un sistema de barandillas es reclamar una cobertura que no existe.
Sondear la política antes de que muerda
Sección titulada «Sondear la política antes de que muerda»Las barandillas están en Ajustes → Espacio de trabajo → Permisos de agentes
(/workspaces/<id>/settings/workspace/permissions). La pantalla contiene la
matriz de políticas donde se escriben las reglas, plantillas de políticas, una
sonda de tipo «¿Qué pasaría si?», el registro de auditoría de autorización y la
matriz de honestidad de los adaptadores.
La sonda recibe una clase de acción (o un comando) y un ámbito, y muestra qué regla decidió y por qué. Como la resolución es pura y determinista —la misma acción, el mismo ámbito, la misma decisión—, la respuesta de la sonda es la respuesta que recibirá el agente.
Conceptos relacionados
Sección titulada «Conceptos relacionados»- Entorno aislado y seguridad: qué limita realmente la ejecución de un agente y hasta dónde llega el suelo del sistema operativo bajo este motor
- Multijugador — identidad, pertenencia y presencia: espacios, principales y dónde vive el dial de autonomía
- Configurar barandillas: escribir y probar reglas en la práctica