@enactprotocol/shared 1.2.7 → 1.2.9

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.
@@ -1,4 +1,4 @@
1
- import { EnactToolDefinition, ToolUsage, ToolSearchQuery, CLITokenCreate, OAuthTokenExchange } from "./types";
1
+ import { EnactToolDefinition, ToolSignaturePayload, ToolUsage, ToolSearchQuery, CLITokenCreate, OAuthTokenExchange } from "./types";
2
2
  export declare class EnactApiClient {
3
3
  baseUrl: string;
4
4
  supabaseUrl: string;
@@ -100,6 +100,7 @@ export declare class EnactApiClient {
100
100
  * Get a user's public key
101
101
  */
102
102
  getUserPublicKey(userId: string): Promise<any>;
103
+ signTool(toolId: string, payload: ToolSignaturePayload, token: string, tokenType?: "jwt" | "cli"): Promise<any>;
103
104
  /**
104
105
  * Generate OAuth authorization URL
105
106
  */
@@ -343,6 +343,13 @@ export class EnactApiClient {
343
343
  throw new EnactApiError("Unknown error occurred", 0);
344
344
  }
345
345
  }
346
+ async signTool(toolId, payload, token, tokenType = "cli") {
347
+ const endpoint = `/functions/v1/tools/${encodeURIComponent(toolId)}/signatures`;
348
+ return this.makeRequest(endpoint, {
349
+ method: "POST",
350
+ body: JSON.stringify(payload),
351
+ }, token, tokenType);
352
+ }
346
353
  // ===================
347
354
  // OAUTH FLOW HELPERS
348
355
  // ===================
@@ -1,6 +1,7 @@
1
1
  export interface EnactToolDefinition {
2
2
  name: string;
3
3
  description: string;
4
+ verified?: boolean;
4
5
  command: string;
5
6
  from?: string;
6
7
  version?: string;
@@ -89,3 +90,14 @@ export interface EnactExecOptions {
89
90
  dangerouslySkipVerification?: boolean;
90
91
  mount?: string;
91
92
  }
93
+ export interface ToolSignaturePayload {
94
+ algorithm: "sha256";
95
+ created: string;
96
+ key_id: string;
97
+ public_key: string;
98
+ role: "author";
99
+ signer: string;
100
+ timestamp: number;
101
+ type: "ecdsa-p256";
102
+ value: string;
103
+ }
@@ -1,4 +1,5 @@
1
1
  import type { EnactTool, ExecutionResult } from "../types.js";
2
+ import { EnactToolDefinition } from "../api/types.js";
2
3
  export interface EnactCoreOptions {
3
4
  apiUrl?: string;
4
5
  supabaseUrl?: string;
@@ -67,6 +68,7 @@ export declare class EnactCore {
67
68
  * Execute a tool by name
68
69
  */
69
70
  executeToolByName(name: string, inputs?: Record<string, any>, options?: ToolExecuteOptions): Promise<ExecutionResult>;
71
+ static checkToolVerificationStatus(tool: EnactToolDefinition): Promise<boolean>;
70
72
  private verifyTool;
71
73
  /**
72
74
  * Execute a tool directly
@@ -5,7 +5,7 @@ import { DaggerExecutionProvider } from "./DaggerExecutionProvider.js";
5
5
  import { resolveToolEnvironmentVariables } from "../utils/env-loader.js";
6
6
  import logger from "../exec/logger.js";
7
7
  import yaml from "yaml";
8
- import { CryptoUtils, SecurityConfigManager, SigningService } from "@enactprotocol/security";
8
+ import { SecurityConfigManager, SigningService } from "@enactprotocol/security";
9
9
  import { getFrontendUrl, getApiUrl } from "../utils/config";
10
10
  export class EnactCore {
11
11
  constructor(options = {}) {
@@ -278,6 +278,33 @@ export class EnactCore {
278
278
  };
279
279
  }
280
280
  }
281
+ static async checkToolVerificationStatus(tool) {
282
+ const documentForVerification = {
283
+ command: tool.command,
284
+ description: tool.description,
285
+ from: tool.from,
286
+ name: tool.name,
287
+ signatures: tool.signatures?.map(sig => ({
288
+ signature: sig.value,
289
+ publicKey: "", // TODO: Look up the correct public key
290
+ algorithm: sig.algorithm,
291
+ timestamp: new Date(sig.created).getTime(),
292
+ })),
293
+ };
294
+ let isValid = false;
295
+ if (tool.signatures && tool.signatures.length > 0) {
296
+ isValid = tool.signatures.some(sig => {
297
+ const referenceSignature = {
298
+ signature: sig.value,
299
+ publicKey: "", // TODO: Lookup correct public key based on signature UUID
300
+ algorithm: sig.algorithm,
301
+ timestamp: new Date(sig.created).getTime()
302
+ };
303
+ return SigningService.verifyDocument(documentForVerification, referenceSignature, { includeFields: ['command', 'description', 'from', 'name'] });
304
+ });
305
+ }
306
+ return isValid;
307
+ }
281
308
  async verifyTool(tool, dangerouslySkipVerification = false) {
282
309
  if (dangerouslySkipVerification) {
283
310
  logger.warn(`Skipping signature verification for tool: ${tool.name}`);
@@ -287,28 +314,33 @@ export class EnactCore {
287
314
  if (!tool.signatures || tool.signatures.length === 0) {
288
315
  throw new Error(`Tool ${tool.name} does not have any signatures`);
289
316
  }
290
- const documentForVerification = {
291
- command: tool.command,
292
- description: tool.description,
293
- from: tool.from,
294
- name: tool.name,
295
- };
296
- const referenceSignature = {
297
- signature: tool.signatures[0].value,
298
- publicKey: "", // Correct public key for UUID 71e02e2c-148c-4534-9900-bd9646e99333
299
- algorithm: tool.signatures[0].algorithm,
300
- timestamp: new Date(tool.signatures[0].created).getTime()
301
- };
302
- // Check what canonical document looks like
303
- const canonicalDoc = SigningService.getCanonicalDocument(documentForVerification, { includeFields: ['command', 'description', 'from', 'name'] });
304
- const docString = JSON.stringify(canonicalDoc);
305
- const messageHash = CryptoUtils.hash(docString);
306
- // Test direct crypto verification
307
- const directVerify = CryptoUtils.verify(referenceSignature.publicKey, messageHash, referenceSignature.signature);
317
+ // const documentForVerification = {
318
+ // command: tool.command,
319
+ // description: tool.description,
320
+ // from: tool.from,
321
+ // name: tool.name,
322
+ // };
323
+ // const referenceSignature = {
324
+ // signature: tool.signatures[0].value,
325
+ // publicKey: "", // Correct public key for UUID 71e02e2c-148c-4534-9900-bd9646e99333
326
+ // algorithm: tool.signatures[0].algorithm,
327
+ // timestamp: new Date(tool.signatures[0].created).getTime()
328
+ // };
329
+ // // Check what canonical document looks like
330
+ // const canonicalDoc = SigningService.getCanonicalDocument(documentForVerification, { includeFields: ['command', 'description', 'from', 'name'] }
331
+ // );
332
+ // const docString = JSON.stringify(canonicalDoc);
333
+ // const messageHash = CryptoUtils.hash(docString);
334
+ // // Test direct crypto verification
335
+ // const directVerify = CryptoUtils.verify(
336
+ // referenceSignature.publicKey,
337
+ // messageHash,
338
+ // referenceSignature.signature
339
+ // );
308
340
  // Check trusted keys
309
341
  // const trustedKeys = KeyManager.getAllTrustedPublicKeys();
310
- const isValid = SigningService.verifyDocument(documentForVerification, referenceSignature, { includeFields: ['command', 'description', 'from', 'name'] });
311
- // console.log("Final verification result:", isValid);
342
+ const isValid = await EnactCore.checkToolVerificationStatus(tool);
343
+ console.log("Final verification result:", isValid);
312
344
  if (!isValid) {
313
345
  throw new Error(`Tool ${tool.name} has invalid signatures`);
314
346
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enactprotocol/shared",
3
- "version": "1.2.7",
3
+ "version": "1.2.9",
4
4
  "description": "Shared utilities and core functionality for Enact Protocol",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  EnactToolDefinition,
3
+ ToolSignaturePayload,
3
4
  ToolUsage,
4
5
  ToolSearchQuery,
5
6
  CLITokenCreate,
@@ -480,6 +481,20 @@ export class EnactApiClient {
480
481
  throw new EnactApiError("Unknown error occurred", 0);
481
482
  }
482
483
  }
484
+
485
+ async signTool(
486
+ toolId: string,
487
+ payload: ToolSignaturePayload,
488
+ token: string,
489
+ tokenType: "jwt" | "cli" = "cli"
490
+ ): Promise<any> {
491
+ const endpoint = `/functions/v1/tools/${encodeURIComponent(toolId)}/signatures`;
492
+
493
+ return this.makeRequest(endpoint, {
494
+ method: "POST",
495
+ body: JSON.stringify(payload),
496
+ }, token, tokenType);
497
+ }
483
498
 
484
499
  // ===================
485
500
  // OAUTH FLOW HELPERS
package/src/api/types.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export interface EnactToolDefinition {
2
2
  name: string;
3
3
  description: string;
4
+ verified?: boolean; // Indicates if the tool has been verified
4
5
  command: string;
5
6
  from?: string;
6
7
  version?: string;
@@ -99,3 +100,15 @@ export interface EnactExecOptions {
99
100
  dangerouslySkipVerification?: boolean; // Skip all signature verification (DANGEROUS)
100
101
  mount?: string; // Mount local directory to container (format: "local:container")
101
102
  }
103
+
104
+ export interface ToolSignaturePayload {
105
+ algorithm: "sha256";
106
+ created: string; // Time of signing
107
+ key_id: string; // ID of the private key
108
+ public_key: string; // The corresponding public key
109
+ role: "author";
110
+ signer: string; // The userID of the signer
111
+ timestamp: number;
112
+ type: "ecdsa-p256";
113
+ value: string; // Signature
114
+ }
@@ -11,7 +11,8 @@ import { parseTimeout } from "../utils/timeout.js";
11
11
  import fs from "fs/promises";
12
12
  import path from "path";
13
13
  import crypto from "crypto";
14
- import { spawnSync } from "child_process";
14
+ import { spawn, spawnSync } from "child_process";
15
+ import { exit } from "process";
15
16
 
16
17
  export interface DaggerExecutionOptions {
17
18
  baseImage?: string; // Default container image
@@ -15,8 +15,11 @@ import { DaggerExecutionProvider } from "./DaggerExecutionProvider.js";
15
15
  import { resolveToolEnvironmentVariables } from "../utils/env-loader.js";
16
16
  import logger from "../exec/logger.js";
17
17
  import yaml from "yaml";
18
+ import fs from "fs";
19
+ import path from "path";
18
20
  import { CryptoUtils, KeyManager, SecurityConfigManager, SigningService } from "@enactprotocol/security";
19
21
  import { getFrontendUrl, getApiUrl } from "../utils/config";
22
+ import { EnactToolDefinition } from "../api/types.js";
20
23
 
21
24
  export interface EnactCoreOptions {
22
25
  apiUrl?: string;
@@ -406,6 +409,43 @@ export class EnactCore {
406
409
  }
407
410
  }
408
411
 
412
+ public static async checkToolVerificationStatus(tool: EnactToolDefinition): Promise<boolean> {
413
+ const documentForVerification = {
414
+ command: tool.command,
415
+ description: tool.description,
416
+ from: tool.from,
417
+ name: tool.name,
418
+ signatures: tool.signatures?.map(sig => ({
419
+ signature: sig.value,
420
+ publicKey: "", // TODO: Look up the correct public key
421
+ algorithm: sig.algorithm,
422
+ timestamp: new Date(sig.created).getTime(),
423
+ })),
424
+ };
425
+
426
+ let isValid = false;
427
+
428
+ if (tool.signatures && tool.signatures.length > 0) {
429
+ isValid = tool.signatures.some(sig => {
430
+ const referenceSignature = {
431
+ signature: sig.value,
432
+ publicKey: "", // TODO: Lookup correct public key based on signature UUID
433
+ algorithm: sig.algorithm,
434
+ timestamp: new Date(sig.created).getTime()
435
+ };
436
+
437
+ return SigningService.verifyDocument(
438
+ documentForVerification,
439
+ referenceSignature,
440
+ { includeFields: ['command', 'description', 'from', 'name'] }
441
+ );
442
+ });
443
+ }
444
+
445
+ return isValid;
446
+ }
447
+
448
+
409
449
  private async verifyTool(tool: EnactTool, dangerouslySkipVerification: boolean = false): Promise<void> {
410
450
  if (dangerouslySkipVerification) {
411
451
  logger.warn(`Skipping signature verification for tool: ${tool.name}`);
@@ -417,46 +457,42 @@ private async verifyTool(tool: EnactTool, dangerouslySkipVerification: boolean =
417
457
  throw new Error(`Tool ${tool.name} does not have any signatures`);
418
458
  }
419
459
 
420
- const documentForVerification = {
421
- command: tool.command,
422
- description: tool.description,
423
- from: tool.from,
424
- name: tool.name,
425
- };
426
-
427
- const referenceSignature = {
428
- signature: tool.signatures[0].value,
429
- publicKey: "", // Correct public key for UUID 71e02e2c-148c-4534-9900-bd9646e99333
430
- algorithm: tool.signatures[0].algorithm,
431
- timestamp: new Date(tool.signatures[0].created).getTime()
432
- };
460
+ // const documentForVerification = {
461
+ // command: tool.command,
462
+ // description: tool.description,
463
+ // from: tool.from,
464
+ // name: tool.name,
465
+ // };
466
+
467
+ // const referenceSignature = {
468
+ // signature: tool.signatures[0].value,
469
+ // publicKey: "", // Correct public key for UUID 71e02e2c-148c-4534-9900-bd9646e99333
470
+ // algorithm: tool.signatures[0].algorithm,
471
+ // timestamp: new Date(tool.signatures[0].created).getTime()
472
+ // };
433
473
 
434
474
 
435
- // Check what canonical document looks like
436
- const canonicalDoc = SigningService.getCanonicalDocument(documentForVerification, { includeFields: ['command', 'description', 'from', 'name'] }
437
- );
475
+ // // Check what canonical document looks like
476
+ // const canonicalDoc = SigningService.getCanonicalDocument(documentForVerification, { includeFields: ['command', 'description', 'from', 'name'] }
477
+ // );
438
478
 
439
- const docString = JSON.stringify(canonicalDoc);
440
- const messageHash = CryptoUtils.hash(docString);
479
+ // const docString = JSON.stringify(canonicalDoc);
480
+ // const messageHash = CryptoUtils.hash(docString);
441
481
 
442
482
 
443
- // Test direct crypto verification
444
- const directVerify = CryptoUtils.verify(
445
- referenceSignature.publicKey,
446
- messageHash,
447
- referenceSignature.signature
448
- );
483
+ // // Test direct crypto verification
484
+ // const directVerify = CryptoUtils.verify(
485
+ // referenceSignature.publicKey,
486
+ // messageHash,
487
+ // referenceSignature.signature
488
+ // );
449
489
 
450
490
  // Check trusted keys
451
491
  // const trustedKeys = KeyManager.getAllTrustedPublicKeys();
452
492
 
453
- const isValid = SigningService.verifyDocument(
454
- documentForVerification,
455
- referenceSignature,
456
- { includeFields: ['command', 'description', 'from', 'name'] }
457
- );
493
+ const isValid = await EnactCore.checkToolVerificationStatus(tool);
458
494
 
459
- // console.log("Final verification result:", isValid);
495
+ console.log("Final verification result:", isValid);
460
496
 
461
497
  if (!isValid) {
462
498
  throw new Error(`Tool ${tool.name} has invalid signatures`);