@forgezero/access 0.1.5 → 0.1.7

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/README.md CHANGED
@@ -35,21 +35,21 @@ Every row links to the detailed explanation and named-import/example area below.
35
35
 
36
36
  | public entry | short description | runtime | details |
37
37
  |---|---|---|---|
38
- | @forgezero/access | Declare routes, factors and policies as orthogonal lists; authorise against them. | portable | [Details + example](#forgezero-access) |
39
- | @forgezero/access/conditions | The twelve guards every project writes into `before`, each with the status its refusal deserves. | portable | [Details + example](#forgezero-access-conditions) |
40
- | @forgezero/access/effects | Audit, emit, meter, invalidate and notify — what happens after a request is decided, never failing it. | portable | [Details + example](#forgezero-access-effects) |
41
- | @forgezero/access/security | Constant-time comparison, CSPRNG tokens, HMAC, HKDF, AES-GCM sealing and redaction. Web Crypto only. | portable | [Details + example](#forgezero-access-security) |
42
- | @forgezero/access/rate-limit | Request counters over a window — in memory, in Redis, or in a Durable Object. | portable | [Details + example](#forgezero-access-rate-limit) |
43
- | @forgezero/access/fetch | A Fetch-native adapter over the declared access pipeline. | portable | [Details + example](#forgezero-access-fetch) |
44
- | @forgezero/access/pipeline | The framework-neutral route, principal, factor, policy, rate-limit and effects pipeline. | portable | [Details + example](#forgezero-access-pipeline) |
45
- | @forgezero/access/elysia | Elysia integration over the same access pipeline and route declarations. | portable | [Details + example](#forgezero-access-elysia) |
46
- | @forgezero/access/client | Typed client helpers that fulfil factors without duplicating the security matrix. | portable | [Details + example](#forgezero-access-client) |
47
- | @forgezero/access/testing | Deterministic access-pipeline fixtures and assertions for consumer tests. | portable | [Details + example](#forgezero-access-testing) |
48
- | @forgezero/access/header | Strict configurable header-identity extraction with canonical names and bounded values. | portable | [Details + example](#forgezero-access-header) |
49
- | @forgezero/access/principal | Generic principal-source resolution for browser, API-key, attestation or future identity adapters. | portable | [Details + example](#forgezero-access-principal) |
50
- | @forgezero/access/principal-session | Short-lived scope-bound delegated-principal sessions with sliding and absolute expiry. | portable | [Details + example](#forgezero-access-principal-session) |
51
- | @forgezero/access/authenticator | Authentication-source contracts for adding identity mechanisms without changing route policy. | portable | [Details + example](#forgezero-access-authenticator) |
52
- | @forgezero/access/ceremony-modes | Named security-ceremony modes and their session/action fulfilment semantics. | portable | [Details + example](#forgezero-access-ceremony-modes) |
38
+ | @forgezero/access | Declare routes, factors and policies as orthogonal lists; authorise against them. | portable | [Reference + usage](#forgezero-access) |
39
+ | @forgezero/access/conditions | The twelve guards every project writes into `before`, each with the status its refusal deserves. | portable | [Reference + usage](#forgezero-access-conditions) |
40
+ | @forgezero/access/effects | Audit, emit, meter, invalidate and notify — what happens after a request is decided, never failing it. | portable | [Reference + usage](#forgezero-access-effects) |
41
+ | @forgezero/access/security | Constant-time comparison, CSPRNG tokens, HMAC, HKDF, AES-GCM sealing and redaction. Web Crypto only. | portable | [Reference + usage](#forgezero-access-security) |
42
+ | @forgezero/access/rate-limit | Request counters over a window — in memory, in Redis, or in a Durable Object. | portable | [Reference + usage](#forgezero-access-rate-limit) |
43
+ | @forgezero/access/fetch | A Fetch-native adapter over the declared access pipeline. | portable | [Reference + usage](#forgezero-access-fetch) |
44
+ | @forgezero/access/pipeline | The framework-neutral route, principal, factor, policy, rate-limit and effects pipeline. | portable | [Reference + usage](#forgezero-access-pipeline) |
45
+ | @forgezero/access/elysia | Elysia integration over the same access pipeline and route declarations. | portable | [Reference + usage](#forgezero-access-elysia) |
46
+ | @forgezero/access/client | Typed client helpers that fulfil factors without duplicating the security matrix. | portable | [Reference + usage](#forgezero-access-client) |
47
+ | @forgezero/access/testing | Deterministic access-pipeline fixtures and assertions for consumer tests. | portable | [Reference + usage](#forgezero-access-testing) |
48
+ | @forgezero/access/header | Strict configurable header-identity extraction with canonical names and bounded values. | portable | [Reference + usage](#forgezero-access-header) |
49
+ | @forgezero/access/principal | Generic principal-source resolution for browser, API-key, attestation or future identity adapters. | portable | [Reference + usage](#forgezero-access-principal) |
50
+ | @forgezero/access/principal-session | Short-lived scope-bound delegated-principal sessions with sliding and absolute expiry. | portable | [Reference + usage](#forgezero-access-principal-session) |
51
+ | @forgezero/access/authenticator | Authentication-source contracts for adding identity mechanisms without changing route policy. | portable | [Reference + usage](#forgezero-access-authenticator) |
52
+ | @forgezero/access/ceremony-modes | Named security-ceremony modes and their session/action fulfilment semantics. | portable | [Reference + usage](#forgezero-access-ceremony-modes) |
53
53
 
54
54
  ## Commands
55
55
 
@@ -180,6 +180,18 @@ import type {
180
180
  } from '@forgezero/access/conditions';
181
181
  ```
182
182
 
183
+ ## @forgezero/access/conditions — Use this entry point
184
+
185
+ This minimal executable use imports one concrete value from this exact entry point without a wildcard or package-root detour. Keep the value or values the application actually needs; the full named inventory remains directly above it.
186
+
187
+ ```text
188
+ import {
189
+ assertDeclaredRefusals,
190
+ } from '@forgezero/access/conditions';
191
+
192
+ export const selectedCapability = assertDeclaredRefusals;
193
+ ```
194
+
183
195
  <a id="forgezero-access-effects"></a>
184
196
  ## @forgezero/access/effects
185
197
 
@@ -214,6 +226,18 @@ import type {
214
226
  } from '@forgezero/access/effects';
215
227
  ```
216
228
 
229
+ ## @forgezero/access/effects — Use this entry point
230
+
231
+ This minimal executable use imports one concrete value from this exact entry point without a wildcard or package-root detour. Keep the value or values the application actually needs; the full named inventory remains directly above it.
232
+
233
+ ```text
234
+ import {
235
+ audit,
236
+ } from '@forgezero/access/effects';
237
+
238
+ export const selectedCapability = audit;
239
+ ```
240
+
217
241
  <a id="forgezero-access-security"></a>
218
242
  ## @forgezero/access/security
219
243
 
@@ -248,6 +272,18 @@ import type {
248
272
  } from '@forgezero/access/security';
249
273
  ```
250
274
 
275
+ ## @forgezero/access/security — Use this entry point
276
+
277
+ This minimal executable use imports one concrete value from this exact entry point without a wildcard or package-root detour. Keep the value or values the application actually needs; the full named inventory remains directly above it.
278
+
279
+ ```text
280
+ import {
281
+ fromBase64Url,
282
+ } from '@forgezero/access/security';
283
+
284
+ export const selectedCapability = fromBase64Url;
285
+ ```
286
+
251
287
  <a id="forgezero-access-rate-limit"></a>
252
288
  ## @forgezero/access/rate-limit
253
289
 
@@ -267,6 +303,18 @@ import type {
267
303
  } from '@forgezero/access/rate-limit';
268
304
  ```
269
305
 
306
+ ## @forgezero/access/rate-limit — Use this entry point
307
+
308
+ This minimal executable use imports one concrete value from this exact entry point without a wildcard or package-root detour. Keep the value or values the application actually needs; the full named inventory remains directly above it.
309
+
310
+ ```text
311
+ import {
312
+ durableObjectStore,
313
+ } from '@forgezero/access/rate-limit';
314
+
315
+ export const selectedCapability = durableObjectStore;
316
+ ```
317
+
270
318
  <a id="forgezero-access-fetch"></a>
271
319
  ## @forgezero/access/fetch
272
320
 
@@ -284,6 +332,18 @@ import type {
284
332
  } from '@forgezero/access/fetch';
285
333
  ```
286
334
 
335
+ ## @forgezero/access/fetch — Use this entry point
336
+
337
+ This minimal executable use imports one concrete value from this exact entry point without a wildcard or package-root detour. Keep the value or values the application actually needs; the full named inventory remains directly above it.
338
+
339
+ ```text
340
+ import {
341
+ compileRoute,
342
+ } from '@forgezero/access/fetch';
343
+
344
+ export const selectedCapability = compileRoute;
345
+ ```
346
+
287
347
  <a id="forgezero-access-pipeline"></a>
288
348
  ## @forgezero/access/pipeline
289
349
 
@@ -309,6 +369,18 @@ import type {
309
369
  } from '@forgezero/access/pipeline';
310
370
  ```
311
371
 
372
+ ## @forgezero/access/pipeline — Use this entry point
373
+
374
+ This minimal executable use imports one concrete value from this exact entry point without a wildcard or package-root detour. Keep the value or values the application actually needs; the full named inventory remains directly above it.
375
+
376
+ ```text
377
+ import {
378
+ createPipeline,
379
+ } from '@forgezero/access/pipeline';
380
+
381
+ export const selectedCapability = createPipeline;
382
+ ```
383
+
312
384
  <a id="forgezero-access-elysia"></a>
313
385
  ## @forgezero/access/elysia
314
386
 
@@ -328,6 +400,18 @@ import type {
328
400
  } from '@forgezero/access/elysia';
329
401
  ```
330
402
 
403
+ ## @forgezero/access/elysia — Use this entry point
404
+
405
+ This minimal executable use imports one concrete value from this exact entry point without a wildcard or package-root detour. Keep the value or values the application actually needs; the full named inventory remains directly above it.
406
+
407
+ ```text
408
+ import {
409
+ elysia,
410
+ } from '@forgezero/access/elysia';
411
+
412
+ export const selectedCapability = elysia;
413
+ ```
414
+
331
415
  <a id="forgezero-access-client"></a>
332
416
  ## @forgezero/access/client
333
417
 
@@ -349,6 +433,18 @@ import type {
349
433
  } from '@forgezero/access/client';
350
434
  ```
351
435
 
436
+ ## @forgezero/access/client — Use this entry point
437
+
438
+ This minimal executable use imports one concrete value from this exact entry point without a wildcard or package-root detour. Keep the value or values the application actually needs; the full named inventory remains directly above it.
439
+
440
+ ```text
441
+ import {
442
+ buildPath,
443
+ } from '@forgezero/access/client';
444
+
445
+ export const selectedCapability = buildPath;
446
+ ```
447
+
352
448
  <a id="forgezero-access-testing"></a>
353
449
  ## @forgezero/access/testing
354
450
 
@@ -367,6 +463,18 @@ import type {
367
463
  } from '@forgezero/access/testing';
368
464
  ```
369
465
 
466
+ ## @forgezero/access/testing — Use this entry point
467
+
468
+ This minimal executable use imports one concrete value from this exact entry point without a wildcard or package-root detour. Keep the value or values the application actually needs; the full named inventory remains directly above it.
469
+
470
+ ```text
471
+ import {
472
+ reachableRoutes,
473
+ } from '@forgezero/access/testing';
474
+
475
+ export const selectedCapability = reachableRoutes;
476
+ ```
477
+
370
478
  <a id="forgezero-access-header"></a>
371
479
  ## @forgezero/access/header
372
480
 
@@ -386,6 +494,18 @@ import type {
386
494
  } from '@forgezero/access/header';
387
495
  ```
388
496
 
497
+ ## @forgezero/access/header — Use this entry point
498
+
499
+ This minimal executable use imports one concrete value from this exact entry point without a wildcard or package-root detour. Keep the value or values the application actually needs; the full named inventory remains directly above it.
500
+
501
+ ```text
502
+ import {
503
+ defineHeaderIdentitySources,
504
+ } from '@forgezero/access/header';
505
+
506
+ export const selectedCapability = defineHeaderIdentitySources;
507
+ ```
508
+
389
509
  <a id="forgezero-access-principal"></a>
390
510
  ## @forgezero/access/principal
391
511
 
@@ -406,6 +526,18 @@ import type {
406
526
  } from '@forgezero/access/principal';
407
527
  ```
408
528
 
529
+ ## @forgezero/access/principal — Use this entry point
530
+
531
+ This minimal executable use imports one concrete value from this exact entry point without a wildcard or package-root detour. Keep the value or values the application actually needs; the full named inventory remains directly above it.
532
+
533
+ ```text
534
+ import {
535
+ assignmentIsActive,
536
+ } from '@forgezero/access/principal';
537
+
538
+ export const selectedCapability = assignmentIsActive;
539
+ ```
540
+
409
541
  <a id="forgezero-access-principal-session"></a>
410
542
  ## @forgezero/access/principal-session
411
543
 
@@ -429,6 +561,18 @@ import type {
429
561
  } from '@forgezero/access/principal-session';
430
562
  ```
431
563
 
564
+ ## @forgezero/access/principal-session — Use this entry point
565
+
566
+ This minimal executable use imports one concrete value from this exact entry point without a wildcard or package-root detour. Keep the value or values the application actually needs; the full named inventory remains directly above it.
567
+
568
+ ```text
569
+ import {
570
+ DEFAULT_PRINCIPAL_ABSOLUTE_TTL_MS,
571
+ } from '@forgezero/access/principal-session';
572
+
573
+ export const selectedCapability = DEFAULT_PRINCIPAL_ABSOLUTE_TTL_MS;
574
+ ```
575
+
432
576
  <a id="forgezero-access-authenticator"></a>
433
577
  ## @forgezero/access/authenticator
434
578
 
@@ -451,6 +595,18 @@ import type {
451
595
  } from '@forgezero/access/authenticator';
452
596
  ```
453
597
 
598
+ ## @forgezero/access/authenticator — Use this entry point
599
+
600
+ This minimal executable use imports one concrete value from this exact entry point without a wildcard or package-root detour. Keep the value or values the application actually needs; the full named inventory remains directly above it.
601
+
602
+ ```text
603
+ import {
604
+ createAuthenticator,
605
+ } from '@forgezero/access/authenticator';
606
+
607
+ export const selectedCapability = createAuthenticator;
608
+ ```
609
+
454
610
  <a id="forgezero-access-ceremony-modes"></a>
455
611
  ## @forgezero/access/ceremony-modes
456
612
 
@@ -469,6 +625,18 @@ import type {
469
625
  } from '@forgezero/access/ceremony-modes';
470
626
  ```
471
627
 
628
+ ## @forgezero/access/ceremony-modes — Use this entry point
629
+
630
+ This minimal executable use imports one concrete value from this exact entry point without a wildcard or package-root detour. Keep the value or values the application actually needs; the full named inventory remains directly above it.
631
+
632
+ ```text
633
+ import {
634
+ MAX_CUSTODIANS,
635
+ } from '@forgezero/access/ceremony-modes';
636
+
637
+ export const selectedCapability = MAX_CUSTODIANS;
638
+ ```
639
+
472
640
  ## 1. Install
473
641
 
474
642
  Zero runtime dependencies. The core is fetch types plus plain JSON Schema, so it runs on Bun, Node 18+, Cloudflare Workers, Deno and every edge runtime.
@@ -582,8 +750,12 @@ reachableRoutes(ACCESS, roles, ['member']);
582
750
  Every project writes the same dozen checks into its before-handlers. These are those checks, each declaring the status it refuses with. requireOwner answers 404 rather than 403 on purpose — a 403 confirms the record exists, which turns sequential identifiers into an enumeration oracle.
583
751
 
584
752
  ```text
585
- import { loadTarget, requireOwner, requireState, requireBalance }
586
- from '@forgezero/access/conditions';
753
+ import {
754
+ loadTarget,
755
+ requireOwner,
756
+ requireState,
757
+ requireBalance,
758
+ } from '@forgezero/access/conditions';
587
759
 
588
760
  beforeHandlers: {
589
761
  load: loadTarget({ routes: ['api/orders/[id]/refund'], load: findOrder }),
@@ -275,7 +275,7 @@ function impactOfDisabling(access, enabledAfter) {
275
275
  }
276
276
  return broken;
277
277
  }
278
- var VERSION = "0.1.5";
278
+ var VERSION = "0.1.7";
279
279
 
280
280
  // src/conditions.ts
281
281
  function define(condition, routes, refusals, run) {
package/dist/effects.js CHANGED
@@ -275,7 +275,7 @@ function impactOfDisabling(access, enabledAfter) {
275
275
  }
276
276
  return broken;
277
277
  }
278
- var VERSION = "0.1.5";
278
+ var VERSION = "0.1.7";
279
279
 
280
280
  // src/security.ts
281
281
  var HEX = Array.from({ length: 256 }, (_, index) => index.toString(16).padStart(2, "0"));
package/dist/elysia.js CHANGED
@@ -275,7 +275,7 @@ function impactOfDisabling(access, enabledAfter) {
275
275
  }
276
276
  return broken;
277
277
  }
278
- var VERSION = "0.1.5";
278
+ var VERSION = "0.1.7";
279
279
 
280
280
  // src/pipeline.ts
281
281
  function defineHandlers(routes, handlers) {
package/dist/fetch.js CHANGED
@@ -275,7 +275,7 @@ function impactOfDisabling(access, enabledAfter) {
275
275
  }
276
276
  return broken;
277
277
  }
278
- var VERSION = "0.1.5";
278
+ var VERSION = "0.1.7";
279
279
 
280
280
  // src/pipeline.ts
281
281
  function defineHandlers(routes, handlers) {
package/dist/header.js CHANGED
@@ -275,7 +275,7 @@ function impactOfDisabling(access, enabledAfter) {
275
275
  }
276
276
  return broken;
277
277
  }
278
- var VERSION = "0.1.5";
278
+ var VERSION = "0.1.7";
279
279
 
280
280
  // src/principal.ts
281
281
  var ATOM = /^[A-Za-z0-9][A-Za-z0-9_.:@/-]{0,255}$/;
@@ -374,7 +374,15 @@ function defineHeaderIdentitySources(sources) {
374
374
  if (!KEY.test(source.key) || !HEADER.test(header)) {
375
375
  throw new AccessError("HEADER_SOURCE_INVALID", "Header identity source keys and names must be bounded atoms.");
376
376
  }
377
- if (["cookie", "authorization", "x-fz-key", "x-fz-node", "x-fz-signature"].includes(header)) {
377
+ if ([
378
+ "cookie",
379
+ "authorization",
380
+ "x-fz-key",
381
+ "x-fz-node",
382
+ "x-fz-signature",
383
+ "x-fz-delegated-session",
384
+ "x-fz-delegated-binding"
385
+ ].includes(header)) {
378
386
  throw new AccessError("HEADER_SOURCE_RESERVED", `Header identity source "${source.key}" uses a reserved credential header.`);
379
387
  }
380
388
  if (keys.has(source.key) || headers.has(header)) {
package/dist/index.d.ts CHANGED
@@ -379,4 +379,4 @@ export declare function impactOfDisabling<R extends RouteRegistry>(access: Acces
379
379
  available: number;
380
380
  required: number;
381
381
  }[];
382
- export declare const VERSION = "0.1.5";
382
+ export declare const VERSION = "0.1.7";
package/dist/index.js CHANGED
@@ -275,7 +275,7 @@ function impactOfDisabling(access, enabledAfter) {
275
275
  }
276
276
  return broken;
277
277
  }
278
- var VERSION = "0.1.5";
278
+ var VERSION = "0.1.7";
279
279
  export {
280
280
  stemOf,
281
281
  resolveActionFactors,
package/dist/pipeline.js CHANGED
@@ -275,7 +275,7 @@ function impactOfDisabling(access, enabledAfter) {
275
275
  }
276
276
  return broken;
277
277
  }
278
- var VERSION = "0.1.5";
278
+ var VERSION = "0.1.7";
279
279
 
280
280
  // src/pipeline.ts
281
281
  function defineHandlers(routes, handlers) {
@@ -18,7 +18,7 @@ export interface PrincipalSessionRecord {
18
18
  absoluteExpiresAtMs: number;
19
19
  }
20
20
  export interface IssuedPrincipalSession {
21
- /** Returned once. Store in an HttpOnly Secure cookie, never localStorage. */
21
+ /** Returned once. Keep in memory or an HttpOnly Secure cookie; never localStorage. */
22
22
  credential: string;
23
23
  record: PrincipalSessionRecord;
24
24
  }
@@ -275,7 +275,7 @@ function impactOfDisabling(access, enabledAfter) {
275
275
  }
276
276
  return broken;
277
277
  }
278
- var VERSION = "0.1.5";
278
+ var VERSION = "0.1.7";
279
279
 
280
280
  // src/security.ts
281
281
  var HEX = Array.from({ length: 256 }, (_, index) => index.toString(16).padStart(2, "0"));
package/dist/principal.js CHANGED
@@ -275,7 +275,7 @@ function impactOfDisabling(access, enabledAfter) {
275
275
  }
276
276
  return broken;
277
277
  }
278
- var VERSION = "0.1.5";
278
+ var VERSION = "0.1.7";
279
279
 
280
280
  // src/principal.ts
281
281
  var ATOM = /^[A-Za-z0-9][A-Za-z0-9_.:@/-]{0,255}$/;
package/dist/testing.js CHANGED
@@ -275,7 +275,7 @@ function impactOfDisabling(access, enabledAfter) {
275
275
  }
276
276
  return broken;
277
277
  }
278
- var VERSION = "0.1.5";
278
+ var VERSION = "0.1.7";
279
279
 
280
280
  // src/testing.ts
281
281
  function nameOf(policies, route) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forgezero/access",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public",