@fidacy/mcp 0.1.15 → 0.1.17

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 CHANGED
@@ -3,6 +3,26 @@
3
3
  All notable changes to `@fidacy/mcp` are documented here. This project follows
4
4
  semantic versioning.
5
5
 
6
+ ## 0.1.17 — 2026-07-03
7
+
8
+ - Config HOT-RELOAD: editing `~/.fidacy/config.json` (payees, caps) takes effect
9
+ on the next call, no host restart. Spend and invoice-dedup state is rebuilt
10
+ from the audit log on reload, so a reload never weakens the firewall.
11
+ - The `payee_not_in_allowlist` DENY now tells the agent exactly how to allow a
12
+ trusted payee (friction fix from a clean-room install test).
13
+
14
+ ## 0.1.16 — 2026-07-03
15
+
16
+ - `anchor_artifact`/`check_artifact`: new kind `conversation` — anchor chatbot
17
+ session digests produced by `@fidacy/session` (conversation receipts).
18
+
19
+ ## 0.1.15 — 2026-07-03
20
+
21
+ - New tools: `anchor_artifact` and `check_artifact` — Bitcoin-anchored integrity
22
+ proof for any artifact (contracts, invoices, prescriptions, claims, images,
23
+ audio, video). The file is hashed locally and never uploaded; only the SHA-256
24
+ joins the tamper-evident audit chain. Signed JWS receipt verifies offline.
25
+
6
26
  ## 0.1.4
7
27
 
8
28
  ### Fixed
package/dist/core.js CHANGED
@@ -1,3 +1,6 @@
1
+ // src/core.ts
2
+ import { statSync } from "node:fs";
3
+
1
4
  // ../firewall/dist/util.js
2
5
  function stableStringify(obj) {
3
6
  if (obj === null || typeof obj !== "object")
@@ -189,6 +192,19 @@ var DevFidacyCore = class {
189
192
  this.spent += r.amount;
190
193
  }
191
194
  }
195
+ /**
196
+ * Swap the active mandate (shell config hot-reload: edit config.json, the next
197
+ * call picks it up, no host restart). Decision state is REBUILT from the audit
198
+ * log under the new window/currency, so a reload can never reset the BEC
199
+ * invoice dedup or undercount spend: a paid invoice stays paid, spent is
200
+ * recomputed.
201
+ */
202
+ setMandate(m) {
203
+ this.mandate = m;
204
+ this.spent = 0;
205
+ this.claimedInvoices.clear();
206
+ this.rehydrate();
207
+ }
192
208
  async getMandate() {
193
209
  return this.mandate;
194
210
  }
@@ -423,7 +439,7 @@ function resolveMandateRules(cfg) {
423
439
  }
424
440
 
425
441
  // src/telemetry.ts
426
- var CLIENT_VERSION = true ? "0.1.15" : "dev";
442
+ var CLIENT_VERSION = true ? "0.1.17" : "dev";
427
443
  var currentShell = "mcp";
428
444
  function telemetryEnabled() {
429
445
  const v = (process.env.FIDACY_DISABLE_TELEMETRY ?? "").trim().toLowerCase();
@@ -525,11 +541,32 @@ function makeCore() {
525
541
  if (!url || !key) throw new Error("FIDACY_MODE=http requires FIDACY_API_URL and FIDACY_API_KEY");
526
542
  return new HttpFidacyCore(url, key, process.env.FIDACY_PUBLIC_KEY_PEM ?? "");
527
543
  }
528
- return new DevFidacyCore({
544
+ const dev = new DevFidacyCore({
529
545
  mandate: buildMandate(),
530
546
  auditLogPath: auditLogPath(),
531
547
  onDecision: (d) => recordDecision(d.status, d.violatedRule)
532
548
  });
549
+ const mtimeOf = () => statSync(configPath(), { throwIfNoEntry: false })?.mtimeMs ?? 0;
550
+ let seenMtime = mtimeOf();
551
+ const maybeReload = () => {
552
+ const m = mtimeOf();
553
+ if (m !== seenMtime) {
554
+ seenMtime = m;
555
+ dev.setMandate(buildMandate());
556
+ }
557
+ };
558
+ return {
559
+ getMandate: () => {
560
+ maybeReload();
561
+ return dev.getMandate();
562
+ },
563
+ decide: (req, subject) => {
564
+ maybeReload();
565
+ return dev.decide(req, subject);
566
+ },
567
+ getProof: (decisionId) => dev.getProof(decisionId),
568
+ publicKey: () => dev.publicKey()
569
+ };
533
570
  }
534
571
  export {
535
572
  makeCore
package/dist/index.js CHANGED
@@ -5,6 +5,9 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
5
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
6
  import { z } from "zod";
7
7
 
8
+ // src/core.ts
9
+ import { statSync } from "node:fs";
10
+
8
11
  // ../firewall/dist/util.js
9
12
  function stableStringify(obj) {
10
13
  if (obj === null || typeof obj !== "object")
@@ -196,6 +199,19 @@ var DevFidacyCore = class {
196
199
  this.spent += r.amount;
197
200
  }
198
201
  }
202
+ /**
203
+ * Swap the active mandate (shell config hot-reload: edit config.json, the next
204
+ * call picks it up, no host restart). Decision state is REBUILT from the audit
205
+ * log under the new window/currency, so a reload can never reset the BEC
206
+ * invoice dedup or undercount spend: a paid invoice stays paid, spent is
207
+ * recomputed.
208
+ */
209
+ setMandate(m) {
210
+ this.mandate = m;
211
+ this.spent = 0;
212
+ this.claimedInvoices.clear();
213
+ this.rehydrate();
214
+ }
199
215
  async getMandate() {
200
216
  return this.mandate;
201
217
  }
@@ -452,7 +468,7 @@ function resolveMandateRules(cfg) {
452
468
  }
453
469
 
454
470
  // src/telemetry.ts
455
- var CLIENT_VERSION = true ? "0.1.15" : "dev";
471
+ var CLIENT_VERSION = true ? "0.1.17" : "dev";
456
472
  var currentShell = "mcp";
457
473
  function telemetryEnabled() {
458
474
  const v = (process.env.FIDACY_DISABLE_TELEMETRY ?? "").trim().toLowerCase();
@@ -557,11 +573,32 @@ function makeCore() {
557
573
  if (!url || !key) throw new Error("FIDACY_MODE=http requires FIDACY_API_URL and FIDACY_API_KEY");
558
574
  return new HttpFidacyCore(url, key, process.env.FIDACY_PUBLIC_KEY_PEM ?? "");
559
575
  }
560
- return new DevFidacyCore({
576
+ const dev = new DevFidacyCore({
561
577
  mandate: buildMandate(),
562
578
  auditLogPath: auditLogPath(),
563
579
  onDecision: (d) => recordDecision(d.status, d.violatedRule)
564
580
  });
581
+ const mtimeOf = () => statSync(configPath(), { throwIfNoEntry: false })?.mtimeMs ?? 0;
582
+ let seenMtime = mtimeOf();
583
+ const maybeReload = () => {
584
+ const m = mtimeOf();
585
+ if (m !== seenMtime) {
586
+ seenMtime = m;
587
+ dev.setMandate(buildMandate());
588
+ }
589
+ };
590
+ return {
591
+ getMandate: () => {
592
+ maybeReload();
593
+ return dev.getMandate();
594
+ },
595
+ decide: (req, subject2) => {
596
+ maybeReload();
597
+ return dev.decide(req, subject2);
598
+ },
599
+ getProof: (decisionId) => dev.getProof(decisionId),
600
+ publicKey: () => dev.publicKey()
601
+ };
565
602
  }
566
603
 
567
604
  // src/assess.ts
@@ -693,6 +730,7 @@ var ARTIFACT_KINDS = [
693
730
  "image",
694
731
  "audio",
695
732
  "video",
733
+ "conversation",
696
734
  "custom"
697
735
  ];
698
736
  async function hashFile(path) {
@@ -745,7 +783,7 @@ async function findArtifacts(sha2562, cfg) {
745
783
  }
746
784
 
747
785
  // src/provision.ts
748
- var CLIENT_VERSION2 = true ? "0.1.15" : "dev";
786
+ var CLIENT_VERSION2 = true ? "0.1.17" : "dev";
749
787
  function provisionEnabled() {
750
788
  const v = (process.env.FIDACY_DISABLE_PROVISION ?? "").trim().toLowerCase();
751
789
  return !(v === "1" || v === "true" || v === "yes");
@@ -845,7 +883,7 @@ function weekOneBootNudge(upgradeToolName) {
845
883
  var state = ensureState();
846
884
  var core = makeCore();
847
885
  var subject = process.env.FIDACY_SUBJECT ?? "agent:demo";
848
- var SERVER_VERSION = true ? "0.1.15" : "dev";
886
+ var SERVER_VERSION = true ? "0.1.17" : "dev";
849
887
  var server = new McpServer({ name: "fidacy", version: SERVER_VERSION });
850
888
  server.registerTool(
851
889
  "request_payment",
@@ -876,7 +914,7 @@ server.registerTool(
876
914
  const d = await core.decide(req, subject);
877
915
  const out = { status: d.status, decisionId: d.decisionId, grant: d.grant, violatedRule: d.violatedRule };
878
916
  const base = d.status === "ALLOW" ? `ALLOW (decision ${d.decisionId})${req.invoiceRef ? ` for invoice ${req.invoiceRef}` : ""}. To settle, call execute_payment with the SAME payee, amount, currency, and idempotencyKey, and set "grant" to EXACTLY this signed value:
879
- ${d.grant}` : `DENY (decision ${d.decisionId}). Rule violated: ${d.violatedRule}. No grant issued, this payment cannot proceed. The denial itself is recorded in the tamper-evident, hash-chained audit: call get_audit_proof with decisionId ${d.decisionId} for the proof of what was blocked.`;
917
+ ${d.grant}` : `DENY (decision ${d.decisionId}). Rule violated: ${d.violatedRule}. No grant issued, this payment cannot proceed. The denial itself is recorded in the tamper-evident, hash-chained audit: call get_audit_proof with decisionId ${d.decisionId} for the proof of what was blocked.${d.violatedRule?.startsWith("payee_not_in_allowlist") ? ` If the user trusts this payee, add "${req.payee}" to mandate.payees in ~/.fidacy/config.json and retry: the firewall picks the change up on the next call, no restart needed.` : ""}`;
880
918
  const nudge = decisionNudge(d.status, d.violatedRule, "upgrade");
881
919
  const human = nudge ? `${base} ${nudge}` : base;
882
920
  return { content: [{ type: "text", text: human }], structuredContent: out };
package/dist/lib.js CHANGED
@@ -230,6 +230,19 @@ var DevFidacyCore = class {
230
230
  this.spent += r.amount;
231
231
  }
232
232
  }
233
+ /**
234
+ * Swap the active mandate (shell config hot-reload: edit config.json, the next
235
+ * call picks it up, no host restart). Decision state is REBUILT from the audit
236
+ * log under the new window/currency, so a reload can never reset the BEC
237
+ * invoice dedup or undercount spend: a paid invoice stays paid, spent is
238
+ * recomputed.
239
+ */
240
+ setMandate(m) {
241
+ this.mandate = m;
242
+ this.spent = 0;
243
+ this.claimedInvoices.clear();
244
+ this.rehydrate();
245
+ }
233
246
  async getMandate() {
234
247
  return this.mandate;
235
248
  }
@@ -490,6 +503,9 @@ var GrantEnforcingExecutor = class {
490
503
  }
491
504
  };
492
505
 
506
+ // src/core.ts
507
+ import { statSync } from "node:fs";
508
+
493
509
  // src/config.ts
494
510
  import { randomUUID as randomUUID3 } from "node:crypto";
495
511
  import { homedir } from "node:os";
@@ -571,7 +587,7 @@ function resolveMandateRules(cfg) {
571
587
  }
572
588
 
573
589
  // src/telemetry.ts
574
- var CLIENT_VERSION = true ? "0.1.15" : "dev";
590
+ var CLIENT_VERSION = true ? "0.1.17" : "dev";
575
591
  var currentShell = "mcp";
576
592
  function setTelemetryShell(shell) {
577
593
  currentShell = shell;
@@ -679,11 +695,32 @@ function makeCore() {
679
695
  if (!url || !key) throw new Error("FIDACY_MODE=http requires FIDACY_API_URL and FIDACY_API_KEY");
680
696
  return new HttpFidacyCore(url, key, process.env.FIDACY_PUBLIC_KEY_PEM ?? "");
681
697
  }
682
- return new DevFidacyCore({
698
+ const dev = new DevFidacyCore({
683
699
  mandate: buildMandate(),
684
700
  auditLogPath: auditLogPath(),
685
701
  onDecision: (d) => recordDecision(d.status, d.violatedRule)
686
702
  });
703
+ const mtimeOf = () => statSync(configPath(), { throwIfNoEntry: false })?.mtimeMs ?? 0;
704
+ let seenMtime = mtimeOf();
705
+ const maybeReload = () => {
706
+ const m = mtimeOf();
707
+ if (m !== seenMtime) {
708
+ seenMtime = m;
709
+ dev.setMandate(buildMandate());
710
+ }
711
+ };
712
+ return {
713
+ getMandate: () => {
714
+ maybeReload();
715
+ return dev.getMandate();
716
+ },
717
+ decide: (req, subject) => {
718
+ maybeReload();
719
+ return dev.decide(req, subject);
720
+ },
721
+ getProof: (decisionId) => dev.getProof(decisionId),
722
+ publicKey: () => dev.publicKey()
723
+ };
687
724
  }
688
725
 
689
726
  // src/upgrade.ts
@@ -699,7 +736,7 @@ function requestUpgrade() {
699
736
  }
700
737
 
701
738
  // src/provision.ts
702
- var CLIENT_VERSION2 = true ? "0.1.15" : "dev";
739
+ var CLIENT_VERSION2 = true ? "0.1.17" : "dev";
703
740
  function provisionEnabled() {
704
741
  const v = (process.env.FIDACY_DISABLE_PROVISION ?? "").trim().toLowerCase();
705
742
  return !(v === "1" || v === "true" || v === "yes");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fidacy/mcp",
3
- "version": "0.1.15",
3
+ "version": "0.1.17",
4
4
  "description": "Fidacy action firewall for AI agents. Mandate-gated payment authorization as an MCP server.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://fidacy.com",