CreaRack-SL

Feature: Autenticación local del Agent — Fase 1 (Backend inerte)

Resumen

Sesión 125 (2026-06-10): primer paso del cierre de la Raíz 3 de la Auditoría Suprema. Implementación backend (totalmente inerte) de autenticación local cross-origin del Agent.

La feature se despliega en 3 fases:

  1. Fase 1 (este commit): backend + endpoints inertes + tests. Ningún cliente lo usa.
  2. Fase 2: frontend web — recoger y usar el token en requests locales.
  3. Fase 3: Agent .exe — generar, depositar y validar tokens.

Qué cambia en esta release

Backend

  • Nuevo campo: AgentInstance.local_token_enc (TextField, cifrado con Fernet).
  • Migración BD: terminal/0003_agentinstance_local_token_enc.py.
  • Dos endpoints nuevos:
    • POST /api/agent/register-local-token — Agent deposita token (auth=None, autoverificado con JWT).
    • GET /api/agent/local-token — Frontend recoge token (sesión + fleet:view + aislamiento org).
  • Schemas: AgentLocalTokenSchema en terminal/api/auth.py.
  • Cifrado seguro: CredentialManager (Fernet) garantiza que el token nunca se guarda en claro.

Visible para clientes

Ningún cambio: la feature es totalmente inerte. Ningún cliente llama a los nuevos endpoints hasta la Fase 2.

Testing

  • Suite completa: tests/api/test_terminal_local_token.py (115 LOC).
  • Cobertura:
    • Round-trip: Agent deposita, frontend recoge descifrado.
    • Autenticación: Agent JWT requerido en POST, sesión en GET.
    • Refresh tokens rechazados en POST.
    • Aislamiento cross-tenant: admin de org B no puede leer token de org A (404).
    • Sesión en GET: Agent JWT rechazado (403).
    • Permisos granulares: solo fleet:view permite leer.
    • Valores ausentes: Agent sin token aún → 404.

Propósito & Impacto

Problema

El Agent hoy no autentica requests locales. Cualquier página web puede enviar comandos a localhost:5050 sin restricción (Raíz 3 de la Auditoría Suprema).

Solución

Guardar de forma cifrada el token local del Agent. En Fase 2, el frontend lo usa en requests. En Fase 3, el Agent lo rechaza si falta o es inválido.

Impacto en seguridad

  • Inerte esta fase: cero impacto visible (endpoints existen pero nadie los llama).
  • Preparatorio: sienta las bases para Fase 2 y 3.
  • Plan Hardening E: implementa CredentialManager + Fernet para secretos en BD.

Cambios técnicos

Ficheros modificados

  • CHANGELOG.md — entrada descriptiva sesión 125.
  • RELEASE_NOTES.md — nota breve para usuarios (s125).
  • terminal/models.py — campo local_token_enc + documentación.
  • terminal/api/auth.py — 2 endpoints + helper AgentLocalTokenSchema.
  • terminal/migrations/0003_agentinstance_local_token_enc.py — migración (AddField).
  • tests/api/test_terminal_local_token.py — suite de tests (nuevo fichero).

Dependencias

  • core.security.credential_manager.CredentialManager — cifrado Fernet.
  • core.utils.get_current_org — aislamiento por org.
  • core.utils.require_perm — validación de permisos.

Schema de la DB

ALTER TABLE terminal_agentinstance ADD COLUMN local_token_enc TEXT NOT NULL DEFAULT '';

ADR & Decisiones

ADR: decision--20260610--terminal-auth-local-cross-origin

  • Almacenamiento: Fernet (simétrico, cifrado en reposo).
  • Endpoints: 2 (uno para Agent, uno para frontend).
  • Autenticación: Agent JWT en POST, sesión en GET.
  • RLS: aislamiento por organización en GET.

Versionado

Sin cambio de versión visible: la feature es inerte, no altera comportamiento del cliente.

(Próximo cambio de versión será cuando Fase 2 ó 3 active la feature.)

Fase 2 — Próximo paso

  • Frontend: actualizar lógica de conexión local para:
    1. Solicitar token vía GET /api/agent/local-token.
    2. Pasarlo en header/body a requests contra localhost:5050.
  • Alcance: cambios en la web, lógica local del navegador.

Fase 3 — Agent .exe

  • Agent: generar UUID local, depositarlo vía POST /api/agent/register-local-token.
  • Agent: validar requests que lleguen de la web (usar token).
  • Alcance: cambios en el binario del Agent (C# / TypeScript).

Véase también

  • [[decision—20260610—terminal-auth-local-cross-origin]]
  • [[entity—terminal—endpoint—register-local-token]]
  • [[entity—terminal—endpoint—get-local-token]]
  • [[entity—terminal—model—agentinstance]]
  • [[concept—security—credential-encryption]]