@enactprotocol/shared 1.0.14 → 1.2.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/dist/api/enact-api.js +2 -2
- package/dist/api/types.d.ts +10 -3
- package/dist/core/DaggerExecutionProvider.d.ts +1 -1
- package/dist/core/DaggerExecutionProvider.js +23 -19
- package/dist/core/EnactCore.d.ts +36 -19
- package/dist/core/EnactCore.js +162 -217
- package/dist/core/NativeExecutionProvider.d.ts +9 -0
- package/dist/core/NativeExecutionProvider.js +16 -0
- package/dist/index.d.ts +0 -4
- package/dist/index.js +0 -4
- package/dist/lib/enact-direct.d.ts +0 -15
- package/dist/lib/enact-direct.js +0 -11
- package/dist/security/sign.d.ts +5 -5
- package/dist/security/sign.js +247 -113
- package/dist/security/verification-enforcer.d.ts +12 -0
- package/dist/security/verification-enforcer.js +26 -3
- package/dist/services/McpCoreService.d.ts +0 -12
- package/dist/services/McpCoreService.js +0 -9
- package/dist/types.d.ts +5 -4
- package/dist/utils/config.js +1 -1
- package/dist/utils/env-loader.js +1 -1
- package/dist/utils/help.js +1 -1
- package/package.json +3 -6
- package/src/api/enact-api.ts +2 -2
- package/src/api/types.ts +11 -4
- package/src/core/DaggerExecutionProvider.ts +26 -13
- package/src/core/EnactCore.ts +232 -269
- package/src/index.ts +0 -5
- package/src/lib/enact-direct.ts +0 -21
- package/src/services/McpCoreService.ts +0 -20
- package/src/types.ts +10 -12
- package/src/utils/config.ts +1 -1
- package/src/utils/env-loader.ts +1 -1
- package/src/utils/help.ts +1 -1
- package/src/security/index.ts +0 -3
- package/src/security/security.ts +0 -188
- package/src/security/sign.ts +0 -797
- package/src/security/verification-enforcer.ts +0 -268
package/dist/core/EnactCore.js
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
import { EnactApiClient } from "../api/enact-api.js";
|
|
2
|
-
import {
|
|
3
|
-
import { validateToolStructure, validateInputs, validateOutput, } from "../exec/validate.js";
|
|
2
|
+
import { validateToolStructure, validateInputs, } from "../exec/validate.js";
|
|
4
3
|
import { DirectExecutionProvider } from "./DirectExecutionProvider.js";
|
|
5
4
|
import { DaggerExecutionProvider } from "./DaggerExecutionProvider.js";
|
|
6
5
|
import { resolveToolEnvironmentVariables } from "../utils/env-loader.js";
|
|
7
6
|
import logger from "../exec/logger.js";
|
|
8
7
|
import yaml from "yaml";
|
|
9
|
-
import {
|
|
10
|
-
import { enforceSignatureVerification, createVerificationFailureResult, logSecurityAudit, } from "../security/verification-enforcer.js";
|
|
11
|
-
import fs from "fs";
|
|
12
|
-
import path from "path";
|
|
8
|
+
import { CryptoUtils, KeyManager, SecurityConfigManager, SigningService } from "@enactprotocol/security";
|
|
13
9
|
export class EnactCore {
|
|
14
10
|
constructor(options = {}) {
|
|
15
11
|
this.options = {
|
|
@@ -17,7 +13,6 @@ export class EnactCore {
|
|
|
17
13
|
supabaseUrl: "https://xjnhhxwxovjifdxdwzih.supabase.co",
|
|
18
14
|
executionProvider: "dagger",
|
|
19
15
|
defaultTimeout: "30s",
|
|
20
|
-
verificationPolicy: "permissive",
|
|
21
16
|
...options,
|
|
22
17
|
};
|
|
23
18
|
this.apiClient = new EnactApiClient(this.options.apiUrl, this.options.supabaseUrl);
|
|
@@ -31,9 +26,10 @@ export class EnactCore {
|
|
|
31
26
|
this.options.authToken = token;
|
|
32
27
|
}
|
|
33
28
|
/**
|
|
34
|
-
*
|
|
29
|
+
* Static method to search for tools (no execution provider needed)
|
|
35
30
|
*/
|
|
36
|
-
async searchTools(options) {
|
|
31
|
+
static async searchTools(options, coreOptions = {}) {
|
|
32
|
+
const apiClient = new EnactApiClient(coreOptions.apiUrl || "https://enact.tools", coreOptions.supabaseUrl || "https://xjnhhxwxovjifdxdwzih.supabase.co");
|
|
37
33
|
try {
|
|
38
34
|
logger.info(`Searching for tools with query: "${options.query}"`);
|
|
39
35
|
const searchParams = {
|
|
@@ -41,13 +37,13 @@ export class EnactCore {
|
|
|
41
37
|
limit: options.limit,
|
|
42
38
|
tags: options.tags,
|
|
43
39
|
};
|
|
44
|
-
const results = await
|
|
40
|
+
const results = await apiClient.searchTools(searchParams);
|
|
45
41
|
// Parse and validate results
|
|
46
42
|
const tools = [];
|
|
47
43
|
for (const result of results) {
|
|
48
44
|
if (result.name) {
|
|
49
45
|
try {
|
|
50
|
-
const tool = await
|
|
46
|
+
const tool = await EnactCore.getToolByName(result.name, undefined, coreOptions);
|
|
51
47
|
if (tool) {
|
|
52
48
|
tools.push(tool);
|
|
53
49
|
}
|
|
@@ -65,19 +61,26 @@ export class EnactCore {
|
|
|
65
61
|
// If it's a 502 error (API server issue), try fallback to local filtering
|
|
66
62
|
if (error instanceof Error && error.message.includes("502")) {
|
|
67
63
|
logger.info("Search API unavailable, trying fallback to local filtering...");
|
|
68
|
-
return
|
|
64
|
+
return EnactCore.searchToolsFallback(options, coreOptions);
|
|
69
65
|
}
|
|
70
66
|
throw new Error(`Search failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
71
67
|
}
|
|
72
68
|
}
|
|
73
69
|
/**
|
|
74
|
-
*
|
|
70
|
+
* Instance method wrapper for backward compatibility
|
|
71
|
+
*/
|
|
72
|
+
async searchTools(options) {
|
|
73
|
+
return EnactCore.searchTools(options, this.options);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Static fallback search method that gets all tools and filters locally
|
|
75
77
|
*/
|
|
76
|
-
async searchToolsFallback(options) {
|
|
78
|
+
static async searchToolsFallback(options, coreOptions = {}) {
|
|
79
|
+
const apiClient = new EnactApiClient(coreOptions.apiUrl || "https://enact.tools", coreOptions.supabaseUrl || "https://xjnhhxwxovjifdxdwzih.supabase.co");
|
|
77
80
|
try {
|
|
78
81
|
logger.info("Using fallback search method...");
|
|
79
82
|
// Get all tools (limited to avoid overwhelming the API)
|
|
80
|
-
const allTools = await
|
|
83
|
+
const allTools = await apiClient.getTools({
|
|
81
84
|
limit: options.limit || 100,
|
|
82
85
|
});
|
|
83
86
|
// Filter tools locally based on search criteria
|
|
@@ -86,7 +89,7 @@ export class EnactCore {
|
|
|
86
89
|
for (const result of allTools) {
|
|
87
90
|
if (result.name) {
|
|
88
91
|
try {
|
|
89
|
-
const tool = await
|
|
92
|
+
const tool = await EnactCore.getToolByName(result.name, undefined, coreOptions);
|
|
90
93
|
if (tool) {
|
|
91
94
|
// Check if tool matches search criteria
|
|
92
95
|
const matchesQuery = tool.name.toLowerCase().includes(query) ||
|
|
@@ -127,37 +130,61 @@ export class EnactCore {
|
|
|
127
130
|
}
|
|
128
131
|
}
|
|
129
132
|
/**
|
|
130
|
-
*
|
|
133
|
+
* Static method to get a specific tool by name
|
|
131
134
|
*/
|
|
132
|
-
async getToolByName(name, version) {
|
|
135
|
+
static async getToolByName(name, version, coreOptions = {}) {
|
|
136
|
+
const apiClient = new EnactApiClient(coreOptions.apiUrl || "https://enact.tools", coreOptions.supabaseUrl || "https://xjnhhxwxovjifdxdwzih.supabase.co");
|
|
133
137
|
try {
|
|
134
138
|
logger.info(`Fetching tool: ${name}${version ? `@${version}` : ""}`);
|
|
135
|
-
const response = await
|
|
139
|
+
const response = await apiClient.getTool(name);
|
|
136
140
|
if (!response) {
|
|
137
141
|
logger.info(`Tool not found: ${name}`);
|
|
138
142
|
return null;
|
|
139
143
|
}
|
|
140
|
-
// Parse tool from response
|
|
144
|
+
// Parse tool from response - prefer raw_content for signature compatibility
|
|
141
145
|
let tool;
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
145
|
-
else if (response.raw_content &&
|
|
146
|
-
typeof response.raw_content === "string") {
|
|
146
|
+
// Try raw_content first (contains original tool definition with correct field names for signatures)
|
|
147
|
+
if (response.raw_content && typeof response.raw_content === "string") {
|
|
147
148
|
try {
|
|
148
149
|
tool = JSON.parse(response.raw_content);
|
|
149
150
|
}
|
|
150
151
|
catch {
|
|
151
152
|
tool = yaml.parse(response.raw_content);
|
|
152
153
|
}
|
|
154
|
+
// Merge signature information from response if not already in raw content
|
|
155
|
+
if (!tool.signature && response.signature) {
|
|
156
|
+
tool.signature = response.signature;
|
|
157
|
+
}
|
|
158
|
+
if (!tool.signatures && response.signatures) {
|
|
159
|
+
// Convert object format to array format
|
|
160
|
+
if (Array.isArray(response.signatures)) {
|
|
161
|
+
tool.signatures = response.signatures;
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
// Convert object format {keyId: signatureData} to array format
|
|
165
|
+
tool.signatures = Object.values(response.signatures);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
else if (response.content && typeof response.content === "string") {
|
|
170
|
+
tool = yaml.parse(response.content);
|
|
153
171
|
// Merge signature information
|
|
154
|
-
if (
|
|
172
|
+
if (!tool.signature && response.signature) {
|
|
155
173
|
tool.signature = response.signature;
|
|
156
|
-
|
|
174
|
+
}
|
|
175
|
+
if (!tool.signatures && response.signatures) {
|
|
176
|
+
// Convert object format to array format
|
|
177
|
+
if (Array.isArray(response.signatures)) {
|
|
178
|
+
tool.signatures = response.signatures;
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
// Convert object format {keyId: signatureData} to array format
|
|
182
|
+
tool.signatures = Object.values(response.signatures);
|
|
183
|
+
}
|
|
157
184
|
}
|
|
158
185
|
}
|
|
159
186
|
else {
|
|
160
|
-
//
|
|
187
|
+
// Fallback: map database fields to tool format (may cause signature verification issues)
|
|
161
188
|
tool = {
|
|
162
189
|
name: response.name,
|
|
163
190
|
description: response.description,
|
|
@@ -174,7 +201,7 @@ export class EnactCore {
|
|
|
174
201
|
env: response.env_vars || response.env,
|
|
175
202
|
resources: response.resources,
|
|
176
203
|
signature: response.signature,
|
|
177
|
-
signatures: response.signatures,
|
|
204
|
+
signatures: response.signatures ? (Array.isArray(response.signatures) ? response.signatures : Object.values(response.signatures)) : undefined,
|
|
178
205
|
namespace: response.namespace,
|
|
179
206
|
};
|
|
180
207
|
}
|
|
@@ -190,6 +217,12 @@ export class EnactCore {
|
|
|
190
217
|
throw error;
|
|
191
218
|
}
|
|
192
219
|
}
|
|
220
|
+
/**
|
|
221
|
+
* Instance method wrapper for backward compatibility
|
|
222
|
+
*/
|
|
223
|
+
async getToolByName(name, version) {
|
|
224
|
+
return EnactCore.getToolByName(name, version, this.options);
|
|
225
|
+
}
|
|
193
226
|
/**
|
|
194
227
|
* Execute a tool by name
|
|
195
228
|
*/
|
|
@@ -232,6 +265,50 @@ export class EnactCore {
|
|
|
232
265
|
};
|
|
233
266
|
}
|
|
234
267
|
}
|
|
268
|
+
async verifyTool(tool, dangerouslySkipVerification = false) {
|
|
269
|
+
if (dangerouslySkipVerification) {
|
|
270
|
+
logger.warn(`Skipping signature verification for tool: ${tool.name}`);
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
try {
|
|
274
|
+
if (!tool.signatures || tool.signatures.length === 0) {
|
|
275
|
+
throw new Error(`Tool ${tool.name} does not have any signatures`);
|
|
276
|
+
}
|
|
277
|
+
const documentForVerification = {
|
|
278
|
+
command: tool.command
|
|
279
|
+
};
|
|
280
|
+
const referenceSignature = {
|
|
281
|
+
signature: tool.signatures[0].value,
|
|
282
|
+
publicKey: tool.signatures[0].signer,
|
|
283
|
+
algorithm: tool.signatures[0].algorithm,
|
|
284
|
+
timestamp: new Date(tool.signatures[0].created).getTime()
|
|
285
|
+
};
|
|
286
|
+
// Check what canonical document looks like
|
|
287
|
+
const canonicalDoc = SigningService.getCanonicalDocument(documentForVerification, { includeFields: ['command'] });
|
|
288
|
+
// console.log("Canonical document:", JSON.stringify(canonicalDoc));
|
|
289
|
+
const docString = JSON.stringify(canonicalDoc);
|
|
290
|
+
const messageHash = CryptoUtils.hash(docString);
|
|
291
|
+
// console.log("Document string:", docString);
|
|
292
|
+
// console.log("Message hash:", messageHash);
|
|
293
|
+
// Test direct crypto verification
|
|
294
|
+
const directVerify = CryptoUtils.verify(referenceSignature.publicKey, messageHash, referenceSignature.signature);
|
|
295
|
+
console.log("Direct crypto verification result:", directVerify);
|
|
296
|
+
// Check trusted keys
|
|
297
|
+
const trustedKeys = KeyManager.getAllTrustedPublicKeys();
|
|
298
|
+
console.log("Trusted keys:", trustedKeys);
|
|
299
|
+
console.log("Is our public key trusted?", trustedKeys.includes(referenceSignature.publicKey));
|
|
300
|
+
const isValid = SigningService.verifyDocument(documentForVerification, referenceSignature, { includeFields: ['command'] });
|
|
301
|
+
console.log("Final verification result:", isValid);
|
|
302
|
+
if (!isValid) {
|
|
303
|
+
throw new Error(`Tool ${tool.name} has invalid signatures`);
|
|
304
|
+
}
|
|
305
|
+
logger.info(`Tool ${tool.name} signature verification passed`);
|
|
306
|
+
}
|
|
307
|
+
catch (error) {
|
|
308
|
+
logger.error(`Signature verification failed for tool ${tool.name}:`, error);
|
|
309
|
+
throw new Error(`Signature verification failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
235
312
|
/**
|
|
236
313
|
* Execute a tool directly
|
|
237
314
|
*/
|
|
@@ -241,129 +318,43 @@ export class EnactCore {
|
|
|
241
318
|
logger.info(`Executing tool: ${tool.name}`);
|
|
242
319
|
// Validate tool structure
|
|
243
320
|
validateToolStructure(tool);
|
|
244
|
-
// MANDATORY SIGNATURE VERIFICATION - All tools must be verified before execution
|
|
245
|
-
const verificationResult = await enforceSignatureVerification(tool, {
|
|
246
|
-
skipVerification: options.skipVerification,
|
|
247
|
-
verifyPolicy: options.verifyPolicy,
|
|
248
|
-
force: options.force,
|
|
249
|
-
allowUnsigned: false, // Never allow unsigned tools in production
|
|
250
|
-
});
|
|
251
|
-
// Log security audit information
|
|
252
|
-
logSecurityAudit(tool, verificationResult, verificationResult.allowed, {
|
|
253
|
-
skipVerification: options.skipVerification,
|
|
254
|
-
verifyPolicy: options.verifyPolicy,
|
|
255
|
-
force: options.force,
|
|
256
|
-
});
|
|
257
|
-
// Block execution if verification fails
|
|
258
|
-
if (!verificationResult.allowed) {
|
|
259
|
-
return createVerificationFailureResult(tool, verificationResult, executionId);
|
|
260
|
-
}
|
|
261
321
|
// Validate inputs
|
|
262
322
|
const validatedInputs = validateInputs(tool, inputs);
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
return {
|
|
267
|
-
success: false,
|
|
268
|
-
error: {
|
|
269
|
-
message: `Unsafe command blocked: ${safetyCheck.blocked?.join(", ")}`,
|
|
270
|
-
code: "COMMAND_UNSAFE",
|
|
271
|
-
details: safetyCheck,
|
|
272
|
-
},
|
|
273
|
-
metadata: {
|
|
274
|
-
executionId,
|
|
275
|
-
toolName: tool.name,
|
|
276
|
-
version: tool.version,
|
|
277
|
-
executedAt: new Date().toISOString(),
|
|
278
|
-
environment: "direct",
|
|
279
|
-
command: tool.command,
|
|
280
|
-
},
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
// Log warnings
|
|
284
|
-
if (safetyCheck.warnings.length > 0) {
|
|
285
|
-
safetyCheck.warnings.forEach((warning) => logger.warn(warning));
|
|
286
|
-
}
|
|
287
|
-
// Dry run - just validate and return
|
|
288
|
-
if (options.dryRun) {
|
|
289
|
-
return {
|
|
290
|
-
success: true,
|
|
291
|
-
output: {
|
|
292
|
-
dryRun: true,
|
|
293
|
-
tool: tool.name,
|
|
294
|
-
command: tool.command,
|
|
295
|
-
inputs: validatedInputs,
|
|
296
|
-
safetyCheck,
|
|
297
|
-
},
|
|
298
|
-
metadata: {
|
|
299
|
-
executionId,
|
|
300
|
-
toolName: tool.name,
|
|
301
|
-
version: tool.version,
|
|
302
|
-
executedAt: new Date().toISOString(),
|
|
303
|
-
environment: "direct",
|
|
304
|
-
command: tool.command,
|
|
305
|
-
},
|
|
306
|
-
};
|
|
323
|
+
const config = SecurityConfigManager.loadConfig();
|
|
324
|
+
if (options.isLocalFile && config.allowLocalUnsigned) {
|
|
325
|
+
logger.warn(`Executing local file without signature verification: ${tool.name} (you can disallow in your security config)`);
|
|
307
326
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
const envResult = await resolveToolEnvironmentVariables(tool.name, tool.env);
|
|
311
|
-
// Log any missing required environment variables
|
|
312
|
-
if (envResult.missing.length > 0) {
|
|
313
|
-
logger.warn(`Missing required environment variables: ${envResult.missing.join(", ")}`);
|
|
327
|
+
if (options.dangerouslySkipVerification) {
|
|
328
|
+
logger.warn(`Skipping signature verification for tool: ${tool.name} because of dangerouslySkipVerification option`);
|
|
314
329
|
}
|
|
315
|
-
const
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
330
|
+
const skipVerification = (options.isLocalFile && config.allowLocalUnsigned) || Boolean(options.dangerouslySkipVerification);
|
|
331
|
+
// Verify tool signatures (unless explicitly skipped)
|
|
332
|
+
await this.verifyTool(tool, skipVerification);
|
|
333
|
+
// Resolve environment variables
|
|
334
|
+
const { resolved: envVars } = await resolveToolEnvironmentVariables(tool.name, tool.env || {});
|
|
335
|
+
// Execute the tool via the execution provider
|
|
336
|
+
return await this.executionProvider.execute(tool, { ...validatedInputs, ...envVars }, {
|
|
337
|
+
vars: { ...envVars, ...validatedInputs },
|
|
338
|
+
resources: {
|
|
339
|
+
timeout: options.timeout || tool.timeout || this.options.defaultTimeout,
|
|
319
340
|
},
|
|
320
|
-
|
|
321
|
-
namespace: tool.namespace,
|
|
322
|
-
};
|
|
323
|
-
// Setup execution provider
|
|
324
|
-
await this.executionProvider.setup(tool);
|
|
325
|
-
// Execute the tool
|
|
326
|
-
const result = await this.executionProvider.execute(tool, validatedInputs, environment);
|
|
327
|
-
// Validate output if schema is provided
|
|
328
|
-
if (result.success && result.output && tool.outputSchema) {
|
|
329
|
-
try {
|
|
330
|
-
result.output = validateOutput(tool, result.output);
|
|
331
|
-
}
|
|
332
|
-
catch (error) {
|
|
333
|
-
logger.warn(`Output validation failed: ${error.message}`);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
logger.info(`Tool execution completed: ${tool.name} (success: ${result.success})`);
|
|
337
|
-
return result;
|
|
341
|
+
});
|
|
338
342
|
}
|
|
339
343
|
catch (error) {
|
|
340
|
-
logger.error(`Error executing tool: ${error.message}`);
|
|
341
344
|
return {
|
|
342
345
|
success: false,
|
|
343
346
|
error: {
|
|
344
347
|
message: error.message,
|
|
345
348
|
code: "EXECUTION_ERROR",
|
|
346
|
-
details: error,
|
|
347
349
|
},
|
|
348
350
|
metadata: {
|
|
349
351
|
executionId,
|
|
350
352
|
toolName: tool.name,
|
|
351
|
-
version: tool.version,
|
|
352
353
|
executedAt: new Date().toISOString(),
|
|
353
354
|
environment: "direct",
|
|
354
|
-
command: tool.command,
|
|
355
355
|
},
|
|
356
356
|
};
|
|
357
357
|
}
|
|
358
|
-
finally {
|
|
359
|
-
// Cleanup
|
|
360
|
-
try {
|
|
361
|
-
await this.executionProvider.cleanup();
|
|
362
|
-
}
|
|
363
|
-
catch (cleanupError) {
|
|
364
|
-
logger.error("Error during cleanup:", cleanupError);
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
358
|
}
|
|
368
359
|
/**
|
|
369
360
|
* Execute a tool from raw YAML definition
|
|
@@ -401,113 +392,56 @@ export class EnactCore {
|
|
|
401
392
|
}
|
|
402
393
|
}
|
|
403
394
|
/**
|
|
404
|
-
*
|
|
395
|
+
* Static method to check if a tool exists
|
|
405
396
|
*/
|
|
406
|
-
async
|
|
397
|
+
static async toolExists(name, coreOptions = {}) {
|
|
407
398
|
try {
|
|
408
|
-
const tool = await
|
|
409
|
-
|
|
410
|
-
return {
|
|
411
|
-
verified: false,
|
|
412
|
-
signatures: [],
|
|
413
|
-
policy: policy || "permissive",
|
|
414
|
-
errors: [`Tool not found: ${name}`],
|
|
415
|
-
};
|
|
416
|
-
}
|
|
417
|
-
// Load public key from keys/file-public.pem
|
|
418
|
-
let publicKey;
|
|
419
|
-
try {
|
|
420
|
-
const keyPath = path.resolve(__dirname, "../../keys/file-public.pem");
|
|
421
|
-
publicKey = fs.readFileSync(keyPath, "utf8");
|
|
422
|
-
}
|
|
423
|
-
catch (e) {
|
|
424
|
-
logger.warn("Could not load public key for signature verification:", e);
|
|
425
|
-
}
|
|
426
|
-
if (!publicKey) {
|
|
427
|
-
return {
|
|
428
|
-
verified: false,
|
|
429
|
-
signatures: [],
|
|
430
|
-
policy: policy || "permissive",
|
|
431
|
-
errors: ["Public key not found for signature verification"],
|
|
432
|
-
};
|
|
433
|
-
}
|
|
434
|
-
const policyKey = (policy || "permissive").toUpperCase();
|
|
435
|
-
const policyObj = VERIFICATION_POLICIES[policyKey];
|
|
436
|
-
const verificationResult = await verifyToolSignatureWithPolicy(tool, policyObj);
|
|
437
|
-
if (!verificationResult.isValid) {
|
|
438
|
-
return {
|
|
439
|
-
verified: false,
|
|
440
|
-
signatures: [],
|
|
441
|
-
policy: policy || "permissive",
|
|
442
|
-
errors: verificationResult.errors,
|
|
443
|
-
};
|
|
444
|
-
}
|
|
445
|
-
const signatures = [];
|
|
446
|
-
if (tool.signature) {
|
|
447
|
-
signatures.push(tool.signature);
|
|
448
|
-
}
|
|
449
|
-
if (tool.signatures) {
|
|
450
|
-
signatures.push(...Object.values(tool.signatures));
|
|
451
|
-
}
|
|
452
|
-
return {
|
|
453
|
-
verified: verificationResult.isValid,
|
|
454
|
-
signatures,
|
|
455
|
-
policy: policy || "permissive",
|
|
456
|
-
};
|
|
399
|
+
const tool = await EnactCore.getToolByName(name, undefined, coreOptions);
|
|
400
|
+
return tool !== null;
|
|
457
401
|
}
|
|
458
402
|
catch (error) {
|
|
459
|
-
return
|
|
460
|
-
verified: false,
|
|
461
|
-
signatures: [],
|
|
462
|
-
policy: policy || "permissive",
|
|
463
|
-
errors: [`Verification error: ${error.message}`],
|
|
464
|
-
};
|
|
403
|
+
return false;
|
|
465
404
|
}
|
|
466
405
|
}
|
|
467
406
|
/**
|
|
468
|
-
*
|
|
407
|
+
* Instance method wrapper for backward compatibility
|
|
469
408
|
*/
|
|
470
409
|
async toolExists(name) {
|
|
471
|
-
|
|
472
|
-
const tool = await this.getToolByName(name);
|
|
473
|
-
return tool !== null;
|
|
474
|
-
}
|
|
475
|
-
catch (error) {
|
|
476
|
-
return false;
|
|
477
|
-
}
|
|
410
|
+
return EnactCore.toolExists(name, this.options);
|
|
478
411
|
}
|
|
479
412
|
/**
|
|
480
413
|
* Get tools by tags
|
|
481
414
|
*/
|
|
482
415
|
async getToolsByTags(tags, limit = 20) {
|
|
483
|
-
return
|
|
416
|
+
return EnactCore.searchTools({
|
|
484
417
|
query: tags.join(" "),
|
|
485
418
|
tags,
|
|
486
419
|
limit,
|
|
487
|
-
});
|
|
420
|
+
}, this.options);
|
|
488
421
|
}
|
|
489
422
|
/**
|
|
490
423
|
* Get tools by author
|
|
491
424
|
*/
|
|
492
425
|
async getToolsByAuthor(author, limit = 20) {
|
|
493
|
-
return
|
|
426
|
+
return EnactCore.searchTools({
|
|
494
427
|
query: `author:${author}`,
|
|
495
428
|
author,
|
|
496
429
|
limit,
|
|
497
|
-
});
|
|
430
|
+
}, this.options);
|
|
498
431
|
}
|
|
499
432
|
/**
|
|
500
|
-
*
|
|
433
|
+
* Static method to get all tools with filters
|
|
501
434
|
*/
|
|
502
|
-
async getTools(options = {}) {
|
|
435
|
+
static async getTools(options = {}, coreOptions = {}) {
|
|
436
|
+
const apiClient = new EnactApiClient(coreOptions.apiUrl || "https://enact.tools", coreOptions.supabaseUrl || "https://xjnhhxwxovjifdxdwzih.supabase.co");
|
|
503
437
|
try {
|
|
504
|
-
const apiResults = await
|
|
438
|
+
const apiResults = await apiClient.getTools(options);
|
|
505
439
|
// Parse and validate results
|
|
506
440
|
const tools = [];
|
|
507
441
|
for (const result of apiResults) {
|
|
508
442
|
if (result.name) {
|
|
509
443
|
try {
|
|
510
|
-
const tool = await
|
|
444
|
+
const tool = await EnactCore.getToolByName(result.name, undefined, coreOptions);
|
|
511
445
|
if (tool) {
|
|
512
446
|
tools.push(tool);
|
|
513
447
|
}
|
|
@@ -524,6 +458,12 @@ export class EnactCore {
|
|
|
524
458
|
throw new Error(`Failed to get tools: ${error instanceof Error ? error.message : String(error)}`);
|
|
525
459
|
}
|
|
526
460
|
}
|
|
461
|
+
/**
|
|
462
|
+
* Instance method wrapper for backward compatibility
|
|
463
|
+
*/
|
|
464
|
+
async getTools(options = {}) {
|
|
465
|
+
return EnactCore.getTools(options, this.options);
|
|
466
|
+
}
|
|
527
467
|
/**
|
|
528
468
|
* Get authentication status (placeholder - would need actual auth implementation)
|
|
529
469
|
*/
|
|
@@ -536,18 +476,13 @@ export class EnactCore {
|
|
|
536
476
|
};
|
|
537
477
|
}
|
|
538
478
|
/**
|
|
539
|
-
*
|
|
479
|
+
* Static method to publish a tool
|
|
540
480
|
*/
|
|
541
|
-
async publishTool(tool) {
|
|
542
|
-
|
|
543
|
-
return {
|
|
544
|
-
success: false,
|
|
545
|
-
message: "Authentication required to publish tools",
|
|
546
|
-
};
|
|
547
|
-
}
|
|
481
|
+
static async publishTool(tool, authToken, coreOptions = {}) {
|
|
482
|
+
const apiClient = new EnactApiClient(coreOptions.apiUrl || "https://enact.tools", coreOptions.supabaseUrl || "https://xjnhhxwxovjifdxdwzih.supabase.co");
|
|
548
483
|
try {
|
|
549
484
|
validateToolStructure(tool);
|
|
550
|
-
await
|
|
485
|
+
await apiClient.publishTool(tool, authToken);
|
|
551
486
|
return {
|
|
552
487
|
success: true,
|
|
553
488
|
message: `Successfully published tool: ${tool.name}`,
|
|
@@ -560,11 +495,23 @@ export class EnactCore {
|
|
|
560
495
|
};
|
|
561
496
|
}
|
|
562
497
|
}
|
|
498
|
+
/**
|
|
499
|
+
* Instance method wrapper for backward compatibility
|
|
500
|
+
*/
|
|
501
|
+
async publishTool(tool) {
|
|
502
|
+
if (!this.options.authToken) {
|
|
503
|
+
return {
|
|
504
|
+
success: false,
|
|
505
|
+
message: "Authentication required to publish tools",
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
return EnactCore.publishTool(tool, this.options.authToken, this.options);
|
|
509
|
+
}
|
|
563
510
|
/**
|
|
564
511
|
* Get tool information (alias for getToolByName for consistency)
|
|
565
512
|
*/
|
|
566
513
|
async getToolInfo(name, version) {
|
|
567
|
-
return
|
|
514
|
+
return EnactCore.getToolByName(name, version, this.options);
|
|
568
515
|
}
|
|
569
516
|
/**
|
|
570
517
|
* Get core library status
|
|
@@ -574,7 +521,6 @@ export class EnactCore {
|
|
|
574
521
|
return {
|
|
575
522
|
executionProvider: this.options.executionProvider || "direct",
|
|
576
523
|
apiUrl: this.options.apiUrl || "https://enact.tools",
|
|
577
|
-
verificationPolicy: this.options.verificationPolicy || "permissive",
|
|
578
524
|
defaultTimeout: this.options.defaultTimeout || "30s",
|
|
579
525
|
authenticated: authStatus.authenticated,
|
|
580
526
|
};
|
|
@@ -605,5 +551,4 @@ export class EnactCore {
|
|
|
605
551
|
return `exec_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
606
552
|
}
|
|
607
553
|
}
|
|
608
|
-
//
|
|
609
|
-
export const enactCore = new EnactCore();
|
|
554
|
+
// No default instance to avoid eager initialization of Dagger
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ExecutionProvider, type EnactTool, type ExecutionEnvironment, type ExecutionResult } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Native execution provider that throws an error if used for actual execution.
|
|
4
|
+
* This is for CLI commands that use Core for API operations only.
|
|
5
|
+
*/
|
|
6
|
+
export declare class NativeExecutionProvider extends ExecutionProvider {
|
|
7
|
+
resolveEnvironmentVariables(envConfig: Record<string, any>, namespace?: string): Promise<Record<string, any>>;
|
|
8
|
+
execute(tool: EnactTool, input: Record<string, any>, environment: ExecutionEnvironment): Promise<ExecutionResult>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// src/core/NativeExecutionProvider.ts - No-op execution provider for CLI commands
|
|
2
|
+
import { ExecutionProvider, } from "../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Native execution provider that throws an error if used for actual execution.
|
|
5
|
+
* This is for CLI commands that use Core for API operations only.
|
|
6
|
+
*/
|
|
7
|
+
export class NativeExecutionProvider extends ExecutionProvider {
|
|
8
|
+
async resolveEnvironmentVariables(envConfig, namespace) {
|
|
9
|
+
// This should never be called for native CLI commands
|
|
10
|
+
throw new Error("Native execution provider cannot resolve environment variables");
|
|
11
|
+
}
|
|
12
|
+
async execute(tool, input, environment) {
|
|
13
|
+
// This should never be called for native CLI commands
|
|
14
|
+
throw new Error(`Native execution provider cannot execute tools. Tool "${tool.name}" should be executed via direct or dagger provider.`);
|
|
15
|
+
}
|
|
16
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -14,10 +14,6 @@ export { showVersion as utilsShowVersion } from './utils/version';
|
|
|
14
14
|
export * from './utils/logger';
|
|
15
15
|
export * from './utils/silent-monitor';
|
|
16
16
|
export * from './utils/timeout';
|
|
17
|
-
export * from './security/security';
|
|
18
|
-
export { verifyTool, shouldExecuteTool, VERIFICATION_POLICIES } from './security/sign';
|
|
19
|
-
export type { VerificationPolicy as SecurityVerificationPolicy } from './security/sign';
|
|
20
|
-
export * from './security/verification-enforcer';
|
|
21
17
|
export * from './services/McpCoreService';
|
|
22
18
|
export * from './web/env-manager-server';
|
|
23
19
|
export * from './api/enact-api';
|
package/dist/index.js
CHANGED
|
@@ -15,10 +15,6 @@ export { showVersion as utilsShowVersion } from './utils/version';
|
|
|
15
15
|
export * from './utils/logger';
|
|
16
16
|
export * from './utils/silent-monitor';
|
|
17
17
|
export * from './utils/timeout';
|
|
18
|
-
// Security
|
|
19
|
-
export * from './security/security';
|
|
20
|
-
export { verifyTool, shouldExecuteTool, VERIFICATION_POLICIES } from './security/sign';
|
|
21
|
-
export * from './security/verification-enforcer';
|
|
22
18
|
// Services
|
|
23
19
|
export * from './services/McpCoreService';
|
|
24
20
|
// Web
|