@ontrails/permits 1.0.0-beta.15 → 1.0.0-beta.16

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 (70) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/README.md +30 -22
  3. package/package.json +12 -3
  4. package/src/adapters/adapter.ts +41 -0
  5. package/src/{connectors → adapters}/jwt.ts +148 -21
  6. package/src/auth-resource.ts +81 -18
  7. package/src/boundary.ts +200 -0
  8. package/src/errors.ts +1 -18
  9. package/src/extraction.ts +22 -16
  10. package/src/index.ts +22 -10
  11. package/src/trails/auth-verify.ts +11 -13
  12. package/.turbo/turbo-build.log +0 -1
  13. package/.turbo/turbo-lint.log +0 -3
  14. package/.turbo/turbo-typecheck.log +0 -1
  15. package/dist/auth-layer.d.ts +0 -18
  16. package/dist/auth-layer.d.ts.map +0 -1
  17. package/dist/auth-layer.js +0 -56
  18. package/dist/auth-layer.js.map +0 -1
  19. package/dist/auth-resource.d.ts +0 -11
  20. package/dist/auth-resource.d.ts.map +0 -1
  21. package/dist/auth-resource.js +0 -22
  22. package/dist/auth-resource.js.map +0 -1
  23. package/dist/connectors/connector.d.ts +0 -26
  24. package/dist/connectors/connector.d.ts.map +0 -1
  25. package/dist/connectors/connector.js +0 -2
  26. package/dist/connectors/connector.js.map +0 -1
  27. package/dist/connectors/jwt.d.ts +0 -25
  28. package/dist/connectors/jwt.d.ts.map +0 -1
  29. package/dist/connectors/jwt.js +0 -148
  30. package/dist/connectors/jwt.js.map +0 -1
  31. package/dist/errors.d.ts +0 -15
  32. package/dist/errors.d.ts.map +0 -1
  33. package/dist/errors.js +0 -15
  34. package/dist/errors.js.map +0 -1
  35. package/dist/extraction.d.ts +0 -20
  36. package/dist/extraction.d.ts.map +0 -1
  37. package/dist/extraction.js +0 -2
  38. package/dist/extraction.js.map +0 -1
  39. package/dist/index.d.ts +0 -11
  40. package/dist/index.d.ts.map +0 -1
  41. package/dist/index.js +0 -11
  42. package/dist/index.js.map +0 -1
  43. package/dist/permit.d.ts +0 -26
  44. package/dist/permit.d.ts.map +0 -1
  45. package/dist/permit.js +0 -17
  46. package/dist/permit.js.map +0 -1
  47. package/dist/rules.d.ts +0 -47
  48. package/dist/rules.d.ts.map +0 -1
  49. package/dist/rules.js +0 -127
  50. package/dist/rules.js.map +0 -1
  51. package/dist/testing.d.ts +0 -20
  52. package/dist/testing.d.ts.map +0 -1
  53. package/dist/testing.js +0 -22
  54. package/dist/testing.js.map +0 -1
  55. package/dist/trails/auth-verify.d.ts +0 -22
  56. package/dist/trails/auth-verify.d.ts.map +0 -1
  57. package/dist/trails/auth-verify.js +0 -85
  58. package/dist/trails/auth-verify.js.map +0 -1
  59. package/src/__tests__/auth-layer.test.ts +0 -130
  60. package/src/__tests__/auth-resource.test.ts +0 -62
  61. package/src/__tests__/auth-verify.test.ts +0 -278
  62. package/src/__tests__/connector.test.ts +0 -338
  63. package/src/__tests__/permit.test.ts +0 -122
  64. package/src/__tests__/rules.test.ts +0 -239
  65. package/src/__tests__/testing.test.ts +0 -57
  66. package/src/auth-layer.ts +0 -80
  67. package/src/connectors/connector.ts +0 -35
  68. package/tsconfig.json +0 -9
  69. package/tsconfig.tests.json +0 -10
  70. package/tsconfig.tsbuildinfo +0 -1
@@ -0,0 +1,200 @@
1
+ import type {
2
+ AnyResource,
3
+ BasePermit,
4
+ ResourceOverrideMap,
5
+ SurfaceConfigValues,
6
+ Topo,
7
+ } from '@ontrails/core';
8
+ import {
9
+ AuthError,
10
+ Result,
11
+ ValidationError,
12
+ basePermitSchema,
13
+ resolveResourceConfig,
14
+ } from '@ontrails/core';
15
+
16
+ import type { AuthAdapter } from './adapters/adapter.js';
17
+ import { authAdapterSchema, authErrorSchema } from './adapters/adapter.js';
18
+ import type { PermitExtractionInput } from './extraction.js';
19
+ import { permitExtractionInputSchema } from './extraction.js';
20
+
21
+ /** Resource id of the auth adapter resource provided by `@ontrails/permits`. */
22
+ export const AUTH_RESOURCE_ID = 'auth';
23
+
24
+ type LocatedAuthResource =
25
+ | { readonly kind: 'override'; readonly value: unknown }
26
+ | { readonly kind: 'declared'; readonly resource: AnyResource };
27
+
28
+ export interface ResolvePermitFromBearerTokenOptions {
29
+ readonly bearerToken: string;
30
+ readonly graph: Topo;
31
+ readonly requestId: string;
32
+ readonly surface: PermitExtractionInput['surface'];
33
+ readonly resources?: ResourceOverrideMap | undefined;
34
+ readonly configValues?: SurfaceConfigValues | undefined;
35
+ readonly headers?: Headers | undefined;
36
+ readonly sessionId?: string | undefined;
37
+ readonly cwd?: string | undefined;
38
+ readonly env?: Record<string, string | undefined> | undefined;
39
+ readonly workspaceRoot?: string | undefined;
40
+ readonly missingAuthResourceMessage?: string | undefined;
41
+ readonly nullPermitMessage?: string | undefined;
42
+ }
43
+
44
+ /** Resolve the auth resource override or registered resource on the topo. */
45
+ const lookupAuthResource = (
46
+ graph: Topo,
47
+ resources: ResourceOverrideMap | undefined,
48
+ missingAuthResourceMessage: string | undefined
49
+ ): Result<LocatedAuthResource, ValidationError> => {
50
+ if (resources !== undefined && Object.hasOwn(resources, AUTH_RESOURCE_ID)) {
51
+ return Result.ok({
52
+ kind: 'override',
53
+ value: resources[AUTH_RESOURCE_ID],
54
+ });
55
+ }
56
+ const declared = graph.getResource(AUTH_RESOURCE_ID);
57
+ if (declared !== undefined) {
58
+ return Result.ok({ kind: 'declared', resource: declared });
59
+ }
60
+ return Result.err(
61
+ new ValidationError(
62
+ missingAuthResourceMessage ??
63
+ 'Bearer token auth requires an auth adapter. Register authResource from @ontrails/permits in your topo.'
64
+ )
65
+ );
66
+ };
67
+
68
+ /**
69
+ * Materialize the auth adapter from an override or by invoking the declared
70
+ * resource's `create()` factory.
71
+ */
72
+ const materializeAuthAdapter = async (
73
+ resolved: LocatedAuthResource,
74
+ options: Pick<
75
+ ResolvePermitFromBearerTokenOptions,
76
+ 'configValues' | 'cwd' | 'env' | 'workspaceRoot'
77
+ >
78
+ ): Promise<Result<AuthAdapter, Error>> => {
79
+ if (resolved.kind === 'override') {
80
+ const parsed = authAdapterSchema.safeParse(resolved.value);
81
+ if (!parsed.success) {
82
+ return Result.err(
83
+ new ValidationError(
84
+ 'Override for resource "auth" does not expose an authenticate() function.'
85
+ )
86
+ );
87
+ }
88
+ return Result.ok(resolved.value as AuthAdapter);
89
+ }
90
+
91
+ const cwd = options.cwd ?? process.cwd();
92
+ const configResult = resolveResourceConfig(
93
+ resolved.resource,
94
+ options.configValues
95
+ );
96
+ if (configResult.isErr()) {
97
+ return configResult;
98
+ }
99
+ const created = await resolved.resource.create({
100
+ config: configResult.value,
101
+ cwd,
102
+ env: options.env ?? {},
103
+ workspaceRoot: options.workspaceRoot ?? cwd,
104
+ });
105
+ if (created.isErr()) {
106
+ return created;
107
+ }
108
+ const parsed = authAdapterSchema.safeParse(created.value);
109
+ if (!parsed.success) {
110
+ return Result.err(
111
+ new ValidationError(
112
+ 'Auth resource factory returned a value without an authenticate() function.'
113
+ )
114
+ );
115
+ }
116
+ return Result.ok(created.value as AuthAdapter);
117
+ };
118
+
119
+ /**
120
+ * Resolve a surface-extracted bearer token to a `BasePermit`.
121
+ *
122
+ * Surfaces own credential extraction. This helper owns the shared auth
123
+ * adapter lookup, invocation, error normalization, and BasePermit projection.
124
+ */
125
+ export const resolvePermitFromBearerToken = async (
126
+ options: ResolvePermitFromBearerTokenOptions
127
+ ): Promise<Result<BasePermit, Error>> => {
128
+ const located = lookupAuthResource(
129
+ options.graph,
130
+ options.resources,
131
+ options.missingAuthResourceMessage
132
+ );
133
+ if (located.isErr()) {
134
+ return located;
135
+ }
136
+ const adapterResult = await materializeAuthAdapter(located.value, options);
137
+ if (adapterResult.isErr()) {
138
+ return adapterResult;
139
+ }
140
+ const inputResult = permitExtractionInputSchema.safeParse({
141
+ bearerToken: options.bearerToken,
142
+ ...(options.headers === undefined ? {} : { headers: options.headers }),
143
+ requestId: options.requestId,
144
+ ...(options.sessionId === undefined
145
+ ? {}
146
+ : { sessionId: options.sessionId }),
147
+ surface: options.surface,
148
+ });
149
+ if (!inputResult.success) {
150
+ return Result.err(
151
+ new ValidationError('Invalid bearer token extraction input.', {
152
+ context: { issues: inputResult.error.issues },
153
+ })
154
+ );
155
+ }
156
+ let authResult: Awaited<ReturnType<AuthAdapter['authenticate']>>;
157
+ try {
158
+ authResult = await adapterResult.value.authenticate(inputResult.data);
159
+ } catch (error) {
160
+ const errorOptions =
161
+ error instanceof Error
162
+ ? { cause: error, context: { code: 'invalid_token' } }
163
+ : { context: { code: 'invalid_token' } };
164
+ return Result.err(
165
+ new AuthError('Auth adapter threw while authenticating bearer token', {
166
+ ...errorOptions,
167
+ })
168
+ );
169
+ }
170
+ if (authResult.isErr()) {
171
+ const parsedError = authErrorSchema.safeParse(authResult.error);
172
+ const { code, message } = parsedError.success
173
+ ? parsedError.data
174
+ : {
175
+ code: 'invalid_token' as const,
176
+ message: 'Auth adapter returned a malformed error',
177
+ };
178
+ return Result.err(new AuthError(message, { context: { code } }));
179
+ }
180
+ if (authResult.value === null) {
181
+ return Result.err(
182
+ new AuthError(
183
+ options.nullPermitMessage ??
184
+ 'Auth adapter did not produce a permit for bearer token',
185
+ {
186
+ context: { code: 'missing_credentials' },
187
+ }
188
+ )
189
+ );
190
+ }
191
+ const permit = basePermitSchema.safeParse(authResult.value);
192
+ if (!permit.success) {
193
+ return Result.err(
194
+ new AuthError('Auth adapter returned a malformed permit', {
195
+ context: { code: 'invalid_token', issues: permit.error.issues },
196
+ })
197
+ );
198
+ }
199
+ return Result.ok(permit.data);
200
+ };
package/src/errors.ts CHANGED
@@ -1,18 +1 @@
1
- import { PermissionError } from '@ontrails/core';
2
-
3
- /**
4
- * Error returned when permit scope enforcement fails.
5
- *
6
- * Extends `PermissionError` (category `'permission'`, HTTP 403) because
7
- * it represents an *authorization* failure — the caller's identity is known
8
- * but lacks the required scopes.
9
- */
10
- export class PermitError extends PermissionError {
11
- constructor(
12
- message: string,
13
- options?: { cause?: Error; context?: Record<string, unknown> }
14
- ) {
15
- super(message, options);
16
- this.name = 'PermitError';
17
- }
18
- }
1
+ export { PermitError } from '@ontrails/core';
package/src/extraction.ts CHANGED
@@ -1,19 +1,25 @@
1
+ import { z } from 'zod';
2
+
3
+ export const permitExtractionInputSchema = z
4
+ .object({
5
+ /** Bearer token from Authorization header or equivalent. */
6
+ bearerToken: z.string().optional(),
7
+ /** Raw headers (HTTP surface only, typically). */
8
+ headers: z.instanceof(Headers).optional(),
9
+ /** Correlation ID for tracing. */
10
+ requestId: z.string(),
11
+ /** Session identifier from transport handshake. */
12
+ sessionId: z.string().optional(),
13
+ /** Which surface produced this extraction. */
14
+ surface: z.enum(['http', 'mcp', 'cli']),
15
+ })
16
+ .readonly();
17
+
1
18
  /**
2
- * Normalized input for auth connectors.
19
+ * Normalized input for auth adapters.
3
20
  *
4
- * Each trailhead extracts raw credentials from its transport and normalizes
5
- * them into this shape. No trailhead types (Request, McpSession, etc.) cross
6
- * into core only this interface.
21
+ * Each surface extracts raw credentials from its transport and normalizes them
22
+ * into this shape. No surface types (Request, McpSession, etc.) cross into
23
+ * core -- only this schema-derived contract.
7
24
  */
8
- export interface PermitExtractionInput {
9
- /** Which trailhead produced this extraction */
10
- readonly trailhead: 'http' | 'mcp' | 'cli';
11
- /** Bearer token from Authorization header or equivalent */
12
- readonly bearerToken?: string;
13
- /** Session identifier from transport handshake */
14
- readonly sessionId?: string;
15
- /** Raw headers (HTTP trailhead only, typically) */
16
- readonly headers?: Headers;
17
- /** Correlation ID for tracing */
18
- readonly requestId: string;
19
- }
25
+ export type PermitExtractionInput = z.infer<typeof permitExtractionInputSchema>;
package/src/index.ts CHANGED
@@ -1,17 +1,29 @@
1
1
  export {
2
- type AuthConnector,
3
- type AuthCredentials,
2
+ authAdapterSchema,
3
+ authErrorSchema,
4
+ type AuthAdapter,
4
5
  type AuthError,
5
- } from './connectors/connector.js';
6
+ } from './adapters/adapter.js';
6
7
  export {
7
- createJwtConnector,
8
- type JwtConnectorOptions,
9
- } from './connectors/jwt.js';
10
- export { authLayer } from './auth-layer.js';
11
- export { authResource } from './auth-resource.js';
8
+ createJwtAdapter,
9
+ type JwtAlgorithm,
10
+ type JwtAdapterOptions,
11
+ } from './adapters/jwt.js';
12
+ export {
13
+ authResource,
14
+ authResourceConfigSchema,
15
+ type AuthResourceConfig,
16
+ } from './auth-resource.js';
17
+ export {
18
+ AUTH_RESOURCE_ID,
19
+ resolvePermitFromBearerToken,
20
+ type ResolvePermitFromBearerTokenOptions,
21
+ } from './boundary.js';
12
22
  export { authVerify } from './trails/auth-verify.js';
13
23
  export { PermitError } from './errors.js';
14
- export { type PermitExtractionInput } from './extraction.js';
24
+ export {
25
+ permitExtractionInputSchema,
26
+ type PermitExtractionInput,
27
+ } from './extraction.js';
15
28
  export { type Permit, getPermit } from './permit.js';
16
29
  export { validatePermits, type PermitDiagnostic } from './rules.js';
17
- export { createTestPermit, createPermitForTrail } from './testing.js';
@@ -1,4 +1,4 @@
1
- import { Result, TRAILHEAD_KEY, trail } from '@ontrails/core';
1
+ import { Result, SURFACE_KEY, trail } from '@ontrails/core';
2
2
  import type { TrailContext } from '@ontrails/core';
3
3
  import { z } from 'zod';
4
4
 
@@ -30,32 +30,30 @@ const toOutputPermit = (permit: Permit) => ({
30
30
  scopes: [...permit.scopes],
31
31
  });
32
32
 
33
- const isTrailhead = (
33
+ const isSurfaceName = (
34
34
  value: unknown
35
- ): value is PermitExtractionInput['trailhead'] =>
35
+ ): value is PermitExtractionInput['surface'] =>
36
36
  value === 'http' || value === 'mcp' || value === 'cli';
37
37
 
38
- const getTrailhead = (
39
- ctx: TrailContext
40
- ): PermitExtractionInput['trailhead'] => {
41
- const trailhead = ctx.extensions?.[TRAILHEAD_KEY];
42
- return isTrailhead(trailhead) ? trailhead : 'http';
38
+ const getSurface = (ctx: TrailContext): PermitExtractionInput['surface'] => {
39
+ const surface = ctx.extensions?.[SURFACE_KEY];
40
+ return isSurfaceName(surface) ? surface : 'http';
43
41
  };
44
42
 
45
43
  /**
46
44
  * Infrastructure trail that verifies a bearer token and returns the resolved permit.
47
45
  *
48
- * Reads the auth connector from `authResource` — the connector is configured
49
- * at bootstrap (e.g. JWT with HMAC secret). The mock connector always
46
+ * Reads the auth adapter from `authResource` — the adapter is configured
47
+ * at bootstrap (e.g. JWT with HMAC secret). The mock adapter always
50
48
  * succeeds with a null permit, so `testAll(app)` works without configuration.
51
49
  */
52
50
  export const authVerify = trail('auth.verify', {
53
51
  blaze: async (input, ctx) => {
54
- const connector = authResource.from(ctx);
55
- const result = await connector.authenticate({
52
+ const adapter = authResource.from(ctx);
53
+ const result = await adapter.authenticate({
56
54
  bearerToken: input.token,
57
55
  requestId: ctx.requestId,
58
- trailhead: getTrailhead(ctx),
56
+ surface: getSurface(ctx),
59
57
  });
60
58
 
61
59
  if (result.isErr()) {
@@ -1 +0,0 @@
1
- $ tsc -b
@@ -1,3 +0,0 @@
1
- $ oxlint ./src
2
- Found 0 warnings and 0 errors.
3
- Finished in 73ms on 18 files with 93 rules using 24 threads.
@@ -1 +0,0 @@
1
- $ tsc --noEmit
@@ -1,18 +0,0 @@
1
- import type { Layer } from '@ontrails/core';
2
- /**
3
- * A {@link Layer} that enforces permit scopes declared on trails.
4
- *
5
- * The layer reads the trail's `permit` field (a `PermitRequirement`):
6
- *
7
- * - If `permit` is `'public'` or `undefined` the layer passes through.
8
- * - If `permit` has `scopes`, the layer checks that `ctx.permit` contains
9
- * all required scopes. A superset is fine; missing scopes produce a
10
- * `PermitError`.
11
- *
12
- * Because `ctx.cross()` re-enters `executeTrail` (which applies layers),
13
- * this layer automatically re-checks on every invocation in a crossing chain.
14
- * No special crossing-chain handling is needed — it is built into the
15
- * architecture.
16
- */
17
- export declare const authLayer: Layer;
18
- //# sourceMappingURL=auth-layer.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"auth-layer.d.ts","sourceRoot":"","sources":["../src/auth-layer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AA6B5C;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,SAAS,EAAE,KAkCvB,CAAC"}
@@ -1,56 +0,0 @@
1
- import { Result } from '@ontrails/core';
2
- import { PermitError } from './errors.js';
3
- import { getPermit } from './permit.js';
4
- // ---------------------------------------------------------------------------
5
- // Helpers (defined before callers — no use-before-define)
6
- // ---------------------------------------------------------------------------
7
- /**
8
- * Returns `true` when the permit requirement means "no enforcement needed."
9
- * Either the trail hasn't declared a permit posture or has explicitly
10
- * opted out with `'public'`.
11
- */
12
- const isPassThrough = (requirement) => requirement === undefined || requirement === 'public';
13
- /** Returns scopes present in `required` but absent from `held`. */
14
- const findMissing = (required, held) => required.filter((s) => !held.includes(s));
15
- // ---------------------------------------------------------------------------
16
- // Auth layer
17
- // ---------------------------------------------------------------------------
18
- /**
19
- * A {@link Layer} that enforces permit scopes declared on trails.
20
- *
21
- * The layer reads the trail's `permit` field (a `PermitRequirement`):
22
- *
23
- * - If `permit` is `'public'` or `undefined` the layer passes through.
24
- * - If `permit` has `scopes`, the layer checks that `ctx.permit` contains
25
- * all required scopes. A superset is fine; missing scopes produce a
26
- * `PermitError`.
27
- *
28
- * Because `ctx.cross()` re-enters `executeTrail` (which applies layers),
29
- * this layer automatically re-checks on every invocation in a crossing chain.
30
- * No special crossing-chain handling is needed — it is built into the
31
- * architecture.
32
- */
33
- export const authLayer = {
34
- description: 'Enforces permit scopes declared on trails',
35
- name: 'auth',
36
- wrap: (_trail, impl) => {
37
- const requirement = _trail.permit;
38
- if (isPassThrough(requirement)) {
39
- return impl;
40
- }
41
- return (input, ctx) => {
42
- const permit = getPermit(ctx);
43
- if (!permit) {
44
- return Promise.resolve(Result.err(new PermitError('No permit provided')));
45
- }
46
- const missing = findMissing(requirement.scopes, permit.scopes);
47
- if (missing.length > 0) {
48
- return Promise.resolve(Result.err(new PermitError(`Missing scopes: ${missing.join(', ')}`, {
49
- context: { missing, required: requirement.scopes },
50
- })));
51
- }
52
- return Promise.resolve(impl(input, ctx));
53
- };
54
- },
55
- };
56
- //# sourceMappingURL=auth-layer.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"auth-layer.js","sourceRoot":"","sources":["../src/auth-layer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAGxC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,8EAA8E;AAC9E,0DAA0D;AAC1D,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,aAAa,GAAG,CACpB,WAAoB,EACiB,EAAE,CACvC,WAAW,KAAK,SAAS,IAAI,WAAW,KAAK,QAAQ,CAAC;AAExD,mEAAmE;AACnE,MAAM,WAAW,GAAG,CAClB,QAA2B,EAC3B,IAAuB,EACJ,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AAElE,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,SAAS,GAAU;IAC9B,WAAW,EAAE,2CAA2C;IACxD,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE;QACrB,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC;QAElC,IAAI,aAAa,CAAC,WAAW,CAAC,EAAE,CAAC;YAC/B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;YACpB,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;YAE9B,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,OAAO,OAAO,CAAC,OAAO,CACpB,MAAM,CAAC,GAAG,CAAC,IAAI,WAAW,CAAC,oBAAoB,CAAC,CAAC,CAClD,CAAC;YACJ,CAAC;YAED,MAAM,OAAO,GAAG,WAAW,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YAE/D,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACvB,OAAO,OAAO,CAAC,OAAO,CACpB,MAAM,CAAC,GAAG,CACR,IAAI,WAAW,CAAC,mBAAmB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE;oBACvD,OAAO,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE;iBACnD,CAAC,CACH,CACF,CAAC;YACJ,CAAC;YAED,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;QAC3C,CAAC,CAAC;IACJ,CAAC;CACF,CAAC"}
@@ -1,11 +0,0 @@
1
- import type { AuthConnector } from './connectors/connector.js';
2
- /**
3
- * Auth resource — manages the auth connector lifecycle.
4
- *
5
- * The v1 factory returns a no-op connector that always succeeds (null permit).
6
- * Real connector configuration will come through `ResourceSpec.config`
7
- * (TRL-91). The mock factory provides a synthetic connector that always
8
- * succeeds.
9
- */
10
- export declare const authResource: import("@ontrails/core").Resource<AuthConnector>;
11
- //# sourceMappingURL=auth-resource.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"auth-resource.d.ts","sourceRoot":"","sources":["../src/auth-resource.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,kDAavB,CAAC"}
@@ -1,22 +0,0 @@
1
- import { Result, resource } from '@ontrails/core';
2
- /**
3
- * Auth resource — manages the auth connector lifecycle.
4
- *
5
- * The v1 factory returns a no-op connector that always succeeds (null permit).
6
- * Real connector configuration will come through `ResourceSpec.config`
7
- * (TRL-91). The mock factory provides a synthetic connector that always
8
- * succeeds.
9
- */
10
- export const authResource = resource('auth', {
11
- create: (_svc) => Result.ok({
12
- // oxlint-disable-next-line require-await -- stub connector satisfies async interface
13
- authenticate: async () => Result.ok(null),
14
- }),
15
- description: 'Authentication connector',
16
- meta: { category: 'infrastructure' },
17
- mock: () => ({
18
- // oxlint-disable-next-line require-await -- mock connector satisfies async interface
19
- authenticate: async () => Result.ok(null),
20
- }),
21
- });
22
- //# sourceMappingURL=auth-resource.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"auth-resource.js","sourceRoot":"","sources":["../src/auth-resource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAIlD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,QAAQ,CAAgB,MAAM,EAAE;IAC1D,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CACf,MAAM,CAAC,EAAE,CAAC;QACR,qFAAqF;QACrF,YAAY,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC;KAClB,CAAC;IAC5B,WAAW,EAAE,0BAA0B;IACvC,IAAI,EAAE,EAAE,QAAQ,EAAE,gBAAgB,EAAE;IACpC,IAAI,EAAE,GAAG,EAAE,CACT,CAAC;QACC,qFAAqF;QACrF,YAAY,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC;KAC1C,CAAyB;CAC7B,CAAC,CAAC"}
@@ -1,26 +0,0 @@
1
- import type { Result } from '@ontrails/core';
2
- import type { PermitExtractionInput } from '../extraction.js';
3
- import type { Permit } from '../permit.js';
4
- /**
5
- * @deprecated Use {@link PermitExtractionInput} instead. Kept as an alias
6
- * for backward compatibility during migration.
7
- */
8
- export type AuthCredentials = PermitExtractionInput;
9
- /** Errors from auth connectors. */
10
- export interface AuthError {
11
- readonly code: 'expired_token' | 'insufficient_scope' | 'invalid_token' | 'missing_credentials';
12
- readonly message: string;
13
- }
14
- /**
15
- * Auth connector port. Given extraction input, produce a permit or an error.
16
- *
17
- * The connector receives the full {@link PermitExtractionInput} — trailhead,
18
- * headers, requestId, and credential fields — so it can make richer
19
- * decisions (e.g., rate-limit by trailhead or correlate via requestId).
20
- *
21
- * Deliberately narrow — no session management, no token refresh.
22
- */
23
- export interface AuthConnector {
24
- readonly authenticate: (input: PermitExtractionInput) => Promise<Result<Permit | null, AuthError>>;
25
- }
26
- //# sourceMappingURL=connector.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"connector.d.ts","sourceRoot":"","sources":["../../src/connectors/connector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAE7C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,qBAAqB,CAAC;AAEpD,mCAAmC;AACnC,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EACT,eAAe,GACf,oBAAoB,GACpB,eAAe,GACf,qBAAqB,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,YAAY,EAAE,CACrB,KAAK,EAAE,qBAAqB,KACzB,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;CAChD"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=connector.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"connector.js","sourceRoot":"","sources":["../../src/connectors/connector.ts"],"names":[],"mappings":""}
@@ -1,25 +0,0 @@
1
- import type { AuthConnector } from './connector.js';
2
- /** Configuration for the JWT auth connector. */
3
- export interface JwtConnectorOptions {
4
- /** HMAC secret for HS256 verification. */
5
- readonly secret?: string;
6
- /** JWKS endpoint for RS256/ES256 (not yet implemented). */
7
- readonly jwksUrl?: string;
8
- /** Expected issuer claim. */
9
- readonly issuer?: string;
10
- /** Expected audience claim. */
11
- readonly audience?: string;
12
- /** Claim containing scopes (default: 'scope'). */
13
- readonly scopesClaim?: string;
14
- /** Claim containing roles (default: 'roles'). */
15
- readonly rolesClaim?: string;
16
- }
17
- /**
18
- * Create a JWT auth connector using Bun's native crypto.
19
- *
20
- * Verifies HS256-signed JWTs, extracts claims into a Permit, and checks
21
- * issuer/audience when configured. Returns `Result.ok(null)` when no
22
- * credentials are provided.
23
- */
24
- export declare const createJwtConnector: (options: JwtConnectorOptions) => AuthConnector;
25
- //# sourceMappingURL=jwt.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../src/connectors/jwt.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAa,MAAM,gBAAgB,CAAC;AAI/D,gDAAgD;AAChD,MAAM,WAAW,mBAAmB;IAClC,0CAA0C;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,6BAA6B;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,+BAA+B;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,kDAAkD;IAClD,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,iDAAiD;IACjD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AA2LD;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,GAC7B,SAAS,mBAAmB,KAC3B,aAeF,CAAC"}