0102afa06e
Mueve el issue a completed/ y actualiza el índice. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
110 lines
6.6 KiB
Markdown
110 lines
6.6 KiB
Markdown
# 0024c — Security integration: wiring, cleanup config, docs
|
|
|
|
> Parte c del issue [0024-centralized-security-groups.md](0024-centralized-security-groups.md).
|
|
> Requiere 0024a y 0024b completados.
|
|
|
|
## Objetivo
|
|
|
|
Conectar el sistema centralizado de seguridad al launcher y al runtime. Eliminar los controles per-agente (`security.roles`, `matrix.filters.allowed_users`) de los configs de agente. Activar el feature flag. Actualizar docs.
|
|
|
|
## Contexto
|
|
|
|
- `pkg/security/` y `shell/security/` ya existen (0024a, 0024b).
|
|
- `agents/runtime.go` ya tiene un campo `acl acl.ACL` (añadido en issue 0010). Verificar si `agents.New()` lo acepta como parámetro o si necesita extenderse.
|
|
- `shell/matrix/listener.go` tiene checks de `AllowedUsers` que se eliminan (el ACL del runtime los reemplaza).
|
|
- `internal/config/schema.go` tiene `security.roles` (lines ~290-315) y `matrix.filters.allowed_users` (line ~230) que se deprecan.
|
|
|
|
## Arquitectura
|
|
|
|
```
|
|
cmd/launcher/main.go MODIFIED
|
|
agents/runtime.go MODIFIED
|
|
shell/matrix/listener.go MODIFIED
|
|
internal/config/schema.go MODIFIED
|
|
agents/assistant-bot/config.yaml MODIFIED
|
|
agents/asistente-2/config.yaml MODIFIED
|
|
dev/feature_flags.json MODIFIED
|
|
docs/security.md MODIFIED
|
|
CLAUDE.md MODIFIED
|
|
```
|
|
|
|
### Patron pure core / impure shell
|
|
|
|
- `cmd/launcher/` — **impuro**: carga la policy, resuelve ACL, inyecta en `Agent{}`
|
|
- `agents/runtime.go` — **composición**: recibe `acl.ACL` pre-resuelta
|
|
|
|
## Tareas
|
|
|
|
### Fase 1: Migrar permisos existentes
|
|
|
|
- [ ] **1.1** Leer los bloques `security.roles` de `agents/assistant-bot/config.yaml` y `agents/asistente-2/config.yaml` y migrarlos a `security/permissions.yaml`
|
|
- [ ] **1.2** Leer `matrix.filters.allowed_users` de ambos configs y añadir esos usuarios a los grupos correspondientes en `security/user-groups.yaml`
|
|
- [ ] **1.3** Verificar que `security/permissions.yaml` captura todos los permisos existentes antes de eliminar los bloques per-agente
|
|
|
|
### Fase 2: Wiring en launcher y runtime
|
|
|
|
- [ ] **2.1** En `cmd/launcher/main.go`: añadir `shellsecurity.Load("security/")` al inicio del proceso de arranque. Si devuelve error, loguear WARN y continuar con policy vacía (no fail-fast — comportamiento conservador)
|
|
- [ ] **2.2** En `cmd/launcher/main.go`: para cada agente, llamar `security.ResolveACL(cfg.Agent.ID, policy)` y pasar la `acl.ACL` resultante a `agents.New()`. Loguear a nivel DEBUG cuántos roles se resolvieron para el agente.
|
|
- [ ] **2.3** En `agents/runtime.go`: verificar/añadir que `agents.New()` acepta `acl.ACL` como parámetro. Si ya existe el campo `acl` en `Agent{}`, adaptar la firma de `New()`. Si no existe, añadir campo y lógica de `CanDo()` en `shouldHandle()`.
|
|
- [ ] **2.4** En `agents/runtime.go`: cuando `a.acl.Empty()` es true (policy vacía), el comportamiento es "sin restricciones" (igual que antes). Cuando no está vacía, `shouldHandle()` verifica `a.acl.CanDo(senderID, "ask")` para mensajes y `a.acl.CanDo(senderID, "command:"+cmd)` para comandos.
|
|
|
|
### Fase 3: Limpiar listener y config
|
|
|
|
- [ ] **3.1** En `shell/matrix/listener.go`: eliminar el bloque de chequeo de `AllowedUsers` en `shouldHandle()` (líneas ~285-301). El control de acceso ahora lo hace el runtime.
|
|
- [ ] **3.2** En `shell/matrix/listener.go`: eliminar el invite gating basado en `AllowedUsers` (líneas ~105-119). Las invitaciones se aceptan siempre; el ACL se aplica cuando el usuario habla.
|
|
- [ ] **3.3** En `internal/config/schema.go`: añadir comentario `// Deprecated: use security/ centralized groups instead` sobre el campo `security.roles` y sobre `matrix.filters.allowed_users`. No eliminar el campo (backward compat temporal).
|
|
- [ ] **3.4** En `agents/assistant-bot/config.yaml`: eliminar bloque `security.roles` y campo `allowed_users`
|
|
- [ ] **3.5** En `agents/asistente-2/config.yaml`: eliminar bloque `security.roles` y campo `allowed_users`
|
|
|
|
### Fase 4: Activar feature flag
|
|
|
|
- [ ] **4.1** En `dev/feature_flags.json`: añadir entrada:
|
|
```json
|
|
"centralized-security-groups": {
|
|
"enabled": true,
|
|
"issue": "0024",
|
|
"description": "Sistema centralizado de grupos de usuarios y agentes para control de acceso",
|
|
"added": "2026-03-08"
|
|
}
|
|
```
|
|
|
|
### Fase 5: Tests
|
|
|
|
- [ ] **5.1** `go build -tags goolm ./...` compila sin errores
|
|
- [ ] **5.2** `go test -tags goolm ./...` pasa completo
|
|
- [ ] **5.3** Arrancar el launcher localmente y verificar en logs: `"security policy loaded"`, `"resolved ACL for agent"` a nivel DEBUG/INFO
|
|
- [ ] **5.4** Verificar que un usuario listado en `admins` puede ejecutar comandos y tools
|
|
- [ ] **5.5** Verificar que un usuario no listado solo puede hacer `ask` (si la policy lo define así)
|
|
|
|
### Fase 6: Docs y cleanup
|
|
|
|
- [ ] **6.1** Actualizar `docs/security.md`: añadir sección "Sistema de grupos centralizados" con estructura de los 3 YAML, campos disponibles, ejemplos, y cómo se resuelven las ACLs. Marcar `security.roles` y `allowed_users` como deprecated.
|
|
- [ ] **6.2** Actualizar `CLAUDE.md`: añadir `security/` en la sección de estructura del proyecto
|
|
- [ ] **6.3** Cerrar issue 0024: mover `dev/issues/0024-centralized-security-groups.md` y sub-issues a `dev/issues/completed/`
|
|
|
|
## Ejemplo de uso
|
|
|
|
Flujo completo en producción:
|
|
```
|
|
1. Editar security/user-groups.yaml — añadir @newuser al grupo "developers"
|
|
2. Reiniciar launcher (o esperar hot-reload si aplica)
|
|
3. @newuser puede hablar con todos los agentes según los permisos del grupo "developers"
|
|
Sin tocar ningún config.yaml de agente individual.
|
|
```
|
|
|
|
## Decisiones de diseño
|
|
|
|
- **No fail-fast en loader**: si `security/` no existe o hay error de parseo, el launcher arranca con ACL vacía (sin restricciones). Preferible a que todos los agentes fallen por un typo en YAML. Se loguea WARN visible.
|
|
- **Eliminar invite gating**: el listener ya no filtra invites por AllowedUsers. El control ocurre cuando el usuario intenta interactuar. Más simple y consistente.
|
|
- **Deprecated pero no eliminado del schema**: los campos `security.roles` y `allowed_users` permanecen en el schema para no romper configs externos. Se eliminarán en un issue de limpieza posterior (0025 o similar).
|
|
|
|
## Prerequisitos
|
|
|
|
- 0024a completado
|
|
- 0024b completado
|
|
|
|
## Riesgos
|
|
|
|
- **Agentes sin permisos si security/permissions.yaml está vacío**: si se eliminan los bloques per-agente antes de migrar a permissions.yaml, los agentes quedan abiertos a todos. Mitigación: hacer la migración (tarea 1.1-1.3) ANTES de eliminar los bloques (tarea 3.4-3.5).
|
|
- **Firma de agents.New() cambia**: puede requerir actualizar tests existentes del runtime. Verificar antes.
|