Manual técnico de operaciones — IA Gobernanza
Audiencia: especialistas en seguridad, DevSecOps, oficiales de cumplimiento con perfil técnico. Describe procedimientos operativos, contratos de API y semántica de cada control tal como está implementado. Donde un control es una hoja de ruta y no una capacidad actual, se indica explícitamente.
Versión 1.0 · Base URL:
https://<su-dominio>/api· Todas las rutas del plano de control exigen sesión de operador (cookiegov_session, httpOnly, SameSite=Lax, 8 h). Rutas de datos usan API key (Authorization: Bearer gov_live_*oX-API-Key).
1. Arquitectura de referencia
[Apps del cliente] ──Bearer gov_live_*──▶ /api/v1/gateway/chat/completions ──▶ Conector (Ollama/vLLM local · Fireworks · DeepSeek · …)
│ │ pre-auditoría (<50 ms) · ZK anonimización · post-auditoría ISO 42001
│ └─▶ connector_transactions (hash/métricas) · incidents · webhooks HMAC v2
[SDK aiguard / Muro Perimetral] ──X-API-Key──▶ /api/v1/public/evaluate-stream (fail-closed PII)
[Operadores] ──cookie + MFA TOTP──▶ /api/{models,policies,killswitch,connectors,threats,keys,webhooks,audit,...}
Persistencia: MongoDB (tenant-scoped por company_id) · Vault efímero ZK: Redis (REDIS_URL) o MongoDB TTLPrincipios implementados:
- Multi-tenancy por actor: toda consulta filtra por
company_idderivado de la sesión o de la API key; accesos por id a recursos ajenos devuelven 404. - Zero-Knowledge fail-closed:
/v1/public/evaluate-streamrechaza PII en claro (422PII_PLAINTEXT_REJECTED) y solo persiste hashes. El Gateway anonimiza PII hacia destinos externos con mapa cifrado efímero (TTL ≤ 300 s). - Kill Switch por consenso (anti-FP): Capa 1 regla dura · Capa 2 confianza (risk ≥ 55) · Capa 3 persistencia (≥ 3 eventos en 5 s). Las amenazas de usuario no disparan el KS por sí solas.
- Auditoría tamper-evident:
audit_eventsencadenada por SHA-256 (prev_hash→hash), verificable enGET /api/audit/verify-chain.
2. Identidad, MFA y RBAC
| Ruta | Método | Rol | Notas |
|---|---|---|---|
/auth/login | POST | — | {email,password}. bcrypt(12). Rate limit 5/min por IP+email. Si el usuario tiene MFA → {mfa_required:true, mfa_token} (JWT purpose=mfa, 5 min). |
/auth/mfa/verify | POST | — | {mfa_token, code} o {mfa_token, recovery_code} → cookie de sesión. 5 intentos/min por usuario. |
/auth/mfa/setup · /enable · /disable · /recovery-codes | POST | sesión | TOTP RFC 6238 (otplib, ventana ±30 s). Secreto cifrado AES-256-GCM con MFA_ENC_KEY; recovery codes solo como SHA-256. |
/auth/users | GET/POST/PUT/DELETE | admin | Crear/rotar rol/deshabilitar/mfa_reset:true. Último admin activo no puede degradarse. |
/auth/change-password | POST | sesión | Invalida sesiones previas (session_version). |
Enforcement MFA (`MFA_REQUIRED_ROLES=admin,operator`): un usuario de rol obligado sin MFA solo puede ejecutar GET; toda mutación devuelve 403 {code:'MFA_ENROLLMENT_REQUIRED'}. En producción el propio usuario no puede desactivar su MFA; otro admin (con MFA) lo reinicia vía PUT /auth/users/:id {mfa_reset:true}.
RBAC (`requiredRoleFor`): GET → viewer · killswitch/simulate/incidents/threats/webhooks test/connectors test → operator · resto → admin. Desactivar un Kill Switch exige admin + reason obligatorio + evento de auditoría + webhook firmado.
Rotación JWT: firma con JWT_SECRET; verificación acepta JWT_SECRET_PREVIOUS durante la ventana de rotación. Proveedor de secretos: SECRETS_PROVIDER=env|aws (AWS Secrets Manager soportado en código; no configurado en esta instalación).
3. Modelos gobernados y Kill Switch
POST /api/models {name, provider, type, risk_sector}creaai_models_registered+killswitch_configs {mode:'alert', status:'inactive', trigger_threshold:80}.PUT /api/killswitch/:modelId {status:'active'|'inactive', mode:'alert'|'block', reason}.mode:'block'marca el modeloblockedy toda evaluación/gateway devuelve bloqueo determinista. Desactivación: admin + reason.- Disparo automático:
evaluateEvent/evaluateV1/ Gateway registranrisk_events(TTL) y aplicandecideAction(layers, circuitMode): ACTION_KILLSWITCH_TRIGGER(L1∧L3, L2∧L3 o L1 aislada en motor de políticas),ACTION_REDACT_AND_SUBSTITUTE(L2),ACTION_LOG_AND_MONITOR,ACTION_ALLOW,HUMAN_ALERT_REQUIRED(circuit breaker: 100 % de la flota fallando, ≥ 2 modelos, congelación 30 s).- Cada decisión lleva
decision_hash(SHA-256 sobre inputs exactos) para anti-repudio. - Webhooks:
killswitch.activated,killswitch.deactivated.
Procedimiento de reactivación (runbook):
- Consultar
GET /api/incidentsyGET /api/threatspara la causa (last_trigger_cause). - Verificar que la causa está contenida (p. ej. API key del atacante revocada, conector corregido).
PUT /api/killswitch/:id {status:'inactive', mode:'alert', reason:'<ticket + justificación>'}como admin con MFA.- Confirmar recepción del webhook en el SIEM y verificar la cadena:
GET /api/audit/verify-chain → chain_valid:true.
4. Políticas (motor determinista)
governance_policies {name, regulation, framework, applies_to[], policy_rules}. Reglas soportadas: max_bias, max_privacy_risk, max_risk_score, max_tokens_per_request, forbidden_categories[], requires_killswitch, max_toxicity, max_semantic_drift, pii_forbidden, prompt_injection_forbidden (+injection_threshold), system_prompt_leak_forbidden, max_pii_tokens_out, applies_to_stage. La política AI Threat Shield se crea automáticamente por tenant si no existe. Cache de políticas en Mongo con invalidación por versión (policies_version).
5. Conectores de IA (modelos propios) y Gateway
5.1 Modelo de datos
ai_connectors:{name, provider, base_url, network(public|private|loopback), egress{mode: direct|direct_private|proxy, proxy_id}, api_key_enc (AES-256-GCM, CONNECTOR_ENC_KEY), api_key_hint, default_model, model_id (→ ai_models_registered), sovereignty{kind, data_leaves_perimeter, processor_jurisdiction, model_origin, risk_level, regulatory_flags[]}, governance{...}, status, last_test}.connector_egress_proxies: proxies inversos autorizados (proxy_url https,allowed_cidrs[],auth_token_enc). Requeridos para destinos privados salvoALLOW_PRIVATE_EGRESS_DIRECT=true(despliegue on-prem/demo).connector_transactions(TTL =governance.retention_days):{transaction_id, kind, latency_ms, upstream_ms, audit_ms, tokens{prompt,completion,total}, compliance_status, geopolitical_risk, data_left_perimeter, zk{anonymized,restored,unresolved,by_type}, rule, violations[], kill_switch_action, request_hash, decision_hash}. Nunca texto.
5.2 Reglas de gobernanza por conector (PUT /api/connectors/:id/governance)
| Campo | Default | Efecto |
|---|---|---|
pii_filter_lfpdppp | true | Escaneo PII (PAN, CURP, RFC, CLABE, CPF, RUT, EMAIL, PHONE). |
zk_anonymize_external | true | Anonimización reversible hacia destinos externos (GovernanceZKEngine). |
prompt_injection_detection | true | Threat Shield determinista + normalización anti-evasión (base64, leetspeak, zero-width, NFKC). |
kill_switch_threshold | 80 | Sensibilidad: solo riesgos ≥ umbral alimentan el consenso (Bajo 90 · Medio 80 · Alto 65). |
block_on_geopolitical_risk | alto | Bloquea egreso de PII sin anonimizar hacia procesadores con ese riesgo o superior. |
post_audit_enabled · post_audit_block_threshold | true · 75 | PostAuditEvaluator; riskScore > 75 o violación crítica → BLOCK_KILL_SWITCH. |
kill_switch_on_output_leak | true | Violación crítica en la salida (fuga de secreto/system prompt, jailbreak exitoso) → KS inmediato del modelo vinculado. |
forbidden_keywords[] · confidential_terms[] | [] | Lista del admin; los términos confidenciales se persisten solo como SHA-256 (confidential_terms_hashes). |
max_tokens_per_request · retention_days | 8192 · 90 | Límite (413) y retención de la bitácora de transacciones. |
5.3 Anti-SSRF (analyzeBaseUrl)
Solo http(s); sin credenciales embebidas; resolución DNS en alta y en cada llamada (anti-rebinding); clases: public, private (RFC1918/fc00::/7), loopback, blocked (169.254/16 metadata, 0/8, 100.64/10 CGNAT, multicast, fe80::/10, fd00:ec2::). blocked nunca se permite. Público sin TLS → advertencia. Redirecciones no se siguen (redirect:'manual').
5.4 Gateway OpenAI-compatible
POST /api/v1/gateway/chat/completions (alias POST /api/v1/chat/completions) · GET /api/v1/gateway/models.
Selección de conector: header X-IAG-Connector: <id|nombre>, o model = "<nombre conector>", o model = "<conector>/<modelo upstream>"; con un único conector activo se usa por defecto y model pasa como upstream.
Secuencia:
- Auth Bearer (scope
gateway:invokeoevaluate:stream), rate limit por key (X-RateLimit-*). - Corto circuito: conector
disabled→ 403CONNECTOR_DISABLED; KSactive+blocko modeloblocked→ 403KILL_SWITCH_ACTIVE. - Pre-auditoría síncrona (sin I/O): tokens (413
MAX_TOKENS_EXCEEDED), Threat Shield (score ≥ 0.6 → 403PROMPT_THREAT_BLOCKEDconrule{id,name,framework,severity,matched_patterns},kill_switch{triggered,consensus_action,layers}), PII, geopolítico (403GEOPOLITICAL_PII_EGRESS), anonimización ZK (mapa →TokenCacheService.saveSessionMap(tx_gober_<uuid>), TTL 300 s). - Forward al upstream (
Authorization: Bearer <api_key descifrada>), timeout de cabeceras 120 s.stream_options.include_usagese añade cuando el proveedor lo soporta. - Retención completa de JSON o SSE: límite de 2 MB y 120 s de lectura del cuerpo. No se entrega contenido mientras el proveedor genera la respuesta. SSE requiere
finish_reasony[DONE]; cierre incompleto, JSON inválido, tamaño excesivo, timeout o canal no auditable → error, nuncaAPPROVED. - Post-auditoría de las elecciones completas, texto de razonamiento/rechazo y llamadas textuales a herramientas. Términos prohibidos, PII residual o tokens inventados bloquean la salida. Los detectores siguen siendo deterministas, no universales. Sólo después se restauran tokens conocidos; borrado del mapa al terminar, incluso en error o cancelación.
- Entrega JSON o envoltura SSE posterior a auditoría, sin streaming de texto en tiempo real. Header
X-IAG-Delivery-Mode: buffered-audited, metadataiag_governance.delivery_mode; un bloqueo devuelve HTTP 403 antes de entregar texto del proveedor. Un cliente SSE debe manejar errores JSON no-200.
Estados de compliance_status: APPROVED, BLOCKED_INJECTION, BLOCKED_OUTPUT, BLOCKED_GEOPOLITICAL, BLOCKED_KILL_SWITCH, BLOCKED_POLICY, UPSTREAM_ERROR, CLIENT_ABORTED.
5.5 GovernanceZKEngine y TokenCacheService
- Tokens
[CURP_n],[RFC_n],[FINANCIAL_n](tarjeta con Luhn, CLABE),[PHONE_n],[EMAIL_n],[NAME_n](honoríficos e introductores en español). Mismo valor → mismo token; índices ya presentes en el texto se reservan; cada valor cifrado AES-256-GCM con IV aleatorio y AAD = token (impide intercambiar entradas). Clave por tenant:HKDF(CONNECTOR_ENC_KEY, company_id); nunca se persiste. - Vault:
REDIS_URL(driver oficialredisv4, reconexión con backoff,SET NX EX ≤300) con respaldo MongoDB TTL (zk_token_maps). Estado:GET /api/public/status → hardening.zk_token_cache. - Métrica objetivo: anonimizar+desanonimizar < 15 ms; pre-auditoría < 50 ms. Observado en pruebas internas:
audit_ms≈ 1–5 ms.
5.6 Integración de una aplicación cliente
export OPENAI_BASE_URL=https://<dominio>/api/v1/gateway
export OPENAI_API_KEY=gov_live_********
# Cualquier SDK OpenAI-compatible funciona: model = nombre del conector
curl $OPENAI_BASE_URL/chat/completions -H "Authorization: Bearer $OPENAI_API_KEY" -H 'Content-Type: application/json' \
-d '{"model":"DeepSeek R1 Local","stream":true,"messages":[{"role":"user","content":"..."}]}'Recomendado: enviar X-IAG-User-Ref: <id opaco del usuario final> para análisis de comportamiento (burst/probing/extracción) sin exponer identidad.
5.7 MOCK de pruebas (solo DEMO_MODE=true)
/api/mock-llm/v1/{models,chat/completions} — OpenAI-compatible, soporta stream. El prompt simula_fuga produce una salida maliciosa (token inventado + jailbreak) para ejercitar la post-auditoría. No existe en producción.
5.8 Vista previa de repositorios de agentes — SIMULADA (MOCK)
Este panel no tiene un escáner ni conexión a GitHub/GitLab. No audita repositorios reales ni acredita cumplimiento.
GET /api/agents/status(sesión): informaintegration_status:not_connected,real_audit_available:false,audited_repositories:0y si el usuario puede cargar ejemplos.GET /api/agents/repos(sesión): array de muestras condata_source:demo,is_demo:true,verification_status:simulated; sin modo demo devuelve[]. Los registros históricos sin procedencia no se muestran; no se eliminan.POST /api/agents/seed(admin y controles MFA existentes, sóloDEMO_MODE=true): carga explícita de ejemplos idempotente, sin borrar registros. Fuera de demo está deshabilitado (404 tras superar autenticación/autorización).- Abrir o actualizar el panel no crea datos. Sus porcentajes y conflictos se etiquetan como ejemplos, sin commits ni sincronizaciones reales. Sin muestras no se calcula un índice de cumplimiento.
6. Gobernanza agéntica: propuestas y autoridad
GET /api/agent-policiesdevuelve la configuración efectiva y, separadamente,pending_change,pending_action,pending_idyrevision. Una edición pendiente no retira la regla vigente del evaluador.- Con Cuatro Ojos, crear/editar/pausar/reactivar/eliminar requiere validar por otro
gov_admin.POST /api/agent-policies/:id/validatey/reject-changerecibenpending_idy credencial de reautenticación; el cliente debe enviarrevisionconocida para evitar una vista obsoleta. No se sustituye una propuesta pendiente por otra. - Desactivar Cuatro Ojos mediante
PUT /api/governance/settingsgenera propuesta y conservadual_control_enabled:true. Se resuelve conPOST /api/governance/settings/validateo/reject-change,pending_idy reautenticación; validación requiere otro administrador. - Aprobar/rechazar
/api/agent-approvals/:id/{approve,reject}exige el rol snapshot de la regla.gov_adminpuede resolver ambas categorías;gov_approverno puede resolver una reservada a admin. El cargo humano descriptivo no se usa como permiso. - La resolución usa comparación atómica
status:PENDINGy expiración: un único ganador, perdedor409 DECISION_CONFLICT. Actualizar la bandeja, no repetir una acción ciegamente. Poll:GET /api/v1/agent/decision/:id(singular), estados en mayúsculas yexecution_tokensólo al aprobar. - No existe endpoint de consumo/verificación de uso único del execution_token; la integración ejecutora debe respetar la autorización.
- Kill-switch: un disparo no autoriza cambiar
mode,auto_triggerotrigger_threshold. Para operator, omitir esos campos incluso si desea conservar su valor; su presencia devuelve 403. Sólo admin configura.alertno detiene tráfico yblocksólo protege el camino integrado. - Evidencia pública:
GET /api/public/capabilitiesy/trust#evidencia; registros documentales curados, no telemetría en vivo. Los campos sin prueba registrada mantienenlast_verification:null.
6b. AI Threat Shield
Detectores deterministas (Capa 1) con pesos: ignore_instructions, reveal_system_prompt, role_override, dan_jailbreak, delimiter_injection, exfil_instruction, dump_data, encoded_payload, tool_abuse; análisis de comportamiento por user_ref (burst ≥ 30/min, tasa de violaciones, plantillas repetidas → MODEL_EXTRACTION_SUSPECTED, tokens PII en salida → DATA_EXFILTRATION_ATTEMPT); huella de system prompt por shingles hasheados (PUT /api/models/:id/system-prompt-fingerprint). Mapeo OWASP LLM Top 10 / MITRE ATLAS. Incidentes THREAT_DETECTED con dedup 10 min; webhook threat.detected con pistas OCSF (class_uid 2004).
Operación: GET /api/threats, PUT /api/threats/:id/ack, PUT /api/threats/:id/resolve {resolution, note}, POST /api/threats/simulate (operator, DEMO).
7. API pública, SDK y Muro Perimetral
POST /api/v1/public/sessions(scopesessions:create) →session_tokenpor modelo/usuario.POST /api/v1/public/evaluate-stream {session_token, text_payload, stage: INPUT|OUTPUT}(scopeevaluate:stream). Tokens[TOKEN_<TIPO>_<HASH>]del SDK se aceptan como PII anonimizada; PII en claro → 422 fail-closed (ZK_FAIL_CLOSED=true).GET /api/v1/public/healthcheck→ heartbeat (Dead Man’s Switch: ausencia > 60 s →stale, incidente DMS con dedup 15 min).- SDK Python
aiguard(/sdk):GovernanceClient,RedactionEngine,RedisTokenVault, mTLS opcional,threats.py. Muro Perimetral (/deploy/perimeter-wall): proxy K8s con redacción local y vault Redis. No publicado en PyPI; se entrega como código.
8. API keys y Webhooks
POST /api/keys {name, scopes[], expires_in_days, rate_limit_per_min}→ la key en claro se muestra una sola vez; se persistekey_hashSHA-256 (en DEMO ademásplain, exclusivamente para evaluación).DELETE /api/keys/:idrevoca de inmediato. Scopes:sessions:create, evaluate:stream, metrics:write, metrics:read, policies:read, policies:write, killswitch:read, killswitch:override, logs:read, keys:manage, gateway:invoke.- Webhooks HMAC v2: cabeceras
X-IAG-Timestamp,X-IAG-Nonce,X-IAG-Signature: v2=HMAC-SHA256(timestamp.nonce.body); ventana ±5 min, anti-replay por nonce, reintentos 2/4/8/16/32 s. Eventos:killswitch.activated|deactivated,policy.violation,threat.detected. Verificación de ejemplo en/docs/WEBHOOKS.md.
9. Auditoría y evidencia
GET /api/audit?limit=(admin) — eventos conseq,prev_hash,hash, actor, IP,detailssaneados (claves sensibles redactadas).GET /api/audit/verify-chain— recalcula la cadena;chain_valid:falseimplica alteración o pérdida.- Logs de evaluación:
monitoring_logs(hash de entrada, scores, decisión, políticas violadas, latencia). Transacciones del Gateway:connector_transactions.
9b. Plataforma: gate de visitantes y Super Admin
- Gate (middleware.js): toda ruta pública (landing, /trust, /status, /manual, /docs) exige una cookie válida:
visitor_pin(PIN),gov_session(operador) osuper_session. Excluidos/api/*,/gate,/superadmin,/legal/*,/?view=dashboard(sólo formulario de login).VISITOR_GATE_ENABLED=falselo desactiva. Es un control de exposición de información comercial, no una frontera de seguridad del plano de control (que sigue protegido por sesión + RBAC + MFA). - PINs:
visitor_pinsguarda SHA-256(pin | JWT_SECRET); vigencia y usos máximos; rate limit 10 verificaciones/min por IP; cada intento queda engate_events(TTL 90 d). - **Super Admin (
/superadmin,/api/superadmin/*): cuenta de plataforma (`platform_admins`, bcrypt, seed desde `SUPERADMIN_PHONE`/`SUPERADMIN_PASSWORD`; se recomienda cambiarla desde la UI: ≥ 12 caracteres). Funciones: alta de empresas (+ admin inicial), edición de plan/contrato/contactos, activar/suspender servicio** (motivo obligatorio; cierra sesiones del tenant víasession_version), inactivación automática al vencercontract_end(auto_suspend_on_expiry), métricas por tenant, generador y revocación de PINs, bitácora de accesos. Efecto de suspensión: login →403 SERVICE_SUSPENDED, API keys → 403, Gateway → 403, rutas del plano de control → 403.
10. Runbooks de anomalías
| Señal | Diagnóstico | Acción |
|---|---|---|
KILL_SWITCH_ACTIVE masivo en gateway | Consenso disparado o activación manual | Revisar last_trigger_cause, GET /api/threats, transacciones del conector; reactivar con reason. |
POST_AUDIT_BLOCK recurrente en un conector | Modelo manipulado/comprometido o lista de prohibidos demasiado amplia | Revisar violations; si RESIDUAL_LEAK_* o SYSTEM_PROMPT_* tratar como compromiso del modelo: rotar system prompt, revisar fine-tuning/proveedor. |
GEOPOLITICAL_PII_EGRESS | Política de transferencia bloqueó PII | Confirmar zk_anonymize_external:true o mover carga a conector local; documentar decisión legal. |
UPSTREAM_ERROR sostenido | Endpoint caído, TLS, API key caducada, proxy de egreso | POST /api/connectors/:id/test; revisar last_test.error; rotar api_key vía PUT. |
PII_PLAINTEXT_REJECTED | Cliente envía PII sin redactar | Desplegar SDK/Muro; revisar X-ZK-Redacted (si venía true → bypass de redacción: ajustar patrones). |
HUMAN_ALERT_REQUIRED | Circuit breaker: toda la flota falla a la vez | Posible falso positivo global o incidente mayor; decisión humana; el modo vuelve a AUTO tras 30 s. |
Heartbeat stale / incidente DMS | Cliente sin latido > 60 s | Verificar disponibilidad del cliente y conectividad saliente hacia /api/v1/public/healthcheck. |
Webhook failing | Receptor 4xx/5xx o firma rechazada | Validar secreto compartido y reloj (ventana ±5 min); revisar nonce store del receptor. |
chain_valid:false | Alteración/pérdida en audit_events | Incidente de seguridad: preservar la colección, comparar con respaldo, investigar accesos a la BD. |
SERVICE_SUSPENDED / contract_expired | Super Admin suspendió el tenant o venció contract_end | Regularizar contrato; Super Admin → Activar o extender contract_end. |
MFA_ENROLLMENT_REQUIRED en automatizaciones | Cuenta de servicio con rol admin/operator sin MFA | Usar API keys para integraciones (no sesiones); las sesiones humanas requieren MFA. |
11. Configuración y despliegue (variables relevantes)
MONGO_URL, DB_NAME, JWT_SECRET (+JWT_SECRET_PREVIOUS), MFA_ENC_KEY, MFA_REQUIRED_ROLES, CONNECTOR_ENC_KEY, ALLOW_PRIVATE_EGRESS_DIRECT, REDIS_URL, ZK_MAP_TTL_SEC, ZK_FAIL_CLOSED, SECRETS_PROVIDER/AWS_SECRETS_ID, DEMO_MODE (false en producción: desactiva cuentas demo, /seed, /demo-credentials, mock LLM y la auto-desactivación de MFA).
Checklist de salida a producción: DEMO_MODE=false · claves hex-64 dedicadas · ALLOW_PRIVATE_EGRESS_DIRECT=false salvo on-prem · Redis con TLS para el vault ZK · respaldos de MongoDB verificados · receptor de webhooks validado · revisión legal de Términos/Privacidad · pentest externo (pendiente en la hoja de ruta).
12. Límites conocidos (transparencia)
- Detección PII/amenazas es determinista (regex + heurísticas); no hay clasificador ML en producción (hoja de ruta).
- La evaluación de riesgo geopolítico es orientativa; no constituye asesoría legal.
- No existen certificaciones SOC 2 / ISO 27001 / ISO 42001 de la plataforma; el diseño está alineado a esos marcos.
- Redis y AWS Secrets Manager están soportados en código pero no aprovisionados en esta instalación.