@orkestrel/middleware 0.0.18 → 0.0.20

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.
@@ -1,27 +1,26 @@
1
- import { ConnectionInfo } from '@orkestrel/server';
2
- import { CookieOptions } from '@orkestrel/server';
3
- import { Encoding } from '@orkestrel/server';
4
- import { Guard } from '@orkestrel/contract';
1
+ import type { Connection } from '@orkestrel/server';
2
+ import type { CookieOptions } from '@orkestrel/server';
3
+ import type { Encoding } from '@orkestrel/server';
4
+ import type { Guard } from '@orkestrel/contract';
5
5
  import { JSONShape } from '@orkestrel/contract';
6
- import { MiddlewareContext } from '@orkestrel/server';
7
- import { MiddlewareHandler } from '@orkestrel/server';
6
+ import type { MiddlewareContext } from '@orkestrel/server';
7
+ import type { MiddlewareHandler } from '@orkestrel/server';
8
8
  import { NumberShape } from '@orkestrel/contract';
9
9
  import { StringShape } from '@orkestrel/contract';
10
- import { TableInterface } from '@orkestrel/database';
11
- import { TokenSecret } from '@orkestrel/server';
10
+ import type { TableInterface } from '@orkestrel/database';
11
+ import type { TokenSecret } from '@orkestrel/server';
12
12
 
13
13
  /**
14
- * Options for `createBearer` — bearer-token authentication.
14
+ * Configures `createBearer` — bearer-token authentication.
15
15
  *
16
- * @param options - See fields below
17
16
  * @remarks
18
17
  * - `secret` — the {@link TokenSecret} `verifyToken` checks the extracted
19
18
  * token against (rotation-aware).
20
19
  * - `header` — the header the token is read from; defaults to
21
20
  * {@link DEFAULT_BEARER_HEADER}.
22
- * - `scheme` — the scheme prefix stripped before verification (case-
23
- * insensitive); defaults to {@link DEFAULT_BEARER_SCHEME}. An empty string
24
- * means the whole header value is the raw token.
21
+ * - `scheme` — the scheme prefix stripped before verification
22
+ * (case-insensitive); defaults to {@link DEFAULT_BEARER_SCHEME}. An empty
23
+ * string means the whole header value is the raw token.
25
24
  */
26
25
  export declare interface BearerOptions {
27
26
  readonly secret: TokenSecret;
@@ -30,7 +29,7 @@ export declare interface BearerOptions {
30
29
  }
31
30
 
32
31
  /**
33
- * The bearer-authentication state slice `createBearer` stashes on
32
+ * Describes the bearer-authentication state slice `createBearer` stashes on
34
33
  * `context.state` once a token verifies.
35
34
  *
36
35
  * @remarks
@@ -43,7 +42,7 @@ export declare interface BearerState {
43
42
  }
44
43
 
45
44
  /**
46
- * The body state slice `createBody` stashes.
45
+ * Describes the body state slice `createBody` stashes.
47
46
  *
48
47
  * @remarks
49
48
  * `body` holds the same defined value the cached `context.body()` resolved
@@ -55,9 +54,8 @@ export declare interface BodyState {
55
54
  }
56
55
 
57
56
  /**
58
- * Options for `createBoundary` — the outermost error-rendering battery.
57
+ * Configures `createBoundary` — the outermost error-rendering battery.
59
58
  *
60
- * @param options - See fields below
61
59
  * @remarks
62
60
  * - `expose` — when `true`, a non-`HTTPError` throw's `error.message` is
63
61
  * surfaced in the 500 body instead of a generic message. Defaults to
@@ -71,22 +69,22 @@ export declare interface BoundaryOptions {
71
69
  }
72
70
 
73
71
  /**
74
- * A parsed client-info fact for {@link ClientInfo} a leaf shaping helper
75
- * `createForwarded` uses to build its stashed slice.
72
+ * Builds the {@link Client} slice `createForwarded` stashes, from the
73
+ * resolved client IP a leaf shaping helper.
76
74
  *
77
75
  * @param ip - The resolved client IP, if any
78
- * @returns The {@link ClientInfo} slice value
76
+ * @returns The {@link Client} slice value
79
77
  *
80
78
  * @example
81
79
  * ```ts
82
- * buildClientInfo('203.0.113.7') // { ip: '203.0.113.7' }
80
+ * buildClient('203.0.113.7') // { ip: '203.0.113.7' }
83
81
  * ```
84
82
  */
85
- export declare function buildClientInfo(ip: string | undefined): ClientInfo;
83
+ export declare function buildClient(ip: string | undefined): Client_2;
86
84
 
87
85
  /**
88
- * Build the draft `RateLimit` structured header field (ruling I) emitted
89
- * only when `createLimiter`'s `policy` option is `true`.
86
+ * Builds the draft `RateLimit` structured header field emitted only when
87
+ * `createLimiter`'s `policy` option is `true`.
90
88
  *
91
89
  * @param remaining - The requests still admitted this window
92
90
  * @param resetAt - The window reset instant (same clock unit as `now`)
@@ -101,8 +99,8 @@ export declare function buildClientInfo(ip: string | undefined): ClientInfo;
101
99
  export declare function buildRateLimitField(remaining: number, resetAt: number, now: number): string;
102
100
 
103
101
  /**
104
- * Build the draft `RateLimit-Policy` structured header field (ruling I)
105
- * emitted only when `createLimiter`'s `policy` option is `true`.
102
+ * Builds the draft `RateLimit-Policy` structured header field emitted only
103
+ * when `createLimiter`'s `policy` option is `true`.
106
104
  *
107
105
  * @param max - The window's admitted request count
108
106
  * @param window - The window length in milliseconds
@@ -116,8 +114,8 @@ export declare function buildRateLimitField(remaining: number, resetAt: number,
116
114
  export declare function buildRateLimitPolicyField(max: number, window: number): string;
117
115
 
118
116
  /**
119
- * Build the `Retry-After` header value — whole seconds until a window reset,
120
- * floored at a minimum of `1` (ruling I).
117
+ * Builds the `Retry-After` header value — whole seconds until a window reset,
118
+ * floored at a minimum of `1`.
121
119
  *
122
120
  * @param resetAt - The window reset instant (same clock unit as `now`)
123
121
  * @param now - The current instant
@@ -131,26 +129,27 @@ export declare function buildRateLimitPolicyField(max: number, window: number):
131
129
  export declare function buildRetryAfter(resetAt: number, now: number): string;
132
130
 
133
131
  /**
134
- * The resolved client connection facts `createForwarded` stashes.
132
+ * Describes the resolved client connection facts `createForwarded` stashes.
135
133
  *
136
134
  * @remarks
137
135
  * `ip` is the first untrusted address walking `X-Forwarded-For` /
138
136
  * `Forwarded` right-to-left past the configured trusted hops, falling back
139
137
  * to the socket peer when no proxy hop qualifies.
140
138
  */
141
- export declare interface ClientInfo {
139
+ declare interface Client_2 {
142
140
  readonly ip?: string;
143
141
  }
142
+ export { Client_2 as Client }
144
143
 
145
144
  /**
146
- * The client-facts state slice `createForwarded` stashes.
145
+ * Describes the client-facts state slice `createForwarded` stashes.
147
146
  */
148
147
  export declare interface ClientState {
149
- readonly client?: ClientInfo;
148
+ readonly client?: Client_2;
150
149
  }
151
150
 
152
151
  /**
153
- * Compress bytes with the host-independent `CompressionStream` primitive.
152
+ * Compresses bytes with the host-independent `CompressionStream` primitive.
154
153
  *
155
154
  * @param bytes - The uncompressed response bytes
156
155
  * @param encoding - The negotiated actionable coding
@@ -166,14 +165,13 @@ export declare interface ClientState {
166
165
  export declare function compressBytes(bytes: Uint8Array<ArrayBuffer>, encoding: Exclude<Encoding, 'identity'>): Promise<Uint8Array<ArrayBuffer>>;
167
166
 
168
167
  /**
169
- * Options for `createCompression` — response-body compression.
168
+ * Configures `createCompression` — response-body compression.
170
169
  *
171
- * @param options - See fields below
172
170
  * @remarks
173
171
  * - `threshold` — the minimum buffered body size (bytes) worth compressing;
174
172
  * defaults to {@link DEFAULT_COMPRESSION_THRESHOLD}.
175
173
  * - `encodings` — the codings offered, in preference order, intersected at
176
- * CONSTRUCTION with what the runtime's `CompressionStream` actually
174
+ * construction with what the runtime's `CompressionStream` actually
177
175
  * supports; defaults to {@link DEFAULT_COMPRESSION_ENCODINGS}.
178
176
  * - `filter` — an optional per-response opt-out predicate (the BREACH
179
177
  * posture escape hatch); a response the predicate declines is never
@@ -186,7 +184,7 @@ export declare interface CompressionOptions {
186
184
  }
187
185
 
188
186
  /**
189
- * The shared negotiate → skip → threshold → compress → header-set skeleton
187
+ * Runs the shared negotiate → skip → threshold → compress → header-set skeleton
190
188
  * both faces' `createCompression` batteries compose — response-body
191
189
  * compression over a caller-supplied set of feature-detected codings.
192
190
  *
@@ -196,17 +194,17 @@ export declare interface CompressionOptions {
196
194
  * even when a later skip declines to compress) → `negotiateEncoding` over
197
195
  * `options.encodings` → {@link isCompressionNegotiated} → `isCompressibleType`
198
196
  * on `Content-Type` → a fast skip when the response already carries a
199
- * numeric `Content-Length` BELOW `options.threshold` (avoids buffering a
200
- * body known too small to be worth compressing) → buffer via
197
+ * numeric `Content-Length` below `options.threshold` (avoids buffering a
198
+ * body known too small to be worth compressing) → buffer through
201
199
  * `response.arrayBuffer()` → a threshold passthrough when the buffered size
202
200
  * is still below `options.threshold` → `options.compress` → set
203
- * `Content-Encoding` and a fresh `Content-Length` via {@link rebuildResponse}.
201
+ * `Content-Encoding` and a fresh `Content-Length` through {@link rebuildResponse}.
204
202
  * Returns `response` unchanged (aside from the `Vary` stamp) on any skip.
205
203
  *
206
204
  * @param request - The inbound `Request` (read for `Accept-Encoding`)
207
205
  * @param context - The `MiddlewareContext` (read for `context.method`)
208
206
  * @param response - The downstream `Response` to consider compressing
209
- * @param options - The threshold, optional filter, offered encodings, and the runtime's `compress` primitive
207
+ * @param options - See {@link CompressResponseOptions}
210
208
  * @returns The original `response` when skipped, or a new compressed `Response`
211
209
  *
212
210
  * @example
@@ -218,27 +216,42 @@ export declare interface CompressionOptions {
218
216
  * })
219
217
  * ```
220
218
  */
221
- export declare function compressResponse(request: Request, context: MiddlewareContext<unknown>, response: Response, options: {
219
+ export declare function compressResponse(request: Request, context: MiddlewareContext<unknown>, response: Response, options: CompressResponseOptions): Promise<Response>;
220
+
221
+ /**
222
+ * Describes the already-resolved settings `compressResponse` runs its shared
223
+ * negotiate → skip → threshold → compress skeleton against — the shape each
224
+ * face's `createCompression` builds from its own option bag.
225
+ *
226
+ * @remarks
227
+ * - `threshold` — the minimum body size (bytes) worth compressing.
228
+ * - `filter` — the per-response opt-out predicate; absent allows every
229
+ * response.
230
+ * - `encodings` — the codings offered, in preference order, already narrowed
231
+ * to what this face can actually produce.
232
+ * - `compress` — the runtime's compression primitive for one negotiated
233
+ * coding.
234
+ */
235
+ export declare interface CompressResponseOptions {
222
236
  readonly threshold: number;
223
237
  readonly filter?: (request: Request, response: Response) => boolean;
224
238
  readonly encodings: readonly Encoding[];
225
239
  readonly compress: (bytes: Uint8Array<ArrayBuffer>, encoding: Exclude<Encoding, 'identity'>) => Promise<Uint8Array<ArrayBuffer>>;
226
- }): Promise<Response>;
240
+ }
227
241
 
228
242
  /**
229
- * The connection-facts state slice `createLimiter`'s default key derivation
243
+ * Describes the connection-facts state slice `createLimiter`'s default key derivation
230
244
  * falls back to when neither {@link BearerState} nor {@link ClientState} is
231
245
  * present — the raw socket peer surfaced on `context.state` by the server's
232
246
  * `state` option.
233
247
  */
234
248
  export declare interface ConnectionState {
235
- readonly connection?: ConnectionInfo;
249
+ readonly connection?: Connection;
236
250
  }
237
251
 
238
252
  /**
239
- * Options for `createCookieTransport` — the signed-cookie {@link SessionTransport}.
253
+ * Configures `createCookieTransport` — the signed-cookie {@link SessionTransportInterface}.
240
254
  *
241
- * @param options - See fields below
242
255
  * @remarks
243
256
  * - `name` — the cookie name; defaults to {@link DEFAULT_SESSION_COOKIE}.
244
257
  * - `secret` — the {@link TokenSecret} the session id is signed with (`signToken`).
@@ -252,9 +265,8 @@ export declare interface CookieTransportOptions {
252
265
  }
253
266
 
254
267
  /**
255
- * Options for `createCors` — Cross-Origin Resource Sharing.
268
+ * Configures `createCors` — Cross-Origin Resource Sharing.
256
269
  *
257
- * @param options - See fields below
258
270
  * @remarks
259
271
  * - `origin` — the allowed origin(s): `'*'` (default), a single origin
260
272
  * string, or an allow-list `readonly string[]` (reflects the request
@@ -270,7 +282,8 @@ export declare interface CorsOptions {
270
282
  }
271
283
 
272
284
  /**
273
- * Bearer-token authentication battery.
285
+ * Creates the bearer-token authentication battery — reads the token from its header and
286
+ * verifies it with `verifyToken`.
274
287
  *
275
288
  * @typeParam TState - The consumer's opaque per-request state type, must carry {@link BearerState}
276
289
  * @param options - See {@link BearerOptions}
@@ -286,7 +299,7 @@ export declare interface CorsOptions {
286
299
  export declare function createBearer<TState extends BearerState>(options: BearerOptions): MiddlewareHandler<TState>;
287
300
 
288
301
  /**
289
- * The body-driving battery — eagerly awaits the cached `context.body()` so
302
+ * Creates the body-driving battery — eagerly awaits the cached `context.body()` so
290
303
  * its throws (or a malformed-JSON `undefined`) surface before the handler
291
304
  * runs, and stashes the resolved value onto {@link BodyState.body}.
292
305
  *
@@ -297,9 +310,8 @@ export declare function createBearer<TState extends BearerState>(options: Bearer
297
310
  * @remarks
298
311
  * The shipped `MiddlewareContext.body()` is a parameterless, server-owned
299
312
  * cache (`ServerOptions.limit` governs its size cap) — this battery carries
300
- * no `limit`/`decompression` options (a deliberate break from the deleted old
301
- * `createBodyParser` surface, which configured them itself). `state.body` is
302
- * stashed from the SAME awaited call the 400 check reads — `context.body()`
313
+ * no `limit`/`decompression` options. `state.body` is
314
+ * stashed from the same awaited call the 400 check reads — `context.body()`
303
315
  * is never invoked twice.
304
316
  *
305
317
  * @example
@@ -310,7 +322,7 @@ export declare function createBearer<TState extends BearerState>(options: Bearer
310
322
  export declare function createBody<TState extends BodyState = BodyState>(): MiddlewareHandler<TState>;
311
323
 
312
324
  /**
313
- * The outermost error-rendering battery — catches a downstream throw and
325
+ * Creates the outermost error-rendering battery — catches a downstream throw and
314
326
  * renders it as a `Response`.
315
327
  *
316
328
  * @typeParam TState - The consumer's opaque per-request state type
@@ -318,15 +330,26 @@ export declare function createBody<TState extends BodyState = BodyState>(): Midd
318
330
  * @returns A `MiddlewareHandler<TState>`
319
331
  * @throws {TypeError} When `options.expose` or `options.report` is malformed
320
332
  *
321
- * @example
333
+ * @example Mount a battery
322
334
  * ```ts
335
+ * import { createBoundary, createSecurity } from '@orkestrel/middleware'
336
+ * import type { IdentifierState } from '@orkestrel/middleware'
337
+ * import { compose } from '@orkestrel/server'
338
+ *
339
+ * interface State extends IdentifierState {}
340
+ *
323
341
  * const boundary = createBoundary({ expose: false })
342
+ * const security = createSecurity({ hsts: true })
343
+ *
344
+ * const handle = compose<State>([boundary, security], async (_request, context) => {
345
+ * return Response.json({ identifier: context.state.identifier })
346
+ * })
324
347
  * ```
325
348
  */
326
349
  export declare function createBoundary<TState>(options?: BoundaryOptions): MiddlewareHandler<TState>;
327
350
 
328
351
  /**
329
- * Response-body compression — negotiates and compresses a buffered response
352
+ * Creates the response-body compression battery — negotiates and compresses a buffered response
330
353
  * body over the runtime's feature-detected `CompressionStream` codings.
331
354
  *
332
355
  * @typeParam TState - The consumer's opaque per-request state type
@@ -342,11 +365,11 @@ export declare function createBoundary<TState>(options?: BoundaryOptions): Middl
342
365
  export declare function createCompression<TState>(options?: CompressionOptions): MiddlewareHandler<TState>;
343
366
 
344
367
  /**
345
- * Create a signed-cookie {@link SessionTransport} — the session id travels as
368
+ * Creates a signed-cookie {@link SessionTransportInterface} — the session id travels as
346
369
  * a `signToken`-signed cookie value.
347
370
  *
348
371
  * @param options - See {@link CookieTransportOptions}
349
- * @returns A {@link SessionTransport}
372
+ * @returns A {@link SessionTransportInterface}
350
373
  * @throws {TypeError} When `options.secret` or `options.name` is malformed
351
374
  *
352
375
  * @example
@@ -354,10 +377,11 @@ export declare function createCompression<TState>(options?: CompressionOptions):
354
377
  * const transport = createCookieTransport({ secret: 'shh' })
355
378
  * ```
356
379
  */
357
- export declare function createCookieTransport(options: CookieTransportOptions): SessionTransport;
380
+ export declare function createCookieTransport(options: CookieTransportOptions): SessionTransportInterface;
358
381
 
359
382
  /**
360
- * Cross-Origin Resource Sharing battery.
383
+ * Creates the Cross-Origin Resource Sharing battery — answers a preflight itself, and
384
+ * reflects an allow-listed origin or serves the configured wildcard.
361
385
  *
362
386
  * @typeParam TState - The consumer's opaque per-request state type
363
387
  * @param options - See {@link CorsOptions}
@@ -372,7 +396,7 @@ export declare function createCookieTransport(options: CookieTransportOptions):
372
396
  export declare function createCors<TState>(options?: CorsOptions): MiddlewareHandler<TState>;
373
397
 
374
398
  /**
375
- * Session-bound double-submit CSRF protection battery.
399
+ * Creates the session-bound double-submit CSRF protection battery.
376
400
  *
377
401
  * @typeParam TState - The consumer's opaque per-request state type, must carry {@link CSRFState}, {@link SessionState}, and {@link ConnectionState}
378
402
  * @param options - See {@link CSRFOptions}
@@ -388,33 +412,33 @@ export declare function createCors<TState>(options?: CorsOptions): MiddlewareHan
388
412
  export declare function createCSRF<TState extends CSRFState & SessionState & ConnectionState>(options: CSRFOptions): MiddlewareHandler<TState>;
389
413
 
390
414
  /**
391
- * Create a {@link DatabaseSessionStore} as a {@link SessionStoreInterface} —
415
+ * Creates a {@link DatabaseSessionStore} as a {@link SessionStoreInterface} —
392
416
  * the durable counterpart to `createMemorySessionStore`, over a caller-opened
393
417
  * `@orkestrel/database` table (declare it with {@link sessionColumns}).
394
418
  *
395
- * @typeParam S - The session data payload type
419
+ * @typeParam S - The session entity type
396
420
  * @param table - The backing `TableInterface<SessionRow>`
397
- * @param is - A {@link Guard} narrowing a restored snapshot to `S`
398
- * @param options - The idle `ttl` / absolute `lifetime` thresholds
421
+ * @param guard - A {@link Guard} narrowing a restored snapshot to `S`
422
+ * @param options - See {@link SessionLimits}
399
423
  * @returns A {@link SessionStoreInterface}
424
+ * @throws {TypeError} When `options.ttl` or `options.lifetime` is malformed
400
425
  *
401
426
  * @remarks
402
427
  * This factory only wraps `new DatabaseSessionStore(...)` — it never opens a
403
428
  * database or driver itself; the caller owns that lifecycle and passes in an
404
- * already-open table.
429
+ * already-open table. It supplies {@link createRestoredSession} as the store's
430
+ * snapshot rebuild step, which is why the store imports nothing from this
431
+ * file.
405
432
  *
406
433
  * @example
407
434
  * ```ts
408
435
  * const store = createDatabaseSessionStore(db.table('sessions'), isSession, { ttl: 60_000 })
409
436
  * ```
410
437
  */
411
- export declare function createDatabaseSessionStore<S extends SessionInterface = Session>(table: TableInterface<SessionRow>, is: Guard<S>, options?: {
412
- readonly ttl?: number;
413
- readonly lifetime?: number;
414
- }): SessionStoreInterface<S>;
438
+ export declare function createDatabaseSessionStore<S extends SessionInterface = Session>(table: TableInterface<SessionRow>, guard: Guard<S>, options?: SessionLimits): SessionStoreInterface<S>;
415
439
 
416
440
  /**
417
- * The application-level per-request deadline battery.
441
+ * Creates the application-level per-request deadline battery.
418
442
  *
419
443
  * @typeParam TState - The consumer's opaque per-request state type
420
444
  * @param options - See {@link DeadlineOptions}
@@ -422,9 +446,9 @@ export declare function createDatabaseSessionStore<S extends SessionInterface =
422
446
  * @throws {TypeError} When `options.ms` or `options.status` is malformed
423
447
  *
424
448
  * @remarks
425
- * MUST sit OUTSIDE `createBody` in the chain — it reconstructs the inbound
449
+ * Mount this battery outside `createBody` in the chain — it reconstructs the inbound
426
450
  * `Request` (to link its `signal` to the deadline `signal`), which throws if
427
- * the body was already consumed upstream (e.g. by `createBody`'s cached read).
451
+ * the body was already consumed upstream (for example by `createBody`'s cached read).
428
452
  *
429
453
  * @example
430
454
  * ```ts
@@ -434,7 +458,7 @@ export declare function createDatabaseSessionStore<S extends SessionInterface =
434
458
  export declare function createDeadline<TState>(options: DeadlineOptions): MiddlewareHandler<TState>;
435
459
 
436
460
  /**
437
- * Dynamic response `ETag` + conditional GET battery.
461
+ * Creates the dynamic response `ETag` + conditional GET battery (RFC 7232).
438
462
  *
439
463
  * @typeParam TState - The consumer's opaque per-request state type
440
464
  * @param options - See {@link ETagOptions}
@@ -449,7 +473,8 @@ export declare function createDeadline<TState>(options: DeadlineOptions): Middle
449
473
  export declare function createETag<TState>(options?: ETagOptions): MiddlewareHandler<TState>;
450
474
 
451
475
  /**
452
- * The trusted-proxy client-IP resolver battery.
476
+ * Creates the trusted-proxy client-IP resolver battery — walks `X-Forwarded-For` past
477
+ * the hops its options declare trusted.
453
478
  *
454
479
  * @typeParam TState - The consumer's opaque per-request state type, must carry {@link ClientState} and {@link ConnectionState}
455
480
  * @param options - See {@link ForwardedOptions}
@@ -464,11 +489,11 @@ export declare function createETag<TState>(options?: ETagOptions): MiddlewareHan
464
489
  export declare function createForwarded<TState extends ClientState & ConnectionState>(options: ForwardedOptions): MiddlewareHandler<TState>;
465
490
 
466
491
  /**
467
- * Create a bare-header {@link SessionTransport} — the session id travels
492
+ * Creates a bare-header {@link SessionTransportInterface} — the session id travels
468
493
  * verbatim in a request/response header.
469
494
  *
470
495
  * @param options - See {@link HeaderTransportOptions}
471
- * @returns A {@link SessionTransport}
496
+ * @returns A {@link SessionTransportInterface}
472
497
  * @throws {TypeError} When `options.header` is malformed
473
498
  *
474
499
  * @example
@@ -476,10 +501,11 @@ export declare function createForwarded<TState extends ClientState & ConnectionS
476
501
  * const transport = createHeaderTransport()
477
502
  * ```
478
503
  */
479
- export declare function createHeaderTransport(options?: HeaderTransportOptions): SessionTransport;
504
+ export declare function createHeaderTransport(options?: HeaderTransportOptions): SessionTransportInterface;
480
505
 
481
506
  /**
482
- * Fixed-window rate-limiting battery.
507
+ * Creates the fixed-window rate-limiting battery — checks a key's budget before
508
+ * consuming it, so one window admits exactly `max` requests.
483
509
  *
484
510
  * @typeParam TState - The consumer's opaque per-request state type, must carry {@link BearerState}, {@link ClientState}, and {@link ConnectionState}
485
511
  * @param options - See {@link LimiterOptions}
@@ -494,28 +520,43 @@ export declare function createHeaderTransport(options?: HeaderTransportOptions):
494
520
  export declare function createLimiter<TState extends BearerState & ClientState & ConnectionState>(options: LimiterOptions<TState>): MiddlewareHandler<TState>;
495
521
 
496
522
  /**
497
- * Create the default in-process {@link SessionStoreInterface} — a `Map`-backed
523
+ * Creates the default in-process {@link SessionStoreInterface} — a `Map`-backed
498
524
  * store enforcing an idle timeout and an absolute lifetime.
499
525
  *
500
- * @typeParam S - The session data payload type
526
+ * @typeParam S - The session entity type
501
527
  * @param options - See {@link MemorySessionStoreOptions}
502
528
  * @returns A {@link SessionStoreInterface}
503
529
  * @throws {TypeError} When `options.ttl` or `options.lifetime` is malformed
504
530
  *
505
531
  * @remarks
506
- * The {@link Session} entity is the `create` option's default value factory
507
- * for `createSession` and deliberately ships WITHOUT its own `create*`
508
- * factory — the name `createSession` belongs to the battery, not this class.
532
+ * The store holds whatever {@link SessionInterface} entity `createSession`'s
533
+ * `create` option produced, keyed by that entity's own `id`.
509
534
  *
510
535
  * @example
511
536
  * ```ts
512
537
  * const store = createMemorySessionStore({ ttl: 60_000 })
513
538
  * ```
514
539
  */
515
- export declare function createMemorySessionStore<S>(options?: MemorySessionStoreOptions): SessionStoreInterface<S>;
540
+ export declare function createMemorySessionStore<S extends SessionInterface>(options?: MemorySessionStoreOptions): SessionStoreInterface<S>;
516
541
 
517
542
  /**
518
- * Security-headers + request-identifier battery.
543
+ * Rebuilds a {@link Session} from an untrusted snapshot value — the inverse of
544
+ * `snapshotSession` and a durable store's `get` deserialization step.
545
+ *
546
+ * @param value - The candidate snapshot, of unknown shape
547
+ * @returns A rebuilt {@link Session}, or `undefined` when `value` is malformed
548
+ *
549
+ * @example
550
+ * ```ts
551
+ * createRestoredSession({ id: 'abc', state: { userId: 'u_1' } }) // Session { id: 'abc' }
552
+ * createRestoredSession({ id: 1 }) // undefined
553
+ * ```
554
+ */
555
+ export declare function createRestoredSession(value: unknown): Session | undefined;
556
+
557
+ /**
558
+ * Creates the security-headers + request-identifier battery — sets each documented
559
+ * header default, and mints or echoes a request identifier.
519
560
  *
520
561
  * @typeParam TState - The consumer's opaque per-request state type, must carry {@link IdentifierState}
521
562
  * @param options - See {@link SecurityOptions}
@@ -530,7 +571,7 @@ export declare function createMemorySessionStore<S>(options?: MemorySessionStore
530
571
  export declare function createSecurity<TState extends IdentifierState>(options?: SecurityOptions): MiddlewareHandler<TState>;
531
572
 
532
573
  /**
533
- * The generic session battery — resolves, mints, and persists a session
574
+ * Creates the generic session battery — resolves, mints, and persists a session
534
575
  * across the request, with a mid-handler `regenerate`/`destroy` control handle.
535
576
  *
536
577
  * @typeParam S - The session entity type the store persists (must implement {@link SessionInterface})
@@ -538,7 +579,7 @@ export declare function createSecurity<TState extends IdentifierState>(options?:
538
579
  * @param options - See {@link SessionOptions}
539
580
  * @returns A `MiddlewareHandler<TState>`
540
581
  * @throws {TypeError} When any option is malformed
541
- * @throws {HTTPError} `404` when `require` is set and no session resolves or mints
582
+ * @throws {HTTPError} `404` when `required` is set and no session resolves or mints
542
583
  *
543
584
  * @example
544
585
  * ```ts
@@ -548,7 +589,7 @@ export declare function createSecurity<TState extends IdentifierState>(options?:
548
589
  export declare function createSession<S extends SessionInterface = SessionInterface, TState extends SessionState & ConnectionState = SessionState & ConnectionState>(options: SessionOptions<S, TState>): MiddlewareHandler<TState>;
549
590
 
550
591
  /**
551
- * The access-log/timing seam — records one {@link TelemetryEntry} per request
592
+ * Creates the access-log/timing seam — records one {@link TelemetryEntry} per request
552
593
  * after the response settles.
553
594
  *
554
595
  * @typeParam TState - The consumer's opaque per-request state type
@@ -564,9 +605,8 @@ export declare function createSession<S extends SessionInterface = SessionInterf
564
605
  export declare function createTelemetry<TState>(options: TelemetryOptions): MiddlewareHandler<TState>;
565
606
 
566
607
  /**
567
- * Options for `createCSRF` — session-bound double-submit CSRF protection.
608
+ * Configures `createCSRF` — session-bound double-submit CSRF protection.
568
609
  *
569
- * @param options - See fields below
570
610
  * @remarks
571
611
  * - `secret` — the {@link TokenSecret} the CSRF token is signed with.
572
612
  * - `cookie` — the signed-cookie name; defaults to {@link DEFAULT_CSRF_COOKIE}.
@@ -587,7 +627,7 @@ export declare interface CSRFOptions {
587
627
  }
588
628
 
589
629
  /**
590
- * The CSRF state slice `createCSRF` stashes — the raw token a safe-method
630
+ * Describes the CSRF state slice `createCSRF` stashes — the raw token a safe-method
591
631
  * response exposes for a subsequent mutating request to submit back.
592
632
  */
593
633
  export declare interface CSRFState {
@@ -595,26 +635,28 @@ export declare interface CSRFState {
595
635
  }
596
636
 
597
637
  /**
598
- * A durable {@link SessionStoreInterface} over an `@orkestrel/database`
638
+ * Implements a durable {@link SessionStoreInterface} over an `@orkestrel/database`
599
639
  * table — the same idle-timeout + absolute-lifetime contract as
600
640
  * {@link MemorySessionStore}, backed by a caller-supplied `TableInterface`
601
641
  * instead of an in-process `Map`.
602
642
  *
603
- * @typeParam S - The session data payload type
643
+ * @typeParam S - The stored session entity type
604
644
  *
605
645
  * @remarks
606
646
  * `get` reads the row, evicts (removes the row) once `sessionExpired`
607
- * reports either threshold elapsed, then rebuilds the session via
608
- * {@link restoreSession} — a malformed snapshot or one that fails the
609
- * caller's `is` guard resolves `undefined` rather than throwing. A live read
610
- * touches `lastSeen`. `set` preserves an existing row's `createdAt` across a
647
+ * reports either threshold elapsed, then rebuilds the session through the
648
+ * `restore` step it was constructed with — a malformed snapshot or one that
649
+ * fails the caller's guard resolves `undefined` rather than throwing.
650
+ * `createDatabaseSessionStore` supplies `createRestoredSession` as that step,
651
+ * so a caller reaching the factory never states it. A live read
652
+ * touches `seen`. `set` preserves an existing row's `created` across a
611
653
  * re-`set` of the same id (stamped once at the first `set`), mirroring
612
654
  * {@link MemorySessionStore}. `delete` of an absent id is a no-op (the
613
655
  * table's `remove` contract).
614
656
  *
615
- * A malformed-snapshot or failed-guard `undefined` LEAVES the row in place —
657
+ * A malformed-snapshot or failed-guard `undefined` leaves the row in place —
616
658
  * unlike the expired path, which removes it. This is deliberate: a
617
- * caller-contextual `is` guard may reject a session that is still perfectly
659
+ * caller-contextual guard may reject a session that is still perfectly
618
660
  * valid for another flow reading the same table (a differently-shaped `S`,
619
661
  * a stricter guard mid-rollout), so `get` never destroys data on a guard
620
662
  * miss. A row that no caller's guard ever accepts again self-heals once its
@@ -622,28 +664,26 @@ export declare interface CSRFState {
622
664
  *
623
665
  * @example
624
666
  * ```ts
625
- * const store = new DatabaseSessionStore(table, isSession, { ttl: 60_000 })
626
- * await store.set('abc', new Session('abc'), Date.now())
667
+ * const store = new DatabaseSessionStore(table, isSession, createRestoredSession, {
668
+ * ttl: 60_000,
669
+ * })
670
+ * await store.set(new Session('abc'), Date.now())
627
671
  * ```
628
672
  */
629
673
  export declare class DatabaseSessionStore<S extends SessionInterface = Session> implements SessionStoreInterface<S> {
630
674
  #private;
631
- constructor(table: TableInterface<SessionRow>, is: Guard<S>, options?: {
632
- readonly ttl?: number;
633
- readonly lifetime?: number;
634
- });
675
+ constructor(table: TableInterface<SessionRow>, guard: Guard<S>, restore: SessionRestoreFunction, options?: SessionLimits);
635
676
  get(id: string, now: number): Promise<S | undefined>;
636
- set(id: string, session: S, now: number): Promise<void>;
677
+ set(session: S, now: number): Promise<void>;
637
678
  delete(id: string): Promise<void>;
638
679
  }
639
680
 
640
681
  /**
641
- * Options for `createDeadline` — the application-level per-request deadline.
682
+ * Configures `createDeadline` — the application-level per-request deadline.
642
683
  *
643
- * @param options - See fields below
644
684
  * @remarks
645
- * - `ms` — the deadline in milliseconds, armed via `@orkestrel/timeout` and
646
- * linked to the request's `signal` via `@orkestrel/abort`'s `linkSignal`.
685
+ * - `ms` — the deadline in milliseconds, armed through `@orkestrel/timeout` and
686
+ * linked to the request's `signal` through `@orkestrel/abort`'s `linkSignal`.
647
687
  * - `status` — the response status returned when the deadline fires before
648
688
  * the downstream chain settles; defaults to {@link DEFAULT_DEADLINE_STATUS}.
649
689
  */
@@ -652,22 +692,22 @@ export declare interface DeadlineOptions {
652
692
  readonly status?: number;
653
693
  }
654
694
 
655
- /** Default header `createBearer` reads the token from. */
695
+ /** Names `'authorization'`, the default header `createBearer` reads the token from. */
656
696
  export declare const DEFAULT_BEARER_HEADER = "authorization";
657
697
 
658
- /** Default scheme prefix `createBearer` strips before verification. */
698
+ /** Names `'Bearer'`, the default scheme prefix `createBearer` strips before verification. */
659
699
  export declare const DEFAULT_BEARER_SCHEME = "Bearer";
660
700
 
661
- /** Default `Origin-Agent-Cluster` value `createSecurity` sets. */
701
+ /** Holds `'?1'`, the default `Origin-Agent-Cluster` value `createSecurity` sets. */
662
702
  export declare const DEFAULT_CLUSTER = "?1";
663
703
 
664
- /** Value `createSecurity` sets for `Cross-Origin-Embedder-Policy` when `coep: true`. */
704
+ /** Holds `'require-corp'`, the value `createSecurity` sets for `Cross-Origin-Embedder-Policy` when `coep: true`. */
665
705
  export declare const DEFAULT_COEP = "require-corp";
666
706
 
667
707
  /**
668
- * Default content-codings `createCompression` offers, in preference order —
669
- * intersected at construction with what the runtime's `CompressionStream`
670
- * actually supports.
708
+ * Lists `['gzip', 'deflate']`, the default content-codings `createCompression` offers in
709
+ * preference order — intersected at construction with what the runtime's
710
+ * `CompressionStream` actually supports.
671
711
  *
672
712
  * @remarks
673
713
  * The shipped `@orkestrel/server` peer's {@link Encoding} union is
@@ -678,76 +718,76 @@ export declare const DEFAULT_COEP = "require-corp";
678
718
  */
679
719
  export declare const DEFAULT_COMPRESSION_ENCODINGS: readonly Encoding[];
680
720
 
681
- /** Default minimum buffered body size (bytes) `createCompression` will compress. */
721
+ /** Holds `1024`, the default minimum buffered body size in bytes `createCompression` will compress. */
682
722
  export declare const DEFAULT_COMPRESSION_THRESHOLD = 1024;
683
723
 
684
- /** Default `Cross-Origin-Opener-Policy` value `createSecurity` sets. */
724
+ /** Holds `'same-origin'`, the default `Cross-Origin-Opener-Policy` value `createSecurity` sets. */
685
725
  export declare const DEFAULT_COOP = "same-origin";
686
726
 
687
- /** Default `Cross-Origin-Resource-Policy` value `createSecurity` sets. */
727
+ /** Holds `'same-origin'`, the default `Cross-Origin-Resource-Policy` value `createSecurity` sets. */
688
728
  export declare const DEFAULT_CORP = "same-origin";
689
729
 
690
- /** Default headers `createCors` advertises on a preflight response. */
730
+ /** Lists the default headers `createCors` advertises on a preflight response. */
691
731
  export declare const DEFAULT_CORS_HEADERS: readonly string[];
692
732
 
693
- /** Default methods `createCors` advertises on a preflight response. */
733
+ /** Lists the default methods `createCors` advertises on a preflight response. */
694
734
  export declare const DEFAULT_CORS_METHODS: readonly string[];
695
735
 
696
736
  /**
697
- * Default `Content-Security-Policy` value `createSecurity` sets a custom
698
- * `csp` option REPLACES this wholesale, never merges.
737
+ * Holds `"default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'self'; form-action 'self'"`,
738
+ * the default `Content-Security-Policy` value `createSecurity` sets a custom
739
+ * `csp` option replaces this wholesale, never merges.
699
740
  */
700
741
  export declare const DEFAULT_CSP = "default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'self'; form-action 'self'";
701
742
 
702
- /** Default signed-cookie name `createCSRF` writes the CSRF token under. */
743
+ /** Names `'csrf'`, the default signed cookie `createCSRF` writes the CSRF token under. */
703
744
  export declare const DEFAULT_CSRF_COOKIE = "csrf";
704
745
 
705
- /** Default body field `createCSRF` falls back to reading a mutating request's submitted token from. */
746
+ /** Names `'_csrf'`, the default body field `createCSRF` falls back to reading a mutating request's submitted token from. */
706
747
  export declare const DEFAULT_CSRF_FIELD = "_csrf";
707
748
 
708
- /** Default header `createCSRF` reads a mutating request's submitted token from. */
749
+ /** Names `'x-csrf-token'`, the default header `createCSRF` reads a mutating request's submitted token from. */
709
750
  export declare const DEFAULT_CSRF_HEADER = "x-csrf-token";
710
751
 
711
- /** Default methods `createCSRF` treats as safe (mint instead of verify). */
752
+ /** Lists `['GET', 'HEAD', 'OPTIONS']`, the default methods `createCSRF` treats as safe (mint instead of verify). */
712
753
  export declare const DEFAULT_CSRF_SAFE_METHODS: readonly string[];
713
754
 
714
- /** Default response status `createDeadline` returns when its deadline fires first. */
755
+ /** Holds `503`, the default response status `createDeadline` returns when its deadline fires first. */
715
756
  export declare const DEFAULT_DEADLINE_STATUS = 503;
716
757
 
717
- /** Default `X-Frame-Options` value `createSecurity` sets. */
758
+ /** Holds `'DENY'`, the default `X-Frame-Options` value `createSecurity` sets. */
718
759
  export declare const DEFAULT_FRAME_OPTIONS = "DENY";
719
760
 
720
- /** Value `createSecurity` sets for `Strict-Transport-Security` when `hsts: true`. */
761
+ /** Holds `'max-age=31536000; includeSubDomains'`, the value `createSecurity` sets for `Strict-Transport-Security` when `hsts: true`. */
721
762
  export declare const DEFAULT_HSTS = "max-age=31536000; includeSubDomains";
722
763
 
723
- /** Default header `createSecurity` mints/echoes a request identifier into. */
764
+ /** Names `'x-request-id'`, the default header `createSecurity` mints or echoes a request identifier into. */
724
765
  export declare const DEFAULT_IDENTIFIER_HEADER = "x-request-id";
725
766
 
726
- /** Default maximum number of distinct rate-limit keys `createLimiter` tracks before LRU eviction. */
767
+ /** Holds `10_000`, the default maximum number of distinct rate-limit keys `createLimiter` tracks before LRU eviction. */
727
768
  export declare const DEFAULT_LIMITER_CAPACITY = 10000;
728
769
 
729
- /** Default 429 body message `createLimiter` sends when a key is over budget. */
770
+ /** Holds `'rate limit exceeded'`, the default 429 body message `createLimiter` sends when a key is over budget. */
730
771
  export declare const DEFAULT_LIMITER_MESSAGE = "rate limit exceeded";
731
772
 
732
- /** Default `Permissions-Policy` value `createSecurity` sets. */
773
+ /** Holds `'camera=(), microphone=(), geolocation=()'`, the default `Permissions-Policy` value `createSecurity` sets. */
733
774
  export declare const DEFAULT_PERMISSIONS_POLICY = "camera=(), microphone=(), geolocation=()";
734
775
 
735
- /** Default `Referrer-Policy` value `createSecurity` sets. */
776
+ /** Holds `'strict-origin-when-cross-origin'`, the default `Referrer-Policy` value `createSecurity` sets. */
736
777
  export declare const DEFAULT_REFERRER_POLICY = "strict-origin-when-cross-origin";
737
778
 
738
- /** Default maximum number of distinct session ids `createMemorySessionStore` tracks before LRU (by last write) eviction. */
779
+ /** Holds `10_000`, the default maximum number of distinct session ids `createMemorySessionStore` tracks before LRU (by last write) eviction. */
739
780
  export declare const DEFAULT_SESSION_CAPACITY = 10000;
740
781
 
741
- /** Default cookie name `createCookieTransport` writes the signed session id under. */
782
+ /** Names `'session'`, the default cookie `createCookieTransport` writes the signed session id under. */
742
783
  export declare const DEFAULT_SESSION_COOKIE = "session";
743
784
 
744
- /** Default header `createHeaderTransport` carries the session id in. */
785
+ /** Names `'session-id'`, the default header `createHeaderTransport` carries the session id in. */
745
786
  export declare const DEFAULT_SESSION_HEADER = "session-id";
746
787
 
747
788
  /**
748
- * Feature-detect which of `candidates` the runtime's `CompressionStream`
749
- * actually supports — `createCompression`'s construction-time intersection
750
- * (ruling J).
789
+ * Feature-detects which of `candidates` the runtime's `CompressionStream`
790
+ * actually supports — `createCompression`'s construction-time intersection.
751
791
  *
752
792
  * @remarks
753
793
  * Probes each candidate with `new CompressionStream(candidate)` inside a
@@ -766,7 +806,7 @@ export declare const DEFAULT_SESSION_HEADER = "session-id";
766
806
  export declare function detectEncodings(candidates: readonly Encoding[]): readonly Encoding[];
767
807
 
768
808
  /**
769
- * Constant-time string equality — `createCSRF`'s double-submit token
809
+ * Compares two strings in constant time — `createCSRF`'s double-submit token
770
810
  * comparison, avoiding a timing oracle on the submitted-vs-cookie match.
771
811
  *
772
812
  * @remarks
@@ -778,7 +818,7 @@ export declare function detectEncodings(candidates: readonly Encoding[]): readon
778
818
  *
779
819
  * @param a - The first string
780
820
  * @param b - The second string
781
- * @returns `true` when `a` and `b` are exactly equal
821
+ * @returns True if `a` and `b` are exactly equal; false otherwise
782
822
  *
783
823
  * @example
784
824
  * ```ts
@@ -789,9 +829,8 @@ export declare function detectEncodings(candidates: readonly Encoding[]): readon
789
829
  export declare function equalsConstantTime(a: string, b: string): boolean;
790
830
 
791
831
  /**
792
- * Options for `createETag` — dynamic response ETag + conditional GET.
832
+ * Configures `createETag` — dynamic response ETag + conditional GET.
793
833
  *
794
- * @param options - See fields below
795
834
  * @remarks
796
835
  * - `weak` — mint a weak `W/"…"` ETag (default `true`) or a strong `"…"` one
797
836
  * (`false`).
@@ -801,8 +840,8 @@ export declare interface ETagOptions {
801
840
  }
802
841
 
803
842
  /**
804
- * Scope a battery to run everywhere EXCEPT a set of exact pathnamesthere
805
- * it steps aside via `next()`.
843
+ * Scopes a battery to every pathname outside a set of exact oneson that set it
844
+ * steps aside through `next()`.
806
845
  *
807
846
  * @typeParam TState - The consumer's opaque per-request state type
808
847
  * @param paths - One pathname, or a set of pathnames, matched exactly against `context.url.pathname`
@@ -817,12 +856,11 @@ export declare interface ETagOptions {
817
856
  export declare function except<TState>(paths: string | readonly string[], handler: MiddlewareHandler<TState>): MiddlewareHandler<TState>;
818
857
 
819
858
  /**
820
- * Options for `createForwarded` — the trusted-proxy client-IP resolver.
859
+ * Configures `createForwarded` — the trusted-proxy client-IP resolver.
821
860
  *
822
- * @param options - See fields below
823
861
  * @remarks
824
- * Construction requires EXACTLY ONE of the two forms (a `TypeError` guards
825
- * both-set and neither-set):
862
+ * Construction requires either `proxies` or `trusted`, never both and never
863
+ * neither (a `TypeError` guards each):
826
864
  * - `proxies` — trust exactly this many hops from the right of
827
865
  * `X-Forwarded-For` / `Forwarded`.
828
866
  * - `trusted` — trust every hop matching one of these CIDR entries.
@@ -834,9 +872,8 @@ export declare type ForwardedOptions = {
834
872
  };
835
873
 
836
874
  /**
837
- * Options for `createHeaderTransport` — the bare-header {@link SessionTransport}.
875
+ * Configures `createHeaderTransport` — the bare-header {@link SessionTransportInterface}.
838
876
  *
839
- * @param options - See fields below
840
877
  * @remarks
841
878
  * - `header` — the header carrying the session id; defaults to
842
879
  * {@link DEFAULT_SESSION_HEADER}.
@@ -846,7 +883,7 @@ export declare interface HeaderTransportOptions {
846
883
  }
847
884
 
848
885
  /**
849
- * The request-identifier state slice `createSecurity` stashes when its
886
+ * Describes the request-identifier state slice `createSecurity` stashes when its
850
887
  * `identifier` option is enabled.
851
888
  */
852
889
  export declare interface IdentifierState {
@@ -854,21 +891,22 @@ export declare interface IdentifierState {
854
891
  }
855
892
 
856
893
  /**
857
- * Whether a response is eligible for the compression/ETag buffering pipeline
858
- * (ruling J) — the shared cheap-skip predicate both batteries apply before
859
- * ever touching `response.arrayBuffer()`.
894
+ * Checks whether a response must skip the compression and ETag buffering pipeline
895
+ * — the shared cheap-skip predicate both batteries apply before ever touching
896
+ * `response.arrayBuffer()`, true for a `HEAD` request, a `204`/`304` or
897
+ * otherwise bodyless response, an `event-stream` response, and a response
898
+ * already carrying the header the caller is about to set.
860
899
  *
861
900
  * @remarks
862
- * Skips a `HEAD` request, a `204`/`304` or otherwise bodyless response, an
863
- * `event-stream` response (SSE buffering would hang the connection), and a
864
- * response that already carries the header the caller is about to set
865
- * (`skipHeader`, e.g. `Content-Encoding` for compression, `ETag` for the
866
- * ETag battery).
901
+ * Buffering an `event-stream` response would hang the connection, so SSE skips
902
+ * whatever its size. `skipHeader` is the header whose presence already answers
903
+ * the question `Content-Encoding` for compression, `ETag` for the ETag
904
+ * battery.
867
905
  *
868
906
  * @param method - The request's HTTP method
869
907
  * @param response - The candidate response
870
908
  * @param skipHeader - The response header whose presence means "already handled"
871
- * @returns `true` when the response should be left untouched
909
+ * @returns True if the response must be left untouched; false otherwise
872
910
  *
873
911
  * @example
874
912
  * ```ts
@@ -878,11 +916,11 @@ export declare interface IdentifierState {
878
916
  export declare function isBufferingIneligible(method: string, response: Response, skipHeader: string): boolean;
879
917
 
880
918
  /**
881
- * Whether a negotiated `Accept-Encoding` outcome is worth acting on —
882
- * `createCompression`'s negotiation-eligibility half of ruling J's skip list.
919
+ * Checks whether a negotiated `Accept-Encoding` outcome is worth acting on —
920
+ * `createCompression`'s negotiation-eligibility half of the skip list.
883
921
  *
884
922
  * @param encoding - The negotiated coding, or `undefined` when negotiation failed
885
- * @returns `true` when `encoding` names an actionable, non-`identity` coding
923
+ * @returns True if `encoding` names an actionable, non-`identity` coding; false otherwise
886
924
  *
887
925
  * @example
888
926
  * ```ts
@@ -893,12 +931,12 @@ export declare function isBufferingIneligible(method: string, response: Response
893
931
  export declare function isCompressionNegotiated(encoding: Encoding | undefined): encoding is Exclude<Encoding, 'identity'>;
894
932
 
895
933
  /**
896
- * Determine whether a value implements {@link MultipartBody} — a total
897
- * structural guard (§14): `files` keyed by field name to arrays of
934
+ * Determines whether a value implements {@link MultipartBody} — a total
935
+ * structural guard: `files` keyed by field name to arrays of
898
936
  * {@link MultipartFile}, and a `fields` string record.
899
937
  *
900
938
  * @param value - The candidate value
901
- * @returns `true` when `value` is shaped like a {@link MultipartBody}
939
+ * @returns True if `value` is shaped like a {@link MultipartBody}; false otherwise
902
940
  *
903
941
  * @example
904
942
  * ```ts
@@ -908,21 +946,34 @@ export declare function isCompressionNegotiated(encoding: Encoding | undefined):
908
946
  export declare function isMultipartBody(value: unknown): value is MultipartBody;
909
947
 
910
948
  /**
911
- * Determine whether a value is one staged {@link MultipartFile} record — a
912
- * total structural guard (§14) checking every required field's shape.
949
+ * Determines whether a value is one staged {@link MultipartFile} record — a
950
+ * total structural guard checking every required field's shape.
913
951
  *
914
952
  * @param value - The candidate value
915
- * @returns `true` when `value` is shaped like a {@link MultipartFile}
953
+ * @returns True if `value` is shaped like a {@link MultipartFile}; false otherwise
954
+ *
955
+ * @example
956
+ * ```ts
957
+ * isMultipartFile({
958
+ * field: 'avatar',
959
+ * name: 'a.png',
960
+ * size: 3,
961
+ * mime: 'image/png',
962
+ * validated: true,
963
+ * status: 'staged',
964
+ * path: '/tmp/a',
965
+ * }) // true
966
+ * ```
916
967
  */
917
968
  export declare function isMultipartFile(value: unknown): value is MultipartFile;
918
969
 
919
970
  /**
920
- * Determine whether a request is a CORS PREFLIGHT — an `OPTIONS` request
971
+ * Determines whether a request is a CORS preflight — an `OPTIONS` request
921
972
  * carrying an `Access-Control-Request-Method` header.
922
973
  *
923
974
  * @param method - The request's HTTP method
924
975
  * @param headers - The request's `Headers`
925
- * @returns `true` when the request is a CORS preflight `createCors` must answer
976
+ * @returns True if the request is a CORS preflight `createCors` must answer; false otherwise
926
977
  *
927
978
  * @example
928
979
  * ```ts
@@ -932,29 +983,29 @@ export declare function isMultipartFile(value: unknown): value is MultipartFile;
932
983
  export declare function isPreflight(method: string, headers: Headers): boolean;
933
984
 
934
985
  /**
935
- * Determine whether a value implements {@link SessionInterface} — a total
936
- * structural guard (§14): an `id` string plus a `data` `Map`. Prototype-agnostic
937
- * — accepts a plain object, a null-prototype object, AND a class instance
938
- * (a real `Session`), since a restored/stored session is routinely a class
939
- * instance, not a literal.
986
+ * Determines whether a value implements {@link SessionInterface} — a total
987
+ * structural guard: an `id` string, a `state` `Map`, and the `set`, `delete`,
988
+ * and `clear` mutators. Prototype-agnostic — accepts a plain object, a
989
+ * null-prototype object, and a class instance (a real `Session`), because a
990
+ * restored or stored session is routinely a class instance rather than a literal.
940
991
  *
941
992
  * @param value - The candidate value
942
- * @returns `true` when `value` is shaped like a {@link SessionInterface}
993
+ * @returns True if `value` is shaped like a {@link SessionInterface}; false otherwise
943
994
  *
944
995
  * @example
945
996
  * ```ts
946
- * isSession({ id: 'a', data: new Map() }) // true
947
997
  * isSession(new Session('a')) // true
998
+ * isSession({ id: 'a', state: new Map() }) // false — the mutators are missing
948
999
  * ```
949
1000
  */
950
1001
  export declare function isSession(value: unknown): value is SessionInterface;
951
1002
 
952
1003
  /**
953
- * Determine whether a value implements {@link SessionControlInterface} — a
954
- * total structural guard (§14): callable `regenerate` and `destroy`.
1004
+ * Determines whether a value implements {@link SessionControlInterface} — a
1005
+ * total structural guard: callable `regenerate` and `destroy`.
955
1006
  *
956
1007
  * @param value - The candidate value
957
- * @returns `true` when `value` is shaped like a {@link SessionControlInterface}
1008
+ * @returns True if `value` is shaped like a {@link SessionControlInterface}; false otherwise
958
1009
  *
959
1010
  * @example
960
1011
  * ```ts
@@ -964,15 +1015,14 @@ export declare function isSession(value: unknown): value is SessionInterface;
964
1015
  export declare function isSessionControl(value: unknown): value is SessionControlInterface;
965
1016
 
966
1017
  /**
967
- * Options for `createLimiter` — fixed-window rate limiting.
1018
+ * Configures `createLimiter` — fixed-window rate limiting.
968
1019
  *
969
1020
  * @typeParam TState - The consumer's opaque per-request state type `key` reads
970
- * @param options - See fields below
971
1021
  * @remarks
972
1022
  * - `max` — the number of requests admitted per key per `window`.
973
1023
  * - `window` — the window length in milliseconds.
974
1024
  * - `capacity` — the maximum number of distinct keys tracked before the
975
- * least-recently-used key is evicted (true LRU — every access, not just
1025
+ * least-recently-used key is evicted (true LRU — every access, not only
976
1026
  * insertion, refreshes recency); defaults to {@link DEFAULT_LIMITER_CAPACITY}.
977
1027
  * - `key` — derives the bucket key from the request; defaults to the
978
1028
  * bearer-token-then-client-IP idiom (see the battery's guide).
@@ -997,7 +1047,7 @@ export declare interface LimiterOptions<TState = unknown> {
997
1047
  }
998
1048
 
999
1049
  /**
1000
- * Whether a candidate address is a bare (non-CIDR) trusted-hop match — an
1050
+ * Checks whether a candidate address is a bare (non-CIDR) trusted-hop match — an
1001
1051
  * exact string match, or a simple prefix-CIDR match for IPv4 (`/8`–`/32`).
1002
1052
  * An IPv6 entry matches by exact string only — there is no IPv6 CIDR
1003
1053
  * support.
@@ -1009,14 +1059,14 @@ export declare interface LimiterOptions<TState = unknown> {
1009
1059
  * never claims full CIDR generality beyond IPv4.
1010
1060
  *
1011
1061
  * @remarks
1012
- * An IPv6 `trusted` roster entry is compared as an EXACT string — it must be
1062
+ * An IPv6 `trusted` roster entry is compared as an exact string — it must be
1013
1063
  * supplied in canonical form (no zero-compression normalization, no case
1014
1064
  * folding) by the caller; this function performs no IPv6 normalization of
1015
1065
  * its own.
1016
1066
  *
1017
1067
  * @param address - The candidate hop address
1018
1068
  * @param entry - One `trusted` roster entry — an exact address or an IPv4 CIDR
1019
- * @returns `true` when `address` is covered by `entry`
1069
+ * @returns True if `address` is covered by `entry`; false otherwise
1020
1070
  *
1021
1071
  * @example
1022
1072
  * ```ts
@@ -1027,18 +1077,18 @@ export declare interface LimiterOptions<TState = unknown> {
1027
1077
  export declare function matchesTrustedEntry(address: string, entry: string): boolean;
1028
1078
 
1029
1079
  /**
1030
- * The default in-process {@link SessionStoreInterface} — a `Map`-backed store
1080
+ * Implements the default in-process {@link SessionStoreInterface} — a `Map`-backed store
1031
1081
  * enforcing both an idle timeout and an absolute lifetime, with lazy
1032
1082
  * (read-time) eviction, a bounded capacity, and no background timers.
1033
1083
  *
1034
- * @typeParam S - The session data payload type
1084
+ * @typeParam S - The stored session entity type
1035
1085
  *
1036
1086
  * @remarks
1037
- * `get` evicts a session whose idle time (`now - lastSeen >= ttl`) or
1038
- * absolute lifetime (`now - createdAt >= lifetime`) has elapsed — the
1039
- * lifetime check fires EVEN IF the session was continuously touched, since
1040
- * `createdAt` is stamped once at the first `set` and preserved across every
1041
- * later re-`set` of the same id. A live read touches `lastSeen`. `delete` of
1087
+ * `get` evicts a session whose idle time (`now - seen >= ttl`) or
1088
+ * absolute lifetime (`now - created >= lifetime`) has elapsed — the
1089
+ * lifetime check fires even if the session was continuously touched, because
1090
+ * `created` is stamped once at the first `set` and preserved across every
1091
+ * later re-`set` of the same id. A live read touches `seen`. `delete` of
1042
1092
  * an absent id is a no-op.
1043
1093
  *
1044
1094
  * Capacity is enforced as least-recently-used **by last write**: `set`
@@ -1053,21 +1103,20 @@ export declare function matchesTrustedEntry(address: string, entry: string): boo
1053
1103
  * @example
1054
1104
  * ```ts
1055
1105
  * const store = new MemorySessionStore({ ttl: 60_000, lifetime: 3_600_000 })
1056
- * await store.set('abc', { userId: 'u_1' }, Date.now())
1106
+ * await store.set(new Session('abc'), Date.now())
1057
1107
  * ```
1058
1108
  */
1059
- export declare class MemorySessionStore<S> implements SessionStoreInterface<S> {
1109
+ export declare class MemorySessionStore<S extends SessionInterface> implements SessionStoreInterface<S> {
1060
1110
  #private;
1061
1111
  constructor(options?: MemorySessionStoreOptions);
1062
1112
  get(id: string, now: number): Promise<S | undefined>;
1063
- set(id: string, session: S, now: number): Promise<void>;
1113
+ set(session: S, now: number): Promise<void>;
1064
1114
  delete(id: string): Promise<void>;
1065
1115
  }
1066
1116
 
1067
1117
  /**
1068
- * Options for `createMemorySessionStore` — the default in-process {@link SessionStoreInterface}.
1118
+ * Configures `createMemorySessionStore` — the default in-process {@link SessionStoreInterface}.
1069
1119
  *
1070
- * @param options - See fields below
1071
1120
  * @remarks
1072
1121
  * - `ttl` — the idle timeout in milliseconds (lazy eviction on `get`).
1073
1122
  * - `lifetime` — the absolute lifetime in milliseconds from first `set`
@@ -1081,15 +1130,13 @@ export declare class MemorySessionStore<S> implements SessionStoreInterface<S> {
1081
1130
  * sink only — it must never call back into the store (no re-entrant
1082
1131
  * `get`/`set`); mutations during eviction are unsupported.
1083
1132
  */
1084
- export declare interface MemorySessionStoreOptions {
1085
- readonly ttl?: number;
1086
- readonly lifetime?: number;
1133
+ export declare interface MemorySessionStoreOptions extends SessionLimits {
1087
1134
  readonly capacity?: number;
1088
1135
  readonly evict?: (id: string) => void;
1089
1136
  }
1090
1137
 
1091
1138
  /**
1092
- * The parsed multipart request body `createMultipart` stashes — files keyed
1139
+ * Describes the parsed multipart request body `createMultipart` stashes — files keyed
1093
1140
  * by their field name, plus every plain text field.
1094
1141
  */
1095
1142
  export declare interface MultipartBody {
@@ -1098,7 +1145,7 @@ export declare interface MultipartBody {
1098
1145
  }
1099
1146
 
1100
1147
  /**
1101
- * One staged multipart upload's public record — the shape the node-face
1148
+ * Represents one staged multipart upload's public record — the shape the node-face
1102
1149
  * `createMultipart` battery (`@orkestrel/middleware/server`) produces per
1103
1150
  * uploaded file.
1104
1151
  *
@@ -1106,7 +1153,7 @@ export declare interface MultipartBody {
1106
1153
  * Declared here rather than in the node-bound server surface so the
1107
1154
  * fetch/string-pure {@link MultipartState} slice — referenced by any
1108
1155
  * environment narrowing `context.state` — never depends on the node face.
1109
- * The server's concrete `UploadedFileInterface` is structurally compatible
1156
+ * The server's concrete `UploadedFile` is structurally compatible
1110
1157
  * with this shape.
1111
1158
  */
1112
1159
  export declare interface MultipartFile {
@@ -1120,7 +1167,7 @@ export declare interface MultipartFile {
1120
1167
  }
1121
1168
 
1122
1169
  /**
1123
- * The multipart state slice `createMultipart` stashes.
1170
+ * Describes the multipart state slice `createMultipart` stashes.
1124
1171
  *
1125
1172
  * @remarks
1126
1173
  * Present only once `createMultipart` has fully parsed a multipart request.
@@ -1133,8 +1180,8 @@ export declare interface MultipartState {
1133
1180
  }
1134
1181
 
1135
1182
  /**
1136
- * Scope a battery to run ONLY on a set of exact pathnames — elsewhere it
1137
- * steps aside via `next()`.
1183
+ * Scopes a battery to a set of exact pathnames and nowhere else outside that set
1184
+ * it steps aside through `next()`.
1138
1185
  *
1139
1186
  * @typeParam TState - The consumer's opaque per-request state type
1140
1187
  * @param paths - One pathname, or a set of pathnames, matched exactly against `context.url.pathname`
@@ -1149,7 +1196,7 @@ export declare interface MultipartState {
1149
1196
  export declare function only<TState>(paths: string | readonly string[], handler: MiddlewareHandler<TState>): MiddlewareHandler<TState>;
1150
1197
 
1151
1198
  /**
1152
- * Rebuild a `Response` around a replacement body while preserving its
1199
+ * Rebuilds a `Response` around a replacement body while preserving its
1153
1200
  * status/statusText — the buffered-response reconstruction shared by the
1154
1201
  * compression and ETag batteries after they have consumed
1155
1202
  * `response.arrayBuffer()`.
@@ -1168,13 +1215,13 @@ export declare function only<TState>(paths: string | readonly string[], handler:
1168
1215
  export declare function rebuildResponse(body: ConstructorParameters<typeof Response>[0], response: Response, headers?: ConstructorParameters<typeof Headers>[0]): Response;
1169
1216
 
1170
1217
  /**
1171
- * Walk `X-Forwarded-For` right-to-left and resolve the first UNTRUSTED hop
1218
+ * Walks `X-Forwarded-For` right-to-left and resolves the first untrusted hop
1172
1219
  * address — `createForwarded`'s core algorithm.
1173
1220
  *
1174
1221
  * @remarks
1175
1222
  * Parses `X-Forwarded-For` only. With `proxies` set, trusts exactly that
1176
1223
  * many hops counted from the right (the closest to this server) and returns
1177
- * the next one left of them; with `trusted` set, trusts every CONSECUTIVE
1224
+ * the next one left of them; with `trusted` set, trusts every consecutive
1178
1225
  * hop from the right that matches one of the roster
1179
1226
  * ({@link matchesTrustedEntry}) and returns the first hop that does not. If
1180
1227
  * the rightmost hop (the immediate sender) does not match the roster, the
@@ -1184,7 +1231,7 @@ export declare function rebuildResponse(body: ConstructorParameters<typeof Respo
1184
1231
  * socket peer).
1185
1232
  *
1186
1233
  * @param header - The raw `X-Forwarded-For` header value (comma-separated hops), if present
1187
- * @param trust - Either a trusted hop COUNT or a `trusted` CIDR/exact roster
1234
+ * @param trust - The {@link ForwardedOptions} form in force — a trusted hop count or a `trusted` CIDR/exact roster
1188
1235
  * @returns The first untrusted hop address, or `undefined` when none qualifies
1189
1236
  *
1190
1237
  * @example
@@ -1192,21 +1239,17 @@ export declare function rebuildResponse(body: ConstructorParameters<typeof Respo
1192
1239
  * resolveForwardedFor('203.0.113.7, 10.0.0.1', { proxies: 1 }) // '203.0.113.7'
1193
1240
  * ```
1194
1241
  */
1195
- export declare function resolveForwardedFor(header: string | undefined, trust: {
1196
- readonly proxies: number;
1197
- } | {
1198
- readonly trusted: readonly string[];
1199
- }): string | undefined;
1242
+ export declare function resolveForwardedFor(header: string | undefined, trust: ForwardedOptions): string | undefined;
1200
1243
 
1201
1244
  /**
1202
- * Derive `createLimiter`'s default rate-limit bucket key from a request's
1245
+ * Derives `createLimiter`'s default rate-limit bucket key from a request's
1203
1246
  * resolved identity facts.
1204
1247
  *
1205
1248
  * @remarks
1206
1249
  * Prefers a verified bearer token ({@link BearerState.token}) as
1207
1250
  * `token:<value>`; else a resolved client IP ({@link ClientState.client.ip},
1208
1251
  * set when `createForwarded` is mounted) or the raw socket peer
1209
- * ({@link ConnectionState.connection.ip}) collapsed via `clientRateKey`
1252
+ * ({@link ConnectionState.connection.ip}) collapsed through `computeClientKey`
1210
1253
  * (IPv6 to its `/64` network) as `ip:<key>`; else the literal `ip:unknown`.
1211
1254
  * Never reads `X-Forwarded-For` itself — that trust decision belongs solely
1212
1255
  * to `createForwarded`.
@@ -1223,8 +1266,8 @@ export declare function resolveForwardedFor(header: string | undefined, trust: {
1223
1266
  export declare function resolveKey(state: BearerState & ClientState & ConnectionState): string;
1224
1267
 
1225
1268
  /**
1226
- * Resolve an opt-in, value-bearing security header — `string | boolean`
1227
- * (default OFF, `true` uses the secure default), the shape `createSecurity`'s
1269
+ * Resolves an opt-in, value-bearing security header — `string | boolean`
1270
+ * (off by default, `true` uses the secure default), the shape `createSecurity`'s
1228
1271
  * `coep`/`hsts` options use, distinct from the plain value-or-`false` shape
1229
1272
  * `resolveSecurityHeader` (the peer substrate) handles.
1230
1273
  *
@@ -1241,22 +1284,7 @@ export declare function resolveKey(state: BearerState & ClientState & Connection
1241
1284
  export declare function resolveOptInHeader(value: string | boolean | undefined, fallback: string): string | undefined;
1242
1285
 
1243
1286
  /**
1244
- * Rebuild a `Session` from an untrusted snapshot value (the inverse of
1245
- * {@link snapshotSession}) — a durable store's `get` deserialization step.
1246
- *
1247
- * @param value - The candidate snapshot, of unknown shape
1248
- * @returns A rebuilt `Session`, or `undefined` when `value` is malformed
1249
- *
1250
- * @example
1251
- * ```ts
1252
- * restoreSession({ id: 'abc', data: { userId: 'u_1' } }) // Session { id: 'abc', data: Map }
1253
- * restoreSession({ id: 1 }) // undefined
1254
- * ```
1255
- */
1256
- export declare function restoreSession(value: unknown): Session | undefined;
1257
-
1258
- /**
1259
- * `createSecurity`'s `identifier` sub-option — request-id minting/echo
1287
+ * Describes `createSecurity`'s `identifier` sub-option request-id minting/echo
1260
1288
  * policy, or `false` to disable the feature entirely.
1261
1289
  *
1262
1290
  * @remarks
@@ -1269,9 +1297,8 @@ export declare type SecurityIdentifierOptions = {
1269
1297
  } | false;
1270
1298
 
1271
1299
  /**
1272
- * Options for `createSecurity` — the security-headers + request-id battery.
1300
+ * Configures `createSecurity` — the security-headers + request-id battery.
1273
1301
  *
1274
- * @param options - See fields below
1275
1302
  * @remarks
1276
1303
  * Every header option is `string | false` (a custom value replaces the
1277
1304
  * default wholesale, `false` omits the header) unless noted; unset uses the
@@ -1284,11 +1311,11 @@ export declare type SecurityIdentifierOptions = {
1284
1311
  * - `coop` — `Cross-Origin-Opener-Policy`; default {@link DEFAULT_COOP}.
1285
1312
  * - `corp` — `Cross-Origin-Resource-Policy`; default {@link DEFAULT_CORP}.
1286
1313
  * - `cluster` — `Origin-Agent-Cluster`; default {@link DEFAULT_CLUSTER}.
1287
- * - `coep` — `Cross-Origin-Embedder-Policy`; `string | boolean`, OFF by
1314
+ * - `coep` — `Cross-Origin-Embedder-Policy`; `string | boolean`, off by
1288
1315
  * default (opt-in, breaks cross-origin subresources); `true` → {@link DEFAULT_COEP}.
1289
- * - `hsts` — `Strict-Transport-Security`; `string | boolean`, OFF by default
1316
+ * - `hsts` — `Strict-Transport-Security`; `string | boolean`, off by default
1290
1317
  * (opt-in, destructive if misconfigured); `true` → {@link DEFAULT_HSTS}.
1291
- * - `identifier` — {@link SecurityIdentifierOptions}; ON by default (mints
1318
+ * - `identifier` — {@link SecurityIdentifierOptions}; on by default (mints
1292
1319
  * and stashes {@link IdentifierState}).
1293
1320
  */
1294
1321
  export declare interface SecurityOptions {
@@ -1305,35 +1332,41 @@ export declare interface SecurityOptions {
1305
1332
  }
1306
1333
 
1307
1334
  /**
1308
- * A server-managed session's default entity — the `create` option's default
1309
- * value factory for `createSession` (ruling G: `Session` ships WITHOUT a
1310
- * `createSession` factory of its own, since that name belongs to the
1311
- * battery).
1335
+ * Represents a server-managed session's default entity — the `create` option's default
1336
+ * value for `createSession`. It ships without a bare `create*` factory of its
1337
+ * own, because the name `createSession` belongs to the battery;
1338
+ * `createRestoredSession` rebuilds one from a stored snapshot.
1312
1339
  *
1313
1340
  * @remarks
1314
- * `data` is a live, mutable `Map` a handler reads/writes directly;
1315
- * `createSession` persists it to the configured store on the way out.
1341
+ * `state` is a `ReadonlyMap` view over the entity's own `Map`: TypeScript
1342
+ * refuses a write through it, and `set`, `delete`, and `clear` are the write
1343
+ * path. `createSession` persists the state to the configured store on the way
1344
+ * out.
1316
1345
  *
1317
1346
  * @example
1318
1347
  * ```ts
1319
1348
  * const session = new Session('abc123')
1320
- * session.data.set('userId', 'u_1')
1349
+ * session.set('userId', 'u_1')
1321
1350
  * ```
1322
1351
  */
1323
1352
  export declare class Session implements SessionInterface {
1324
- readonly id: string;
1325
- readonly data: Map<string, unknown>;
1353
+ #private;
1326
1354
  constructor(id: string);
1355
+ get id(): string;
1356
+ get state(): ReadonlyMap<string, unknown>;
1357
+ set(key: string, value: unknown): void;
1358
+ delete(key: string): boolean;
1359
+ clear(): void;
1327
1360
  }
1328
1361
 
1329
1362
  /**
1330
- * The `@orkestrel/database` column shape for a
1331
- * {@link import('./types.js').SessionRow} table pass as-is to
1363
+ * Holds the `@orkestrel/database` column shape for a
1364
+ * {@link import('./types.js').SessionRow} table. Pass it as-is to
1332
1365
  * `createDatabase({ tables: { sessions: sessionColumns } })` so an app
1333
1366
  * declaring a durable session table never hand-writes the shape.
1334
1367
  *
1335
1368
  * @remarks
1336
- * `lastSeen`/`createdAt` are `integerShape({ min: 0 })` — the table validates
1369
+ * `seen`/`created` are `integerShape({ min: 0 })` — the table validates
1337
1370
  * them as integers, so
1338
1371
  * {@link import('./stores/DatabaseSessionStore.js').DatabaseSessionStore}'s
1339
1372
  * `now` clock must yield integer milliseconds (`Date.now()`, the implicit
@@ -1349,76 +1382,130 @@ export declare class Session implements SessionInterface {
1349
1382
  export declare const sessionColumns: {
1350
1383
  id: StringShape;
1351
1384
  session: JSONShape;
1352
- lastSeen: NumberShape;
1353
- createdAt: NumberShape;
1385
+ seen: NumberShape;
1386
+ created: NumberShape;
1354
1387
  };
1355
1388
 
1356
1389
  /**
1357
- * The mid-handler control handle `createSession` stashes alongside the
1390
+ * Describes the mid-handler control handle `createSession` stashes alongside the
1358
1391
  * session itself — the OWASP anti-fixation / logout primitives.
1359
1392
  *
1360
1393
  * @remarks
1361
- * `regenerate` and `destroy` record intent SYNCHRONOUSLY when called; the
1394
+ * `regenerate` and `destroy` record intent synchronously when called; the
1362
1395
  * store I/O and transport write happen after the handler's `next()` returns
1363
1396
  * (`destroy` supersedes a prior `regenerate`). `regenerate` mints a new id,
1364
- * carries the session's `data` over, and invalidates the old id.
1397
+ * carries the session's `state` over, and invalidates the old id.
1365
1398
  */
1366
1399
  export declare interface SessionControlInterface {
1400
+ /** Mints a fresh id, carries the session's `state` over, and invalidates the old id. */
1367
1401
  regenerate(): void;
1402
+ /** Ends the session — deletes it from the store and clears its transport. */
1368
1403
  destroy(): void;
1369
1404
  }
1370
1405
 
1371
1406
  /**
1372
- * Whether a session has aged past its idle timeout or absolute lifetime as
1407
+ * Describes the per-session instants a store stamps and `sessionExpired` measures
1408
+ * against.
1409
+ *
1410
+ * @remarks
1411
+ * - `seen` — the instant of the most recent live read or write.
1412
+ * - `created` — the instant of the first `set`, preserved across every
1413
+ * later re-`set` of the same id.
1414
+ */
1415
+ export declare interface SessionCursors {
1416
+ readonly seen: number;
1417
+ readonly created: number;
1418
+ }
1419
+
1420
+ /**
1421
+ * Represents one in-process session entry — the payload {@link MemorySessionStore} holds
1422
+ * against an id, alongside the same cursors a persisted row carries.
1423
+ *
1424
+ * @typeParam S - The stored session entity type
1425
+ */
1426
+ export declare interface SessionEntry<S extends SessionInterface> extends SessionCursors {
1427
+ readonly session: S;
1428
+ }
1429
+
1430
+ /**
1431
+ * Checks whether a session has aged past its idle timeout or absolute lifetime as
1373
1432
  * of `now` — the pure expiry predicate `MemorySessionStore` delegates to.
1374
1433
  *
1375
- * @param cursors - The session's `lastSeen` (idle) and `createdAt` (absolute) instants
1434
+ * @param cursors - See {@link SessionCursors}
1376
1435
  * @param now - The current instant (same clock unit as `cursors`)
1377
- * @param limits - The optional `ttl` (idle) and `lifetime` (absolute) thresholds
1378
- * @returns `true` when either configured threshold has elapsed
1436
+ * @param limits - See {@link SessionLimits}
1437
+ * @returns True if either configured threshold has elapsed; false otherwise
1379
1438
  *
1380
1439
  * @example
1381
1440
  * ```ts
1382
- * sessionExpired({ lastSeen: 0, createdAt: 0 }, 1_000, { ttl: 500 }) // true
1441
+ * sessionExpired({ seen: 0, created: 0 }, 1_000, { ttl: 500 }) // true
1383
1442
  * ```
1384
1443
  */
1385
- export declare function sessionExpired(cursors: {
1386
- readonly lastSeen: number;
1387
- readonly createdAt: number;
1388
- }, now: number, limits: {
1389
- readonly ttl?: number;
1390
- readonly lifetime?: number;
1391
- }): boolean;
1444
+ export declare function sessionExpired(cursors: SessionCursors, now: number, limits: SessionLimits): boolean;
1392
1445
 
1393
1446
  /**
1394
- * A server-managed session's public surface — an id and its mutable data bag.
1447
+ * Represents a server-managed session's public surface — an id, its live state, and the
1448
+ * mutators that write it.
1395
1449
  *
1396
1450
  * @remarks
1397
- * `data` is a live `Map` a handler reads/writes directly; `createSession`
1398
- * persists it to the configured {@link SessionStoreInterface} on the way out.
1451
+ * `state` is a `ReadonlyMap` view a handler reads directly: TypeScript
1452
+ * refuses a write through it, and `set`, `delete`, and `clear` are the write
1453
+ * path. `createSession` persists the state to the configured
1454
+ * {@link SessionStoreInterface} on the way out. `clear` empties the state
1455
+ * without ending the session — `SessionControlInterface.destroy` does that.
1399
1456
  */
1400
1457
  export declare interface SessionInterface {
1401
1458
  readonly id: string;
1402
- readonly data: Map<string, unknown>;
1459
+ readonly state: ReadonlyMap<string, unknown>;
1460
+ /**
1461
+ * Writes one key's value into the session's state.
1462
+ *
1463
+ * @param key - The state key to write
1464
+ * @param value - The value to store under `key`
1465
+ */
1466
+ set(key: string, value: unknown): void;
1467
+ /**
1468
+ * Removes one key from the session's state.
1469
+ *
1470
+ * @param key - The state key to remove
1471
+ * @returns True when the session held `key`; false otherwise
1472
+ */
1473
+ delete(key: string): boolean;
1474
+ /** Empties the state, leaving the session and its id alive. */
1475
+ clear(): void;
1403
1476
  }
1404
1477
 
1405
1478
  /**
1406
- * Options for `createSession` the generic session battery.
1479
+ * Describes the idle and absolute-lifetime thresholds a session store enforces —
1480
+ * `sessionExpired`'s limits argument and both shipped stores' construction
1481
+ * options.
1407
1482
  *
1408
- * @typeParam S - The session data payload type `create` produces
1483
+ * @remarks
1484
+ * - `ttl` — the idle timeout in milliseconds; absent means no idle expiry.
1485
+ * - `lifetime` — the absolute lifetime in milliseconds from the first `set`;
1486
+ * absent means no absolute expiry.
1487
+ */
1488
+ export declare interface SessionLimits {
1489
+ readonly ttl?: number | undefined;
1490
+ readonly lifetime?: number | undefined;
1491
+ }
1492
+
1493
+ /**
1494
+ * Configures `createSession` — the generic session battery.
1495
+ *
1496
+ * @typeParam S - The session entity type `create` produces
1409
1497
  * @typeParam TState - The consumer's opaque per-request state type `mint` reads
1410
- * @param options - See fields below
1411
1498
  * @remarks
1412
- * - `transport` — the {@link SessionTransport} (`createCookieTransport(...)`,
1499
+ * - `transport` — the {@link SessionTransportInterface} (`createCookieTransport(...)`,
1413
1500
  * `createHeaderTransport(...)`, or a custom one).
1414
1501
  * - `store` — the {@link SessionStoreInterface}; defaults to
1415
1502
  * `createMemorySessionStore({ ttl, lifetime, capacity, evict })`.
1416
1503
  * - `ttl` — the idle timeout in milliseconds.
1417
1504
  * - `lifetime` — the absolute session lifetime in milliseconds from mint.
1418
- * - `capacity` — the maximum number of distinct session ids the DEFAULT
1505
+ * - `capacity` — the maximum number of distinct session ids the default
1419
1506
  * memory store tracks before LRU eviction; ignored when `store` is
1420
1507
  * provided. Defaults to {@link DEFAULT_SESSION_CAPACITY}.
1421
- * - `evict` — invoked with a session id evicted by the DEFAULT memory
1508
+ * - `evict` — invoked with a session id evicted by the default memory
1422
1509
  * store's own policy; ignored when `store` is provided. It is a
1423
1510
  * notification sink only — it must never call back into the store
1424
1511
  * (no re-entrant `get`/`set`); mutations during eviction are unsupported.
@@ -1426,14 +1513,12 @@ export declare interface SessionInterface {
1426
1513
  * defaults to `new Session(id)`.
1427
1514
  * - `mint` — decides whether to auto-mint a session when none resolves;
1428
1515
  * defaults to always minting (auto-session).
1429
- * - `require` — when `true`, a request that resolves no session and does not
1516
+ * - `required` — when `true`, a request that resolves no session and does not
1430
1517
  * mint one renders a 404 instead of proceeding sessionless. Defaults to `false`.
1431
- * - `ends` — when `true`, a `DELETE` request carrying a valid session id
1432
- * deletes the session and short-circuits with `204`. Defaults to `false`.
1433
1518
  * - `clock` — the injected time source fed to the store; defaults to `Date.now`.
1434
1519
  */
1435
- export declare interface SessionOptions<S, TState = unknown> {
1436
- readonly transport: SessionTransport;
1520
+ export declare interface SessionOptions<S extends SessionInterface, TState = unknown> {
1521
+ readonly transport: SessionTransportInterface;
1437
1522
  readonly store?: SessionStoreInterface<S>;
1438
1523
  readonly ttl?: number;
1439
1524
  readonly lifetime?: number;
@@ -1441,25 +1526,47 @@ export declare interface SessionOptions<S, TState = unknown> {
1441
1526
  readonly evict?: (id: string) => void;
1442
1527
  readonly create?: (id: string) => S;
1443
1528
  readonly mint?: (context: MiddlewareContext<TState>) => boolean | Promise<boolean>;
1444
- readonly require?: boolean;
1445
- readonly ends?: boolean;
1529
+ readonly required?: boolean;
1446
1530
  readonly clock?: () => number;
1447
1531
  }
1448
1532
 
1449
1533
  /**
1450
- * One persisted session row an opaque snapshot column plus the store-owned
1534
+ * Rebuilds a session entity from an untrusted stored snapshot, or resolves `undefined` when the value is malformed.
1535
+ *
1536
+ * @remarks
1537
+ * The step {@link DatabaseSessionStore} is constructed with, and the seam a
1538
+ * consumer implements to restore its own session entity from a persisted row.
1539
+ * `createDatabaseSessionStore` supplies `createRestoredSession` as that step.
1540
+ */
1541
+ export declare type SessionRestoreFunction = (value: unknown) => SessionInterface | undefined;
1542
+
1543
+ /**
1544
+ * Represents one persisted session row — an opaque snapshot column plus the store-owned
1451
1545
  * idle/absolute-lifetime cursors, the shape a {@link DatabaseSessionStore}'s
1452
1546
  * backing table holds.
1453
1547
  */
1454
- export declare interface SessionRow {
1548
+ export declare interface SessionRow extends SessionCursors {
1455
1549
  readonly id: string;
1456
1550
  readonly session: unknown;
1457
- readonly lastSeen: number;
1458
- readonly createdAt: number;
1459
1551
  }
1460
1552
 
1461
1553
  /**
1462
- * The session state slice `createSession` stashes.
1554
+ * Represents a session's serializable projection — the value `snapshotSession` produces
1555
+ * and a durable store's `set` writes.
1556
+ *
1557
+ * @remarks
1558
+ * `state` is the wire member a persisted row carries, built on a
1559
+ * null-prototype record so a session key literally named `__proto__`
1560
+ * round-trips as an own enumerable property. It holds the same entries the
1561
+ * entity's own `state` view publishes.
1562
+ */
1563
+ export declare interface SessionSnapshot {
1564
+ readonly id: string;
1565
+ readonly state: Readonly<Record<string, unknown>>;
1566
+ }
1567
+
1568
+ /**
1569
+ * Describes the session state slice `createSession` stashes.
1463
1570
  *
1464
1571
  * @remarks
1465
1572
  * `session` is present whenever a request resolves or mints a session;
@@ -1471,68 +1578,112 @@ export declare interface SessionState {
1471
1578
  }
1472
1579
 
1473
1580
  /**
1474
- * The pluggable session persistence seam `createSession`'s `store` option
1475
- * implements — a point-access store (AGENTS §5) keyed by session id.
1581
+ * Describes the pluggable session persistence seam `createSession`'s `store` option
1582
+ * implements — a point-access store keyed by session id.
1476
1583
  *
1477
- * @typeParam S - The session data payload type
1584
+ * @typeParam S - The stored session entity type
1478
1585
  * @remarks
1479
1586
  * Every primitive is async and takes a trailing `now` clock reading (the
1480
1587
  * same seam `createSession`'s `clock` option feeds) so a store can apply its
1481
1588
  * own idle/absolute expiry against the caller's injected time rather than
1482
- * its own wall clock. `delete` of an absent id is a no-op, never throws.
1483
- */
1484
- export declare interface SessionStoreInterface<S> {
1589
+ * its own wall clock. `set` reads the id from the session it is handed —
1590
+ * a stored value carries its own id, so no separate id is passed. `delete` of
1591
+ * an absent id is a no-op, never throws.
1592
+ *
1593
+ * `get` must resolve a value satisfying {@link isSession} — an `id` string,
1594
+ * a `state` `Map` view, and the mutators — or `undefined`. `createSession`
1595
+ * dereferences the resolved value's `id` and `state` without re-checking
1596
+ * them, so a store that resolves an off-shape value corrupts the battery's
1597
+ * own state rather than being refused at the seam. The shipped
1598
+ * `DatabaseSessionStore` enforces this with the caller-supplied guard it is
1599
+ * constructed with.
1600
+ */
1601
+ export declare interface SessionStoreInterface<S extends SessionInterface> {
1602
+ /**
1603
+ * Reads a session by id, applying the idle and absolute expiry against `now`.
1604
+ *
1605
+ * @param id - The session id to read
1606
+ * @param now - The caller's clock reading the expiry is measured against
1607
+ * @returns The stored session, or `undefined` when it is absent or expired
1608
+ */
1485
1609
  get(id: string, now: number): Promise<S | undefined>;
1486
- set(id: string, session: S, now: number): Promise<void>;
1610
+ /**
1611
+ * Persists a session under its own `id`, refreshing its idle window.
1612
+ *
1613
+ * @param session - The session to persist, keyed by its own `id`
1614
+ * @param now - The caller's clock reading stamped as the session's `seen`
1615
+ * @returns A promise that resolves once the session is stored
1616
+ */
1617
+ set(session: S, now: number): Promise<void>;
1618
+ /**
1619
+ * Removes a session by id — a no-op on an absent id, never throws.
1620
+ *
1621
+ * @param id - The session id to remove
1622
+ * @returns A promise that resolves once the id is absent from the store
1623
+ */
1487
1624
  delete(id: string): Promise<void>;
1488
1625
  }
1489
1626
 
1490
1627
  /**
1491
- * The transport seam `createSession`'s `transport` option implements — how a
1628
+ * Describes the transport seam `createSession`'s `transport` option implements — how a
1492
1629
  * session id travels to and from the client (a signed cookie, a header, …).
1493
1630
  *
1494
1631
  * @remarks
1495
1632
  * `read` is total (a malformed/tampered credential resolves `undefined`,
1496
- * never throws). `write` and `clear` mutate the RETURNED `Response` on the
1633
+ * never throws). `write` and `clear` mutate the returned `Response` on the
1497
1634
  * way out — the returning onion makes "before send" automatic. `write` is
1498
1635
  * called only when a session is freshly minted or regenerated; `clear` is
1499
1636
  * called on `destroy()`. `write`'s `encrypted` flag is the request's resolved
1500
1637
  * transport security (derived from `context.url.protocol`) so a cookie
1501
- * transport can resolve its own `Secure` attribute via `resolveSecure`
1638
+ * transport can resolve its own `Secure` attribute through `resolveSecure`
1502
1639
  * without re-deriving connection facts itself.
1503
1640
  */
1504
- export declare interface SessionTransport {
1641
+ export declare interface SessionTransportInterface {
1642
+ /**
1643
+ * Reads the incoming session id from the request — `undefined` on any failure.
1644
+ *
1645
+ * @param request - The inbound request the credential travels on
1646
+ * @returns The session id, or `undefined` when none is present or readable
1647
+ */
1505
1648
  read(request: Request): string | undefined | Promise<string | undefined>;
1649
+ /**
1650
+ * Writes a freshly minted or regenerated session id onto the response, together with
1651
+ * the request's encrypted-transport fact.
1652
+ *
1653
+ * @param response - The outgoing response the credential is written onto
1654
+ * @param id - The session id carried to the client
1655
+ * @param encrypted - Whether the request arrived over an encrypted transport
1656
+ * @returns Nothing, or a promise that resolves once the credential is written
1657
+ */
1506
1658
  write(response: Response, id: string, encrypted: boolean): void | Promise<void>;
1659
+ /** Clears the transport's credential on `destroy()`. */
1507
1660
  clear(response: Response): void;
1508
1661
  }
1509
1662
 
1510
1663
  /**
1511
- * Snapshot a session's `data` Map into a plain, serializable record — the
1664
+ * Snapshots a session's `state` into a plain, serializable record — the
1512
1665
  * projection a durable store's `set` writes to disk.
1513
1666
  *
1514
1667
  * @param session - The session to snapshot
1515
- * @returns A plain-object copy of `session.data`, keyed alongside `session.id`
1668
+ * @returns A {@link SessionSnapshot} whose `state` is a plain-object copy of
1669
+ * `session.state`, keyed alongside `session.id`
1516
1670
  *
1517
1671
  * @remarks
1518
- * `data` is built on a null-prototype object (`Object.create(null)`), never
1672
+ * `state` is built on a null-prototype object (`Object.create(null)`), never
1519
1673
  * a `{}` literal — a session key literally named `__proto__` must round-trip
1520
- * as an OWN enumerable property instead of hitting `Object.prototype`'s
1674
+ * as an own enumerable property instead of hitting `Object.prototype`'s
1521
1675
  * `__proto__` accessor (which would silently drop the entry and risk
1522
1676
  * polluting the shared prototype).
1523
1677
  *
1524
1678
  * @example
1525
1679
  * ```ts
1526
- * snapshotSession(session) // { id: 'abc', data: { userId: 'u_1' } }
1680
+ * snapshotSession(session) // { id: 'abc', state: { userId: 'u_1' } }
1527
1681
  * ```
1528
1682
  */
1529
- export declare function snapshotSession(session: SessionInterface): {
1530
- readonly id: string;
1531
- readonly data: Record<string, unknown>;
1532
- };
1683
+ export declare function snapshotSession(session: SessionInterface): SessionSnapshot;
1533
1684
 
1534
1685
  /**
1535
- * One access-log-style entry `createTelemetry` records after a response
1686
+ * Represents one access-log-style entry `createTelemetry` records after a response
1536
1687
  * settles — the access-log/timing seam's payload shape.
1537
1688
  *
1538
1689
  * @remarks
@@ -1551,9 +1702,8 @@ export declare interface TelemetryEntry {
1551
1702
  }
1552
1703
 
1553
1704
  /**
1554
- * Options for `createTelemetry` — the request timing/access-log seam.
1705
+ * Configures `createTelemetry` — the request timing/access-log seam.
1555
1706
  *
1556
- * @param options - See fields below
1557
1707
  * @remarks
1558
1708
  * - `record` — invoked once per request with the settled {@link
1559
1709
  * TelemetryEntry}; its own throw is swallowed so a broken sink can never
@@ -1564,17 +1714,36 @@ export declare interface TelemetryOptions {
1564
1714
  }
1565
1715
 
1566
1716
  /**
1567
- * Copy every entry of one session's `data` into another — the regenerate
1568
- * data-carry `createSession`'s `control.regenerate()` applies (ruling D).
1717
+ * Copies every entry of one session's `state` into another — the regenerate
1718
+ * state-carry `createSession`'s `control.regenerate()` applies.
1719
+ *
1720
+ * @param from - The source session whose `state` is copied
1721
+ * @param to - The destination session the entries are written into, through
1722
+ * its own `set` mutator
1723
+ *
1724
+ * @example
1725
+ * ```ts
1726
+ * transferSessionState(oldSession, newSession)
1727
+ * ```
1728
+ */
1729
+ export declare function transferSessionState(from: SessionInterface, to: SessionInterface): void;
1730
+
1731
+ /**
1732
+ * Validates a store's idle and absolute-lifetime thresholds, throwing when
1733
+ * either is present and malformed — the shared construction gate
1734
+ * {@link MemorySessionStore} and {@link DatabaseSessionStore} both apply, so
1735
+ * one malformed `ttl` is refused identically by whichever store receives it.
1569
1736
  *
1570
- * @param from - The source session whose `data` is copied
1571
- * @param to - The destination session `data` is copied into
1737
+ * @param limits - See {@link SessionLimits}
1738
+ * @returns Nothing; a successful return means both thresholds are usable
1739
+ * @throws {TypeError} Thrown when `ttl` or `lifetime` is present and is not a
1740
+ * positive finite number
1572
1741
  *
1573
1742
  * @example
1574
1743
  * ```ts
1575
- * transferSessionData(oldSession, newSession)
1744
+ * validateSessionLimits({ ttl: 60_000 }) // returns; the thresholds are usable
1576
1745
  * ```
1577
1746
  */
1578
- export declare function transferSessionData(from: SessionInterface, to: SessionInterface): void;
1747
+ export declare function validateSessionLimits(limits: SessionLimits | undefined): void;
1579
1748
 
1580
1749
  export { }