
Recibos de delegación firmados criptográficamente para agentes de IA. Define exactamente lo que una IA puede y no puede hacer: firmado, verificable, a prueba de manipulaciones.
AuthProof es un protocolo de delegación criptográfica para IA agentiva. La mayoría de los protocolos en este espacio se aplican contra una política definida por el operador, otorgándole autoridad para expandir o reinterpretar la intención original del usuario después del hecho. AuthProof está construido alrededor de un modelo de confianza diferente: la clave privada del propio usuario firma el objeto de autorización que controla la ejecución, y el estado del modelo en vivo se verifica tanto en el momento de la autorización como inmediatamente antes de la ejecución. La combinación de autoridad firmada por el usuario y control del estado del modelo en vivo es la afirmación específica, no una historia de aplicación amplia.
Qué lo hace diferente:
El usuario es la autoridad firmante. Todos los protocolos competidores (AIP, AITH, OAP, SAGA, AgentSpec) se aplican contra una política que el operador define. En AuthProof, la clave privada del usuario firma el objeto de autorización directamente. El operador no puede ampliar el alcance después de que el usuario haya firmado.
Compromiso de estado del modelo en dos fases. El modelo se mide en el momento de la autorización y se vuelve a medir inmediatamente antes de la ejecución. Si el modelo se ha desviado entre esos dos puntos, la ejecución se bloquea en la verificación previa a la ejecución.
Actualización del proveedor versus sustitución maliciosa, distinguidos. El protocolo clasifica los cambios de estado del modelo en dos categorías: actualizaciones legítimas del proveedor (PROVIDER_UPDATE_REQUIRES_REAUTH) e intercambios no autorizados (MALICIOUS_MODEL_SUBSTITUTION). Cada una produce un código de motivo de denegación legible por máquina que identifica qué componentes cambiaron.
La puerta determinista que se ejecuta antes de que se ejecute cualquier acción del agente.
El PreExecutionVerifier se encuentra fuera del runtime del agente. El runtime nunca obtiene el control hasta que el verificador pasa. Un agente comprometido o malicioso no puede omitirlo â se ejecuta antes de que el runtime comience.
Las comprobaciones de autorización tradicionales ocurren dentro del runtime del agente. Si el runtime está comprometido, esas comprobaciones pueden omitirse, reordenarse o eludirse. PreExecutionVerifier elimina esta superficie de ataque al mover la autorización completamente fuera del runtime. El agente solo ejecuta si — y solo si — las seis comprobaciones secuenciales pasan primero.
import { PreExecutionVerifier, DelegationLog } from 'authproof-sdk/pre-execution-verifier' import { RevocationRegistry } from 'authproof-sdk'
// 1. Set up the gate const delegationLog = new DelegationLog() const revocationRegistry = new RevocationRegistry() await revocationRegistry.init({ privateKey, publicJwk })
const verifier = new PreExecutionVerifier({ delegationLog, revocationRegistry }) await verifier.init({ privateKey: verifierKey, publicJwk: verifierPub })
// 2. Register your delegation receipt delegationLog.add(receiptHash, receipt)
// 3. Gate every action â before the agent runs const result = await verifier.check({ receiptHash, action: { operation: 'read', resource: 'calendar' }, operatorInstructions: 'Summarize meetings. Stay within scope.', programHash, // optional: prevents code substitution attacks })
if (!result.allowed) {
throw new Error(Blocked: ${result.blockedReason})
}
// Agent runtime only reaches here after all six checks pass
### Seis verificaciones secuenciales (se detiene ante el primer fallo)
| # | Verificación | Bloquea cuando |
|---|-------|-------------|
| 1 | Firma del recibo | Firma ECDSA P-256 inválida o recibo alterado |
| 2 | Revocación | El recibo ha sido revocado mediante `RevocationRegistry` |
| 3 | Ventana temporal | Recibo caducado o aún no válido (oráculo de marca de tiempo del registro, no reloj del cliente) |
| 4 | Alcance | La acción no está en `ScopeSchema.allowedActions` o falla la coincidencia de alcance basada en texto |
| 5 | Instrucciones del operador | Las instrucciones actuales no coinciden con el hash bloqueado en el recibo en el momento de la emisión |
| 6 | Hash del programa | El `programHash` proporcionado no coincide con el hash de `executes` comprometido (prevención de sustitución de código) |
Cada resultado de verificación — pase o falle — se registra automáticamente en un `ActionLog` inmutable firmado con la propia clave del verificador.
### Integraciones de middleware
Wrappers de integración directa para frameworks comunes. Cada wrapper controla cada llamada a través de `PreExecutionVerifier` antes de que se ejecute el código envuelto.
- **[LangChain](https://github.com/commonguy25/authproof-sdk/blob/HEAD/src/middleware/langchain.js)** — envuelve cualquier agente con un método `invoke()`
- **[Express/HTTP](https://github.com/commonguy25/authproof-sdk/blob/HEAD/src/middleware/express.js)** — middleware de solicitud para cualquier framework compatible con Express
- **[Generic function wrapper](https://github.com/commonguy25/authproof-sdk/blob/HEAD/src/middleware/generic.js)** — envuelve cualquier función asíncrona```js
// LangChain
import { authproofMiddleware } from 'authproof-sdk/middleware/langchain'
const guardedAgent = authproofMiddleware(agent, { receiptHash, verifier })
// Express
import { authproofMiddleware } from 'authproof-sdk/middleware/express'
app.use(authproofMiddleware({ verifier, getReceiptHash: (req) => req.headers['x-receipt-hash'] }))
// Any function
import { guardFunction } from 'authproof-sdk/middleware/generic'
const guardedExecute = guardFunction(executeAction, { receiptHash, verifier, action })
Cada marco existente del IETF para identidad de agentes — AIP, draft-klrc-aiagent-auth, WIMSE — aborda la confianza servicio-a-agente: cómo un servicio posterior verifica que un agente está autorizado para llamarlo. Ninguno de ellos aborda la confianza usuario-a-operador. La cadena de delegación en los sistemas agentivos actuales es:
-``` User â Operator â Agent â Services
El usuario instruye al operador. El operador instruye al agente. Pero no existe ningún registro criptográfico de la intención original del usuario en el momento de la delegación. El operador se convierte en un tercero de confianza con autoridad sin control para ampliar, distorsionar u omitir las instrucciones del usuario antes de que lleguen al agente.
Las consecuencias:
- Los usuarios no pueden probar lo que autorizaron.
- Los reguladores no tienen una pista de auditoría.
- Los tribunales no tienen una cadena de pruebas.
- Los agentes no pueden distinguir las instrucciones legítimas del operador de las comprometidas o maliciosas.
AuthProof llena este vacío.
---
## El Primitivo Central: Recibo de Delegación
Un **Recibo de Delegación** es un Objeto de Autorización firmado anclado a un registro descentralizado de solo añadido antes de que comience cualquier acción del agente. Contiene cuatro campos requeridos:
### Alcance
Una lista de permisos explícita de operaciones permitidas. Todo lo que no está listado está denegado por defecto. Expresado en formato estructurado — no en lenguaje natural. Clases de operación:
| Class | Description |
|---|---|
| `reads` | Acceso de lectura a recursos especificados |
| `writes` | Acceso de escritura a recursos especificados |
| `deletes` | Eliminación de recursos especificados |
| `executes` | Ejecución de un programa específico, referenciado por su **hash de firma de capacidad estática** |
`executes` es la clase más peligrosa. Debe referenciar el hash criptográfico del DAG de capacidad estática de un programa Safescript — no un nombre, URI o descripción. Sin coincidencia de hash significa que no hay ejecución.
### Límites
Prohibiciones explícitas que no pueden ser anuladas por instrucciones del operador bajo ninguna circunstancia. Límites duros definidos por el usuario que sobreviven a cualquier instrucción posterior del operador.
### Ventana de Tiempo
Período de validez de la autorización. La **marca de tiempo del registro** es el oráculo de tiempo — no el reloj del cliente. Los relojes del cliente están explícitamente excluidos de la validación de tiempo.
### Hash de Instrucción del Operador
Un hash criptográfico de las instrucciones declaradas por el operador en el momento de la delegación. Si el operador posteriormente instruye al agente de manera diferente, la discrepancia es detectable desde el registro sin suposiciones de confianza adicionales.
El usuario firma este objeto con su clave privada mediante **WebAuthn/FIDO2 usando el enclave seguro del dispositivo**. La firma se publica en el registro antes de cualquier acción del agente. Cada acción posterior del agente referencia el hash del recibo. Las acciones fuera del alcance son criptográficamente inválidas.
---
## Arquitectura de la Pila de Confianza
Tres capas de protocolo eliminan tres terceros de confianza:
### Capa 1 — Manifiesto de Capacidad Firmado *(elimina la confianza en el registro)*
En el ecosistema MCP actual, no existe una atestación criptográfica de que las descripciones de un servidor de herramientas coincidan con lo que realmente hace. Un operador puede presentar un esquema arbitrario.
La solución: los servidores de herramientas publican un **manifiesto de capacidad firmado criptográficamente** antes de que ocurra cualquier autorización de usuario. El campo `scope` del Recibo de Delegación referencia el **hash de este manifiesto** — no el esquema autoinformado por el operador. La divergencia entre el comportamiento del servidor y el manifiesto es detectable en la capa de registro.
### Capa 2 — Recibo de Delegación *(elimina la confianza en el operador)*
La intención original del usuario se registra de manera inmutable antes de que las instrucciones del operador lleguen al agente. La desviación del operador es demostrable.
### Capa 3 — Ejecución de Safescript *(elimina la confianza en el código)*
[Safescript](https://github.com/safescript) es un lenguaje de código abierto en entorno aislado para la ejecución de agentes de IA. Su estructura DAG estática significa que la firma completa de capacidad de cada programa es computable antes de que se ejecute — sin despacho dinámico, sin expansión de capacidad en tiempo de ejecución.
La clase de alcance `executes` referencia un hash de firma de capacidad de Safescript específico. Si el programa proporcionado por el operador no coincide con el hash comprometido, la ejecución se bloquea. El agente no puede ser sustituido por un programa diferente después de la delegación.
## Inicio Rápido```js
import { AuthProof, Scope, KeyCustody } from 'authproof-sdk';
// Initialize with hardware-backed key custody (recommended)
const authproof = new AuthProof({
custody: KeyCustody.HARDWARE, // WebAuthn/FIDO2 via device secure enclave
log: 'https://log.authproof.dev',
});
// Define permitted operations â explicit allowlist, deny-by-default
const scope = new Scope()
.allow('reads', ['resource://calendar/events', 'resource://email/inbox'])
.allow('writes', ['resource://calendar/events'])
.deny('deletes', '*')
.execute('sha256:a3f1c9d8...', { program: 'scheduler-v1.sg' }); // Safescript hash
// Hard limits that survive any operator instruction
const boundaries = {
never: ['external-network', 'credential-store', 'payment-methods'],
};
// Issue the Delegation Receipt â anchored to log before any agent action
const receipt = await authproof.delegate({
scope,
boundaries,
window: { duration: '8h' }, // validated against log timestamp
operatorInstructions: instructionText, // hashed and committed
});
// receipt.id â unique receipt identifier
// receipt.hash â reference in every agent action
// receipt.log â append-only log anchor
// Agent-side: validate an action against the receipt
const check = await authproof.validate({
receiptHash: receipt.hash,
action: { class: 'writes', resource: 'resource://calendar/events' },
});
if (!check.authorized) {
// Out-of-scope action: surface a micro-receipt request to the user
const microReceipt = await authproof.requestMicroReceipt({
action: check.requestedAction,
parent: receipt.hash,
});
}
Para llamadas a herramientas no cubiertas por el Recibo de Delegación original, el agente no puede proceder en silencio. El protocolo exige:
Las acciones desconocidas requieren una nueva autorización explícita del usuario. La resolución de dependencias sigue la misma regla â las dependencias se verifican contra el hash del manifiesto de dependencias comprometido en el momento de la delegación. Las dependencias inesperadas son una violación del alcance.
Cada evento de delegación lleva un ID de recibo único. Los agentes concurrentes hacen referencia a su propio hash de recibo. Se distinguen por recibo, no por identidad de agente.
La custodia por hardware es la opción predeterminada recomendada. La clave privada nunca sale del enclave seguro; la firma está protegida por biometría o PIN del dispositivo.
Un Recibo de Delegación define lo que un agente de IA está autorizado a hacer. El Registro de Acciones registra lo que realmente hizo â y hace que cualquier desviación sea instantáneamente verificable.
Cada acción que realiza un agente produce una entrada firmada y con marca de tiempo vinculada al recibo activo. Las entradas forman una cadena a prueba de manipulaciones: cada entrada incrusta el hash SHA-256 de la anterior, por lo que cualquier modificación retroactiva es detectable sin un tercero de confianza. El método diff() es la primitiva de auditoría â alinea el alcance autorizado del recibo con cada acción registrada y devuelve cualquier desviación.```js
import AuthProof, { ActionLog } from 'authproof-sdk';
// 1. Issue a delegation receipt as normal const { privateKey, publicJwk } = await AuthProof.generateKey();
const { receipt, receiptId } = await AuthProof.create({ scope: 'Search the web for competitor pricing. Read calendar events.', boundaries: 'Do not send emails. Do not make purchases.', instructions: 'Cite sources. Keep under 500 words.', ttlHours: 4, privateKey, publicJwk, });
// 2. Initialize the action log with the agent's signing key const log = new ActionLog(); await log.init({ privateKey, publicJwk });
// Register the receipt so diff() knows what was authorized log.registerReceipt(receiptId, receipt);
// 3. Record each action the agent takes const e1 = await log.record(receiptId, { operation: 'Search competitor pricing', resource: 'web/search', parameters: { query: 'rival.com pricing 2024' }, });
const e2 = await log.record(receiptId, { operation: 'Read calendar events', resource: 'calendar/events', parameters: { range: 'this_week' }, });
// 4. Verify an individual entry (signature + chain integrity) const check = await log.verify(e1.entryId); // { valid: true, reason: 'Signature and chain integrity verified' }
// 5. Diff: authorized scope vs. everything that was done const report = log.diff(receiptId); // { // clean: true, // totalEntries: 2, // compliant: [{ entry: {...}, reason: '"Search competitor pricing" matches authorized scope' }, ...], // violations: [], // }
// A scope violation surfaces immediately await log.record(receiptId, { operation: 'Send email', resource: 'email/outbox' }); const auditReport = log.diff(receiptId); // auditReport.violations[0].reason â // '"Send email" outside authorized scope (0% scope match, 92% boundary overlap)'
### Action Log API
| Método | Descripción |
|---|---|
| `new ActionLog()` | Crea una nueva instancia de registro. El estado está en memoria. |
| `log.init({ privateKey, publicJwk })` | Inicializa con la clave ECDSA P-256 del agente. Requerido antes de `record()`. |
| `log.registerReceipt(receiptHash, receipt)` | Registra un recibo para comparación de ámbito. Requerido antes de `diff()`. |
| `log.record(receiptHash, action)` | Añade una entrada firmada y encadenada. Devuelve la entrada sellada. |
| `log.verify(entryId)` | Verifica la firma y la posición en la cadena de una entrada. Devuelve `{ valid, reason }`. |
| `log.getEntries(receiptHash)` | Todas las entradas de un recibo en orden cronológico. |
| `log.diff(receiptHash)` | Compara todas las entradas con el ámbito del recibo. Devuelve `{ compliant, violations, clean }`. |
### Advertencia de producción
Las marcas de tiempo en v1 usan el reloj del cliente. Para contextos de cumplimiento o legales donde las marcas de tiempo deben ser verificables de forma independiente, reemplácelas con una autoridad de sellado de tiempo confiable RFC 3161 antes de implementar en producción.
### Importante
Defina siempre el ámbito utilizando arreglos explícitos de `allowedActions`. La coincidencia de ámbito basada en texto está disponible solo para desarrollo y no es adecuada para producción o contextos de cumplimiento.
---
## Despliegue Confidencial
Ejecute agentes AuthProof dentro de Entornos de Ejecución Confiables (TEE) atestiguados por hardware. La clase `ConfidentialRuntime` vincula los recibos de delegación con las mediciones del enclave, de modo que cualquier sustitución de pesos del modelo, código de verificador o plataforma sea detectable antes de la ejecución.
### Requisitos de hardware
- **Intel TDX** — Intel Ice Lake Xeon o más reciente (Xeon Escalable de 4.ª generación). Azure DCdsv3-series, GCP C3 Confidential VMs.
- **AMD SEV-SNP** — AMD EPYC de 3.ª generación (Milan) o más reciente. Azure DCasv5-series, AWS m6a con Nitro Enclaves.
### Crear un recibo con vinculación de medición TEE```javascript
import { AuthProofClient } from 'authproof-sdk';
const client = new AuthProofClient();
const { receipt } = await client.delegate({
scope: 'Summarize calendar events',
operatorInstructions: 'Stay within scope.',
expiresIn: '2h',
privateKey,
publicJwk,
teeConfig: {
platform: 'intel-tdx',
verifierHash: verifierCodeHash, // SHA-256 of your verifier binary
modelHash: modelWeightsHash, // SHA-256 of model weights
},
});
// receipt.teeMeasurement.expectedMrenclave is now bound to the receipt
import { ConfidentialRuntime } from 'authproof-sdk';
// Generate deployment configuration const config = ConfidentialRuntime.azureTDXConfig({ receiptHash, verifierHash, modelHash, region: 'eastus', }); // config.vmSize === 'Standard_DC4ds_v3' // config.attestationEndpoint === 'https://sharedeus.eus.attest.azure.net' // config.receiptBinding binds the receipt to the VM measurement
// At runtime inside the VM: const runtime = new ConfidentialRuntime({ platform: 'intel-tdx', verifier, actionLog, }); const result = await runtime.launch({ receiptHash, agentFn, operatorInstructions, verifierHash, modelHash, teeMeasurement: receipt.teeMeasurement, // mismatch blocks execution });
Requisitos de SKU de Azure: `Standard_DC4ds_v3` o superior de la serie DCdsv3. Habilitar el cifrado de disco de SO confidencial. Usar el punto de conexión compartido de Microsoft Azure Attestation (MAA) para la verificación de citas.
### Implementar en AWS Nitro Enclaves```javascript
const config = ConfidentialRuntime.awsNitroConfig({
receiptHash,
verifierHash,
modelHash,
region: 'us-east-1',
});
// config.instanceType === 'c6a.xlarge'
// config.enclaveOptions.enabled === true
// config.pcr0 is the combined receipt+verifier+model measurement
Requisitos de AWS: c6a.xlarge o superior con --enclave-options Enabled. Usa nitro-cli para construir y ejecutar la imagen de enclave. PCR0 en el documento de atestación debe coincidir con config.pcr0 para que el enlace de recibo sea válido.
const manifest = ConfidentialRuntime.kubernetesConfig({ receiptHash, platform: 'intel-tdx', namespace: 'production', }); // manifest is a full K8s List containing: // - Pod with TDX node selector and attestation sidecar // - ServiceAccount with minimal RBAC // - ConfigMap with receipt binding
Aplique con `kubectl apply -f` después de serializar a YAML. El selector de nodos `intel.feature.node.kubernetes.io/tdx: "true"` requiere el Intel Device Plugin for Kubernetes.
### Módulo del kernel eBPF â se busca ayuda
La capa de ejecución TEE está completa en el lado del espacio de usuario (`ConfidentialRuntime`, `TokenPreparer`). El paso final de ejecución â validar el token de capacidad firmado en cada llamada al sistema mediante un hook eBPF LSM â requiere un módulo del kernel que está abierto para contribuciones.
Ingenieros con experiencia en eBPF LSM (Isovalent, Red Canary, o similar) son especialmente bienvenidos. Abra un issue o PR en https://github.com/Commonguy25/authproof-sdk/issues
---
## Ejemplos
Dos ejemplos ejecutables se encuentran en el directorio `examples/`.
**[`examples/langchain-example.js`](https://github.com/commonguy25/authproof-sdk/blob/HEAD/examples/langchain-example.js)** â Muestra la ruta completa de integración con LangChain: generar un par de claves, emitir un recibo de delegación, inicializar `PreExecutionVerifier` y envolver cualquier agente con `authproofMiddleware` para que cada llamada a `invoke()` sea verificada antes de que el runtime del agente tome el control. Incluye un agente simulado que puede ejecutar de inmediato y el patrón de código exacto para un `AgentExecutor` real. Ejecute con `npm run example:langchain`.
**[`examples/webauthn-example.html`](https://github.com/commonguy25/authproof-sdk/blob/HEAD/examples/webauthn-example.html)** â Una demostración auto-contenida de tres tarjetas en el navegador del flujo completo de delegación. La Tarjeta 1 le permite definir alcance, límites e instrucciones del operador, luego firma un recibo con una clave local (intercambie por `navigator.credentials` para WebAuthn real). La Tarjeta 2 muestra el ID del recibo, vencimiento, prompt del sistema y el JSON sin procesar. La Tarjeta 3 le permite escribir cualquier acción propuesta y verificarla contra el recibo en tiempo real, mostrando cada resultado de comprobación. Ábralo directamente en un navegador â no se requiere paso de compilación.
---
## Instalación```bash
npm install authproof-sdk
WHITEPAPER.md| Modelo | Descripción | Recomendado |
|---|
| Hardware | WebAuthn/FIDO2 a través del enclave seguro del dispositivo. La clave privada nunca sale del hardware. | Sí â predeterminado |
| Delegado | Un administrador de claves de confianza retiene la clave en nombre del usuario. | Entornos sin soporte FIDO2 |
| Autocustodia | El usuario retiene y gestiona su propia clave privada. | Usuarios avanzados, flujos de trabajo aislados |