@fidacy/mcp 0.1.17 → 0.1.18

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/README.md CHANGED
@@ -73,6 +73,9 @@ Mental model: `assess_action` -> **engine** (signed verdict);
73
73
  | `request_payment` | core | Authorize a payment action. ALLOW + grant, or DENY + rule. |
74
74
  | `verify_mandate` | core | Read the mandate envelope + Fidacy public key. |
75
75
  | `get_audit_proof` | core | Hash-chained proof for a decision id. |
76
+ | `anchor_artifact` | engine | Bitcoin-anchored integrity proof for any file (contract, invoice, prescription, claim, image, audio, video, conversation). Hashed locally; only the SHA-256 leaves. Returns a signed receipt. |
77
+ | `check_artifact` | engine | Check whether a file (or hash) was anchored, and its Bitcoin checkpoint state. A mismatch is the tampering signal. |
78
+ | `upgrade` | — | Start upgrading this local install to a real Fidacy account; preserves and migrates anonymous usage. |
76
79
 
77
80
  ### `assess_action`
78
81
 
@@ -145,6 +148,21 @@ repository stays private. Set `FIDACY_MODE=http` and implement three endpoints:
145
148
 
146
149
  No change to the MCP layer is needed.
147
150
 
151
+ ## Telemetry
152
+
153
+ The install emits **anonymous, opt-out** usage telemetry so we can measure
154
+ traction (installs, active agents, decision counts, deny-rate). It is
155
+ best-effort and never on the decision critical path, so it can never block or
156
+ slow a verdict.
157
+
158
+ - It carries an anonymous install id and counters only. It **never** includes
159
+ payment content — no payee, amount, invoice, or mandate ever leaves your
160
+ machine. Payload-carrying types are rejected by a strict schema.
161
+ - Turn it off completely with `FIDACY_DISABLE_TELEMETRY=1` (or `true`).
162
+
163
+ Consistent with the product: you don't have to trust us, you can verify. The
164
+ firewall runs fully with telemetry disabled.
165
+
148
166
  ## Dev
149
167
 
150
168
  ```bash
package/dist/assess.js CHANGED
@@ -88,7 +88,7 @@ async function postOnce(fetchImpl, url, headers, payload, timeoutMs) {
88
88
  body: payload,
89
89
  signal: controller.signal
90
90
  });
91
- } catch (err) {
91
+ } catch {
92
92
  const aborted = controller.signal.aborted;
93
93
  throw new AssessError({ type: aborted ? "timeout" : "network_error", status: 0 });
94
94
  } finally {
package/dist/core.js CHANGED
@@ -347,6 +347,9 @@ var FileAuditStore = class {
347
347
  const digest = sha256(stableStringify({ decisionId: decision.decisionId, status: decision.status, request: decision.request, violatedRule: decision.violatedRule ?? null }));
348
348
  const hash = sha256(`${prevHash}|${digest}|${seq}|${ts}`);
349
349
  const record2 = { seq, decisionId: decision.decisionId, status: decision.status, subject: decision.subject, digest, prevHash, hash, ts };
350
+ if (typeof decision.request?.purpose === "string" && decision.request.purpose.trim()) {
351
+ record2.purpose = decision.request.purpose.slice(0, 500);
352
+ }
350
353
  if (decision.status === "ALLOW") {
351
354
  const req = decision.request;
352
355
  if (typeof req?.amount === "number" && Number.isFinite(req.amount))
@@ -439,7 +442,7 @@ function resolveMandateRules(cfg) {
439
442
  }
440
443
 
441
444
  // src/telemetry.ts
442
- var CLIENT_VERSION = true ? "0.1.17" : "dev";
445
+ var CLIENT_VERSION = true ? "0.1.18" : "dev";
443
446
  var currentShell = "mcp";
444
447
  function telemetryEnabled() {
445
448
  const v = (process.env.FIDACY_DISABLE_TELEMETRY ?? "").trim().toLowerCase();
package/dist/index.js CHANGED
@@ -354,6 +354,9 @@ var FileAuditStore = class {
354
354
  const digest = sha256(stableStringify({ decisionId: decision.decisionId, status: decision.status, request: decision.request, violatedRule: decision.violatedRule ?? null }));
355
355
  const hash = sha256(`${prevHash}|${digest}|${seq}|${ts}`);
356
356
  const record2 = { seq, decisionId: decision.decisionId, status: decision.status, subject: decision.subject, digest, prevHash, hash, ts };
357
+ if (typeof decision.request?.purpose === "string" && decision.request.purpose.trim()) {
358
+ record2.purpose = decision.request.purpose.slice(0, 500);
359
+ }
357
360
  if (decision.status === "ALLOW") {
358
361
  const req = decision.request;
359
362
  if (typeof req?.amount === "number" && Number.isFinite(req.amount))
@@ -468,7 +471,7 @@ function resolveMandateRules(cfg) {
468
471
  }
469
472
 
470
473
  // src/telemetry.ts
471
- var CLIENT_VERSION = true ? "0.1.17" : "dev";
474
+ var CLIENT_VERSION = true ? "0.1.18" : "dev";
472
475
  var currentShell = "mcp";
473
476
  function telemetryEnabled() {
474
477
  const v = (process.env.FIDACY_DISABLE_TELEMETRY ?? "").trim().toLowerCase();
@@ -691,7 +694,7 @@ async function postOnce(fetchImpl, url, headers, payload, timeoutMs) {
691
694
  body: payload,
692
695
  signal: controller.signal
693
696
  });
694
- } catch (err) {
697
+ } catch {
695
698
  const aborted = controller.signal.aborted;
696
699
  throw new AssessError({ type: aborted ? "timeout" : "network_error", status: 0 });
697
700
  } finally {
@@ -783,7 +786,7 @@ async function findArtifacts(sha2562, cfg) {
783
786
  }
784
787
 
785
788
  // src/provision.ts
786
- var CLIENT_VERSION2 = true ? "0.1.17" : "dev";
789
+ var CLIENT_VERSION2 = true ? "0.1.18" : "dev";
787
790
  function provisionEnabled() {
788
791
  const v = (process.env.FIDACY_DISABLE_PROVISION ?? "").trim().toLowerCase();
789
792
  return !(v === "1" || v === "true" || v === "yes");
@@ -883,7 +886,7 @@ function weekOneBootNudge(upgradeToolName) {
883
886
  var state = ensureState();
884
887
  var core = makeCore();
885
888
  var subject = process.env.FIDACY_SUBJECT ?? "agent:demo";
886
- var SERVER_VERSION = true ? "0.1.17" : "dev";
889
+ var SERVER_VERSION = true ? "0.1.18" : "dev";
887
890
  var server = new McpServer({ name: "fidacy", version: SERVER_VERSION });
888
891
  server.registerTool(
889
892
  "request_payment",
@@ -894,7 +897,9 @@ server.registerTool(
894
897
  payee: z.string().describe("Payee identifier"),
895
898
  amount: z.number().positive().describe("Amount in the mandate currency"),
896
899
  currency: z.string().length(3).describe("ISO 4217 currency code"),
897
- purpose: z.string().describe("Human-readable purpose"),
900
+ purpose: z.string().describe(
901
+ "Your stated reason for this payment, in your own words. It is persisted readably on the tamper-evident audit record (ALLOW and DENY alike) and becomes part of the after-the-fact proof, so write the real reason."
902
+ ),
898
903
  category: z.string().describe("Purpose category (must be allowed by the mandate)"),
899
904
  idempotencyKey: z.string().describe("Caller-supplied idempotency key"),
900
905
  invoiceRef: z.string().describe(
package/dist/lib.js CHANGED
@@ -385,6 +385,9 @@ var FileAuditStore = class {
385
385
  const digest = sha256(stableStringify({ decisionId: decision.decisionId, status: decision.status, request: decision.request, violatedRule: decision.violatedRule ?? null }));
386
386
  const hash = sha256(`${prevHash}|${digest}|${seq}|${ts}`);
387
387
  const record2 = { seq, decisionId: decision.decisionId, status: decision.status, subject: decision.subject, digest, prevHash, hash, ts };
388
+ if (typeof decision.request?.purpose === "string" && decision.request.purpose.trim()) {
389
+ record2.purpose = decision.request.purpose.slice(0, 500);
390
+ }
388
391
  if (decision.status === "ALLOW") {
389
392
  const req = decision.request;
390
393
  if (typeof req?.amount === "number" && Number.isFinite(req.amount))
@@ -457,6 +460,10 @@ var GrantEnforcingExecutor = class {
457
460
  this.rail = rail;
458
461
  this.pub = createPublicKey(publicKeyPem2);
459
462
  this.redeem = opts?.redeem;
463
+ const isProd = typeof process !== "undefined" && process.env?.NODE_ENV === "production";
464
+ if (isProd && !this.redeem && !opts?.allowUnsafeInMemorySingleUse) {
465
+ throw new Error("GrantEnforcingExecutor in production requires a durable `redeem` (single-use across instances). Wire httpRedeem(coreUrl, apiKey), or pass allowUnsafeInMemorySingleUse:true only for a true single-process deployment.");
466
+ }
460
467
  }
461
468
  async execute(req, grant) {
462
469
  if (!grant)
@@ -587,7 +594,7 @@ function resolveMandateRules(cfg) {
587
594
  }
588
595
 
589
596
  // src/telemetry.ts
590
- var CLIENT_VERSION = true ? "0.1.17" : "dev";
597
+ var CLIENT_VERSION = true ? "0.1.18" : "dev";
591
598
  var currentShell = "mcp";
592
599
  function setTelemetryShell(shell) {
593
600
  currentShell = shell;
@@ -736,7 +743,7 @@ function requestUpgrade() {
736
743
  }
737
744
 
738
745
  // src/provision.ts
739
- var CLIENT_VERSION2 = true ? "0.1.17" : "dev";
746
+ var CLIENT_VERSION2 = true ? "0.1.18" : "dev";
740
747
  function provisionEnabled() {
741
748
  const v = (process.env.FIDACY_DISABLE_PROVISION ?? "").trim().toLowerCase();
742
749
  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.17",
3
+ "version": "0.1.18",
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",