Saltar a contenido

ADR-048: La plataforma puede apagar el asistente de una entidad sin escribir su decisión

Estado: Aceptado Fecha: 2026-10-22 Autores: Giampiero (mantenedor principal); lote D, bloque D-7 Relacionados: ADR-037 (residuo "apagado por la plataforma"), ADR-035, ADR-010


Contexto

El asistente (E18/E21) lo enciende cada entidad; si una entidad hace un mal uso o el operador debe contener un incidente, no había forma de apagarlo sin tocar la decisión de la entidad (asistente_habilitado) ni la base a mano.

Decisión

  1. El bloqueo es otra columna, no la bandera: tres columnas en public.tenants (migración global 006: bloqueo, motivo, fecha) y CHECK tenants_asistente_bloqueo_forma. El estado efectivo es asistente_habilitado AND NOT bloqueado (orpycamcp_common.tenant.estado_asistente); desbloquear devuelve a la entidad exactamente lo que había decidido.
  2. PUT /api/v1/tenants/{id}/asistente-bloqueo solo con X-Internal-Token; no está en el gateway a propósito. El operador usa scripts/asistente-plataforma.sh dentro del contenedor de tenant-service. El asiento va en la cadena de la entidad (no en una del sistema), con motivo obligatorio. Una entidad inactiva responde 409 tenant_inactivo.
  3. Quien lo obedece: knowledge-service (403 asistente_bloqueado_plataforma, evaluado antes del permiso por entidad), /config/asistente (efectivo, bloqueo_plataforma; encender bajo bloqueo = 409) y /auth/me (devuelve el efectivo; si la lectura falla, false). mcp-server lo acata por /auth/me sin cambios de código.
  4. UI: AsistenteEntidadCard muestra el aviso con fecha y motivo y deshabilita el encendido (apagar sigue permitido); /busqueda y el dock distinguen este 403 del de "deshabilitado".

Alternativas descartadas

  • Poner asistente_habilitado = false: borraría la decisión de la entidad y no se podría restituir.
  • Endpoint en el gateway con rol de plataforma: crea un rol que hoy no existe y amplía la frontera pública.

Residuos declarados

  • operador es un nombre declarado, no una identidad autenticada: el token interno acredita el canal, no la persona.
  • No hay caducidad del bloqueo.

Consecuencias

  • INTERNAL_SERVICE_TOKEN pasa a ser obligatorio en tenant-service (dev: TENANT_INTERNAL_TOKEN; producción: sin valor por defecto).