# ¿Puede un rastro de auditoría de aprobaciones demostrar quién aprobó una acción del agente?

Un registro de aprobación que solo dice «approved» no responde a la pregunta importante después de que un agente toque producción: ¿quién permitió qué acción, con qué autoridad y qué ocurrió después? Registra un momento tranquilizador en una interfaz y luego deja que la persona que investiga deduzca el resto.

Un rastro de auditoría de aprobaciones debe conservar la cadena que va desde un proceso del agente hasta una decisión humana, desde esa decisión hasta el uso de una credencial y desde la credencial hasta una solicitud HTTP o un comando SSH completado. Si son registros separados sin vínculos duraderos, el revisor puede construir una historia plausible. No puede demostrarla.

La diferencia se vuelve dolorosa cuando la acción tuvo éxito y nadie recuerda haberla aprobado, cuando un agente se reinició a mitad de una tarea o cuando alguien pregunta si un clic y una confirmación de Touch ID significaban lo mismo. No es así. Tratarlos como equivalentes produce un registro que parece completo hasta la primera revisión seria.

## Un evento de aprobación debe responder a algo más que «sí»

Un evento de aprobación útil indica qué aprobó la persona, por qué el sistema lo solicitó, cómo se tomó la decisión y dónde termina la autorización. El clic visible en el botón es solo uno de los campos del evento.

Registra estos datos cuando se produzca la decisión:

- Un identificador de aprobación único y una marca de tiempo del evento con su desfase horario.
- El método de aprobación, como `click` o `touch_id`.
- La cuenta local u otra identidad conocida de quien aprueba, junto con las pruebas usadas para atribuirla.
- El alcance de la autorización: una sesión o un único uso de una credencial para una llamada.
- La solicitud que provocó el aviso, identificada mediante un identificador estable de solicitud o llamada.

No escribas `user=alex` solo porque una máquina tenga una cuenta llamada Alex. Puede ser la mejor atribución disponible y aun así merece la pena registrarla, pero llámala por su nombre: contexto de la cuenta local. Si una solicitud biométrica tuvo éxito, registra que una biometría inscrita en ese dispositivo autorizó el evento. Estas afirmaciones son más sólidas que «alguien llamado Alex lo aprobó», porque no fingen que el registro sabe más de lo que realmente sabe.

NIST SP 800-171 Rev. 3 ofrece un punto de partida razonable para el contenido de auditoría: marcas de tiempo, direcciones de origen y destino, identificadores de usuarios o procesos, descripciones de eventos, controles de acceso aplicables y resultados. También señala que los registros detallados pueden incluir comandos privilegiados y las identidades individuales que están detrás de cuentas compartidas. Es un buen mínimo para las acciones de un agente, no un diseño terminado. Un flujo de aprobación de agentes necesita que las relaciones entre la decisión, la credencial y la llamada sean datos de primera clase.

El error más fácil es registrar la aprobación como un atributo de la acción final, por ejemplo `approved=true`. Eso reduce un evento a una etiqueta. Se pierde el tiempo entre la solicitud y la decisión, el origen de la decisión, el alcance del consentimiento y cualquier revocación posterior. También se vuelve imposible distinguir la aprobación de una persona de una autorización predeterminada, una autorización almacenada en caché o una regla de automatización.

Una decisión debe tener su propio registro incluso cuando la respuesta sea negativa. Una solicitud rechazada puede explicar por qué un agente no pudo desplegar. Una solicitud caducada puede explicar por qué el agente reintentó. Un almacén bloqueado puede explicar por qué el sistema se negó a realizar una llamada de red. Son eventos materialmente distintos y, más adelante, el revisor no debería tener que deducir la diferencia a partir de la ausencia de un registro de éxito.

## Cinco identidades mantienen la línea temporal honesta

Una línea temporal completa necesita cinco identidades separadas. Combinarlas ahorra columnas en una tabla y destruye el significado durante una investigación.

La primera es el **proceso del agente**. Registra un identificador del proceso o de la ejecución, el ejecutable o la autoridad de firma de código que lo inició, la hora de inicio y la hora de finalización. La persona debe poder responder: «¿Qué programa en ejecución solicitó esto?». El nombre de un proyecto o una transcripción de chat no bastan. Dos copias del mismo agente de programación pueden ejecutarse al mismo tiempo y una puede ser inofensiva mientras la otra apunta a un repositorio diferente.

La segunda es la **sesión**. Una sesión es la relación limitada entre un proceso del agente y el gateway. Debe tener su propio identificador porque un proceso puede realizar muchas llamadas y porque la autorización de sesión suele aplicarse a varias llamadas. Cuando el proceso termina, la sesión debe terminar. Si después comienza un proceso nuevo, debe crear una sesión nueva aunque tenga el mismo ejecutable, la misma cuenta local y la misma descripción de la tarea.

La tercera es el **contexto de quien aprueba**. Incluye la cuenta del dispositivo, cualquier usuario autenticado de la aplicación y el método de aprobación. No hagas que el campo de aprobador contenga datos que no puede respaldar. `local_account=maya`, `method=touch_id` y `device_id=...` son claros. `human=maya` afirma más. En algunos entornos esa afirmación es razonable; en otros, una estación de trabajo compartida o un escritorio desbloqueado la invalida de inmediato.

La cuarta es la **referencia de la credencial**. Identifica la autoridad que usó el gateway, no el secreto en sí. Normalmente bastan para revisar la actividad un identificador opaco estable de credencial, una etiqueta legible, el canal y el tipo de credencial. Un token bearer no es un campo de auditoría. La huella de una clave privada SSH también puede convertirse en contexto sensible, así que decide si tus investigadores la necesitan antes de extenderla por los registros habituales.

La quinta es la **operación ejecutada**. En HTTP, incluye la identidad resuelta del destino, el método de la solicitud, la ruta normalizada, los datos no secretos seleccionados de la solicitud, el estado de la respuesta y los tiempos. En SSH, incluye la identidad del host, la cuenta remota, el comando o un resumen criptográfico del comando aprobado, el estado de salida y los tiempos. El evento debe indicar qué se ejecutó, no solo qué se solicitó.

Estas identidades forman un grafo, no una fila plana:

```text
agent_process
  -> session
    -> approval_decision
      -> credential_use
        -> executed_call
```

Una pantalla de actividad plana puede mostrar ese grafo como una sola línea cuando la persona necesita rapidez. Conserva los vínculos subyacentes de todos modos. La pantalla sirve para revisar el trabajo de un día. Los identificadores sirven para quien tenga que explicar una llamada seis semanas después.

## Un clic y Touch ID son pruebas diferentes

Un clic registra la interacción con un control de aprobación en la interfaz de usuario actual. Touch ID registra una autorización biométrica correcta a través del sistema operativo, además de la interacción que la inició. Ambos pueden autorizar una acción. No deben compartir un valor impreciso como `approved_manually`.

Usa un campo de método explícito con un conjunto controlado de valores. Por ejemplo:

```json
{
  "approval_id": "apr_01J8K4VY5Q",
  "occurred_at": "2026-07-22T14:18:06.184Z",
  "decision": "approved",
  "method": "touch_id",
  "approver": {
    "local_account": "maya",
    "identity_assurance": "device_account_and_biometric"
  },
  "scope": "credential_use",
  "session_id": "ses_01J8K4TE0M",
  "requested_call_id": "call_01J8K4VPM2"
}
```

Los nombres exactos de los campos no son sagrados. La separación sí lo es. `method` indica cómo se completó la aprobación. `identity_assurance` indica qué puede afirmar responsablemente el sistema sobre la persona. `scope` indica qué autorizó la decisión. `requested_call_id` vincula la aprobación con una solicitud que ya existía antes de que la persona viera el aviso.

Un clic puede ser la opción adecuada para una confirmación sencilla, especialmente cuando la persona ya está observando el trabajo del agente. Touch ID añade un paso de confirmación local más sólido para una operación sensible, pero no proporciona por arte de magia una identidad corporativa, un motivo para la decisión ni una aprobación de todas las llamadas posteriores. Si un equipo necesita la aprobación de una persona identificada mediante un proveedor de identidad externo, necesita un flujo que registre la afirmación de ese proveedor. No tomes prestada esa garantía de un evento biométrico local.

El error contrario es igual de grave: tratar Touch ID como algo decorativo. Si una acción exigía aprobación biométrica y el registro reduce el evento a `approved=true`, ya no puede demostrar que el control más estricto se ejecutó. La revisión pierde pruebas que podrían separar una confirmación deliberada de un clic accidental en una solicitud amplia de sesión.

Registra con cuidado los intentos biométricos fallidos. Un rastro de auditoría normalmente debe saber que la acción solicitada no recibió aprobación, pero rara vez necesita cada fallo de autenticación del nivel del sistema operativo. Un evento útil es `decision=denied_or_cancelled`, `method=touch_id` y un motivo como `user_cancelled` cuando la plataforma permita distinguirlo. No conviertas un gateway de acciones en un recopilador de telemetría biométrica.

## El consentimiento de sesión y el consentimiento por llamada tienen alcances distintos

La autorización de sesión concede a un proceso limitado del agente permiso para operar después de que una persona revise la identidad del proceso. La aprobación por llamada concede consentimiento para un uso de credencial y una operación. Llamar «aprobación» a ambas cosas sin registrar el alcance hace que la línea temporal posterior resulte engañosa.

Imagina un proceso del agente que comienza a las 09:00. El gateway muestra una tarjeta de autorización que identifica la autoridad de firma de código del proceso. Un desarrollador hace clic en aprobar. A las 09:20, el agente realiza una solicitud HTTP con una credencial cuya configuración no exige confirmación por llamada. Esa llamada puede permitirse porque la sesión sigue autorizada. La línea temporal correcta muestra dos hechos separados:

1. A las 09:00, el desarrollador aprobó la sesión `ses_...` durante la vida de ese proceso.
2. A las 09:20, esa sesión usó la credencial `cred_...` para realizar la llamada `call_...`.

No debe crear una aprobación ficticia de las 09:20. El desarrollador no vio ni aprobó esa llamada exacta. La autorización anterior la cubría.

Ahora cambia un ajuste: la credencial exige aprobación en cada uso. A las 09:20, el gateway vuelve a preguntar y el desarrollador aprueba con Touch ID. El nuevo evento debe apuntar a `call_...`, indicar `scope=credential_use` e incluir `method=touch_id`. La aprobación de sesión sigue siendo relevante porque explica por qué el agente pudo llegar a la solicitud de la credencial. No sustituye la segunda decisión.

Esta diferencia importa especialmente cuando un agente realiza una llamada inesperada al final de una sesión. Si el registro dice «approved» junto a ella, el revisor necesita saber si significa que una persona aprobó el ejecutable treinta minutos antes o si aprobó ese uso concreto de la credencial tres segundos antes. Las consecuencias para el diseño de los avisos, la configuración de las credenciales y la respuesta a incidentes son muy distintas.

No resuelvas la ambigüedad haciendo que cada llamada requiera aprobación. Esa recomendación es popular porque parece segura y produce una cantidad tranquilizadora de registros. También acostumbra a las personas a aprobar avisos repetitivos sin leerlos y luego les impide distinguir la única llamada excepcional de las rutinarias. Activa la aprobación por llamada para las credenciales cuyo uso necesite una confirmación humana nueva. Mantén activada de forma predeterminada la autorización de sesión para vincular el proceso del agente a un límite de aprobación sujeto a responsabilidad.

Una revocación también necesita alcance. Si un operador revoca una sesión, registra el evento de revocación contra esa sesión e indica la hora efectiva. No sobrescribas la aprobación anterior. Si un usuario desactiva o elimina una credencial, registra ese cambio por separado. Una línea temporal de auditoría debe mostrar por qué una llamada posterior fue denegada sin reescribir el historial para hacer desaparecer la autorización anterior.

## Los registros de credenciales deben identificar la autoridad sin exponerla

El registro de uso de credenciales es donde muchos equipos hacen un intercambio peligroso: añaden material secreto para facilitar una investigación. Es un mal trato. Los registros se copian, indexan, exportan y conservan más tiempo que el proceso que los generó. Un secreto en un diario de actividad convierte a cada lector del registro en poseedor de una credencial.

Asigna a cada credencial almacenada un identificador opaco e inmutable, como `cred_01J8K...`. Combínalo con una etiqueta que ayude a reconocer su finalidad, como `payments-readonly` o `staging-deploy`. Registra el canal y el modo de inyección, por ejemplo `http_bearer`, `http_custom_header` o `ssh_key`. Así el investigador obtiene suficiente contexto para formular la pregunta correcta sin copiar la clave en el registro.

Un evento práctico de uso de credenciales puede verse así:

```json
{
  "credential_use_id": "use_01J8K4WHD7",
  "occurred_at": "2026-07-22T14:18:06.221Z",
  "credential": {
    "id": "cred_01J7ZB7F8P",
    "label": "inventory-production",
    "channel": "http",
    "injection": "bearer"
  },
  "session_id": "ses_01J8K4TE0M",
  "approval_id": "apr_01J8K4VY5Q",
  "call_id": "call_01J8K4VPM2",
  "secret_exposed_to_agent": false
}
```

El campo `secret_exposed_to_agent` puede parecer redundante cuando el diseño del gateway lo garantiza. Consérvalo si la línea temporal puede incluir varias rutas de ejecución o migraciones. Hace que la propiedad de seguridad se pueda inspeccionar en el mismo registro que la acción. Si todas las rutas compatibles ofrecen la misma garantía, el campo puede quedar implícito en el diseño del sistema y documentarse una sola vez.

Separa la selección de credenciales de su uso. Un agente puede solicitar una credencial por su etiqueta, pero no se ha usado ninguna credencial hasta que el gateway comienza la operación saliente. Esto importa en las denegaciones. Si Touch ID se cancela antes de que la solicitud salga de la máquina, escribe una llamada intentada y un evento de aprobación denegada. No escribas un evento correcto de uso de credencial. De lo contrario, el recuento de auditoría afirmará que se usó una credencial de producción cuando no fue así.

En SSH, evita tratar un alias de host como la identidad completa del destino. `prod-db` es legible, pero los alias pueden cambiar. Registra el destino configurado y las pruebas de identidad del host que verifique tu flujo de conexión. Si el agente solicitó `prod-db` pero el destino resuelto era diferente, esa diferencia pertenece al registro de ejecución. Es exactamente el tipo de detalle que importa después de un despliegue fallido.

## La llamada ejecutada demuestra que la acción ocurrió

La aprobación demuestra el consentimiento. La selección de la credencial demuestra la autoridad prevista. Solo un registro de ejecución indica si el gateway intentó realizar la operación en el exterior y qué resultado recibió.

En las llamadas HTTP, registra la operación de forma normalizada. Conserva el método de la solicitud, el origen del destino o la identidad del servicio, la ruta canónica, los nombres seleccionados de los campos de consulta cuando sean útiles, el estado de la respuesta, las marcas de tiempo de inicio y finalización y una referencia al resultado. Decide deliberadamente qué campos de solicitud y respuesta es seguro conservar. Los encabezados de autorización, las cookies, los valores con forma de token, los cuerpos completos de las solicitudes y los cuerpos sin procesar de las respuestas no deben llegar a una línea temporal general de actividad.

Un resumen criptográfico de la solicitud puede ayudar a demostrar que el contenido aprobado y el contenido ejecutado coincidían, pero solo si defines exactamente sus datos de entrada. Aplicar un hash a un cuerpo JSON sin normalizar el orden de los campos crea discrepancias falsas. Aplicar un hash a un cuerpo que contiene un valor pequeño y predecible aún puede ayudar a un atacante a confirmar sus conjeturas. Usa un resumen criptográfico para correlacionar la integridad cuando el contenido ya esté protegido en otro lugar, no como sustituto universal de la gestión del contenido.

En SSH, registra la cuenta remota, la identidad del destino, la representación del comando, el estado de salida y las horas de inicio y finalización. Una línea de comando completa puede contener secretos en asignaciones de entorno, URL temporales o argumentos. Una solución razonable es guardar un comando renderizado seguro para la revisión habitual y una representación completa protegida o un resumen criptográfico para la investigación. No afirmes que un resumen es una prueba legible. Indica que dos valores coinciden, pero no dice al revisor qué hizo el comando.

RFC 5424 separa la marca de tiempo y la identidad del mensaje de los datos estructurados porque los analizadores necesitan campos fiables, no prosa que tengan que interpretar. Su formato de marca de tiempo también lleva un desfase horario y permite fracciones de segundo. No necesitas emitir syslog, pero la lección de diseño se mantiene: conserva estructurados los tipos de evento y los campos de correlación, y reserva el texto humano para las explicaciones.

Usa tipos de evento distintos. `call.requested`, `call.dispatched`, `call.completed` y `call.failed_before_dispatch` dicen más que un evento `call` sobrecargado cuyo campo de estado cambia de significado. Los registros adicionales permiten responder si se produjo un tiempo de espera de red después de inyectar la credencial, si una validación local bloqueó primero la solicitud y si el servicio remoto devolvió una respuesta.

El tiempo por sí solo no puede establecer el orden entre máquinas. Usa marcas de tiempo UTC con desfases y conserva un número de secuencia monotónico dentro de cada registro de auditoría local. Si la API remota devuelve su propio ID de solicitud, guárdalo como valor de correlación remoto. Así el investigador puede comparar la línea temporal local con los registros del proveedor sin fingir que los relojes coinciden a la perfección.

## Una línea temporal rota se oculta en los registros normales de éxito

Imagina un agente de despliegue que recibe la aprobación de sesión a las 10:02. Lee un repositorio, prepara una versión y llama a un endpoint de despliegue de producción a las 10:17. El endpoint acepta la solicitud. A las 10:18, el desarrollador advierte que se seleccionó el entorno equivocado.

Un registro débil contiene esto:

```text
10:02 approved agent
10:17 deployment API call succeeded
```

Ese registro casi no responde a nada. ¿La llamada de las 10:17 estaba cubierta por la aprobación de las 10:02? ¿La credencial exigía un segundo aviso? ¿Qué proceso hizo la llamada? ¿El agente usó la credencial de despliegue prevista o un token más amplio? ¿El sistema envió la solicitud a producción o un redireccionamiento o un error de configuración la llevó allí? ¿La persona hizo clic en aprobar, usó Touch ID o nunca vio un aviso específico para la acción?

Una línea temporal útil se lee así:

```text
10:02:11  session.opened       ses_71  process=proc_44 signer=known_authority
10:02:14  approval.approved    apr_02  method=click scope=session session=ses_71 account=maya
10:17:03  call.requested       call_88 POST deploy.example/release target=production session=ses_71
10:17:04  credential.selected  use_53  credential=cred_prod_deploy call=call_88
10:17:04  call.dispatched      call_88 destination=deploy.example
10:17:06  call.completed       call_88 status=202 remote_request=req_914
```

Este registro puede establecer que el agente tenía una autorización de sesión válida, pero no recibió una aprobación específica para la llamada. No demuestra que el despliegue fuera deseado. Aporta pruebas sobre el funcionamiento del control. Después, el equipo puede decidir si la credencial de producción debe exigir aprobación por llamada, si el aviso debe mostrar con más claridad el entorno de destino o si el agente no debería tener acceso a esa credencial.

Ahora añade una confirmación por llamada. La entrada adicional correcta no es otra línea genérica `approved`. Debe indicar la llamada que aprobó y su alcance:

```text
10:17:04  approval.approved    apr_03  method=touch_id scope=credential_use
          session=ses_71 call=call_88 credential=cred_prod_deploy account=maya
```

Si el agente reintenta después de un tiempo de espera, asígnale un ID de llamada nuevo. Puede reutilizar una autorización de sesión existente, pero una regla de credencial por llamada debe crear una nueva solicitud de aprobación para el reintento. Registrar el reintento como si fuera la llamada original crea la falsa impresión de que una confirmación cubrió dos acciones externas.

## La integridad de la auditoría necesita una afirmación separada

Un registro de auditoría puede ser suficientemente completo para explicar una secuencia y aun así ser fácil de alterar. Puede estar pensado como de solo anexado y permitir que un administrador o un malware con acceso local elimine las líneas incómodas. Trata el contenido y la integridad como propiedades separadas.

Un diario encadenado mediante hashes vincula cada registro con el anterior mediante un resumen criptográfico. Si se cambia un registro antiguo, la cadena posterior deja de verificarse. Esto resulta útil porque una pantalla de actividad exportada puede contrastarse con el diario subyacente en lugar de aceptarse por confianza. No demuestra que el sistema original registrara todos los eventos, que un escritor comprometido no creara registros falsos ni que una aprobación válida fuera una buena decisión. Son afirmaciones distintas que requieren controles distintos.

Verifica la integridad en el límite donde las pruebas salen del sistema. El investigador debe poder tomar el flujo de registros cifrado, ejecutar una comprobación de integridad sin conexión y saber si la secuencia está intacta sin exponer credenciales solo para validar una cadena. El resultado de la verificación debe identificar el intervalo comprobado, el estado de la cadena y la primera secuencia que falla si la verificación no tiene éxito.

Sallyport proyecta sus diarios Sessions y Activity desde un único registro de auditoría cifrado, ciego para escritura y encadenado mediante hashes, y `sp audit verify` puede verificar la cadena sin conexión sobre el texto cifrado sin una clave del almacén. Esta disposición importa porque la decisión de sesión y la operación individual siguen siendo vistas de las mismas pruebas, no historias editables por separado.

No uses la verificación de integridad como motivo para conservar datos excesivos para siempre. La retención, el control de acceso y la redacción siguen siendo importantes. Un registro perfectamente conservado y lleno de secretos es un incidente a la espera de una consulta conveniente. Define quién puede inspeccionar los registros sin procesar, quién puede exportarlos, cuánto tiempo permanecen disponibles y qué campos son seguros en las vistas habituales.

## Construye la línea temporal alrededor de las relaciones y prueba después los casos difíciles

Una revisión del esquema debe comenzar con una pregunta directa: ¿puede un investigador partir de cualquier acción ejecutada y retroceder hasta la aprobación sin adivinar? Si no puede, añade el identificador que falta antes de perfeccionar la pantalla de actividad.

Prueba la implementación con una matriz pequeña. No necesitas una simulación grande. Necesitas casos que expongan errores de alcance y orden:

- Inicia un proceso nuevo del agente, aprueba su sesión con un clic y realiza una llamada de bajo riesgo.
- Usa una credencial que exija aprobación por llamada, autorízala con Touch ID y confirma que la llamada apunta a esa aprobación.
- Cancela el aviso biométrico y confirma que no aparece ningún registro correcto de uso de credencial.
- Termina el proceso del agente, inícialo de nuevo y verifica que el proceso nuevo no pueda heredar la autorización de sesión anterior.
- Fuerza un fallo remoto después del envío y comprueba que la línea temporal distingue el envío de la finalización.

Inspecciona el resultado en ambas direcciones. Empieza por la aprobación y enumera cada acción que dependió de ella. Después empieza por la llamada ejecutada y sigue el proceso, la sesión, la decisión y la credencial. La primera vista encuentra autorizaciones más amplias o duraderas de lo esperado. La segunda encuentra llamadas con pruebas rotas o ambiguas.

Mantén el lenguaje de la interfaz tan estricto como el modelo de datos. «Sesión aprobada mediante clic» es claro. «Credencial de despliegue de producción aprobada con Touch ID para esta llamada» es claro. «Approved» es una palabra de estado decorativa que obliga al lector a inventar los detalles más importantes.

La primera vez que alguien pregunte quién aprobó una acción de un agente, no le entregues una captura de pantalla con una insignia verde. Entrégale una línea temporal que muestre el proceso, el método de decisión, el alcance, la autoridad de la credencial, la llamada exacta y el resultado. Cualquier cosa inferior puede resultar cómoda durante una demostración. No resistirá cuando la acción importe.
