@forgezero/access 0.1.4 → 0.1.6
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 +503 -87
- package/dist/conditions.js +1 -1
- package/dist/effects.js +1 -1
- package/dist/elysia.js +1 -1
- package/dist/fetch.js +1 -1
- package/dist/header.js +10 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/pipeline.js +1 -1
- package/dist/principal-session.d.ts +1 -1
- package/dist/principal-session.js +1 -1
- package/dist/principal.js +1 -1
- package/dist/testing.js +1 -1
- package/package.json +1 -1
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 | [
|
|
39
|
-
| @forgezero/access/conditions | The twelve guards every project writes into `before`, each with the status its refusal deserves. | portable | [
|
|
40
|
-
| @forgezero/access/effects | Audit, emit, meter, invalidate and notify — what happens after a request is decided, never failing it. | portable | [
|
|
41
|
-
| @forgezero/access/security | Constant-time comparison, CSPRNG tokens, HMAC, HKDF, AES-GCM sealing and redaction. Web Crypto only. | portable | [
|
|
42
|
-
| @forgezero/access/rate-limit | Request counters over a window — in memory, in Redis, or in a Durable Object. | portable | [
|
|
43
|
-
| @forgezero/access/fetch | A Fetch-native adapter over the declared access pipeline. | portable | [
|
|
44
|
-
| @forgezero/access/pipeline | The framework-neutral route, principal, factor, policy, rate-limit and effects pipeline. | portable | [
|
|
45
|
-
| @forgezero/access/elysia | Elysia integration over the same access pipeline and route declarations. | portable | [
|
|
46
|
-
| @forgezero/access/client | Typed client helpers that fulfil factors without duplicating the security matrix. | portable | [
|
|
47
|
-
| @forgezero/access/testing | Deterministic access-pipeline fixtures and assertions for consumer tests. | portable | [
|
|
48
|
-
| @forgezero/access/header | Strict configurable header-identity extraction with canonical names and bounded values. | portable | [
|
|
49
|
-
| @forgezero/access/principal | Generic principal-source resolution for browser, API-key, attestation or future identity adapters. | portable | [
|
|
50
|
-
| @forgezero/access/principal-session | Short-lived scope-bound delegated-principal sessions with sliding and absolute expiry. | portable | [
|
|
51
|
-
| @forgezero/access/authenticator | Authentication-source contracts for adding identity mechanisms without changing route policy. | portable | [
|
|
52
|
-
| @forgezero/access/ceremony-modes | Named security-ceremony modes and their session/action fulfilment semantics. | portable | [
|
|
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
|
|
|
@@ -62,18 +62,62 @@ bun add @forgezero/access
|
|
|
62
62
|
<a id="forgezero-access"></a>
|
|
63
63
|
## @forgezero/access
|
|
64
64
|
|
|
65
|
-
Declare routes, factors and policies as orthogonal lists; authorise against them.
|
|
65
|
+
Declare routes, factors and policies as orthogonal lists; authorise against them. This entry exposes 21 named value exports and 27 named type exports. The generated import block lists one name per line for scanning and copying; keep only the names used by your file.
|
|
66
66
|
|
|
67
67
|
```text
|
|
68
|
-
import {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
68
|
+
import {
|
|
69
|
+
AccessError,
|
|
70
|
+
Refusal,
|
|
71
|
+
SCHEMA_VERSION,
|
|
72
|
+
Settled,
|
|
73
|
+
VERSION,
|
|
74
|
+
action,
|
|
75
|
+
assertReadable,
|
|
76
|
+
authorise,
|
|
77
|
+
codePolicy,
|
|
78
|
+
defineAccessControl,
|
|
79
|
+
defineFactors,
|
|
80
|
+
defineRoutes,
|
|
81
|
+
externalPolicy,
|
|
82
|
+
fulfilledActionFactors,
|
|
83
|
+
grantsRoute,
|
|
84
|
+
impactOfDisabling,
|
|
85
|
+
isRefusal,
|
|
86
|
+
isSettled,
|
|
87
|
+
page,
|
|
88
|
+
resolveActionFactors,
|
|
89
|
+
stemOf,
|
|
90
|
+
} from '@forgezero/access';
|
|
91
|
+
|
|
92
|
+
import type {
|
|
93
|
+
AccessControl,
|
|
94
|
+
AccessControlConfig,
|
|
95
|
+
ActionPolicy,
|
|
96
|
+
ActionRoute,
|
|
97
|
+
AfterHandler,
|
|
98
|
+
BeforeHandler,
|
|
99
|
+
Binding,
|
|
100
|
+
FactorContext,
|
|
101
|
+
FactorKind,
|
|
102
|
+
FactorRegistry,
|
|
103
|
+
FactorSpec,
|
|
104
|
+
GrantOptions,
|
|
105
|
+
Method,
|
|
106
|
+
Outcome,
|
|
107
|
+
PageRoute,
|
|
108
|
+
PolicySource,
|
|
109
|
+
Problem,
|
|
110
|
+
RatePolicy,
|
|
111
|
+
RequestContext,
|
|
112
|
+
Role,
|
|
113
|
+
RouteBase,
|
|
114
|
+
RouteContract,
|
|
115
|
+
RouteRegistry,
|
|
116
|
+
RouteSpec,
|
|
117
|
+
SessionContext,
|
|
118
|
+
SessionPolicy,
|
|
119
|
+
Versioned,
|
|
120
|
+
} from '@forgezero/access';
|
|
77
121
|
```
|
|
78
122
|
|
|
79
123
|
## @forgezero/access — Declare routes before handlers
|
|
@@ -81,7 +125,11 @@ import type { SessionContext, SessionPolicy, Versioned } from '@forgezero/access
|
|
|
81
125
|
Routes and their access policy are data; Fetch and Elysia adapters enforce the same declaration.
|
|
82
126
|
|
|
83
127
|
```text
|
|
84
|
-
import {
|
|
128
|
+
import {
|
|
129
|
+
defineRoutes,
|
|
130
|
+
action,
|
|
131
|
+
page,
|
|
132
|
+
} from '@forgezero/access';
|
|
85
133
|
|
|
86
134
|
export const routes = defineRoutes({
|
|
87
135
|
orders: page('Orders'),
|
|
@@ -92,153 +140,501 @@ export const routes = defineRoutes({
|
|
|
92
140
|
<a id="forgezero-access-conditions"></a>
|
|
93
141
|
## @forgezero/access/conditions
|
|
94
142
|
|
|
95
|
-
The twelve guards every project writes into `before`, each with the status its refusal deserves.
|
|
143
|
+
The twelve guards every project writes into `before`, each with the status its refusal deserves. This entry exposes 14 named value exports and 16 named type exports. The generated import block lists one name per line for scanning and copying; keep only the names used by your file.
|
|
96
144
|
|
|
97
145
|
```text
|
|
98
|
-
import {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
146
|
+
import {
|
|
147
|
+
assertDeclaredRefusals,
|
|
148
|
+
loadTarget,
|
|
149
|
+
refusalsFor,
|
|
150
|
+
requireApproval,
|
|
151
|
+
requireBalance,
|
|
152
|
+
requireIdempotency,
|
|
153
|
+
requireNotFrozen,
|
|
154
|
+
requireOwner,
|
|
155
|
+
requireQuota,
|
|
156
|
+
requireService,
|
|
157
|
+
requireState,
|
|
158
|
+
requireTier,
|
|
159
|
+
requireUnlocked,
|
|
160
|
+
requireVersion,
|
|
161
|
+
} from '@forgezero/access/conditions';
|
|
162
|
+
|
|
163
|
+
import type {
|
|
164
|
+
ApprovalState,
|
|
165
|
+
Condition,
|
|
166
|
+
IdempotencyStore,
|
|
167
|
+
LoadTargetOptions,
|
|
168
|
+
RefusalSpec,
|
|
169
|
+
RequireApprovalOptions,
|
|
170
|
+
RequireBalanceOptions,
|
|
171
|
+
RequireIdempotencyOptions,
|
|
172
|
+
RequireNotFrozenOptions,
|
|
173
|
+
RequireOwnerOptions,
|
|
174
|
+
RequireQuotaOptions,
|
|
175
|
+
RequireServiceOptions,
|
|
176
|
+
RequireStateOptions,
|
|
177
|
+
RequireTierOptions,
|
|
178
|
+
RequireUnlockedOptions,
|
|
179
|
+
RequireVersionOptions,
|
|
180
|
+
} from '@forgezero/access/conditions';
|
|
181
|
+
```
|
|
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;
|
|
104
193
|
```
|
|
105
194
|
|
|
106
195
|
<a id="forgezero-access-effects"></a>
|
|
107
196
|
## @forgezero/access/effects
|
|
108
197
|
|
|
109
|
-
Audit, emit, meter, invalidate and notify — what happens after a request is decided, never failing it.
|
|
198
|
+
Audit, emit, meter, invalidate and notify — what happens after a request is decided, never failing it. This entry exposes 6 named value exports and 15 named type exports. The generated import block lists one name per line for scanning and copying; keep only the names used by your file.
|
|
110
199
|
|
|
111
200
|
```text
|
|
112
|
-
import {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
201
|
+
import {
|
|
202
|
+
audit,
|
|
203
|
+
emit,
|
|
204
|
+
invalidate,
|
|
205
|
+
meter,
|
|
206
|
+
notify,
|
|
207
|
+
settlementOf,
|
|
208
|
+
} from '@forgezero/access/effects';
|
|
209
|
+
|
|
210
|
+
import type {
|
|
211
|
+
AuditOptions,
|
|
212
|
+
AuditRecord,
|
|
213
|
+
AuditSink,
|
|
214
|
+
CacheInvalidator,
|
|
215
|
+
Effect,
|
|
216
|
+
EmitOptions,
|
|
217
|
+
InvalidateOptions,
|
|
218
|
+
MeterOptions,
|
|
219
|
+
Notification,
|
|
220
|
+
Notifier,
|
|
221
|
+
NotifyOptions,
|
|
222
|
+
Outbox,
|
|
223
|
+
OutboxEvent,
|
|
224
|
+
Settlement,
|
|
225
|
+
UsageMeter,
|
|
226
|
+
} from '@forgezero/access/effects';
|
|
227
|
+
```
|
|
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;
|
|
116
239
|
```
|
|
117
240
|
|
|
118
241
|
<a id="forgezero-access-security"></a>
|
|
119
242
|
## @forgezero/access/security
|
|
120
243
|
|
|
121
|
-
Constant-time comparison, CSPRNG tokens, HMAC, HKDF, AES-GCM sealing and redaction. Web Crypto only.
|
|
244
|
+
Constant-time comparison, CSPRNG tokens, HMAC, HKDF, AES-GCM sealing and redaction. Web Crypto only. This entry exposes 20 named value exports and 1 named type export. The generated import block lists one name per line for scanning and copying; keep only the names used by your file.
|
|
245
|
+
|
|
246
|
+
```text
|
|
247
|
+
import {
|
|
248
|
+
fromBase64Url,
|
|
249
|
+
fromHex,
|
|
250
|
+
hashToken,
|
|
251
|
+
hkdf,
|
|
252
|
+
hmacSha256,
|
|
253
|
+
isLive,
|
|
254
|
+
nowSeconds,
|
|
255
|
+
open,
|
|
256
|
+
randomDigits,
|
|
257
|
+
randomHex,
|
|
258
|
+
randomInt,
|
|
259
|
+
randomToken,
|
|
260
|
+
redact,
|
|
261
|
+
seal,
|
|
262
|
+
secretFieldPattern,
|
|
263
|
+
sha256,
|
|
264
|
+
timingSafeEqual,
|
|
265
|
+
toBase64Url,
|
|
266
|
+
toHex,
|
|
267
|
+
verifyHmac,
|
|
268
|
+
} from '@forgezero/access/security';
|
|
269
|
+
|
|
270
|
+
import type {
|
|
271
|
+
Sealed,
|
|
272
|
+
} from '@forgezero/access/security';
|
|
273
|
+
```
|
|
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.
|
|
122
278
|
|
|
123
279
|
```text
|
|
124
|
-
import {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
280
|
+
import {
|
|
281
|
+
fromBase64Url,
|
|
282
|
+
} from '@forgezero/access/security';
|
|
283
|
+
|
|
284
|
+
export const selectedCapability = fromBase64Url;
|
|
129
285
|
```
|
|
130
286
|
|
|
131
287
|
<a id="forgezero-access-rate-limit"></a>
|
|
132
288
|
## @forgezero/access/rate-limit
|
|
133
289
|
|
|
134
|
-
Request counters over a window — in memory, in Redis, or in a Durable Object.
|
|
290
|
+
Request counters over a window — in memory, in Redis, or in a Durable Object. This entry exposes 4 named value exports and 2 named type exports. The generated import block lists one name per line for scanning and copying; keep only the names used by your file.
|
|
291
|
+
|
|
292
|
+
```text
|
|
293
|
+
import {
|
|
294
|
+
durableObjectStore,
|
|
295
|
+
memoryStore,
|
|
296
|
+
redisStore,
|
|
297
|
+
slidingWindowStore,
|
|
298
|
+
} from '@forgezero/access/rate-limit';
|
|
299
|
+
|
|
300
|
+
import type {
|
|
301
|
+
DurableStorageLike,
|
|
302
|
+
RedisLike,
|
|
303
|
+
} from '@forgezero/access/rate-limit';
|
|
304
|
+
```
|
|
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.
|
|
135
309
|
|
|
136
310
|
```text
|
|
137
|
-
import {
|
|
138
|
-
|
|
311
|
+
import {
|
|
312
|
+
durableObjectStore,
|
|
313
|
+
} from '@forgezero/access/rate-limit';
|
|
314
|
+
|
|
315
|
+
export const selectedCapability = durableObjectStore;
|
|
139
316
|
```
|
|
140
317
|
|
|
141
318
|
<a id="forgezero-access-fetch"></a>
|
|
142
319
|
## @forgezero/access/fetch
|
|
143
320
|
|
|
144
|
-
A Fetch-native adapter over the declared access pipeline.
|
|
321
|
+
A Fetch-native adapter over the declared access pipeline. This entry exposes 3 named value exports and 1 named type export. The generated import block lists one name per line for scanning and copying; keep only the names used by your file.
|
|
145
322
|
|
|
146
323
|
```text
|
|
147
|
-
import {
|
|
148
|
-
|
|
324
|
+
import {
|
|
325
|
+
compileRoute,
|
|
326
|
+
matchRoute,
|
|
327
|
+
toFetch,
|
|
328
|
+
} from '@forgezero/access/fetch';
|
|
329
|
+
|
|
330
|
+
import type {
|
|
331
|
+
FetchHandler,
|
|
332
|
+
} from '@forgezero/access/fetch';
|
|
333
|
+
```
|
|
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;
|
|
149
345
|
```
|
|
150
346
|
|
|
151
347
|
<a id="forgezero-access-pipeline"></a>
|
|
152
348
|
## @forgezero/access/pipeline
|
|
153
349
|
|
|
154
|
-
The framework-neutral route, principal, factor, policy, rate-limit and effects pipeline.
|
|
350
|
+
The framework-neutral route, principal, factor, policy, rate-limit and effects pipeline. This entry exposes 3 named value exports and 9 named type exports. The generated import block lists one name per line for scanning and copying; keep only the names used by your file.
|
|
155
351
|
|
|
156
352
|
```text
|
|
157
|
-
import {
|
|
158
|
-
|
|
159
|
-
|
|
353
|
+
import {
|
|
354
|
+
createPipeline,
|
|
355
|
+
defineHandlers,
|
|
356
|
+
windowSeconds,
|
|
357
|
+
} from '@forgezero/access/pipeline';
|
|
358
|
+
|
|
359
|
+
import type {
|
|
360
|
+
Handler,
|
|
361
|
+
HandlerRegistry,
|
|
362
|
+
Pipeline,
|
|
363
|
+
PipelineOptions,
|
|
364
|
+
RateStore,
|
|
365
|
+
SessionResolver,
|
|
366
|
+
StepUpStore,
|
|
367
|
+
Telemetry,
|
|
368
|
+
Validator,
|
|
369
|
+
} from '@forgezero/access/pipeline';
|
|
370
|
+
```
|
|
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;
|
|
160
382
|
```
|
|
161
383
|
|
|
162
384
|
<a id="forgezero-access-elysia"></a>
|
|
163
385
|
## @forgezero/access/elysia
|
|
164
386
|
|
|
165
|
-
Elysia integration over the same access pipeline and route declarations.
|
|
387
|
+
Elysia integration over the same access pipeline and route declarations. This entry exposes 4 named value exports and 2 named type exports. The generated import block lists one name per line for scanning and copying; keep only the names used by your file.
|
|
388
|
+
|
|
389
|
+
```text
|
|
390
|
+
import {
|
|
391
|
+
elysia,
|
|
392
|
+
forbiddenTelemetryAttribute,
|
|
393
|
+
telemetryFrom,
|
|
394
|
+
toElysiaPath,
|
|
395
|
+
} from '@forgezero/access/elysia';
|
|
396
|
+
|
|
397
|
+
import type {
|
|
398
|
+
ElysiaAdapterOptions,
|
|
399
|
+
OtelTracer,
|
|
400
|
+
} from '@forgezero/access/elysia';
|
|
401
|
+
```
|
|
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.
|
|
166
406
|
|
|
167
407
|
```text
|
|
168
|
-
import {
|
|
169
|
-
|
|
408
|
+
import {
|
|
409
|
+
elysia,
|
|
410
|
+
} from '@forgezero/access/elysia';
|
|
411
|
+
|
|
412
|
+
export const selectedCapability = elysia;
|
|
170
413
|
```
|
|
171
414
|
|
|
172
415
|
<a id="forgezero-access-client"></a>
|
|
173
416
|
## @forgezero/access/client
|
|
174
417
|
|
|
175
|
-
Typed client helpers that fulfil factors without duplicating the security matrix.
|
|
418
|
+
Typed client helpers that fulfil factors without duplicating the security matrix. This entry exposes 2 named value exports and 6 named type exports. The generated import block lists one name per line for scanning and copying; keep only the names used by your file.
|
|
176
419
|
|
|
177
420
|
```text
|
|
178
|
-
import {
|
|
179
|
-
|
|
421
|
+
import {
|
|
422
|
+
buildPath,
|
|
423
|
+
createClient,
|
|
424
|
+
} from '@forgezero/access/client';
|
|
425
|
+
|
|
426
|
+
import type {
|
|
427
|
+
ChallengeHandler,
|
|
428
|
+
ClientOptions,
|
|
429
|
+
ClientResult,
|
|
430
|
+
Problem,
|
|
431
|
+
RequestArgs,
|
|
432
|
+
SecurityChallenge,
|
|
433
|
+
} from '@forgezero/access/client';
|
|
434
|
+
```
|
|
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;
|
|
180
446
|
```
|
|
181
447
|
|
|
182
448
|
<a id="forgezero-access-testing"></a>
|
|
183
449
|
## @forgezero/access/testing
|
|
184
450
|
|
|
185
|
-
Deterministic access-pipeline fixtures and assertions for consumer tests.
|
|
451
|
+
Deterministic access-pipeline fixtures and assertions for consumer tests. This entry exposes 3 named value exports and 2 named type exports. The generated import block lists one name per line for scanning and copying; keep only the names used by your file.
|
|
186
452
|
|
|
187
453
|
```text
|
|
188
|
-
import {
|
|
189
|
-
|
|
454
|
+
import {
|
|
455
|
+
reachableRoutes,
|
|
456
|
+
simulate,
|
|
457
|
+
unreachableRoutes,
|
|
458
|
+
} from '@forgezero/access/testing';
|
|
459
|
+
|
|
460
|
+
import type {
|
|
461
|
+
SimulateArgs,
|
|
462
|
+
Verdict,
|
|
463
|
+
} from '@forgezero/access/testing';
|
|
464
|
+
```
|
|
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;
|
|
190
476
|
```
|
|
191
477
|
|
|
192
478
|
<a id="forgezero-access-header"></a>
|
|
193
479
|
## @forgezero/access/header
|
|
194
480
|
|
|
195
|
-
Strict configurable header-identity extraction with canonical names and bounded values.
|
|
481
|
+
Strict configurable header-identity extraction with canonical names and bounded values. This entry exposes 2 named value exports and 4 named type exports. The generated import block lists one name per line for scanning and copying; keep only the names used by your file.
|
|
482
|
+
|
|
483
|
+
```text
|
|
484
|
+
import {
|
|
485
|
+
defineHeaderIdentitySources,
|
|
486
|
+
headerIdentityResolver,
|
|
487
|
+
} from '@forgezero/access/header';
|
|
488
|
+
|
|
489
|
+
import type {
|
|
490
|
+
HeaderAssignmentResolver,
|
|
491
|
+
HeaderIdentity,
|
|
492
|
+
HeaderIdentitySource,
|
|
493
|
+
HeaderPrincipal,
|
|
494
|
+
} from '@forgezero/access/header';
|
|
495
|
+
```
|
|
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.
|
|
196
500
|
|
|
197
501
|
```text
|
|
198
|
-
import {
|
|
199
|
-
|
|
502
|
+
import {
|
|
503
|
+
defineHeaderIdentitySources,
|
|
504
|
+
} from '@forgezero/access/header';
|
|
505
|
+
|
|
506
|
+
export const selectedCapability = defineHeaderIdentitySources;
|
|
200
507
|
```
|
|
201
508
|
|
|
202
509
|
<a id="forgezero-access-principal"></a>
|
|
203
510
|
## @forgezero/access/principal
|
|
204
511
|
|
|
205
|
-
Generic principal-source resolution for browser, API-key, attestation or future identity adapters.
|
|
512
|
+
Generic principal-source resolution for browser, API-key, attestation or future identity adapters. This entry exposes 4 named value exports and 3 named type exports. The generated import block lists one name per line for scanning and copying; keep only the names used by your file.
|
|
513
|
+
|
|
514
|
+
```text
|
|
515
|
+
import {
|
|
516
|
+
assignmentIsActive,
|
|
517
|
+
decidePrincipalAccess,
|
|
518
|
+
defineRbacPrincipal,
|
|
519
|
+
touchPrincipalAssignment,
|
|
520
|
+
} from '@forgezero/access/principal';
|
|
521
|
+
|
|
522
|
+
import type {
|
|
523
|
+
PrincipalAccessDecision,
|
|
524
|
+
PrincipalAssignment,
|
|
525
|
+
RbacPrincipal,
|
|
526
|
+
} from '@forgezero/access/principal';
|
|
527
|
+
```
|
|
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.
|
|
206
532
|
|
|
207
533
|
```text
|
|
208
|
-
import {
|
|
209
|
-
|
|
534
|
+
import {
|
|
535
|
+
assignmentIsActive,
|
|
536
|
+
} from '@forgezero/access/principal';
|
|
537
|
+
|
|
538
|
+
export const selectedCapability = assignmentIsActive;
|
|
210
539
|
```
|
|
211
540
|
|
|
212
541
|
<a id="forgezero-access-principal-session"></a>
|
|
213
542
|
## @forgezero/access/principal-session
|
|
214
543
|
|
|
215
|
-
Short-lived scope-bound delegated-principal sessions with sliding and absolute expiry.
|
|
544
|
+
Short-lived scope-bound delegated-principal sessions with sliding and absolute expiry. This entry exposes 8 named value exports and 2 named type exports. The generated import block lists one name per line for scanning and copying; keep only the names used by your file.
|
|
216
545
|
|
|
217
546
|
```text
|
|
218
|
-
import {
|
|
219
|
-
|
|
220
|
-
|
|
547
|
+
import {
|
|
548
|
+
DEFAULT_PRINCIPAL_ABSOLUTE_TTL_MS,
|
|
549
|
+
DEFAULT_PRINCIPAL_IDLE_TTL_MS,
|
|
550
|
+
MAX_PRINCIPAL_ABSOLUTE_TTL_MS,
|
|
551
|
+
MAX_PRINCIPAL_IDLE_TTL_MS,
|
|
552
|
+
authenticatePrincipalSession,
|
|
553
|
+
issuePrincipalSession,
|
|
554
|
+
principalSessionIsActive,
|
|
555
|
+
touchPrincipalSession,
|
|
556
|
+
} from '@forgezero/access/principal-session';
|
|
557
|
+
|
|
558
|
+
import type {
|
|
559
|
+
IssuedPrincipalSession,
|
|
560
|
+
PrincipalSessionRecord,
|
|
561
|
+
} from '@forgezero/access/principal-session';
|
|
562
|
+
```
|
|
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;
|
|
221
574
|
```
|
|
222
575
|
|
|
223
576
|
<a id="forgezero-access-authenticator"></a>
|
|
224
577
|
## @forgezero/access/authenticator
|
|
225
578
|
|
|
226
|
-
Authentication-source contracts for adding identity mechanisms without changing route policy.
|
|
579
|
+
Authentication-source contracts for adding identity mechanisms without changing route policy. This entry exposes 2 named value exports and 7 named type exports. The generated import block lists one name per line for scanning and copying; keep only the names used by your file.
|
|
227
580
|
|
|
228
581
|
```text
|
|
229
|
-
import {
|
|
230
|
-
|
|
231
|
-
|
|
582
|
+
import {
|
|
583
|
+
createAuthenticator,
|
|
584
|
+
encoding,
|
|
585
|
+
} from '@forgezero/access/authenticator';
|
|
586
|
+
|
|
587
|
+
import type {
|
|
588
|
+
AuthenticationOptions,
|
|
589
|
+
AuthenticationResponse,
|
|
590
|
+
Authenticator,
|
|
591
|
+
AuthenticatorOptions,
|
|
592
|
+
Credential,
|
|
593
|
+
RegistrationOptions,
|
|
594
|
+
RegistrationResponse,
|
|
595
|
+
} from '@forgezero/access/authenticator';
|
|
596
|
+
```
|
|
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;
|
|
232
608
|
```
|
|
233
609
|
|
|
234
610
|
<a id="forgezero-access-ceremony-modes"></a>
|
|
235
611
|
## @forgezero/access/ceremony-modes
|
|
236
612
|
|
|
237
|
-
Named security-ceremony modes and their session/action fulfilment semantics.
|
|
613
|
+
Named security-ceremony modes and their session/action fulfilment semantics. This entry exposes 3 named value exports and 2 named type exports. The generated import block lists one name per line for scanning and copying; keep only the names used by your file.
|
|
614
|
+
|
|
615
|
+
```text
|
|
616
|
+
import {
|
|
617
|
+
MAX_CUSTODIANS,
|
|
618
|
+
THRESHOLD_MODES,
|
|
619
|
+
thresholdMode,
|
|
620
|
+
} from '@forgezero/access/ceremony-modes';
|
|
621
|
+
|
|
622
|
+
import type {
|
|
623
|
+
ThresholdMode,
|
|
624
|
+
ThresholdModeId,
|
|
625
|
+
} from '@forgezero/access/ceremony-modes';
|
|
626
|
+
```
|
|
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.
|
|
238
631
|
|
|
239
632
|
```text
|
|
240
|
-
import {
|
|
241
|
-
|
|
633
|
+
import {
|
|
634
|
+
MAX_CUSTODIANS,
|
|
635
|
+
} from '@forgezero/access/ceremony-modes';
|
|
636
|
+
|
|
637
|
+
export const selectedCapability = MAX_CUSTODIANS;
|
|
242
638
|
```
|
|
243
639
|
|
|
244
640
|
## 1. Install
|
|
@@ -254,7 +650,12 @@ bun add @forgezero/access
|
|
|
254
650
|
Routes carry their contract — label, method, and the shapes they accept and return. WHO may reach them is a separate list, because the two change for different reasons and on different schedules.
|
|
255
651
|
|
|
256
652
|
```text
|
|
257
|
-
import {
|
|
653
|
+
import {
|
|
654
|
+
defineRoutes,
|
|
655
|
+
defineAccessControl,
|
|
656
|
+
page,
|
|
657
|
+
action,
|
|
658
|
+
} from '@forgezero/access';
|
|
258
659
|
|
|
259
660
|
export const ROUTES = defineRoutes({
|
|
260
661
|
orders: page('Orders'),
|
|
@@ -278,11 +679,15 @@ One line per runtime. The pipeline is written once and shared, so an adapter nev
|
|
|
278
679
|
|
|
279
680
|
```text
|
|
280
681
|
// anywhere fetch exists — Workers, Deno, Node, Bun
|
|
281
|
-
import {
|
|
682
|
+
import {
|
|
683
|
+
toFetch,
|
|
684
|
+
} from '@forgezero/access/fetch';
|
|
282
685
|
export default { fetch: toFetch({ access: ACCESS, handlers: HANDLERS }) };
|
|
283
686
|
|
|
284
687
|
// Elysia
|
|
285
|
-
import {
|
|
688
|
+
import {
|
|
689
|
+
elysia,
|
|
690
|
+
} from '@forgezero/access/elysia';
|
|
286
691
|
app.use(elysia({ access: ACCESS, handlers: HANDLERS, Elysia }));
|
|
287
692
|
```
|
|
288
693
|
|
|
@@ -328,7 +733,10 @@ impactOfDisabling(ACCESS, ['passkey'])
|
|
|
328
733
|
simulate() reports which policy decided, which a browser 403 never tells you. reachableRoutes() answers what a role can actually do — worth running, because stem inheritance grants more than a grant list reads like.
|
|
329
734
|
|
|
330
735
|
```text
|
|
331
|
-
import {
|
|
736
|
+
import {
|
|
737
|
+
simulate,
|
|
738
|
+
reachableRoutes,
|
|
739
|
+
} from '@forgezero/access/testing';
|
|
332
740
|
|
|
333
741
|
simulate(ACCESS, { route: 'api/settings', roles, as: 'member' });
|
|
334
742
|
// { allowed: false, status: 403, reason: 'ACCESS_DENIED', sessionPolicy: 'admin' }
|
|
@@ -342,8 +750,12 @@ reachableRoutes(ACCESS, roles, ['member']);
|
|
|
342
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.
|
|
343
751
|
|
|
344
752
|
```text
|
|
345
|
-
import {
|
|
346
|
-
|
|
753
|
+
import {
|
|
754
|
+
loadTarget,
|
|
755
|
+
requireOwner,
|
|
756
|
+
requireState,
|
|
757
|
+
requireBalance,
|
|
758
|
+
} from '@forgezero/access/conditions';
|
|
347
759
|
|
|
348
760
|
beforeHandlers: {
|
|
349
761
|
load: loadTarget({ routes: ['api/orders/[id]/refund'], load: findOrder }),
|
|
@@ -379,7 +791,11 @@ assertDeclaredRefusals({ routes: ROUTES, conditions: CONDITIONS });
|
|
|
379
791
|
Audit, emit, meter, invalidate and notify. None can fail the request — a dead audit sink must not turn a completed transfer into a 500. Audit records denials as well as successes, because a run of 403s from one session is the signal an incident is reconstructed from. Every payload is redacted first.
|
|
380
792
|
|
|
381
793
|
```text
|
|
382
|
-
import {
|
|
794
|
+
import {
|
|
795
|
+
audit,
|
|
796
|
+
emit,
|
|
797
|
+
meter,
|
|
798
|
+
} from '@forgezero/access/effects';
|
|
383
799
|
|
|
384
800
|
afterHandlers: {
|
|
385
801
|
trail: audit({ routes: [...], sink }),
|
package/dist/conditions.js
CHANGED
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.
|
|
278
|
+
var VERSION = "0.1.6";
|
|
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
package/dist/fetch.js
CHANGED
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.
|
|
278
|
+
var VERSION = "0.1.6";
|
|
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 ([
|
|
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
package/dist/index.js
CHANGED
package/dist/pipeline.js
CHANGED
|
@@ -18,7 +18,7 @@ export interface PrincipalSessionRecord {
|
|
|
18
18
|
absoluteExpiresAtMs: number;
|
|
19
19
|
}
|
|
20
20
|
export interface IssuedPrincipalSession {
|
|
21
|
-
/** Returned once.
|
|
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.
|
|
278
|
+
var VERSION = "0.1.6";
|
|
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
package/dist/testing.js
CHANGED