@lawreneliang/atel-sdk 0.1.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.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +221 -0
  3. package/dist/anchor/base.d.ts +21 -0
  4. package/dist/anchor/base.js +26 -0
  5. package/dist/anchor/bsc.d.ts +20 -0
  6. package/dist/anchor/bsc.js +25 -0
  7. package/dist/anchor/evm.d.ts +67 -0
  8. package/dist/anchor/evm.js +176 -0
  9. package/dist/anchor/index.d.ts +173 -0
  10. package/dist/anchor/index.js +165 -0
  11. package/dist/anchor/mock.d.ts +43 -0
  12. package/dist/anchor/mock.js +100 -0
  13. package/dist/anchor/solana.d.ts +62 -0
  14. package/dist/anchor/solana.js +190 -0
  15. package/dist/gateway/index.d.ts +278 -0
  16. package/dist/gateway/index.js +520 -0
  17. package/dist/graph/index.d.ts +215 -0
  18. package/dist/graph/index.js +524 -0
  19. package/dist/identity/index.d.ts +114 -0
  20. package/dist/identity/index.js +178 -0
  21. package/dist/index.d.ts +14 -0
  22. package/dist/index.js +16 -0
  23. package/dist/orchestrator/index.d.ts +190 -0
  24. package/dist/orchestrator/index.js +297 -0
  25. package/dist/policy/index.d.ts +100 -0
  26. package/dist/policy/index.js +206 -0
  27. package/dist/proof/index.d.ts +220 -0
  28. package/dist/proof/index.js +541 -0
  29. package/dist/rollback/index.d.ts +76 -0
  30. package/dist/rollback/index.js +91 -0
  31. package/dist/schema/capability-schema.json +52 -0
  32. package/dist/schema/index.d.ts +128 -0
  33. package/dist/schema/index.js +163 -0
  34. package/dist/schema/task-schema.json +69 -0
  35. package/dist/score/index.d.ts +132 -0
  36. package/dist/score/index.js +202 -0
  37. package/dist/service/index.d.ts +34 -0
  38. package/dist/service/index.js +273 -0
  39. package/dist/service/server.d.ts +7 -0
  40. package/dist/service/server.js +22 -0
  41. package/dist/trace/index.d.ts +217 -0
  42. package/dist/trace/index.js +446 -0
  43. package/dist/trust/index.d.ts +84 -0
  44. package/dist/trust/index.js +107 -0
  45. package/dist/trust-sync/index.d.ts +30 -0
  46. package/dist/trust-sync/index.js +57 -0
  47. package/package.json +59 -0
@@ -0,0 +1,178 @@
1
+ import nacl from 'tweetnacl';
2
+ import bs58 from 'bs58';
3
+ import { v4 as uuidv4 } from 'uuid';
4
+ // ─── Custom Errors ───────────────────────────────────────────────
5
+ export class IdentityError extends Error {
6
+ constructor(message) {
7
+ super(message);
8
+ this.name = 'IdentityError';
9
+ }
10
+ }
11
+ export class SignatureError extends Error {
12
+ constructor(message) {
13
+ super(message);
14
+ this.name = 'SignatureError';
15
+ }
16
+ }
17
+ // ─── Core Functions ──────────────────────────────────────────────
18
+ /**
19
+ * Generate an Ed25519 key pair using tweetnacl.
20
+ * @returns A KeyPair containing 32-byte publicKey and 64-byte secretKey.
21
+ */
22
+ export function generateKeyPair() {
23
+ const kp = nacl.sign.keyPair();
24
+ return { publicKey: kp.publicKey, secretKey: kp.secretKey };
25
+ }
26
+ /**
27
+ * Create a DID (Decentralized Identifier) from a public key.
28
+ * Format: "did:atel:<base58(publicKey)>"
29
+ * @param publicKey - The 32-byte Ed25519 public key.
30
+ * @returns The DID string.
31
+ */
32
+ export function createDID(publicKey) {
33
+ if (publicKey.length !== 32) {
34
+ throw new IdentityError(`Invalid public key length: expected 32, got ${publicKey.length}`);
35
+ }
36
+ const encoded = bs58.encode(publicKey);
37
+ return `did:atel:${encoded}`;
38
+ }
39
+ /**
40
+ * Parse a DID string and extract the public key bytes.
41
+ * @param did - A DID string in format "did:atel:<base58>"
42
+ * @returns The decoded 32-byte public key.
43
+ */
44
+ export function parseDID(did) {
45
+ const parts = did.split(':');
46
+ if (parts.length !== 3 || parts[0] !== 'did' || parts[1] !== 'atel') {
47
+ throw new IdentityError(`Invalid DID format: ${did}`);
48
+ }
49
+ try {
50
+ const decoded = bs58.decode(parts[2]);
51
+ if (decoded.length !== 32) {
52
+ throw new IdentityError(`Invalid public key in DID: expected 32 bytes, got ${decoded.length}`);
53
+ }
54
+ return decoded;
55
+ }
56
+ catch (e) {
57
+ if (e instanceof IdentityError)
58
+ throw e;
59
+ throw new IdentityError(`Failed to decode DID: ${e.message}`);
60
+ }
61
+ }
62
+ /**
63
+ * Deterministic JSON serialization — keys sorted recursively.
64
+ * Ensures identical payloads produce identical byte sequences for signing.
65
+ * @param obj - The object to serialize.
66
+ * @returns A deterministic JSON string.
67
+ */
68
+ export function serializePayload(obj) {
69
+ return JSON.stringify(obj, (_key, value) => {
70
+ if (value !== null && typeof value === 'object' && !Array.isArray(value) && !(value instanceof Uint8Array)) {
71
+ const sorted = {};
72
+ for (const k of Object.keys(value).sort()) {
73
+ sorted[k] = value[k];
74
+ }
75
+ return sorted;
76
+ }
77
+ return value;
78
+ });
79
+ }
80
+ /**
81
+ * Sign a payload with an Ed25519 secret key.
82
+ * The payload is first deterministically serialized, then signed.
83
+ * @param payload - The object or string to sign.
84
+ * @param secretKey - The 64-byte Ed25519 secret key.
85
+ * @returns A base64-encoded detached signature.
86
+ */
87
+ export function sign(payload, secretKey) {
88
+ if (secretKey.length !== 64) {
89
+ throw new SignatureError(`Invalid secret key length: expected 64, got ${secretKey.length}`);
90
+ }
91
+ const message = typeof payload === 'string' ? payload : serializePayload(payload);
92
+ const messageBytes = new TextEncoder().encode(message);
93
+ const signature = nacl.sign.detached(messageBytes, secretKey);
94
+ return Buffer.from(signature).toString('base64');
95
+ }
96
+ /**
97
+ * Verify a detached Ed25519 signature against a payload.
98
+ * @param payload - The original object or string that was signed.
99
+ * @param signature - The base64-encoded signature to verify.
100
+ * @param publicKey - The 32-byte Ed25519 public key.
101
+ * @returns True if the signature is valid.
102
+ */
103
+ export function verify(payload, signature, publicKey) {
104
+ if (publicKey.length !== 32) {
105
+ throw new SignatureError(`Invalid public key length: expected 32, got ${publicKey.length}`);
106
+ }
107
+ try {
108
+ const message = typeof payload === 'string' ? payload : serializePayload(payload);
109
+ const messageBytes = new TextEncoder().encode(message);
110
+ const sigBytes = Uint8Array.from(Buffer.from(signature, 'base64'));
111
+ return nacl.sign.detached.verify(messageBytes, sigBytes, publicKey);
112
+ }
113
+ catch {
114
+ return false;
115
+ }
116
+ }
117
+ // ─── AgentIdentity Class ─────────────────────────────────────────
118
+ /**
119
+ * Encapsulates an agent's cryptographic identity.
120
+ * Provides key generation, DID creation, signing, and verification.
121
+ */
122
+ export class AgentIdentity {
123
+ agent_id;
124
+ publicKey;
125
+ secretKey;
126
+ did;
127
+ /** Optional metadata describing the agent */
128
+ metadata;
129
+ /**
130
+ * Create an AgentIdentity from an existing key pair.
131
+ * @param params - Optional agent_id, key pair, and metadata. Generates new keys if omitted.
132
+ */
133
+ constructor(params) {
134
+ if (params?.publicKey && params?.secretKey) {
135
+ this.publicKey = params.publicKey;
136
+ this.secretKey = params.secretKey;
137
+ }
138
+ else {
139
+ const kp = generateKeyPair();
140
+ this.publicKey = kp.publicKey;
141
+ this.secretKey = kp.secretKey;
142
+ }
143
+ this.agent_id = params?.agent_id ?? uuidv4();
144
+ this.did = createDID(this.publicKey);
145
+ this.metadata = params?.metadata;
146
+ }
147
+ /**
148
+ * Sign a payload using this agent's secret key.
149
+ * @param payload - The data to sign.
150
+ * @returns Base64-encoded signature.
151
+ */
152
+ sign(payload) {
153
+ return sign(payload, this.secretKey);
154
+ }
155
+ /**
156
+ * Verify a signature against this agent's public key.
157
+ * @param payload - The original data.
158
+ * @param signature - The base64 signature to verify.
159
+ * @returns True if valid.
160
+ */
161
+ verify(payload, signature) {
162
+ return verify(payload, signature, this.publicKey);
163
+ }
164
+ /**
165
+ * Export identity data (excluding secret key) for sharing.
166
+ */
167
+ toPublic() {
168
+ const pub = {
169
+ agent_id: this.agent_id,
170
+ did: this.did,
171
+ publicKey: Buffer.from(this.publicKey).toString('base64'),
172
+ };
173
+ if (this.metadata) {
174
+ pub.metadata = this.metadata;
175
+ }
176
+ return pub;
177
+ }
178
+ }
@@ -0,0 +1,14 @@
1
+ export * from './identity/index.js';
2
+ export * from './schema/index.js';
3
+ export * from './policy/index.js';
4
+ export * from './gateway/index.js';
5
+ export * from './trace/index.js';
6
+ export * from './proof/index.js';
7
+ export * from './score/index.js';
8
+ export * from './graph/index.js';
9
+ export * from './service/index.js';
10
+ export * from './anchor/index.js';
11
+ export * from './rollback/index.js';
12
+ export * from './trust/index.js';
13
+ export * from './trust-sync/index.js';
14
+ export * from './orchestrator/index.js';
package/dist/index.js ADDED
@@ -0,0 +1,16 @@
1
+ // ATEL SDK - Agent Trust & Economics Layer
2
+ // Unified exports
3
+ export * from './identity/index.js';
4
+ export * from './schema/index.js';
5
+ export * from './policy/index.js';
6
+ export * from './gateway/index.js';
7
+ export * from './trace/index.js';
8
+ export * from './proof/index.js';
9
+ export * from './score/index.js';
10
+ export * from './graph/index.js';
11
+ export * from './service/index.js';
12
+ export * from './anchor/index.js';
13
+ export * from './rollback/index.js';
14
+ export * from './trust/index.js';
15
+ export * from './trust-sync/index.js';
16
+ export * from './orchestrator/index.js';
@@ -0,0 +1,190 @@
1
+ /**
2
+ * ATEL Orchestrator — High-level orchestration class
3
+ *
4
+ * Ties together all ATEL modules (Identity, Schema, Policy, Gateway,
5
+ * Trace, Proof, Trust, Anchor) into a simple, cohesive API for
6
+ * common agent collaboration workflows.
7
+ */
8
+ import { AgentIdentity, type AgentMetadata } from '../identity/index.js';
9
+ import { type Task } from '../schema/index.js';
10
+ import { type ConsentToken } from '../policy/index.js';
11
+ import type { RiskLevel } from '../schema/index.js';
12
+ import { ToolGateway, type ToolHandler } from '../gateway/index.js';
13
+ import { ExecutionTrace } from '../trace/index.js';
14
+ import { type ProofBundle, type VerifyReport } from '../proof/index.js';
15
+ import { TrustManager } from '../trust/index.js';
16
+ import type { TrustSyncAdapter } from '../trust-sync/index.js';
17
+ import { AnchorManager, type AnchorProvider, type AnchorRecord, type ChainId } from '../anchor/index.js';
18
+ /** Configuration for ATELOrchestrator */
19
+ export interface OrchestratorConfig {
20
+ /** Agent ID (auto-generated if omitted) */
21
+ agentId?: string;
22
+ /** Agent metadata */
23
+ metadata?: AgentMetadata;
24
+ /** Anchor providers to register */
25
+ anchors?: AnchorProvider[];
26
+ /** Data directory for persistence */
27
+ dataDir?: string;
28
+ /**
29
+ * Optional network trust sync adapter.
30
+ * Local trust is always computed; this adapter enables shared/network trust.
31
+ */
32
+ trustSync?: TrustSyncAdapter;
33
+ }
34
+ /** Parameters for delegating a task */
35
+ export interface DelegateTaskParams {
36
+ /** Executor's AgentIdentity or DID string */
37
+ executor: AgentIdentity | string;
38
+ /** Task intent */
39
+ intent: {
40
+ type: string;
41
+ goal: string;
42
+ constraints?: Record<string, unknown>;
43
+ };
44
+ /** Risk level */
45
+ risk: RiskLevel;
46
+ /** Scopes to grant */
47
+ scopes: string[];
48
+ /** Maximum cost */
49
+ maxCost?: number;
50
+ /** Deadline (ISO 8601) */
51
+ deadline?: string;
52
+ /** Consent token TTL in seconds (default: 3600) */
53
+ ttlSec?: number;
54
+ /** Max tool calls allowed (default: 100) */
55
+ maxCalls?: number;
56
+ }
57
+ /** Context returned after delegating a task */
58
+ export interface DelegationContext {
59
+ /** The created task */
60
+ task: Task;
61
+ /** The minted consent token */
62
+ consentToken: ConsentToken;
63
+ /** Serialize the context for transmission to the executor */
64
+ serialize(): string;
65
+ }
66
+ /** Parameters for executing a delegated task */
67
+ export interface ExecuteTaskParams {
68
+ /** The task to execute */
69
+ task: Task;
70
+ /** The consent token authorizing execution */
71
+ consentToken: ConsentToken;
72
+ /** Tool handlers to register */
73
+ tools: Record<string, ToolHandler>;
74
+ /** The execution logic */
75
+ execute: (gateway: ToolGateway, trace: ExecutionTrace) => Promise<unknown>;
76
+ }
77
+ /** Result of task execution */
78
+ export interface ExecutionResult {
79
+ /** Whether execution succeeded */
80
+ success: boolean;
81
+ /** The execution result value */
82
+ result: unknown;
83
+ /** The generated proof bundle */
84
+ proof: ProofBundle;
85
+ /** The execution trace */
86
+ trace: ExecutionTrace;
87
+ /** Anchor records (if anchoring was performed) */
88
+ anchorRecords?: AnchorRecord[];
89
+ /**
90
+ * Standardized anchor receipt for requestor-side policy decisions.
91
+ * Always present even when anchoring is skipped.
92
+ */
93
+ anchor: AnchorReceipt;
94
+ /**
95
+ * Trust sync receipt. Local trust update is always done; this indicates
96
+ * whether optional network sync succeeded.
97
+ */
98
+ trustSync: TrustSyncReceipt;
99
+ }
100
+ /** Requestor-visible trust synchronization status */
101
+ export interface TrustSyncReceipt {
102
+ mode: 'local-only' | 'local+network';
103
+ localUpdated: boolean;
104
+ networkSynced: boolean;
105
+ reference?: string;
106
+ detail?: string;
107
+ }
108
+ /** Per-chain anchor verification status */
109
+ export interface AnchorChainStatus {
110
+ chain: string;
111
+ txHash: string;
112
+ blockNumber?: number;
113
+ anchoredHash: string;
114
+ anchored: boolean;
115
+ anchorVerified: boolean;
116
+ detail?: string;
117
+ }
118
+ /** Standardized anchor receipt returned to the requestor */
119
+ export interface AnchorReceipt {
120
+ anchored: boolean;
121
+ anchoredHash: string;
122
+ verificationPassed: boolean;
123
+ records: AnchorChainStatus[];
124
+ failedChains: string[];
125
+ error?: string;
126
+ }
127
+ /** Result of proof verification */
128
+ export interface OrchestratorVerifyResult {
129
+ /** Overall validity */
130
+ valid: boolean;
131
+ /** Whether the proof itself is valid */
132
+ proofValid: boolean;
133
+ /** Whether the anchor is valid (if checked) */
134
+ anchorValid?: boolean;
135
+ /** Trust score for the executor */
136
+ trustScore?: number;
137
+ /** Detailed verification report */
138
+ report: VerifyReport;
139
+ }
140
+ /**
141
+ * High-level orchestrator that ties all ATEL modules together.
142
+ *
143
+ * Provides a simple API for:
144
+ * - Delegating tasks to other agents
145
+ * - Executing delegated tasks with automatic tracing and proof generation
146
+ * - Verifying execution proofs
147
+ */
148
+ export declare class ATELOrchestrator {
149
+ /** This agent's identity */
150
+ readonly identity: AgentIdentity;
151
+ /** Trust manager (score + graph) */
152
+ readonly trustManager: TrustManager;
153
+ /** Anchor manager for on-chain anchoring */
154
+ readonly anchorManager: AnchorManager;
155
+ /** Optional network trust sync adapter */
156
+ private readonly trustSync?;
157
+ constructor(config?: OrchestratorConfig);
158
+ /**
159
+ * Get this orchestrator's agent identity.
160
+ */
161
+ getIdentity(): AgentIdentity;
162
+ /**
163
+ * Delegate a task to another agent.
164
+ *
165
+ * Creates a signed task and mints a consent token in one step.
166
+ *
167
+ * @param params - Delegation parameters.
168
+ * @returns A DelegationContext with the task and consent token.
169
+ */
170
+ delegateTask(params: DelegateTaskParams): DelegationContext;
171
+ /**
172
+ * Execute a delegated task with automatic tracing, proof generation,
173
+ * and optional anchoring.
174
+ *
175
+ * @param params - Execution parameters.
176
+ * @returns The execution result with proof and trace.
177
+ */
178
+ executeTask(params: ExecuteTaskParams): Promise<ExecutionResult>;
179
+ /**
180
+ * Verify an execution proof, optionally checking on-chain anchors.
181
+ *
182
+ * @param proof - The proof bundle to verify.
183
+ * @param options - Verification options.
184
+ * @returns Verification result.
185
+ */
186
+ verifyExecution(proof: ProofBundle, options?: {
187
+ trace?: ExecutionTrace;
188
+ anchorChain?: ChainId | string;
189
+ }): Promise<OrchestratorVerifyResult>;
190
+ }
@@ -0,0 +1,297 @@
1
+ /**
2
+ * ATEL Orchestrator — High-level orchestration class
3
+ *
4
+ * Ties together all ATEL modules (Identity, Schema, Policy, Gateway,
5
+ * Trace, Proof, Trust, Anchor) into a simple, cohesive API for
6
+ * common agent collaboration workflows.
7
+ */
8
+ import { AgentIdentity, verify as verifySignature, parseDID } from '../identity/index.js';
9
+ import { createSignedTask, } from '../schema/index.js';
10
+ import { mintConsentToken, verifyConsentToken, PolicyEngine, } from '../policy/index.js';
11
+ import { ToolGateway, } from '../gateway/index.js';
12
+ import { ExecutionTrace } from '../trace/index.js';
13
+ import { ProofGenerator, ProofVerifier } from '../proof/index.js';
14
+ import { TrustManager } from '../trust/index.js';
15
+ import { AnchorManager, } from '../anchor/index.js';
16
+ // ─── Orchestrator ────────────────────────────────────────────────
17
+ /**
18
+ * High-level orchestrator that ties all ATEL modules together.
19
+ *
20
+ * Provides a simple API for:
21
+ * - Delegating tasks to other agents
22
+ * - Executing delegated tasks with automatic tracing and proof generation
23
+ * - Verifying execution proofs
24
+ */
25
+ export class ATELOrchestrator {
26
+ /** This agent's identity */
27
+ identity;
28
+ /** Trust manager (score + graph) */
29
+ trustManager;
30
+ /** Anchor manager for on-chain anchoring */
31
+ anchorManager;
32
+ /** Optional network trust sync adapter */
33
+ trustSync;
34
+ constructor(config = {}) {
35
+ this.identity = new AgentIdentity({
36
+ agent_id: config.agentId,
37
+ metadata: config.metadata,
38
+ });
39
+ this.trustManager = new TrustManager();
40
+ this.anchorManager = new AnchorManager();
41
+ this.trustSync = config.trustSync;
42
+ // Register anchor providers
43
+ if (config.anchors) {
44
+ for (const provider of config.anchors) {
45
+ this.anchorManager.registerProvider(provider);
46
+ }
47
+ }
48
+ }
49
+ /**
50
+ * Get this orchestrator's agent identity.
51
+ */
52
+ getIdentity() {
53
+ return this.identity;
54
+ }
55
+ /**
56
+ * Delegate a task to another agent.
57
+ *
58
+ * Creates a signed task and mints a consent token in one step.
59
+ *
60
+ * @param params - Delegation parameters.
61
+ * @returns A DelegationContext with the task and consent token.
62
+ */
63
+ delegateTask(params) {
64
+ const executorDid = typeof params.executor === 'string'
65
+ ? params.executor
66
+ : params.executor.did;
67
+ // Create and sign the task
68
+ const task = createSignedTask({
69
+ issuer: this.identity.did,
70
+ audience: [executorDid],
71
+ intent: params.intent,
72
+ risk: { level: params.risk },
73
+ economics: params.maxCost != null
74
+ ? { max_cost: params.maxCost, currency: 'USD', settlement: 'offchain' }
75
+ : undefined,
76
+ deadline: params.deadline,
77
+ }, this.identity.secretKey);
78
+ // Mint consent token
79
+ const consentToken = mintConsentToken(this.identity.did, executorDid, params.scopes, {
80
+ max_calls: params.maxCalls ?? 100,
81
+ ttl_sec: params.ttlSec ?? 3600,
82
+ }, params.risk, this.identity.secretKey);
83
+ return {
84
+ task,
85
+ consentToken,
86
+ serialize() {
87
+ return JSON.stringify({ task, consentToken });
88
+ },
89
+ };
90
+ }
91
+ /**
92
+ * Execute a delegated task with automatic tracing, proof generation,
93
+ * and optional anchoring.
94
+ *
95
+ * @param params - Execution parameters.
96
+ * @returns The execution result with proof and trace.
97
+ */
98
+ async executeTask(params) {
99
+ const { task, consentToken, tools, execute } = params;
100
+ const issuerPublicKey = parseDID(task.issuer);
101
+ // Validate task and consent before any execution side effects.
102
+ if (!task.signature || task.signature.alg !== 'ed25519') {
103
+ throw new Error('Invalid task: missing or unsupported signature');
104
+ }
105
+ const unsignedTask = { ...task };
106
+ delete unsignedTask.signature;
107
+ if (!verifySignature(unsignedTask, task.signature.sig, issuerPublicKey)) {
108
+ throw new Error('Invalid task signature');
109
+ }
110
+ verifyConsentToken(consentToken, issuerPublicKey);
111
+ if (consentToken.iss !== task.issuer) {
112
+ throw new Error('Invalid consent token: issuer does not match task issuer');
113
+ }
114
+ if (consentToken.sub !== this.identity.did) {
115
+ throw new Error('Invalid consent token: subject does not match executor DID');
116
+ }
117
+ if (task.audience && task.audience.length > 0 && !task.audience.includes(this.identity.did)) {
118
+ throw new Error('Task audience does not include this executor');
119
+ }
120
+ // Set up policy engine and gateway with auto-tracing
121
+ const policyEngine = new PolicyEngine(consentToken);
122
+ const trace = new ExecutionTrace(task.task_id, this.identity);
123
+ const gateway = new ToolGateway(policyEngine, {
124
+ trace,
125
+ defaultRiskLevel: task.risk.level,
126
+ });
127
+ // Register tools
128
+ for (const [name, handler] of Object.entries(tools)) {
129
+ gateway.registerTool(name, handler);
130
+ }
131
+ // Record task acceptance
132
+ trace.append('TASK_ACCEPTED', {
133
+ task_id: task.task_id,
134
+ executor: this.identity.did,
135
+ accepted_at: new Date().toISOString(),
136
+ });
137
+ let result;
138
+ let success = true;
139
+ try {
140
+ result = await execute(gateway, trace);
141
+ }
142
+ catch (err) {
143
+ success = false;
144
+ result = { error: err instanceof Error ? err.message : String(err) };
145
+ trace.fail(err instanceof Error ? err : new Error(String(err)));
146
+ }
147
+ // Finalize trace if not already done
148
+ if (success && !trace.isFinalized() && !trace.isFailed()) {
149
+ trace.finalize(typeof result === 'object' && result !== null
150
+ ? result
151
+ : { result });
152
+ }
153
+ // Generate proof
154
+ const proofGen = new ProofGenerator(trace, this.identity);
155
+ const proof = proofGen.generateFromContext({
156
+ consentToken: consentToken,
157
+ taskResult: result,
158
+ });
159
+ // Anchor if providers are available
160
+ let anchorRecords;
161
+ const anchorReceipt = {
162
+ anchored: false,
163
+ anchoredHash: proof.trace_root,
164
+ verificationPassed: false,
165
+ records: [],
166
+ failedChains: [],
167
+ };
168
+ const providers = this.anchorManager.getProviders();
169
+ if (providers.length > 0) {
170
+ try {
171
+ anchorRecords = await this.anchorManager.anchorAll(proof.trace_root, {
172
+ proof_id: proof.proof_id,
173
+ task_id: task.task_id,
174
+ });
175
+ anchorReceipt.anchored = anchorRecords.length > 0;
176
+ for (const record of anchorRecords) {
177
+ try {
178
+ const verification = await this.anchorManager.verify(proof.trace_root, record.txHash, record.chain);
179
+ anchorReceipt.records.push({
180
+ chain: record.chain,
181
+ txHash: record.txHash,
182
+ blockNumber: record.blockNumber,
183
+ anchoredHash: proof.trace_root,
184
+ anchored: true,
185
+ anchorVerified: verification.valid,
186
+ detail: verification.detail,
187
+ });
188
+ if (!verification.valid) {
189
+ anchorReceipt.failedChains.push(record.chain);
190
+ }
191
+ }
192
+ catch (err) {
193
+ anchorReceipt.records.push({
194
+ chain: record.chain,
195
+ txHash: record.txHash,
196
+ blockNumber: record.blockNumber,
197
+ anchoredHash: proof.trace_root,
198
+ anchored: true,
199
+ anchorVerified: false,
200
+ detail: err instanceof Error ? err.message : String(err),
201
+ });
202
+ anchorReceipt.failedChains.push(record.chain);
203
+ }
204
+ }
205
+ anchorReceipt.verificationPassed =
206
+ anchorReceipt.records.length > 0 &&
207
+ anchorReceipt.records.every((r) => r.anchorVerified);
208
+ }
209
+ catch {
210
+ // Anchoring is best-effort
211
+ anchorReceipt.error = 'Anchoring failed on all configured providers';
212
+ }
213
+ }
214
+ const trustSubmission = {
215
+ executor: this.identity.did,
216
+ issuer: task.issuer,
217
+ task_id: task.task_id,
218
+ task_type: task.intent.type,
219
+ risk_level: task.risk.level,
220
+ success,
221
+ duration_ms: trace.getStats().duration_ms ?? 0,
222
+ tool_calls: trace.getStats().tool_calls,
223
+ policy_violations: trace.getStats().policy_violations,
224
+ proof_id: proof.proof_id,
225
+ timestamp: new Date().toISOString(),
226
+ };
227
+ // Local trust update is always performed.
228
+ this.trustManager.submitResult(trustSubmission);
229
+ const trustSyncReceipt = {
230
+ mode: this.trustSync ? 'local+network' : 'local-only',
231
+ localUpdated: true,
232
+ networkSynced: false,
233
+ };
234
+ // Network trust sync is optional and best-effort.
235
+ if (this.trustSync) {
236
+ try {
237
+ const sync = await this.trustSync.submit(trustSubmission);
238
+ trustSyncReceipt.networkSynced = sync.synced;
239
+ trustSyncReceipt.reference = sync.reference;
240
+ trustSyncReceipt.detail = sync.detail;
241
+ }
242
+ catch (err) {
243
+ trustSyncReceipt.networkSynced = false;
244
+ trustSyncReceipt.detail = err instanceof Error ? err.message : String(err);
245
+ }
246
+ }
247
+ return {
248
+ success,
249
+ result,
250
+ proof,
251
+ trace,
252
+ anchorRecords,
253
+ anchor: anchorReceipt,
254
+ trustSync: trustSyncReceipt,
255
+ };
256
+ }
257
+ /**
258
+ * Verify an execution proof, optionally checking on-chain anchors.
259
+ *
260
+ * @param proof - The proof bundle to verify.
261
+ * @param options - Verification options.
262
+ * @returns Verification result.
263
+ */
264
+ async verifyExecution(proof, options) {
265
+ // Verify the proof bundle
266
+ const report = ProofVerifier.verify(proof, {
267
+ trace: options?.trace,
268
+ });
269
+ let anchorValid;
270
+ // Verify anchor if chain is specified
271
+ if (options?.anchorChain) {
272
+ try {
273
+ const records = await this.anchorManager.lookup(proof.trace_root);
274
+ const chainRecords = records.filter((r) => r.chain === options.anchorChain);
275
+ if (chainRecords.length > 0) {
276
+ const verification = await this.anchorManager.verify(proof.trace_root, chainRecords[0].txHash, options.anchorChain);
277
+ anchorValid = verification.valid;
278
+ }
279
+ else {
280
+ anchorValid = false;
281
+ }
282
+ }
283
+ catch {
284
+ anchorValid = false;
285
+ }
286
+ }
287
+ // Get trust score for executor
288
+ const scoreReport = this.trustManager.getAgentScore(proof.executor);
289
+ return {
290
+ valid: report.valid && (anchorValid === undefined || anchorValid),
291
+ proofValid: report.valid,
292
+ anchorValid,
293
+ trustScore: scoreReport.trust_score,
294
+ report,
295
+ };
296
+ }
297
+ }