agentpassport-ts 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.
@@ -0,0 +1,155 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { TrustMiddleware, ScopeError } from "../src/trust.js";
3
+ import { signDelegation } from "../src/jwt.js";
4
+ import { generateKeypair, didFromPublicKey } from "../src/identity.js";
5
+
6
+ function makeParty() {
7
+ const kp = generateKeypair();
8
+ const did = didFromPublicKey(kp.publicKey);
9
+ return { kp, did };
10
+ }
11
+
12
+ describe("TrustMiddleware", () => {
13
+ it("passes when capability has no required scope", () => {
14
+ const agent = makeParty();
15
+ const middleware = new TrustMiddleware(
16
+ agent.did,
17
+ new Map(),
18
+ new Map() // no scopes declared
19
+ );
20
+ // Should not throw
21
+ expect(() => middleware.check([], "queryCustomers")).not.toThrow();
22
+ });
23
+
24
+ it("passes when auth chain grants the required scope", () => {
25
+ const issuer = makeParty();
26
+ const agent = makeParty();
27
+
28
+ const token = signDelegation({
29
+ issuerPrivateKey: issuer.kp.privateKey,
30
+ issuerDid: issuer.did,
31
+ subjectDid: agent.did,
32
+ scope: ["read:db:customers"],
33
+ });
34
+
35
+ const middleware = new TrustMiddleware(
36
+ agent.did,
37
+ new Map([[issuer.did, issuer.kp.publicKey]]),
38
+ new Map([["queryCustomers", ["read:db:customers"]]])
39
+ );
40
+
41
+ expect(() => middleware.check([token], "queryCustomers")).not.toThrow();
42
+ });
43
+
44
+ it("passes when auth chain grants wildcard *", () => {
45
+ const issuer = makeParty();
46
+ const agent = makeParty();
47
+
48
+ const token = signDelegation({
49
+ issuerPrivateKey: issuer.kp.privateKey,
50
+ issuerDid: issuer.did,
51
+ subjectDid: agent.did,
52
+ scope: ["*"],
53
+ });
54
+
55
+ const middleware = new TrustMiddleware(
56
+ agent.did,
57
+ new Map([[issuer.did, issuer.kp.publicKey]]),
58
+ new Map([["queryCustomers", ["read:db:customers"]]])
59
+ );
60
+
61
+ expect(() => middleware.check([token], "queryCustomers")).not.toThrow();
62
+ });
63
+
64
+ it("throws ScopeError when auth chain is empty but scope is required", () => {
65
+ const agent = makeParty();
66
+ const middleware = new TrustMiddleware(
67
+ agent.did,
68
+ new Map(),
69
+ new Map([["queryCustomers", ["read:db:customers"]]])
70
+ );
71
+
72
+ expect(() => middleware.check([], "queryCustomers")).toThrow(ScopeError);
73
+ });
74
+
75
+ it("throws ScopeError when scope is missing from chain", () => {
76
+ const issuer = makeParty();
77
+ const agent = makeParty();
78
+
79
+ const token = signDelegation({
80
+ issuerPrivateKey: issuer.kp.privateKey,
81
+ issuerDid: issuer.did,
82
+ subjectDid: agent.did,
83
+ scope: ["write:api:stripe"], // wrong scope
84
+ });
85
+
86
+ const middleware = new TrustMiddleware(
87
+ agent.did,
88
+ new Map([[issuer.did, issuer.kp.publicKey]]),
89
+ new Map([["queryCustomers", ["read:db:customers"]]])
90
+ );
91
+
92
+ expect(() => middleware.check([token], "queryCustomers")).toThrow(ScopeError);
93
+ });
94
+
95
+ it("ScopeError carries capability name and required/granted info", () => {
96
+ const agent = makeParty();
97
+ const middleware = new TrustMiddleware(
98
+ agent.did,
99
+ new Map(),
100
+ new Map([["queryCustomers", ["read:db:customers"]]])
101
+ );
102
+
103
+ try {
104
+ middleware.check([], "queryCustomers");
105
+ expect.fail("should have thrown");
106
+ } catch (e) {
107
+ expect(e).toBeInstanceOf(ScopeError);
108
+ const err = e as ScopeError;
109
+ expect(err.capability).toBe("queryCustomers");
110
+ expect(err.required).toEqual(["read:db:customers"]);
111
+ }
112
+ });
113
+
114
+ it("ignores tokens whose sub is not the agent DID", () => {
115
+ const issuer = makeParty();
116
+ const agent = makeParty();
117
+ const other = makeParty();
118
+
119
+ // Token delegates to 'other', not 'agent'
120
+ const token = signDelegation({
121
+ issuerPrivateKey: issuer.kp.privateKey,
122
+ issuerDid: issuer.did,
123
+ subjectDid: other.did,
124
+ scope: ["read:db:customers"],
125
+ });
126
+
127
+ const middleware = new TrustMiddleware(
128
+ agent.did,
129
+ new Map([[issuer.did, issuer.kp.publicKey]]),
130
+ new Map([["queryCustomers", ["read:db:customers"]]])
131
+ );
132
+
133
+ expect(() => middleware.check([token], "queryCustomers")).toThrow(ScopeError);
134
+ });
135
+
136
+ it("ignores tokens from untrusted issuers", () => {
137
+ const untrusted = makeParty();
138
+ const agent = makeParty();
139
+
140
+ const token = signDelegation({
141
+ issuerPrivateKey: untrusted.kp.privateKey,
142
+ issuerDid: untrusted.did,
143
+ subjectDid: agent.did,
144
+ scope: ["read:db:customers"],
145
+ });
146
+
147
+ const middleware = new TrustMiddleware(
148
+ agent.did,
149
+ new Map(), // untrusted not registered
150
+ new Map([["queryCustomers", ["read:db:customers"]]])
151
+ );
152
+
153
+ expect(() => middleware.check([token], "queryCustomers")).toThrow(ScopeError);
154
+ });
155
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "lib": ["ES2022"],
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
9
+ "strict": true,
10
+ "declaration": true,
11
+ "declarationMap": true,
12
+ "sourceMap": true,
13
+ "esModuleInterop": true,
14
+ "skipLibCheck": true,
15
+ "forceConsistentCasingInFileNames": true
16
+ },
17
+ "include": ["src/**/*"],
18
+ "exclude": ["node_modules", "dist", "tests"]
19
+ }
@@ -0,0 +1,8 @@
1
+ import { defineConfig } from "vitest/config";
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ environment: "node",
6
+ include: ["tests/**/*.test.ts", "../../tests/cross-sdk/*.test.ts"],
7
+ },
8
+ });