mneme-ai 3.1.0 → 3.2.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.
@@ -0,0 +1,10 @@
1
+ /**
2
+ * `mneme skillscan` (v3.2.0) — the signed provenance gate for AI agent skills / MCP tools.
3
+ * Scan a skill (a file or a directory) against the 8-point checklist, pin it by content hash,
4
+ * and (optionally) mint a NOTARY (Ed25519) provenance receipt that anyone verifies OFFLINE.
5
+ * skillscan <path> [--sign] [--out receipt.json] [--json]
6
+ * skillscan verify <receipt.json> [--path <skill>] (also re-hashes the skill if --path given)
7
+ */
8
+ import type { Command } from "commander";
9
+ export declare function registerSkillscanCommands(program: Command): void;
10
+ //# sourceMappingURL=skillscan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skillscan.d.ts","sourceRoot":"","sources":["../../src/commands/skillscan.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA6BzC,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAyChE"}
@@ -0,0 +1,110 @@
1
+ import { existsSync, readFileSync, writeFileSync, statSync, readdirSync } from "node:fs";
2
+ import { join, extname, basename } from "node:path";
3
+ import { skillscan, notary } from "@mneme-ai/core";
4
+ function out(s) { process.stdout.write(s + "\n"); }
5
+ const SKILL_EXT = new Set([".md", ".markdown", ".json", ".mjs", ".cjs", ".js", ".ts", ".txt", ".yaml", ".yml", ".toml", ".sh", ".py"]);
6
+ /** Read a skill's text: a single file, or concatenate the skill-ish files in a directory (≤512KB). */
7
+ function readSkill(path) {
8
+ if (!existsSync(path))
9
+ return { text: "", files: [] };
10
+ const st = statSync(path);
11
+ if (st.isFile())
12
+ return { text: readFileSync(path, "utf8"), files: [path] };
13
+ const parts = [];
14
+ const files = [];
15
+ let total = 0;
16
+ const walk = (dir, depth) => {
17
+ if (depth > 3 || total > 512_000)
18
+ return;
19
+ for (const e of readdirSync(dir, { withFileTypes: true })) {
20
+ if (e.name === "node_modules" || e.name.startsWith(".git"))
21
+ continue;
22
+ const p = join(dir, e.name);
23
+ if (e.isDirectory())
24
+ walk(p, depth + 1);
25
+ else if (SKILL_EXT.has(extname(e.name).toLowerCase()) && total < 512_000) {
26
+ try {
27
+ const c = readFileSync(p, "utf8");
28
+ parts.push(`\n# ── ${e.name} ──\n${c}`);
29
+ files.push(p);
30
+ total += c.length;
31
+ }
32
+ catch { /* */ }
33
+ }
34
+ }
35
+ };
36
+ walk(path, 0);
37
+ return { text: parts.join("\n"), files };
38
+ }
39
+ export function registerSkillscanCommands(program) {
40
+ const k = program.command("skillscan").description("🛂 SKILLSCAN — the signed provenance gate for AI agent skills / MCP tools: 8-point static scan (prompt-injection · exfiltration · secret · dangerous-command · obfuscation · external-fetch · credential-access · privilege-escalation) + a content-hash + an offline-verifiable NOTARY receipt. The supply-chain frontier, local-first.");
41
+ k.command("scan <path>", { isDefault: true }).description("Scan a skill file/dir; optionally mint a signed provenance receipt.")
42
+ .option("--sign", "mint a NOTARY-signed provenance receipt").option("--out <file>", "write the receipt JSON").option("--json", "emit the full result as JSON")
43
+ .action((path, o) => {
44
+ const { text, files } = readSkill(path);
45
+ if (!text.trim()) {
46
+ out(`✗ nothing to scan at ${path}`);
47
+ process.exitCode = 2;
48
+ return;
49
+ }
50
+ const r = skillscan.scanSkill(text);
51
+ const subject = `skill:${basename(path)}`;
52
+ let receipt = null;
53
+ if (o.sign || o.out) {
54
+ try {
55
+ receipt = notary.issueReceipt(process.cwd(), { kind: "skill-provenance", subject, payload: { contentHash: r.contentHash, bytes: r.bytes, verdict: r.verdict, hits: r.hits, files: files.length }, includePayload: true, issuedAt: Date.now() });
56
+ }
57
+ catch { /* */ }
58
+ if (o.out && receipt)
59
+ writeFileSync(o.out, JSON.stringify(receipt, null, 2), "utf8");
60
+ }
61
+ if (o.json) {
62
+ out(JSON.stringify({ result: r, receipt }, null, 2));
63
+ if (r.verdict === "BLOCK")
64
+ process.exitCode = 2;
65
+ return;
66
+ }
67
+ const icon = r.verdict === "BLOCK" ? "🔴" : r.verdict === "REVIEW" ? "🟡" : "🟢";
68
+ out(`🛂 SKILLSCAN — ${icon} ${r.verdict} · ${files.length} file(s) · ${r.bytes}B · sha256 ${r.contentHash.slice(0, 16)}…`);
69
+ for (const h of r.hits)
70
+ out(` 🚩 ${h.id} (${h.severity})${h.evidence ? " " + h.evidence : ""}`);
71
+ if (!r.hits.length)
72
+ out(" ✓ no risk-class hits across the 8-point checklist");
73
+ if (receipt)
74
+ out(` 🪪 signed provenance receipt${o.out ? " → " + o.out : ""} (verify offline: mneme skillscan verify)`);
75
+ if (r.verdict === "BLOCK")
76
+ process.exitCode = 2;
77
+ });
78
+ k.command("verify <receipt>").description("Verify a provenance receipt OFFLINE (Ed25519); with --path, re-hash the skill to confirm it's unchanged.")
79
+ .option("--path <skill>", "re-scan this skill and confirm its content-hash matches the receipt")
80
+ .action((receiptFile, o) => {
81
+ if (!existsSync(receiptFile)) {
82
+ out("receipt not found");
83
+ process.exitCode = 2;
84
+ return;
85
+ }
86
+ let receipt;
87
+ try {
88
+ receipt = JSON.parse(readFileSync(receiptFile, "utf8"));
89
+ }
90
+ catch {
91
+ out("✗ invalid receipt JSON");
92
+ process.exitCode = 2;
93
+ return;
94
+ }
95
+ const v = notary.verifyReceipt(receipt);
96
+ out(v.valid ? "✓ signature VALID (Ed25519, offline)" : `✗ signature INVALID: ${v.reason}`);
97
+ if (v.valid && receipt.payload)
98
+ out(` verdict at signing: ${receipt.payload.verdict} · pinned sha256 ${String(receipt.payload.contentHash).slice(0, 16)}…`);
99
+ if (o.path && receipt.payload?.contentHash) {
100
+ const now = skillscan.scanSkill(readSkill(o.path).text);
101
+ const match = now.contentHash === receipt.payload.contentHash;
102
+ out(match ? " ✓ content UNCHANGED since signing (hash matches)" : " ⚠ content CHANGED since signing — receipt does NOT cover the current skill!");
103
+ if (!match)
104
+ process.exitCode = 2;
105
+ }
106
+ if (!v.valid)
107
+ process.exitCode = 2;
108
+ });
109
+ }
110
+ //# sourceMappingURL=skillscan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skillscan.js","sourceRoot":"","sources":["../../src/commands/skillscan.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA4LA,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA4lNvD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA6LA,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA6lNvD"}
package/dist/index.js CHANGED
@@ -106,6 +106,7 @@ import { registerSuccessionCommands } from "./commands/succession.js";
106
106
  import { registerPagerCommands } from "./commands/pager.js";
107
107
  import { registerKeryxCommands } from "./commands/keryx.js";
108
108
  import { registerCompileCommands } from "./commands/compile.js";
109
+ import { registerSkillscanCommands } from "./commands/skillscan.js";
109
110
  import { registerAdamasCommands } from "./commands/adamas.js";
110
111
  import { registerPrismCommands } from "./commands/prism.js";
111
112
  import { registerGoldilocksCommands } from "./commands/goldilocks.js";
@@ -4779,6 +4780,7 @@ export async function run(argv) {
4779
4780
  registerPagerCommands(program);
4780
4781
  registerKeryxCommands(program);
4781
4782
  registerCompileCommands(program);
4783
+ registerSkillscanCommands(program);
4782
4784
  registerAdamasCommands(program);
4783
4785
  registerPrismCommands(program);
4784
4786
  registerGoldilocksCommands(program);