@aroha-sdk/credentials 1.0.0 → 1.2.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/dist/credentials.d.ts +53 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +117 -0
- package/dist/credentials.js.map +1 -0
- package/dist/credentials.test.d.ts +2 -0
- package/dist/credentials.test.d.ts.map +1 -0
- package/dist/credentials.test.js +69 -0
- package/dist/credentials.test.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/mandate.d.ts +59 -0
- package/dist/mandate.d.ts.map +1 -0
- package/dist/mandate.js +180 -0
- package/dist/mandate.js.map +1 -0
- package/dist/mandate.test.d.ts +2 -0
- package/dist/mandate.test.d.ts.map +1 -0
- package/dist/mandate.test.js +222 -0
- package/dist/mandate.test.js.map +1 -0
- package/dist/middleware.d.ts +53 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +227 -0
- package/dist/middleware.js.map +1 -0
- package/dist/rbac.d.ts +22 -0
- package/dist/rbac.d.ts.map +1 -0
- package/dist/rbac.js +50 -0
- package/dist/rbac.js.map +1 -0
- package/dist/rbac.test.d.ts +2 -0
- package/dist/rbac.test.d.ts.map +1 -0
- package/dist/rbac.test.js +97 -0
- package/dist/rbac.test.js.map +1 -0
- package/dist/registry.d.ts +125 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +227 -0
- package/dist/registry.js.map +1 -0
- package/dist/registry.test.d.ts +2 -0
- package/dist/registry.test.d.ts.map +1 -0
- package/dist/registry.test.js +142 -0
- package/dist/registry.test.js.map +1 -0
- package/dist/types.d.ts +19 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/package.json +5 -1
- package/tsconfig.json +0 -12
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import * as ed from "@noble/ed25519";
|
|
3
|
+
import { sha512 } from "@noble/hashes/sha512";
|
|
4
|
+
import { issueIntentMandate, attenuateToCart, attenuateToPayment, verifyMandate, } from "./mandate.js";
|
|
5
|
+
ed.etc.sha512Sync = (...m) => sha512(...m);
|
|
6
|
+
async function makeKey() {
|
|
7
|
+
const priv = ed.utils.randomPrivateKey();
|
|
8
|
+
const pub = await ed.getPublicKeyAsync(priv);
|
|
9
|
+
return { priv, pub };
|
|
10
|
+
}
|
|
11
|
+
const BASE = {
|
|
12
|
+
spendLimitUsd: 500,
|
|
13
|
+
sessionLimitUsd: 200,
|
|
14
|
+
requireHumanApprovalAboveUsd: 100,
|
|
15
|
+
allowedMerchants: ["merchant-a", "merchant-b", "merchant-c"],
|
|
16
|
+
};
|
|
17
|
+
// ─── issueIntentMandate ───────────────────────────────────────────────────────
|
|
18
|
+
describe("issueIntentMandate", () => {
|
|
19
|
+
it("issues a mandate with correct fields", async () => {
|
|
20
|
+
const k = await makeKey();
|
|
21
|
+
const m = await issueIntentMandate("did:aroha:grantor", "did:aroha:grantee", BASE, k.priv);
|
|
22
|
+
expect(m.mandate.mandateTier).toBe("intent");
|
|
23
|
+
expect(m.mandate.grantor).toBe("did:aroha:grantor");
|
|
24
|
+
expect(m.mandate.grantee).toBe("did:aroha:grantee");
|
|
25
|
+
expect(m.mandate.parentMandateId).toBeNull();
|
|
26
|
+
expect(m.mandate.mandateId).toBeTruthy();
|
|
27
|
+
expect(new Date(m.mandate.expiresAt) > new Date()).toBe(true);
|
|
28
|
+
expect(m.token).toBeTruthy();
|
|
29
|
+
expect(m.signature).toBeTruthy();
|
|
30
|
+
});
|
|
31
|
+
it("respects custom ttlMs", async () => {
|
|
32
|
+
const k = await makeKey();
|
|
33
|
+
const before = Date.now();
|
|
34
|
+
const m = await issueIntentMandate("did:aroha:g", "did:aroha:e", BASE, k.priv, 10_000);
|
|
35
|
+
const expMs = new Date(m.mandate.expiresAt).getTime();
|
|
36
|
+
expect(expMs - before).toBeGreaterThan(9_000);
|
|
37
|
+
expect(expMs - before).toBeLessThan(11_000);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
// ─── verifyMandate ────────────────────────────────────────────────────────────
|
|
41
|
+
describe("verifyMandate", () => {
|
|
42
|
+
it("accepts a valid token", async () => {
|
|
43
|
+
const k = await makeKey();
|
|
44
|
+
const m = await issueIntentMandate("did:aroha:g", "did:aroha:e", BASE, k.priv);
|
|
45
|
+
const r = await verifyMandate(m.token, k.pub);
|
|
46
|
+
expect(r.valid).toBe(true);
|
|
47
|
+
expect(r.mandate?.mandateId).toBe(m.mandate.mandateId);
|
|
48
|
+
});
|
|
49
|
+
it("rejects a token signed by a different key", async () => {
|
|
50
|
+
const k = await makeKey();
|
|
51
|
+
const other = await makeKey();
|
|
52
|
+
const m = await issueIntentMandate("did:aroha:g", "did:aroha:e", BASE, k.priv);
|
|
53
|
+
const r = await verifyMandate(m.token, other.pub);
|
|
54
|
+
expect(r.valid).toBe(false);
|
|
55
|
+
expect(r.reason).toMatch(/signature/i);
|
|
56
|
+
});
|
|
57
|
+
it("rejects an expired mandate", async () => {
|
|
58
|
+
const k = await makeKey();
|
|
59
|
+
const m = await issueIntentMandate("did:aroha:g", "did:aroha:e", BASE, k.priv, -1);
|
|
60
|
+
const r = await verifyMandate(m.token, k.pub);
|
|
61
|
+
expect(r.valid).toBe(false);
|
|
62
|
+
expect(r.reason).toMatch(/expired/i);
|
|
63
|
+
});
|
|
64
|
+
it("rejects grantee mismatch", async () => {
|
|
65
|
+
const k = await makeKey();
|
|
66
|
+
const m = await issueIntentMandate("did:aroha:g", "did:aroha:e", BASE, k.priv);
|
|
67
|
+
const r = await verifyMandate(m.token, k.pub, "did:aroha:someone-else");
|
|
68
|
+
expect(r.valid).toBe(false);
|
|
69
|
+
expect(r.reason).toMatch(/grantee/i);
|
|
70
|
+
});
|
|
71
|
+
it("rejects malformed token", async () => {
|
|
72
|
+
const k = await makeKey();
|
|
73
|
+
const r = await verifyMandate("not!!valid!!base64url", k.pub);
|
|
74
|
+
expect(r.valid).toBe(false);
|
|
75
|
+
expect(r.reason).toMatch(/malformed/i);
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
// ─── attenuateToCart — narrowing enforcement ──────────────────────────────────
|
|
79
|
+
describe("attenuateToCart narrowing", () => {
|
|
80
|
+
async function intent() {
|
|
81
|
+
const k = await makeKey();
|
|
82
|
+
const m = await issueIntentMandate("did:aroha:user", "did:aroha:agent", BASE, k.priv);
|
|
83
|
+
return [m, k.priv, k.pub];
|
|
84
|
+
}
|
|
85
|
+
it("allows valid narrowing", async () => {
|
|
86
|
+
const [parent, agentKey] = await intent();
|
|
87
|
+
const narrow = {
|
|
88
|
+
spendLimitUsd: 100,
|
|
89
|
+
sessionLimitUsd: 50,
|
|
90
|
+
requireHumanApprovalAboveUsd: 50,
|
|
91
|
+
allowedMerchants: ["merchant-a"],
|
|
92
|
+
};
|
|
93
|
+
await expect(attenuateToCart(parent, "did:aroha:provider", narrow, agentKey)).resolves.toBeDefined();
|
|
94
|
+
});
|
|
95
|
+
it("rejects spendLimitUsd widening", async () => {
|
|
96
|
+
const [parent, agentKey] = await intent();
|
|
97
|
+
await expect(attenuateToCart(parent, "did:aroha:p", { spendLimitUsd: 1000 }, agentKey)).rejects.toThrow(/spendLimit/i);
|
|
98
|
+
});
|
|
99
|
+
it("rejects sessionLimitUsd widening", async () => {
|
|
100
|
+
const [parent, agentKey] = await intent();
|
|
101
|
+
await expect(attenuateToCart(parent, "did:aroha:p", { spendLimitUsd: 100, sessionLimitUsd: 999 }, agentKey)).rejects.toThrow(/sessionLimit/i);
|
|
102
|
+
});
|
|
103
|
+
it("rejects requireHumanApprovalAboveUsd widening", async () => {
|
|
104
|
+
const [parent, agentKey] = await intent();
|
|
105
|
+
await expect(attenuateToCart(parent, "did:aroha:p", { spendLimitUsd: 100, requireHumanApprovalAboveUsd: 999 }, agentKey)).rejects.toThrow(/approval threshold/i);
|
|
106
|
+
});
|
|
107
|
+
it("rejects allowedMerchants with unlisted merchant", async () => {
|
|
108
|
+
const [parent, agentKey] = await intent();
|
|
109
|
+
await expect(attenuateToCart(parent, "did:aroha:p", {
|
|
110
|
+
spendLimitUsd: 100,
|
|
111
|
+
allowedMerchants: ["merchant-a", "merchant-unknown"],
|
|
112
|
+
}, agentKey)).rejects.toThrow(/allowedMerchants/i);
|
|
113
|
+
});
|
|
114
|
+
it("rejects empty allowedMerchants when parent restricts", async () => {
|
|
115
|
+
const [parent, agentKey] = await intent();
|
|
116
|
+
await expect(attenuateToCart(parent, "did:aroha:p", {
|
|
117
|
+
spendLimitUsd: 100,
|
|
118
|
+
allowedMerchants: [],
|
|
119
|
+
}, agentKey)).rejects.toThrow(/allowedMerchants/i);
|
|
120
|
+
});
|
|
121
|
+
it("rejects missing allowedMerchants when parent restricts", async () => {
|
|
122
|
+
const [parent, agentKey] = await intent();
|
|
123
|
+
await expect(attenuateToCart(parent, "did:aroha:p", { spendLimitUsd: 100 }, agentKey)).rejects.toThrow(/allowedMerchants/i);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
// ─── attenuateToPayment — narrowing enforcement ───────────────────────────────
|
|
127
|
+
describe("attenuateToPayment narrowing", () => {
|
|
128
|
+
it("rejects spendLimitUsd widening from cart", async () => {
|
|
129
|
+
const intentKey = await makeKey();
|
|
130
|
+
const cartKey = await makeKey();
|
|
131
|
+
const intent = await issueIntentMandate("did:aroha:user", "did:aroha:agent", BASE, intentKey.priv);
|
|
132
|
+
const cart = await attenuateToCart(intent, "did:aroha:provider", {
|
|
133
|
+
spendLimitUsd: 100, allowedMerchants: ["merchant-a"],
|
|
134
|
+
}, intentKey.priv);
|
|
135
|
+
await expect(attenuateToPayment(cart, "did:aroha:processor", { spendLimitUsd: 999 }, cartKey.priv)).rejects.toThrow(/spendLimit/i);
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
// ─── Full chain: intent → cart → payment ─────────────────────────────────────
|
|
139
|
+
describe("full delegation chain", () => {
|
|
140
|
+
it("intent → cart → payment verifies end-to-end", async () => {
|
|
141
|
+
const userKey = await makeKey();
|
|
142
|
+
const agentKey = await makeKey();
|
|
143
|
+
const providerKey = await makeKey();
|
|
144
|
+
const intent = await issueIntentMandate("did:aroha:user", "did:aroha:agent", BASE, userKey.priv);
|
|
145
|
+
const cart = await attenuateToCart(intent, "did:aroha:provider", {
|
|
146
|
+
spendLimitUsd: 100,
|
|
147
|
+
allowedMerchants: ["merchant-a"],
|
|
148
|
+
}, userKey.priv);
|
|
149
|
+
const payment = await attenuateToPayment(cart, "did:aroha:processor", {
|
|
150
|
+
spendLimitUsd: 42,
|
|
151
|
+
allowedMerchants: ["merchant-a"],
|
|
152
|
+
}, userKey.priv);
|
|
153
|
+
expect(payment.mandate.mandateTier).toBe("payment");
|
|
154
|
+
expect(payment.mandate.parentMandateId).toBe(cart.mandate.mandateId);
|
|
155
|
+
expect(payment.mandate.constraints.spendLimitUsd).toBe(42);
|
|
156
|
+
const r = await verifyMandate(payment.token, userKey.pub, "did:aroha:processor");
|
|
157
|
+
expect(r.valid).toBe(true);
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
describe("assertNarrowing — merchantCategory", () => {
|
|
161
|
+
it("allows child to keep same merchantCategory", async () => {
|
|
162
|
+
const k = await makeKey();
|
|
163
|
+
const parent = await issueIntentMandate("did:aroha:g", "did:aroha:e", {
|
|
164
|
+
spendLimitUsd: 500,
|
|
165
|
+
merchantCategory: "travel",
|
|
166
|
+
}, k.priv);
|
|
167
|
+
await expect(attenuateToCart(parent, "did:aroha:p", { spendLimitUsd: 100, merchantCategory: "travel" }, k.priv)).resolves.toBeDefined();
|
|
168
|
+
});
|
|
169
|
+
it("rejects child setting merchantCategory to null when parent restricts it", async () => {
|
|
170
|
+
const k = await makeKey();
|
|
171
|
+
const parent = await issueIntentMandate("did:aroha:g", "did:aroha:e", {
|
|
172
|
+
spendLimitUsd: 500,
|
|
173
|
+
merchantCategory: "travel",
|
|
174
|
+
}, k.priv);
|
|
175
|
+
await expect(attenuateToCart(parent, "did:aroha:p", { spendLimitUsd: 100, merchantCategory: null }, k.priv)).rejects.toThrow(/merchantCategory/i);
|
|
176
|
+
});
|
|
177
|
+
it("rejects child setting different merchantCategory", async () => {
|
|
178
|
+
const k = await makeKey();
|
|
179
|
+
const parent = await issueIntentMandate("did:aroha:g", "did:aroha:e", {
|
|
180
|
+
spendLimitUsd: 500,
|
|
181
|
+
merchantCategory: "travel",
|
|
182
|
+
}, k.priv);
|
|
183
|
+
await expect(attenuateToCart(parent, "did:aroha:p", { spendLimitUsd: 100, merchantCategory: "food" }, k.priv)).rejects.toThrow(/merchantCategory/i);
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
describe("assertNarrowing — validUntil / validFrom", () => {
|
|
187
|
+
const future = (offsetMs) => new Date(Date.now() + offsetMs).toISOString();
|
|
188
|
+
it("rejects child validUntil beyond parent validUntil", async () => {
|
|
189
|
+
const k = await makeKey();
|
|
190
|
+
const parent = await issueIntentMandate("did:aroha:g", "did:aroha:e", {
|
|
191
|
+
spendLimitUsd: 500,
|
|
192
|
+
validUntil: future(3_600_000), // 1 hour
|
|
193
|
+
}, k.priv);
|
|
194
|
+
await expect(attenuateToCart(parent, "did:aroha:p", {
|
|
195
|
+
spendLimitUsd: 100,
|
|
196
|
+
validUntil: future(7_200_000), // 2 hours — wider
|
|
197
|
+
}, k.priv)).rejects.toThrow(/validUntil/i);
|
|
198
|
+
});
|
|
199
|
+
it("allows child validUntil within parent window", async () => {
|
|
200
|
+
const k = await makeKey();
|
|
201
|
+
const parent = await issueIntentMandate("did:aroha:g", "did:aroha:e", {
|
|
202
|
+
spendLimitUsd: 500,
|
|
203
|
+
validUntil: future(3_600_000),
|
|
204
|
+
}, k.priv);
|
|
205
|
+
await expect(attenuateToCart(parent, "did:aroha:p", {
|
|
206
|
+
spendLimitUsd: 100,
|
|
207
|
+
validUntil: future(1_800_000), // 30 min — narrower
|
|
208
|
+
}, k.priv)).resolves.toBeDefined();
|
|
209
|
+
});
|
|
210
|
+
it("rejects child validFrom before parent validFrom", async () => {
|
|
211
|
+
const k = await makeKey();
|
|
212
|
+
const parent = await issueIntentMandate("did:aroha:g", "did:aroha:e", {
|
|
213
|
+
spendLimitUsd: 500,
|
|
214
|
+
validFrom: future(3_600_000),
|
|
215
|
+
}, k.priv);
|
|
216
|
+
await expect(attenuateToCart(parent, "did:aroha:p", {
|
|
217
|
+
spendLimitUsd: 100,
|
|
218
|
+
validFrom: future(1_800_000), // starts earlier than parent — wider
|
|
219
|
+
}, k.priv)).rejects.toThrow(/validFrom/i);
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
//# sourceMappingURL=mandate.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mandate.test.js","sourceRoot":"","sources":["../src/mandate.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @aroha-sdk/credentials — ArohaServer middleware and HTTP route helpers
|
|
3
|
+
*
|
|
4
|
+
* Wire RBAC and the credential registry into ArohaServer without coupling
|
|
5
|
+
* aroha-core to this package.
|
|
6
|
+
*
|
|
7
|
+
* import { createRbacMiddleware, credentialRegistryRoutes } from "@aroha-sdk/credentials";
|
|
8
|
+
*
|
|
9
|
+
* const server = new ArohaServer({
|
|
10
|
+
* ...
|
|
11
|
+
* middleware: [createRbacMiddleware(policy)],
|
|
12
|
+
* httpRoutes: credentialRegistryRoutes(registry, { resolveIssuerPublicKey }),
|
|
13
|
+
* });
|
|
14
|
+
*/
|
|
15
|
+
import { type ArohaMiddleware, type ArohaHttpRoute } from "@aroha-sdk/core";
|
|
16
|
+
import { CredentialRegistry } from "./registry.js";
|
|
17
|
+
import { type RbacPolicy } from "./rbac.js";
|
|
18
|
+
/**
|
|
19
|
+
* Create a ArohaServer middleware that enforces RBAC on every inbound message.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* server = new ArohaServer({
|
|
23
|
+
* middleware: [createRbacMiddleware({
|
|
24
|
+
* resolveAgentRoles: async (did) => agentRoles.get(did) ?? [],
|
|
25
|
+
* resolveIssuerPublicKey: async (did) => issuerKeys.get(did) ?? null,
|
|
26
|
+
* })],
|
|
27
|
+
* });
|
|
28
|
+
*/
|
|
29
|
+
export declare function createRbacMiddleware(policy: RbacPolicy): ArohaMiddleware;
|
|
30
|
+
export interface CredentialRegistryRouteOptions {
|
|
31
|
+
/**
|
|
32
|
+
* Resolve the issuer's public key for signature verification on register/revoke.
|
|
33
|
+
* When omitted, credentials are stored without signature verification.
|
|
34
|
+
*/
|
|
35
|
+
resolveIssuerPublicKey?: (issuerDID: string) => Promise<Uint8Array | null>;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Returns ArohaHttpRoute[] that mount credential registry endpoints on ArohaServer.
|
|
39
|
+
*
|
|
40
|
+
* Endpoints added:
|
|
41
|
+
* POST /aroha/credentials — register a credential
|
|
42
|
+
* GET /aroha/credentials/:id — resolve by ID
|
|
43
|
+
* GET /aroha/credentials?userId= — list by user
|
|
44
|
+
* DELETE /aroha/credentials/:id — revoke (requires X-Revoke-Proof header)
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* const registry = new CredentialRegistry();
|
|
48
|
+
* const server = new ArohaServer({
|
|
49
|
+
* httpRoutes: credentialRegistryRoutes(registry, { resolveIssuerPublicKey }),
|
|
50
|
+
* });
|
|
51
|
+
*/
|
|
52
|
+
export declare function credentialRegistryRoutes(registry: CredentialRegistry, opts?: CredentialRegistryRouteOptions): ArohaHttpRoute[];
|
|
53
|
+
//# sourceMappingURL=middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAsB,KAAK,eAAe,EAAE,KAAK,cAAc,EAAY,MAAM,iBAAiB,CAAC;AAE1G,OAAO,EAAqB,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACtE,OAAO,EAAmE,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAM7G;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,UAAU,GAAG,eAAe,CASxE;AAmED,MAAM,WAAW,8BAA8B;IAC7C;;;OAGG;IACH,sBAAsB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;CAC5E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,kBAAkB,EAC5B,IAAI,GAAE,8BAAmC,GACxC,cAAc,EAAE,CAuBlB"}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @aroha-sdk/credentials — ArohaServer middleware and HTTP route helpers
|
|
3
|
+
*
|
|
4
|
+
* Wire RBAC and the credential registry into ArohaServer without coupling
|
|
5
|
+
* aroha-core to this package.
|
|
6
|
+
*
|
|
7
|
+
* import { createRbacMiddleware, credentialRegistryRoutes } from "@aroha-sdk/credentials";
|
|
8
|
+
*
|
|
9
|
+
* const server = new ArohaServer({
|
|
10
|
+
* ...
|
|
11
|
+
* middleware: [createRbacMiddleware(policy)],
|
|
12
|
+
* httpRoutes: credentialRegistryRoutes(registry, { resolveIssuerPublicKey }),
|
|
13
|
+
* });
|
|
14
|
+
*/
|
|
15
|
+
import { readBody } from "@aroha-sdk/core";
|
|
16
|
+
import { verifyHumanCredential, deserializeCredential, serializeCredential } from "./credentials.js";
|
|
17
|
+
import { verifyRevokeProof } from "./registry.js";
|
|
18
|
+
import { checkPermission, actionForMessageType, DEFAULT_RBAC_PERMISSIONS } from "./rbac.js";
|
|
19
|
+
// ─── RBAC middleware ──────────────────────────────────────────────────────────
|
|
20
|
+
/**
|
|
21
|
+
* Create a ArohaServer middleware that enforces RBAC on every inbound message.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* server = new ArohaServer({
|
|
25
|
+
* middleware: [createRbacMiddleware({
|
|
26
|
+
* resolveAgentRoles: async (did) => agentRoles.get(did) ?? [],
|
|
27
|
+
* resolveIssuerPublicKey: async (did) => issuerKeys.get(did) ?? null,
|
|
28
|
+
* })],
|
|
29
|
+
* });
|
|
30
|
+
*/
|
|
31
|
+
export function createRbacMiddleware(policy) {
|
|
32
|
+
return async (envelope, reject) => {
|
|
33
|
+
const result = await checkRbac(envelope, policy);
|
|
34
|
+
if (!result.allowed) {
|
|
35
|
+
const status = result.unauthorized ? 401 : 403;
|
|
36
|
+
const code = result.unauthorized ? "Aroha_UNAUTHORIZED" : "Aroha_FORBIDDEN";
|
|
37
|
+
reject(status, code, result.reason ?? "Access denied");
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
async function checkRbac(envelope, policy) {
|
|
42
|
+
const action = actionForMessageType(envelope.type);
|
|
43
|
+
if (!action)
|
|
44
|
+
return { allowed: true }; // acks and responses skip RBAC
|
|
45
|
+
const permissions = policy.permissions ?? DEFAULT_RBAC_PERMISSIONS;
|
|
46
|
+
const body = envelope.body;
|
|
47
|
+
const credentialId = body?.credentialId;
|
|
48
|
+
const credentialToken = body?.credentialToken;
|
|
49
|
+
let roles;
|
|
50
|
+
if (credentialId) {
|
|
51
|
+
if (!policy.credentialRegistry) {
|
|
52
|
+
return { allowed: false, unauthorized: true, reason: "credentialId supplied but no credential registry configured" };
|
|
53
|
+
}
|
|
54
|
+
const cred = await policy.credentialRegistry.resolve(credentialId);
|
|
55
|
+
if (!cred) {
|
|
56
|
+
return { allowed: false, unauthorized: true, reason: `Credential not found or expired: ${credentialId}` };
|
|
57
|
+
}
|
|
58
|
+
if (policy.resolveIssuerPublicKey) {
|
|
59
|
+
const issuerPubKey = await policy.resolveIssuerPublicKey(cred.issuerDID);
|
|
60
|
+
if (issuerPubKey) {
|
|
61
|
+
const token = serializeCredential(cred);
|
|
62
|
+
const verifyResult = await verifyHumanCredential(token, issuerPubKey);
|
|
63
|
+
if (!verifyResult.valid) {
|
|
64
|
+
return { allowed: false, unauthorized: true, reason: `Registry credential signature invalid: ${verifyResult.reason}` };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
roles = cred.roles;
|
|
69
|
+
}
|
|
70
|
+
else if (credentialToken) {
|
|
71
|
+
if (!policy.resolveIssuerPublicKey) {
|
|
72
|
+
return { allowed: false, unauthorized: true, reason: "Server does not accept human credentials (no resolveIssuerPublicKey configured)" };
|
|
73
|
+
}
|
|
74
|
+
const parsed = deserializeCredential(credentialToken);
|
|
75
|
+
if (!parsed) {
|
|
76
|
+
return { allowed: false, unauthorized: true, reason: "credentialToken is malformed" };
|
|
77
|
+
}
|
|
78
|
+
const issuerPubKey = await policy.resolveIssuerPublicKey(parsed.issuerDID);
|
|
79
|
+
if (!issuerPubKey) {
|
|
80
|
+
return { allowed: false, unauthorized: true, reason: `Unknown credential issuer: ${parsed.issuerDID}` };
|
|
81
|
+
}
|
|
82
|
+
const verifyResult = await verifyHumanCredential(credentialToken, issuerPubKey);
|
|
83
|
+
if (!verifyResult.valid) {
|
|
84
|
+
return { allowed: false, unauthorized: true, reason: verifyResult.reason };
|
|
85
|
+
}
|
|
86
|
+
roles = verifyResult.credential.roles;
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
roles = await policy.resolveAgentRoles(envelope.from);
|
|
90
|
+
if (roles.length === 0) {
|
|
91
|
+
return { allowed: false, unauthorized: false, reason: `Agent ${envelope.from} has no assigned roles` };
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const result = checkPermission(roles, action, permissions);
|
|
95
|
+
return { allowed: result.allowed, reason: result.reason };
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Returns ArohaHttpRoute[] that mount credential registry endpoints on ArohaServer.
|
|
99
|
+
*
|
|
100
|
+
* Endpoints added:
|
|
101
|
+
* POST /aroha/credentials — register a credential
|
|
102
|
+
* GET /aroha/credentials/:id — resolve by ID
|
|
103
|
+
* GET /aroha/credentials?userId= — list by user
|
|
104
|
+
* DELETE /aroha/credentials/:id — revoke (requires X-Revoke-Proof header)
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* const registry = new CredentialRegistry();
|
|
108
|
+
* const server = new ArohaServer({
|
|
109
|
+
* httpRoutes: credentialRegistryRoutes(registry, { resolveIssuerPublicKey }),
|
|
110
|
+
* });
|
|
111
|
+
*/
|
|
112
|
+
export function credentialRegistryRoutes(registry, opts = {}) {
|
|
113
|
+
return [
|
|
114
|
+
{
|
|
115
|
+
method: "POST",
|
|
116
|
+
test: (url) => url === "/aroha/credentials",
|
|
117
|
+
handle: (req, res) => handleRegister(req, res, registry, opts),
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
method: "DELETE",
|
|
121
|
+
test: (url) => /^\/aroha\/credentials\/[^?/]+$/.test(url),
|
|
122
|
+
handle: (req, res) => handleRevoke(req, res, registry, opts),
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
method: "GET",
|
|
126
|
+
test: (url) => /^\/aroha\/credentials\/[^?/]+$/.test(url),
|
|
127
|
+
handle: (req, res) => handleResolve(req, res, registry),
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
method: "GET",
|
|
131
|
+
test: (url) => url === "/aroha/credentials" || url.startsWith("/aroha/credentials?"),
|
|
132
|
+
handle: (req, res) => handleList(req, res, registry),
|
|
133
|
+
},
|
|
134
|
+
];
|
|
135
|
+
}
|
|
136
|
+
// ─── Route handlers ───────────────────────────────────────────────────────────
|
|
137
|
+
async function handleRegister(req, res, registry, opts) {
|
|
138
|
+
const body = await readBody(req).catch(() => null);
|
|
139
|
+
if (!body) {
|
|
140
|
+
res.writeHead(400);
|
|
141
|
+
res.end(JSON.stringify({ error: "Invalid body" }));
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
let cred;
|
|
145
|
+
try {
|
|
146
|
+
cred = JSON.parse(body);
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
res.writeHead(400);
|
|
150
|
+
res.end(JSON.stringify({ error: "Invalid JSON" }));
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
if (opts.resolveIssuerPublicKey) {
|
|
154
|
+
const pubKey = await opts.resolveIssuerPublicKey(cred.issuerDID);
|
|
155
|
+
if (!pubKey) {
|
|
156
|
+
res.writeHead(401);
|
|
157
|
+
res.end(JSON.stringify({ error: `Unknown credential issuer: ${cred.issuerDID}` }));
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const ok = await registry.register(cred, pubKey);
|
|
161
|
+
if (!ok) {
|
|
162
|
+
res.writeHead(400);
|
|
163
|
+
res.end(JSON.stringify({ error: "Credential signature invalid" }));
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
registry.registerTrusted(cred);
|
|
169
|
+
}
|
|
170
|
+
res.writeHead(201, { "Content-Type": "application/json" });
|
|
171
|
+
res.end(JSON.stringify({ credentialId: cred.credentialId, stored: true }));
|
|
172
|
+
}
|
|
173
|
+
async function handleRevoke(req, res, registry, opts) {
|
|
174
|
+
const credentialId = decodeURIComponent((req.url ?? "").split("/").pop() ?? "");
|
|
175
|
+
const cred = registry.resolve(credentialId);
|
|
176
|
+
if (!cred) {
|
|
177
|
+
res.writeHead(404);
|
|
178
|
+
res.end(JSON.stringify({ error: "Credential not found" }));
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
if (opts.resolveIssuerPublicKey) {
|
|
182
|
+
const pubKey = await opts.resolveIssuerPublicKey(cred.issuerDID);
|
|
183
|
+
if (!pubKey) {
|
|
184
|
+
res.writeHead(401);
|
|
185
|
+
res.end(JSON.stringify({ error: `Unknown credential issuer: ${cred.issuerDID}` }));
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
const proof = req.headers["x-revoke-proof"];
|
|
189
|
+
if (!proof) {
|
|
190
|
+
res.writeHead(401);
|
|
191
|
+
res.end(JSON.stringify({ error: "X-Revoke-Proof header required" }));
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
const valid = await verifyRevokeProof(credentialId, proof, pubKey);
|
|
195
|
+
if (!valid) {
|
|
196
|
+
res.writeHead(403);
|
|
197
|
+
res.end(JSON.stringify({ error: "Revoke proof invalid" }));
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
registry.revoke(credentialId);
|
|
202
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
203
|
+
res.end(JSON.stringify({ credentialId, revoked: true }));
|
|
204
|
+
}
|
|
205
|
+
async function handleResolve(_req, res, registry) {
|
|
206
|
+
const credentialId = decodeURIComponent((_req.url ?? "").split("?")[0].split("/").pop() ?? "");
|
|
207
|
+
const cred = registry.resolve(credentialId);
|
|
208
|
+
if (!cred) {
|
|
209
|
+
res.writeHead(404);
|
|
210
|
+
res.end(JSON.stringify({ error: "Credential not found or expired" }));
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
214
|
+
res.end(JSON.stringify(cred));
|
|
215
|
+
}
|
|
216
|
+
async function handleList(req, res, registry) {
|
|
217
|
+
const urlObj = new URL(req.url ?? "/", "http://localhost");
|
|
218
|
+
const userId = urlObj.searchParams.get("userId");
|
|
219
|
+
if (!userId) {
|
|
220
|
+
res.writeHead(400);
|
|
221
|
+
res.end(JSON.stringify({ error: "userId query param required" }));
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
225
|
+
res.end(JSON.stringify(registry.listForUser(userId)));
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"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"}
|
package/dist/rbac.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type ArohaMessageType } from "@aroha-sdk/core";
|
|
2
|
+
import { ArohaRole, type HumanCredential } from "./types.js";
|
|
3
|
+
export { ArohaRole } from "./types.js";
|
|
4
|
+
export type ArohaAction = "query" | "reserve" | "commit" | "cancel" | "delegate" | "negotiate" | "mandate" | "admin";
|
|
5
|
+
export declare function actionForMessageType(type: ArohaMessageType): ArohaAction | null;
|
|
6
|
+
export type RolePermissions = Partial<Record<ArohaRole, ArohaAction[]>>;
|
|
7
|
+
export interface RbacPolicy {
|
|
8
|
+
permissions?: RolePermissions;
|
|
9
|
+
resolveAgentRoles: (agentDID: string) => Promise<ArohaRole[]> | ArohaRole[];
|
|
10
|
+
resolveIssuerPublicKey?: (issuerDID: string) => Promise<Uint8Array | null> | Uint8Array | null;
|
|
11
|
+
credentialRegistry?: {
|
|
12
|
+
resolve(credentialId: string): HumanCredential | null | Promise<HumanCredential | null>;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export declare const DEFAULT_RBAC_PERMISSIONS: RolePermissions;
|
|
16
|
+
export interface RbacCheckResult {
|
|
17
|
+
allowed: boolean;
|
|
18
|
+
roles: ArohaRole[];
|
|
19
|
+
reason?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function checkPermission(roles: ArohaRole[], action: ArohaAction, permissions?: RolePermissions): RbacCheckResult;
|
|
22
|
+
//# sourceMappingURL=rbac.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rbac.d.ts","sourceRoot":"","sources":["../src/rbac.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7D,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAIvC,MAAM,MAAM,WAAW,GACnB,OAAO,GACP,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,UAAU,GACV,WAAW,GACX,SAAS,GACT,OAAO,CAAC;AAEZ,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,gBAAgB,GAAG,WAAW,GAAG,IAAI,CAsB/E;AAID,MAAM,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;AAExE,MAAM,WAAW,UAAU;IACzB,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,iBAAiB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC;IAC5E,sBAAsB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,UAAU,GAAG,IAAI,CAAC;IAC/F,kBAAkB,CAAC,EAAE;QACnB,OAAO,CAAC,YAAY,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;KACzF,CAAC;CACH;AAED,eAAO,MAAM,wBAAwB,EAAE,eAOtC,CAAC;AAIF,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,eAAe,CAC7B,KAAK,EAAE,SAAS,EAAE,EAClB,MAAM,EAAE,WAAW,EACnB,WAAW,GAAE,eAA0C,GACtD,eAAe,CAejB"}
|
package/dist/rbac.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { ArohaRole } from "./types.js";
|
|
2
|
+
export { ArohaRole } from "./types.js";
|
|
3
|
+
export function actionForMessageType(type) {
|
|
4
|
+
switch (type) {
|
|
5
|
+
case "ArohaRequest":
|
|
6
|
+
case "ArohaStream":
|
|
7
|
+
return "query";
|
|
8
|
+
case "ArohaReserve":
|
|
9
|
+
return "reserve";
|
|
10
|
+
case "ArohaCommit":
|
|
11
|
+
return "commit";
|
|
12
|
+
case "ArohaCancel":
|
|
13
|
+
return "cancel";
|
|
14
|
+
case "ArohaDelegate":
|
|
15
|
+
return "delegate";
|
|
16
|
+
case "ArohaNegotiate":
|
|
17
|
+
case "ArohaCounterOffer":
|
|
18
|
+
case "ArohaAccept":
|
|
19
|
+
return "negotiate";
|
|
20
|
+
case "ArohaSpendingMandate":
|
|
21
|
+
return "mandate";
|
|
22
|
+
default:
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export const DEFAULT_RBAC_PERMISSIONS = {
|
|
27
|
+
[ArohaRole.HumanAdmin]: ["query", "reserve", "commit", "cancel", "delegate", "negotiate", "mandate", "admin"],
|
|
28
|
+
[ArohaRole.HumanUser]: ["query", "reserve", "commit", "cancel", "negotiate", "mandate"],
|
|
29
|
+
[ArohaRole.HumanReadonly]: ["query"],
|
|
30
|
+
[ArohaRole.AgentOrchestrator]: ["query", "reserve", "commit", "cancel", "delegate", "negotiate", "mandate"],
|
|
31
|
+
[ArohaRole.AgentProvider]: [],
|
|
32
|
+
[ArohaRole.AgentObserver]: ["query"],
|
|
33
|
+
};
|
|
34
|
+
export function checkPermission(roles, action, permissions = DEFAULT_RBAC_PERMISSIONS) {
|
|
35
|
+
if (roles.length === 0) {
|
|
36
|
+
return { allowed: false, roles, reason: "No roles assigned" };
|
|
37
|
+
}
|
|
38
|
+
for (const role of roles) {
|
|
39
|
+
const allowed = permissions[role] ?? [];
|
|
40
|
+
if (allowed.includes("admin") || allowed.includes(action)) {
|
|
41
|
+
return { allowed: true, roles };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
allowed: false,
|
|
46
|
+
roles,
|
|
47
|
+
reason: `Roles [${roles.join(", ")}] do not permit action "${action}"`,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=rbac.js.map
|
package/dist/rbac.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rbac.js","sourceRoot":"","sources":["../src/rbac.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAwB,MAAM,YAAY,CAAC;AAE7D,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAcvC,MAAM,UAAU,oBAAoB,CAAC,IAAsB;IACzD,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,cAAc,CAAC;QACpB,KAAK,aAAa;YAChB,OAAO,OAAO,CAAC;QACjB,KAAK,cAAc;YACjB,OAAO,SAAS,CAAC;QACnB,KAAK,aAAa;YAChB,OAAO,QAAQ,CAAC;QAClB,KAAK,aAAa;YAChB,OAAO,QAAQ,CAAC;QAClB,KAAK,eAAe;YAClB,OAAO,UAAU,CAAC;QACpB,KAAK,gBAAgB,CAAC;QACtB,KAAK,mBAAmB,CAAC;QACzB,KAAK,aAAa;YAChB,OAAO,WAAW,CAAC;QACrB,KAAK,sBAAsB;YACzB,OAAO,SAAS,CAAC;QACnB;YACE,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC;AAeD,MAAM,CAAC,MAAM,wBAAwB,GAAoB;IACvD,CAAC,SAAS,CAAC,UAAU,CAAC,EAAS,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,CAAC;IACpH,CAAC,SAAS,CAAC,SAAS,CAAC,EAAU,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,CAAC;IAC/F,CAAC,SAAS,CAAC,aAAa,CAAC,EAAM,CAAC,OAAO,CAAC;IACxC,CAAC,SAAS,CAAC,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,CAAC;IAC3G,CAAC,SAAS,CAAC,aAAa,CAAC,EAAM,EAAE;IACjC,CAAC,SAAS,CAAC,aAAa,CAAC,EAAM,CAAC,OAAO,CAAC;CACzC,CAAC;AAUF,MAAM,UAAU,eAAe,CAC7B,KAAkB,EAClB,MAAmB,EACnB,cAA+B,wBAAwB;IAEvD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAChE,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACxC,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QAClC,CAAC;IACH,CAAC;IACD,OAAO;QACL,OAAO,EAAE,KAAK;QACd,KAAK;QACL,MAAM,EAAE,UAAU,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,2BAA2B,MAAM,GAAG;KACvE,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rbac.test.d.ts","sourceRoot":"","sources":["../src/rbac.test.ts"],"names":[],"mappings":""}
|