feat(cybersecurity): auto-commit con 48 cambios

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-04 23:44:39 +02:00
parent efc9911925
commit 729921e16e
48 changed files with 3765 additions and 8 deletions
+2 -1
View File
@@ -23,7 +23,7 @@ Indice de grupos de capacidades del registry. Cada grupo agrupa >=3 funciones qu
| [nlp](nlp.md) | 33 | Extraccion NLP: PDFs, OCR, chunking, GLiNER/GLiREL, dedup, agregacion de entities/relations |
| [docker](docker.md) | 38 | Operar Docker desde Go/Bash: build/run/stop, compose, networks, volumes, logs, deploys |
| [android](android.md) | 37 | Toolbelt Android desde WSL2: adb, emuladores AVD, APK build/install, Capacitor, logcat |
| [web-proxy](web-proxy.md) | 4 | Captura de trafico HTTP/HTTPS liviana (mitmproxy): proxy con rotacion, navegador proxeado, consulta de capturas. Alternativa ligera a ZAP/Burp |
| [web-proxy](web-proxy.md) | 5 | Captura de trafico HTTP/HTTPS liviana (mitmproxy): proxy con rotacion, navegador proxeado, consulta de capturas, tee del SSE de claude. Alternativa ligera a ZAP/Burp |
| [metabase](metabase.md) | 106 | Operar Metabase via API REST: auth, cards, dashboards, collections, snippets, permissions |
| [doctor](doctor.md) | 11 | Diagnostico read-only del registry: artefactos, servicios, drift, funciones huerfanas |
| [notebook](notebook.md) | 5 | Operar Jupyter Lab colaborativo (discover/read/exec/write/kernel) |
@@ -45,6 +45,7 @@ Indice de grupos de capacidades del registry. Cada grupo agrupa >=3 funciones qu
| [wireguard](wireguard.md) | 7 | Instalar, configurar, operar y monitorizar mesh WireGuard hub-and-spoke: keygen, hub setup, peer add/revoke, status JSON |
| [matrix-mas](matrix-mas.md) | 5 | Migración Synapse→MAS: habilitar MSC3861, verificar login flows, parche .well-known, registro clientes OAuth2, syn2mas |
| [mesh-3d](mesh-3d.md) | 3 | Carga y upload a GPU de meshes 3D (OBJ, GLB/glTF 2.0): loaders CPU + mesh_gpu_upload OpenGL |
| [terminal-capture](terminal-capture.md) | 6 | Automatizar y capturar el texto de una CLI/TUI interactiva via PTY headless: spawn+input scripteado (one-shot y streaming), render del layout 2D (emulador VT), strip ANSI, delta por prefijo, y parseo de la TUI de claude a datos |
## Como anadir grupo
+97
View File
@@ -0,0 +1,97 @@
---
group: e2e-messaging
description: "Criptografía extremo a extremo para bus de mensajería: identidades duales Ed25519/X25519, distribución de claves de sala con sealed box anónimo, cifrado simétrico AEAD por mensaje, y firma/verificación de mensajes."
functions:
- generate_identity_go_cybersecurity
- seal_aead_go_cybersecurity
- open_aead_go_cybersecurity
- seal_key_box_go_cybersecurity
- open_key_box_go_cybersecurity
- sign_ed25519_go_cybersecurity
- verify_ed25519_go_cybersecurity
---
## Funciones del grupo
| ID | Firma corta | Qué hace |
|---|---|---|
| `generate_identity_go_cybersecurity` | `GenerateIdentity() (Identity, error)` | Genera par Ed25519 (firma) + par X25519 (kex) para un participante |
| `seal_aead_go_cybersecurity` | `SealAEAD(key, plaintext, aad []byte) (nonce, ct []byte, err error)` | Cifra mensaje con ChaCha20-Poly1305, nonce aleatorio por llamada |
| `open_aead_go_cybersecurity` | `OpenAEAD(key, nonce, ct, aad []byte) ([]byte, error)` | Descifra y autentica; error explícito si el tag falla |
| `seal_key_box_go_cybersecurity` | `SealKeyBox(recipientKexPub, secret []byte) ([]byte, error)` | Cifra room key para un destinatario con su X25519 pubkey (sealed box anónimo) |
| `open_key_box_go_cybersecurity` | `OpenKeyBox(kexPub, kexPriv, sealedMsg []byte) ([]byte, error)` | Abre sealed box con el par X25519 propio para recuperar la room key |
| `sign_ed25519_go_cybersecurity` | `SignEd25519(priv, msg []byte) []byte` | Firma determinista Ed25519 (pura, sin I/O) |
| `verify_ed25519_go_cybersecurity` | `VerifyEd25519(pub, msg, sig []byte) bool` | Verifica firma Ed25519 (pura, sin I/O) |
## Ejemplo canónico end-to-end
```go
package main
import (
"fmt"
"log"
cs "fn-registry/functions/cybersecurity"
)
func main() {
// 1. Cada participante genera su identidad una sola vez
server, err := cs.GenerateIdentity()
if err != nil { log.Fatal(err) }
user, err := cs.GenerateIdentity()
if err != nil { log.Fatal(err) }
// 2. Servidor genera room key y la distribuye al usuario cifrada
roomKey := make([]byte, 32)
// ... llenar roomKey con crypto/rand en producción ...
sealed, err := cs.SealKeyBox(user.KexPub, roomKey)
if err != nil { log.Fatal(err) }
// 3. Usuario recupera la room key
gotKey, err := cs.OpenKeyBox(user.KexPub, user.KexPriv, sealed)
if err != nil { log.Fatal(err) }
// 4. Usuario cifra un mensaje con la room key
aad := []byte("room:sala-general:seq:1")
nonce, ct, err := cs.SealAEAD(gotKey, []byte("hola sala"), aad)
if err != nil { log.Fatal(err) }
// 5. Usuario firma el ciphertext para autenticar autoría
sig := cs.SignEd25519(user.SignPriv, ct)
// 6. Receptor verifica firma y descifra
if !cs.VerifyEd25519(user.SignPub, ct, sig) {
log.Fatal("firma inválida")
}
plain, err := cs.OpenAEAD(gotKey, nonce, ct, aad)
if err != nil { log.Fatal(err) }
fmt.Printf("recibido: %s\n", plain)
_ = server // server.SignPub publicado en directorio de participantes
}
```
## Fronteras
Este grupo cubre las primitivas criptográficas del bus, no el protocolo completo:
- **No cubre**: transporte (WebSocket, gRPC), gestión de sesiones, ratchet de claves (doble ratchet), persistencia de identidades, revocación de claves.
- **No cubre**: cifrado de archivos adjuntos (usar SealAEAD directamente con una key derivada).
- **No reemplaza**: libsodium ni libolm para implementaciones de producción de Signal/Matrix — estas funciones son el sustrato criptográfico, no el protocolo completo.
## Prerequisitos
- `golang.org/x/crypto` ya en `go.mod` (presente en fn-registry).
- `crypto/ed25519` de stdlib (Go 1.13+).
- Identidades persistidas de forma segura (keyring, HSM, archivo cifrado): este grupo no gestiona almacenamiento.
## Patrón de uso recomendado
```
GenerateIdentity() → persiste Identity por participante
SealKeyBox(kexPub, roomKey) → distribuye room key al unirse a sala
OpenKeyBox(kexPub, kexPriv) → recupera room key
SealAEAD(roomKey, msg, aad) → cifra cada mensaje
SignEd25519(signPriv, ct) → autentica autoría sobre ciphertext
VerifyEd25519(signPub, ct) → verifica antes de descifrar
OpenAEAD(roomKey, nonce, ct)→ descifra mensaje verificado
```
+86
View File
@@ -0,0 +1,86 @@
# terminal-capture
Automatizar una CLI/TUI interactiva y capturar su texto, de forma headless, a través de un
pseudo-terminal (PTY). Cubre el ciclo completo: lanzar el proceso con un TTY real, inyectarle
input scripteado, esperar a que el render se estabilice, y convertir el stream crudo de bytes a
texto plano — bien reconstruyendo el layout 2D (TUIs con cursor absoluto), bien limpiando ANSI
de output secuencial.
Existe porque muchas CLIs (sobre todo la CLI `claude`) solo entran en su modo interactivo rico
cuando detectan un TTY; un pipe normal las degrada. El PTY es virtual, en memoria: **nunca abre
una ventana de terminal**.
## Funciones
| ID | Firma | Qué hace |
|---|---|---|
| `pty_capture_idle_go_infra` | `func PTYCaptureIdle(ctx, name string, args []string, warmup time.Duration, inputs []string, stepDelay, idle, maxDur time.Duration) (string, error)` | Lanza `name args` en un PTY (40×120), espera `warmup`, escribe cada `inputs` separado por `stepDelay`, y captura todos los bytes hasta que pasa `idle` sin output nuevo o se alcanza `maxDur`. Devuelve el stream **crudo** (ANSI intacto). One-shot. |
| `pty_capture_stream_go_infra` | `func PTYCaptureStream(ctx, name string, args []string, warmup time.Duration, inputs []string, stepDelay, snapshotInterval, idle, maxDur time.Duration) (<-chan string, error)` | Igual que `pty_capture_idle` pero emite **snapshots acumulativos** del buffer por un canal cada `snapshotInterval` — para hacer streaming de la TUI mientras renderiza. El consumidor renderiza/parsea cada snapshot. |
| `text_prefix_delta_go_core` | `func PrefixDelta(prev, curr string) string` | Devuelve la parte de `curr` que sigue al prefijo común con `prev` (delta de streaming por snapshots). Pura, compara por runas. Heurística ante reflow. |
| `vt_render_go_tui` | `func VTRender(raw string, rows, cols int) string` | Emula un terminal VT100 de `rows×cols`, alimenta `raw`, y devuelve el estado final de la pantalla como texto plano **con el layout reconstruido** (espacios reales donde el stream tenía movimientos de cursor). Pura. |
| `strip_ansi_go_core` | `func StripANSI(s string) string` | Elimina secuencias ANSI/VT100 y caracteres de control de un stream **secuencial** (logs), preservando `\n`, `\t`, `\r`. Pura. NO reconstruye layout 2D. |
| `parse_claude_tui_go_tui` | `func ParseClaudeTUI(screen string) ClaudeTUIParse` | Parsea la pantalla renderizada de la TUI de `claude` (salida de `vt_render`) y extrae los turnos (user/assistant/tool_use/tool_result) + la respuesta final (`Answer`), equivalente a lo que devolvería `claude -p`. Pura, heurística, específica de la TUI de claude. |
## Cuándo usar cada limpiador
El corazón del grupo es `pty_capture_idle` (la captura). Lo que cambia es cómo conviertes el raw a texto:
| Si la salida es… | Usa | Porque |
|---|---|---|
| Una TUI con posicionamiento absoluto (`claude`, `htop`, `dialog`) | `vt_render_go_tui` (modo screen) | Los "espacios" entre columnas eran movimientos de cursor; sin emular el grid las palabras se pegan (`2newMCPservers`). |
| Output secuencial línea a línea (logs, builds) | `strip_ansi_go_core` (modo stream) | No hay layout 2D que reconstruir; basta quitar los escape codes. |
| Quieres procesar los escape codes tú mismo | (ninguno — usa el raw) | El raw de `pty_capture_idle` ya los conserva. |
## Ejemplo canónico (end-to-end)
Capturar la respuesta de la CLI `claude` como texto con layout, en Go:
```go
import (
"context"
"time"
"fn-registry/functions/infra"
"fn-registry/functions/tui"
)
func main() {
ctx := context.Background()
// Teclear el prompt y pulsar Enter como pasos separados: un "\r" pegado al
// texto lo trata claude como newline literal, no como submit.
inputs := []string{"resume el README en 3 lineas", "\r"}
raw, _ := infra.PTYCaptureIdle(ctx, "claude", nil,
4*time.Second, // warmup: deja cargar la TUI
inputs, 600*time.Millisecond,
4*time.Second, // idle: corta tras 4s de silencio
60*time.Second) // maxDur: tope duro
screen := tui.VTRender(raw, 40, 120) // reconstruye el layout 2D
print(screen)
}
```
La app `claude_extract` (`apps/claude_extract`) empaqueta exactamente este flujo como CLI, con
modos `screen|stream|raw`, `--exec` para pipear a otro proceso, y `--cwd` para saltar el diálogo
de arranque de claude. Es el consumidor de referencia del grupo.
La app `claude_pipe` (`apps/claude_pipe`) va un paso más allá: añade `parse_claude_tui_go_tui`
al final del pipeline para devolver la respuesta de claude **como dato** con el mismo shape que
`claude -p --output-format json` (`--format json|text|turns`). Es la alternativa "parsea la TUI"
a `claude -p`, para cuando se quiere expresamente ir a través de la TUI en vez del stream-json.
## Fronteras
- **No es `claude -p`**: este grupo captura la TUI real (lo que se ve). Para interacción programática
limpia con la CLI `claude`, usa `claude_stream_go_core` (`claude -p --output-format stream-json`).
- **Linux/Unix only**: PTY POSIX (`creack/pty`). No Windows.
- **Sin color**: `vt_render` reconstruye texto y layout, no atributos de color.
- **Idle es heurístico**: TUIs con render periódico (spinners, relojes) no disparan el idle y caen
al `maxDur`. Para `claude` el spinner se detiene al terminar la respuesta, así que corta bien.
- **Dimensiones fijas 40×120**: el render debe usar el mismo tamaño que la captura o el wrapping no
cuadra.
## Notas
- Las dos funciones de limpieza son **puras**; solo `pty_capture_idle` es impura (lanza procesos).
Puras en los bordes, impura en el centro de la captura.
- `pty_capture_idle` no fija el cwd del hijo: para controlarlo, cambia el cwd del proceso que la
invoca antes de llamarla (lo que hace `claude_extract --cwd`).
+1
View File
@@ -12,6 +12,7 @@ Filtro MCP: `mcp__registry__fn_search query="" tag="web-proxy"`.
| [rotate_capture_flows_py_cybersecurity](../../python/functions/cybersecurity/rotate_capture_flows.md) | `mitmdump -s rotate_capture_flows.py --set rotate_min=N --set capture_dir=DIR` | Addon de mitmproxy que trocea las capturas en archivos `traffic-YYYYmmdd-HHMMSS.mitm` por ventanas de tiempo. Hace `flush()` por flujo, asi que la captura sobrevive a un `kill -9`. |
| [query_mitm_flows_bash_cybersecurity](../../bash/functions/cybersecurity/query_mitm_flows.md) | `query_mitm_flows <file_or_glob> [--filter EXPR] [--har OUT]` | Consulta capturas `.mitm` guardadas: vuelca los flujos que matchean un filtro de mitmproxy, o exporta a HAR. Acepta globs de varios archivos. |
| [launch_chromium_proxy_bash_browser](../../bash/functions/browser/launch_chromium_proxy.md) | `launch_chromium_proxy [--proxy URL] [--profile DIR] [--url URL]` | Lanza Chromium apuntando al proxy con un perfil aislado, sin contaminar la sesion normal. Maneja el CA del proxy o cae a `--ignore-certificate-errors`. |
| [tee_anthropic_sse_py_cybersecurity](../../python/functions/cybersecurity/tee_anthropic_sse.md) | `mitmdump -s tee_anthropic_sse.py` | Addon mitmproxy que intercepta el SSE de `POST api.anthropic.com/v1/messages` (la respuesta del modelo de la CLI claude) y emite el texto exacto token a token como NDJSON. Filtra la respuesta principal (`has_tools`) de las auxiliares (titulo/clasificador en haiku). Strip de `Accept-Encoding` para ver el SSE sin comprimir. Lo consume `apps/claude_wire`. |
Complementa: `port_kill_bash_infra` (limpieza de puertos ocupados).