@metamynd/agentsafe-signer 0.20.0 → 0.20.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/package.json +1 -1
- package/policy-core.mjs +57 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metamynd/agentsafe-signer",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.1",
|
|
4
4
|
"description": "Local signer daemon for AgentSafe agent/service keys \u2014 the key never enters the calling guard's own process. See docs/design/agent-key-custody-local-signer-daemon-plan.md.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./daemon.mjs",
|
package/policy-core.mjs
CHANGED
|
@@ -43,6 +43,57 @@ function riskFloorFor(mandate, target) {
|
|
|
43
43
|
}
|
|
44
44
|
return floor;
|
|
45
45
|
}
|
|
46
|
+
var DEFAULT_AMOUNT_SHARE_HIGH = 0.7;
|
|
47
|
+
function grantsFor(mandate, target) {
|
|
48
|
+
return (mandate?.permission ?? []).filter((p) => !!p && typeof p === "object" && (p.target ?? mandate?.target) === target);
|
|
49
|
+
}
|
|
50
|
+
function perTxnCapFor(mandate, target) {
|
|
51
|
+
let cap = null;
|
|
52
|
+
for (const p of grantsFor(mandate, target)) {
|
|
53
|
+
for (const c of p.constraint ?? []) {
|
|
54
|
+
if (c?.leftOperand !== "mm:payAmount") continue;
|
|
55
|
+
const n = Number(c.rightOperand);
|
|
56
|
+
if (Number.isFinite(n) && n > 0 && (cap === null || n < cap)) cap = n;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return cap;
|
|
60
|
+
}
|
|
61
|
+
function hasMerchantAllowList(mandate, target) {
|
|
62
|
+
return grantsFor(mandate, target).some((p) => (p.constraint ?? []).some((c) => c?.leftOperand === "mm:merchant"));
|
|
63
|
+
}
|
|
64
|
+
function riskSignalSettings(mandate, target) {
|
|
65
|
+
const grants = grantsFor(mandate, target);
|
|
66
|
+
if (grants.length === 0) return { amountShare: DEFAULT_AMOUNT_SHARE_HIGH, newMerchant: true };
|
|
67
|
+
let amountShare = null;
|
|
68
|
+
let newMerchant = false;
|
|
69
|
+
for (const p of grants) {
|
|
70
|
+
const s = p.riskSignals;
|
|
71
|
+
if (s === false) continue;
|
|
72
|
+
const cfg = s && typeof s === "object" ? s : {};
|
|
73
|
+
const share = cfg.amountShare === false ? null : cfg.amountShare === void 0 ? DEFAULT_AMOUNT_SHARE_HIGH : Number(cfg.amountShare);
|
|
74
|
+
if (share !== null && Number.isFinite(share) && share > 0 && share <= 1 && (amountShare === null || share < amountShare)) amountShare = share;
|
|
75
|
+
if (cfg.newMerchant !== false) newMerchant = true;
|
|
76
|
+
}
|
|
77
|
+
return { amountShare, newMerchant };
|
|
78
|
+
}
|
|
79
|
+
function riskSignalsFor(mandate, target, amount, opts = {}) {
|
|
80
|
+
const out = [];
|
|
81
|
+
const tier = riskFloorFor(mandate, target);
|
|
82
|
+
if (tier) out.push({ signal: "owner-tier", level: tier, detail: `the owner's risk tier for ${target}` });
|
|
83
|
+
const settings = riskSignalSettings(mandate, target);
|
|
84
|
+
const n = typeof amount === "number" ? amount : Number(amount);
|
|
85
|
+
const cap = perTxnCapFor(mandate, target);
|
|
86
|
+
if (settings.amountShare !== null && cap !== null && Number.isFinite(n) && n > 0 && n >= settings.amountShare * cap) {
|
|
87
|
+
out.push({ signal: "amount-share", level: "high", detail: `${Math.round(n / cap * 100)}% of the ${cap} per-transaction cap (review from ${Math.round(settings.amountShare * 100)}%)` });
|
|
88
|
+
}
|
|
89
|
+
if (opts.newMerchant === true && settings.newMerchant && !hasMerchantAllowList(mandate, target)) {
|
|
90
|
+
out.push({ signal: "new-merchant", level: "high", detail: "the first payment to this merchant" });
|
|
91
|
+
}
|
|
92
|
+
return out;
|
|
93
|
+
}
|
|
94
|
+
function effectiveRiskFloor(mandate, target, amount, opts = {}) {
|
|
95
|
+
return maxRisk(...riskSignalsFor(mandate, target, amount, opts).map((s) => s.level));
|
|
96
|
+
}
|
|
46
97
|
function requiresPayloadBindingFor(mandate, target) {
|
|
47
98
|
if (!mandate) return false;
|
|
48
99
|
for (const p of mandate.permission ?? []) {
|
|
@@ -793,6 +844,7 @@ export {
|
|
|
793
844
|
AUTH_MESSAGE_V2_TAG,
|
|
794
845
|
CATALOGUED_ATOMS,
|
|
795
846
|
CONTEXT_UNVERIFIABLE,
|
|
847
|
+
DEFAULT_AMOUNT_SHARE_HIGH,
|
|
796
848
|
JURISDICTION_ATOM,
|
|
797
849
|
MODES_BY_RANK,
|
|
798
850
|
MODE_RANK,
|
|
@@ -815,10 +867,12 @@ export {
|
|
|
815
867
|
canAuthorize,
|
|
816
868
|
contextFieldProblem,
|
|
817
869
|
documentEnforcesJurisdiction,
|
|
870
|
+
effectiveRiskFloor,
|
|
818
871
|
evaluate,
|
|
819
872
|
evaluateBoundStandards,
|
|
820
873
|
evaluateMandate,
|
|
821
874
|
evaluateStandardRules,
|
|
875
|
+
hasMerchantAllowList,
|
|
822
876
|
isAuthorityFailure,
|
|
823
877
|
isOperatingMode,
|
|
824
878
|
isProvenance,
|
|
@@ -829,6 +883,7 @@ export {
|
|
|
829
883
|
moreRestrictive,
|
|
830
884
|
normalizeRiskLevel,
|
|
831
885
|
operatingModeGate,
|
|
886
|
+
perTxnCapFor,
|
|
832
887
|
provenanceOf,
|
|
833
888
|
releaseHold,
|
|
834
889
|
remainingBudget,
|
|
@@ -836,6 +891,8 @@ export {
|
|
|
836
891
|
requiredContextOf,
|
|
837
892
|
requiresPayloadBindingFor,
|
|
838
893
|
riskFloorFor,
|
|
894
|
+
riskSignalSettings,
|
|
895
|
+
riskSignalsFor,
|
|
839
896
|
sumEventField,
|
|
840
897
|
validateMolecules
|
|
841
898
|
};
|