@ontrails/permits 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,416 @@
1
+ # @ontrails/permits
2
+
3
+ ## 0.2.0
4
+
5
+ ### Patch Changes
6
+
7
+ - [`664e8bb`](https://github.com/outfitter-dev/trails/commit/664e8bb049e61f1d47cec1dd246606707af5d1a8): Point public installation examples at exact approved 0.2.0 versions and distinguish the prepared source release from pending npm publication.
8
+ - [`b3ddf91`](https://github.com/outfitter-dev/trails/commit/b3ddf918ada8211f44983512e2bbdfbc5b66d722): Prepare the first normal Trails release at `0.2.0` on `latest`, replacing the unpublished 1.0.0 source release. The target advances the original `0.1.0` source minor, which was never published under the current package names. Public packages remain in lockstep. Update consumer installation guidance and provide a temporary manifest bridge for old 1.0 beta sources. Published beta versions remain unchanged; minor 0.x releases may carry documented breaking changes.
9
+
10
+ The `1.0.0` section retained below records an unpublished preparation, not an npm release. Its accumulated changes are included in `0.2.0`; the section remains as source history alongside the published beta entries.
11
+
12
+ ## 1.0.0
13
+
14
+ ### Major Changes
15
+
16
+ - [`200bece`](https://github.com/outfitter-dev/trails/commit/200bece897d79af9029492d7cbbe400cf9e4d25c): BREAKING: rename auth connector vocabulary to adapter.
17
+
18
+ This stays on the current `1.0.0-beta` prerelease line: the package is part of
19
+ the fixed `@ontrails/*` beta group, so beta-breaking API renames advance the
20
+ next beta rather than opening a stable-major release line.
21
+
22
+ - `AuthConnector` -> `AuthAdapter`
23
+ - `authConnectorSchema` -> `authAdapterSchema`
24
+ - `JwtConnectorOptions` -> `JwtAdapterOptions`
25
+ - `createJwtConnector` -> `createJwtAdapter`
26
+ - auth resource config discriminant `{ connector: 'jwt' | 'none' }` -> `{ adapter: 'jwt' | 'none' }`
27
+
28
+ The `@ontrails/permits/jwt` subpath is unchanged. The internal `connectors/`
29
+ source directory becomes `adapters/`. See
30
+ `docs/migration/connector-to-adapter.md` for the full rename map.
31
+
32
+ The Trails CLI package updates its generated auth-resource configuration to use
33
+ the new `adapter` discriminant.
34
+
35
+ ### Minor Changes
36
+
37
+ - [`73622ae`](https://github.com/outfitter-dev/trails/commit/73622aec93125756d589af3e056d252bdb91169e): Thread `ResourceSpec.config` through the built-in auth resource. Resource config schemas that accept `undefined` now receive their parsed default when config values are omitted, and `authResource` can materialize the no-op or JWT adapter from typed config while preserving existing mock and override paths.
38
+ - [`6944147`](https://github.com/outfitter-dev/trails/commit/694414712949a1107235684a2492ac982ed39a20): Complete trifecta for config, permits, and tracker (formerly tracks)
39
+
40
+ - **config**: Add `configResource`, `config.trail`, and `config.workspace` trails with full `defineConfig`, `resolve`, `describe`, `explain`, `doctor`, and code generation support
41
+ - **permits**: Add `authResource` and `auth.verify` trail for runtime authorization checks
42
+ - **tracing**: Rename tracks to tracing; add `tracingResource` and `tracing.status` trail for structured signal tracking
43
+ - **cli**: Fix build flag handling and improve bootstrap scaffolding
44
+ - **testing**: Expand test context helpers and example-based testing utilities
45
+ - **core/mcp/http**: Internal alignment for resource and composition updates
46
+
47
+ - [`69057e9`](https://github.com/outfitter-dev/trails/commit/69057e9348006b2b70c9f6237572a5aa8de3ee1f): Add hierarchical CLI command trees and structured input, enforce established-only topo exports across surfaces, move developer topo and tracing state onto shared `trails.db` with pins and maintenance flows, and ship schema-derived stores through `@ontrails/store` and its Drizzle runtime.
48
+ - [`4b8d13b`](https://github.com/outfitter-dev/trails/commit/4b8d13b6bbac0de4e78bcb0ea0aae6cf06638f1e): **BREAKING:** Remove the deprecated `AuthCredentials` alias from the permits public API.
49
+
50
+ Use `PermitExtractionInput` instead. See `docs/migration/trailhead-to-surface.md` for the full migration map.
51
+
52
+ - [`5adb995`](https://github.com/outfitter-dev/trails/commit/5adb99551c2dda6190d46cce7f60bb08d63c99aa): Complete the v1 hard cutover from the authored `blaze` field to
53
+ `implementation` across trail contracts, surface projections, tests, examples,
54
+ and public source-analysis helpers. Existing applications must rename authored
55
+ trail behavior fields and direct trail-object access before upgrading.
56
+ - [`66056ac`](https://github.com/outfitter-dev/trails/commit/66056ac3325e513519bc788e4bf27ccba202ddb0): **BREAKING:** TRL-475 drops user-facing exports of `authLayer`, `autoIterateLayer`, and `dateShortcutsLayer`. Breaking change for any app still wiring these layers manually.
57
+
58
+ Migration:
59
+
60
+ - **`autoIterateLayer`** — remove from `blaze`/`run`/`surface` options. The CLI surface now derives the `--all` flag and multi-page collection automatically from any trail whose output matches the pagination pattern (`items`, `hasMore`, `nextCursor`). See TRL-469.
61
+ - **`dateShortcutsLayer`** — remove from `blaze`/`run`/`surface` options. The CLI surface now expands `since`/`until` shortcut strings (`today`, `yesterday`, `7d`, `30d`, `this-week`, `this-month`) automatically from input schema shape. See TRL-470.
62
+ - **`authLayer`** — remove from `blaze`/`run`/`surface` options. Permit scope enforcement is intrinsic to `executeTrail` (`enforcePermitRequirement` runs before resource creation and layer composition). The compatibility shim was already a no-op.
63
+
64
+ The `Layer` type, `composeLayers`, and canonical per-call `executeTrail({ layers })` option remain available; only the legacy layer exports were removed.
65
+
66
+ - [`fde5516`](https://github.com/outfitter-dev/trails/commit/fde5516ad396faa718936b10ff658b3ade3383b9): Trail-native vocabulary cutover. Breaking API field renames across all packages:
67
+
68
+ - Trail spec: `run:` → `blaze:`, `follow:` → `crosses:`, `services:` → `resources:`, `metadata:` → `meta:`, `emits:` → `fires:`
69
+ - Runtime: `ctx.follow()` → `ctx.cross()`, `ctx.emit()` → `ctx.fire()`, `ctx.signal` (abort) → `ctx.abortSignal`
70
+ - Entry points: `trailhead(app)` → `surface(app)`
71
+ - Package rename: `@ontrails/crumbs` / `@ontrails/tracker` → `@ontrails/tracing`
72
+ - Wrapper types: retired gate/middleware vocabulary in favor of `Layer` and `layers`
73
+ - Package taxonomy: retired connector vocabulary in favor of adapters
74
+
75
+ ### Patch Changes
76
+
77
+ - [`3e5c0fc`](https://github.com/outfitter-dev/trails/commit/3e5c0fc1f2db8fae130782d167cd6b7bb141f4e5): Export shared diagnostic base types from core and align governance diagnostic
78
+ severity vocabulary across adapter checks, permits, and Warden.
79
+ - [`199304e`](https://github.com/outfitter-dev/trails/commit/199304ec8d46dff22d65c81a5c8a9dd2d037bfa9): Harden JWT permit validation by requiring `exp` by default, validating the
80
+ header algorithm allowlist before signature verification, and enforcing finite
81
+ clock skew for `exp` and `nbf` checks.
82
+ - [`e4beec9`](https://github.com/outfitter-dev/trails/commit/e4beec9e756dbd44b333a26215ea03d50eafd7e7): Document `@ontrails/permits/jwt` as the canonical JWT adapter import while keeping root JWT re-exports as intentional convenience exports.
83
+ - [`88a6a62`](https://github.com/outfitter-dev/trails/commit/88a6a62a9e9e230ca6d368fa78dc3ece6c816204): Complete the v1 classification-first cutover from projection/project vocabulary
84
+ to derive/derived for contract-owned fact production and render/rendered for
85
+ surface presentation. Public type, helper, rule, relation, and report names move
86
+ without compatibility aliases; ordinary repository/project nouns remain
87
+ explicit preserves or structured review inventory.
88
+ - [`b1fbe57`](https://github.com/outfitter-dev/trails/commit/b1fbe574e6f44d1fecb5e3a000270955c0a77b7b): Publish Bun-validated package tarballs through an npm trusted-publishing adapter
89
+ binding, add exact repository metadata for each public workspace package, and
90
+ correct the native Bun release descriptor to its pack-only runtime boundary.
91
+ - [`5d88104`](https://github.com/outfitter-dev/trails/commit/5d88104c6c269e2ef1e92ba3b9e09a410df10c7b): Polish Trails blaze terminology across package docs and Warden guidance.
92
+ - [`99523f2`](https://github.com/outfitter-dev/trails/commit/99523f2a67e92091781165b6c847252b910554e2): Clean up resource context naming in shipped source and examples so resource
93
+ factories consistently use resource vocabulary.
94
+
95
+ ## 1.0.0-beta.50
96
+
97
+ ## 1.0.0-beta.49
98
+
99
+ ## 1.0.0-beta.48
100
+
101
+ ## 1.0.0-beta.47
102
+
103
+ ## 1.0.0-beta.46
104
+
105
+ ## 1.0.0-beta.45
106
+
107
+ ## 1.0.0-beta.44
108
+
109
+ ### Patch Changes
110
+
111
+ - [`b1fbe57`](https://github.com/outfitter-dev/trails/commit/b1fbe574e6f44d1fecb5e3a000270955c0a77b7b): Publish Bun-validated package tarballs through an npm trusted-publishing adapter
112
+ binding, add exact repository metadata for each public workspace package, and
113
+ correct the native Bun release descriptor to its pack-only runtime boundary.
114
+
115
+ ## 1.0.0-beta.43
116
+
117
+ ### Patch Changes
118
+
119
+ - [`88a6a62`](https://github.com/outfitter-dev/trails/commit/88a6a62a9e9e230ca6d368fa78dc3ece6c816204): Complete the v1 classification-first cutover from projection/project vocabulary
120
+ to derive/derived for contract-owned fact production and render/rendered for
121
+ surface presentation. Public type, helper, rule, relation, and report names move
122
+ without compatibility aliases; ordinary repository/project nouns remain
123
+ explicit preserves or structured review inventory.
124
+
125
+ ## 1.0.0-beta.42
126
+
127
+ ## 1.0.0-beta.41
128
+
129
+ ## 1.0.0-beta.40
130
+
131
+ ### Minor Changes
132
+
133
+ - [`5adb995`](https://github.com/outfitter-dev/trails/commit/5adb99551c2dda6190d46cce7f60bb08d63c99aa): Complete the v1 hard cutover from the authored `blaze` field to
134
+ `implementation` across trail contracts, surface projections, tests, examples,
135
+ and public source-analysis helpers. Existing applications must rename authored
136
+ trail behavior fields and direct trail-object access before upgrading.
137
+
138
+ ## 1.0.0-beta.39
139
+
140
+ ## 1.0.0-beta.38
141
+
142
+ ## 1.0.0-beta.37
143
+
144
+ ## 1.0.0-beta.36
145
+
146
+ ## 1.0.0-beta.35
147
+
148
+ ## 1.0.0-beta.34
149
+
150
+ ## 1.0.0-beta.33
151
+
152
+ ## 1.0.0-beta.32
153
+
154
+ ### Patch Changes
155
+
156
+ - 3e5c0fc: Export shared diagnostic base types from core and align governance diagnostic
157
+ severity vocabulary across adapter checks, permits, and Warden.
158
+ - Updated dependencies [3e5c0fc]
159
+ - Updated dependencies [f3c4fef]
160
+ - Updated dependencies [cb0a9d8]
161
+ - Updated dependencies [21c6dda]
162
+ - Updated dependencies [fe72b84]
163
+ - @ontrails/core@1.0.0-beta.32
164
+
165
+ ## 1.0.0-beta.31
166
+
167
+ ### Patch Changes
168
+
169
+ - Updated dependencies [4cd5d4e]
170
+ - Updated dependencies [38907cc]
171
+ - @ontrails/core@1.0.0-beta.31
172
+
173
+ ## 1.0.0-beta.30
174
+
175
+ ### Patch Changes
176
+
177
+ - @ontrails/core@1.0.0-beta.30
178
+
179
+ ## 1.0.0-beta.29
180
+
181
+ ### Patch Changes
182
+
183
+ - @ontrails/core@1.0.0-beta.29
184
+
185
+ ## 1.0.0-beta.28
186
+
187
+ ### Patch Changes
188
+
189
+ - @ontrails/core@1.0.0-beta.28
190
+
191
+ ## 1.0.0-beta.27
192
+
193
+ ### Patch Changes
194
+
195
+ - @ontrails/core@1.0.0-beta.27
196
+
197
+ ## 1.0.0-beta.26
198
+
199
+ ### Patch Changes
200
+
201
+ - Updated dependencies [1307568]
202
+ - Updated dependencies [371d19e]
203
+ - @ontrails/core@1.0.0-beta.26
204
+
205
+ ## 1.0.0-beta.25
206
+
207
+ ### Patch Changes
208
+
209
+ - Updated dependencies [c36aca9]
210
+ - Updated dependencies [3befcf1]
211
+ - Updated dependencies [a4f9cf6]
212
+ - Updated dependencies [9bcf34e]
213
+ - @ontrails/core@1.0.0-beta.25
214
+
215
+ ## 1.0.0-beta.24
216
+
217
+ ### Patch Changes
218
+
219
+ - @ontrails/core@1.0.0-beta.24
220
+
221
+ ## 1.0.0-beta.23
222
+
223
+ ### Patch Changes
224
+
225
+ - @ontrails/core@1.0.0-beta.23
226
+
227
+ ## 1.0.0-beta.22
228
+
229
+ ### Patch Changes
230
+
231
+ - @ontrails/core@1.0.0-beta.22
232
+
233
+ ## 1.0.0-beta.21
234
+
235
+ ### Patch Changes
236
+
237
+ - 99523f2: Clean up resource context naming in shipped source and examples so resource
238
+ factories consistently use resource vocabulary.
239
+ - Updated dependencies [99523f2]
240
+ - @ontrails/core@1.0.0-beta.21
241
+
242
+ ## 1.0.0-beta.20
243
+
244
+ ### Patch Changes
245
+
246
+ - Updated dependencies [851a2a3]
247
+ - @ontrails/core@1.0.0-beta.20
248
+
249
+ ## 1.0.0-beta.19
250
+
251
+ ### Patch Changes
252
+
253
+ - 5d88104: Polish Trails blaze terminology across package docs and Warden guidance.
254
+ - Updated dependencies [e41c382]
255
+ - Updated dependencies [1eb5bdc]
256
+ - Updated dependencies [f8d80b9]
257
+ - Updated dependencies [846a597]
258
+ - Updated dependencies [223aaad]
259
+ - Updated dependencies [3125f4d]
260
+ - Updated dependencies [2494dc6]
261
+ - Updated dependencies [2d53717]
262
+ - Updated dependencies [16cb740]
263
+ - Updated dependencies [8894ecb]
264
+ - Updated dependencies [fdf7ec9]
265
+ - Updated dependencies [d76be13]
266
+ - Updated dependencies [84f56a5]
267
+ - Updated dependencies [431b04c]
268
+ - Updated dependencies [5d88104]
269
+ - Updated dependencies [f04a9ef]
270
+ - @ontrails/core@1.0.0-beta.19
271
+
272
+ ## 1.0.0-beta.18
273
+
274
+ ### Patch Changes
275
+
276
+ - @ontrails/core@1.0.0-beta.18
277
+
278
+ ## 1.0.0-beta.17
279
+
280
+ ### Patch Changes
281
+
282
+ - Updated dependencies [3dc8254]
283
+ - @ontrails/core@1.0.0-beta.17
284
+
285
+ ## 1.0.0-beta.16
286
+
287
+ ### Major Changes
288
+
289
+ - 200bece: BREAKING: rename auth connector vocabulary to adapter.
290
+
291
+ This stays on the current `1.0.0-beta` prerelease line: the package is part of
292
+ the fixed `@ontrails/*` beta group, so beta-breaking API renames advance the
293
+ next beta rather than opening a stable-major release line.
294
+
295
+ - `AuthConnector` -> `AuthAdapter`
296
+ - `authConnectorSchema` -> `authAdapterSchema`
297
+ - `JwtConnectorOptions` -> `JwtAdapterOptions`
298
+ - `createJwtConnector` -> `createJwtAdapter`
299
+ - auth resource config discriminant `{ connector: 'jwt' | 'none' }` -> `{ adapter: 'jwt' | 'none' }`
300
+
301
+ The `@ontrails/permits/jwt` subpath is unchanged. The internal `connectors/`
302
+ source directory becomes `adapters/`. See
303
+ `docs/migration/connector-to-adapter.md` for the full rename map.
304
+
305
+ The Trails CLI package updates its generated auth-resource configuration to use
306
+ the new `adapter` discriminant.
307
+
308
+ ### Minor Changes
309
+
310
+ - 73622ae: Thread `ResourceSpec.config` through the built-in auth resource. Resource config schemas that accept `undefined` now receive their parsed default when config values are omitted, and `authResource` can materialize the no-op or JWT adapter from typed config while preserving existing mock and override paths.
311
+ - 4b8d13b: **BREAKING:** Remove the deprecated `AuthCredentials` alias from the permits public API.
312
+
313
+ Use `PermitExtractionInput` instead. See `docs/migration/trailhead-to-surface.md` for the full migration map.
314
+
315
+ - 66056ac: **BREAKING:** TRL-475 drops user-facing exports of `authLayer`, `autoIterateLayer`, and `dateShortcutsLayer`. Breaking change for any app still wiring these layers manually.
316
+
317
+ Migration:
318
+
319
+ - **`autoIterateLayer`** — remove from `blaze`/`run`/`surface` options. The CLI surface now derives the `--all` flag and multi-page collection automatically from any trail whose output matches the pagination pattern (`items`, `hasMore`, `nextCursor`). See TRL-469.
320
+ - **`dateShortcutsLayer`** — remove from `blaze`/`run`/`surface` options. The CLI surface now expands `since`/`until` shortcut strings (`today`, `yesterday`, `7d`, `30d`, `this-week`, `this-month`) automatically from input schema shape. See TRL-470.
321
+ - **`authLayer`** — remove from `blaze`/`run`/`surface` options. Permit scope enforcement is intrinsic to `executeTrail` (`enforcePermitRequirement` runs before resource creation and layer composition). The compatibility shim was already a no-op.
322
+
323
+ The `Layer` type, `composeLayers`, and canonical per-call `executeTrail({ layers })` option remain available; only the legacy layer exports were removed.
324
+
325
+ ### Patch Changes
326
+
327
+ - 199304e: Harden JWT permit validation by requiring `exp` by default, validating the
328
+ header algorithm allowlist before signature verification, and enforcing finite
329
+ clock skew for `exp` and `nbf` checks.
330
+ - e4beec9: Document `@ontrails/permits/jwt` as the canonical JWT adapter import while keeping root JWT re-exports as intentional convenience exports.
331
+ - Updated dependencies [73622ae]
332
+ - Updated dependencies [6300f70]
333
+ - Updated dependencies [d172013]
334
+ - Updated dependencies [c3fc5c3]
335
+ - Updated dependencies [20d7a5c]
336
+ - Updated dependencies [be5fb46]
337
+ - Updated dependencies [e898cc4]
338
+ - Updated dependencies [3395234]
339
+ - Updated dependencies [bcdc484]
340
+ - Updated dependencies [331e3a9]
341
+ - Updated dependencies [4399fdb]
342
+ - Updated dependencies [4b8d13b]
343
+ - Updated dependencies [112b9f2]
344
+ - Updated dependencies [893025e]
345
+ - Updated dependencies [eec5e9d]
346
+ - Updated dependencies [ebd4434]
347
+ - Updated dependencies [863d473]
348
+ - Updated dependencies [344f2f7]
349
+ - Updated dependencies [26f9ffd]
350
+ - Updated dependencies [10eae9a]
351
+ - Updated dependencies [22c6c06]
352
+ - @ontrails/core@1.0.0-beta.16
353
+
354
+ ## 1.0.0-beta.15
355
+
356
+ ### Patch Changes
357
+
358
+ - Updated dependencies [4ad6b25]
359
+ - @ontrails/core@1.0.0-beta.15
360
+
361
+ ## 1.0.0-beta.14
362
+
363
+ ### Minor Changes
364
+
365
+ - 69057e9: Add hierarchical CLI command trees and structured input, enforce established-only topo exports across trailheads, move developer topo and tracker state onto shared `trails.db` with pins and maintenance flows, and ship schema-derived stores through `@ontrails/store` and its Drizzle runtime.
366
+
367
+ ### Patch Changes
368
+
369
+ - Updated dependencies [69057e9]
370
+ - @ontrails/core@1.0.0-beta.14
371
+
372
+ ## 1.0.0-beta.13
373
+
374
+ ### Minor Changes
375
+
376
+ - 6944147: Complete trifecta for config, permits, and tracker (formerly tracks)
377
+
378
+ - **config**: Add `configProvision`, `configGate`, `config.trail`, and `config.workspace` trails with full `defineConfig`, `resolve`, `describe`, `explain`, `doctor`, and code generation support
379
+ - **permits**: Add `authService` and `auth.verify` trail for runtime authorization checks
380
+ - **tracker**: Rename tracks to tracker; add `trackerProvision` and `tracker.status` trail for structured signal tracking
381
+ - **cli**: Fix build flag handling and improve bootstrap scaffolding
382
+ - **testing**: Expand test context helpers and example-based testing utilities
383
+ - **core/mcp/http**: Internal alignment for provision and composition updates
384
+
385
+ - Trail-native vocabulary cutover. Breaking API field renames across all packages:
386
+
387
+ - Trail spec: `run:` → `blaze:`, `follow:` → `crosses:`, `services:` → `provisions:`, `metadata:` → `meta:`, `emits:` → `signals:`
388
+ - Runtime: `ctx.follow()` → `ctx.cross()`, `ctx.emit()` → `ctx.signal()`, `ctx.signal` (abort) → `ctx.abortSignal`
389
+ - Entry points: `blaze(app)` → `trailhead(app)`
390
+ - Package rename: `@ontrails/crumbs` → `@ontrails/tracker`
391
+ - Wrapper types: `Layer` → `Gate`, `layers`/`middleware` → `gates`
392
+ - Transport: `surface` → `trailhead`, `adapter` → `connector`
393
+
394
+ ### Patch Changes
395
+
396
+ - Updated dependencies [6944147]
397
+ - Updated dependencies
398
+ - @ontrails/core@1.0.0-beta.13
399
+
400
+ ## 1.0.0-beta.12
401
+
402
+ ### Minor Changes
403
+
404
+ - Complete trifecta for config, permits, and tracker (formerly tracks)
405
+
406
+ - **config**: Add `configProvision`, `config.gate`, `config.trail`, and `config.workspace` trails with full `defineConfig`, `resolve`, `describe`, `explain`, `doctor`, and code generation support
407
+ - **permits**: Add `authProvision` and `auth.verify` trail for runtime authorization checks
408
+ - **tracker**: Rename tracks to tracker; add `trackerProvision` and `tracker.status` trail for structured event tracking
409
+ - **cli**: Fix build flag handling and improve bootstrap scaffolding
410
+ - **testing**: Expand test context helpers and example-based testing utilities
411
+ - **core/mcp/http**: Internal alignment for provision and composition updates
412
+
413
+ ### Patch Changes
414
+
415
+ - Updated dependencies
416
+ - @ontrails/core@1.0.0-beta.12
package/README.md ADDED
@@ -0,0 +1,182 @@
1
+ # @ontrails/permits
2
+
3
+ Scope-based authorization for Trails.
4
+
5
+ The permits package owns adapter-agnostic auth resources, adapters, and helpers. Core `executeTrail` enforces trail `permit` declarations once a surface has resolved a permit into `ctx.permit`.
6
+
7
+ ## The core pattern
8
+
9
+ ### 1. Declare permit requirements on trails
10
+
11
+ ```typescript
12
+ export const create = trail('gist.create', {
13
+ permit: { scopes: ['gist:write'] },
14
+ implementation: async (input, ctx) => {
15
+ // executeTrail enforces scopes before execution enters the implementation
16
+ return Result.ok(newGist);
17
+ },
18
+ });
19
+
20
+ export const search = trail('gist.search', {
21
+ permit: 'public',
22
+ implementation: async (input, ctx) => {
23
+ // No authentication required
24
+ return Result.ok(results);
25
+ },
26
+ });
27
+ ```
28
+
29
+ ### 2. Resolve a permit at the surface
30
+
31
+ ```typescript
32
+ export const graph = topo('my-app', gistModule);
33
+ // Surface auth verifies credentials and passes { permit } into executeTrail.
34
+ ```
35
+
36
+ The execution pipeline reads each trail's `permit` field:
37
+
38
+ - `'public'` or `undefined` — execution passes through
39
+ - `{ scopes: [...] }` — execution checks that `ctx.permit` contains all required scopes
40
+
41
+ Permit enforcement is intrinsic to `executeTrail`; there is no opt-in layer to wire. The previously deprecated `authLayer` compatibility wrapper has been removed (TRL-475).
42
+
43
+ ### 3. Bind an adapter at bootstrap
44
+
45
+ ```typescript
46
+ import { createJwtAdapter } from '@ontrails/permits/jwt';
47
+
48
+ const adapter = createJwtAdapter({
49
+ secret: process.env.JWT_SECRET,
50
+ issuer: 'https://auth.example.com',
51
+ audience: 'api.example.com',
52
+ });
53
+ ```
54
+
55
+ ## Auth adapters
56
+
57
+ An auth adapter authenticates requests and produces permits.
58
+
59
+ ### Built-in: JWT adapter
60
+
61
+ Verifies HS256-signed JWTs and extracts claims into permits:
62
+
63
+ ```typescript
64
+ import { createJwtAdapter } from '@ontrails/permits/jwt';
65
+
66
+ const adapter = createJwtAdapter({
67
+ secret: 'your-hmac-secret',
68
+ issuer: 'https://auth.example.com',
69
+ audience: 'api.example.com',
70
+ scopesClaim: 'scope',
71
+ rolesClaim: 'roles',
72
+ });
73
+ ```
74
+
75
+ `@ontrails/permits/jwt` is the canonical built-in JWT adapter subpath. The root package intentionally keeps convenience re-exports for interactive discovery, but generated code, docs, and adapter-specific examples should import JWT names from the subpath.
76
+
77
+ ### Custom adapters
78
+
79
+ Implement the `AuthAdapter` interface:
80
+
81
+ ```typescript
82
+ import type { AuthAdapter, PermitExtractionInput, Permit } from '@ontrails/permits';
83
+
84
+ const myAdapter: AuthAdapter = {
85
+ authenticate: async (input: PermitExtractionInput) => {
86
+ if (!input.bearerToken) return Result.ok(null);
87
+ const permit: Permit = {
88
+ id: 'user-42',
89
+ scopes: ['user:read', 'user:write'],
90
+ roles: ['admin'],
91
+ };
92
+ return Result.ok(permit);
93
+ },
94
+ };
95
+ ```
96
+
97
+ ## Permits and scopes
98
+
99
+ A `Permit` is the resolved identity and scopes from successful authentication:
100
+
101
+ ```typescript
102
+ interface Permit {
103
+ readonly id: string;
104
+ readonly scopes: readonly string[];
105
+ readonly roles?: readonly string[];
106
+ readonly tenantId?: string;
107
+ readonly metadata?: Readonly<Record<string, unknown>>;
108
+ }
109
+ ```
110
+
111
+ Access the permit in your implementation:
112
+
113
+ ```typescript
114
+ import { getPermit } from '@ontrails/permits';
115
+
116
+ const myTrail = trail('do.something', {
117
+ implementation: async (_input, ctx) => {
118
+ const permit = getPermit(ctx);
119
+ if (!permit) return Result.err(new Error('Not authenticated'));
120
+ return Result.ok({ userId: permit.id });
121
+ },
122
+ });
123
+ ```
124
+
125
+ Scopes follow the `entity:action` convention: `user:read`, `gist:write`, etc.
126
+
127
+ ## The auth.verify trail
128
+
129
+ An infrastructure trail that verifies bearer tokens and returns permits:
130
+
131
+ ```typescript
132
+ import { authVerify } from '@ontrails/permits';
133
+
134
+ // Returns { valid: true, permit: { id, scopes, roles } }
135
+ // or { valid: false, error: 'Token has expired', errorCode: 'expired_token' }
136
+ ```
137
+
138
+ ## Testing with mock permits
139
+
140
+ Use `createTestPermit()` and `createPermitForTrail()` in tests:
141
+
142
+ ```typescript
143
+ import {
144
+ createTestPermit,
145
+ createPermitForTrail,
146
+ } from '@ontrails/permits/testing';
147
+
148
+ const permit = createTestPermit({
149
+ id: 'user-123',
150
+ scopes: ['gist:read', 'gist:write'],
151
+ roles: ['editor'],
152
+ });
153
+
154
+ // Create a permit matching a trail's requirements
155
+ const trailPermit = createPermitForTrail(myTrail);
156
+ // { id: 'test-...', scopes: ['gist:write'] }
157
+ ```
158
+
159
+ ## Permit governance
160
+
161
+ Use `validatePermits()` to check trails against governance rules:
162
+
163
+ ```typescript
164
+ import { validatePermits } from '@ontrails/permits';
165
+
166
+ const diagnostics = validatePermits(app.list());
167
+ ```
168
+
169
+ Built-in rules:
170
+
171
+ - `destroyWithoutPermit` — error if a destroy trail has no permit
172
+ - `writeWithoutPermit` — warning if a write trail has no permit
173
+ - `scopeNamingConsistency` — warning if a scope doesn't follow `entity:action`
174
+ - `orphanScopeDetection` — warning if a scope appears in only one trail
175
+
176
+ ## Installation
177
+
178
+ These commands target stable `0.2.0`. Run them after that version is published to npm.
179
+
180
+ ```bash
181
+ bun add --exact @ontrails/permits@0.2.0 @ontrails/core@0.2.0 zod
182
+ ```
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@ontrails/permits",
3
+ "version": "0.2.0",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "git+https://github.com/outfitter-dev/trails.git",
7
+ "directory": "packages/permits"
8
+ },
9
+ "files": [
10
+ "src/**/*.ts",
11
+ "!src/**/__tests__/**",
12
+ "!src/**/*.test.ts",
13
+ "!src/**/*.test-d.ts",
14
+ "README.md",
15
+ "CHANGELOG.md"
16
+ ],
17
+ "type": "module",
18
+ "exports": {
19
+ ".": "./src/index.ts",
20
+ "./jwt": "./src/adapters/jwt.ts",
21
+ "./testing": "./src/testing.ts",
22
+ "./package.json": "./package.json"
23
+ },
24
+ "scripts": {
25
+ "build": "tsc -b",
26
+ "test": "bun test",
27
+ "typecheck": "tsc --noEmit",
28
+ "lint": "oxlint ./src",
29
+ "clean": "rm -rf dist *.tsbuildinfo"
30
+ },
31
+ "peerDependencies": {
32
+ "@ontrails/core": "^0.2.0",
33
+ "zod": "^4.3.5"
34
+ }
35
+ }
@@ -0,0 +1,41 @@
1
+ import { z } from 'zod';
2
+ import type { Result } from '@ontrails/core';
3
+
4
+ import type { PermitExtractionInput } from '../extraction.js';
5
+ import type { Permit } from '../permit.js';
6
+
7
+ /** Errors from auth adapters. */
8
+ export const authErrorSchema = z
9
+ .object({
10
+ code: z.enum([
11
+ 'expired_token',
12
+ 'insufficient_scope',
13
+ 'invalid_token',
14
+ 'missing_credentials',
15
+ ]),
16
+ message: z.string(),
17
+ })
18
+ .readonly();
19
+
20
+ export type AuthError = z.infer<typeof authErrorSchema>;
21
+
22
+ export const authAdapterSchema = z
23
+ .object({
24
+ authenticate: z.function(),
25
+ })
26
+ .readonly();
27
+
28
+ /**
29
+ * Auth adapter port. Given extraction input, produce a permit or an error.
30
+ *
31
+ * The adapter receives the full {@link PermitExtractionInput} — surface,
32
+ * headers, requestId, and credential fields — so it can make richer
33
+ * decisions (e.g., rate-limit by surface or correlate via requestId).
34
+ *
35
+ * Deliberately narrow — no session management, no token refresh.
36
+ */
37
+ export interface AuthAdapter {
38
+ readonly authenticate: (
39
+ input: PermitExtractionInput
40
+ ) => Promise<Result<Permit | null, AuthError>>;
41
+ }