Saltar al contenido
ColliePWA

13/Documentation

Seguridad: leer antes de ejecutar

Lo que expone un Collie, las defensas y la vinculación de un dispositivo, la credencial para cada petición

Collie proporciona acceso a una shell remota en su máquina por diseño. Una sola llamada a la API de Collie envía pulsaciones de teclas arbitrarias directamente a un panel de terminal activo. Cualquier dispositivo emparejado puede leer todos los paneles (código fuente, secretos, variables de entorno, salida del agente) y ejecutar comandos como su usuario. Desde la versión 1.18.0, cada solicitud a la API requiere el token de un dispositivo emparejado, incluidas las lecturas; por lo tanto, el punto de acceso es el emparejamiento en sí: cualquiera que pueda acceder a la URL y tenga un código de emparejamiento válido obtiene el mismo acceso. Antes de la versión 1.18.0, cualquiera que pudiera acceder a la URL podía leer todos los paneles.

No hay entorno de aislamiento (sandbox) ni lista de comandos permitidos, ya que filtrar comandos anularía el propósito de la herramienta. Trate cada dispositivo emparejado como un inicio de sesión de root y un código de emparejamiento como una contraseña. Revoque de inmediato un dispositivo extraviado con collie devices revoke <label>. El emparejamiento reduce el riesgo, pero no lo elimina; por ello, mantenga la URL en una red privada como una tailnet, nunca en la internet pública.

Emparejar un dispositivo: la credencial de escritura

Desde 1.18.0 esta es la credencial para cada petición, lecturas incluidas, no solo para escrituras.

# on the host — prints an 8-character code and a QR code, good for 10 minutes
bin/collie pair

La vinculación siempre está activa, y las lecturas requieren el token de vinculación al igual que las escrituras. Hasta que un dispositivo esté vinculado, Collie responde a cada teléfono y navegador con 403 device not paired. Ejecute collie pair primero, en el host, antes de abrir Collie en el teléfono.

Abra Collie en el teléfono, vaya a Settings → Paired devices e introduzca el código con una etiqueta para el dispositivo, o escanee el código QR impreso por el comando para abrir directamente esa pantalla con el código ya rellenado. El teléfono almacena el token devuelto. Collie solo conserva el hash y el token se muestra una sola vez. No es necesario reiniciar el proceso; el daemon en ejecución aplica los emparejamientos y las revocaciones en la siguiente solicitud.

Las dos restricciones de dispositivo responden a preguntas distintas, y es posible utilizar cualquiera de ellas, ambas o ninguna:

preguntaconfía enrevocación mediante
COLLIE_DEVICE_HEADER¿está este dispositivo en la lista del operador?su proxy, para inyectar un nombre saneadola edición de COLLIE_DEVICE_ALLOWLIST y el reinicio posterior
emparejamiento¿posee este dispositivo una credencial emitida por mí?nada en la redcollie devices revoke <label> (en tiempo real)

El emparejamiento no requiere infraestructura adicional. Es adecuado para una configuración directa de tailscale serve donde no existe ningún proxy para inyectar encabezados.

El emparejamiento restringe cada ruta /api, incluidas las lecturas. Solo dos rutas permanecen abiertas: /api/health, consultada por un monitor o balanceador de carga, y /api/pair, requerida por un dispositivo antes de poseer un token. /api/health responde con la compilación, el modo de equipo y tres conteos de los últimos siete días (frecuencia con la que el cuadro de entrada figuró libre, frecuencia con la que no se pudo leer y frecuencia con la que un usuario envió manualmente omitiendo una pantalla ilegible para Collie). Los conteos no mencionan paneles, textos ni personas.

El encabezado de dispositivo controla las escrituras y dos lecturas: la Vista Files, que puede mostrar cada archivo bajo la carpeta de un espacio de trabajo, y Explorar en la página New, que enumera nombres de carpetas bajo home (ADR 0086).

bin/collie devices list             # what holds a credential, and when each was last seen
bin/collie devices revoke old-phone # effective immediately, no restart

Una instalación limpia no tiene ningún dispositivo emparejado, por lo que Collie no responde a ningún teléfono hasta que se ejecuta collie pair. Revocar el último dispositivo no vuelve a abrir Collie: cada dispositivo recibe entonces device not paired. Para recuperarlo, ejecute collie pair en el host y vuelva a emparejar el teléfono. collie doctor advierte mientras no haya ningún dispositivo emparejado.

Nota. El enlace de crew y la standby door conservan sus propias credenciales. Un lead reenvía una lectura a un member mediante TLS mutuo fijado y el secreto de crew, por lo que un member no necesita un dispositivo emparejado propio (crew).

Cinco intentos fallidos de código invalidan el código, lo que requiere ejecutar collie pair de nuevo. Además, el bridge rechaza más de diez intentos de emparejamiento por dirección de origen por minuto con 429 y Retry-After: 60. Detrás de una front door en la misma máquina, la dirección de origen es la última entrada de X-Forwarded-For, la que añade la front door. Desde cualquier otro par, esa cabecera se ignora. Los contadores residen en la memoria y se reinician cuando el bridge se reinicia.

Lecturas propias de la CLI

En cada inicio, el bridge escribe un nuevo secreto aleatorio en local-secret dentro de su carpeta de estado. collie doctor y collie crew update lo envían para leer su propio bridge en la misma máquina. El archivo es de acceso exclusivo para el propietario, por lo que solo su cuenta puede leerlo, y una detención limpia lo elimina. El bridge solo lo acepta para lecturas, nunca para una escritura o la vista Files, y nunca desde otra máquina. Acepta el secreto únicamente desde loopback, y nunca en una petición que contenga la cabecera de un proxy como X-Forwarded-For. Un crew member que vincula COLLIE_HOST a su dirección de tailnet no tiene nada en loopback, por lo que allí el bridge también lo acepta desde las direcciones propias de esta máquina. Un retransmisor TCP simple en la misma máquina, como socat o ssh -L, aún puede transmitir el secreto. El archivo es lo que mantiene el secreto bajo su control, por lo que debe mantener la carpeta de estado accesible solo para el propietario.

Asignar una caducidad a un dispositivo

Un dispositivo emparejado conserva su token hasta que se revoca. Para limitar esto, pase un tiempo de vida al emparejar:

bin/collie pair --expires 30d             # also 12h, 2w; at most 3650d
bin/collie devices set-expiry pixel 90d   # a new lifetime, counted from now
bin/collie devices clear-expiry pixel     # no expiry again

El tiempo de vida se cuenta desde el momento en que el teléfono reclama el código. Sin --expires, un token nunca caduca, exactamente como antes, y ningún token existente cambia. Después de la caducidad, el bridge rechaza el token con device expired en lugar de device not paired. El teléfono entonces borra lo que dejó el emparejamiento y muestra Emparejar de nuevo en Settings, por lo que se debe ejecutar collie pair para obtener un nuevo código. collie devices list y la pantalla de Settings muestran la caducidad de cada dispositivo. Un dispositivo caducado permanece en la lista hasta que se revoca o se le asigna una nueva caducidad con set-expiry. Para emparejarlo de nuevo, se puede usar el mismo nombre: el nuevo emparejamiento reemplaza la entrada caducada y revoca su token anterior, y el registro de auditoría registra la revocación. Se rechaza un nombre que un dispositivo todavía esté usando con un token que no haya caducado. La standby door de un crew deputy también rechaza un token caducado.

En un host que ejecute varias instancias, anteponga COLLIE_INSTANCE=<name> a los comandos y abra la URL de esa instancia específica en el teléfono (Múltiples instancias de Collie en un mismo host).

Lo que se borra en el teléfono al desemparejar

Cuando finaliza un emparejamiento, el teléfono elimina lo que Collie almacenó bajo este. Esto ocurre cuando se desempareja el teléfono desde Settings y cuando el bridge rechaza su token con device not paired o device expired.

El teléfono elimina el token, cada borrador no enviado, el texto del panel guardado y la herd, la suscripción push, las confirmaciones de "Sin solicitudes" y las cachés de Collie excepto la shell de la aplicación. Su configuración permanece: el tema, el idioma, los elementos fijados y otras preferencias no contienen texto de sesión. Configuración solicita confirmación antes de revocar cualquier dispositivo.

El borrado propio del teléfono es el único que se realiza. El bridge no envía la cabecera Clear-Site-Data, ya que esa cabecera también borraría su configuración y la aplicación sin conexión, y en un nombre de host compartido afectaría también a las demás aplicaciones presentes.

Si el bridge no puede leer su lista de dispositivos emparejados, por ejemplo debido a un archivo escrito a medias, responde 503 pairing unavailable en su lugar. El teléfono conserva entonces su token y todo lo almacenado, y vuelve a intentarlo.

Lo que conserva el teléfono

El teléfono conserva una copia pequeña y limitada de lo último que vio, de modo que una apertura en frío pueda mostrarlo mientras el bridge esté inaccesible. Cada elemento siguiente tiene un límite de tamaño y un tiempo de vida.

QuéDóndeCuánto tiempoAl desemparejar
Token de emparejamientolocalStoragehasta desemparejar, revocar o caducareliminado
Settings: tema, idioma, pineslocalStoragehasta que se modifiquenconservado
Borradores no enviadoslocalStorage48 horaseliminado
Endpoint de pushlocalStoragehasta que cambieeliminado
App shellCache Storagehasta la siguiente compilaciónconservado
Fuentes y títulos de notificaciones pushCache Storagehasta que se reemplaceeliminado
Archivos del motor y del modelo de voz de Whistle (solo si se decidió copiarlos)Cache Storagehasta que se elimineneliminado
Texto de herd y paneles, según la última visualizaciónIndexedDB collie-store24 horaseliminado
Turnos de Chat más recientes de cada panelIndexedDB collie-store1 día, o la configuración "Keep chat on this phone"eliminado

Las dos últimas filas corresponden al almacenamiento en el dispositivo. Solo conserva texto que el bridge ya enmascarado, como máximo 256 KiB por panel y 10 MiB en total, y descarta primero las entradas más antiguas. El texto del panel y los turnos de Chat reciben cada uno la mitad de los 256 KiB del panel, de modo que uno nunca expulsa al otro. Los turnos de Chat se conservan completos, tal como Chat los representó, nunca como la pantalla sin procesar de la terminal. Si "Keep chat on this phone" se desactiva, no se conserva ninguno y se eliminan los guardados. Cuando un panel solicita una contraseña, el teléfono descarta las entradas de ese panel. Ningún elemento del almacenamiento puede enviar una pulsación de tecla o una respuesta. Las eliminaciones al desvincular son las indicadas en Lo que se borra en el teléfono al desemparejar.

El selector de aplicaciones del teléfono también puede mostrar un panel. Al salir de Collie, el teléfono conserva una captura de la pantalla para su lista de aplicaciones recientes, y esa imagen puede mostrar texto del panel. Una aplicación web no puede impedir esto: Android tomó su captura antes de que la página recibiera la notificación de paso a segundo plano (probado en un Pixel, 2026-10-08), e iOS tampoco ofrece garantías. Si esto supone un problema, bloquee el teléfono o cierre Collie antes de entregárselo a otra persona.

Modelo de riesgos

Límites de seguridad y riesgos clave:

  • Se ejecuta con sus permisos de usuario. Collie hereda todos sus derechos de acceso, incluidos ~/.ssh, git push --force, rm -rf y sudo.
  • La autenticación identifica dispositivos, no personas. Tailscale verifica el endpoint de hardware y no al usuario que lo tiene en la mano. No hay contraseñas ni sesiones de usuario; un teléfono desbloqueado o robado ofrece una shell abierta. La vinculación asocia el acceso a una credencial en el dispositivo (arriba), por lo que se debe revocar de inmediato un teléfono perdido. El bloqueo por inactividad integrado simplemente deja en blanco una pantalla desatendida y no proporciona un límite de seguridad real (ADR 0007).
  • Todos los usuarios locales del sistema pueden acceder al puerto. Los sockets estándar de multiplexores de terminal (tmux, zellij, herdr) utilizan permisos del sistema de archivos para restringir el acceso a otros usuarios locales. Collie escucha en un puerto TCP local, lo que lo expone a todos los UID locales. Las lecturas requieren el token de vinculación, por lo que otro usuario local sin token solo puede leer /api/health. El token es el límite: un usuario local con permisos de lectura sobre el perfil del navegador también puede leer el token (ARCHITECTURE.md §6).
  • Un permiso retenido espera la pulsación de un usuario. Con collie hooks install claude --hold-permissions, el hook de permisos de Claude consulta al bridge mediante un archivo de socket. Solo su usuario puede abrirlo (modo 0600 en una carpeta 0700). El hook verifica el propietario del socket, la carpeta y el directorio de estado superior antes de conectarse. El bridge responde únicamente por procesos ubicados en un panel. Nunca responde por sí solo. Una pulsación debe incluir el hash de lo mostrado en la tarjeta. Una tarjeta de pantalla nunca responde a solicitudes cuyo diálogo no figure en pantalla (Permisos retenidos para el teléfono).
  • La vista Files lee archivos directamente del disco. Muestra cualquier archivo dentro de la carpeta de un espacio de trabajo, excepto carpetas .git, las carpetas de estado y configuración propias de Collie, y archivos con nombres similares a los secretos de estado de Collie. Por tanto, requiere un dispositivo autorizado, al igual que una escritura (ADR 0083).
  • La opción Browse de la página New enumera nombres de carpetas bajo su directorio home. Solo nombres, con los límites de la vista Files: no se muestran carpetas que comienzan con punto a menos que se escriban explícitamente, sin .git, sin carpeta de estado o configuración de Collie, sin enlaces fuera de home, como máximo 200 filas. También requiere un dispositivo autorizado (Carpetas favoritas y recientes).
  • Cualquier dispositivo vinculado puede leer archivos ubicados dentro de la carpeta del espacio de trabajo. Eso incluye archivos .env. Vincule únicamente dispositivos en los que confíe plenamente para el acceso a la propia shell.
  • Los archivos de credenciales ubicados dentro de la carpeta de un espacio de trabajo son legibles. Un espacio de trabajo abierto en ~/.claude, ~/.codex, ~/.config/gh o ~/.ssh muestra su contenido. Lo mismo ocurre con el .env de un segundo Collie cuya carpeta de configuración resida bajo el espacio de trabajo. Tampoco se intercepta un enlace duro dentro de la carpeta que apunte a un archivo fuera de ella.
  • Un dispositivo vinculado puede añadir lanzadores. Con el valor predeterminado [phone] adds = true, un teléfono puede añadir una fila generada a partir de una receta: un agente más fichas de opciones cuyos flags el bridge toma de su propia tabla. Una línea escrita a mano requiere free_text = true, deshabilitado de forma predeterminada. Una receta aún puede omitir solicitudes de permisos. Dicha fila lleva un distintivo "Sin solicitudes" y cada dispositivo la confirma una vez. Revocar un dispositivo elimina las filas que añadió. Establezca adds = false para desactivar todas las filas añadidas desde teléfonos (Lanzadores propios, ADR 0094).
  • Un dispositivo vinculado puede ejecutar un comando puntual. Con el valor predeterminado [phone] run = true, un teléfono puede escribir una línea redactada por él en una nueva shell de una máquina. Esto no añade privilegios, ya que un teléfono vinculado ya puede abrir una shell y escribir en ella. La línea sigue la regla de caracteres de línea libre, y el bridge la rechaza si no hay ningún dispositivo vinculado. Cada comando iniciado se conserva, hasta 12, en commands-recent.json en la carpeta de estado (modo 0600). Una línea que parezca contener un secreto (una asignación como TOKEN=…, una URL con contraseña, o una palabra como token o password) se ejecuta pero no se conserva. La comprobación es una estimación, por lo que un secreto aún podría colarse en la lista; el registro de auditoría registra únicamente la primera palabra de la línea y su longitud. Desvincular o revocar un dispositivo deja la lista intacta, ya que ejecutar una línea de nuevo requiere un dispositivo vinculado. Establezca run = false para eliminar el acceso rápido (Comandos puntuales, ADR 0095).
  • Cada máquina conserva las líneas de shell que se envían mediante Collie. Sent guarda una línea enviada a un panel de shell, y cada comando puntual, en sent.jsonl dentro de la carpeta de estado (modo 0600). Un dispositivo emparejado puede leerlo, del mismo modo que puede leer los paneles. Aún se conservan algunos secretos (Sent: las líneas de shell que se enviaron).
  • Una sola instancia expone todas las sesiones de Herdr. Por defecto, un proceso de Collie gestiona cada sesión de Herdr detectada bajo la raíz de configuración de Herdr, incluidas las sesiones de sandbox (Multisesión).
  • Las escrituras se registran en <state-dir>/audit.log, que es ~/.local/state/collie/audit.log salvo que COLLIE_STATE_DIR lo mueva. El servidor registra todas las pulsaciones de teclas entrantes, respuestas, subidas de archivos y eventos del ciclo de vida de paneles o pestañas. Tenga en cuenta que un registro de auditoría proporciona visibilidad a posteriori y no control de acceso. Los caracteres enviados en modo Type nunca se escriben en el registro: COLLIE_AUDIT_CONTENT=none oculta cada uno de ellos y la vista previa predeterminada solo registra un conteo de marcas •. Las teclas con nombre como Enter y Ctrl+C permanecen legibles (ARCHITECTURE.md §6). Las respuestas, envíos, detenciones, pulsaciones de botones, inicios, reaperturas y cambios de nombre de un agente durable también se registran (Qué se registra).
  • Cabeceras de respuesta. Cada respuesta incluye X-Content-Type-Options: nosniff, Referrer-Policy: no-referrer y Permissions-Policy: camera=(), geolocation=(), microphone=(self), payment=(), usb=(). El micrófono permanece permitido para la opción de voz manos libres. La directiva Content-Security-Policy en el app shell incluye object-src 'none', form-action 'self' y frame-ancestors 'none'. Strict-Transport-Security solo se envía cuando una solicitud llega a través de HTTPS, ya sea en un listener TLS o con X-Forwarded-Proto: https desde su proxy. Cubre el nombre de host que respondió y no sus subdominios, ya que Collie a menudo comparte un dominio principal con otros servicios. El propio bridge utiliza HTTP sin cifrar detrás de tailscale serve, y el navegador ignora la cabecera en ese caso. Las imágenes servidas desde /api/blobs/ son contenido de sesión, por lo que incluyen Cache-Control: private, no-store y ninguna caché las conserva, ni siquiera la del teléfono.
  • Controles defensivos predeterminados. Collie se vincula estrictamente a interfaces de bucle invertido (loopback), enruta el tráfico exclusivamente mediante tailscale serve o un proxy inverso equivalente, y aplica reglas estrictas de CSP, comprobaciones de mismo origen y validación de encabezados Host. La salida del panel se procesa como nodos de texto de React en lugar de innerHTML. Nunca use tailscale funnel ni exponga un puerto sin procesar. Para autorizar hardware específico, use emparejamiento directamente o, si su proxy inyecta identificadores de dispositivo, las dos variables COLLIE_DEVICE_* siguientes.
variablequé hace
COLLIE_ALLOW_NON_LOOPBACK_BIND=1Desactiva el enlace exclusivo a loopback; si no se establece, el puente rechaza vincularse a 0.0.0.0.
COLLIE_ALLOW_ANY_HOST=1Deshabilita la validación del encabezado Host, que de otro modo está activada por defecto y se bloquea por seguridad en caso de fallo.
COLLIE_TRUSTED_USERRechaza una solicitud cuyo encabezado Tailscale-User-Login falte o no coincida.
COLLIE_TRUSTED_USER_OPTIONAL=1Permite la ausencia del encabezado Tailscale-User-Login (los nodos etiquetados nunca envían uno).
COLLIE_ACCESS_TEAM + COLLIE_ACCESS_AUDSolo Cloudflare Tunnel. Rechaza cada solicitud remota a menos que su Cf-Access-Jwt-Assertion se verifique para esta aplicación de Access. Solo un proceso local en loopback, /api/health y los enlaces del equipo la omiten, y el emparejamiento sigue siendo obligatorio. Otras vías de acceso, como tailscale serve, también se rechazan (Cloudflare Tunnel).
COLLIE_DEVICE_HEADERNombre del encabezado que su proxy inyecta con un identificador de dispositivo.
COLLIE_DEVICE_ALLOWLISTIdentificadores de dispositivo separados por comas autorizados para escribir; todos los demás dispositivos permanecen en modo de solo lectura (docs/deployment.md).
COLLIE_REDACT=offDesactiva la máscara de secretos en el texto de paneles, diffs y texto de archivos (abajo). Activado de forma predeterminada.
COLLIE_SENT=offNo guarda ningún registro de las líneas de shell enviadas (abajo). Activado de forma predeterminada.
🚫 Nunca use tailscale funnel con Collie. Funnel enruta el tráfico a internet público, mientras que tailscale serve restringe el acceso a su tailnet privada. No existe ningún caso de uso admitido para ejecutar Collie a través de Funnel.

Restrinja aún más el acceso con ACLs de Tailscale y COLLIE_TRUSTED_USER. Se proporciona tal cual, sin garantía.

Durable agents

Un agente durable acoplado es código ejecutado o desplegado por usted, y Collie trata su texto como no confiable. Un socket privado bloquea a otros usuarios pero no a procesos de su propio usuario, y un token es la única restricción a través de https. Las reglas de confianza por transporte, el tratamiento que Collie da al texto de un agente durable y lo almacenado en el registro de auditoría figuran en Seguridad de un durable agent.

El motor de voz (Whistle)

Whistle ejecuta código de terceros: un motor WebAssembly de Cactus Compute. Se ejecuta en el teléfono, o en el host bajo el usuario del bridge. Collie delimita el alcance de ese código. No puede eliminar el alcance por completo.

  • Integrado como dependencia externa y fijado. El motor consta de dos archivos, needle.js y needle.wasm, conservados byte por byte según los publicó el proyecto original, con la licencia original y una nota de procedencia (web/public/stt/needle-3-93e88ede/). Una prueba fija el sha256 de ambos archivos y la lista de las dieciséis funciones que el wasm puede solicitar a su host. Una nueva importación es motivo de interrupción. Solo una persona actualiza la fijación, y lee el diff previamente. El modelo tiene su propio hash fijado, y Collie conserva una copia descargada solo cuando coincide.
  • En el teléfono, un worker con su propia política. El wasm se ejecuta en un worker dedicado. El bridge sirve cada script bajo stt/ con esta política, y ninguna otra página la recibe:
    Content-Security-Policy: default-src 'none'; script-src 'self' 'wasm-unsafe-eval'; base-uri 'none'

    El worker no dispone de acceso a la red, carece de DOM y no puede cargar código externo. No puede leer el token de emparejamiento, ubicado en localStorage, y los workers no tienen acceso a localStorage. Antes de realizar cualquier otra acción, compila un módulo wasm mínimo. Cualquier navegador que no asigne al worker una directiva propia rechazará la operación, y Este teléfono aparecerá como no disponible allí.

  • La directiva de la página no cambia. La directiva del documento nunca adquiere 'wasm-unsafe-eval', y conserva connect-src 'self'.
  • A qué puede acceder todavía el worker. Puede leer y escribir en IndexedDB y Cache Storage de este origen, recursos que ninguna directiva de política restringe. collie-store almacena texto reciente de paneles y de Chat (Lo que conserva el teléfono). Dicho texto ya estaba enmascarado, pero resulta legible. Este alcance está aceptado y documentado en el ADR. Si llega a representar un problema, el paso siguiente es un marco aislado en sandbox alrededor del worker.
  • En el host, un subproceso del propio binario de Collie. Un subproceso efímero por cada dictado ejecuta _whistle-transcribe con una lista fija de argumentos definida por Collie. Comprueba el motor, el wasm y el modelo contra sus valores fijados antes de compilar nada. Cuenta con un límite de tiempo de 60 segundos antes de terminarse con SIGKILL, un tope de salida de 256 KiB y un máximo de dos ejecuciones simultáneas. No recibe ninguna de las variables COLLIE_* del bridge. El bridge solo define dos, el directorio de estado y el directorio de instalación, asignadas a rutas resueltas por sí mismo. Ningún dato de la petición llega a la lista de argumentos salvo la grabación.
  • Una segunda llamada saliente, iniciada manualmente por el usuario. La comprobación de actualizaciones es la primera. La descarga del modelo es la segunda: un único archivo, desde una dirección fija de Hugging Face, guardado solo tras verificar la coincidencia del hash. El teléfono nunca se conecta a Hugging Face. Copia el modelo desde el host mediante el token de emparejamiento. Las rutas requieren un dispositivo de escritura, se ejecutan únicamente en el nodo principal, permiten una sola descarga simultánea y se auditan.
  • La configuración desde Ajustes es una excepción a la regla de configuración exclusiva por CLI. Los proveedores que almacenan credenciales o definen un comando permanecen en el terminal. Whistle no realiza ninguna de estas acciones. Un token de escritura comprometido ya puede escribir en terminales e iniciar una actualización, por lo que la confirmación de configuración no le otorga privilegios adicionales.
  • Cambiar a Codex desde Ajustes es la otra excepción. Un dispositivo de escritura solo puede alternar el host entre Whistle, Codex y Off, sin otras opciones. Codex requiere el consentimiento completo, con las mismas palabras que imprime collie stt setup, y pulsar en Acepto; a continuación, el bridge ejecuta la propia verificación de la CLI. Un token de escritura comprometido podría redirigir la función de voz del host hacia la cuenta de ChatGPT con sesión iniciada del operador. No puede añadir una clave ni un comando, ni sustituirlos. El token ya puede escribir codex en un terminal. ADR 0097 evalúa este riesgo. Un cambio desde Ajustes también escribe en stt.json el nombre del dispositivo emparejado, tal como se indicó al emparejarlo, y la fecha y hora, permitiendo a Voz del host indicar quién lo modificó por última vez. No se registra ningún token ni dirección. La ejecución de collie stt setup elimina esa línea.
  • Los dispositivos emparejados pueden consultar lo que designan los ajustes de voz del host, únicamente por su nombre. Es el nombre del comando, el nombre de un archivo de modelo y el nombre de host de un servicio de voz; nunca una ruta, un argumento, una clave o una ruta URL.

Por qué está diseñado de esta forma: ADR 0096. Los pasos de configuración están en Entrada de voz y Web Push.

Walky talky

Walky talky transporta mensajes entre sesiones de agentes; por lo tanto, esta sección detalla lo que un mensaje demuestra y lo que no. Los comandos están en Walky talky.

# in .env, then run `collie restart`
COLLIE_WALKY=off

Esa línea hace que esta máquina rechace todo mensaje destinado a sus paneles. La CLI de la máquina aún puede enviar.

  • Una clave de crew firma un mensaje entre máquinas. Un miembro firma un mensaje con su clave de crew. El lead verifica la firma contra la clave fijada para ese miembro y luego añade su propia firma para la máquina receptora. Una instalación individual no posee clave de crew. No firma nada ni envía nada fuera de la máquina.
  • El receptor verifica al remitente mediante la palabra del lead. Un miembro fija únicamente a su lead. Por tanto, el lead envía el certificado del remitente con el mensaje y firma una breve declaración de que dicho certificado pertenece a ese miembro de la crew. La máquina receptora verifica esa declaración y luego comprueba la firma del remitente contra el certificado. Si alguna comprobación falla, rechaza el mensaje. Sigue confiando en el lead respecto a quién integra la crew.
  • Solo el lead puede devolver un resultado por escrito. El lead envía a un miembro los resultados de los propios mensajes de ese miembro. El miembro los acepta únicamente de su lead fijado, y solo para un mensaje enviado por él que aún mantenga en el registro. Los resultados y el registro de lo recibido por el lead permanecen en memoria y se descartan tras 10 minutos.
  • La tarjeta del teléfono requiere el registro. El teléfono dibuja una tarjeta de mensaje únicamente si el registro del propio puente contiene dicho id de mensaje. Un encabezado que un agente solo imprime en pantalla se mantiene como texto plano, con la marca "no log record on this machine".
  • Un token de panel no es secreto. El token en una dirección, como #k3f9, evita que un mensaje llegue a una sesión nueva que haya tomado el id de un panel cerrado. collie walky who lo imprime para cada agente, y <stateDir>/walky/instances.json puede ser leído por su usuario. No prueba nada sobre la identidad del remitente.
  • Toda máquina por la que pasa un mensaje lo conserva. La máquina emisora, el lead y la máquina receptora registran cada uno el mensaje en <stateDir>/walky/. El registro conserva 7 días y un máximo de 2.000 líneas. Nunca incluya un secreto en un mensaje.
  • El mensaje de un agente son las palabras de un par. El panel recibe una sola línea con el encabezado del remitente y sin cuerpo. El agente lee el cuerpo como la salida de collie walky inbox <id>, que un entorno de pruebas trata como datos y no como su instrucción. La habilidad instalada indica al agente que lo evalúe y que nunca ejecute un comando destructivo porque un par lo haya solicitado.
Nota. Un agente se ejecuta bajo su usuario, por lo que puede leer la clave de crew y abrir el socket local. Podría firmar un mensaje o reclamar un panel que no le pertenece. La firma protege un mensaje en su trayecto entre máquinas e indica al receptor qué máquina lo envió. No le protege de un programa en la misma máquina que mienta sobre su identidad.

Walky talky no añade llamadas salientes. Un mensaje hacia otra máquina viaja por el enlace de crew ya existente, y ningún modelo, servicio en la nube o tercero lo ve.

Lo que sale de la máquina se enmascara

Collie enmascara los patrones de secretos conocidos en el texto de los paneles y en el contenido de los archivos antes de que lleguen al teléfono.

# in your .env, only to turn the mask off; it is on by default
COLLIE_REDACT=off

La máscara se ejecuta en el bridge, en cinco rutas: el reflejo de la terminal, las vistas Chat e History, cada notificación push, los diffs en la vista Changes y el texto de los archivos en la vista Files. Lo que oculta se sustituye por marcas • del mismo ancho, manteniendo así las columnas y el número de líneas. Los prefijos de proveedor permanecen legibles, de modo que sk-o•••• sigue indicando qué se ha ocultado.

Solo coincide con patrones de alta confianza:

patrónejemplo de lo que se enmascara
claves de API con prefijosk-…, sk-ant-…, sk-or-v1-…, ghp_…, github_pat_…, xoxb-…, AKIA…, AIza…, glpat-…, npm_…
JWTtres partes en base64url, la primera comenzando con eyJ
claves privadas PEMcada línea entre BEGIN … PRIVATE KEY y su línea END
tokens de portadorel token después de Bearer , de 20 caracteres o más
valores con nombreel valor después de password=, secret:, token=, api_key: y similares, de 8 caracteres o más
Precaución. Esto es una mitigación, no una garantía. Una contraseña simple por sí sola, un valor hexadecimal o base64 puro, y una clave con un prefijo que no esté en la lista se omiten a propósito. Un patrón para ellos enmascararía texto ordinario y código en cada pantalla.

Parte del texto ordinario también se enmascara, por ejemplo una línea de prosa o YAML que contenga token: something. Lo que se escribe y se envía nunca se enmascara, y el registro de auditoría mantiene sus propias reglas (COLLIE_AUDIT_CONTENT).

El interruptor reside únicamente en el bridge, como COLLIE_REDACT. Configuración → Sistema lo muestra en modo de solo lectura, como "Secret masking". El teléfono no tiene interruptor a propósito: un interruptor en el teléfono permitiría a cualquier teléfono emparejado, o a uno robado, desactivar la máscara. Para leer un valor enmascarado, léalo en la máquina. La primera vez que un panel muestra texto enmascarado, una línea corta en el teléfono lo indica, una vez por dispositivo. Si se pega texto enmascarado en una respuesta, una advertencia debajo del cuadro indica que el panel recibe los puntos, no el secreto.

En un crew, cada miembro enmascara su propio texto, y el líder lo enmascara de nuevo antes de que llegue a su teléfono. El líder enmascara el espejo, Chat, Historial, diffs, texto de archivos y títulos de paneles de un miembro con la misma máscara que usa para los suyos, de modo que un miembro que aún ejecute 1.17.x no pueda enviar una clave a su teléfono en texto claro. El texto enmascarado permanece igual cuando se vuelve a enmascarar. El texto llega al teléfono sin enmascarar únicamente cuando COLLIE_REDACT=off está configurado tanto en el líder como en el miembro. Una excepción: un miembro en 1.17.x no enmascara nada por sí mismo, por lo que cuando hay un secreto en las líneas contra las que se verifica una respuesta, el teléfono puede rechazar esa respuesta con "La pantalla cambió antes de que pudiera enviarse". La respuesta entonces espera hasta que el miembro ejecute 1.18.0.

Si el líder no puede leer la respuesta de un miembro para enmascararla, no reenvía la respuesta. El teléfono muestra entonces esa lectura como fallida, igual que hace con un miembro al que no puede acceder.

Una notificación push también identifica un panel solo por el nombre asignado: la etiqueta del panel, el nombre /rename de Claude o el nombre de una pestaña de un solo panel. Nunca usa el título establecido por un programa en el panel, porque cualquier programa puede establecer ese título, y un título puede contener una ruta, un comando o un secreto. Un panel sin dicho nombre se denomina por su harness, por ejemplo claude.

Sent: las líneas de shell que se enviaron

Cada máquina conserva un registro de las líneas de shell que se envían a través de Collie, para que sea posible encontrarlas y enviarlas de nuevo.

# in your .env, to keep no record on this machine
COLLIE_SENT=off
preguntarespuesta
Qué se conservaLas líneas enviadas a un panel de shell y cada comando puntual de la página New. Para cada línea: el texto, su carpeta, la hora y cuál de los dos tipos era.
Qué nunca se conservaInstrucciones para un agente, texto para un programa, claves del tablero Keys y el modo Type.
Dóndesent.jsonl en la carpeta de estado, ~/.local/state/collie/ a menos que COLLIE_STATE_DIR lo mueva. El archivo tiene permisos 0600, dentro de una carpeta con 0700.
Cuánto tiempoComo máximo 5000 líneas en cada máquina, y ninguna con más de 365 días de antigüedad.
Quién puede leerloUn dispositivo emparejado, ya que puede leer los paneles a los que se enviaron las líneas.
En una crewCada máquina conserva su propio archivo. El líder consulta a sus miembros cuando el teléfono lo solicita, y no guarda ninguna copia.

Collie envía cada línea que se introduce y luego decide si conservarla. No conserva nada sobre una línea que:

  • comience con un espacio o un tabulador,
  • defina una variable, como TOKEN=abc deploy o export AWS_SECRET_ACCESS_KEY=…,
  • contenga una URL con contraseña, como https://user:pass@host,
  • contenga una palabra como password, secret, token, bearer o authorization,
  • tenga una estructura reconocida por la máscara de secretos, como una clave de ghp_… o sk-…,
  • supere los 4096 caracteres.

Dicha línea no deja ninguna fila, ningún recuento ni ninguna línea de registro con su texto.

Para excluir una línea, iníciela con un espacio. La shell la ejecuta con normalidad y Collie no conserva nada.

Precaución. La comprobación es una estimación. Conservará contraseñas que se pasen como argumento simple, como mysql -pPASS, y cualquier secreto con una estructura que no reconozca. Inicie ese tipo de líneas con un espacio.

Para olvidar una línea, use Forget en su fila dentro de la hoja Sent. Para olvidar una máquina completa, use Clear Sent. Ambas opciones funcionan mientras COLLIE_SENT=off esté configurado. El registro de auditoría anota cada acción de olvidar con un recuento, nunca con la línea en sí. Cada línea pasa por la máscara de secretos antes de salir de la máquina.

Por qué está diseñado de esta forma: ADR 0107.

Archivos secretos en Windows

En Windows (experimental), Collie restringe sus archivos secretos a su cuenta, a SYSTEM y a Administrators. "Su cuenta" corresponde a la cuenta de Windows que ejecuta Collie.

NTFS carece del modo 0600, por lo que Collie utiliza la lista de control de acceso (ACL) de su carpeta de estado y de su carpeta de configuración. Cada archivo escrito por Collie allí recibe la misma lista. Las carpetas predeterminadas en el perfil de usuario ya están restringidas para otros usuarios estándar. La comprobación resulta fundamental al mover una carpeta con COLLIE_STATE_DIR u otra configuración.

Al iniciar, el puente comprueba ambas carpetas y sus archivos secretos. Si otras cuentas pueden leer alguno, el puente lo repara, pero solo en las carpetas propias de Collie. Primero guarda la lista anterior en acl-backups dentro de la carpeta de estado y muestra el comando icacls /restore para restaurarla. Ejecute ese comando en una terminal iniciada como administrador. Una carpeta que también contiene otros archivos solo se comprueba, no se modifica: Collie muestra el comando icacls para su ejecución manual. Otros comandos, como collie version, solo comprueban y emiten advertencias.

collie doctor muestra el resultado como secrets-private. Una carpeta accesible para otras cuentas constituye un error y se incluye la solución. Una carpeta que Collie no puede comprobar genera una advertencia: cannot confirm.

CasoQué ocurre
Se copia, restaura o sincroniza la carpeta (zip, robocopy sin /SEC, OneDrive, Historial de archivos o una unidad USB)La copia puede perder la lista. Collie vuelve a comprobarla en el siguiente inicio.
El antivirus o el Acceso controlado a carpetas bloquea el cambioCollie indica que no se pudo restringir la carpeta a privada y proporciona la solución.
La carpeta está en FAT, exFAT o en un recurso compartido de redNo existe una lista compatible para Collie. Collie indica cannot confirm. Mueva la carpeta de estado a una unidad NTFS en este equipo.
COLLIE_NO_ACL_REPAIR=1Collie no modifica ninguna lista. Mantiene las comprobaciones y las advertencias, y doctor continúa informando.
Nota. Esto no ofrece protección frente a un administrador. Los administradores pueden leer los archivos. Tampoco cubre otros programas ejecutados con su cuenta, enlaces duros dentro de la carpeta, copias de seguridad de agentes en ~/.claude, ni una carpeta de estado ubicada dentro de OneDrive o Documentos.

Qué información sale de su máquina

Nada, por defecto y por política. Collie no envía eventos de instalación, estadísticas de uso, informes de fallos ni analíticas. No existe ninguna opción que los habilite.

La única llamada saliente no solicitada es la comprobación de actualizaciones: una petición HTTPS GET anónima a la API pública de etiquetas de GitHub (bridge/update.ts) que compara su versión con la etiqueta más reciente. No transmite datos sobre usted ni sobre su máquina, solo el user-agent estático collie-update-check.

La descarga del modelo de Whistle es la otra llamada saliente. Se produce únicamente cuando alguien pulsa Descargar al host o ejecuta collie stt whistle, y no envía ningún dato sobre usted (El motor de voz (Whistle)).

Walky talky no añade llamadas salientes. Un mensaje hacia otra máquina viaja por el enlace de crew y no va a ningún otro lugar (Walky talky).

Informar de un problema no añade llamadas salientes. Tras envíos fallidos, el teléfono puede abrir el formulario de nueva incidencia de GitHub, ya completado, como un enlace en su propio navegador. Se lee todo el texto primero y se envía de forma manual desde su propia cuenta. Collie no almacena ningún token de GitHub y el teléfono nunca llama a GitHub (ADR 0123).

Si se configura COLLIE_ACCESS_TEAM, Collie también obtiene las claves públicas de ese equipo de Cloudflare Access al iniciar y una vez por hora. Esta llamada es opcional y no transmite información personal.

Si acopla un agente durable mediante URL, Collie consulta dicha URL en cada sondeo con el token de portador del agente durable en la cabecera Authorization. Dicha llamada también debe activarse manualmente y no se envía nada hasta acoplar uno (Seguridad de un durable agent).

Si alguna vez se añade recopilación de datos, el límite máximo es el consentimiento explícito: desactivado por defecto, formulado como una pregunta visible, nunca activado mediante una opción o por omisión. Eliminar esa promesa constituiría un cambio incompatible (ADR 0034).

Editar esta página en GitHub

The rest of the documentation