agentic-flow 2.0.13 → 2.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.
- package/CHANGELOG.md +87 -0
- package/README.md +376 -186
- package/dist/.tsbuildinfo +1 -1
- package/dist/agent-booster/index.d.ts +14 -0
- package/dist/agent-booster/index.d.ts.map +1 -0
- package/dist/agent-booster/index.js +25 -0
- package/dist/agent-booster/index.js.map +1 -0
- package/dist/agents/directApiAgent.d.ts.map +1 -1
- package/dist/agents/directApiAgent.js +37 -19
- package/dist/agents/directApiAgent.js.map +1 -1
- package/dist/cli/commands/hooks.d.ts.map +1 -1
- package/dist/cli/commands/hooks.js +4 -1
- package/dist/cli/commands/hooks.js.map +1 -1
- package/dist/cli/mcp-manager.js +13 -6
- package/dist/cli/mcp-manager.js.map +1 -1
- package/dist/harness/provenance.d.ts +72 -0
- package/dist/harness/provenance.d.ts.map +1 -0
- package/dist/harness/provenance.js +92 -0
- package/dist/harness/provenance.js.map +1 -0
- package/dist/intelligence/EmbeddingService.js +3 -3
- package/dist/intelligence/EmbeddingService.js.map +1 -1
- package/dist/intelligence/agent-booster-enhanced.d.ts.map +1 -1
- package/dist/intelligence/agent-booster-enhanced.js +5 -3
- package/dist/intelligence/agent-booster-enhanced.js.map +1 -1
- package/dist/mcp/claudeFlowSdkServer.d.ts.map +1 -1
- package/dist/mcp/claudeFlowSdkServer.js +76 -29
- package/dist/mcp/claudeFlowSdkServer.js.map +1 -1
- package/dist/mcp/fastmcp/servers/claude-flow-sdk.js +27 -22
- package/dist/mcp/fastmcp/servers/claude-flow-sdk.js.map +1 -1
- package/dist/mcp/fastmcp/servers/http-sse.js +31 -20
- package/dist/mcp/fastmcp/servers/http-sse.js.map +1 -1
- package/dist/mcp/fastmcp/servers/http-streaming-updated.js +33 -32
- package/dist/mcp/fastmcp/servers/http-streaming-updated.js.map +1 -1
- package/dist/mcp/fastmcp/servers/poc-stdio.js +10 -11
- package/dist/mcp/fastmcp/servers/poc-stdio.js.map +1 -1
- package/dist/mcp/fastmcp/servers/stdio-full.js +33 -32
- package/dist/mcp/fastmcp/servers/stdio-full.js.map +1 -1
- package/dist/mcp/fastmcp/tools/agent/execute.d.ts.map +1 -1
- package/dist/mcp/fastmcp/tools/agent/execute.js +8 -5
- package/dist/mcp/fastmcp/tools/agent/execute.js.map +1 -1
- package/dist/mcp/fastmcp/tools/agent/list.d.ts.map +1 -1
- package/dist/mcp/fastmcp/tools/agent/list.js +4 -2
- package/dist/mcp/fastmcp/tools/agent/list.js.map +1 -1
- package/dist/mcp/fastmcp/tools/agent/parallel.d.ts.map +1 -1
- package/dist/mcp/fastmcp/tools/agent/parallel.js +4 -2
- package/dist/mcp/fastmcp/tools/agent/parallel.js.map +1 -1
- package/dist/mcp/fastmcp/tools/hooks/pretrain.d.ts.map +1 -1
- package/dist/mcp/fastmcp/tools/hooks/pretrain.js +11 -3
- package/dist/mcp/fastmcp/tools/hooks/pretrain.js.map +1 -1
- package/dist/mcp/fastmcp/tools/swarm/orchestrate.d.ts.map +1 -1
- package/dist/mcp/fastmcp/tools/swarm/orchestrate.js +9 -5
- package/dist/mcp/fastmcp/tools/swarm/orchestrate.js.map +1 -1
- package/dist/mcp/standalone-stdio.js +76 -57
- package/dist/mcp/standalone-stdio.js.map +1 -1
- package/dist/mcp/tools/harness-tools.d.ts +28 -0
- package/dist/mcp/tools/harness-tools.d.ts.map +1 -0
- package/dist/mcp/tools/harness-tools.js +90 -0
- package/dist/mcp/tools/harness-tools.js.map +1 -0
- package/dist/optimizations/configuration-tuning.d.ts +1 -1
- package/dist/reasoningbank/utils/embeddings.d.ts +0 -6
- package/dist/reasoningbank/utils/embeddings.d.ts.map +1 -1
- package/dist/reasoningbank/utils/embeddings.js +9 -43
- package/dist/reasoningbank/utils/embeddings.js.map +1 -1
- package/dist/repair/cli.d.ts +24 -0
- package/dist/repair/cli.d.ts.map +1 -0
- package/dist/repair/cli.js +69 -0
- package/dist/repair/cli.js.map +1 -0
- package/dist/repair/darwin-repair.d.ts +80 -0
- package/dist/repair/darwin-repair.d.ts.map +1 -0
- package/dist/repair/darwin-repair.js +81 -0
- package/dist/repair/darwin-repair.js.map +1 -0
- package/dist/router/cost-optimal-router.d.ts +89 -0
- package/dist/router/cost-optimal-router.d.ts.map +1 -0
- package/dist/router/cost-optimal-router.js +94 -0
- package/dist/router/cost-optimal-router.js.map +1 -0
- package/dist/router/providers/onnx-local-optimized.d.ts +1 -10
- package/dist/router/providers/onnx-local-optimized.d.ts.map +1 -1
- package/dist/router/providers/onnx-local-optimized.js +9 -10
- package/dist/router/providers/onnx-local-optimized.js.map +1 -1
- package/dist/router/providers/onnx-local.d.ts +0 -9
- package/dist/router/providers/onnx-local.d.ts.map +1 -1
- package/dist/router/providers/onnx-local.js +7 -22
- package/dist/router/providers/onnx-local.js.map +1 -1
- package/dist/router/router.d.ts +29 -0
- package/dist/router/router.d.ts.map +1 -1
- package/dist/router/router.js +83 -0
- package/dist/router/router.js.map +1 -1
- package/dist/router/types.d.ts +1 -1
- package/dist/router/types.d.ts.map +1 -1
- package/dist/router/types.js.map +1 -1
- package/dist/sdk/plugins.d.ts +6 -6
- package/dist/sdk/plugins.d.ts.map +1 -1
- package/dist/sdk/plugins.js +37 -0
- package/dist/sdk/plugins.js.map +1 -1
- package/dist/transport/index.d.ts +1 -0
- package/dist/transport/index.d.ts.map +1 -1
- package/dist/transport/index.js +1 -0
- package/dist/transport/index.js.map +1 -1
- package/dist/transport/quic-loader.d.ts +250 -0
- package/dist/transport/quic-loader.d.ts.map +1 -0
- package/dist/transport/quic-loader.js +507 -0
- package/dist/transport/quic-loader.js.map +1 -0
- package/dist/utils/agentBoosterPreprocessor.js +16 -22
- package/dist/utils/agentBoosterPreprocessor.js.map +1 -1
- package/package.json +21 -6
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Harness provenance — Ed25519 witness manifest over harness/agent config files
|
|
3
|
+
* (ADR-075, Track B).
|
|
4
|
+
*
|
|
5
|
+
* Produces a tamper-evident manifest (sha256 per file) and signs it with Ed25519
|
|
6
|
+
* (Node's built-in `crypto` — no external deps), complementing the CWE-78
|
|
7
|
+
* hardening: a signed manifest lets a consumer verify that the agent/skill/policy
|
|
8
|
+
* files a harness ships are exactly the ones that were reviewed.
|
|
9
|
+
*
|
|
10
|
+
* Deterministic by construction (no wall-clock inside): the caller supplies any
|
|
11
|
+
* timestamp, and entries are sorted, so signing the same files yields the same
|
|
12
|
+
* payload.
|
|
13
|
+
*
|
|
14
|
+
* @see docs/adr/ADR-075-metaharness-harness-evolution-and-provenance.md
|
|
15
|
+
*/
|
|
16
|
+
export interface ManifestEntry {
|
|
17
|
+
/** File path as supplied (used as the stable sort/identity key). */
|
|
18
|
+
path: string;
|
|
19
|
+
/** Lowercase hex sha256 of the file contents. */
|
|
20
|
+
sha256: string;
|
|
21
|
+
}
|
|
22
|
+
export interface HarnessManifest {
|
|
23
|
+
version: 1;
|
|
24
|
+
/** Optional caller-supplied timestamp (ISO string). Part of the signed payload. */
|
|
25
|
+
createdAt?: string;
|
|
26
|
+
/** File digests, sorted by path for a canonical, reproducible payload. */
|
|
27
|
+
entries: ManifestEntry[];
|
|
28
|
+
}
|
|
29
|
+
export interface KeyPairPem {
|
|
30
|
+
publicKey: string;
|
|
31
|
+
privateKey: string;
|
|
32
|
+
}
|
|
33
|
+
/** Generate an Ed25519 keypair as PEM strings (spki/pkcs8). */
|
|
34
|
+
export declare function generateKeyPairPem(): KeyPairPem;
|
|
35
|
+
/** sha256 (hex) of a buffer. */
|
|
36
|
+
export declare function sha256Hex(data: Buffer | string): string;
|
|
37
|
+
/**
|
|
38
|
+
* Build a canonical manifest over the given files. Entries are sorted by path so
|
|
39
|
+
* the signed payload is stable regardless of input order. `createdAt` is included
|
|
40
|
+
* verbatim if provided.
|
|
41
|
+
*/
|
|
42
|
+
export declare function buildManifest(files: string[], opts?: {
|
|
43
|
+
createdAt?: string;
|
|
44
|
+
}): HarnessManifest;
|
|
45
|
+
/** Sign a manifest with an Ed25519 private-key PEM. Returns a base64 signature. */
|
|
46
|
+
export declare function signManifest(manifest: HarnessManifest, privateKeyPem: string): string;
|
|
47
|
+
/** Verify a base64 Ed25519 signature over a manifest with a public-key PEM. */
|
|
48
|
+
export declare function verifyManifest(manifest: HarnessManifest, signatureBase64: string, publicKeyPem: string): boolean;
|
|
49
|
+
export interface SignedManifest {
|
|
50
|
+
manifest: HarnessManifest;
|
|
51
|
+
signature: string;
|
|
52
|
+
publicKey: string;
|
|
53
|
+
}
|
|
54
|
+
/** Convenience: build + sign in one step, returning a portable signed bundle. */
|
|
55
|
+
export declare function signFiles(files: string[], privateKeyPem: string, publicKeyPem: string, opts?: {
|
|
56
|
+
createdAt?: string;
|
|
57
|
+
}): SignedManifest;
|
|
58
|
+
/**
|
|
59
|
+
* Verify a signed bundle AND that the on-disk files still match the manifest
|
|
60
|
+
* digests. Returns a per-file drift report so a caller can see exactly what
|
|
61
|
+
* changed since signing.
|
|
62
|
+
*/
|
|
63
|
+
export declare function verifySignedManifest(signed: SignedManifest): {
|
|
64
|
+
signatureValid: boolean;
|
|
65
|
+
filesIntact: boolean;
|
|
66
|
+
drift: {
|
|
67
|
+
path: string;
|
|
68
|
+
expected: string;
|
|
69
|
+
actual: string | null;
|
|
70
|
+
}[];
|
|
71
|
+
};
|
|
72
|
+
//# sourceMappingURL=provenance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provenance.d.ts","sourceRoot":"","sources":["../../src/harness/provenance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,MAAM,WAAW,aAAa;IAC5B,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,CAAC,CAAC;IACX,mFAAmF;IACnF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,+DAA+D;AAC/D,wBAAgB,kBAAkB,IAAI,UAAU,CAM/C;AAED,gCAAgC;AAChC,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,eAAe,CAKjG;AAYD,mFAAmF;AACnF,wBAAgB,YAAY,CAAC,QAAQ,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAIrF;AAED,+EAA+E;AAC/E,wBAAgB,cAAc,CAAC,QAAQ,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAOhH;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,eAAe,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,iFAAiF;AACjF,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,cAAc,CAGzI;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,cAAc,GAAG;IAC5D,cAAc,EAAE,OAAO,CAAC;IACxB,WAAW,EAAE,OAAO,CAAC;IACrB,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,EAAE,CAAC;CACpE,CAaA"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Harness provenance — Ed25519 witness manifest over harness/agent config files
|
|
3
|
+
* (ADR-075, Track B).
|
|
4
|
+
*
|
|
5
|
+
* Produces a tamper-evident manifest (sha256 per file) and signs it with Ed25519
|
|
6
|
+
* (Node's built-in `crypto` — no external deps), complementing the CWE-78
|
|
7
|
+
* hardening: a signed manifest lets a consumer verify that the agent/skill/policy
|
|
8
|
+
* files a harness ships are exactly the ones that were reviewed.
|
|
9
|
+
*
|
|
10
|
+
* Deterministic by construction (no wall-clock inside): the caller supplies any
|
|
11
|
+
* timestamp, and entries are sorted, so signing the same files yields the same
|
|
12
|
+
* payload.
|
|
13
|
+
*
|
|
14
|
+
* @see docs/adr/ADR-075-metaharness-harness-evolution-and-provenance.md
|
|
15
|
+
*/
|
|
16
|
+
import { generateKeyPairSync, sign as cryptoSign, verify as cryptoVerify, createHash } from 'node:crypto';
|
|
17
|
+
import { readFileSync } from 'node:fs';
|
|
18
|
+
/** Generate an Ed25519 keypair as PEM strings (spki/pkcs8). */
|
|
19
|
+
export function generateKeyPairPem() {
|
|
20
|
+
const { publicKey, privateKey } = generateKeyPairSync('ed25519');
|
|
21
|
+
return {
|
|
22
|
+
publicKey: publicKey.export({ type: 'spki', format: 'pem' }).toString(),
|
|
23
|
+
privateKey: privateKey.export({ type: 'pkcs8', format: 'pem' }).toString(),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/** sha256 (hex) of a buffer. */
|
|
27
|
+
export function sha256Hex(data) {
|
|
28
|
+
return createHash('sha256').update(data).digest('hex');
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Build a canonical manifest over the given files. Entries are sorted by path so
|
|
32
|
+
* the signed payload is stable regardless of input order. `createdAt` is included
|
|
33
|
+
* verbatim if provided.
|
|
34
|
+
*/
|
|
35
|
+
export function buildManifest(files, opts = {}) {
|
|
36
|
+
const entries = files
|
|
37
|
+
.map((path) => ({ path, sha256: sha256Hex(readFileSync(path)) }))
|
|
38
|
+
.sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));
|
|
39
|
+
return { version: 1, ...(opts.createdAt ? { createdAt: opts.createdAt } : {}), entries };
|
|
40
|
+
}
|
|
41
|
+
/** Canonical bytes that get signed/verified — stable JSON of the manifest. */
|
|
42
|
+
function canonicalPayload(manifest) {
|
|
43
|
+
// Keys emitted in a fixed order; entries already sorted by buildManifest.
|
|
44
|
+
return JSON.stringify({
|
|
45
|
+
version: manifest.version,
|
|
46
|
+
createdAt: manifest.createdAt ?? null,
|
|
47
|
+
entries: manifest.entries.map((e) => ({ path: e.path, sha256: e.sha256 })),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/** Sign a manifest with an Ed25519 private-key PEM. Returns a base64 signature. */
|
|
51
|
+
export function signManifest(manifest, privateKeyPem) {
|
|
52
|
+
const payload = Buffer.from(canonicalPayload(manifest), 'utf8');
|
|
53
|
+
// Ed25519 takes a null algorithm (the curve fixes the hash).
|
|
54
|
+
return cryptoSign(null, payload, privateKeyPem).toString('base64');
|
|
55
|
+
}
|
|
56
|
+
/** Verify a base64 Ed25519 signature over a manifest with a public-key PEM. */
|
|
57
|
+
export function verifyManifest(manifest, signatureBase64, publicKeyPem) {
|
|
58
|
+
try {
|
|
59
|
+
const payload = Buffer.from(canonicalPayload(manifest), 'utf8');
|
|
60
|
+
return cryptoVerify(null, payload, publicKeyPem, Buffer.from(signatureBase64, 'base64'));
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return false; // malformed signature/key → not verified
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/** Convenience: build + sign in one step, returning a portable signed bundle. */
|
|
67
|
+
export function signFiles(files, privateKeyPem, publicKeyPem, opts = {}) {
|
|
68
|
+
const manifest = buildManifest(files, opts);
|
|
69
|
+
return { manifest, signature: signManifest(manifest, privateKeyPem), publicKey: publicKeyPem };
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Verify a signed bundle AND that the on-disk files still match the manifest
|
|
73
|
+
* digests. Returns a per-file drift report so a caller can see exactly what
|
|
74
|
+
* changed since signing.
|
|
75
|
+
*/
|
|
76
|
+
export function verifySignedManifest(signed) {
|
|
77
|
+
const signatureValid = verifyManifest(signed.manifest, signed.signature, signed.publicKey);
|
|
78
|
+
const drift = [];
|
|
79
|
+
for (const entry of signed.manifest.entries) {
|
|
80
|
+
let actual = null;
|
|
81
|
+
try {
|
|
82
|
+
actual = sha256Hex(readFileSync(entry.path));
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
actual = null; // missing/unreadable
|
|
86
|
+
}
|
|
87
|
+
if (actual !== entry.sha256)
|
|
88
|
+
drift.push({ path: entry.path, expected: entry.sha256, actual });
|
|
89
|
+
}
|
|
90
|
+
return { signatureValid, filesIntact: drift.length === 0, drift };
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=provenance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provenance.js","sourceRoot":"","sources":["../../src/harness/provenance.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Harness provenance — Ed25519 witness manifest over harness/agent config files\n * (ADR-075, Track B).\n *\n * Produces a tamper-evident manifest (sha256 per file) and signs it with Ed25519\n * (Node's built-in `crypto` — no external deps), complementing the CWE-78\n * hardening: a signed manifest lets a consumer verify that the agent/skill/policy\n * files a harness ships are exactly the ones that were reviewed.\n *\n * Deterministic by construction (no wall-clock inside): the caller supplies any\n * timestamp, and entries are sorted, so signing the same files yields the same\n * payload.\n *\n * @see docs/adr/ADR-075-metaharness-harness-evolution-and-provenance.md\n */\n\nimport { generateKeyPairSync, sign as cryptoSign, verify as cryptoVerify, createHash } from 'node:crypto';\nimport { readFileSync } from 'node:fs';\n\nexport interface ManifestEntry {\n /** File path as supplied (used as the stable sort/identity key). */\n path: string;\n /** Lowercase hex sha256 of the file contents. */\n sha256: string;\n}\n\nexport interface HarnessManifest {\n version: 1;\n /** Optional caller-supplied timestamp (ISO string). Part of the signed payload. */\n createdAt?: string;\n /** File digests, sorted by path for a canonical, reproducible payload. */\n entries: ManifestEntry[];\n}\n\nexport interface KeyPairPem {\n publicKey: string;\n privateKey: string;\n}\n\n/** Generate an Ed25519 keypair as PEM strings (spki/pkcs8). */\nexport function generateKeyPairPem(): KeyPairPem {\n const { publicKey, privateKey } = generateKeyPairSync('ed25519');\n return {\n publicKey: publicKey.export({ type: 'spki', format: 'pem' }).toString(),\n privateKey: privateKey.export({ type: 'pkcs8', format: 'pem' }).toString(),\n };\n}\n\n/** sha256 (hex) of a buffer. */\nexport function sha256Hex(data: Buffer | string): string {\n return createHash('sha256').update(data).digest('hex');\n}\n\n/**\n * Build a canonical manifest over the given files. Entries are sorted by path so\n * the signed payload is stable regardless of input order. `createdAt` is included\n * verbatim if provided.\n */\nexport function buildManifest(files: string[], opts: { createdAt?: string } = {}): HarnessManifest {\n const entries: ManifestEntry[] = files\n .map((path) => ({ path, sha256: sha256Hex(readFileSync(path)) }))\n .sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));\n return { version: 1, ...(opts.createdAt ? { createdAt: opts.createdAt } : {}), entries };\n}\n\n/** Canonical bytes that get signed/verified — stable JSON of the manifest. */\nfunction canonicalPayload(manifest: HarnessManifest): string {\n // Keys emitted in a fixed order; entries already sorted by buildManifest.\n return JSON.stringify({\n version: manifest.version,\n createdAt: manifest.createdAt ?? null,\n entries: manifest.entries.map((e) => ({ path: e.path, sha256: e.sha256 })),\n });\n}\n\n/** Sign a manifest with an Ed25519 private-key PEM. Returns a base64 signature. */\nexport function signManifest(manifest: HarnessManifest, privateKeyPem: string): string {\n const payload = Buffer.from(canonicalPayload(manifest), 'utf8');\n // Ed25519 takes a null algorithm (the curve fixes the hash).\n return cryptoSign(null, payload, privateKeyPem).toString('base64');\n}\n\n/** Verify a base64 Ed25519 signature over a manifest with a public-key PEM. */\nexport function verifyManifest(manifest: HarnessManifest, signatureBase64: string, publicKeyPem: string): boolean {\n try {\n const payload = Buffer.from(canonicalPayload(manifest), 'utf8');\n return cryptoVerify(null, payload, publicKeyPem, Buffer.from(signatureBase64, 'base64'));\n } catch {\n return false; // malformed signature/key → not verified\n }\n}\n\nexport interface SignedManifest {\n manifest: HarnessManifest;\n signature: string; // base64\n publicKey: string; // spki PEM (the verification anchor)\n}\n\n/** Convenience: build + sign in one step, returning a portable signed bundle. */\nexport function signFiles(files: string[], privateKeyPem: string, publicKeyPem: string, opts: { createdAt?: string } = {}): SignedManifest {\n const manifest = buildManifest(files, opts);\n return { manifest, signature: signManifest(manifest, privateKeyPem), publicKey: publicKeyPem };\n}\n\n/**\n * Verify a signed bundle AND that the on-disk files still match the manifest\n * digests. Returns a per-file drift report so a caller can see exactly what\n * changed since signing.\n */\nexport function verifySignedManifest(signed: SignedManifest): {\n signatureValid: boolean;\n filesIntact: boolean;\n drift: { path: string; expected: string; actual: string | null }[];\n} {\n const signatureValid = verifyManifest(signed.manifest, signed.signature, signed.publicKey);\n const drift: { path: string; expected: string; actual: string | null }[] = [];\n for (const entry of signed.manifest.entries) {\n let actual: string | null = null;\n try {\n actual = sha256Hex(readFileSync(entry.path));\n } catch {\n actual = null; // missing/unreadable\n }\n if (actual !== entry.sha256) drift.push({ path: entry.path, expected: entry.sha256, actual });\n }\n return { signatureValid, filesIntact: drift.length === 0, drift };\n}\n"]}
|
|
@@ -814,11 +814,11 @@ export class EmbeddingService {
|
|
|
814
814
|
let newChunks = 0;
|
|
815
815
|
let skipped = 0;
|
|
816
816
|
try {
|
|
817
|
-
const {
|
|
817
|
+
const { execFileSync } = await import('child_process');
|
|
818
818
|
const path = await import('path');
|
|
819
819
|
const fs = await import('fs');
|
|
820
|
-
// Get changed files from git
|
|
821
|
-
const gitOutput =
|
|
820
|
+
// Get changed files from git — pass `since` as a separate arg to avoid shell injection
|
|
821
|
+
const gitOutput = execFileSync('git', ['diff', '--name-only', since], {
|
|
822
822
|
cwd: repoPath,
|
|
823
823
|
encoding: 'utf-8',
|
|
824
824
|
});
|