agent-passport-system 1.15.0 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -18
- package/dist/src/core/gateway.d.ts +32 -0
- package/dist/src/core/gateway.d.ts.map +1 -1
- package/dist/src/core/gateway.js +289 -28
- package/dist/src/core/gateway.js.map +1 -1
- package/dist/src/core/messaging-audit.d.ts +69 -0
- package/dist/src/core/messaging-audit.d.ts.map +1 -0
- package/dist/src/core/messaging-audit.js +112 -0
- package/dist/src/core/messaging-audit.js.map +1 -0
- package/dist/src/core/oracle-witness.d.ts +24 -0
- package/dist/src/core/oracle-witness.d.ts.map +1 -0
- package/dist/src/core/oracle-witness.js +224 -0
- package/dist/src/core/oracle-witness.js.map +1 -0
- package/dist/src/core/policy-conflict.d.ts +64 -0
- package/dist/src/core/policy-conflict.d.ts.map +1 -0
- package/dist/src/core/policy-conflict.js +177 -0
- package/dist/src/core/policy-conflict.js.map +1 -0
- package/dist/src/index.d.ts +6 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +6 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/types/gateway.d.ts +59 -0
- package/dist/src/types/gateway.d.ts.map +1 -1
- package/dist/src/types/oracle-witness.d.ts +77 -0
- package/dist/src/types/oracle-witness.d.ts.map +1 -0
- package/dist/src/types/oracle-witness.js +11 -0
- package/dist/src/types/oracle-witness.js.map +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/agent-passport-system)
|
|
4
4
|
[](https://github.com/aeoess/agent-passport-system/blob/main/LICENSE)
|
|
5
|
-
[](https://github.com/aeoess/agent-passport-system)
|
|
6
6
|
[](https://doi.org/10.5281/zenodo.18749779)
|
|
7
7
|
|
|
8
8
|
Cryptographic identity, ethical governance, economic attribution, protocol-native communication, intent architecture, cascade revocation, coordination primitives, and agentic commerce for autonomous AI agents.
|
|
@@ -285,14 +285,14 @@ const receipt = await completeCheckout(session.id, {
|
|
|
285
285
|
|
|
286
286
|
// Verify any commerce receipt (tamper-proof)
|
|
287
287
|
const valid = verifyCommerceReceipt(receipt)
|
|
288
|
-
// → true (
|
|
288
|
+
// → true (Ed25519 signature over canonical JSON)
|
|
289
289
|
|
|
290
290
|
// Track spending against delegation limits
|
|
291
291
|
const summary = getSpendSummary(delegation, allReceipts)
|
|
292
292
|
// → { limit: 500, spent: 49.99, remaining: 450.01, utilization: '10.0%', nearLimit: false }
|
|
293
293
|
```
|
|
294
294
|
|
|
295
|
-
**4-gate enforcement pipeline:** Every purchase passes through passport verification (
|
|
295
|
+
**4-gate enforcement pipeline:** Every purchase passes through passport verification (Ed25519 signature), delegation scope check (must have `commerce:checkout`), spend limit enforcement (amount ≤ remaining budget), and optional merchant allowlist. Agents cannot bypass gates — the cryptography prevents it.
|
|
296
296
|
|
|
297
297
|
**Human approval thresholds:** Purchases above a configurable amount require explicit human confirmation. The agent generates an approval request; the human signs it. No unsigned approvals accepted.
|
|
298
298
|
|
|
@@ -319,7 +319,7 @@ const summary = getSpendSummary(delegation, allReceipts)
|
|
|
319
319
|
│ consensus · Precedent memory · Signed outcomes │
|
|
320
320
|
├─────────────────────────────────────────────────┤
|
|
321
321
|
│ Layer 4: Agent Agora │
|
|
322
|
-
│
|
|
322
|
+
│ Ed25519 signed messages · Registry · │
|
|
323
323
|
│ Threading · Public observability │
|
|
324
324
|
├─────────────────────────────────────────────────┤
|
|
325
325
|
│ Layer 3: Beneficiary Attribution │
|
|
@@ -331,18 +331,18 @@ const summary = getSpendSummary(delegation, allReceipts)
|
|
|
331
331
|
│ Compliance verification · Agent negotiation │
|
|
332
332
|
├─────────────────────────────────────────────────┤
|
|
333
333
|
│ Layer 1: Agent Passport Protocol │
|
|
334
|
-
│
|
|
334
|
+
│ Ed25519 identity · Scoped delegation · │
|
|
335
335
|
│ Signed receipts · Revocation · Reputation │
|
|
336
336
|
└─────────────────────────────────────────────────┘
|
|
337
337
|
```
|
|
338
338
|
|
|
339
|
-
**Layer 1 — Identity & Accountability.**
|
|
339
|
+
**Layer 1 — Identity & Accountability.** Ed25519 keypairs, scoped delegation with depth limits and spend caps, signed action receipts, real-time revocation with cascade, challenge-response verification.
|
|
340
340
|
|
|
341
341
|
**Layer 2 — Human Values Floor.** Seven universal principles. Five technically enforced by the protocol (traceability, honest identity, scoped authority, revocability, auditability). Two attested through cryptographic commitment. Compliance verifiable against receipts. Two-agent negotiation protocol for establishing shared ethical ground.
|
|
342
342
|
|
|
343
343
|
**Layer 3 — Beneficiary Attribution.** Every agent action traces to a human through the delegation chain. SHA-256 Merkle trees commit to receipt sets in 32 bytes. 100,000 receipts → provable with ~17 hashes. Configurable scope weights per domain. Logarithmic spend normalization prevents gaming.
|
|
344
344
|
|
|
345
|
-
**Layer 4 — Agent Agora.** Protocol-native communication where every message is
|
|
345
|
+
**Layer 4 — Agent Agora.** Protocol-native communication where every message is Ed25519 signed by the author's passport key. Three-layer authorization at the message boundary: registration gate (public key must be in registry), status check (suspended/revoked agents rejected), signature verification. Agent registry for membership verification. Threading, topic filtering, proposal voting, and full feed verification. Web interface at [aeoess.com/agora](https://aeoess.com/agora.html) for human observation.
|
|
346
346
|
|
|
347
347
|
**Layer 5 — Intent Architecture.** Context tells agents what they know. Intent tells them what to care about. Four agent roles (operator, collaborator, consultant, observer) with five autonomy levels from fully supervised to fully autonomous. Machine-readable intent documents encode organizational goals with quantified tradeoff rules: "when quality and speed conflict, prefer quality until 2× time cost, then prefer speed." Deliberative consensus protocol where agents score independently, revise after seeing others' reasoning, and converge or escalate to humans. Every resolved deliberation becomes a citable precedent. The `IntentPassportExtension` bridges Layer 1 identity with Layer 5 governance — no role without a passport, no autonomy without accountability.
|
|
348
348
|
|
|
@@ -350,7 +350,7 @@ const summary = getSpendSummary(delegation, allReceipts)
|
|
|
350
350
|
|
|
351
351
|
**Layer 7 — Coordination Primitives.** Protocol-native multi-agent task orchestration. Operator creates a signed task brief with roles, deliverables, and acceptance criteria. Agents are assigned to roles and sign acceptance. Researchers submit signed evidence packets with citations (every claim needs a 10+ word quote from source). Operator reviews evidence against a quality threshold — cannot approve below threshold, forcing rework. Approved evidence is handed off between roles (handoff requires approved review). Analysts submit deliverables citing evidence packets. Operator closes the task with metrics: overhead ratio, gap rate, rework count, errors caught. Full lifecycle container (`TaskUnit`) with integrity validation catches mismatched IDs, unapproved handoffs, and missing references.
|
|
352
352
|
|
|
353
|
-
**Layer 8 — Agentic Commerce (ACP by OpenAI + Stripe).** Implements the [Agentic Commerce Protocol](https://openai.com/index/agentic-commerce-protocol/) identity and governance layer. 4-gate enforcement pipeline: passport verification (
|
|
353
|
+
**Layer 8 — Agentic Commerce (ACP by OpenAI + Stripe).** Implements the [Agentic Commerce Protocol](https://openai.com/index/agentic-commerce-protocol/) identity and governance layer. 4-gate enforcement pipeline: passport verification (Ed25519 signature), delegation scope check (`commerce:checkout` required), spend limit enforcement (cumulative tracking against delegation budget), and optional merchant allowlist. Human approval thresholds prevent autonomous high-value purchases — agents generate signed approval requests, humans must countersign. Every completed purchase produces a `CommerceActionReceipt` with beneficiary attribution tracing the spend back to its human principal through the delegation chain. Spend analytics with utilization warnings at 80%. 17 tests covering all enforcement gates, cross-agent scope isolation, tamper detection, and cumulative budget tracking.
|
|
354
354
|
|
|
355
355
|
## Human Values Floor — v0.1
|
|
356
356
|
|
|
@@ -380,9 +380,9 @@ Or zero-install remote mode:
|
|
|
380
380
|
npx agent-passport-system-mcp setup --remote
|
|
381
381
|
```
|
|
382
382
|
|
|
383
|
-
**61 tools across all 27 modules, role-scoped access control.** Identity, delegation, agora, values/policy, coordination, and commerce — all accessible via MCP. Every operation
|
|
383
|
+
**61 tools across all 27 modules, role-scoped access control.** Identity, delegation, agora, values/policy, coordination, and commerce — all accessible via MCP. Every operation Ed25519 signed. Auto-configures Claude Desktop and Cursor.
|
|
384
384
|
|
|
385
|
-
Every operation is
|
|
385
|
+
Every operation is Ed25519 signed. Role is auto-detected from task assignments. Role-specific prompts served via MCP prompts API. File-backed task persistence at `~/.agent-passport-tasks.json`.
|
|
386
386
|
|
|
387
387
|
npm: [agent-passport-system-mcp](https://www.npmjs.com/package/agent-passport-system-mcp) · GitHub: [aeoess/agent-passport-mcp](https://github.com/aeoess/agent-passport-mcp)
|
|
388
388
|
|
|
@@ -394,7 +394,7 @@ Full Python implementation with cross-language compatibility. Signatures created
|
|
|
394
394
|
pip install agent-passport-system
|
|
395
395
|
```
|
|
396
396
|
|
|
397
|
-
All
|
|
397
|
+
All 8 foundational layers plus Principal Identity. 86 tests. Same canonical JSON serialization and Ed25519 signatures. Extended modules (M10-M27) in progress.
|
|
398
398
|
|
|
399
399
|
PyPI: [agent-passport-system](https://pypi.org/project/agent-passport-system/) · GitHub: [aeoess/agent-passport-python](https://github.com/aeoess/agent-passport-python)
|
|
400
400
|
|
|
@@ -402,10 +402,10 @@ PyPI: [agent-passport-system](https://pypi.org/project/agent-passport-system/)
|
|
|
402
402
|
|
|
403
403
|
```bash
|
|
404
404
|
npm test
|
|
405
|
-
# 785 tests across
|
|
405
|
+
# 785 tests across 43 files, 220 suites, 0 failures
|
|
406
406
|
```
|
|
407
407
|
|
|
408
|
-
Includes
|
|
408
|
+
Includes 73 adversarial tests across 4 test files: Merkle tree tampering, attribution gaming resistance, compliance violations, floor negotiation attacks, wrong-key attestations, cross-chain confused deputy, taint laundering, permit bypass, causal chain manipulation.
|
|
409
409
|
|
|
410
410
|
15 Agora-specific tests: message signing, tamper detection, registry membership, feed operations, threading, full feed verification.
|
|
411
411
|
|
|
@@ -426,7 +426,7 @@ By Tymofii Pidlisnyi — Published on Zenodo
|
|
|
426
426
|
| | Social Contract | DeepMind | GaaS | OpenAI | LOKA |
|
|
427
427
|
|---|---|---|---|---|---|
|
|
428
428
|
| Status | Running code | Paper | Simulated | Advisory | Paper |
|
|
429
|
-
| Identity |
|
|
429
|
+
| Identity | Ed25519 | Proposed | External | — | Proposed |
|
|
430
430
|
| Delegation depth | Configurable | Proposed | N/A | — | Consensus |
|
|
431
431
|
| Action receipts | Signed + verifiable | Proposed | Logs | General | — |
|
|
432
432
|
| Values layer | Attested + auditable | — | Rules | — | — |
|
|
@@ -434,16 +434,16 @@ By Tymofii Pidlisnyi — Published on Zenodo
|
|
|
434
434
|
| Communication | Signed Agora | — | — | — | — |
|
|
435
435
|
| Coordination | Task units + MCP server | — | — | — | — |
|
|
436
436
|
| Commerce | ACP + 4-gate enforcement | — | — | — | — |
|
|
437
|
-
| Tests |
|
|
437
|
+
| Tests | 785 (73 adversarial) | None | Limited | None | None |
|
|
438
438
|
| Dependencies | Node.js crypto + uuid | — | Multi-LLM | — | Consensus network |
|
|
439
439
|
|
|
440
440
|
## Structure
|
|
441
441
|
|
|
442
442
|
```
|
|
443
|
-
src/
|
|
443
|
+
src/ 32 source files
|
|
444
444
|
contract.ts — High-level API (6 functions)
|
|
445
445
|
core/
|
|
446
|
-
passport.ts —
|
|
446
|
+
passport.ts — Ed25519 identity
|
|
447
447
|
delegation.ts — Scoped delegation, receipts, cascade revocation
|
|
448
448
|
canonical.ts — Deterministic JSON serialization
|
|
449
449
|
values.ts — Floor attestation, compliance, negotiation
|
|
@@ -462,10 +462,23 @@ src/ 22 source files
|
|
|
462
462
|
euaiact.ts — EU AI Act compliance
|
|
463
463
|
principal.ts — Principal identity, endorsement, fleet
|
|
464
464
|
reputation-authority.ts — Bayesian trust, tier authority, promotions
|
|
465
|
+
gateway.ts — ProxyGateway enforcement boundary
|
|
466
|
+
cross-chain.ts — Taint tracking, confused deputy prevention, SAOs
|
|
467
|
+
encrypted-messaging.ts — E2E encrypted Agora messages (X25519 + XSalsa20)
|
|
468
|
+
obligations.ts — Duties on delegations, penalty severity narrowing
|
|
469
|
+
execution-envelope.ts — Cross-engine signed execution envelopes
|
|
470
|
+
intent-network.ts — IntentCards, semantic matching, introductions
|
|
471
|
+
governance.ts — Governance artifact provenance, weakening controls
|
|
472
|
+
identity.ts — Key rotation with continuity proofs
|
|
473
|
+
receipt-ledger.ts — Merkle-committed audit batches
|
|
474
|
+
feasibility.ts — Preflight linting for delegations and tasks
|
|
475
|
+
precedent.ts — Normative precedent library, drift detection
|
|
476
|
+
reanchor.ts — Delegation re-anchoring to DIDs
|
|
477
|
+
escalation.ts — Bounded escalation (4th attenuation invariant)
|
|
465
478
|
cli/
|
|
466
479
|
index.ts — CLI (14 commands)
|
|
467
480
|
crypto/
|
|
468
|
-
keys.ts —
|
|
481
|
+
keys.ts — Ed25519 primitives
|
|
469
482
|
types/
|
|
470
483
|
passport.ts — Layers 1–3 types
|
|
471
484
|
agora.ts — Layer 4 types
|
|
@@ -481,6 +494,9 @@ src/ 22 source files
|
|
|
481
494
|
reputation-authority.ts — Reputation/tier types
|
|
482
495
|
tests/ 43 test files, 785 tests (220 suites)
|
|
483
496
|
adversarial.ts — 23 adversarial cases
|
|
497
|
+
adversarial-paper.test.ts — 22 paper-linked attack scenarios
|
|
498
|
+
adversarial-causal-chain.test.ts — 18 causal chain attacks
|
|
499
|
+
adversarial-audit-v2.test.ts — 10 gateway audit attack vectors
|
|
484
500
|
agora.test.ts — 15 Agora tests
|
|
485
501
|
contract.test.ts — High-level API tests
|
|
486
502
|
passport.test.ts — v1.0 primitives
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { type ActiveEscalation, type EscalationGrant } from './escalation.js';
|
|
2
|
+
import type { GovernanceArtifact, GovernanceEnvelope, GovernanceDiff } from '../types/governance.js';
|
|
1
3
|
import type { Delegation, FloorAttestation } from '../types/passport.js';
|
|
2
4
|
import type { PolicyDecision } from '../types/policy.js';
|
|
3
5
|
import type { CrossChainPermit, ExecutionFrame } from '../types/cross-chain.js';
|
|
@@ -51,6 +53,36 @@ export declare class ProxyGateway {
|
|
|
51
53
|
getAgentTier(agentId: string): AuthorityTier | undefined;
|
|
52
54
|
/** Externally set agent reputation (for injection from external reputation systems) */
|
|
53
55
|
setAgentReputation(agentId: string, reputation: ScopedReputation): boolean;
|
|
56
|
+
/** Update the gateway's governance artifact. Enforces INV-2: governance can only
|
|
57
|
+
* strengthen; weakening requires higher-order authorization (more approvals). */
|
|
58
|
+
updateGovernance(envelope: GovernanceEnvelope, previousArtifact?: GovernanceArtifact | null): {
|
|
59
|
+
accepted: boolean;
|
|
60
|
+
error?: string;
|
|
61
|
+
diff?: GovernanceDiff;
|
|
62
|
+
};
|
|
63
|
+
/** Re-attest an agent to the current governance version after an update. */
|
|
64
|
+
reattestGovernance(agentId: string): {
|
|
65
|
+
success: boolean;
|
|
66
|
+
error?: string;
|
|
67
|
+
};
|
|
68
|
+
/** Get current governance artifact version */
|
|
69
|
+
getGovernanceVersion(): string | undefined;
|
|
70
|
+
/** Get agent's attested governance version */
|
|
71
|
+
getAgentGovernanceVersion(agentId: string): string | undefined;
|
|
72
|
+
/** Add an escalation grant for an agent */
|
|
73
|
+
addEscalationGrant(agentId: string, grant: EscalationGrant): {
|
|
74
|
+
added: boolean;
|
|
75
|
+
error?: string;
|
|
76
|
+
};
|
|
77
|
+
/** Activate an escalation for an agent (gateway validates and activates) */
|
|
78
|
+
activateAgentEscalation(agentId: string, escalation: ActiveEscalation): {
|
|
79
|
+
activated: boolean;
|
|
80
|
+
error?: string;
|
|
81
|
+
};
|
|
82
|
+
/** Get active escalations for an agent */
|
|
83
|
+
getAgentEscalations(agentId: string): ActiveEscalation[];
|
|
84
|
+
/** Expire stale escalations for an agent */
|
|
85
|
+
private _expireAgentEscalations;
|
|
54
86
|
private findDelegation;
|
|
55
87
|
private buildValidationContext;
|
|
56
88
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../../src/core/gateway.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../../src/core/gateway.ts"],"names":[],"mappings":"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"}
|
package/dist/src/core/gateway.js
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
//
|
|
25
25
|
// ══════════════════════════════════════════════════════════════════
|
|
26
26
|
import { v4 as uuidv4 } from 'uuid';
|
|
27
|
-
import { verify } from '../crypto/keys.js';
|
|
27
|
+
import { verify, sign as signData } from '../crypto/keys.js';
|
|
28
28
|
import { canonicalize } from './canonical.js';
|
|
29
29
|
import { createActionIntent, evaluateIntent, createPolicyReceipt, FloorValidatorV1 } from './policy.js';
|
|
30
30
|
import { verifyDelegation, createReceipt, scopeAuthorizes, getRevocation } from './delegation.js';
|
|
@@ -33,6 +33,9 @@ import { verifyAttestation } from './values.js';
|
|
|
33
33
|
import { createTaintLabel, createSAO, createExecutionFrame, recordAccess, checkDataFlow, mergeTaints, verifyCrossChainPermit, isFrameExpired, rotateFrame } from './cross-chain.js';
|
|
34
34
|
import { checkFulfillment, resolveObligation } from './obligations.js';
|
|
35
35
|
import { createExecutionEnvelope } from './execution-envelope.js';
|
|
36
|
+
import { loadGovernanceArtifact as loadGovArtifact } from './governance.js';
|
|
37
|
+
import { checkEscalatedAction, isEscalationActive } from './escalation.js';
|
|
38
|
+
import { DEFAULT_LOAD_POLICY } from '../types/governance.js';
|
|
36
39
|
import { computeEffectiveScore, createScopedReputation, resolveAuthorityTier, checkTierForIntent, updateReputationFromResult, shouldDemote, triggerDemotion, DEFAULT_TIERS } from './reputation-authority.js';
|
|
37
40
|
// ══════════════════════════════════════
|
|
38
41
|
// PROXY GATEWAY CLASS
|
|
@@ -65,7 +68,15 @@ export class ProxyGateway {
|
|
|
65
68
|
obligationsTerminated: 0,
|
|
66
69
|
tierDenials: 0,
|
|
67
70
|
reputationUpdates: 0,
|
|
68
|
-
demotions: 0
|
|
71
|
+
demotions: 0,
|
|
72
|
+
governanceUpdates: 0,
|
|
73
|
+
governanceWeakeningBlocked: 0,
|
|
74
|
+
governanceStaleBlocks: 0,
|
|
75
|
+
escalationsActivated: 0,
|
|
76
|
+
escalationsUsed: 0,
|
|
77
|
+
escalationsExpired: 0,
|
|
78
|
+
escalationsDenied: 0,
|
|
79
|
+
reversibilityDenied: 0
|
|
69
80
|
};
|
|
70
81
|
constructor(config, executor) {
|
|
71
82
|
this.config = {
|
|
@@ -123,6 +134,10 @@ export class ProxyGateway {
|
|
|
123
134
|
obligations: this.config.enableObligationMonitoring ? [] : undefined,
|
|
124
135
|
reputation,
|
|
125
136
|
authorityTier,
|
|
137
|
+
governanceVersion: this.config.enableGovernanceEnforcement && this.config.governanceEnvelope
|
|
138
|
+
? this.config.governanceEnvelope.artifact.version : undefined,
|
|
139
|
+
escalationGrants: this.config.enableEscalation ? [] : undefined,
|
|
140
|
+
activeEscalations: this.config.enableEscalation ? [] : undefined,
|
|
126
141
|
});
|
|
127
142
|
this.stats.activeAgents = this.agents.size;
|
|
128
143
|
return { registered: true };
|
|
@@ -235,19 +250,89 @@ export class ProxyGateway {
|
|
|
235
250
|
return { executed: false, requestId: request.requestId, denialReason: 'Invalid request signature' };
|
|
236
251
|
}
|
|
237
252
|
// Step 2: Find and verify delegation
|
|
238
|
-
|
|
253
|
+
let delegation = this.findDelegation(agent, request);
|
|
254
|
+
let viaEscalation = false;
|
|
255
|
+
let usedEscalationId;
|
|
256
|
+
let escalationDelegation;
|
|
239
257
|
if (!delegation) {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
258
|
+
// Step 2.1: Escalation fallback (Module 27 / INV-4)
|
|
259
|
+
// If no delegation covers this action, check for active escalation grants
|
|
260
|
+
if (this.config.enableEscalation && agent.activeEscalations) {
|
|
261
|
+
// Expire stale escalations first
|
|
262
|
+
this._expireAgentEscalations(agent);
|
|
263
|
+
const esc = agent.activeEscalations.find(e => {
|
|
264
|
+
if (!isEscalationActive(e))
|
|
265
|
+
return false;
|
|
266
|
+
const grant = agent.escalationGrants?.find(g => g.grantId === e.grantId);
|
|
267
|
+
if (!grant)
|
|
268
|
+
return false;
|
|
269
|
+
const check = checkEscalatedAction({
|
|
270
|
+
escalation: e, grant,
|
|
271
|
+
action: request.scopeRequired,
|
|
272
|
+
actionClass: 'tentative', // default — gateway can only do tentative via escalation
|
|
273
|
+
spend: request.spend?.amount,
|
|
274
|
+
});
|
|
275
|
+
return check.permitted;
|
|
276
|
+
});
|
|
277
|
+
if (esc) {
|
|
278
|
+
viaEscalation = true;
|
|
279
|
+
usedEscalationId = esc.escalationId;
|
|
280
|
+
// Track spend
|
|
281
|
+
if (request.spend) {
|
|
282
|
+
esc.spentDuringEscalation += request.spend.amount;
|
|
283
|
+
}
|
|
284
|
+
this.stats.escalationsUsed = (this.stats.escalationsUsed ?? 0) + 1;
|
|
285
|
+
this.config.onEscalationUsed?.(request.agentId, esc.escalationId, request.tool);
|
|
286
|
+
// Use the first delegation from agent's set as the base for intent creation
|
|
287
|
+
// (escalation extends beyond delegation scope, but we need a delegation for the 3-sig chain)
|
|
288
|
+
escalationDelegation = agent.delegations.values().next().value;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
if (!viaEscalation) {
|
|
292
|
+
this.stats.totalDenied++;
|
|
293
|
+
return {
|
|
294
|
+
executed: false, requestId: request.requestId,
|
|
295
|
+
denialReason: `No valid delegation covers scope "${request.scopeRequired}" for tool "${request.tool}"`
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
// Use escalation delegation as base
|
|
299
|
+
delegation = escalationDelegation;
|
|
245
300
|
}
|
|
246
301
|
const delegationStatus = verifyDelegation(delegation);
|
|
247
302
|
if (!delegationStatus.valid || delegationStatus.expired || delegationStatus.revoked) {
|
|
248
303
|
this.stats.totalDenied++;
|
|
249
304
|
return { executed: false, requestId: request.requestId, denialReason: `Delegation ${delegation.delegationId} is no longer valid` };
|
|
250
305
|
}
|
|
306
|
+
// Step 2.5: Governance staleness check (Module 21 / INV-2)
|
|
307
|
+
// If governance enforcement is enabled and the agent's attested version doesn't
|
|
308
|
+
// match the current governance version, block the action until re-attestation.
|
|
309
|
+
if (this.config.enableGovernanceEnforcement && this.config.governanceEnvelope) {
|
|
310
|
+
const currentVersion = this.config.governanceEnvelope.artifact.version;
|
|
311
|
+
const agentVersion = agent.governanceVersion;
|
|
312
|
+
if (agentVersion !== currentVersion) {
|
|
313
|
+
this.stats.totalDenied++;
|
|
314
|
+
this.stats.governanceStaleBlocks = (this.stats.governanceStaleBlocks ?? 0) + 1;
|
|
315
|
+
this.config.onGovernanceStaleBlock?.(request.agentId, agentVersion ?? 'none', currentVersion);
|
|
316
|
+
return {
|
|
317
|
+
executed: false, requestId: request.requestId,
|
|
318
|
+
denialReason: `Governance stale: agent attested to v${agentVersion ?? 'none'}, current is v${currentVersion}. Re-attestation required.`
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
// Step 2.6: Reversibility check (Gap 3 taxonomy)
|
|
323
|
+
if (this.config.maxReversibility && request.reversibility) {
|
|
324
|
+
const RANK = { tentative: 0, compensable: 1, irreversible: 2 };
|
|
325
|
+
const maxRank = RANK[this.config.maxReversibility] ?? 2;
|
|
326
|
+
const actionRank = RANK[request.reversibility] ?? 2;
|
|
327
|
+
if (actionRank > maxRank) {
|
|
328
|
+
this.stats.totalDenied++;
|
|
329
|
+
this.stats.reversibilityDenied = (this.stats.reversibilityDenied ?? 0) + 1;
|
|
330
|
+
return {
|
|
331
|
+
executed: false, requestId: request.requestId,
|
|
332
|
+
denialReason: `Action reversibility "${request.reversibility}" exceeds gateway max "${this.config.maxReversibility}"`
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
}
|
|
251
336
|
// Step 3: Create intent
|
|
252
337
|
const intent = createActionIntent({
|
|
253
338
|
agentId: this.config.gatewayId,
|
|
@@ -264,6 +349,16 @@ export class ProxyGateway {
|
|
|
264
349
|
});
|
|
265
350
|
// Step 4: Evaluate intent against policy
|
|
266
351
|
const validationCtx = this.buildValidationContext(agent, delegation);
|
|
352
|
+
// INV-4: Override scope for escalated actions — use escalation's effective scope
|
|
353
|
+
if (viaEscalation && usedEscalationId) {
|
|
354
|
+
const esc = agent.activeEscalations?.find(e => e.escalationId === usedEscalationId);
|
|
355
|
+
if (esc) {
|
|
356
|
+
validationCtx.delegation.scope = esc.effectiveScope;
|
|
357
|
+
if (esc.effectiveSpendLimit !== undefined) {
|
|
358
|
+
validationCtx.delegation.spendLimit = esc.effectiveSpendLimit;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
267
362
|
const decision = evaluateIntent({
|
|
268
363
|
intent,
|
|
269
364
|
evaluatorId: this.config.gatewayId,
|
|
@@ -419,25 +514,55 @@ export class ProxyGateway {
|
|
|
419
514
|
sao = createSAO(toolResult.result, taintLabel, this.config.gatewayPrivateKey, this.config.gatewayPublicKey);
|
|
420
515
|
}
|
|
421
516
|
// Step 7: Generate receipt (GATEWAY signs, not agent)
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
:
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
517
|
+
// For escalated actions, build receipt directly (base delegation's scope doesn't cover
|
|
518
|
+
// the escalated action — that's the whole point of escalation). The gateway IS the
|
|
519
|
+
// enforcement boundary and is authorized to sign receipts for escalated actions.
|
|
520
|
+
let receipt;
|
|
521
|
+
if (viaEscalation && usedEscalationId) {
|
|
522
|
+
const receiptData = {
|
|
523
|
+
receiptId: 'rcpt_' + uuidv4().slice(0, 12),
|
|
524
|
+
version: '1.1',
|
|
525
|
+
timestamp: new Date().toISOString(),
|
|
526
|
+
agentId: this.config.gatewayId,
|
|
527
|
+
delegationId: delegation.delegationId,
|
|
528
|
+
action: {
|
|
529
|
+
type: `gateway:${request.tool}`,
|
|
530
|
+
target: JSON.stringify(request.params),
|
|
531
|
+
scopeUsed: request.scopeRequired,
|
|
532
|
+
spend: request.spend
|
|
533
|
+
},
|
|
534
|
+
result: {
|
|
535
|
+
status: toolResult.success ? 'success' : 'failure',
|
|
536
|
+
summary: toolResult.success
|
|
537
|
+
? `Executed ${request.tool} via escalation ${usedEscalationId}`
|
|
538
|
+
: `Executed ${request.tool} via escalation with error: ${toolResult.error}`
|
|
539
|
+
},
|
|
540
|
+
delegationChain: [this.config.gatewayPublicKey],
|
|
541
|
+
};
|
|
542
|
+
const canonical = canonicalize(receiptData);
|
|
543
|
+
receipt = { ...receiptData, signature: signData(canonical, this.config.gatewayPrivateKey) };
|
|
544
|
+
}
|
|
545
|
+
else {
|
|
546
|
+
receipt = createReceipt({
|
|
547
|
+
agentId: this.config.gatewayId,
|
|
548
|
+
delegationId: delegation.delegationId,
|
|
549
|
+
delegation: delegation,
|
|
550
|
+
action: {
|
|
551
|
+
type: `gateway:${request.tool}`,
|
|
552
|
+
target: JSON.stringify(request.params),
|
|
553
|
+
scopeUsed: request.scopeRequired,
|
|
554
|
+
spend: request.spend
|
|
555
|
+
},
|
|
556
|
+
result: {
|
|
557
|
+
status: toolResult.success ? 'success' : 'failure',
|
|
558
|
+
summary: toolResult.success
|
|
559
|
+
? `Executed ${request.tool} successfully`
|
|
560
|
+
: `Executed ${request.tool} with error: ${toolResult.error}`
|
|
561
|
+
},
|
|
562
|
+
delegationChain: [this.config.gatewayPublicKey],
|
|
563
|
+
privateKey: this.config.gatewayPrivateKey
|
|
564
|
+
});
|
|
565
|
+
}
|
|
441
566
|
// Step 8: Create policy receipt (links all 3 signatures)
|
|
442
567
|
const policyReceipt = createPolicyReceipt({
|
|
443
568
|
intent,
|
|
@@ -551,7 +676,10 @@ export class ProxyGateway {
|
|
|
551
676
|
sao, flowCheck: flowCheckResult,
|
|
552
677
|
obligationResolutions: obligationResolutions.length > 0 ? obligationResolutions : undefined,
|
|
553
678
|
envelope,
|
|
554
|
-
tierCheck
|
|
679
|
+
tierCheck,
|
|
680
|
+
viaEscalation: viaEscalation || undefined,
|
|
681
|
+
escalationId: usedEscalationId,
|
|
682
|
+
reversibility: request.reversibility,
|
|
555
683
|
};
|
|
556
684
|
this.config.onToolCall?.(request, result);
|
|
557
685
|
return result;
|
|
@@ -666,6 +794,23 @@ export class ProxyGateway {
|
|
|
666
794
|
agent.executionFrame = fresh;
|
|
667
795
|
}
|
|
668
796
|
}
|
|
797
|
+
// Governance staleness recheck at execution time (Module 21 / INV-2)
|
|
798
|
+
// Even if the approval was granted under the old governance, execution
|
|
799
|
+
// must verify the agent's attestation is still current.
|
|
800
|
+
if (this.config.enableGovernanceEnforcement && this.config.governanceEnvelope) {
|
|
801
|
+
const currentVersion = this.config.governanceEnvelope.artifact.version;
|
|
802
|
+
const agentVersion = agent.governanceVersion;
|
|
803
|
+
if (agentVersion !== currentVersion) {
|
|
804
|
+
this.stats.totalDenied++;
|
|
805
|
+
this.stats.governanceStaleBlocks = (this.stats.governanceStaleBlocks ?? 0) + 1;
|
|
806
|
+
this.config.onGovernanceStaleBlock?.(approval.agentId, agentVersion ?? 'none', currentVersion);
|
|
807
|
+
return {
|
|
808
|
+
executed: false, requestId: approval.requestId,
|
|
809
|
+
denialReason: `Governance stale at execution: agent attested to v${agentVersion ?? 'none'}, current is v${currentVersion}`,
|
|
810
|
+
decision: approval.decision
|
|
811
|
+
};
|
|
812
|
+
}
|
|
813
|
+
}
|
|
669
814
|
// Cross-chain data flow check (Module 18)
|
|
670
815
|
let flowCheckResult;
|
|
671
816
|
if (this.config.enableCrossChainEnforcement && agent.executionFrame) {
|
|
@@ -912,6 +1057,122 @@ export class ProxyGateway {
|
|
|
912
1057
|
};
|
|
913
1058
|
return true;
|
|
914
1059
|
}
|
|
1060
|
+
// ── Governance Enforcement (Module 21 / INV-2) ──
|
|
1061
|
+
/** Update the gateway's governance artifact. Enforces INV-2: governance can only
|
|
1062
|
+
* strengthen; weakening requires higher-order authorization (more approvals). */
|
|
1063
|
+
updateGovernance(envelope, previousArtifact) {
|
|
1064
|
+
if (!this.config.enableGovernanceEnforcement) {
|
|
1065
|
+
return { accepted: false, error: 'Governance enforcement not enabled' };
|
|
1066
|
+
}
|
|
1067
|
+
const policy = this.config.governanceLoadPolicy ?? DEFAULT_LOAD_POLICY;
|
|
1068
|
+
const verification = loadGovArtifact(envelope, policy, previousArtifact ?? this.config.governanceEnvelope?.artifact ?? null);
|
|
1069
|
+
if (!verification.valid) {
|
|
1070
|
+
// Check specifically for weakening block
|
|
1071
|
+
if (!verification.weakeningApproved) {
|
|
1072
|
+
this.stats.governanceWeakeningBlocked = (this.stats.governanceWeakeningBlocked ?? 0) + 1;
|
|
1073
|
+
this.config.onGovernanceWeakeningBlocked?.(envelope.artifact, verification.errors.join('; '));
|
|
1074
|
+
}
|
|
1075
|
+
return { accepted: false, error: verification.errors.join('; ') };
|
|
1076
|
+
}
|
|
1077
|
+
// Compute diff if we have a previous artifact
|
|
1078
|
+
let diff;
|
|
1079
|
+
if (this.config.governanceEnvelope) {
|
|
1080
|
+
const prev = this.config.governanceEnvelope.artifact;
|
|
1081
|
+
// Extract principle IDs or item identifiers from content for diff
|
|
1082
|
+
// Use additions/removals from the artifact metadata
|
|
1083
|
+
diff = {
|
|
1084
|
+
changeType: envelope.artifact.changeType,
|
|
1085
|
+
additions: envelope.artifact.additions,
|
|
1086
|
+
modifications: envelope.artifact.modifications,
|
|
1087
|
+
removals: envelope.artifact.removals,
|
|
1088
|
+
isWeakening: envelope.artifact.removals.length > 0,
|
|
1089
|
+
isStrengthening: envelope.artifact.additions.length > 0 && envelope.artifact.removals.length === 0,
|
|
1090
|
+
};
|
|
1091
|
+
}
|
|
1092
|
+
// Accept the update
|
|
1093
|
+
this.config.governanceEnvelope = envelope;
|
|
1094
|
+
this.stats.governanceUpdates = (this.stats.governanceUpdates ?? 0) + 1;
|
|
1095
|
+
this.config.onGovernanceChange?.(diff ?? {
|
|
1096
|
+
changeType: 'initial', additions: [], modifications: [], removals: [],
|
|
1097
|
+
isWeakening: false, isStrengthening: false,
|
|
1098
|
+
}, envelope.artifact);
|
|
1099
|
+
return { accepted: true, diff };
|
|
1100
|
+
}
|
|
1101
|
+
/** Re-attest an agent to the current governance version after an update. */
|
|
1102
|
+
reattestGovernance(agentId) {
|
|
1103
|
+
const agent = this.agents.get(agentId);
|
|
1104
|
+
if (!agent)
|
|
1105
|
+
return { success: false, error: 'Agent not registered' };
|
|
1106
|
+
if (!this.config.enableGovernanceEnforcement)
|
|
1107
|
+
return { success: false, error: 'Governance enforcement not enabled' };
|
|
1108
|
+
if (!this.config.governanceEnvelope)
|
|
1109
|
+
return { success: false, error: 'No governance artifact loaded' };
|
|
1110
|
+
agent.governanceVersion = this.config.governanceEnvelope.artifact.version;
|
|
1111
|
+
return { success: true };
|
|
1112
|
+
}
|
|
1113
|
+
/** Get current governance artifact version */
|
|
1114
|
+
getGovernanceVersion() {
|
|
1115
|
+
return this.config.governanceEnvelope?.artifact.version;
|
|
1116
|
+
}
|
|
1117
|
+
/** Get agent's attested governance version */
|
|
1118
|
+
getAgentGovernanceVersion(agentId) {
|
|
1119
|
+
return this.agents.get(agentId)?.governanceVersion;
|
|
1120
|
+
}
|
|
1121
|
+
// ── Escalation Enforcement (Module 27 / INV-4) ──
|
|
1122
|
+
/** Add an escalation grant for an agent */
|
|
1123
|
+
addEscalationGrant(agentId, grant) {
|
|
1124
|
+
const agent = this.agents.get(agentId);
|
|
1125
|
+
if (!agent)
|
|
1126
|
+
return { added: false, error: 'Agent not registered' };
|
|
1127
|
+
if (!this.config.enableEscalation)
|
|
1128
|
+
return { added: false, error: 'Escalation not enabled' };
|
|
1129
|
+
if (!agent.escalationGrants)
|
|
1130
|
+
agent.escalationGrants = [];
|
|
1131
|
+
agent.escalationGrants.push(grant);
|
|
1132
|
+
return { added: true };
|
|
1133
|
+
}
|
|
1134
|
+
/** Activate an escalation for an agent (gateway validates and activates) */
|
|
1135
|
+
activateAgentEscalation(agentId, escalation) {
|
|
1136
|
+
const agent = this.agents.get(agentId);
|
|
1137
|
+
if (!agent)
|
|
1138
|
+
return { activated: false, error: 'Agent not registered' };
|
|
1139
|
+
if (!this.config.enableEscalation)
|
|
1140
|
+
return { activated: false, error: 'Escalation not enabled' };
|
|
1141
|
+
if (!agent.activeEscalations)
|
|
1142
|
+
agent.activeEscalations = [];
|
|
1143
|
+
// Expire stale ones first
|
|
1144
|
+
this._expireAgentEscalations(agent);
|
|
1145
|
+
// Check max concurrent
|
|
1146
|
+
const maxConcurrent = this.config.maxConcurrentEscalations ?? 1;
|
|
1147
|
+
const activeCount = agent.activeEscalations.filter(e => isEscalationActive(e)).length;
|
|
1148
|
+
if (activeCount >= maxConcurrent) {
|
|
1149
|
+
this.stats.escalationsDenied = (this.stats.escalationsDenied ?? 0) + 1;
|
|
1150
|
+
return { activated: false, error: `Max concurrent escalations reached (${maxConcurrent})` };
|
|
1151
|
+
}
|
|
1152
|
+
agent.activeEscalations.push(escalation);
|
|
1153
|
+
this.stats.escalationsActivated = (this.stats.escalationsActivated ?? 0) + 1;
|
|
1154
|
+
return { activated: true };
|
|
1155
|
+
}
|
|
1156
|
+
/** Get active escalations for an agent */
|
|
1157
|
+
getAgentEscalations(agentId) {
|
|
1158
|
+
const agent = this.agents.get(agentId);
|
|
1159
|
+
if (!agent || !agent.activeEscalations)
|
|
1160
|
+
return [];
|
|
1161
|
+
this._expireAgentEscalations(agent);
|
|
1162
|
+
return agent.activeEscalations.filter(e => isEscalationActive(e));
|
|
1163
|
+
}
|
|
1164
|
+
/** Expire stale escalations for an agent */
|
|
1165
|
+
_expireAgentEscalations(agent) {
|
|
1166
|
+
if (!agent.activeEscalations)
|
|
1167
|
+
return;
|
|
1168
|
+
for (const esc of agent.activeEscalations) {
|
|
1169
|
+
if (esc.status === 'active' && !isEscalationActive(esc)) {
|
|
1170
|
+
esc.status = 'expired';
|
|
1171
|
+
this.stats.escalationsExpired = (this.stats.escalationsExpired ?? 0) + 1;
|
|
1172
|
+
this.config.onEscalationExpired?.(agent.passport.passport.agentId, esc.escalationId);
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
915
1176
|
findDelegation(agent, request) {
|
|
916
1177
|
if (request.delegationId) {
|
|
917
1178
|
const d = agent.delegations.get(request.delegationId);
|