# Las pruebas de canales laterales temporales deben tratar el rechazo como un resultado

Un agente no necesita conocer un secreto para aprender algo peligroso. Si puede llamar repetidamente a una puerta de enlace de acciones y ordenar los resultados por duración, quizá descubra si la bóveda está bloqueada, si existe un nombre de credencial, si una solicitud pasó la autorización o si la puerta de enlace llegó a un servicio remoto.

Esa información basta para cambiar su comportamiento. Un agente de programación que descubre que existe una credencial puede seguir pidiendo acceso a ese servicio. Un agente comprometido puede usar el resultado para hacer reconocimiento. La fuga puede parecer inofensiva en una sola llamada. Se vuelve útil cuando quien llama controla las entradas, repite las solicitudes y puede medir el tiempo con precisión.

MITRE registra esta clase como CWE-208, Observable Timing Discrepancy. Su descripción es adecuadamente amplia: el estado interno relevante para la seguridad puede escapar cuando las operaciones tardan cantidades de tiempo observables diferentes. El ejemplo habitual es la comprobación de contraseñas. Una puerta de enlace para agentes tiene una versión menos conocida del mismo problema: quien llama ya está dentro del flujo de trabajo del desarrollador y puede realizar muchas llamadas estructuradas a herramientas sin cansarse.

La solución no consiste en hacer que cada acción tarde exactamente lo mismo. Esa promesa suele ser falsa, especialmente cuando una solicitud HTTP o una conexión SSH sale de la máquina. El trabajo es más concreto y práctico: identificar los estados que un agente no debería poder distinguir, hacer comparable su tratamiento local y mantener una suite de pruebas diferenciales que detecte nuevas rutas rápidas.

## Trata el estado de la bóveda como información que el usuario no debe inferir

Una bóveda bloqueada, una credencial inexistente, una acción rechazada y una credencial remota incorrecta son condiciones operativas distintas. No son automáticamente datos diferentes que el agente necesite conocer.

Empieza por anotar qué puede saber cada usuario. Parece obvio, pero los equipos suelen saltarse este paso y dejan que el orden de implementación decida la política de divulgación. Una búsqueda temprana en la bóveda revela si existe una credencial. Una comprobación temprana de autorización revela si un proceso tiene una sesión aprobada. Un error local inmediato revela que la bóveda está bloqueada. Cada atajo puede ser razonable por separado. Juntos proporcionan al usuario una sonda del estado.

En una puerta de enlace de acciones, separa estas preguntas:

- ¿Puede este proceso solicitar una acción?
- ¿Está disponible la bóveda para ejecutarla?
- ¿Existe una asignación de credencial para esta acción?
- ¿El servicio remoto aceptó la credencial?
- ¿Puede quien llama ver alguna de esas respuestas directamente o solo recibir el resultado de una acción?

La distinción importante es entre el **estado de autorización** y el **estado de la credencial**. La autorización responde si una ejecución concreta del agente puede invocar una acción. El estado de la credencial responde si la puerta de enlace tiene el material necesario para ejecutar esa acción. Si los mezclas internamente, un resultado temporal puede decirle por accidente al agente que existe una credencial simplemente porque la puerta de enlace la comprobó después de aprobar la solicitud.

El bloqueo de la bóveda de Sallyport es deliberadamente absoluto: mientras la bóveda está bloqueada, se rechaza toda acción. Es un límite de seguridad claro, pero aun así merece pruebas de tiempo, porque quien llama puede observar cómo se produce el rechazo. El objetivo no es fingir que una bóveda bloqueada puede completar una solicitud remota. Es asegurarse de que el tratamiento local del rechazo no cree una firma sencilla y repetible que revele más de lo necesario.

OWASP plantea lo mismo en su Authentication Cheat Sheet. Un texto de error genérico no elimina por sí solo una fuga de enumeración si una ruta de fallo realiza más trabajo que otra. La guía habla de autenticación, pero la lección de ingeniería se aplica aquí: un mensaje uniforme que envuelve rutas de ejecución diferentes sigue filtrando información mediante el tiempo transcurrido.

## Cuatro resultados necesitan dos contratos temporales distintos

Intentar igualar todos los resultados es una recomendación popular porque resulta fácil de expresar. También es incorrecta cuando una puerta de enlace puede llamar a redes. Necesitas dos contratos temporales, no una duración universal imposible.

El primer contrato cubre los **resultados locales**. Son estados en los que la puerta de enlace debe rechazar la solicitud antes de enviar nada: la bóveda está bloqueada, falta la autorización de sesión o ha sido rechazada, una acción no tiene una credencial configurada o se ha rechazado una aprobación por llamada. Para los estados que deben revelar la misma cantidad de información al agente, usa una respuesta local común.

El segundo contrato cubre los **resultados enviados**. Tanto una credencial válida como una no válida pueden llegar al mismo servidor HTTP de prueba o al mismo host SSH de prueba. Sus tiempos totales incluyen el transporte, la reutilización de conexiones, el trabajo del servidor y la entrega de la respuesta. No puedes hacer que Internet tenga un tiempo constante. Sí puedes asegurarte de que la puerta de enlace inserte, envíe, registre y traduzca ambos resultados mediante rutas comparables, y después usar un servidor controlado para mantener estable la parte remota durante la prueba.

Esto produce una matriz útil:

| Resultado | ¿Sale la solicitud de la puerta de enlace? | ¿Con qué debe compararlo la prueba de tiempo? |
| --- | --- | --- |
| Bóveda bloqueada | No | Otros rechazos locales que no deban revelar más estado |
| Autorización rechazada | No | Otros rechazos locales, medidos antes de la interacción humana |
| Credencial inexistente | No | Fallo local con la bóveda disponible, usando la misma envoltura de respuesta cuando la política de divulgación lo exija |
| Credencial no válida | Sí | Credencial válida contra el mismo servicio ascendente controlado |
| Credencial válida | Sí | Credencial no válida y variantes de error remoto |

No compares directamente una credencial inexistente con una llamada exitosa a una API de terceros y declares que la prueba ha fallado porque una es más rápida. Esa prueba solo demuestra que una solicitud que nunca salió de la máquina es más rápida que una solicitud de Internet. Eso ya lo sabías.

Prueba los límites por separado. Un usuario local debería tener dificultades para separar los estados locales que quieres ocultar. Un usuario que envía solicitudes debería tener dificultades para distinguir una credencial de prueba buena de una mala basándose en el trabajo añadido por la puerta de enlace. El servidor de prueba puede devolver códigos de estado distintos deliberadamente después del mismo retraso, de modo que el resultado semántico siga siendo diferente y el experimento temporal continúe siendo útil.

Hay un límite claro: si quien llama recibe un error detallado que dice «credencial inexistente», ya no necesita usar el tiempo para saberlo. Las defensas temporales no pueden salvar una API que informa libremente del estado secreto. Decide primero qué semántica de errores está permitida.

## Un fallo rápido se convierte en un oráculo cuando las llamadas pueden repetirse

Una fuga temporal rara vez aparece como una diferencia espectacular. Lo más habitual es que alguien añada un retorno anticipado razonable durante una refactorización.

Imagina una puerta de enlace con este orden de operaciones:

1. Analizar la solicitud del agente.
2. Buscar la credencial indicada en el índice de la bóveda.
3. Comprobar si el proceso del agente tiene aprobación de sesión.
4. Construir y enviar la solicitud.

Una credencial inexistente termina en el paso dos. Una credencial existente con un proceso no aprobado continúa hasta el paso tres. La respuesta externa podría ser idéntica en ambos casos: «acción no disponible». Sin embargo, la segunda ruta incluye un acierto en el índice de la bóveda, una búsqueda de autorización, la preparación de la auditoría y quizá la creación de una tarjeta de aprobación. Quien llama puede ejecutar cada entrada muchas veces y ordenar los resultados.

La fuga empeora cuando el agente puede elegir alias de credenciales. Puede probar una lista de nombres como `staging`, `production`, `deploy` o los nombres que haya encontrado en un repositorio. No necesita ejecutar una acción con éxito. Solo necesita separar un grupo rápido de uno lento.

El orden defensivo depende de tu política de divulgación, pero una estructura más segura sería:

1. Validar la solicitud sin ramas que dependan de secretos.
2. Aplicar el bloqueo absoluto de la bóveda.
3. Aplicar la autorización del proceso o de la sesión.
4. Resolver la acción y la credencial solo después de que el usuario haya superado los controles que deben preceder a ese conocimiento.
5. Hacer que los fallos locales que deban permanecer indistinguibles pasen por el mismo trabajo de registro, preparación del error y finalización de la respuesta.

No interpretes esto como una instrucción para realizar trabajo secreto destinado a un proceso no autorizado. No debes descifrar una credencial ni construir un encabezado de autorización real solo para perder tiempo. El objetivo es evitar atajos dependientes del estado en el límite observable, no convertir los rechazos en una forma de acceder a secretos.

Un parche defectuoso habitual es `sleep(100ms)` antes de cada rechazo. Hace más bonito el gráfico de una demostración, pero crea tres problemas. La duración suele variar después por el ruido del planificador y el comportamiento de la caché. El retraso perjudica a los usuarios legítimos. Sobre todo, quien llama repetidamente puede eliminar mediante promedios el relleno aleatorio o fijo si las rutas subyacentes siguen siendo diferentes. Igualar el trabajo necesario es más fiable que añadir retrasos encima de un trabajo desigual.

## Mide en el límite que realmente observa el agente

La instrumentación dentro de la puerta de enlace sirve para diagnosticar, pero no es la medición de seguridad principal. El agente observa el tiempo entre el envío de una llamada a una herramienta y la recepción de su resultado final. Ahí empieza y termina tu prueba diferencial de extremo a extremo.

Usa un controlador de pruebas dedicado que se comporte como un cliente de agente. Debe comenzar con una identidad de proceso conocida, enviar una solicitud, esperar una respuesta completa, registrar una duración monotónica y guardar la etiqueta del resultado fuera de la solicitud medida. No muestres etiquetas durante la ejecución. La salida de consola, los exportadores de trazas y los registros de depuración pueden distorsionar las rutas locales cortas y ocultar la regresión que buscas.

Un registro de muestra práctico necesita más de un número:

```json
{
  "case": "vault_locked",
  "sequence": 184,
  "elapsed_us": 12746,
  "result_class": "local_denial",
  "connection_mode": "fresh",
  "run_id": "test-run-7"
}
```

Usa un reloj monotónico. Los relojes de pared saltan cuando se ejecuta la sincronización horaria y son instrumentos deficientes para comparar intervalos inferiores a un segundo. Registra microsegundos o nanosegundos si la plataforma los ofrece y muestra milisegundos cuando las personas lean los resultados. La precisión del archivo no implica exactitud de la medición, pero evita perder información antes del análisis.

Ejecuta una fase de calentamiento antes de recoger muestras. Las primeras llamadas pueden iniciar la aplicación, cargar código, inicializar un identificador de bóveda, crear un grupo de conexiones o llenar una caché. Esos efectos son reales desde el punto de vista operativo, pero a menudo eclipsan la diferencia estable que necesitas examinar. Prueba por separado el arranque en frío si los agentes pueden observarlo. No descartes en silencio el comportamiento incómodo de la primera llamada solo porque afee los gráficos.

Aleatoriza el orden de los casos. Si ejecutas 500 llamadas con la bóveda bloqueada y después 500 con credenciales inexistentes, el estado térmico, la recolección de basura, la actividad en segundo plano y la reutilización de conexiones se convierten en factores de confusión. Intercala los casos mediante una mezcla con semilla para que los fallos puedan reproducirse.

Alterna también conexiones nuevas y reutilizadas cuando el protocolo del cliente admita ambas. Una fuga que desaparece con una conexión caliente puede seguir importando si un agente crea clientes de corta duración. Una fuga que solo aparece con la reutilización puede revelar una caché indexada por la existencia de la credencial.

## Construye un servicio ascendente controlado que separe la semántica del retraso

Las credenciales no válidas son el caso de prueba que más suelen hacer mal los equipos. Apuntan el sistema de pruebas a un servicio real, envían un token deliberadamente incorrecto y lo comparan con una llamada exitosa. Los límites de velocidad del proveedor, el enrutamiento regional, la reanudación de sesiones TLS y los controles contra abusos pasan a formar parte del resultado. Eso no es una prueba temporal de la puerta de enlace.

Construye un pequeño servidor de pruebas bajo tu control. Debe leer una credencial de prueba conocida con el mismo formato de encabezado que inserta la puerta de enlace, esperar una cantidad fija de trabajo y devolver un cuerpo y un estado distintos para las credenciales buenas y malas. No debe acortar la ruta de la credencial no válida.

Por ejemplo, este contrato del servidor de prueba es suficiente:

```text
Request header: Authorization: Bearer test-good
Response: 200 {"fixture":"accepted"}

Request header: Authorization: Bearer test-bad
Response: 401 {"fixture":"rejected"}

Both requests: wait until the same server-side target duration has elapsed
```

La duración objetivo debe ser mayor que el ruido habitual del planificador local, pero lo bastante corta para que la suite siga siendo rápida. Elígela a partir de mediciones realizadas en tu propia máquina de pruebas, en lugar de copiar un número de una publicación. Lo importante es que ambas ramas del servidor de prueba ejecuten la misma ruta de análisis, reloj, espera y respuesta antes de diferenciarse semánticamente.

En HTTP, ejecuta el servidor de prueba en loopback cuando quieras aislar la puerta de enlace y el cliente. Ejecútalo en un host remoto controlado en una segunda tarea cuando quieras observar cómo afecta el ruido normal de la red a la detección. Mantén esos informes separados. Un resultado de loopback indica si cambió la implementación local. Un resultado remoto indica si la prueba sigue siendo sensible bajo variaciones de transporte realistas.

Para SSH, usa una cuenta de prueba y un comando que termine de una forma conocida después de la autenticación. No hagas pruebas fallando repetidamente contra un bastión de producción. Los servidores SSH pueden ralentizar deliberadamente los fallos, bloquear cuentas o añadir trabajo de registro. Son defensas razonables, pero hacen que la medición hable del servidor y no de la puerta de enlace.

Sallyport envía solicitudes HTTP con inserción de credenciales bearer, básicas o de encabezado personalizado, y usa su asistente sin estado `sp-ssh` incluido para SSH. Son canales separados y necesitan servidores de prueba separados. Un resultado uniforme para una ruta de encabezado HTTP no dice nada sobre una ruta SSH que resuelve claves, inicia un asistente y negocia una conexión.

## Compara distribuciones y después intenta clasificar el estado

Las medias ocultan las fugas temporales. Si el 90 % de las llamadas tarda 12 milisegundos y el 10 % tarda 80 porque una caché solo falla para una credencial existente, la media puede parecer suficientemente cercana a la de otro caso, aunque un agente pueda aprovechar el grupo rápido.

Para cada caso, conserva el conjunto completo de muestras. Informa al menos de la mediana, los percentiles inferior y superior, el mínimo, el máximo y el número de muestras. Un histograma suele revelar más que una tabla porque muestra inmediatamente dos grupos.

Después haz que la prueba sea adversarial. Entrega a un clasificador deliberadamente sencillo solo la duración transcurrida y pídele que adivine la etiqueta oculta. Empieza con un clasificador por umbral. Elige un único límite, por ejemplo «menos de X microsegundos significa que falta la credencial», e informa de la precisión con datos que no se hayan usado para elegir ese límite. Si un clasificador de un solo umbral supera repetidamente la línea base por un margen amplio, existe una señal observable que merece investigación.

Un pequeño script de análisis en Python puede hacer visible esta regresión sin fingir que demuestra un tiempo criptográfico constante:

```python
from statistics import median

samples = {
    "vault_locked": [...],
    "credential_missing": [...],
}

for name, values in samples.items():
    ordered = sorted(values)
    p10 = ordered[int(len(ordered) * 0.10)]
    p90 = ordered[int(len(ordered) * 0.90)]
    print(name, {"n": len(values), "p10": p10,
                 "median": median(values), "p90": p90})

best = None
all_values = sorted(set(samples["vault_locked"] + samples["credential_missing"]))
for cutoff in all_values:
    correct = 0
    total = 0
    for label, values in samples.items():
        for value in values:
            guess = "vault_locked" if value <= cutoff else "credential_missing"
            correct += (guess == label)
            total += 1
    score = correct / total
    if best is None or score > best[0]:
        best = (score, cutoff)

print({"best_training_accuracy": best[0], "cutoff_us": best[1]})
```

Separa las muestras en grupos de entrenamiento y de validación antes de seleccionar el límite. De lo contrario, el script se ajustará demasiado al ruido y se felicitará a sí mismo. Si añades un clasificador más complejo, úsalo como diagnóstico secundario. Un modelo complicado puede encontrar patrones diminutos que ningún agente práctico pueda aprovechar, mientras que un umbral sencillo revela las fugas embarazosas que los ingenieros introducen de verdad.

No establezcas una condición universal como «todas las medianas deben estar a menos de cinco milisegundos». Ese umbral no significa lo mismo en máquinas y configuraciones diferentes. Usa una línea base registrada en tu entorno controlado, comprueba si las distribuciones se superponen como esperas y haz fallar la prueba cuando un cambio cree una separación estable entre estados que querías ocultar.

## La comparación de tiempo constante resuelve un problema más pequeño

Cuando oyen «ataque temporal», los desarrolladores suelen recurrir a una función de igualdad en tiempo constante. Esa función importa al comparar secretos, firmas, MAC y tokens de la misma longitud. No hace que toda la ruta de una solicitud de la puerta de enlace tenga un tiempo constante.

El paquete `crypto/subtle` de Go proporciona `ConstantTimeCompare` para segmentos de bytes con contenido de igual longitud. Es el tipo de primitiva adecuado cuando la propia comparación secreta necesita un comportamiento independiente de los datos. Pero no puede igualar una rama que retorna antes de abrir la bóveda, una rama que muestra una tarjeta de aprobación o una rama que abre una conexión de red.

Usa comparaciones de tiempo constante cuando compares valores sensibles y de formato fijo. Después revisa el flujo de control que las rodea. Una comparación limpia dentro de una ruta que retorna inmediatamente si falta una credencial sigue dejando un oráculo sobre la presencia de esa credencial.

Por eso también debes evitar llamar a todo el problema «tiempo constante». Para una puerta de enlace de escritorio que puede realizar llamadas HTTP y SSH, el tiempo constante de extremo a extremo no es alcanzable ni necesario. El requisito es más concreto: los estados locales sensibles no deben crear una señal temporal que el usuario pueda clasificar fácilmente.

Los ejemplos de CWE-208 de MITRE incluyen salidas anticipadas durante las comprobaciones de contraseñas y trabajos diferentes para cuentas existentes e inexistentes. El patrón es el mismo aunque no haya ninguna comparación de contraseñas. La diferencia observable proviene de la ruta de decisión, no de un único operador de igualdad inseguro.

## Los flujos de aprobación necesitan un límite de medición explícito

La aprobación por sesión y por llamada introduce a una persona en la línea temporal. La duración de la llamada completa incluye el tiempo que alguien tarda en ver una tarjeta, leer la identidad del proceso, decidir, autenticarse con Touch ID y hacer clic. Esa duración varía por razones ajenas al estado de la bóveda.

No intentes ocultarlo con relleno. Empeorarás la interacción y aun así no conseguirás que las personas actúen siguiendo un reloj.

En su lugar, divide el flujo en partes automáticas y controladas por una persona. La parte automática empieza cuando el agente envía la llamada y termina cuando la puerta de enlace produce un rechazo sin mostrar un aviso o presenta una solicitud de aprobación. Mide esa parte entre los distintos estados. La parte humana comienza cuando se muestra la solicitud y termina con la aprobación, el rechazo, el tiempo agotado o la salida del proceso. Regístrala para operaciones, pero no la uses como objetivo de equivalencia temporal de un canal lateral.

También necesitas un modo de prueba que establezca un estado de aprobación estable antes de tomar muestras de las llamadas enviadas. De lo contrario, la distribución de tu «credencial válida» incluirá una tarjeta de aprobación una vez y la omitirá durante el resto de la sesión. Esto produce un valor atípico enorme en la primera muestra y oculta diferencias más sutiles.

Una buena suite debe tener casos distintos para estas preguntas:

- ¿Una bóveda bloqueada rechaza la solicitud antes de cualquier búsqueda de credenciales que dependa de la aprobación?
- ¿Un proceso no aprobado recibe el mismo tratamiento previo al aviso independientemente de que una acción tenga una credencial configurada?
- Después de aprobar una sesión, ¿las credenciales de prueba válidas y no válidas siguen rutas comparables hasta el servidor ascendente controlado?
- ¿El rechazo de una aprobación por llamada expone trabajo adicional dependiente de la credencial antes de mostrar la solicitud?

Sallyport identifica un proceso de agente nuevo mediante su autoridad de firma de código en la tarjeta de aprobación, y su autorización por sesión dura solo mientras se ejecuta ese proceso. La suite temporal debe crear procesos de agente nuevos deliberadamente al probar el comportamiento de la primera llamada y mantener vivo un proceso conocido al probar una sesión aprobada. Mezclar esos modos hace imposible interpretar el resultado.

## El trabajo de auditoría no debe crear una ruta rápida dependiente del secreto

Los registros de auditoría suelen causar la última fuga temporal porque se consideran tareas administrativas y no parte del límite de seguridad. Una solicitud rechazada puede registrar solo un evento breve. Una solicitud exitosa puede reservar un registro detallado, calcular su hash para una cadena y escribirlo en almacenamiento cifrado. Esa diferencia puede ser legítima si el éxito ya es observable. Es peligrosa cuando dos rechazos locales revelan cantidades diferentes de un estado oculto.

Decide qué campos puede registrar cada resultado de forma segura y haz que los fallos locales equivalentes realicen un trabajo de auditoría equivalente. No necesitas escribir credenciales ficticias ni enviar solicitudes de prueba. Sí debes evitar una rama en la que «credencial inexistente» omita el diario mientras «bóveda bloqueada» realiza una búsqueda y escribe un registro más pesado, si el agente no debe distinguirlas.

Mantén la verificación de auditoría fuera de la ruta de solicitudes. La verificación es una acción del operador con otro propósito y otro perfil temporal. La cadena de auditoría de Sallyport puede verificarse sin conexión sobre el texto cifrado con `sp audit verify`, sin una clave de bóveda. Ese diseño evita que la verificación necesite leer un secreto, pero no elimina la necesidad de probar el comportamiento de las solicitudes alrededor del registro.

Añade intervalos internos alrededor del análisis de solicitudes, la autorización, el bloqueo de la bóveda, la resolución de credenciales, la adición de auditoría, el envío y el mapeo de respuestas. No expongas esos intervalos al agente. Cuando la prueba de extremo a extremo encuentre una separación, compara las duraciones agregadas de los intervalos entre casos para localizar la etapa que acaba de divergir.

El error es añadir trazas detalladas solo después de que aparezca una regresión temporal. Añade la instrumentación pronto, protégela mediante una opción de pruebas o diagnósticos locales y asegúrate de que la ruta normal no emita registros síncronos cuyo coste dependa de una credencial o de un resultado.

## Coloca las pruebas diferenciales junto al código que añade ramas

Una suite temporal debe revisarse junto con las pruebas de autorización. Las ramas con más probabilidades de retroceder suelen formar parte de cambios de mantenimiento corrientes: un atajo para una configuración ausente, una caché de alias de credenciales, un campo nuevo de auditoría, un mensaje de error mejor o una refactorización que mueve la búsqueda en la bóveda antes de la aprobación del proceso.

Ejecuta una suite local compacta en cada cambio que afecte al acceso a la bóveda, la autorización, la resolución de acciones, el mapeo de errores, la configuración del transporte o las escrituras de auditoría. Puede usar servidores de loopback y un número moderado de muestras. Ejecuta una suite aleatoria más larga en un entorno controlado y tranquilo antes de los lanzamientos, registrando por separado los modos en frío y caliente.

Haz que la prueba produzca algo que un revisor pueda utilizar. Esto es mejor que un indicador verde con una puntuación agregada inexplicable:

```text
case pair: vault_locked vs credential_missing
samples: 400 per case, randomized order
median: 12.7 ms vs 13.1 ms
p10-p90: 11.8-14.0 ms vs 11.9-14.3 ms
holdout threshold accuracy: 51.4%
result: within baseline
```

Y esto es mejor que ocultar el problema bajo un fallo de rendimiento genérico:

```text
case pair: vault_locked vs credential_missing
samples: 400 per case, randomized order
median: 4.2 ms vs 19.6 ms
p10-p90: 3.9-4.7 ms vs 18.2-22.1 ms
holdout threshold accuracy: 99.1%
result: investigate credential lookup before authorization
```

El segundo informe no afirma que un atacante siempre vaya a obtener una precisión del 99,1 % en una estación de trabajo ocupada. Indica al ingeniero que el código local ha creado una separación clara y repetible. Basta para bloquear el cambio hasta corregir el orden de las ramas o la envoltura de respuesta.

No ocultes el resultado con un retraso arbitrario. Mueve el trabajo dependiente de secretos detrás del control correcto, elimina el trabajo innecesario específico de cada estado y vuelve a probar desde el límite del agente. El resultado útil no es un gráfico perfectamente plano. Es un agente que no puede convertir un cronómetro en un inventario de lo que hay detrás de la bóveda.
