mneme-ai 2.59.0 → 2.61.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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAuIA,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA29KvD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAuIA,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAgrLvD"}
package/dist/index.js CHANGED
@@ -4682,6 +4682,238 @@ export async function run(argv) {
4682
4682
  process.exitCode = 1;
4683
4683
  }
4684
4684
  });
4685
+ // v2.61.0 — PASSPORT: capability-based security for MCP.
4686
+ // Agents request HMAC-signed passports before sensitive tool calls;
4687
+ // trust score gates issuance; delegation chain + revocation cascade
4688
+ // + HMAC-chained audit ledger.
4689
+ const passportParent = program
4690
+ .command("capability")
4691
+ .description("v2.61 — capability-based security. Default action = audit ledger.")
4692
+ .action(async () => {
4693
+ try {
4694
+ const core = await import("@mneme-ai/core");
4695
+ const led = core.passport.verifyLedgerChain(process.cwd());
4696
+ const rows = core.passport.readLedger(process.cwd());
4697
+ process.stdout.write(JSON.stringify({ ok: led.ok, rows: led.rows, brokenAt: led.brokenAt, recent: rows.slice(-10) }, null, 2) + "\n");
4698
+ }
4699
+ catch (e) {
4700
+ process.stdout.write(JSON.stringify({ ok: false, error: e.message }) + "\n");
4701
+ process.exitCode = 1;
4702
+ }
4703
+ });
4704
+ passportParent.command("request")
4705
+ .description("Request a passport for a sensitive tool. Trust score must clear tier threshold.")
4706
+ .requiredOption("--tool <name>", "Tool name (e.g. shell.exec)")
4707
+ .requiredOption("--agent <id>", "Requesting agent identifier")
4708
+ .option("--tier <t>", "Explicit risk tier (safe/read/write/network/destructive). Default: auto-classify from tool name.")
4709
+ .option("--env-confidence <n>", "Trust signal: NEMESIS env-scan confidence 0..1", (v) => Number(v))
4710
+ .option("--identity-verdict <v>", "Trust signal: NEMESIS verify_identity (CONFIRMED|DISPUTED|IMPOSSIBLE|INCONCLUSIVE)")
4711
+ .option("--hm-weight <n>", "Trust signal: HONEST_MIRROR weight 0..1", (v) => Number(v))
4712
+ .option("--stealth <n>", "Trust signal: STEALTH score 0..1 (inverted)", (v) => Number(v))
4713
+ .option("--history <n>", "Trust signal: historical approval rate 0..1", (v) => Number(v))
4714
+ .option("--scope <list>", "Comma-separated scope sub-restrictions", (v) => v.split(",").map((s) => s.trim()).filter(Boolean))
4715
+ .option("--parent <token>", "Parent passport token (for delegation)")
4716
+ .action(async (opts) => {
4717
+ try {
4718
+ const core = await import("@mneme-ai/core");
4719
+ const trustInputs = {
4720
+ envScanConfidence: opts.envConfidence,
4721
+ identityVerdict: opts.identityVerdict,
4722
+ honestMirrorWeight: opts.hmWeight,
4723
+ stealthScore: opts.stealth,
4724
+ historicalApprovalRate: opts.history,
4725
+ };
4726
+ const r = core.passport.issuePassport({
4727
+ tool: opts.tool,
4728
+ agent: opts.agent,
4729
+ tier: opts.tier,
4730
+ trustInputs,
4731
+ scope: opts.scope,
4732
+ parent: opts.parent,
4733
+ cwd: process.cwd(),
4734
+ });
4735
+ process.stdout.write(JSON.stringify(r, null, 2) + "\n");
4736
+ if (!r.ok)
4737
+ process.exitCode = 1;
4738
+ }
4739
+ catch (e) {
4740
+ process.stdout.write(JSON.stringify({ ok: false, error: e.message }) + "\n");
4741
+ process.exitCode = 1;
4742
+ }
4743
+ });
4744
+ passportParent.command("verify")
4745
+ .description("Verify a passport token (HMAC + TTL + revocation + optional expected tool/scope).")
4746
+ .requiredOption("--token <t>", "Passport token to verify")
4747
+ .option("--tool <name>", "Optional expected tool")
4748
+ .option("--scope <list>", "Optional expected scope (comma-separated; all must be present)", (v) => v.split(",").map((s) => s.trim()).filter(Boolean))
4749
+ .action(async (opts) => {
4750
+ try {
4751
+ const core = await import("@mneme-ai/core");
4752
+ const r = core.passport.verifyPassport({ token: opts.token, expectedTool: opts.tool, expectedScope: opts.scope, cwd: process.cwd() });
4753
+ process.stdout.write(JSON.stringify(r, null, 2) + "\n");
4754
+ if (!r.valid)
4755
+ process.exitCode = 1;
4756
+ }
4757
+ catch (e) {
4758
+ process.stdout.write(JSON.stringify({ ok: false, error: e.message }) + "\n");
4759
+ process.exitCode = 1;
4760
+ }
4761
+ });
4762
+ passportParent.command("revoke")
4763
+ .description("Revoke a passport. Cascade revoke = also revokes every delegated descendant (default).")
4764
+ .option("--token <t>", "Passport token")
4765
+ .option("--jti <id>", "Direct jti (when you don't have the token)")
4766
+ .option("--no-cascade", "Disable cascade revoke of descendants")
4767
+ .action(async (opts) => {
4768
+ try {
4769
+ const core = await import("@mneme-ai/core");
4770
+ const r = core.passport.revokePassport({ token: opts.token, jti: opts.jti, cascade: opts.cascade !== false, cwd: process.cwd() });
4771
+ process.stdout.write(JSON.stringify(r, null, 2) + "\n");
4772
+ if (!r.ok)
4773
+ process.exitCode = 1;
4774
+ }
4775
+ catch (e) {
4776
+ process.stdout.write(JSON.stringify({ ok: false, error: e.message }) + "\n");
4777
+ process.exitCode = 1;
4778
+ }
4779
+ });
4780
+ passportParent.command("audit")
4781
+ .description("Verify the HMAC-chained passport ledger + show last N entries.")
4782
+ .option("--limit <n>", "How many entries to show", (v) => Number(v), 20)
4783
+ .action(async (opts) => {
4784
+ try {
4785
+ const core = await import("@mneme-ai/core");
4786
+ const led = core.passport.verifyLedgerChain(process.cwd());
4787
+ const rows = core.passport.readLedger(process.cwd());
4788
+ process.stdout.write(JSON.stringify({ ok: led.ok, totalRows: led.rows, brokenAt: led.brokenAt, recent: rows.slice(-(opts.limit ?? 20)) }, null, 2) + "\n");
4789
+ if (!led.ok)
4790
+ process.exitCode = 1;
4791
+ }
4792
+ catch (e) {
4793
+ process.stdout.write(JSON.stringify({ ok: false, error: e.message }) + "\n");
4794
+ process.exitCode = 1;
4795
+ }
4796
+ });
4797
+ passportParent.command("policy")
4798
+ .description("Show the current default policy (tier → minTrust + ttlMs).")
4799
+ .action(async () => {
4800
+ try {
4801
+ const core = await import("@mneme-ai/core");
4802
+ process.stdout.write(JSON.stringify({ policy: core.passport.DEFAULT_POLICY }, null, 2) + "\n");
4803
+ }
4804
+ catch (e) {
4805
+ process.stdout.write(JSON.stringify({ ok: false, error: e.message }) + "\n");
4806
+ process.exitCode = 1;
4807
+ }
4808
+ });
4809
+ // v2.60.0 — SKELETON KEY: MCP server security auditor.
4810
+ // First MCP security audit tool in the ecosystem. Discovers MCP
4811
+ // servers in Claude Desktop / Cursor / Continue / Cline configs +
4812
+ // risk-scores them + computes transitive bypass graph + pins HMAC
4813
+ // snapshot for drift detection.
4814
+ const skeletonKeyParent = program
4815
+ .command("skeleton_key")
4816
+ .description("v2.60 — MCP server security auditor. Default action = audit.")
4817
+ .option("--budget <n>", "risk budget cap (default 5.0)", (v) => Number(v), 5.0)
4818
+ .option("--empirical", "spawn each MCP server + read tools/list (slow, accurate)", false)
4819
+ .action(async (opts) => {
4820
+ try {
4821
+ const core = await import("@mneme-ai/core");
4822
+ const r = await core.skeletonKey.auditMcpConfigs({ budgetCap: opts.budget, empiricalProbe: opts.empirical });
4823
+ process.stdout.write(JSON.stringify(r, null, 2) + "\n");
4824
+ if (!r.ok)
4825
+ process.exitCode = 1;
4826
+ }
4827
+ catch (e) {
4828
+ process.stdout.write(JSON.stringify({ ok: false, error: e.message }) + "\n");
4829
+ process.exitCode = 1;
4830
+ }
4831
+ });
4832
+ skeletonKeyParent.command("audit")
4833
+ .description("Full MCP audit: discover servers, score risk, compute bypass graph, render banner.")
4834
+ .option("--budget <n>", "risk budget cap (default 5.0)", (v) => Number(v), 5.0)
4835
+ .option("--empirical", "spawn each MCP server + read tools/list (slow, accurate)", false)
4836
+ .option("--banner", "render ASCII banner instead of JSON", false)
4837
+ .action(async (opts) => {
4838
+ try {
4839
+ const core = await import("@mneme-ai/core");
4840
+ const r = await core.skeletonKey.auditMcpConfigs({ budgetCap: opts.budget, empiricalProbe: opts.empirical });
4841
+ if (opts.banner)
4842
+ process.stdout.write(core.skeletonKey.renderAuditBanner(r) + "\n");
4843
+ else
4844
+ process.stdout.write(JSON.stringify(r, null, 2) + "\n");
4845
+ if (!r.ok)
4846
+ process.exitCode = 1;
4847
+ }
4848
+ catch (e) {
4849
+ process.stdout.write(JSON.stringify({ ok: false, error: e.message }) + "\n");
4850
+ process.exitCode = 1;
4851
+ }
4852
+ });
4853
+ skeletonKeyParent.command("recommend")
4854
+ .description("Concrete config changes to reduce risk surface.")
4855
+ .option("--budget <n>", "risk budget cap (default 5.0)", (v) => Number(v), 5.0)
4856
+ .action(async (opts) => {
4857
+ try {
4858
+ const core = await import("@mneme-ai/core");
4859
+ const a = await core.skeletonKey.auditMcpConfigs({ budgetCap: opts.budget });
4860
+ const recs = core.skeletonKey.buildRecommendations(a);
4861
+ process.stdout.write(JSON.stringify({ ok: recs.length === 0, count: recs.length, recommendations: recs }, null, 2) + "\n");
4862
+ }
4863
+ catch (e) {
4864
+ process.stdout.write(JSON.stringify({ ok: false, error: e.message }) + "\n");
4865
+ process.exitCode = 1;
4866
+ }
4867
+ });
4868
+ skeletonKeyParent.command("pin")
4869
+ .description("Snapshot the current MCP config (HMAC-signed). Future drift checks compare against this.")
4870
+ .action(async () => {
4871
+ try {
4872
+ const core = await import("@mneme-ai/core");
4873
+ const snap = core.skeletonKey.pinConfigSnapshot(process.cwd());
4874
+ process.stdout.write(JSON.stringify({ ok: true, snapshot: snap }, null, 2) + "\n");
4875
+ }
4876
+ catch (e) {
4877
+ process.stdout.write(JSON.stringify({ ok: false, error: e.message }) + "\n");
4878
+ process.exitCode = 1;
4879
+ }
4880
+ });
4881
+ skeletonKeyParent.command("drift")
4882
+ .description("Compare current MCP config vs pinned snapshot. Detects silent tampering.")
4883
+ .action(async () => {
4884
+ try {
4885
+ const core = await import("@mneme-ai/core");
4886
+ const r = core.skeletonKey.detectConfigDrift(process.cwd());
4887
+ process.stdout.write(JSON.stringify(r, null, 2) + "\n");
4888
+ if (!r.ok)
4889
+ process.exitCode = 1;
4890
+ }
4891
+ catch (e) {
4892
+ process.stdout.write(JSON.stringify({ ok: false, error: e.message }) + "\n");
4893
+ process.exitCode = 1;
4894
+ }
4895
+ });
4896
+ skeletonKeyParent.command("probe")
4897
+ .description("Empirically spawn ONE MCP server + read its tools/list. Reveals real capabilities (not name-heuristic).")
4898
+ .requiredOption("--server <name>", "MCP server name to probe (must match a discovered config entry)")
4899
+ .action(async (opts) => {
4900
+ try {
4901
+ const core = await import("@mneme-ai/core");
4902
+ const all = core.skeletonKey.discoverServers(core.skeletonKey.defaultConfigPaths());
4903
+ const found = all.find((s) => s.name === opts.server);
4904
+ if (!found || !found.command) {
4905
+ process.stdout.write(JSON.stringify({ ok: false, hint: `server '${opts.server}' not found in any discovered config (or has no command)` }) + "\n");
4906
+ process.exitCode = 1;
4907
+ return;
4908
+ }
4909
+ const r = await core.skeletonKey.probeServer({ name: found.name, command: found.command, args: found.args, env: found.env });
4910
+ process.stdout.write(JSON.stringify(r, null, 2) + "\n");
4911
+ }
4912
+ catch (e) {
4913
+ process.stdout.write(JSON.stringify({ ok: false, error: e.message }) + "\n");
4914
+ process.exitCode = 1;
4915
+ }
4916
+ });
4685
4917
  // v2.59.0 — SDK SURFACE AUDITOR: gate-self-verification.
4686
4918
  // Empirically imports @mneme-ai/sdk + checks the external public
4687
4919
  // surface matches WIRING DOCTOR's claims. Closes the v2.58 blind-spot