@metamynd/agentsafe-mcp-guard 0.2.1 → 0.3.1
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 +5 -0
- package/package.json +1 -1
- package/policy-core.mjs +15 -0
package/README.md
CHANGED
|
@@ -67,6 +67,11 @@ const bookFlight = guard.guardIncomingTool('flight-purchase', rawBookFlight);
|
|
|
67
67
|
4. evaluates Standards → SOPs → mandate with `policy-core` — signed fields applied last, so a
|
|
68
68
|
forged `itinerary` key can't shadow the signed amount/merchant (§6.4.2).
|
|
69
69
|
|
|
70
|
+
`policy-core`'s `amount-unknown` atom (0.3.0) is a deny-by-default check for any value-moving
|
|
71
|
+
tool call whose amount the guard can't determine — a signed-transaction or nested x402 payload
|
|
72
|
+
can carry its value somewhere a naive spend cap never looks, and this blocks that case instead
|
|
73
|
+
of letting it slip past the cap untested.
|
|
74
|
+
|
|
70
75
|
### Replay and cumulative spend (`requireAuthorization`)
|
|
71
76
|
|
|
72
77
|
Re-evaluating policy per request (above) proves the request is well-formed and in-policy — it
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metamynd/agentsafe-mcp-guard",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Zero-dependency trustless governance for the SERVICE side. An MCP server or API re-verifies a calling agent's signed request against the agent's own published policy \u00e2\u20ac\u201d so an agent that ignores its own guard still cannot make your service act.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./agentsafe-mcp-guard.mjs",
|
package/policy-core.mjs
CHANGED
|
@@ -11,6 +11,14 @@ var ATOM_REGISTRY = {
|
|
|
11
11
|
return have !== void 0 && need !== void 0 && have >= need;
|
|
12
12
|
},
|
|
13
13
|
"amount-over": (c, cfg) => typeof c.amount === "number" && c.amount > Number(cfg?.limit ?? 0),
|
|
14
|
+
// Deny-by-default primitive for value-moving actions. Fires on ABSENCE (like the
|
|
15
|
+
// evidence atoms below, and unlike `amount-over`): true when the context carries no
|
|
16
|
+
// usable amount — the gate cannot tell how much value the call would move, so a
|
|
17
|
+
// spend cap authored next to it would silently never fire. Author it with BLOCK as
|
|
18
|
+
// the FIRST rule of a spend policy; the cap that follows then only ever judges a
|
|
19
|
+
// known number. Opt-in: only a rule that keys it runs it, so actions that carry no
|
|
20
|
+
// amount by nature are unaffected.
|
|
21
|
+
"amount-unknown": (c) => !(typeof c.amount === "number" && Number.isFinite(c.amount)),
|
|
14
22
|
// Total budget: cumulativeSpend is a SERVER-derived, signed-last context field (never
|
|
15
23
|
// shadowable by the agent's itinerary), so this compares already-spent + this amount.
|
|
16
24
|
"cumulative-over": (c, cfg) => Number(c.cumulativeSpend ?? 0) + Number(c.amount ?? 0) > Number(cfg?.limit ?? 0),
|
|
@@ -72,6 +80,13 @@ var ATOM_SPECS = [
|
|
|
72
80
|
config: [{ key: "limit", type: "number", required: true, description: "Maximum allowed amount for one transaction" }],
|
|
73
81
|
requiredContext: ["amount"]
|
|
74
82
|
},
|
|
83
|
+
{
|
|
84
|
+
predicate: "amount-unknown",
|
|
85
|
+
label: "Amount not determinable",
|
|
86
|
+
description: "Fires when the action carries no usable amount \u2014 the gate cannot tell how much value it would move. A deny-by-default control for value-moving actions: author it with BLOCK ahead of a spend cap, otherwise an action whose amount is missing or unparseable passes the cap untested. Fires on ABSENCE, so only attach it to actions that must always carry an amount.",
|
|
87
|
+
config: [],
|
|
88
|
+
requiredContext: ["amount"]
|
|
89
|
+
},
|
|
75
90
|
{
|
|
76
91
|
predicate: "cumulative-over",
|
|
77
92
|
label: "Total budget over limit",
|