@amodalai/runtime 0.3.70 → 0.3.72

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.
Files changed (96) hide show
  1. package/dist/src/agent/local-server.js +7 -0
  2. package/dist/src/agent/local-server.js.map +1 -1
  3. package/dist/src/agent/local-server.test.js +96 -1
  4. package/dist/src/agent/local-server.test.js.map +1 -1
  5. package/dist/src/agent/routes/logs.d.ts +12 -0
  6. package/dist/src/agent/routes/logs.js +46 -0
  7. package/dist/src/agent/routes/logs.js.map +1 -0
  8. package/dist/src/agent/snapshot-server.js +4 -0
  9. package/dist/src/agent/snapshot-server.js.map +1 -1
  10. package/dist/src/auth/__fixtures__/custom-strategy.d.ts +8 -0
  11. package/dist/src/auth/__fixtures__/custom-strategy.js +27 -0
  12. package/dist/src/auth/__fixtures__/custom-strategy.js.map +1 -0
  13. package/dist/src/auth/compose.d.ts +55 -0
  14. package/dist/src/auth/compose.js +142 -0
  15. package/dist/src/auth/compose.js.map +1 -0
  16. package/dist/src/auth/compose.test.d.ts +6 -0
  17. package/dist/src/auth/compose.test.js +159 -0
  18. package/dist/src/auth/compose.test.js.map +1 -0
  19. package/dist/src/auth/config.d.ts +261 -0
  20. package/dist/src/auth/config.js +107 -0
  21. package/dist/src/auth/config.js.map +1 -0
  22. package/dist/src/auth/config.test.d.ts +6 -0
  23. package/dist/src/auth/config.test.js +85 -0
  24. package/dist/src/auth/config.test.js.map +1 -0
  25. package/dist/src/auth/factory.d.ts +19 -0
  26. package/dist/src/auth/factory.js +57 -0
  27. package/dist/src/auth/factory.js.map +1 -0
  28. package/dist/src/auth/factory.test.d.ts +6 -0
  29. package/dist/src/auth/factory.test.js +60 -0
  30. package/dist/src/auth/factory.test.js.map +1 -0
  31. package/dist/src/auth/index.d.ts +48 -0
  32. package/dist/src/auth/index.js +19 -0
  33. package/dist/src/auth/index.js.map +1 -0
  34. package/dist/src/auth/strategies/amodal.d.ts +36 -0
  35. package/dist/src/auth/strategies/amodal.js +28 -0
  36. package/dist/src/auth/strategies/amodal.js.map +1 -0
  37. package/dist/src/auth/strategies/api-key.d.ts +41 -0
  38. package/dist/src/auth/strategies/api-key.js +63 -0
  39. package/dist/src/auth/strategies/api-key.js.map +1 -0
  40. package/dist/src/auth/strategies/auth-modes.integration.test.d.ts +6 -0
  41. package/dist/src/auth/strategies/auth-modes.integration.test.js +363 -0
  42. package/dist/src/auth/strategies/auth-modes.integration.test.js.map +1 -0
  43. package/dist/src/auth/strategies/cookie.d.ts +41 -0
  44. package/dist/src/auth/strategies/cookie.js +84 -0
  45. package/dist/src/auth/strategies/cookie.js.map +1 -0
  46. package/dist/src/auth/strategies/custom-loader.d.ts +17 -0
  47. package/dist/src/auth/strategies/custom-loader.js +37 -0
  48. package/dist/src/auth/strategies/custom-loader.js.map +1 -0
  49. package/dist/src/auth/strategies/header.d.ts +35 -0
  50. package/dist/src/auth/strategies/header.js +42 -0
  51. package/dist/src/auth/strategies/header.js.map +1 -0
  52. package/dist/src/auth/strategies/jwks.d.ts +38 -0
  53. package/dist/src/auth/strategies/jwks.js +86 -0
  54. package/dist/src/auth/strategies/jwks.js.map +1 -0
  55. package/dist/src/auth/strategies/jwt-secret.d.ts +25 -0
  56. package/dist/src/auth/strategies/jwt-secret.js +82 -0
  57. package/dist/src/auth/strategies/jwt-secret.js.map +1 -0
  58. package/dist/src/auth/strategies/jwt-secret.test.d.ts +6 -0
  59. package/dist/src/auth/strategies/jwt-secret.test.js +75 -0
  60. package/dist/src/auth/strategies/jwt-secret.test.js.map +1 -0
  61. package/dist/src/auth/strategies/none.d.ts +37 -0
  62. package/dist/src/auth/strategies/none.js +31 -0
  63. package/dist/src/auth/strategies/none.js.map +1 -0
  64. package/dist/src/auth/strategies/oidc.d.ts +48 -0
  65. package/dist/src/auth/strategies/oidc.integration.test.d.ts +6 -0
  66. package/dist/src/auth/strategies/oidc.integration.test.js +290 -0
  67. package/dist/src/auth/strategies/oidc.integration.test.js.map +1 -0
  68. package/dist/src/auth/strategies/oidc.js +284 -0
  69. package/dist/src/auth/strategies/oidc.js.map +1 -0
  70. package/dist/src/auth/strategies/oidc.test.d.ts +6 -0
  71. package/dist/src/auth/strategies/oidc.test.js +111 -0
  72. package/dist/src/auth/strategies/oidc.test.js.map +1 -0
  73. package/dist/src/auth/strategies/strategies.test.d.ts +6 -0
  74. package/dist/src/auth/strategies/strategies.test.js +190 -0
  75. package/dist/src/auth/strategies/strategies.test.js.map +1 -0
  76. package/dist/src/auth/types.d.ts +95 -0
  77. package/dist/src/auth/types.js +7 -0
  78. package/dist/src/auth/types.js.map +1 -0
  79. package/dist/src/index.d.ts +4 -2
  80. package/dist/src/index.js +3 -1
  81. package/dist/src/index.js.map +1 -1
  82. package/dist/src/logger.d.ts +4 -3
  83. package/dist/src/logger.js +2 -1
  84. package/dist/src/logger.js.map +1 -1
  85. package/dist/src/logger.test.js +22 -1
  86. package/dist/src/logger.test.js.map +1 -1
  87. package/dist/src/runtime-log-store.d.ts +37 -0
  88. package/dist/src/runtime-log-store.js +132 -0
  89. package/dist/src/runtime-log-store.js.map +1 -0
  90. package/dist/src/server.js +7 -0
  91. package/dist/src/server.js.map +1 -1
  92. package/dist/src/session/manager.d.ts +1 -0
  93. package/dist/src/session/manager.js +18 -7
  94. package/dist/src/session/manager.js.map +1 -1
  95. package/dist/tsconfig.tsbuildinfo +1 -1
  96. package/package.json +9 -4
@@ -0,0 +1,363 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ /**
7
+ * End-to-end tests for the simpler auth modes — `none`, `header`,
8
+ * `jwt_secret`, `custom`, `amodal` — exercised through a real Express
9
+ * app over real HTTP. The OIDC strategy gets its own integration file
10
+ * (`oidc.integration.test.ts`) since it requires booting a full IdP.
11
+ *
12
+ * Each test:
13
+ * 1. Constructs the strategy via `createAuthStrategy(config)` so the
14
+ * factory's wiring is on the hot path (not just the strategy's
15
+ * constructor).
16
+ * 2. Mounts it on a real Express server bound to a random port.
17
+ * 3. Hits a protected route with appropriate credentials.
18
+ * 4. Asserts both the success and rejection paths.
19
+ */
20
+ import http from 'node:http';
21
+ import { randomBytes, generateKeyPairSync } from 'node:crypto';
22
+ import { fileURLToPath } from 'node:url';
23
+ import { dirname, resolve } from 'node:path';
24
+ import express from 'express';
25
+ import { SignJWT, exportJWK } from 'jose';
26
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
27
+ import { createAuthStrategy } from '../factory.js';
28
+ import { authenticate, getSession } from '../compose.js';
29
+ async function startProtectedApp(strategy) {
30
+ const app = express();
31
+ app.get('/protected', authenticate(strategy), (_req, res) => {
32
+ const session = getSession(res);
33
+ res.json({ user: session?.user, method: session?.method });
34
+ });
35
+ return new Promise((resolve, reject) => {
36
+ const server = http.createServer(app);
37
+ server.on('error', reject);
38
+ server.listen(0, '127.0.0.1', () => {
39
+ const addr = server.address();
40
+ resolve({
41
+ url: `http://127.0.0.1:${addr.port}`,
42
+ close: () => new Promise((closeResolve, closeReject) => {
43
+ server.close((err) => err ? closeReject(err) : closeResolve());
44
+ }),
45
+ });
46
+ });
47
+ });
48
+ }
49
+ async function getJson(url, init = {}) {
50
+ const res = await fetch(url, init);
51
+ let body = {};
52
+ if (res.headers.get('content-type')?.includes('application/json')) {
53
+ body = (await res.json());
54
+ }
55
+ return { status: res.status, body };
56
+ }
57
+ // ---------------------------------------------------------------------------
58
+ // none
59
+ // ---------------------------------------------------------------------------
60
+ describe('none mode — integration', () => {
61
+ let app;
62
+ beforeAll(async () => {
63
+ const strategy = await createAuthStrategy({ type: 'none' });
64
+ app = await startProtectedApp(strategy);
65
+ });
66
+ afterAll(async () => {
67
+ if (app)
68
+ await app.close();
69
+ });
70
+ it('lets every request through with the synthesized anonymous user', async () => {
71
+ const { status, body } = await getJson(`${app.url}/protected`);
72
+ expect(status).toBe(200);
73
+ expect(body.user?.id).toBe('anonymous');
74
+ expect(body.method).toBe('none');
75
+ });
76
+ it('respects a custom userId override', async () => {
77
+ const strategy = await createAuthStrategy({ type: 'none', userId: 'guest' });
78
+ const guestApp = await startProtectedApp(strategy);
79
+ try {
80
+ const { status, body } = await getJson(`${guestApp.url}/protected`);
81
+ expect(status).toBe(200);
82
+ expect(body.user?.id).toBe('guest');
83
+ }
84
+ finally {
85
+ await guestApp.close();
86
+ }
87
+ });
88
+ });
89
+ // ---------------------------------------------------------------------------
90
+ // header
91
+ // ---------------------------------------------------------------------------
92
+ describe('header mode — integration', () => {
93
+ let app;
94
+ beforeAll(async () => {
95
+ const strategy = await createAuthStrategy({ type: 'header' });
96
+ app = await startProtectedApp(strategy);
97
+ });
98
+ afterAll(async () => {
99
+ if (app)
100
+ await app.close();
101
+ });
102
+ it('reads identity from the default X-Auth-User header', async () => {
103
+ const { status, body } = await getJson(`${app.url}/protected`, {
104
+ headers: { 'X-Auth-User': 'alice' },
105
+ });
106
+ expect(status).toBe(200);
107
+ expect(body.user?.id).toBe('alice');
108
+ expect(body.method).toBe('header');
109
+ });
110
+ it('rejects requests with no identity header', async () => {
111
+ const { status } = await getJson(`${app.url}/protected`);
112
+ expect(status).toBe(401);
113
+ });
114
+ it('honours a configured headerName', async () => {
115
+ const strategy = await createAuthStrategy({
116
+ type: 'header',
117
+ headerName: 'X-Forwarded-User',
118
+ });
119
+ const customApp = await startProtectedApp(strategy);
120
+ try {
121
+ const ok = await getJson(`${customApp.url}/protected`, {
122
+ headers: { 'X-Forwarded-User': 'bob' },
123
+ });
124
+ expect(ok.status).toBe(200);
125
+ expect(ok.body.user?.id).toBe('bob');
126
+ // wrong header → rejected
127
+ const bad = await getJson(`${customApp.url}/protected`, {
128
+ headers: { 'X-Auth-User': 'eve' },
129
+ });
130
+ expect(bad.status).toBe(401);
131
+ }
132
+ finally {
133
+ await customApp.close();
134
+ }
135
+ });
136
+ });
137
+ // ---------------------------------------------------------------------------
138
+ // jwt_secret
139
+ // ---------------------------------------------------------------------------
140
+ describe('jwt_secret mode — integration', () => {
141
+ const SECRET = 'shared-hmac-secret-please-rotate';
142
+ let app;
143
+ async function mintToken(claims = {}, ttl = 300) {
144
+ const key = new TextEncoder().encode(SECRET);
145
+ return new SignJWT({ sub: 'user-1', email: 'u1@example.com', name: 'User One', ...claims })
146
+ .setProtectedHeader({ alg: 'HS256' })
147
+ .setIssuedAt()
148
+ .setExpirationTime(`${ttl}s`)
149
+ .sign(key);
150
+ }
151
+ beforeAll(async () => {
152
+ const strategy = await createAuthStrategy({ type: 'jwt_secret', secret: SECRET });
153
+ app = await startProtectedApp(strategy);
154
+ });
155
+ afterAll(async () => {
156
+ if (app)
157
+ await app.close();
158
+ });
159
+ it('accepts a valid HS256 bearer token', async () => {
160
+ const token = await mintToken();
161
+ const { status, body } = await getJson(`${app.url}/protected`, {
162
+ headers: { Authorization: `Bearer ${token}` },
163
+ });
164
+ expect(status).toBe(200);
165
+ expect(body.user?.id).toBe('user-1');
166
+ expect(body.user?.email).toBe('u1@example.com');
167
+ });
168
+ it('rejects a tampered signature', async () => {
169
+ const token = await mintToken();
170
+ const tampered = `${token.slice(0, -3)}AAA`;
171
+ const { status } = await getJson(`${app.url}/protected`, {
172
+ headers: { Authorization: `Bearer ${tampered}` },
173
+ });
174
+ expect(status).toBe(401);
175
+ });
176
+ it('rejects a token signed with a different secret', async () => {
177
+ const wrongKey = new TextEncoder().encode('different-secret-of-similar-length');
178
+ const token = await new SignJWT({ sub: 'imposter' })
179
+ .setProtectedHeader({ alg: 'HS256' })
180
+ .setIssuedAt()
181
+ .setExpirationTime('5m')
182
+ .sign(wrongKey);
183
+ const { status } = await getJson(`${app.url}/protected`, {
184
+ headers: { Authorization: `Bearer ${token}` },
185
+ });
186
+ expect(status).toBe(401);
187
+ });
188
+ it('rejects when no Authorization header is sent', async () => {
189
+ const { status } = await getJson(`${app.url}/protected`);
190
+ expect(status).toBe(401);
191
+ });
192
+ it('enforces issuer when configured', async () => {
193
+ const strategy = await createAuthStrategy({
194
+ type: 'jwt_secret',
195
+ secret: SECRET,
196
+ issuer: 'expected-issuer',
197
+ });
198
+ const issuerApp = await startProtectedApp(strategy);
199
+ try {
200
+ const goodKey = new TextEncoder().encode(SECRET);
201
+ const goodToken = await new SignJWT({ sub: 'user-1' })
202
+ .setProtectedHeader({ alg: 'HS256' })
203
+ .setIssuedAt()
204
+ .setExpirationTime('5m')
205
+ .setIssuer('expected-issuer')
206
+ .sign(goodKey);
207
+ const badToken = await new SignJWT({ sub: 'user-1' })
208
+ .setProtectedHeader({ alg: 'HS256' })
209
+ .setIssuedAt()
210
+ .setExpirationTime('5m')
211
+ .setIssuer('other-issuer')
212
+ .sign(goodKey);
213
+ const ok = await getJson(`${issuerApp.url}/protected`, {
214
+ headers: { Authorization: `Bearer ${goodToken}` },
215
+ });
216
+ expect(ok.status).toBe(200);
217
+ const bad = await getJson(`${issuerApp.url}/protected`, {
218
+ headers: { Authorization: `Bearer ${badToken}` },
219
+ });
220
+ expect(bad.status).toBe(401);
221
+ }
222
+ finally {
223
+ await issuerApp.close();
224
+ }
225
+ });
226
+ });
227
+ // ---------------------------------------------------------------------------
228
+ // custom
229
+ // ---------------------------------------------------------------------------
230
+ describe('custom mode — integration', () => {
231
+ let app;
232
+ beforeAll(async () => {
233
+ // Resolve the fixture path relative to this test file so the dynamic
234
+ // import works regardless of cwd.
235
+ const here = dirname(fileURLToPath(import.meta.url));
236
+ const modulePath = resolve(here, '../__fixtures__/custom-strategy.ts');
237
+ const strategy = await createAuthStrategy({ type: 'custom', module: modulePath });
238
+ app = await startProtectedApp(strategy);
239
+ });
240
+ afterAll(async () => {
241
+ if (app)
242
+ await app.close();
243
+ });
244
+ it('authenticates when the fixture token matches', async () => {
245
+ const { status, body } = await getJson(`${app.url}/protected`, {
246
+ headers: { 'X-Custom-Token': 'secret-value' },
247
+ });
248
+ expect(status).toBe(200);
249
+ expect(body.user?.id).toBe('custom-user');
250
+ expect(body.method).toBe('custom-test');
251
+ });
252
+ it('rejects when the fixture token is wrong', async () => {
253
+ const { status } = await getJson(`${app.url}/protected`, {
254
+ headers: { 'X-Custom-Token': 'not-the-secret' },
255
+ });
256
+ expect(status).toBe(401);
257
+ });
258
+ it('rejects when the fixture header is missing', async () => {
259
+ const { status } = await getJson(`${app.url}/protected`);
260
+ expect(status).toBe(401);
261
+ });
262
+ it('throws at construction when the module path does not exist', async () => {
263
+ await expect(createAuthStrategy({ type: 'custom', module: '/path/that/does/not/exist.ts' })).rejects.toThrow(/Failed to load custom auth strategy/);
264
+ });
265
+ });
266
+ async function startJwksServer() {
267
+ // jose's exportJWK + SignJWT accept Node's KeyObject as a valid KeyLike.
268
+ const { publicKey, privateKey } = generateKeyPairSync('rsa', { modulusLength: 2048 });
269
+ const publicJwk = await exportJWK(publicKey);
270
+ const kid = randomBytes(8).toString('hex');
271
+ publicJwk.kid = kid;
272
+ publicJwk.alg = 'RS256';
273
+ publicJwk.use = 'sig';
274
+ const app = express();
275
+ app.get('/.well-known/jwks.json', (_req, res) => {
276
+ res.json({ keys: [publicJwk] });
277
+ });
278
+ const signingKey = privateKey;
279
+ return new Promise((resolve, reject) => {
280
+ const server = http.createServer(app);
281
+ server.on('error', reject);
282
+ server.listen(0, '127.0.0.1', () => {
283
+ const addr = server.address();
284
+ const url = `http://127.0.0.1:${addr.port}`;
285
+ resolve({
286
+ url,
287
+ jwksUrl: `${url}/.well-known/jwks.json`,
288
+ signingKey,
289
+ kid,
290
+ close: () => new Promise((closeResolve, closeReject) => {
291
+ server.close((err) => err ? closeReject(err) : closeResolve());
292
+ }),
293
+ });
294
+ });
295
+ });
296
+ }
297
+ describe('amodal mode — integration', () => {
298
+ const ISSUER = 'integration-test-platform';
299
+ let jwks;
300
+ let app;
301
+ async function mintPlatformToken(claims = {}, issuer = ISSUER) {
302
+ return new SignJWT({ sub: 'amodal-user-1', email: 'a1@amodal.test', ...claims })
303
+ .setProtectedHeader({ alg: 'RS256', kid: jwks.kid })
304
+ .setIssuedAt()
305
+ .setIssuer(issuer)
306
+ .setExpirationTime('5m')
307
+ .sign(jwks.signingKey);
308
+ }
309
+ beforeAll(async () => {
310
+ jwks = await startJwksServer();
311
+ const strategy = await createAuthStrategy({
312
+ type: 'amodal',
313
+ jwksUrl: jwks.jwksUrl,
314
+ issuer: ISSUER,
315
+ });
316
+ app = await startProtectedApp(strategy);
317
+ });
318
+ afterAll(async () => {
319
+ if (app)
320
+ await app.close();
321
+ if (jwks)
322
+ await jwks.close();
323
+ });
324
+ it('accepts a platform-signed JWT verified against the JWKS', async () => {
325
+ const token = await mintPlatformToken();
326
+ const { status, body } = await getJson(`${app.url}/protected`, {
327
+ headers: { Authorization: `Bearer ${token}` },
328
+ });
329
+ expect(status).toBe(200);
330
+ expect(body.user?.id).toBe('amodal-user-1');
331
+ expect(body.method).toBe('amodal');
332
+ });
333
+ it('rejects a token with the wrong issuer', async () => {
334
+ const token = await mintPlatformToken({}, 'someone-elses-platform');
335
+ const { status } = await getJson(`${app.url}/protected`, {
336
+ headers: { Authorization: `Bearer ${token}` },
337
+ });
338
+ expect(status).toBe(401);
339
+ });
340
+ it('rejects a token signed by a different key', async () => {
341
+ const otherJwks = await startJwksServer();
342
+ try {
343
+ const token = await new SignJWT({ sub: 'imposter' })
344
+ .setProtectedHeader({ alg: 'RS256', kid: otherJwks.kid })
345
+ .setIssuedAt()
346
+ .setIssuer(ISSUER)
347
+ .setExpirationTime('5m')
348
+ .sign(otherJwks.signingKey);
349
+ const { status } = await getJson(`${app.url}/protected`, {
350
+ headers: { Authorization: `Bearer ${token}` },
351
+ });
352
+ expect(status).toBe(401);
353
+ }
354
+ finally {
355
+ await otherJwks.close();
356
+ }
357
+ });
358
+ it('rejects when no bearer token is sent', async () => {
359
+ const { status } = await getJson(`${app.url}/protected`);
360
+ expect(status).toBe(401);
361
+ });
362
+ });
363
+ //# sourceMappingURL=auth-modes.integration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-modes.integration.test.js","sourceRoot":"","sources":["../../../../src/auth/strategies/auth-modes.integration.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ /**
7
+ * CookieSessionStrategy — reads a session JWT from a cookie and verifies
8
+ * it against a JWKS endpoint. Useful for SPA + runtime stacks that don't
9
+ * sit behind cf-worker (or any other Bearer-injecting proxy) and need
10
+ * cookie-based session continuity in the browser.
11
+ *
12
+ * The JWT contract is the same as `JwksAuthStrategy` — same JWKS, same
13
+ * issuer check, same claim shape. The only difference is where the token
14
+ * lives (cookie vs Authorization header).
15
+ */
16
+ import { createRemoteJWKSet } from 'jose';
17
+ import type { Request } from 'express';
18
+ import type { AuthResult, AuthStrategy } from '../types.js';
19
+ export interface CookieSessionStrategyOptions {
20
+ /** Cookie name to read. Defaults to `'amodal_session'`. */
21
+ cookieName?: string;
22
+ /** JWKS endpoint URL — same shape as `JwksAuthStrategy`. */
23
+ jwksUrl: string;
24
+ /** Required `iss` claim. Defaults to no issuer check. */
25
+ issuer?: string;
26
+ /** Override `AuthSession.method`. Defaults to `'cookie'`. */
27
+ authMethod?: string;
28
+ /** Pass-through to `jose.createRemoteJWKSet`. */
29
+ jwksOptions?: Parameters<typeof createRemoteJWKSet>[1];
30
+ }
31
+ export declare class CookieSessionStrategy implements AuthStrategy {
32
+ readonly name = "cookie";
33
+ private readonly cookieName;
34
+ private readonly jwks;
35
+ private readonly issuer?;
36
+ private readonly authMethod;
37
+ constructor(options: CookieSessionStrategyOptions);
38
+ valid(req: Request): boolean;
39
+ authenticate(req: Request): Promise<AuthResult>;
40
+ private readCookie;
41
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ /**
7
+ * CookieSessionStrategy — reads a session JWT from a cookie and verifies
8
+ * it against a JWKS endpoint. Useful for SPA + runtime stacks that don't
9
+ * sit behind cf-worker (or any other Bearer-injecting proxy) and need
10
+ * cookie-based session continuity in the browser.
11
+ *
12
+ * The JWT contract is the same as `JwksAuthStrategy` — same JWKS, same
13
+ * issuer check, same claim shape. The only difference is where the token
14
+ * lives (cookie vs Authorization header).
15
+ */
16
+ import { createRemoteJWKSet, jwtVerify } from 'jose';
17
+ export class CookieSessionStrategy {
18
+ name = 'cookie';
19
+ cookieName;
20
+ jwks;
21
+ issuer;
22
+ authMethod;
23
+ constructor(options) {
24
+ this.cookieName = options.cookieName ?? 'amodal_session';
25
+ this.jwks = createRemoteJWKSet(new URL(options.jwksUrl), options.jwksOptions);
26
+ if (options.issuer !== undefined)
27
+ this.issuer = options.issuer;
28
+ this.authMethod = options.authMethod ?? 'cookie';
29
+ }
30
+ valid(req) {
31
+ return Boolean(this.readCookie(req));
32
+ }
33
+ async authenticate(req) {
34
+ const token = this.readCookie(req);
35
+ if (!token)
36
+ return { kind: 'rejected', reason: 'No session cookie' };
37
+ let payload;
38
+ try {
39
+ const result = await jwtVerify(token, this.jwks, this.issuer ? { issuer: this.issuer } : {});
40
+ payload = result.payload;
41
+ }
42
+ catch (err) {
43
+ const detail = err instanceof Error ? err.message : String(err);
44
+ return { kind: 'rejected', reason: `Cookie session JWT invalid: ${detail}` };
45
+ }
46
+ return { kind: 'authenticated', session: buildSession(payload, this.authMethod) };
47
+ }
48
+ readCookie(req) {
49
+ const header = req.headers['cookie'];
50
+ if (typeof header !== 'string' || header.length === 0)
51
+ return null;
52
+ for (const pair of header.split(';')) {
53
+ const trimmed = pair.trim();
54
+ const eq = trimmed.indexOf('=');
55
+ if (eq === -1)
56
+ continue;
57
+ const name = trimmed.slice(0, eq);
58
+ if (name !== this.cookieName)
59
+ continue;
60
+ const value = trimmed.slice(eq + 1);
61
+ return value.length > 0 ? decodeURIComponent(value) : null;
62
+ }
63
+ return null;
64
+ }
65
+ }
66
+ function buildSession(payload, method) {
67
+ const userId = typeof payload['user_id'] === 'string'
68
+ ? payload['user_id']
69
+ : typeof payload['sub'] === 'string'
70
+ ? payload['sub']
71
+ : '';
72
+ const session = { user: { id: userId }, method };
73
+ if (typeof payload['email'] === 'string')
74
+ session.user.email = payload['email'];
75
+ if (typeof payload['name'] === 'string')
76
+ session.user.name = payload['name'];
77
+ if (typeof payload['agent_id'] === 'string')
78
+ session.agentId = payload['agent_id'];
79
+ if (typeof payload['scope_id'] === 'string')
80
+ session.scopeId = payload['scope_id'];
81
+ session.claims = { ...payload };
82
+ return session;
83
+ }
84
+ //# sourceMappingURL=cookie.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cookie.js","sourceRoot":"","sources":["../../../../src/auth/strategies/cookie.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ /**
7
+ * Load a custom AuthStrategy from a user-supplied module path. Used by
8
+ * `AuthConfig` `{type: 'custom', module: './path'}` to let agent owners
9
+ * drop in a verifier function for any auth system they already use
10
+ * (Auth0 SDK, Supabase getUser, internal verify endpoint, etc.).
11
+ *
12
+ * The module's default export must be an `AuthStrategy` (object with
13
+ * `name`, `valid`, `authenticate`). The shape is validated; a wrong-
14
+ * shape export throws at startup with a clear message.
15
+ */
16
+ import type { AuthStrategy } from '../types.js';
17
+ export declare function loadCustomStrategy(modulePath: string): Promise<AuthStrategy>;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ export async function loadCustomStrategy(modulePath) {
7
+ let mod;
8
+ try {
9
+ mod = await import(modulePath);
10
+ }
11
+ catch (err) {
12
+ const detail = err instanceof Error ? err.message : String(err);
13
+ throw new Error(`Failed to load custom auth strategy from '${modulePath}': ${detail}`, { cause: err });
14
+ }
15
+ if (typeof mod !== 'object' || mod === null) {
16
+ throw new Error(`Custom auth strategy at '${modulePath}' did not export anything`);
17
+ }
18
+ const candidate = 'default' in mod
19
+ ? mod.default
20
+ : mod;
21
+ if (!isStrategy(candidate)) {
22
+ throw new Error(`Custom auth strategy at '${modulePath}' default export does not match the AuthStrategy shape ` +
23
+ `({name: string, valid(req): boolean, authenticate(req): Promise<AuthResult>})`);
24
+ }
25
+ return candidate;
26
+ }
27
+ function isStrategy(value) {
28
+ if (typeof value !== 'object' || value === null)
29
+ return false;
30
+ if (!('name' in value) || !('valid' in value) || !('authenticate' in value)) {
31
+ return false;
32
+ }
33
+ return (typeof value.name === 'string' &&
34
+ typeof value.valid === 'function' &&
35
+ typeof value.authenticate === 'function');
36
+ }
37
+ //# sourceMappingURL=custom-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom-loader.js","sourceRoot":"","sources":["../../../../src/auth/strategies/custom-loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAcH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,UAAkB;IAElB,IAAI,GAAY,CAAC;IACjB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;IACjC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAChE,MAAM,IAAI,KAAK,CACb,6CAA6C,UAAU,MAAM,MAAM,EAAE,EACrE,EAAC,KAAK,EAAE,GAAG,EAAC,CACb,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CACb,4BAA4B,UAAU,2BAA2B,CAClE,CAAC;IACJ,CAAC;IACD,MAAM,SAAS,GACb,SAAS,IAAI,GAAG;QACd,CAAC,CAAE,GAA0B,CAAC,OAAO;QACrC,CAAC,CAAE,GAAe,CAAC;IACvB,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CACb,4BAA4B,UAAU,yDAAyD;YAC7F,+EAA+E,CAClF,CAAC;IACJ,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,UAAU,CAAC,KAAc;IAChC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC9D,IAAI,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,cAAc,IAAI,KAAK,CAAC,EAAE,CAAC;QAC5E,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,CACL,OAAQ,KAAyB,CAAC,IAAI,KAAK,QAAQ;QACnD,OAAQ,KAA0B,CAAC,KAAK,KAAK,UAAU;QACvD,OAAQ,KAAiC,CAAC,YAAY,KAAK,UAAU,CACtE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ /**
7
+ * HeaderAuthStrategy — reads the user identity from a configured request
8
+ * header (default `X-Auth-User`). For service-to-service calls behind a
9
+ * trusted proxy that authenticates upstream and writes the verified
10
+ * identity into a header.
11
+ *
12
+ * Security: never expose a route protected by this strategy directly to
13
+ * the public internet. Trusted-header strategies presume an upstream
14
+ * proxy strips the header on inbound requests and writes its own.
15
+ */
16
+ import type { Request } from 'express';
17
+ import type { AuthResult, AuthStrategy } from '../types.js';
18
+ export interface HeaderAuthStrategyOptions {
19
+ /** Header name to read (case-insensitive). Defaults to `'X-Auth-User'`. */
20
+ headerName?: string;
21
+ /** Optional `agentId` to attach to the resulting session. */
22
+ agentId?: string;
23
+ /** Override `AuthSession.method`. Defaults to `'header'`. */
24
+ authMethod?: string;
25
+ }
26
+ export declare class HeaderAuthStrategy implements AuthStrategy {
27
+ readonly name = "header";
28
+ private readonly headerName;
29
+ private readonly agentId?;
30
+ private readonly authMethod;
31
+ constructor(options?: HeaderAuthStrategyOptions);
32
+ valid(req: Request): boolean;
33
+ authenticate(req: Request): Promise<AuthResult>;
34
+ private read;
35
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ export class HeaderAuthStrategy {
7
+ name = 'header';
8
+ headerName;
9
+ agentId;
10
+ authMethod;
11
+ constructor(options = {}) {
12
+ this.headerName = (options.headerName ?? 'X-Auth-User').toLowerCase();
13
+ if (options.agentId !== undefined)
14
+ this.agentId = options.agentId;
15
+ this.authMethod = options.authMethod ?? 'header';
16
+ }
17
+ valid(req) {
18
+ return Boolean(this.read(req));
19
+ }
20
+ async authenticate(req) {
21
+ const userId = this.read(req);
22
+ if (!userId)
23
+ return { kind: 'rejected', reason: 'Missing identity header' };
24
+ return {
25
+ kind: 'authenticated',
26
+ session: {
27
+ user: { id: userId },
28
+ method: this.authMethod,
29
+ ...(this.agentId ? { agentId: this.agentId } : {}),
30
+ scopeId: userId,
31
+ },
32
+ };
33
+ }
34
+ read(req) {
35
+ const value = req.headers[this.headerName];
36
+ const id = Array.isArray(value) ? value[0] : value;
37
+ if (typeof id !== 'string' || id.length === 0)
38
+ return null;
39
+ return id;
40
+ }
41
+ }
42
+ //# sourceMappingURL=header.js.map