agent-passport-system 1.15.0 → 1.16.1

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 CHANGED
@@ -2,12 +2,12 @@
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/agent-passport-system)](https://www.npmjs.com/package/agent-passport-system)
4
4
  [![license](https://img.shields.io/npm/l/agent-passport-system)](https://github.com/aeoess/agent-passport-system/blob/main/LICENSE)
5
- [![tests](https://img.shields.io/badge/tests-595%20passing-brightgreen)](https://github.com/aeoess/agent-passport-system)
5
+ [![tests](https://img.shields.io/badge/tests-862%20passing-brightgreen)](https://github.com/aeoess/agent-passport-system)
6
6
  [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.18749779.svg)](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.
9
9
 
10
- **27 modules. 785 tests. Zero heavy dependencies. Running code. MCP server included.**
10
+ **35 modules. 862 tests. Zero heavy dependencies. Running code. MCP server included.**
11
11
 
12
12
  > *As AI agents from different creators, running different models, serving different humans begin to collaborate — who is responsible, under what authority, according to what values, and who benefits?*
13
13
 
@@ -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 (Ed25959 signature over canonical JSON)
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 (Ed25959 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.
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
- Ed25959 signed messages · Registry · │
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
- Ed25959 identity · Scoped delegation · │
334
+ Ed25519 identity · Scoped delegation · │
335
335
  │ Signed receipts · Revocation · Reputation │
336
336
  └─────────────────────────────────────────────────┘
337
337
  ```
338
338
 
339
- **Layer 1 — Identity & Accountability.** Ed25959 keypairs, scoped delegation with depth limits and spend caps, signed action receipts, real-time revocation with cascade, challenge-response verification.
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 Ed25959 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.
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 (Ed25959 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.
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 Ed25959 signed. Auto-configures Claude Desktop and Cursor.
383
+ **61 tools across all 35 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 Ed25959 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`.
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 17 protocol modules. 86 tests. Same canonical JSON serialization and Ed25959 signatures.
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 38 files, 220 suites, 0 failures
405
+ # 862 tests across 43 files, 238 suites, 0 failures
406
406
  ```
407
407
 
408
- Includes 23 adversarial tests: Merkle tree tampering, attribution gaming resistance, compliance violations, floor negotiation attacks, wrong-key attestations.
408
+ Includes 50 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 | Ed25959 | Proposed | External | — | Proposed |
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 | 595 (23 adversarial) | None | Limited | None | None |
437
+ | Tests | 862 (50 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/ 22 source files
443
+ src/ 32 source files
444
444
  contract.ts — High-level API (6 functions)
445
445
  core/
446
- passport.ts — Ed25959 identity
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 — Ed25959 primitives
481
+ keys.ts — Ed25519 primitives
469
482
  types/
470
483
  passport.ts — Layers 1–3 types
471
484
  agora.ts — Layer 4 types
@@ -479,8 +492,11 @@ src/ 22 source files
479
492
  euaiact.ts — EU AI Act types
480
493
  principal.ts — Principal identity types
481
494
  reputation-authority.ts — Reputation/tier types
482
- tests/ 43 test files, 785 tests (220 suites)
483
- adversarial.ts — 23 adversarial cases
495
+ tests/ 49 test files, 862 tests (238 suites)
496
+ adversarial.ts — 50 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":"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"}
1
+ {"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../../src/core/gateway.ts"],"names":[],"mappings":"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"}
@@ -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
- const delegation = this.findDelegation(agent, request);
253
+ let delegation = this.findDelegation(agent, request);
254
+ let viaEscalation = false;
255
+ let usedEscalationId;
256
+ let escalationDelegation;
239
257
  if (!delegation) {
240
- this.stats.totalDenied++;
241
- return {
242
- executed: false, requestId: request.requestId,
243
- denialReason: `No valid delegation covers scope "${request.scopeRequired}" for tool "${request.tool}"`
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
- const receipt = createReceipt({
423
- agentId: this.config.gatewayId,
424
- delegationId: delegation.delegationId,
425
- delegation: delegation,
426
- action: {
427
- type: `gateway:${request.tool}`,
428
- target: JSON.stringify(request.params),
429
- scopeUsed: request.scopeRequired,
430
- spend: request.spend
431
- },
432
- result: {
433
- status: toolResult.success ? 'success' : 'failure',
434
- summary: toolResult.success
435
- ? `Executed ${request.tool} successfully`
436
- : `Executed ${request.tool} with error: ${toolResult.error}`
437
- },
438
- delegationChain: [this.config.gatewayPublicKey],
439
- privateKey: this.config.gatewayPrivateKey
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);