@amodalai/runtime 0.3.69 → 0.3.71

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 (85) hide show
  1. package/dist/src/auth/__fixtures__/custom-strategy.d.ts +8 -0
  2. package/dist/src/auth/__fixtures__/custom-strategy.js +27 -0
  3. package/dist/src/auth/__fixtures__/custom-strategy.js.map +1 -0
  4. package/dist/src/auth/compose.d.ts +55 -0
  5. package/dist/src/auth/compose.js +142 -0
  6. package/dist/src/auth/compose.js.map +1 -0
  7. package/dist/src/auth/compose.test.d.ts +6 -0
  8. package/dist/src/auth/compose.test.js +159 -0
  9. package/dist/src/auth/compose.test.js.map +1 -0
  10. package/dist/src/auth/config.d.ts +261 -0
  11. package/dist/src/auth/config.js +107 -0
  12. package/dist/src/auth/config.js.map +1 -0
  13. package/dist/src/auth/config.test.d.ts +6 -0
  14. package/dist/src/auth/config.test.js +85 -0
  15. package/dist/src/auth/config.test.js.map +1 -0
  16. package/dist/src/auth/factory.d.ts +19 -0
  17. package/dist/src/auth/factory.js +57 -0
  18. package/dist/src/auth/factory.js.map +1 -0
  19. package/dist/src/auth/factory.test.d.ts +6 -0
  20. package/dist/src/auth/factory.test.js +60 -0
  21. package/dist/src/auth/factory.test.js.map +1 -0
  22. package/dist/src/auth/index.d.ts +48 -0
  23. package/dist/src/auth/index.js +19 -0
  24. package/dist/src/auth/index.js.map +1 -0
  25. package/dist/src/auth/strategies/amodal.d.ts +36 -0
  26. package/dist/src/auth/strategies/amodal.js +28 -0
  27. package/dist/src/auth/strategies/amodal.js.map +1 -0
  28. package/dist/src/auth/strategies/api-key.d.ts +41 -0
  29. package/dist/src/auth/strategies/api-key.js +63 -0
  30. package/dist/src/auth/strategies/api-key.js.map +1 -0
  31. package/dist/src/auth/strategies/auth-modes.integration.test.d.ts +6 -0
  32. package/dist/src/auth/strategies/auth-modes.integration.test.js +363 -0
  33. package/dist/src/auth/strategies/auth-modes.integration.test.js.map +1 -0
  34. package/dist/src/auth/strategies/cookie.d.ts +41 -0
  35. package/dist/src/auth/strategies/cookie.js +84 -0
  36. package/dist/src/auth/strategies/cookie.js.map +1 -0
  37. package/dist/src/auth/strategies/custom-loader.d.ts +17 -0
  38. package/dist/src/auth/strategies/custom-loader.js +37 -0
  39. package/dist/src/auth/strategies/custom-loader.js.map +1 -0
  40. package/dist/src/auth/strategies/header.d.ts +35 -0
  41. package/dist/src/auth/strategies/header.js +42 -0
  42. package/dist/src/auth/strategies/header.js.map +1 -0
  43. package/dist/src/auth/strategies/jwks.d.ts +38 -0
  44. package/dist/src/auth/strategies/jwks.js +86 -0
  45. package/dist/src/auth/strategies/jwks.js.map +1 -0
  46. package/dist/src/auth/strategies/jwt-secret.d.ts +25 -0
  47. package/dist/src/auth/strategies/jwt-secret.js +82 -0
  48. package/dist/src/auth/strategies/jwt-secret.js.map +1 -0
  49. package/dist/src/auth/strategies/jwt-secret.test.d.ts +6 -0
  50. package/dist/src/auth/strategies/jwt-secret.test.js +75 -0
  51. package/dist/src/auth/strategies/jwt-secret.test.js.map +1 -0
  52. package/dist/src/auth/strategies/none.d.ts +37 -0
  53. package/dist/src/auth/strategies/none.js +31 -0
  54. package/dist/src/auth/strategies/none.js.map +1 -0
  55. package/dist/src/auth/strategies/oidc.d.ts +48 -0
  56. package/dist/src/auth/strategies/oidc.integration.test.d.ts +6 -0
  57. package/dist/src/auth/strategies/oidc.integration.test.js +290 -0
  58. package/dist/src/auth/strategies/oidc.integration.test.js.map +1 -0
  59. package/dist/src/auth/strategies/oidc.js +284 -0
  60. package/dist/src/auth/strategies/oidc.js.map +1 -0
  61. package/dist/src/auth/strategies/oidc.test.d.ts +6 -0
  62. package/dist/src/auth/strategies/oidc.test.js +111 -0
  63. package/dist/src/auth/strategies/oidc.test.js.map +1 -0
  64. package/dist/src/auth/strategies/strategies.test.d.ts +6 -0
  65. package/dist/src/auth/strategies/strategies.test.js +190 -0
  66. package/dist/src/auth/strategies/strategies.test.js.map +1 -0
  67. package/dist/src/auth/types.d.ts +95 -0
  68. package/dist/src/auth/types.js +7 -0
  69. package/dist/src/auth/types.js.map +1 -0
  70. package/dist/src/index.d.ts +2 -0
  71. package/dist/src/index.js +2 -0
  72. package/dist/src/index.js.map +1 -1
  73. package/dist/src/routes/session-resolver.d.ts +10 -10
  74. package/dist/src/routes/session-resolver.js +33 -17
  75. package/dist/src/routes/session-resolver.js.map +1 -1
  76. package/dist/src/routes/session-resolver.test.js +121 -80
  77. package/dist/src/routes/session-resolver.test.js.map +1 -1
  78. package/dist/src/session/drizzle-session-store.d.ts +8 -12
  79. package/dist/src/session/drizzle-session-store.js +38 -37
  80. package/dist/src/session/drizzle-session-store.js.map +1 -1
  81. package/dist/src/session/store.d.ts +5 -5
  82. package/dist/src/session/store.js +54 -38
  83. package/dist/src/session/store.js.map +1 -1
  84. package/dist/tsconfig.tsbuildinfo +1 -1
  85. package/package.json +9 -4
@@ -0,0 +1,261 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ /**
7
+ * Config-driven auth — discriminated union the agent owner sets in
8
+ * `amodal.json` (or whatever surfaces the runtime through). The host
9
+ * resolves any `env:` references against its secrets store before
10
+ * passing the config to `createAuthStrategy(config)`.
11
+ *
12
+ * {
13
+ * "auth": {
14
+ * "type": "oidc",
15
+ * "issuer": "https://acme.okta.com",
16
+ * ...
17
+ * }
18
+ * }
19
+ */
20
+ import { z } from 'zod';
21
+ declare const NoneAuthConfigSchema: z.ZodObject<{
22
+ type: z.ZodLiteral<"none">;
23
+ /** Synthesized user id for the anonymous session. Defaults to `'anonymous'`. */
24
+ userId: z.ZodOptional<z.ZodString>;
25
+ }, "strip", z.ZodTypeAny, {
26
+ type: "none";
27
+ userId?: string | undefined;
28
+ }, {
29
+ type: "none";
30
+ userId?: string | undefined;
31
+ }>;
32
+ declare const JwtSecretAuthConfigSchema: z.ZodObject<{
33
+ type: z.ZodLiteral<"jwt_secret">;
34
+ /** Shared HMAC secret used to verify incoming JWTs. */
35
+ secret: z.ZodString;
36
+ /** HMAC algorithm. Defaults to HS256. */
37
+ algorithm: z.ZodOptional<z.ZodEnum<["HS256", "HS384", "HS512"]>>;
38
+ /** Expected `iss` claim. Optional. */
39
+ issuer: z.ZodOptional<z.ZodString>;
40
+ /** Expected `aud` claim. Optional. */
41
+ audience: z.ZodOptional<z.ZodString>;
42
+ }, "strip", z.ZodTypeAny, {
43
+ type: "jwt_secret";
44
+ secret: string;
45
+ issuer?: string | undefined;
46
+ audience?: string | undefined;
47
+ algorithm?: "HS256" | "HS384" | "HS512" | undefined;
48
+ }, {
49
+ type: "jwt_secret";
50
+ secret: string;
51
+ issuer?: string | undefined;
52
+ audience?: string | undefined;
53
+ algorithm?: "HS256" | "HS384" | "HS512" | undefined;
54
+ }>;
55
+ declare const OidcAuthConfigSchema: z.ZodObject<{
56
+ type: z.ZodLiteral<"oidc">;
57
+ /** OIDC issuer URL — the IdP's discovery base (`https://acme.okta.com`). */
58
+ issuer: z.ZodString;
59
+ clientId: z.ZodString;
60
+ clientSecret: z.ZodString;
61
+ /** Where the IdP redirects back after login. Must be registered with the IdP. */
62
+ callbackUrl: z.ZodString;
63
+ /** OAuth scopes to request. Defaults to `['openid', 'email', 'profile']`. */
64
+ scopes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
65
+ /**
66
+ * HMAC secret used to sign the session JWT stored in the runtime's cookie.
67
+ * Distinct from the IdP — this is purely the runtime's session signing key.
68
+ */
69
+ sessionSecret: z.ZodString;
70
+ /** Cookie name for the session JWT. Defaults to `'amodal_session'`. */
71
+ cookieName: z.ZodOptional<z.ZodString>;
72
+ /** Session TTL in seconds. Defaults to 24h. */
73
+ sessionTtlSeconds: z.ZodOptional<z.ZodNumber>;
74
+ }, "strip", z.ZodTypeAny, {
75
+ type: "oidc";
76
+ issuer: string;
77
+ clientId: string;
78
+ clientSecret: string;
79
+ callbackUrl: string;
80
+ sessionSecret: string;
81
+ scopes?: string[] | undefined;
82
+ cookieName?: string | undefined;
83
+ sessionTtlSeconds?: number | undefined;
84
+ }, {
85
+ type: "oidc";
86
+ issuer: string;
87
+ clientId: string;
88
+ clientSecret: string;
89
+ callbackUrl: string;
90
+ sessionSecret: string;
91
+ scopes?: string[] | undefined;
92
+ cookieName?: string | undefined;
93
+ sessionTtlSeconds?: number | undefined;
94
+ }>;
95
+ declare const HeaderAuthConfigSchema: z.ZodObject<{
96
+ type: z.ZodLiteral<"header">;
97
+ headerName: z.ZodOptional<z.ZodString>;
98
+ }, "strip", z.ZodTypeAny, {
99
+ type: "header";
100
+ headerName?: string | undefined;
101
+ }, {
102
+ type: "header";
103
+ headerName?: string | undefined;
104
+ }>;
105
+ declare const CustomAuthConfigSchema: z.ZodObject<{
106
+ type: z.ZodLiteral<"custom">;
107
+ /**
108
+ * Module path (relative to the agent's runtime directory) whose default
109
+ * export implements the `AuthStrategy` interface. The runtime imports
110
+ * this file at startup and validates the shape.
111
+ */
112
+ module: z.ZodString;
113
+ }, "strip", z.ZodTypeAny, {
114
+ type: "custom";
115
+ module: string;
116
+ }, {
117
+ type: "custom";
118
+ module: string;
119
+ }>;
120
+ /**
121
+ * "Sign in with Amodal" — verifies platform JWTs minted by the Amodal
122
+ * cloud (or any self-hosted Amodal-equivalent platform). Agent owners on
123
+ * the Amodal cloud need zero config; the cloud's deploy pipeline injects
124
+ * the JWKS URL via the `AMODAL_JWKS_URL` env var. Self-hosters override
125
+ * via the optional `jwksUrl` field.
126
+ */
127
+ declare const AmodalAuthConfigSchema: z.ZodObject<{
128
+ type: z.ZodLiteral<"amodal">;
129
+ jwksUrl: z.ZodOptional<z.ZodString>;
130
+ issuer: z.ZodOptional<z.ZodString>;
131
+ }, "strip", z.ZodTypeAny, {
132
+ type: "amodal";
133
+ issuer?: string | undefined;
134
+ jwksUrl?: string | undefined;
135
+ }, {
136
+ type: "amodal";
137
+ issuer?: string | undefined;
138
+ jwksUrl?: string | undefined;
139
+ }>;
140
+ export declare const AuthConfigSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
141
+ type: z.ZodLiteral<"none">;
142
+ /** Synthesized user id for the anonymous session. Defaults to `'anonymous'`. */
143
+ userId: z.ZodOptional<z.ZodString>;
144
+ }, "strip", z.ZodTypeAny, {
145
+ type: "none";
146
+ userId?: string | undefined;
147
+ }, {
148
+ type: "none";
149
+ userId?: string | undefined;
150
+ }>, z.ZodObject<{
151
+ type: z.ZodLiteral<"jwt_secret">;
152
+ /** Shared HMAC secret used to verify incoming JWTs. */
153
+ secret: z.ZodString;
154
+ /** HMAC algorithm. Defaults to HS256. */
155
+ algorithm: z.ZodOptional<z.ZodEnum<["HS256", "HS384", "HS512"]>>;
156
+ /** Expected `iss` claim. Optional. */
157
+ issuer: z.ZodOptional<z.ZodString>;
158
+ /** Expected `aud` claim. Optional. */
159
+ audience: z.ZodOptional<z.ZodString>;
160
+ }, "strip", z.ZodTypeAny, {
161
+ type: "jwt_secret";
162
+ secret: string;
163
+ issuer?: string | undefined;
164
+ audience?: string | undefined;
165
+ algorithm?: "HS256" | "HS384" | "HS512" | undefined;
166
+ }, {
167
+ type: "jwt_secret";
168
+ secret: string;
169
+ issuer?: string | undefined;
170
+ audience?: string | undefined;
171
+ algorithm?: "HS256" | "HS384" | "HS512" | undefined;
172
+ }>, z.ZodObject<{
173
+ type: z.ZodLiteral<"oidc">;
174
+ /** OIDC issuer URL — the IdP's discovery base (`https://acme.okta.com`). */
175
+ issuer: z.ZodString;
176
+ clientId: z.ZodString;
177
+ clientSecret: z.ZodString;
178
+ /** Where the IdP redirects back after login. Must be registered with the IdP. */
179
+ callbackUrl: z.ZodString;
180
+ /** OAuth scopes to request. Defaults to `['openid', 'email', 'profile']`. */
181
+ scopes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
182
+ /**
183
+ * HMAC secret used to sign the session JWT stored in the runtime's cookie.
184
+ * Distinct from the IdP — this is purely the runtime's session signing key.
185
+ */
186
+ sessionSecret: z.ZodString;
187
+ /** Cookie name for the session JWT. Defaults to `'amodal_session'`. */
188
+ cookieName: z.ZodOptional<z.ZodString>;
189
+ /** Session TTL in seconds. Defaults to 24h. */
190
+ sessionTtlSeconds: z.ZodOptional<z.ZodNumber>;
191
+ }, "strip", z.ZodTypeAny, {
192
+ type: "oidc";
193
+ issuer: string;
194
+ clientId: string;
195
+ clientSecret: string;
196
+ callbackUrl: string;
197
+ sessionSecret: string;
198
+ scopes?: string[] | undefined;
199
+ cookieName?: string | undefined;
200
+ sessionTtlSeconds?: number | undefined;
201
+ }, {
202
+ type: "oidc";
203
+ issuer: string;
204
+ clientId: string;
205
+ clientSecret: string;
206
+ callbackUrl: string;
207
+ sessionSecret: string;
208
+ scopes?: string[] | undefined;
209
+ cookieName?: string | undefined;
210
+ sessionTtlSeconds?: number | undefined;
211
+ }>, z.ZodObject<{
212
+ type: z.ZodLiteral<"header">;
213
+ headerName: z.ZodOptional<z.ZodString>;
214
+ }, "strip", z.ZodTypeAny, {
215
+ type: "header";
216
+ headerName?: string | undefined;
217
+ }, {
218
+ type: "header";
219
+ headerName?: string | undefined;
220
+ }>, z.ZodObject<{
221
+ type: z.ZodLiteral<"custom">;
222
+ /**
223
+ * Module path (relative to the agent's runtime directory) whose default
224
+ * export implements the `AuthStrategy` interface. The runtime imports
225
+ * this file at startup and validates the shape.
226
+ */
227
+ module: z.ZodString;
228
+ }, "strip", z.ZodTypeAny, {
229
+ type: "custom";
230
+ module: string;
231
+ }, {
232
+ type: "custom";
233
+ module: string;
234
+ }>, z.ZodObject<{
235
+ type: z.ZodLiteral<"amodal">;
236
+ jwksUrl: z.ZodOptional<z.ZodString>;
237
+ issuer: z.ZodOptional<z.ZodString>;
238
+ }, "strip", z.ZodTypeAny, {
239
+ type: "amodal";
240
+ issuer?: string | undefined;
241
+ jwksUrl?: string | undefined;
242
+ }, {
243
+ type: "amodal";
244
+ issuer?: string | undefined;
245
+ jwksUrl?: string | undefined;
246
+ }>]>;
247
+ export type AuthConfig = z.infer<typeof AuthConfigSchema>;
248
+ export type NoneAuthConfig = z.infer<typeof NoneAuthConfigSchema>;
249
+ export type JwtSecretAuthConfig = z.infer<typeof JwtSecretAuthConfigSchema>;
250
+ export type OidcAuthConfig = z.infer<typeof OidcAuthConfigSchema>;
251
+ export type HeaderAuthConfig = z.infer<typeof HeaderAuthConfigSchema>;
252
+ export type CustomAuthConfig = z.infer<typeof CustomAuthConfigSchema>;
253
+ export type AmodalAuthConfig = z.infer<typeof AmodalAuthConfigSchema>;
254
+ /**
255
+ * Parse + validate an `auth` block from agent config. Throws a clear
256
+ * error on any malformed shape so misconfiguration fails at startup
257
+ * rather than at first request. Pass `undefined` / missing config to
258
+ * default to `{type: 'none'}`.
259
+ */
260
+ export declare function parseAuthConfig(raw: unknown): AuthConfig;
261
+ export {};
@@ -0,0 +1,107 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ /**
7
+ * Config-driven auth — discriminated union the agent owner sets in
8
+ * `amodal.json` (or whatever surfaces the runtime through). The host
9
+ * resolves any `env:` references against its secrets store before
10
+ * passing the config to `createAuthStrategy(config)`.
11
+ *
12
+ * {
13
+ * "auth": {
14
+ * "type": "oidc",
15
+ * "issuer": "https://acme.okta.com",
16
+ * ...
17
+ * }
18
+ * }
19
+ */
20
+ import { z } from 'zod';
21
+ const NoneAuthConfigSchema = z.object({
22
+ type: z.literal('none'),
23
+ /** Synthesized user id for the anonymous session. Defaults to `'anonymous'`. */
24
+ userId: z.string().optional(),
25
+ });
26
+ const JwtSecretAuthConfigSchema = z.object({
27
+ type: z.literal('jwt_secret'),
28
+ /** Shared HMAC secret used to verify incoming JWTs. */
29
+ secret: z.string().min(1),
30
+ /** HMAC algorithm. Defaults to HS256. */
31
+ algorithm: z.enum(['HS256', 'HS384', 'HS512']).optional(),
32
+ /** Expected `iss` claim. Optional. */
33
+ issuer: z.string().optional(),
34
+ /** Expected `aud` claim. Optional. */
35
+ audience: z.string().optional(),
36
+ });
37
+ const OidcAuthConfigSchema = z.object({
38
+ type: z.literal('oidc'),
39
+ /** OIDC issuer URL — the IdP's discovery base (`https://acme.okta.com`). */
40
+ issuer: z.string().url(),
41
+ clientId: z.string().min(1),
42
+ clientSecret: z.string().min(1),
43
+ /** Where the IdP redirects back after login. Must be registered with the IdP. */
44
+ callbackUrl: z.string().url(),
45
+ /** OAuth scopes to request. Defaults to `['openid', 'email', 'profile']`. */
46
+ scopes: z.array(z.string()).optional(),
47
+ /**
48
+ * HMAC secret used to sign the session JWT stored in the runtime's cookie.
49
+ * Distinct from the IdP — this is purely the runtime's session signing key.
50
+ */
51
+ sessionSecret: z.string().min(16),
52
+ /** Cookie name for the session JWT. Defaults to `'amodal_session'`. */
53
+ cookieName: z.string().optional(),
54
+ /** Session TTL in seconds. Defaults to 24h. */
55
+ sessionTtlSeconds: z.number().int().positive().optional(),
56
+ });
57
+ const HeaderAuthConfigSchema = z.object({
58
+ type: z.literal('header'),
59
+ headerName: z.string().optional(),
60
+ });
61
+ const CustomAuthConfigSchema = z.object({
62
+ type: z.literal('custom'),
63
+ /**
64
+ * Module path (relative to the agent's runtime directory) whose default
65
+ * export implements the `AuthStrategy` interface. The runtime imports
66
+ * this file at startup and validates the shape.
67
+ */
68
+ module: z.string().min(1),
69
+ });
70
+ /**
71
+ * "Sign in with Amodal" — verifies platform JWTs minted by the Amodal
72
+ * cloud (or any self-hosted Amodal-equivalent platform). Agent owners on
73
+ * the Amodal cloud need zero config; the cloud's deploy pipeline injects
74
+ * the JWKS URL via the `AMODAL_JWKS_URL` env var. Self-hosters override
75
+ * via the optional `jwksUrl` field.
76
+ */
77
+ const AmodalAuthConfigSchema = z.object({
78
+ type: z.literal('amodal'),
79
+ jwksUrl: z.string().url().optional(),
80
+ issuer: z.string().optional(),
81
+ });
82
+ export const AuthConfigSchema = z.discriminatedUnion('type', [
83
+ NoneAuthConfigSchema,
84
+ JwtSecretAuthConfigSchema,
85
+ OidcAuthConfigSchema,
86
+ HeaderAuthConfigSchema,
87
+ CustomAuthConfigSchema,
88
+ AmodalAuthConfigSchema,
89
+ ]);
90
+ /**
91
+ * Parse + validate an `auth` block from agent config. Throws a clear
92
+ * error on any malformed shape so misconfiguration fails at startup
93
+ * rather than at first request. Pass `undefined` / missing config to
94
+ * default to `{type: 'none'}`.
95
+ */
96
+ export function parseAuthConfig(raw) {
97
+ if (raw == null)
98
+ return { type: 'none' };
99
+ const parsed = AuthConfigSchema.safeParse(raw);
100
+ if (!parsed.success) {
101
+ throw new Error(`Invalid auth config: ${parsed.error.errors
102
+ .map((e) => `${e.path.join('.') || '<root>'}: ${e.message}`)
103
+ .join('; ')}`);
104
+ }
105
+ return parsed.data;
106
+ }
107
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/auth/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ export {};
@@ -0,0 +1,85 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ import { describe, it, expect } from 'vitest';
7
+ import { parseAuthConfig } from './config.js';
8
+ describe('parseAuthConfig', () => {
9
+ it('defaults to {type: none} when undefined', () => {
10
+ expect(parseAuthConfig(undefined)).toEqual({ type: 'none' });
11
+ expect(parseAuthConfig(null)).toEqual({ type: 'none' });
12
+ });
13
+ it('accepts a valid none config', () => {
14
+ expect(parseAuthConfig({ type: 'none' })).toEqual({ type: 'none' });
15
+ expect(parseAuthConfig({ type: 'none', userId: 'guest' })).toEqual({
16
+ type: 'none',
17
+ userId: 'guest',
18
+ });
19
+ });
20
+ it('accepts a valid jwt_secret config', () => {
21
+ const cfg = parseAuthConfig({ type: 'jwt_secret', secret: 'sssh' });
22
+ expect(cfg.type).toBe('jwt_secret');
23
+ });
24
+ it('rejects jwt_secret without secret', () => {
25
+ expect(() => parseAuthConfig({ type: 'jwt_secret' })).toThrow(/secret/);
26
+ });
27
+ it('accepts a valid oidc config', () => {
28
+ const cfg = parseAuthConfig({
29
+ type: 'oidc',
30
+ issuer: 'https://acme.okta.com',
31
+ clientId: 'abc',
32
+ clientSecret: 'shh',
33
+ callbackUrl: 'https://agent.example.com/auth/callback',
34
+ sessionSecret: 'a-secret-of-at-least-16-chars-long',
35
+ });
36
+ expect(cfg.type).toBe('oidc');
37
+ });
38
+ it('rejects oidc with a non-URL issuer', () => {
39
+ expect(() => parseAuthConfig({
40
+ type: 'oidc',
41
+ issuer: 'not-a-url',
42
+ clientId: 'a',
43
+ clientSecret: 'b',
44
+ callbackUrl: 'https://x.test/cb',
45
+ sessionSecret: 'a-secret-of-at-least-16-chars-long',
46
+ })).toThrow(/url/i);
47
+ });
48
+ it('rejects oidc with too-short sessionSecret', () => {
49
+ expect(() => parseAuthConfig({
50
+ type: 'oidc',
51
+ issuer: 'https://x.test',
52
+ clientId: 'a',
53
+ clientSecret: 'b',
54
+ callbackUrl: 'https://x.test/cb',
55
+ sessionSecret: 'short',
56
+ })).toThrow(/sessionSecret/);
57
+ });
58
+ it('accepts custom config with module path', () => {
59
+ expect(parseAuthConfig({ type: 'custom', module: './my-auth.ts' })).toEqual({
60
+ type: 'custom',
61
+ module: './my-auth.ts',
62
+ });
63
+ });
64
+ it('accepts a bare amodal config (zero-config sign-in with Amodal)', () => {
65
+ expect(parseAuthConfig({ type: 'amodal' })).toEqual({ type: 'amodal' });
66
+ });
67
+ it('accepts amodal config with optional jwksUrl + issuer overrides', () => {
68
+ expect(parseAuthConfig({
69
+ type: 'amodal',
70
+ jwksUrl: 'https://example.com/.well-known/jwks.json',
71
+ issuer: 'custom-issuer',
72
+ })).toEqual({
73
+ type: 'amodal',
74
+ jwksUrl: 'https://example.com/.well-known/jwks.json',
75
+ issuer: 'custom-issuer',
76
+ });
77
+ });
78
+ it('rejects amodal config with a non-URL jwksUrl', () => {
79
+ expect(() => parseAuthConfig({ type: 'amodal', jwksUrl: 'not-a-url' })).toThrow(/url/i);
80
+ });
81
+ it('rejects unknown type', () => {
82
+ expect(() => parseAuthConfig({ type: 'wat', whatever: true })).toThrow(/Invalid auth config/);
83
+ });
84
+ });
85
+ //# sourceMappingURL=config.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.js","sourceRoot":"","sources":["../../../src/auth/config.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ /**
7
+ * Translate a parsed `AuthConfig` into an `AuthStrategy` instance.
8
+ * The host (cloud's runtime, self-hoster's app) calls this once at boot
9
+ * with the agent's already-resolved config.
10
+ */
11
+ import type { AuthConfig } from './config.js';
12
+ import type { AuthStrategy } from './types.js';
13
+ /**
14
+ * Build an `AuthStrategy` from a validated `AuthConfig`. For `'custom'`
15
+ * type configs this is async (the user's module is dynamically imported);
16
+ * everything else resolves synchronously but the function is uniformly
17
+ * async for ergonomics.
18
+ */
19
+ export declare function createAuthStrategy(config: AuthConfig): Promise<AuthStrategy>;
@@ -0,0 +1,57 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ import { NoneAuthStrategy } from './strategies/none.js';
7
+ import { HeaderAuthStrategy } from './strategies/header.js';
8
+ import { JwtSecretAuthStrategy } from './strategies/jwt-secret.js';
9
+ import { OidcAuthStrategy } from './strategies/oidc.js';
10
+ import { AmodalAuthStrategy } from './strategies/amodal.js';
11
+ import { loadCustomStrategy } from './strategies/custom-loader.js';
12
+ /**
13
+ * Build an `AuthStrategy` from a validated `AuthConfig`. For `'custom'`
14
+ * type configs this is async (the user's module is dynamically imported);
15
+ * everything else resolves synchronously but the function is uniformly
16
+ * async for ergonomics.
17
+ */
18
+ export async function createAuthStrategy(config) {
19
+ switch (config.type) {
20
+ case 'none':
21
+ return new NoneAuthStrategy(config.userId !== undefined ? { userId: config.userId } : {});
22
+ case 'header':
23
+ return new HeaderAuthStrategy(config.headerName !== undefined ? { headerName: config.headerName } : {});
24
+ case 'jwt_secret':
25
+ return new JwtSecretAuthStrategy({
26
+ secret: config.secret,
27
+ ...(config.algorithm ? { algorithm: config.algorithm } : {}),
28
+ ...(config.issuer ? { issuer: config.issuer } : {}),
29
+ ...(config.audience ? { audience: config.audience } : {}),
30
+ });
31
+ case 'oidc':
32
+ return new OidcAuthStrategy({
33
+ issuer: config.issuer,
34
+ clientId: config.clientId,
35
+ clientSecret: config.clientSecret,
36
+ callbackUrl: config.callbackUrl,
37
+ ...(config.scopes ? { scopes: config.scopes } : {}),
38
+ sessionSecret: config.sessionSecret,
39
+ ...(config.cookieName ? { cookieName: config.cookieName } : {}),
40
+ ...(config.sessionTtlSeconds
41
+ ? { sessionTtlSeconds: config.sessionTtlSeconds }
42
+ : {}),
43
+ });
44
+ case 'custom':
45
+ return loadCustomStrategy(config.module);
46
+ case 'amodal':
47
+ return new AmodalAuthStrategy({
48
+ ...(config.jwksUrl ? { jwksUrl: config.jwksUrl } : {}),
49
+ ...(config.issuer ? { issuer: config.issuer } : {}),
50
+ });
51
+ default: {
52
+ const _exhaustive = config;
53
+ throw new Error(`Unknown auth config type: ${JSON.stringify(_exhaustive)}`);
54
+ }
55
+ }
56
+ }
57
+ //# sourceMappingURL=factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../../src/auth/factory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ export {};
@@ -0,0 +1,60 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ import { describe, it, expect, vi } from 'vitest';
7
+ import { createAuthStrategy } from './factory.js';
8
+ vi.mock('openid-client', () => ({
9
+ // OidcAuthStrategy doesn't call discovery() at construction — it
10
+ // lazy-init's on first request. The factory only needs the module
11
+ // to import cleanly.
12
+ discovery: vi.fn(),
13
+ randomPKCECodeVerifier: vi.fn(),
14
+ calculatePKCECodeChallenge: vi.fn(),
15
+ randomState: vi.fn(),
16
+ buildAuthorizationUrl: vi.fn(),
17
+ authorizationCodeGrant: vi.fn(),
18
+ }));
19
+ describe('createAuthStrategy', () => {
20
+ it('returns NoneAuthStrategy for type: none', async () => {
21
+ const s = await createAuthStrategy({ type: 'none' });
22
+ expect(s.name).toBe('none');
23
+ });
24
+ it('returns HeaderAuthStrategy for type: header', async () => {
25
+ const s = await createAuthStrategy({ type: 'header' });
26
+ expect(s.name).toBe('header');
27
+ });
28
+ it('returns JwtSecretAuthStrategy for type: jwt_secret', async () => {
29
+ const s = await createAuthStrategy({ type: 'jwt_secret', secret: 'shh' });
30
+ expect(s.name).toBe('jwt-secret');
31
+ });
32
+ it('returns OidcAuthStrategy for type: oidc', async () => {
33
+ const s = await createAuthStrategy({
34
+ type: 'oidc',
35
+ issuer: 'https://acme.okta.com',
36
+ clientId: 'abc',
37
+ clientSecret: 'shh',
38
+ callbackUrl: 'https://agent.example.com/auth/callback',
39
+ sessionSecret: 'a-secret-of-at-least-16-chars-long',
40
+ });
41
+ expect(s.name).toBe('oidc');
42
+ expect(s.routes).toBeDefined();
43
+ });
44
+ it('returns AmodalAuthStrategy for type: amodal', async () => {
45
+ const s = await createAuthStrategy({ type: 'amodal' });
46
+ expect(s.name).toBe('amodal');
47
+ });
48
+ it('passes overrides through to AmodalAuthStrategy', async () => {
49
+ const s = await createAuthStrategy({
50
+ type: 'amodal',
51
+ jwksUrl: 'https://example.com/.well-known/jwks.json',
52
+ issuer: 'custom-issuer',
53
+ });
54
+ expect(s.name).toBe('amodal');
55
+ });
56
+ it('throws when custom module fails to load', async () => {
57
+ await expect(createAuthStrategy({ type: 'custom', module: '/nonexistent/path.ts' })).rejects.toThrow(/Failed to load custom auth strategy/);
58
+ });
59
+ });
60
+ //# sourceMappingURL=factory.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.test.js","sourceRoot":"","sources":["../../../src/auth/factory.test.ts"],"names":[],"mappings":"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"}