@fidacy/openclaw-plugin 0.5.5 → 0.5.7
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 +13 -0
- package/README.md +5 -3
- package/dist/index.js +52 -9
- package/openclaw.plugin.json +5 -28
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Four configuration mistakes that presented themselves as security verdicts, so the firewall looked broken and stopped real payments for reasons nobody could see.
|
|
8
|
+
|
|
9
|
+
- `FIDACY_MANDATE_JSON` was the last human-authored surface returned verbatim, with no validation of its caps. `"perTxMax": "10000"` built a mandate the engine had to refuse, so **every** payment came back `invalid_mandate_cap:perTxMax=10000` — a message naming 10000 as the invalid cap, when 10000 is a perfectly good number and the quotes were the whole problem. It now honours a quoted number (which means exactly one thing) and refuses anything that would need a guess, loudly, saying that the payees and caps in force are not the ones you wrote.
|
|
10
|
+
- **Fail-open, now closed:** both window checks are `now < Date.parse(...)` and `now > Date.parse(...)`, and a date that does not parse yields NaN, which makes both comparisons false. An unreadable window was not a narrow window, it was no window: the mandate never expired. An unenforceable window now denies, at the engine as well as at the override.
|
|
11
|
+
- A quoted cap in `config.json` was discarded silently, so the 2500 default applied and a 5000 payment came back `per_tx_cap_exceeded:5000>2500`, quoting a cap the operator had never set. It now follows the same rule as the environment variables, which had warned since 2026-07-24.
|
|
12
|
+
- `"currency": "usd"` denied every payment with `currency_not_allowed:USD`, naming as forbidden the exact currency it had allowed. ISO 4217 codes are case-insensitive; case was never a policy decision.
|
|
13
|
+
|
|
14
|
+
Nothing was loosened. Caps still cap, a genuinely different currency is still denied, a payee off the allowlist is still denied, and an unreadable value still falls back to the safe default rather than to no limit at all.
|
|
15
|
+
|
|
3
16
|
## 0.5.5
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -46,9 +46,11 @@ it never holds funds.
|
|
|
46
46
|
|
|
47
47
|
## To everyone who installed Fidacy
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
The Fidacy firewall has taken **3,099 decisions** to date, **98% of them blocks**,
|
|
50
|
+
counted by the engine and public at
|
|
51
|
+
[api.fidacy.com/v1/pulse](https://api.fidacy.com/v1/pulse) if you want to check the
|
|
52
|
+
number yourself. Thank you for being part of it. Two things worth a minute of your
|
|
53
|
+
time:
|
|
52
54
|
|
|
53
55
|
1. **See and claim what YOUR install blocked.** Your install carries a private,
|
|
54
56
|
anonymous id on your machine (we never learn who you are unless you choose to).
|
package/dist/index.js
CHANGED
|
@@ -4320,14 +4320,24 @@ function resolveMandateRules(cfg) {
|
|
|
4320
4320
|
}
|
|
4321
4321
|
return n;
|
|
4322
4322
|
};
|
|
4323
|
-
const fileNum = (v) =>
|
|
4323
|
+
const fileNum = (name, v) => {
|
|
4324
|
+
if (v === void 0 || v === null) return void 0;
|
|
4325
|
+
const n = typeof v === "number" ? v : typeof v === "string" ? Number(v.trim()) : NaN;
|
|
4326
|
+
if (!Number.isFinite(n) || n <= 0) {
|
|
4327
|
+
console.error(
|
|
4328
|
+
`[fidacy] mandate.${name} in config.json is ${JSON.stringify(v)}, which is not a positive number, so it cannot be enforced as a cap. Ignoring it and using the safe default. Write it as a bare JSON number, with no quotes, thousands separator, currency symbol or unit (e.g. "${name}": 2500).`
|
|
4329
|
+
);
|
|
4330
|
+
return void 0;
|
|
4331
|
+
}
|
|
4332
|
+
return n;
|
|
4333
|
+
};
|
|
4324
4334
|
const payees = envList(process.env.FIDACY_ALLOW_PAYEES) ?? m.payees ?? [];
|
|
4325
4335
|
return {
|
|
4326
4336
|
payees: payees.includes(DEMO_PAYEE) ? payees : [...payees, DEMO_PAYEE],
|
|
4327
4337
|
categories: envList(process.env.FIDACY_ALLOW_CATEGORIES) ?? m.categories ?? ["*"],
|
|
4328
4338
|
currency: process.env.FIDACY_CURRENCY ?? m.currency ?? "USD",
|
|
4329
|
-
perTxMax: envNum("FIDACY_PER_TX_MAX", process.env.FIDACY_PER_TX_MAX) ?? fileNum(m.perTxMax) ?? 2500,
|
|
4330
|
-
maxTotal: envNum("FIDACY_MAX_TOTAL", process.env.FIDACY_MAX_TOTAL) ?? fileNum(m.maxTotal) ?? 1e4
|
|
4339
|
+
perTxMax: envNum("FIDACY_PER_TX_MAX", process.env.FIDACY_PER_TX_MAX) ?? fileNum("perTxMax", m.perTxMax) ?? 2500,
|
|
4340
|
+
maxTotal: envNum("FIDACY_MAX_TOTAL", process.env.FIDACY_MAX_TOTAL) ?? fileNum("maxTotal", m.maxTotal) ?? 1e4
|
|
4331
4341
|
};
|
|
4332
4342
|
}
|
|
4333
4343
|
|
|
@@ -4759,6 +4769,13 @@ function validateMandateCaps(mandate) {
|
|
|
4759
4769
|
return `invalid_mandate_cap:perTxMax=${String(mandate.allow.perTxMax)}`;
|
|
4760
4770
|
if (bad(mandate.allow.maxTotal))
|
|
4761
4771
|
return `invalid_mandate_cap:maxTotal=${String(mandate.allow.maxTotal)}`;
|
|
4772
|
+
if (!mandate.window || typeof mandate.window !== "object")
|
|
4773
|
+
return "invalid_mandate:missing_window";
|
|
4774
|
+
for (const campo of ["notBefore", "notAfter"]) {
|
|
4775
|
+
const v = mandate.window[campo];
|
|
4776
|
+
if (typeof v !== "string" || Number.isNaN(Date.parse(v)))
|
|
4777
|
+
return `invalid_mandate_window:${campo}=${String(v)}`;
|
|
4778
|
+
}
|
|
4762
4779
|
return null;
|
|
4763
4780
|
}
|
|
4764
4781
|
function evaluate(mandate, req, spentSoFar) {
|
|
@@ -4772,7 +4789,7 @@ function evaluate(mandate, req, spentSoFar) {
|
|
|
4772
4789
|
return "before_mandate_window";
|
|
4773
4790
|
if (now > Date.parse(mandate.window.notAfter))
|
|
4774
4791
|
return "after_mandate_window";
|
|
4775
|
-
if (req.currency !== mandate.allow.currency)
|
|
4792
|
+
if (req.currency.toUpperCase() !== mandate.allow.currency.toUpperCase())
|
|
4776
4793
|
return `currency_not_allowed:${req.currency}`;
|
|
4777
4794
|
if (req.amount <= 0)
|
|
4778
4795
|
return "non_positive_amount";
|
|
@@ -5085,7 +5102,7 @@ var FileAuditStore = class {
|
|
|
5085
5102
|
import { statSync } from "node:fs";
|
|
5086
5103
|
|
|
5087
5104
|
// ../mcp/src/telemetry.ts
|
|
5088
|
-
var CLIENT_VERSION = true ? "0.5.
|
|
5105
|
+
var CLIENT_VERSION = true ? "0.5.7" : "dev";
|
|
5089
5106
|
function bandOf(amount) {
|
|
5090
5107
|
if (typeof amount !== "number" || !Number.isFinite(amount) || amount <= 0) return void 0;
|
|
5091
5108
|
if (amount < 10) return "lt10";
|
|
@@ -5193,12 +5210,38 @@ async function flush() {
|
|
|
5193
5210
|
}
|
|
5194
5211
|
|
|
5195
5212
|
// ../mcp/src/core.ts
|
|
5213
|
+
function normalizaMandatoDeEnv(m) {
|
|
5214
|
+
const allow = m.allow;
|
|
5215
|
+
for (const campo of ["perTxMax", "maxTotal"]) {
|
|
5216
|
+
const v = allow[campo];
|
|
5217
|
+
const n = typeof v === "number" ? v : typeof v === "string" ? Number(v.trim()) : NaN;
|
|
5218
|
+
if (!Number.isFinite(n) || n <= 0) {
|
|
5219
|
+
return `has allow.${campo} = ${JSON.stringify(v)}, which is not a positive number, so that cap cannot be enforced. Write it as a bare JSON number, with no quotes, thousands separator, currency symbol or unit (e.g. "${campo}": 2500).`;
|
|
5220
|
+
}
|
|
5221
|
+
allow[campo] = n;
|
|
5222
|
+
}
|
|
5223
|
+
const window = m.window;
|
|
5224
|
+
for (const campo of ["notBefore", "notAfter"]) {
|
|
5225
|
+
const v = window[campo];
|
|
5226
|
+
if (typeof v !== "string" || Number.isNaN(Date.parse(v))) {
|
|
5227
|
+
return `has window.${campo} = ${JSON.stringify(v)}, which is not a readable date, so the mandate's time window cannot be enforced. Use an ISO 8601 timestamp (e.g. "${campo}": "2026-01-01T00:00:00Z").`;
|
|
5228
|
+
}
|
|
5229
|
+
}
|
|
5230
|
+
return null;
|
|
5231
|
+
}
|
|
5196
5232
|
function buildMandate() {
|
|
5197
5233
|
if (process.env.FIDACY_MANDATE_JSON) {
|
|
5198
5234
|
try {
|
|
5199
5235
|
const parsed = JSON.parse(process.env.FIDACY_MANDATE_JSON);
|
|
5200
|
-
if (parsed && typeof parsed === "object" && parsed.allow && parsed.window)
|
|
5201
|
-
|
|
5236
|
+
if (parsed && typeof parsed === "object" && parsed.allow && parsed.window) {
|
|
5237
|
+
const problema = normalizaMandatoDeEnv(parsed);
|
|
5238
|
+
if (!problema) return parsed;
|
|
5239
|
+
console.error(
|
|
5240
|
+
`[fidacy] FIDACY_MANDATE_JSON ${problema} The override is being IGNORED and the safe default mandate is in force instead, so your payees and caps are NOT the ones you wrote.`
|
|
5241
|
+
);
|
|
5242
|
+
} else {
|
|
5243
|
+
console.error("[fidacy] FIDACY_MANDATE_JSON is missing allow/window; ignoring it and using the safe default mandate.");
|
|
5244
|
+
}
|
|
5202
5245
|
} catch (err) {
|
|
5203
5246
|
console.error(`[fidacy] FIDACY_MANDATE_JSON is not valid JSON (${err.message}); ignoring it and using the safe default mandate.`);
|
|
5204
5247
|
}
|
|
@@ -5274,7 +5317,7 @@ function requestUpgrade() {
|
|
|
5274
5317
|
}
|
|
5275
5318
|
|
|
5276
5319
|
// ../mcp/src/provision.ts
|
|
5277
|
-
var CLIENT_VERSION2 = true ? "0.5.
|
|
5320
|
+
var CLIENT_VERSION2 = true ? "0.5.7" : "dev";
|
|
5278
5321
|
function provisionEnabled() {
|
|
5279
5322
|
const v = (process.env.FIDACY_DISABLE_PROVISION ?? "").trim().toLowerCase();
|
|
5280
5323
|
return !(v === "1" || v === "true" || v === "yes");
|
|
@@ -5417,7 +5460,7 @@ function trialCountdownLine(keyOverride) {
|
|
|
5417
5460
|
}
|
|
5418
5461
|
|
|
5419
5462
|
// ../mcp/src/register.ts
|
|
5420
|
-
var CLIENT_VERSION3 = true ? "0.5.
|
|
5463
|
+
var CLIENT_VERSION3 = true ? "0.5.7" : "dev";
|
|
5421
5464
|
function endpoint3() {
|
|
5422
5465
|
const base = (process.env.FIDACY_ENGINE_URL ?? "https://api.fidacy.com").replace(/\/$/, "");
|
|
5423
5466
|
return `${base}/v1/register`;
|
package/openclaw.plugin.json
CHANGED
|
@@ -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.5.
|
|
6
|
+
"version": "0.5.7",
|
|
7
7
|
"contracts": {
|
|
8
8
|
"tools": [
|
|
9
9
|
"request_payment",
|
|
@@ -25,43 +25,20 @@
|
|
|
25
25
|
"properties": {
|
|
26
26
|
"operatorEmail": {
|
|
27
27
|
"type": "string",
|
|
28
|
-
"description": "Your email (optional). Ties this agent's protection history to you so it can move into a free account, and lets Fidacy reach you about this install. Never shared; remove any time."
|
|
28
|
+
"description": "Your email (optional). Ties this agent's protection history to you so it can move into a free account, and lets Fidacy reach you about this install. Never shared; remove any time. Your email (optional) Ties this agent's protection history to you so it can move into a free account, and lets Fidacy reach you about this install. Optional — the firewall works without it."
|
|
29
29
|
},
|
|
30
30
|
"engineApiKey": {
|
|
31
31
|
"type": "string",
|
|
32
|
-
"description": "Fidacy engine API key (fky_live_/fky_test_) enabling signed verdicts via assess_action. Falls back to FIDACY_ENGINE_API_KEY."
|
|
32
|
+
"description": "Fidacy engine API key (fky_live_/fky_test_) enabling signed verdicts via assess_action. Falls back to FIDACY_ENGINE_API_KEY. Engine API key Free key at app.fidacy.com/signup. Enables signed trust verdicts (assess_action) and keeps the firewall active past the 20-decision anonymous trial."
|
|
33
33
|
},
|
|
34
34
|
"engineUrl": {
|
|
35
35
|
"type": "string",
|
|
36
|
-
"description": "Fidacy engine base URL. Defaults to https://api.fidacy.com (or FIDACY_ENGINE_URL)."
|
|
36
|
+
"description": "Fidacy engine base URL. Defaults to https://api.fidacy.com (or FIDACY_ENGINE_URL). Engine URL"
|
|
37
37
|
},
|
|
38
38
|
"subject": {
|
|
39
39
|
"type": "string",
|
|
40
|
-
"description": "Mandate subject identity for this agent. Defaults to agent:demo (or FIDACY_SUBJECT)."
|
|
40
|
+
"description": "Mandate subject identity for this agent. Defaults to agent:demo (or FIDACY_SUBJECT). Agent subject"
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
|
-
},
|
|
44
|
-
"uiHints": {
|
|
45
|
-
"operatorEmail": {
|
|
46
|
-
"label": "Your email (optional)",
|
|
47
|
-
"placeholder": "you@company.com",
|
|
48
|
-
"help": "Ties this agent's protection history to you so it can move into a free account, and lets Fidacy reach you about this install. Optional — the firewall works without it."
|
|
49
|
-
},
|
|
50
|
-
"engineApiKey": {
|
|
51
|
-
"label": "Engine API key",
|
|
52
|
-
"placeholder": "fky_live_...",
|
|
53
|
-
"sensitive": true,
|
|
54
|
-
"help": "Free key at app.fidacy.com/signup. Enables signed trust verdicts (assess_action) and keeps the firewall active past the 20-decision anonymous trial."
|
|
55
|
-
},
|
|
56
|
-
"engineUrl": {
|
|
57
|
-
"label": "Engine URL",
|
|
58
|
-
"placeholder": "https://api.fidacy.com",
|
|
59
|
-
"advanced": true
|
|
60
|
-
},
|
|
61
|
-
"subject": {
|
|
62
|
-
"label": "Agent subject",
|
|
63
|
-
"placeholder": "agent:demo",
|
|
64
|
-
"advanced": true
|
|
65
|
-
}
|
|
66
43
|
}
|
|
67
44
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fidacy/openclaw-plugin",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.7",
|
|
4
4
|
"description": "Fidacy payment firewall as a native OpenClaw plugin: signed, verifiable verdicts on every money-moving agent action, in-process (no MCP subprocess).",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Fidacy (ZeepCode Group Technology LLC) <hello@fidacy.com> (https://fidacy.com)",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"typebox": "1.1.39",
|
|
58
58
|
"typescript": "^5.6.3",
|
|
59
59
|
"@fidacy/firewall": "0.1.1",
|
|
60
|
-
"@fidacy/mcp": "0.7.
|
|
60
|
+
"@fidacy/mcp": "0.7.4"
|
|
61
61
|
},
|
|
62
62
|
"scripts": {
|
|
63
63
|
"build": "node scripts/bundle.mjs",
|