@fidacy/openclaw-plugin 0.8.0 → 0.10.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 CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.10.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 6db2c6f: Require an account-owned API key before a connector can evaluate or execute a consequential action. Anonymous installation and local trial activity no longer create a protected-agent claim. Operators activate a workspace in the Fidacy dashboard, configure `FIDACY_ENGINE_API_KEY`, and then receive authenticated live protection signals.
8
+
9
+ ## 0.9.0
10
+
11
+ ### Minor Changes
12
+
13
+ - Fidacy can now ask the 452 people who already installed it whether to turn on full protection, without them ever opening a terminal.
14
+
15
+ The problem was that **2 of 407** MCP installs had ever run `install-hooks`. Without that hook an MCP server only sees calls to its own tools, so deleting a file, reading a secret or reaching a CRM goes nowhere near us. For 99% of the base the product is a payment gate that almost never fires, and there was no way to ask those people anything: they do not open terminals, do not read changelogs, and the guided setup only helps whoever installs next.
16
+
17
+ Two things solve it together. The installed base is **not** stuck in the past — hosts launch the server as `npx -y @fidacy/mcp` with no version pin, so every agent restart already pulls the newest build. And the protocol has elicitation: during a tool call, a server may ask the user for input _through the host_, and they answer in a dialog inside the tool they already use.
18
+
19
+ So on the next payment decision, the operator is asked once, in their own UI, and one click wires it in — existing hooks merged around, backup kept, every path printed.
20
+
21
+ It asks only while processing a call, only if the client declares the capability, only once per install ever, and it never blocks or delays a decision. Where elicitation is not supported it degrades to a line in the tool result, which is still better than the silence it replaces.
22
+
3
23
  ## 0.8.0
4
24
 
5
25
  ### Minor Changes
package/README.md CHANGED
@@ -129,17 +129,16 @@ Plugin config (`plugins.entries.fidacy.config`):
129
129
  }
130
130
  ```
131
131
 
132
- `engineApiKey` enables signed verdicts (`assess_action`) and keeps the firewall
133
- active past the anonymous trial. Environment variables (`FIDACY_ENGINE_API_KEY`,
132
+ `engineApiKey` activates signed authority and verdicts (`assess_action`).
133
+ Environment variables (`FIDACY_ENGINE_API_KEY`,
134
134
  `FIDACY_ENGINE_URL`, `FIDACY_SUBJECT`) are the fallback. Decisions run locally,
135
135
  deny-by-default (deny-unknown-payee + per-tx cap); add trusted payees/caps in
136
136
  `~/.fidacy/config.json`.
137
137
 
138
- **No key yet?** The install works anonymously for its first **20 firewall
139
- decisions**, then fails closed (payments denied with `activation_required`) until
140
- the free key is set. Claim an anonymous install's history:
141
- `grep anon_id ~/.fidacy/config.json`, then open
142
- `https://fidacy.com/claim?ref=<that id>`.
138
+ **No key yet? YOUR AI AGENT IS UNPROTECTED.** Consequential actions are refused
139
+ with `activation_required`. Get your free key now at
140
+ https://app.fidacy.com/signup, configure `engineApiKey` or
141
+ `FIDACY_ENGINE_API_KEY`, and connect the executor before retrying.
143
142
 
144
143
  Verify any verdict yourself: https://api.fidacy.com/.well-known/jwks.json
145
144
 
package/dist/index.js CHANGED
@@ -4655,7 +4655,7 @@ var FileAuditStore = class {
4655
4655
 
4656
4656
  // ../firewall/dist/destination.js
4657
4657
  function normalizeKeepingEdges(raw) {
4658
- return String(raw ?? "").normalize("NFKC").toLowerCase().replace(/[​-‍⁠­]/g, "").replace(/(?<=[a-z0-9])[_\-.]+(?=[a-z0-9])/g, ".").replace(/\s+/g, " ");
4658
+ return String(raw ?? "").normalize("NFKC").toLowerCase().replace(/[\u200b-\u200d\u2060\ufeff\u00ad]/g, "").replace(/(?<=[a-z0-9])[_\-.]+(?=[a-z0-9])/g, ".").replace(/\s+/g, " ");
4659
4659
  }
4660
4660
 
4661
4661
  // ../firewall/dist/action-classes.js
@@ -4846,7 +4846,10 @@ function canonical(obj) {
4846
4846
  return "{" + keys.map((k) => `${JSON.stringify(k)}:${JSON.stringify(obj[k])}`).join(",") + "}";
4847
4847
  }
4848
4848
  function chainStep(prevHead, a) {
4849
- return sha2562(`${prevHead}|${sha2562(canonical({ category: a.category, i: a.i, tool: a.tool, ts: a.ts }))}`);
4849
+ const folha = { category: a.category, i: a.i, tool: a.tool, ts: a.ts };
4850
+ if (a.target !== void 0) folha.target = a.target;
4851
+ if (a.content !== void 0) folha.content = a.content;
4852
+ return sha2562(`${prevHead}|${sha2562(canonical(folha))}`);
4850
4853
  }
4851
4854
  function genesisHead() {
4852
4855
  return sha2562(GENESIS);
@@ -4957,6 +4960,10 @@ var EXACT = {
4957
4960
  // Fidacy's own money tools, so the report counts what we ourselves gated.
4958
4961
  request_payment: "money",
4959
4962
  assess_action: "money",
4963
+ // O compromisso decisao-sessao (decision-marker.ts). Sem esta entrada ele
4964
+ // classifica como "other" e a acao mais importante da sessao sai do topo do
4965
+ // relatorio, que ordena dinheiro primeiro.
4966
+ fidacy_decision: "money",
4960
4967
  // The common OpenClaw / agent-host tool vocabulary.
4961
4968
  bash: "shell",
4962
4969
  shell: "shell",
@@ -5027,7 +5034,7 @@ function newLedger(sessionId, now) {
5027
5034
  truncated: false
5028
5035
  };
5029
5036
  }
5030
- function record(ledger, toolName, derivedPaths, failed = false, at = Date.now()) {
5037
+ function record(ledger, toolName, derivedPaths, failed = false, at = Date.now(), target, content) {
5031
5038
  const category = classify(toolName, derivedPaths);
5032
5039
  let tally = ledger.byCategory.get(category);
5033
5040
  if (!tally) {
@@ -5045,7 +5052,9 @@ function record(ledger, toolName, derivedPaths, failed = false, at = Date.now())
5045
5052
  i: ledger.total,
5046
5053
  category,
5047
5054
  tool: toolName,
5048
- ts: new Date(at).toISOString()
5055
+ ts: new Date(at).toISOString(),
5056
+ ...target ? { target } : {},
5057
+ ...content ? { content } : {}
5049
5058
  };
5050
5059
  ledger.head = chainStep(ledger.head, action);
5051
5060
  if (ledger.actions.length < ACTION_LOG_CAP) ledger.actions.push(action);
@@ -5062,12 +5071,13 @@ var LABEL = {
5062
5071
  message: "sent messages",
5063
5072
  other: "other"
5064
5073
  };
5065
- function renderReport(ledger, now, activated, logPath) {
5074
+ function renderReport(ledger, now, activated, logPath, uploaded) {
5066
5075
  if (ledger.total < MIN_ACTIONS_FOR_REPORT) return null;
5067
5076
  const minutes = Math.max(1, Math.round((now - ledger.startedAt) / 6e4));
5077
+ const destino = uploaded === "sent" ? "copied to your Fidacy account" : uploaded === "failed" ? "kept on this machine \xB7 the copy to your account will retry" : "nothing left this machine";
5068
5078
  const lines = [];
5069
5079
  lines.push(
5070
- `[fidacy] SESSION REPORT \xB7 ${ledger.total} agent actions watched over ${minutes} min \xB7 nothing left this machine`
5080
+ `[fidacy] SESSION REPORT \xB7 ${ledger.total} agent actions watched over ${minutes} min \xB7 ${destino}`
5071
5081
  );
5072
5082
  for (const category of ORDER) {
5073
5083
  const tally = ledger.byCategory.get(category);
@@ -5078,6 +5088,17 @@ function renderReport(ledger, now, activated, logPath) {
5078
5088
  if (tally.failures > 0) parts.push(`${tally.failures} failed`);
5079
5089
  lines.push(`[fidacy] ${LABEL[category].padEnd(20)} ${parts.join(" \xB7 ")}`);
5080
5090
  }
5091
+ const comAlvo = ledger.actions.filter((a) => a.target);
5092
+ const destaque = [...comAlvo].sort((x, y) => notavel(y) - notavel(x)).slice(0, MAX_HIGHLIGHTS);
5093
+ if (destaque.length) {
5094
+ lines.push(`[fidacy] what it touched`);
5095
+ for (const a of destaque.sort((x, y) => x.i - y.i)) {
5096
+ const alvo = a.target.length > 96 ? `${a.target.slice(0, 96)}\u2026` : a.target;
5097
+ lines.push(`[fidacy] #${String(a.i).padEnd(3)} ${a.category.padEnd(8)} ${alvo}`);
5098
+ }
5099
+ const resto = comAlvo.length - destaque.length;
5100
+ if (resto > 0) lines.push(`[fidacy] +${resto} more \xB7 full timeline: npx -y @fidacy/mcp log ${ledger.sessionId}`);
5101
+ }
5081
5102
  const money2 = ledger.byCategory.get("money");
5082
5103
  if (!money2) {
5083
5104
  lines.push(`[fidacy] no money-moving action was attempted \xB7 the firewall stayed armed and idle`);
@@ -5089,7 +5110,15 @@ function renderReport(ledger, now, activated, logPath) {
5089
5110
  );
5090
5111
  return lines.join("\n");
5091
5112
  }
5113
+ var CHEIRO_DE_CREDENCIAL = /(^|[/\\.])(\.aws|\.ssh|\.env|\.netrc|\.npmrc|id_rsa|id_ed25519|credentials|secrets?|token|keychain|\.pem|\.p12|kubeconfig)/i;
5114
+ function notavel(a) {
5115
+ if (a.category === "money") return 4;
5116
+ if (a.target && CHEIRO_DE_CREDENCIAL.test(a.target)) return 3;
5117
+ if (a.category === "shell" || a.category === "message") return 2;
5118
+ return 1;
5119
+ }
5092
5120
  var MIN_ACTIONS_FOR_REPORT = 5;
5121
+ var MAX_HIGHLIGHTS = 6;
5093
5122
  function installObserver(api, emit, isActivated, now = Date.now, anchor) {
5094
5123
  if (typeof api?.on !== "function") return;
5095
5124
  const ledgers = /* @__PURE__ */ new Map();
@@ -5178,7 +5207,7 @@ function sessionIdOf(ctx) {
5178
5207
  import { statSync } from "node:fs";
5179
5208
 
5180
5209
  // ../mcp/src/telemetry.ts
5181
- var CLIENT_VERSION = true ? "0.7.0" : "dev";
5210
+ var CLIENT_VERSION = true ? "0.10.0" : "dev";
5182
5211
  function bandOf(amount) {
5183
5212
  if (typeof amount !== "number" || !Number.isFinite(amount) || amount <= 0) return void 0;
5184
5213
  if (amount < 10) return "lt10";
@@ -5198,9 +5227,6 @@ function capRatioOf(amount, perTxMax) {
5198
5227
  return "gt10x";
5199
5228
  }
5200
5229
  var currentShell = "mcp";
5201
- function setTelemetryShell(shell) {
5202
- currentShell = shell;
5203
- }
5204
5230
  function telemetryEnabled() {
5205
5231
  const v = (process.env.FIDACY_DISABLE_TELEMETRY ?? "").trim().toLowerCase();
5206
5232
  return !(v === "1" || v === "true" || v === "yes");
@@ -5257,8 +5283,6 @@ function record2(type, result, band, capRatio, action) {
5257
5283
  if (typeof flushTimer.unref === "function") flushTimer.unref();
5258
5284
  }
5259
5285
  }
5260
- var recordInstall = () => record2("install");
5261
- var recordAgentActive = () => record2("agent_active");
5262
5286
  var recordDecision = (status, violatedRule, amount, perTxMax) => record2("decision", resultOf(status, violatedRule), bandOf(amount), capRatioOf(amount, perTxMax));
5263
5287
  var recordUpgradeIntent = () => record2("upgrade_intent");
5264
5288
  var recordNudge = (key) => record2("nudge", void 0, void 0, void 0, key);
@@ -5392,43 +5416,6 @@ function requestUpgrade() {
5392
5416
  return { url: upgradeUrl(), anonId: anonId2 };
5393
5417
  }
5394
5418
 
5395
- // ../mcp/src/provision.ts
5396
- var CLIENT_VERSION2 = true ? "0.7.0" : "dev";
5397
- function provisionEnabled() {
5398
- const v = (process.env.FIDACY_DISABLE_PROVISION ?? "").trim().toLowerCase();
5399
- return !(v === "1" || v === "true" || v === "yes");
5400
- }
5401
- function endpoint2() {
5402
- const base = (process.env.FIDACY_ENGINE_URL ?? "https://api.fidacy.com").replace(/\/$/, "");
5403
- return `${base}/v1/provision`;
5404
- }
5405
- async function autoProvision() {
5406
- if (!provisionEnabled()) return "skipped";
5407
- const cfg = readConfig();
5408
- if (!cfg) return "skipped";
5409
- if (cfg.api_key) return "skipped";
5410
- try {
5411
- const res = await fetch(endpoint2(), {
5412
- method: "POST",
5413
- headers: { "content-type": "application/json" },
5414
- body: JSON.stringify({ anon_id: cfg.anon_id, client_version: CLIENT_VERSION2 })
5415
- });
5416
- if (res.status === 429) return "rate_limited";
5417
- if (!res.ok) return "failed";
5418
- const data = await res.json();
5419
- if (typeof data.api_key !== "string" || !data.api_key) return "failed";
5420
- const fresh = readConfig() ?? cfg;
5421
- writeConfig({
5422
- ...fresh,
5423
- api_key: data.api_key,
5424
- tier: data.tier === "paid" ? "paid" : "free"
5425
- });
5426
- return "provisioned";
5427
- } catch {
5428
- return "failed";
5429
- }
5430
- }
5431
-
5432
5419
  // ../mcp/src/nudges.ts
5433
5420
  function claimUrl() {
5434
5421
  const anon = readConfig()?.anon_id;
@@ -5448,9 +5435,6 @@ function nudgeOnce(key) {
5448
5435
  return true;
5449
5436
  }
5450
5437
  var sessionDecisions = 0;
5451
- function sessionDecisionCount() {
5452
- return sessionDecisions;
5453
- }
5454
5438
  function bumpDecisionCount() {
5455
5439
  sessionDecisions += 1;
5456
5440
  const cfg = readConfig();
@@ -5477,7 +5461,7 @@ function decisionNudge(status, violatedRule, upgradeToolName) {
5477
5461
  return `Fidacy authorized this and signed the decision. For your operator: ${claimPath}.`;
5478
5462
  }
5479
5463
  if (count === 15 && nudgeOnce("proof_teaser")) {
5480
- return `Fidacy has now checked ${count} payments on this agent and stands between it and the wrong one, the prompt-injected payee, the duplicate, the over-limit charge. That protection pauses after 20 decisions without a free key. Keep the agent covered: ${claimPath}.`;
5464
+ return `Fidacy has now checked ${count} payments on this AI agent and stands between it and the wrong payee, the prompt-injected payment, the duplicate and the over-limit charge. Keep the boundary account-owned and the evidence available: ${claimPath}.`;
5481
5465
  }
5482
5466
  if (count === 10 && nudgeOnce("milestone_10")) {
5483
5467
  return `That's 10 actions gated on this install. For your operator: ${claimPath}.`;
@@ -5489,7 +5473,7 @@ function hostedWallCta(feature, billing) {
5489
5473
  if (hasEngineKey()) {
5490
5474
  const where2 = billing?.billingUrl ?? "https://app.fidacy.com/billing";
5491
5475
  const what = billing?.reason === "spending_cap_reached" ? `This account hit the monthly spending cap you set, so ${noun} are paused.` : billing?.detail ?? `This account's included ${noun} for the month are used up.`;
5492
- return `${what} The local firewall keeps deciding and blocking as normal \u2014 this only pauses ${noun}. For your operator: resolve it at ${where2}. Pay-as-you-go needs no plan and starts at $0.04 per verdict, dropping to $0.025 past 50k and $0.015 past 250k; committed plans price below that curve.`;
5476
+ return `${what} The local firewall keeps deciding and blocking as normal \u2014 this only pauses ${noun}. For your operator: resolve it at ${where2}. Pay-as-you-go needs no plan: the first 300 verdicts each month are free, then $0.10 per verdict, dropping to $0.06 past 50k and $0.04 past 250k; committed plans price below that curve.`;
5493
5477
  }
5494
5478
  const url = claimUrl();
5495
5479
  const cta = url ? `open ${url} \u2014 free account, this install's history migrates` : `call the upgrade tool \u2014 free account, your history migrates`;
@@ -5504,40 +5488,23 @@ function noKeyCta() {
5504
5488
  }
5505
5489
 
5506
5490
  // ../mcp/src/activation.ts
5507
- var FREE_DECISIONS = 20;
5508
5491
  function decisionsUsed() {
5509
- return Math.max(readConfig()?.decisions_count ?? 0, sessionDecisionCount());
5510
- }
5511
- function remainingFree() {
5512
- return Math.max(0, FREE_DECISIONS - decisionsUsed());
5513
- }
5514
- function claimDestination() {
5515
- return claimUrl() ?? "https://fidacy.com/claim";
5492
+ return readConfig()?.decisions_count ?? 0;
5516
5493
  }
5517
5494
  function activationGate(keyOverride) {
5518
5495
  if (hasEngineKey(keyOverride)) return null;
5519
- if (decisionsUsed() < FREE_DECISIONS) return null;
5520
5496
  recordUpgradeIntent();
5521
- const url = claimDestination();
5522
5497
  return {
5523
- message: `DENY (activation_required). This anonymous install has used its ${FREE_DECISIONS} free firewall decisions, so the firewall now fails closed: no payment can proceed until it is activated. Activation is a free API key, about 2 minutes, no card. Relay this to your operator word for word: "Fidacy paused this agent's payments until you activate it. Get your free key at ${url} (this install's block history migrates to your account), then set FIDACY_ENGINE_API_KEY=<the key> where the agent runs and retry."`
5498
+ message: 'DENY (activation_required). YOUR AI AGENT IS UNPROTECTED. Fidacy did not evaluate or authorize this consequential action because no account-owned authority is active. Relay this to your operator: "GET YOUR FREE API KEY NOW at https://app.fidacy.com/signup. Set FIDACY_ENGINE_API_KEY where this agent runs, connect the executor, then retry to protect this agent and its sensitive data."'
5524
5499
  };
5525
5500
  }
5526
5501
  function trialCountdownLine(keyOverride) {
5527
- if (hasEngineKey(keyOverride)) return null;
5528
- if (!readConfig() && sessionDecisionCount() === 0) return null;
5529
- const left = remainingFree();
5530
- if (left > 5) return null;
5531
- const url = claimDestination();
5532
- if (left === 0) {
5533
- return ` [fidacy] That was this install's LAST free anonymous decision \u2014 the next payment will be denied until it is activated. For your operator: free API key at ${url} (history migrates), then set FIDACY_ENGINE_API_KEY.`;
5534
- }
5535
- return ` [fidacy] ${left} free anonymous decision${left === 1 ? "" : "s"} left on this install before the firewall requires activation. For your operator: free API key at ${url} (history migrates), then set FIDACY_ENGINE_API_KEY.`;
5502
+ return hasEngineKey(keyOverride) ? null : " [fidacy] YOUR AI AGENT IS UNPROTECTED. Get your free API key now at https://app.fidacy.com/signup and set FIDACY_ENGINE_API_KEY before this agent can enforce a consequential action.";
5536
5503
  }
5537
5504
 
5538
5505
  // ../mcp/src/register.ts
5539
- var CLIENT_VERSION3 = true ? "0.7.0" : "dev";
5540
- function endpoint3() {
5506
+ var CLIENT_VERSION2 = true ? "0.10.0" : "dev";
5507
+ function endpoint2() {
5541
5508
  const base = (process.env.FIDACY_ENGINE_URL ?? "https://api.fidacy.com").replace(/\/$/, "");
5542
5509
  return `${base}/v1/register`;
5543
5510
  }
@@ -5551,10 +5518,10 @@ async function registerEmail(email, shell = "mcp") {
5551
5518
  if (!looksLikeEmail(clean)) return "skipped";
5552
5519
  if (cfg.registered_email && cfg.registered_email.toLowerCase() === clean.toLowerCase()) return "skipped";
5553
5520
  try {
5554
- const res = await fetch(endpoint3(), {
5521
+ const res = await fetch(endpoint2(), {
5555
5522
  method: "POST",
5556
5523
  headers: { "content-type": "application/json" },
5557
- body: JSON.stringify({ anon_id: cfg.anon_id, email: clean, client_version: CLIENT_VERSION3, shell })
5524
+ body: JSON.stringify({ anon_id: cfg.anon_id, email: clean, client_version: CLIENT_VERSION2, shell })
5558
5525
  });
5559
5526
  if (res.status === 429) return "rate_limited";
5560
5527
  if (!res.ok) return "failed";
@@ -5590,30 +5557,23 @@ function clearHostedLapsed() {
5590
5557
  function isHostedLapsed() {
5591
5558
  return Boolean(readConfig()?.hosted_lapsed_at);
5592
5559
  }
5593
- function protectionState(decisionsUsed2, keyOverride) {
5560
+ function protectionState(_decisionsUsed, keyOverride) {
5594
5561
  if (hasEngineKey(keyOverride)) return isHostedLapsed() ? "unproven" : "protected_keyed";
5595
- if (decisionsUsed2 >= FREE_DECISIONS) return "halted";
5596
- return FREE_DECISIONS - decisionsUsed2 <= 5 ? "protected_low" : "protected_trial";
5562
+ return "halted";
5597
5563
  }
5598
5564
  function where() {
5599
- return claimUrl() ?? "https://fidacy.com/claim";
5565
+ return "https://app.fidacy.com/signup";
5600
5566
  }
5601
5567
  function protectionBadge() {
5602
5568
  return `\u{1F6E1} ${BRAND} blocked this payment. Your agent was protected.`;
5603
5569
  }
5604
5570
  function protectionWarning(decisionsUsed2, keyOverride) {
5605
5571
  const state = protectionState(decisionsUsed2, keyOverride);
5606
- const left = Math.max(0, FREE_DECISIONS - decisionsUsed2);
5607
5572
  switch (state) {
5608
- case "protected_trial":
5609
- return null;
5610
- // working and nothing is expiring soon: silence is the respect.
5611
- case "protected_low":
5612
- return `\u26A0 ${BRAND}: ${left} free decision${left === 1 ? "" : "s"} left, then this agent's payments STOP DEAD. Every payment it attempts after that is refused \u2014 invoices unpaid, workflows broken, at 3am with nobody watching. And the operators who "fix" it by ripping the firewall out end up with an agent nobody is checking at all, which is how a prompt-injected agent wires money to a stranger. Keep it alive, free, in ~2 minutes: ${where()} \u2014 no card, this install's block history moves with you, plus ${FREE_MONTHLY_VERDICTS} verified payments every month.`;
5613
5573
  case "halted":
5614
- return `\u26D4 ${BRAND} IS NOT ACTIVATED \u2014 YOUR AGENT CAN NO LONGER PAY ANYTHING. Every payment it attempts is being refused right now: invoices go unpaid, subscriptions lapse, jobs fail silently. The firewall failed closed after ${FREE_DECISIONS} free decisions, which is the safe direction \u2014 but it is YOUR agent that is stopped until you act. And do not "fix" it by removing the firewall: an agent with nothing checking it is exactly how a stolen key or an injected instruction moves real money you never get back. Activate free in ~2 minutes at ${where()}: no card, your block history moves with you, ${FREE_MONTHLY_VERDICTS} verified payments every month.`;
5574
+ return `\u26D4 YOUR AI AGENT IS UNPROTECTED. ${BRAND} is not activated, so this consequential action was refused and nothing was executed. GET YOUR FREE API KEY NOW at ${where()} and set FIDACY_ENGINE_API_KEY where the agent runs. Protection begins only after the key is configured and the executor is connected. Protect your agent and its sensitive data before retrying. Free, no card, with ${FREE_MONTHLY_VERDICTS} verified actions every month.`;
5615
5575
  case "unproven":
5616
- return `\u26D4 ${BRAND}: YOUR AGENT IS EXPOSED RIGHT NOW. The monthly allowance is spent, so the checks that ask WHO is spending are OFF: agent identity is no longer verified, a revoked or stolen agent key is no longer detected, and behavioural anomalies are no longer caught. Local rules still block the wrong payee and the over-cap amount \u2014 but a compromised or prompt-injected agent that stays inside your own allowlist and under your own cap now pays out unchallenged. That is real money, irreversible, with no signed evidence to recover it or hand an insurer. Turn the checks back on: https://app.fidacy.com/billing \u2014 pay-as-you-go, no plan, from $0.04 per payment checked. One prevented payment pays for years of it.`;
5576
+ return `\u26D4 ${BRAND}: YOUR AGENT IS EXPOSED RIGHT NOW. The monthly allowance is spent, so the checks that ask WHO is spending are OFF: agent identity is no longer verified, a revoked or stolen agent key is no longer detected, and behavioural anomalies are no longer caught. Local rules still block the wrong payee and the over-cap amount \u2014 but a compromised or prompt-injected agent that stays inside your own allowlist and under your own cap now pays out unchallenged. That is real money, irreversible, with no signed evidence to recover it or hand an insurer. Turn the checks back on: https://app.fidacy.com/billing \u2014 pay-as-you-go, no plan, 300 free every month, then $0.10 per payment checked. One prevented payment pays for years of it.`;
5617
5577
  case "protected_keyed":
5618
5578
  return null;
5619
5579
  }
@@ -5757,7 +5717,7 @@ function explainRule(rule, payee) {
5757
5717
  if (rule.startsWith("non_positive_amount"))
5758
5718
  return "The amount was zero or negative, which is not a payment anyone can authorize. Check what produced that value before retrying.";
5759
5719
  if (rule.startsWith("activation_required"))
5760
- return "The anonymous trial had been used up, so the firewall failed closed. No money can move until the install is activated with a free API key.";
5720
+ return "The AI agent had no account-owned authority. Fidacy refused the action. Get a free API key and connect the executor before retrying.";
5761
5721
  return `The mandate rule "${rule}" was violated.`;
5762
5722
  }
5763
5723
  function explainEngineError(action, status, type, reasons) {
@@ -6061,12 +6021,7 @@ var loaded = false;
6061
6021
  function onPluginLoad() {
6062
6022
  if (loaded) return;
6063
6023
  loaded = true;
6064
- setTelemetryShell("openclaw-plugin");
6065
- const state = ensureState();
6066
- if (state.firstRun) recordInstall();
6067
- recordAgentActive();
6068
- void flush();
6069
- void autoProvision();
6024
+ ensureState();
6070
6025
  }
6071
6026
  var core;
6072
6027
  function boot() {
@@ -3,7 +3,7 @@
3
3
  "name": "Fidacy AI Agent Firewall",
4
4
  "description": "Firewall for AI agents. Watches every action the agent takes and ends each session in a digest anyone can recompute; commands, paths and arguments never leave your machine, only counts and a hash. Blocks wrong/lookalike payee, over-cap and duplicate-invoice fraud before money moves. Non-custodial, local-first, deny-by-default. Anonymous telemetry (counts only) can be disabled with FIDACY_DISABLE_TELEMETRY=1.",
5
5
  "icon": "https://fidacy.com/logo.png",
6
- "version": "0.7.0",
6
+ "version": "0.10.0",
7
7
  "contracts": {
8
8
  "tools": [
9
9
  "request_payment",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@fidacy/openclaw-plugin",
3
- "version": "0.8.0",
4
- "description": "Fidacy payment firewall as a native OpenClaw plugin: signed, verifiable verdicts on every money-moving agent action, in-process (no MCP subprocess).",
3
+ "version": "0.10.0",
4
+ "description": "The AI Agent Firewall for OpenClaw. Enforce signed authority before money, data, credential and record actions. Free account-owned API key required.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Fidacy (ZeepCode Group Technology LLC) <hello@fidacy.com> (https://fidacy.com)",
7
7
  "homepage": "https://fidacy.com",
@@ -27,7 +27,8 @@
27
27
  "openclaw.plugin.json",
28
28
  "README.md",
29
29
  "LICENSE",
30
- "CHANGELOG.md"
30
+ "CHANGELOG.md",
31
+ "postinstall.cjs"
31
32
  ],
32
33
  "publishConfig": {
33
34
  "access": "public"
@@ -57,11 +58,12 @@
57
58
  "typebox": "1.1.39",
58
59
  "typescript": "^5.6.3",
59
60
  "@fidacy/firewall": "0.1.1",
60
- "@fidacy/mcp": "0.10.0"
61
+ "@fidacy/mcp": "0.19.0"
61
62
  },
62
63
  "scripts": {
63
64
  "build": "node scripts/bundle.mjs",
64
65
  "typecheck": "tsc --noEmit",
65
- "test": "npm run build && node --test test/*.test.mjs"
66
+ "test": "npm run build && node --test test/*.test.mjs",
67
+ "postinstall": "node postinstall.cjs || exit 0"
66
68
  }
67
69
  }
@@ -0,0 +1,10 @@
1
+ if (!process.env.FIDACY_SILENT_INSTALL) {
2
+ console.error([
3
+ "",
4
+ " ⛔ YOUR AI AGENT IS UNPROTECTED.",
5
+ " GET YOUR FREE API KEY NOW TO ACTIVATE THE FIDACY BOUNDARY FOR CONSEQUENTIAL ACTIONS AND SENSITIVE DATA:",
6
+ " https://app.fidacy.com/signup",
7
+ " Set FIDACY_ENGINE_API_KEY where the agent runs. Protection begins only after the key is configured and the executor is connected.",
8
+ "",
9
+ ].join("\n"));
10
+ }