@fidacy/mcp 0.1.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/LICENSE +201 -0
- package/README.md +131 -0
- package/dist/assess.d.ts +78 -0
- package/dist/assess.js +139 -0
- package/dist/assess.js.map +1 -0
- package/dist/audit-store.d.ts +11 -0
- package/dist/audit-store.js +51 -0
- package/dist/audit-store.js.map +1 -0
- package/dist/core.d.ts +33 -0
- package/dist/core.js +143 -0
- package/dist/core.js.map +1 -0
- package/dist/executor.d.ts +30 -0
- package/dist/executor.js +56 -0
- package/dist/executor.js.map +1 -0
- package/dist/grant.d.ts +18 -0
- package/dist/grant.js +39 -0
- package/dist/grant.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +135 -0
- package/dist/index.js.map +1 -0
- package/dist/lib.d.ts +4 -0
- package/dist/lib.js +5 -0
- package/dist/lib.js.map +1 -0
- package/dist/signing.d.ts +10 -0
- package/dist/signing.js +32 -0
- package/dist/signing.js.map +1 -0
- package/dist/types.d.ts +51 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/util.d.ts +1 -0
- package/dist/util.js +9 -0
- package/dist/util.js.map +1 -0
- package/package.json +50 -0
package/dist/core.js
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { loadOrGenerateKeyPair, publicKeyPem, sign } from "./signing.js";
|
|
3
|
+
import { stableStringify } from "./util.js";
|
|
4
|
+
import { FileAuditStore } from "./audit-store.js";
|
|
5
|
+
// Pure mandate evaluation. Returns the first violated rule, or null if allowed.
|
|
6
|
+
export function evaluate(mandate, req, spentSoFar) {
|
|
7
|
+
const now = Date.now();
|
|
8
|
+
if (mandate.revoked)
|
|
9
|
+
return "mandate_revoked";
|
|
10
|
+
if (now < Date.parse(mandate.window.notBefore))
|
|
11
|
+
return "before_mandate_window";
|
|
12
|
+
if (now > Date.parse(mandate.window.notAfter))
|
|
13
|
+
return "after_mandate_window";
|
|
14
|
+
if (req.currency !== mandate.allow.currency)
|
|
15
|
+
return `currency_not_allowed:${req.currency}`;
|
|
16
|
+
if (req.amount <= 0)
|
|
17
|
+
return "non_positive_amount";
|
|
18
|
+
if (req.amount > mandate.allow.perTxMax)
|
|
19
|
+
return `per_tx_cap_exceeded:${req.amount}>${mandate.allow.perTxMax}`;
|
|
20
|
+
if (spentSoFar + req.amount > mandate.allow.maxTotal)
|
|
21
|
+
return `total_cap_exceeded:${spentSoFar + req.amount}>${mandate.allow.maxTotal}`;
|
|
22
|
+
const payeeOk = mandate.allow.payees.includes("*") || mandate.allow.payees.includes(req.payee);
|
|
23
|
+
if (!payeeOk)
|
|
24
|
+
return `payee_not_in_allowlist:${req.payee}`;
|
|
25
|
+
const catOk = mandate.allow.categories.includes("*") || mandate.allow.categories.includes(req.category);
|
|
26
|
+
if (!catOk)
|
|
27
|
+
return `category_not_allowed:${req.category}`;
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
// Reference core: real Ed25519 grants + durable hash-chained audit. Ships a demo
|
|
31
|
+
// mandate so the firewall runs out of the box. Swap for HttpFidacyCore in prod.
|
|
32
|
+
export class DevFidacyCore {
|
|
33
|
+
priv;
|
|
34
|
+
pubPem;
|
|
35
|
+
mandate;
|
|
36
|
+
store;
|
|
37
|
+
spent = 0;
|
|
38
|
+
constructor() {
|
|
39
|
+
const kp = loadOrGenerateKeyPair();
|
|
40
|
+
this.priv = kp.privateKey;
|
|
41
|
+
this.pubPem = publicKeyPem(kp.publicKey);
|
|
42
|
+
if (kp.ephemeral)
|
|
43
|
+
console.error("[fidacy] WARNING: ephemeral signing key. Set FIDACY_SIGNING_KEY_B64 in production.");
|
|
44
|
+
this.mandate = this.loadMandate();
|
|
45
|
+
this.store = new FileAuditStore(process.env.FIDACY_AUDIT_PATH ?? "./fidacy-audit.log");
|
|
46
|
+
}
|
|
47
|
+
loadMandate() {
|
|
48
|
+
if (process.env.FIDACY_MANDATE_JSON)
|
|
49
|
+
return JSON.parse(process.env.FIDACY_MANDATE_JSON);
|
|
50
|
+
const subject = process.env.FIDACY_SUBJECT ?? "agent:demo";
|
|
51
|
+
return {
|
|
52
|
+
id: "mandate:demo",
|
|
53
|
+
subject,
|
|
54
|
+
version: "ap2.v0.2.0",
|
|
55
|
+
allow: {
|
|
56
|
+
payees: (process.env.FIDACY_ALLOW_PAYEES ?? "supplier:acme,supplier:globex").split(","),
|
|
57
|
+
categories: (process.env.FIDACY_ALLOW_CATEGORIES ?? "invoice,subscription").split(","),
|
|
58
|
+
currency: process.env.FIDACY_CURRENCY ?? "USD",
|
|
59
|
+
maxTotal: Number(process.env.FIDACY_MAX_TOTAL ?? 10000),
|
|
60
|
+
perTxMax: Number(process.env.FIDACY_PER_TX_MAX ?? 2500),
|
|
61
|
+
},
|
|
62
|
+
window: {
|
|
63
|
+
notBefore: process.env.FIDACY_NOT_BEFORE ?? new Date(Date.now() - 3600_000).toISOString(),
|
|
64
|
+
notAfter: process.env.FIDACY_NOT_AFTER ?? new Date(Date.now() + 30 * 86400_000).toISOString(),
|
|
65
|
+
},
|
|
66
|
+
revoked: false,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
async getMandate() {
|
|
70
|
+
return this.mandate;
|
|
71
|
+
}
|
|
72
|
+
async decide(req, subject) {
|
|
73
|
+
const decisionId = randomUUID();
|
|
74
|
+
const ts = new Date().toISOString();
|
|
75
|
+
const violated = evaluate(this.mandate, req, this.spent);
|
|
76
|
+
if (violated) {
|
|
77
|
+
const decision = { decisionId, status: "DENY", subject, mandateId: this.mandate.id, request: req, violatedRule: violated, ts };
|
|
78
|
+
this.store.append(decision);
|
|
79
|
+
return decision;
|
|
80
|
+
}
|
|
81
|
+
const grantPayload = { decisionId, subject, payee: req.payee, amount: req.amount, currency: req.currency, exp: Date.now() + 120_000 };
|
|
82
|
+
const grantBody = Buffer.from(stableStringify(grantPayload), "utf8").toString("base64url");
|
|
83
|
+
const grant = `${grantBody}.${sign(this.priv, grantBody)}`;
|
|
84
|
+
const decision = { decisionId, status: "ALLOW", subject, mandateId: this.mandate.id, request: req, grant, ts };
|
|
85
|
+
this.spent += req.amount;
|
|
86
|
+
this.store.append(decision);
|
|
87
|
+
return decision;
|
|
88
|
+
}
|
|
89
|
+
async getProof(decisionId) {
|
|
90
|
+
const record = this.store.find(decisionId);
|
|
91
|
+
if (!record)
|
|
92
|
+
return null;
|
|
93
|
+
return { record, chainIntact: this.store.intact(), verifiedAgainstPublicKey: this.pubPem };
|
|
94
|
+
}
|
|
95
|
+
publicKey() {
|
|
96
|
+
return this.pubPem;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// Production core: delegates to your backend over HTTP. Implement three
|
|
100
|
+
// endpoints in the Fidacy core and the MCP layer needs zero changes.
|
|
101
|
+
export class HttpFidacyCore {
|
|
102
|
+
baseUrl;
|
|
103
|
+
apiKey;
|
|
104
|
+
subjectPub;
|
|
105
|
+
constructor(baseUrl, apiKey, subjectPub = "") {
|
|
106
|
+
this.baseUrl = baseUrl;
|
|
107
|
+
this.apiKey = apiKey;
|
|
108
|
+
this.subjectPub = subjectPub;
|
|
109
|
+
}
|
|
110
|
+
async call(path, body) {
|
|
111
|
+
const res = await fetch(`${this.baseUrl}${path}`, {
|
|
112
|
+
method: "POST",
|
|
113
|
+
headers: { "content-type": "application/json", authorization: `Bearer ${this.apiKey}` },
|
|
114
|
+
body: JSON.stringify(body),
|
|
115
|
+
});
|
|
116
|
+
if (!res.ok)
|
|
117
|
+
throw new Error(`fidacy core ${path} -> ${res.status}`);
|
|
118
|
+
return (await res.json());
|
|
119
|
+
}
|
|
120
|
+
async getMandate(subject) {
|
|
121
|
+
return this.call("/v1/mandate/get", { subject });
|
|
122
|
+
}
|
|
123
|
+
async decide(req, subject) {
|
|
124
|
+
return this.call("/v1/decide", { req, subject });
|
|
125
|
+
}
|
|
126
|
+
async getProof(decisionId) {
|
|
127
|
+
return this.call("/v1/audit/proof", { decisionId });
|
|
128
|
+
}
|
|
129
|
+
publicKey() {
|
|
130
|
+
return this.subjectPub;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
export function makeCore() {
|
|
134
|
+
if ((process.env.FIDACY_MODE ?? "dev") === "http") {
|
|
135
|
+
const url = process.env.FIDACY_API_URL;
|
|
136
|
+
const key = process.env.FIDACY_API_KEY;
|
|
137
|
+
if (!url || !key)
|
|
138
|
+
throw new Error("FIDACY_MODE=http requires FIDACY_API_URL and FIDACY_API_KEY");
|
|
139
|
+
return new HttpFidacyCore(url, key, process.env.FIDACY_PUBLIC_KEY_PEM ?? "");
|
|
140
|
+
}
|
|
141
|
+
return new DevFidacyCore();
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=core.js.map
|
package/dist/core.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { PaymentRequest } from "./types.js";
|
|
2
|
+
export interface Rail {
|
|
3
|
+
execute(req: PaymentRequest): Promise<{
|
|
4
|
+
railRef: string;
|
|
5
|
+
}>;
|
|
6
|
+
}
|
|
7
|
+
export declare class ReferenceRail implements Rail {
|
|
8
|
+
settlements: Array<PaymentRequest & {
|
|
9
|
+
railRef: string;
|
|
10
|
+
at: string;
|
|
11
|
+
}>;
|
|
12
|
+
execute(req: PaymentRequest): Promise<{
|
|
13
|
+
railRef: string;
|
|
14
|
+
}>;
|
|
15
|
+
}
|
|
16
|
+
export type ExecResult = {
|
|
17
|
+
status: "EXECUTED";
|
|
18
|
+
railRef: string;
|
|
19
|
+
decisionId: string;
|
|
20
|
+
} | {
|
|
21
|
+
status: "REFUSED";
|
|
22
|
+
reason: string;
|
|
23
|
+
};
|
|
24
|
+
export declare class GrantEnforcingExecutor {
|
|
25
|
+
private rail;
|
|
26
|
+
private used;
|
|
27
|
+
private pub;
|
|
28
|
+
constructor(publicKeyPem: string, rail: Rail);
|
|
29
|
+
execute(req: PaymentRequest, grant: string | undefined): Promise<ExecResult>;
|
|
30
|
+
}
|
package/dist/executor.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { createPublicKey } from "node:crypto";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
import { verify } from "./signing.js";
|
|
4
|
+
export class ReferenceRail {
|
|
5
|
+
settlements = [];
|
|
6
|
+
async execute(req) {
|
|
7
|
+
const railRef = "ref_" + randomUUID();
|
|
8
|
+
this.settlements.push({ ...req, railRef, at: new Date().toISOString() });
|
|
9
|
+
return { railRef };
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
// The enforcement point. It runs at the payment boundary and refuses any action
|
|
13
|
+
// not backed by a valid, unexpired, unused Fidacy grant bound to THIS exact
|
|
14
|
+
// request. This is what makes the firewall non-bypassable: even a correct deny
|
|
15
|
+
// is meaningless unless the executor requires the grant, and this one does.
|
|
16
|
+
export class GrantEnforcingExecutor {
|
|
17
|
+
rail;
|
|
18
|
+
used = new Set();
|
|
19
|
+
pub;
|
|
20
|
+
constructor(publicKeyPem, rail) {
|
|
21
|
+
this.rail = rail;
|
|
22
|
+
this.pub = createPublicKey(publicKeyPem);
|
|
23
|
+
}
|
|
24
|
+
async execute(req, grant) {
|
|
25
|
+
if (!grant)
|
|
26
|
+
return { status: "REFUSED", reason: "missing_grant" };
|
|
27
|
+
const dot = grant.indexOf(".");
|
|
28
|
+
if (dot < 0)
|
|
29
|
+
return { status: "REFUSED", reason: "malformed_grant" };
|
|
30
|
+
const body = grant.slice(0, dot);
|
|
31
|
+
const sig = grant.slice(dot + 1);
|
|
32
|
+
if (!verify(this.pub, body, sig))
|
|
33
|
+
return { status: "REFUSED", reason: "invalid_signature" };
|
|
34
|
+
let p;
|
|
35
|
+
try {
|
|
36
|
+
p = JSON.parse(Buffer.from(body, "base64url").toString("utf8"));
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return { status: "REFUSED", reason: "undecodable_grant" };
|
|
40
|
+
}
|
|
41
|
+
if (Date.now() > p.exp)
|
|
42
|
+
return { status: "REFUSED", reason: "grant_expired" };
|
|
43
|
+
if (this.used.has(p.decisionId))
|
|
44
|
+
return { status: "REFUSED", reason: "grant_replayed" };
|
|
45
|
+
if (p.payee !== req.payee)
|
|
46
|
+
return { status: "REFUSED", reason: "payee_mismatch" };
|
|
47
|
+
if (p.amount !== req.amount)
|
|
48
|
+
return { status: "REFUSED", reason: "amount_mismatch" };
|
|
49
|
+
if (p.currency !== req.currency)
|
|
50
|
+
return { status: "REFUSED", reason: "currency_mismatch" };
|
|
51
|
+
this.used.add(p.decisionId);
|
|
52
|
+
const { railRef } = await this.rail.execute(req);
|
|
53
|
+
return { status: "EXECUTED", railRef, decisionId: p.decisionId };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"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"}
|
package/dist/grant.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface GrantPayload {
|
|
2
|
+
decisionId: string;
|
|
3
|
+
subject: string;
|
|
4
|
+
payee: string;
|
|
5
|
+
amount: number;
|
|
6
|
+
currency: string;
|
|
7
|
+
exp: number;
|
|
8
|
+
}
|
|
9
|
+
export interface GrantCheck {
|
|
10
|
+
valid: boolean;
|
|
11
|
+
reason?: string;
|
|
12
|
+
payload?: GrantPayload;
|
|
13
|
+
}
|
|
14
|
+
export declare function verifyGrant(publicKeyPem: string, grant: string, expected: {
|
|
15
|
+
payee: string;
|
|
16
|
+
amount: number;
|
|
17
|
+
currency: string;
|
|
18
|
+
}): GrantCheck;
|
package/dist/grant.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import { verify } from "./signing.js";
|
|
3
|
+
// The non-bypass gate. A payment executor MUST call this before moving funds.
|
|
4
|
+
// It verifies the Ed25519 signature against Fidacy's pinned public key, checks
|
|
5
|
+
// expiry, and (critically) that the grant matches the payment actually about to
|
|
6
|
+
// be executed. A hallucinated or swapped payment has no valid grant and is
|
|
7
|
+
// rejected here.
|
|
8
|
+
export function verifyGrant(publicKeyPem, grant, expected) {
|
|
9
|
+
const parts = grant.split(".");
|
|
10
|
+
if (parts.length !== 2 || !parts[0] || !parts[1])
|
|
11
|
+
return { valid: false, reason: "malformed_grant" };
|
|
12
|
+
const [body, sig] = parts;
|
|
13
|
+
let pub;
|
|
14
|
+
try {
|
|
15
|
+
pub = crypto.createPublicKey(publicKeyPem);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return { valid: false, reason: "bad_public_key" };
|
|
19
|
+
}
|
|
20
|
+
if (!verify(pub, body, sig))
|
|
21
|
+
return { valid: false, reason: "invalid_signature" };
|
|
22
|
+
let payload;
|
|
23
|
+
try {
|
|
24
|
+
payload = JSON.parse(Buffer.from(body, "base64url").toString("utf8"));
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return { valid: false, reason: "undecodable_payload" };
|
|
28
|
+
}
|
|
29
|
+
if (Date.now() > payload.exp)
|
|
30
|
+
return { valid: false, reason: "grant_expired" };
|
|
31
|
+
if (payload.payee !== expected.payee)
|
|
32
|
+
return { valid: false, reason: `payee_mismatch:${payload.payee}!=${expected.payee}` };
|
|
33
|
+
if (payload.amount !== expected.amount)
|
|
34
|
+
return { valid: false, reason: `amount_mismatch:${payload.amount}!=${expected.amount}` };
|
|
35
|
+
if (payload.currency !== expected.currency)
|
|
36
|
+
return { valid: false, reason: `currency_mismatch` };
|
|
37
|
+
return { valid: true, payload };
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=grant.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grant.js","sourceRoot":"","sources":["../src/grant.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAiBtC,8EAA8E;AAC9E,+EAA+E;AAC/E,gFAAgF;AAChF,2EAA2E;AAC3E,iBAAiB;AACjB,MAAM,UAAU,WAAW,CACzB,YAAoB,EACpB,KAAa,EACb,QAA6D;IAE7D,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;IACrG,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC;IAE1B,IAAI,GAAqB,CAAC;IAC1B,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACpD,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAElF,IAAI,OAAqB,CAAC;IAC1B,IAAI,CAAC;QACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAiB,CAAC;IACxF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,qBAAqB,EAAE,CAAC;IACzD,CAAC;IAED,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG;QAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IAC/E,IAAI,OAAO,CAAC,KAAK,KAAK,QAAQ,CAAC,KAAK;QAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,kBAAkB,OAAO,CAAC,KAAK,KAAK,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC;IAC5H,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM;QAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,mBAAmB,OAAO,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;IACjI,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC,QAAQ;QAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAEjG,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAClC,CAAC"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { makeCore } from "./core.js";
|
|
6
|
+
import { assessAction, AssessError } from "./assess.js";
|
|
7
|
+
const core = makeCore();
|
|
8
|
+
const subject = process.env.FIDACY_SUBJECT ?? "agent:demo";
|
|
9
|
+
const server = new McpServer({ name: "fidacy", version: "0.1.0" });
|
|
10
|
+
// ACTION FIREWALL. The agent calls this INSTEAD of any raw payment tool.
|
|
11
|
+
// Fidacy verifies the action against the signed mandate BEFORE money can move.
|
|
12
|
+
// ALLOW returns a short-lived Ed25519 grant the executor requires.
|
|
13
|
+
// DENY returns no grant: the action is dead on arrival. Non-custodial: Fidacy
|
|
14
|
+
// authorizes, it never holds funds.
|
|
15
|
+
server.registerTool("request_payment", {
|
|
16
|
+
title: "Request Payment Authorization",
|
|
17
|
+
description: "Authorize a payment action against the active Fidacy mandate. Returns an ALLOW with a signed grant, or a DENY with the violated rule. The downstream executor MUST require the grant. Call this before any payment; never pay without it.",
|
|
18
|
+
inputSchema: {
|
|
19
|
+
payee: z.string().describe("Payee identifier"),
|
|
20
|
+
amount: z.number().positive().describe("Amount in the mandate currency"),
|
|
21
|
+
currency: z.string().length(3).describe("ISO 4217 currency code"),
|
|
22
|
+
purpose: z.string().describe("Human-readable purpose"),
|
|
23
|
+
category: z.string().describe("Purpose category (must be allowed by the mandate)"),
|
|
24
|
+
idempotencyKey: z.string().describe("Caller-supplied idempotency key"),
|
|
25
|
+
},
|
|
26
|
+
outputSchema: {
|
|
27
|
+
status: z.enum(["ALLOW", "DENY"]),
|
|
28
|
+
decisionId: z.string(),
|
|
29
|
+
grant: z.string().optional(),
|
|
30
|
+
violatedRule: z.string().optional(),
|
|
31
|
+
},
|
|
32
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
33
|
+
}, async (args) => {
|
|
34
|
+
const req = args;
|
|
35
|
+
const d = await core.decide(req, subject);
|
|
36
|
+
const out = { status: d.status, decisionId: d.decisionId, grant: d.grant, violatedRule: d.violatedRule };
|
|
37
|
+
const human = d.status === "ALLOW"
|
|
38
|
+
? `ALLOW. Grant issued (decision ${d.decisionId}). Present this grant to the executor.`
|
|
39
|
+
: `DENY. Rule violated: ${d.violatedRule}. No grant issued; this payment cannot proceed.`;
|
|
40
|
+
return { content: [{ type: "text", text: human }], structuredContent: out };
|
|
41
|
+
});
|
|
42
|
+
// Read-only: surface the guardrails so the agent/human can see the envelope and
|
|
43
|
+
// pin Fidacy's public key for grant verification.
|
|
44
|
+
server.registerTool("verify_mandate", {
|
|
45
|
+
title: "Verify Active Mandate",
|
|
46
|
+
description: "Return the active mandate envelope (caps, allowed payees/categories, window, revocation) and Fidacy's Ed25519 public key for grant verification.",
|
|
47
|
+
inputSchema: {},
|
|
48
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
49
|
+
}, async () => {
|
|
50
|
+
const m = await core.getMandate(subject);
|
|
51
|
+
const payload = { mandate: m, fidacyPublicKey: core.publicKey() };
|
|
52
|
+
return { content: [{ type: "text", text: JSON.stringify(payload, null, 2) }], structuredContent: payload };
|
|
53
|
+
});
|
|
54
|
+
// Read-only: portable, hash-chained proof for a decision. The non-repudiation
|
|
55
|
+
// artifact for audit, reinsurance, or dispute.
|
|
56
|
+
server.registerTool("get_audit_proof", {
|
|
57
|
+
title: "Get Audit Proof",
|
|
58
|
+
description: "Return the immutable, hash-chained proof for a decision id, including whether the chain is intact and the public key it verifies against.",
|
|
59
|
+
inputSchema: { decisionId: z.string().describe("Decision id returned by request_payment") },
|
|
60
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
61
|
+
}, async ({ decisionId }) => {
|
|
62
|
+
const proof = await core.getProof(decisionId);
|
|
63
|
+
if (!proof)
|
|
64
|
+
return { content: [{ type: "text", text: `No proof found for ${decisionId}` }], isError: true };
|
|
65
|
+
return { content: [{ type: "text", text: JSON.stringify(proof, null, 2) }], structuredContent: proof };
|
|
66
|
+
});
|
|
67
|
+
// VERDICT LAYER (advisory). Calls the LIVE Fidacy engine POST /v1/assess and
|
|
68
|
+
// returns the SIGNED trust verdict. This complements the payment-firewall tools
|
|
69
|
+
// above: one install of @fidacy/mcp ships both backends. assess_action moves no
|
|
70
|
+
// money; it returns a judgment whose proof (riskPayloadJws + signingKeyId) is
|
|
71
|
+
// verifiable by anyone via @fidacy/verify against the engine JWKS.
|
|
72
|
+
//
|
|
73
|
+
// Tool registration NEVER requires a key: only CALLING it without one returns a
|
|
74
|
+
// helpful error, so the server still boots with no FIDACY_ENGINE_API_KEY set.
|
|
75
|
+
server.registerTool("assess_action", {
|
|
76
|
+
title: "Assess Action (Signed Trust Verdict)",
|
|
77
|
+
description: "Return a SIGNED Fidacy trust verdict from the live engine (default https://api.fidacy.com) for a proposed action. The signed proof is `riskPayloadJws` + `signingKeyId`, verifiable by anyone via @fidacy/verify against the engine JWKS at /.well-known/jwks.json. `kind` is one of ap2_payment, message_send, voice_call, custom, claim_document; `mandate` is the action/mandate object for that kind. This is the verdict (advisory) layer and moves no money; it complements the payment-firewall tools (request_payment et al.) in the same install.",
|
|
78
|
+
inputSchema: {
|
|
79
|
+
kind: z
|
|
80
|
+
.enum(["ap2_payment", "message_send", "voice_call", "custom", "claim_document"])
|
|
81
|
+
.optional(),
|
|
82
|
+
mandate: z.record(z.unknown()),
|
|
83
|
+
mandateType: z.string().optional(),
|
|
84
|
+
idempotencyKey: z.string().optional(),
|
|
85
|
+
spendingMandate: z.record(z.unknown()).optional(),
|
|
86
|
+
a2a: z.object({ task_id: z.string() }).optional(),
|
|
87
|
+
},
|
|
88
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
89
|
+
}, async ({ kind, mandate, mandateType, idempotencyKey, spendingMandate, a2a }) => {
|
|
90
|
+
const engineUrl = process.env.FIDACY_ENGINE_URL ?? "https://api.fidacy.com";
|
|
91
|
+
const apiKey = (process.env.FIDACY_ENGINE_API_KEY ?? "").trim();
|
|
92
|
+
if (!apiKey) {
|
|
93
|
+
return {
|
|
94
|
+
content: [
|
|
95
|
+
{
|
|
96
|
+
type: "text",
|
|
97
|
+
text: "assess_action requires FIDACY_ENGINE_API_KEY (an fky_live_/fky_test_ key with assess:write). Set it to enable signed verdicts.",
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
isError: true,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
const r = await assessAction({ kind, mandate, mandateType, idempotencyKey, spendingMandate, a2a }, { engineUrl, apiKey });
|
|
105
|
+
return {
|
|
106
|
+
content: [{ type: "text", text: `${r.decision} (score ${r.score}) signed by ${r.signingKeyId}` }],
|
|
107
|
+
structuredContent: r,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
catch (e) {
|
|
111
|
+
if (e instanceof AssessError) {
|
|
112
|
+
const reasons = e.rejection_reasons?.length
|
|
113
|
+
? " (" + e.rejection_reasons.map((x) => x.key).join(",") + ")"
|
|
114
|
+
: "";
|
|
115
|
+
return {
|
|
116
|
+
content: [{ type: "text", text: `ASSESS ${e.status}: ${e.type}${reasons}` }],
|
|
117
|
+
isError: true,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
content: [{ type: "text", text: "ASSESS failed: unexpected error" }],
|
|
122
|
+
isError: true,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
async function main() {
|
|
127
|
+
const transport = new StdioServerTransport();
|
|
128
|
+
await server.connect(transport);
|
|
129
|
+
console.error("[fidacy] action firewall running on stdio");
|
|
130
|
+
}
|
|
131
|
+
main().catch((e) => {
|
|
132
|
+
console.error("[fidacy] fatal:", e);
|
|
133
|
+
process.exit(1);
|
|
134
|
+
});
|
|
135
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/lib.d.ts
ADDED
package/dist/lib.js
ADDED
package/dist/lib.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lib.js","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { KeyObject } from "node:crypto";
|
|
2
|
+
export declare function loadOrGenerateKeyPair(): {
|
|
3
|
+
privateKey: KeyObject;
|
|
4
|
+
publicKey: KeyObject;
|
|
5
|
+
ephemeral: boolean;
|
|
6
|
+
};
|
|
7
|
+
export declare function publicKeyPem(publicKey: KeyObject): string;
|
|
8
|
+
export declare function sign(privateKey: KeyObject, message: string): string;
|
|
9
|
+
export declare function verify(publicKey: KeyObject, message: string, signatureB64url: string): boolean;
|
|
10
|
+
export declare function sha256(input: string): string;
|
package/dist/signing.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
// Ed25519 keypair for the co-signature (the "grant"). Non-custodial: this key
|
|
3
|
+
// authorizes actions, it never touches funds.
|
|
4
|
+
export function loadOrGenerateKeyPair() {
|
|
5
|
+
const b64 = process.env.FIDACY_SIGNING_KEY_B64;
|
|
6
|
+
if (b64) {
|
|
7
|
+
const pem = Buffer.from(b64, "base64").toString("utf8");
|
|
8
|
+
const privateKey = crypto.createPrivateKey(pem);
|
|
9
|
+
const publicKey = crypto.createPublicKey(privateKey);
|
|
10
|
+
return { privateKey, publicKey, ephemeral: false };
|
|
11
|
+
}
|
|
12
|
+
const { privateKey, publicKey } = crypto.generateKeyPairSync("ed25519");
|
|
13
|
+
return { privateKey, publicKey, ephemeral: true };
|
|
14
|
+
}
|
|
15
|
+
export function publicKeyPem(publicKey) {
|
|
16
|
+
return publicKey.export({ type: "spki", format: "pem" }).toString();
|
|
17
|
+
}
|
|
18
|
+
export function sign(privateKey, message) {
|
|
19
|
+
return crypto.sign(null, Buffer.from(message, "utf8"), privateKey).toString("base64url");
|
|
20
|
+
}
|
|
21
|
+
export function verify(publicKey, message, signatureB64url) {
|
|
22
|
+
try {
|
|
23
|
+
return crypto.verify(null, Buffer.from(message, "utf8"), publicKey, Buffer.from(signatureB64url, "base64url"));
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export function sha256(input) {
|
|
30
|
+
return crypto.createHash("sha256").update(input).digest("hex");
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=signing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signing.js","sourceRoot":"","sources":["../src/signing.ts"],"names":[],"mappings":"AAAA,OAAO,MAAqB,MAAM,aAAa,CAAC;AAEhD,8EAA8E;AAC9E,8CAA8C;AAC9C,MAAM,UAAU,qBAAqB;IACnC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC;IAC/C,IAAI,GAAG,EAAE,CAAC;QACR,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACxD,MAAM,UAAU,GAAG,MAAM,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;QAChD,MAAM,SAAS,GAAG,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;QACrD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IACrD,CAAC;IACD,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC;IACxE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,SAAoB;IAC/C,OAAO,SAAS,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;AACtE,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,UAAqB,EAAE,OAAe;IACzD,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAC3F,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,SAAoB,EAAE,OAAe,EAAE,eAAuB;IACnF,IAAI,CAAC;QACH,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,WAAW,CAAC,CAAC,CAAC;IACjH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,KAAa;IAClC,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACjE,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export type Mandate = {
|
|
2
|
+
id: string;
|
|
3
|
+
subject: string;
|
|
4
|
+
version: string;
|
|
5
|
+
allow: {
|
|
6
|
+
payees: string[];
|
|
7
|
+
categories: string[];
|
|
8
|
+
currency: string;
|
|
9
|
+
maxTotal: number;
|
|
10
|
+
perTxMax: number;
|
|
11
|
+
};
|
|
12
|
+
window: {
|
|
13
|
+
notBefore: string;
|
|
14
|
+
notAfter: string;
|
|
15
|
+
};
|
|
16
|
+
revoked: boolean;
|
|
17
|
+
};
|
|
18
|
+
export type PaymentRequest = {
|
|
19
|
+
payee: string;
|
|
20
|
+
amount: number;
|
|
21
|
+
currency: string;
|
|
22
|
+
purpose: string;
|
|
23
|
+
category: string;
|
|
24
|
+
idempotencyKey: string;
|
|
25
|
+
};
|
|
26
|
+
export type DecisionStatus = "ALLOW" | "DENY";
|
|
27
|
+
export type Decision = {
|
|
28
|
+
decisionId: string;
|
|
29
|
+
status: DecisionStatus;
|
|
30
|
+
subject: string;
|
|
31
|
+
mandateId: string;
|
|
32
|
+
request: PaymentRequest;
|
|
33
|
+
violatedRule?: string;
|
|
34
|
+
grant?: string;
|
|
35
|
+
ts: string;
|
|
36
|
+
};
|
|
37
|
+
export type AuditRecord = {
|
|
38
|
+
seq: number;
|
|
39
|
+
decisionId: string;
|
|
40
|
+
status: DecisionStatus;
|
|
41
|
+
subject: string;
|
|
42
|
+
digest: string;
|
|
43
|
+
prevHash: string;
|
|
44
|
+
hash: string;
|
|
45
|
+
ts: string;
|
|
46
|
+
};
|
|
47
|
+
export type AuditProof = {
|
|
48
|
+
record: AuditRecord;
|
|
49
|
+
chainIntact: boolean;
|
|
50
|
+
verifiedAgainstPublicKey: string;
|
|
51
|
+
};
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/dist/util.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function stableStringify(obj: unknown): string;
|
package/dist/util.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function stableStringify(obj) {
|
|
2
|
+
if (obj === null || typeof obj !== "object")
|
|
3
|
+
return JSON.stringify(obj);
|
|
4
|
+
if (Array.isArray(obj))
|
|
5
|
+
return "[" + obj.map(stableStringify).join(",") + "]";
|
|
6
|
+
const keys = Object.keys(obj).sort();
|
|
7
|
+
return "{" + keys.map((k) => JSON.stringify(k) + ":" + stableStringify(obj[k])).join(",") + "}";
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=util.js.map
|
package/dist/util.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,eAAe,CAAC,GAAY;IAC1C,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IACxE,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;IAC9E,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,GAA8B,CAAC,CAAC,IAAI,EAAE,CAAC;IAChE,OAAO,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,eAAe,CAAE,GAA+B,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;AAC/H,CAAC"}
|