@fuzdev/fuz_app 0.127.0 → 0.128.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/actions/CLAUDE.md +35 -18
- package/dist/actions/connection_closer.d.ts +16 -4
- package/dist/actions/connection_closer.d.ts.map +1 -1
- package/dist/actions/connection_closer.js +20 -4
- package/dist/actions/register_action_ws.d.ts +10 -2
- package/dist/actions/register_action_ws.d.ts.map +1 -1
- package/dist/actions/register_action_ws.js +6 -3
- package/dist/actions/register_ws_endpoint.d.ts +3 -1
- package/dist/actions/register_ws_endpoint.d.ts.map +1 -1
- package/dist/actions/register_ws_endpoint.js +3 -1
- package/dist/auth/CLAUDE.md +13 -9
- package/dist/auth/audit_emitter.d.ts +59 -12
- package/dist/auth/audit_emitter.d.ts.map +1 -1
- package/dist/auth/audit_emitter.js +53 -15
- package/dist/auth/middleware.d.ts +30 -0
- package/dist/auth/middleware.d.ts.map +1 -1
- package/dist/auth/middleware.js +59 -0
- package/dist/realtime/sse_auth_guard.d.ts +3 -1
- package/dist/realtime/sse_auth_guard.d.ts.map +1 -1
- package/dist/server/app_server.d.ts +39 -12
- package/dist/server/app_server.d.ts.map +1 -1
- package/dist/server/app_server.js +92 -39
- package/dist/testing/CLAUDE.md +36 -23
- package/dist/testing/app_server.d.ts +1 -1
- package/dist/testing/app_server.d.ts.map +1 -1
- package/dist/testing/attack_surface.d.ts +1 -1
- package/dist/testing/attack_surface.d.ts.map +1 -1
- package/dist/testing/audit_drift_guard.d.ts +4 -2
- package/dist/testing/audit_drift_guard.d.ts.map +1 -1
- package/dist/testing/audit_drift_guard.js +14 -4
- package/dist/testing/cross_backend/account_lifecycle.d.ts.map +1 -1
- package/dist/testing/cross_backend/account_lifecycle.js +1 -2
- package/dist/testing/cross_backend/capabilities.d.ts +3 -1
- package/dist/testing/cross_backend/capabilities.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_reset_actions.d.ts +27 -18
- package/dist/testing/cross_backend/testing_reset_actions.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_reset_actions.js +30 -19
- package/dist/testing/cross_backend/ws_round_trip.d.ts +2 -1
- package/dist/testing/cross_backend/ws_round_trip.d.ts.map +1 -1
- package/dist/testing/cross_backend/ws_round_trip.js +40 -4
- package/dist/testing/stubs.d.ts +23 -6
- package/dist/testing/stubs.d.ts.map +1 -1
- package/dist/testing/stubs.js +39 -14
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/middleware.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAIjE;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,oBAAoB,WAAW,CAAC;AAE7C;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,6BAA6B,GACzC,QAAQ,eAAe,GAAG,cAAc,EACxC,MAAM,MAAM,KACV,IAOF,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACrC,eAAe,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/B,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,iFAAiF;IACjF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mFAAmF;IACnF,kBAAkB,CAAC,EAAE,gBAAgB,CAAC;CACtC;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,4BAA4B,GACxC,MAAM,OAAO,EACb,SAAS,qBAAqB,KAC5B,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,CA4E/B,CAAC"}
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/middleware.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAIjE;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,oBAAoB,WAAW,CAAC;AAE7C;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,6BAA6B,GACzC,QAAQ,eAAe,GAAG,cAAc,EACxC,MAAM,MAAM,KACV,IAOF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,+BAA+B,GAC3C,aAAa,aAAa,CAAC,cAAc,CAAC,EAC1C,kBAAkB,aAAa,CAAC,cAAc,CAAC,KAC7C,IA+BF,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACrC,eAAe,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/B,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,iFAAiF;IACjF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mFAAmF;IACnF,kBAAkB,CAAC,EAAE,gBAAgB,CAAC;CACtC;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,4BAA4B,GACxC,MAAM,OAAO,EACb,SAAS,qBAAqB,KAC5B,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,CA4E/B,CAAC"}
|
package/dist/auth/middleware.js
CHANGED
|
@@ -41,6 +41,65 @@ export const assert_endpoint_in_auth_scope = (option, path) => {
|
|
|
41
41
|
`(${AUTH_MIDDLEWARE_PATH}) — it would see every caller as unauthenticated — mount it under /api/`);
|
|
42
42
|
}
|
|
43
43
|
};
|
|
44
|
+
/**
|
|
45
|
+
* Throw unless a middleware list still mounts every spec of the stack it was
|
|
46
|
+
* built from — the trusted-proxy spec and the auth middleware — exactly once,
|
|
47
|
+
* at its original path, in its original order.
|
|
48
|
+
*
|
|
49
|
+
* `create_app_server` and `create_test_app_surface_spec` run it on the list
|
|
50
|
+
* a `transform_middleware` option returns, against the stack they handed it
|
|
51
|
+
* (`[proxy, ...auth]`). The endpoint auth-scope check
|
|
52
|
+
* (`assert_endpoint_in_auth_scope`) assumes the auth stack is mounted at
|
|
53
|
+
* `AUTH_MIDDLEWARE_PATH`, and every IP-keyed rate limiter assumes the proxy
|
|
54
|
+
* spec ran first — without it `get_client_ip` answers `'unknown'` for every
|
|
55
|
+
* caller, collapsing each limiter into one shared bucket. So a transform that
|
|
56
|
+
* moves, drops, duplicates, reorders, wraps, or replaces a stack layer is
|
|
57
|
+
* refused. Other specs may sit anywhere, including before the proxy spec and
|
|
58
|
+
* between the auth layers. The check pins where the stack's layers sit, not
|
|
59
|
+
* what added layers do — a layer you add runs with full context access.
|
|
60
|
+
*
|
|
61
|
+
* Each stack spec is matched by its `handler` — the closure its factory built
|
|
62
|
+
* — not by `name`, which any spec can carry, so a same-named replacement or a
|
|
63
|
+
* wrapped handler counts as missing. A spread copy (`{...spec}`) keeps the
|
|
64
|
+
* handler and still matches. Its path is compared with the original's, so
|
|
65
|
+
* pass specs the transform could not reach: the assemblies hand the transform
|
|
66
|
+
* shallow copies in a fresh array and keep the originals here.
|
|
67
|
+
*
|
|
68
|
+
* @param stack_specs - the stack the transform was built from, in mount order
|
|
69
|
+
* @param middleware_specs - the middleware list the transform returned
|
|
70
|
+
* @throws Error when a stack spec is missing, mounted more than once, mounted
|
|
71
|
+
* at another path, or out of order
|
|
72
|
+
*/
|
|
73
|
+
export const assert_middleware_stack_mounted = (stack_specs, middleware_specs) => {
|
|
74
|
+
let previous_index = -1;
|
|
75
|
+
for (const stack_spec of stack_specs) {
|
|
76
|
+
let index = -1;
|
|
77
|
+
let count = 0;
|
|
78
|
+
for (let i = 0; i < middleware_specs.length; i++) {
|
|
79
|
+
if (middleware_specs[i].handler === stack_spec.handler) {
|
|
80
|
+
if (count === 0)
|
|
81
|
+
index = i;
|
|
82
|
+
count++;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const found = count === 0
|
|
86
|
+
? 'missing'
|
|
87
|
+
: count > 1
|
|
88
|
+
? `mounted ${count} times`
|
|
89
|
+
: middleware_specs[index].path !== stack_spec.path
|
|
90
|
+
? `mounted at ${middleware_specs[index].path}`
|
|
91
|
+
: index < previous_index
|
|
92
|
+
? 'out of order'
|
|
93
|
+
: null;
|
|
94
|
+
if (found) {
|
|
95
|
+
throw new Error(`transform_middleware must keep the middleware '${stack_spec.name}' mounted once ` +
|
|
96
|
+
`at ${stack_spec.path} in its original order (${found}) — endpoint auth-scope checks ` +
|
|
97
|
+
'and client-IP rate limiting assume it; add layers around the stack, ' +
|
|
98
|
+
"don't move, drop, wrap, or replace it");
|
|
99
|
+
}
|
|
100
|
+
previous_index = index;
|
|
101
|
+
}
|
|
102
|
+
};
|
|
44
103
|
/**
|
|
45
104
|
* Create the auth middleware stack.
|
|
46
105
|
*
|
|
@@ -164,7 +164,9 @@ export declare const create_audit_log_sse: (options: {
|
|
|
164
164
|
* Required so it can't be forgotten: without it a revoked credential's
|
|
165
165
|
* streams close only through the audit listener, which a failed audit write
|
|
166
166
|
* or a cap eviction never reaches. Pass `null` only for a registry no
|
|
167
|
-
* revocation has to reach (tests of the registry itself)
|
|
167
|
+
* revocation has to reach (tests of the registry itself), or when the
|
|
168
|
+
* caller adds `create_sse_connection_closer(registry)` itself — as
|
|
169
|
+
* `create_app_server` does, to hold the remover `add` returns.
|
|
168
170
|
*/
|
|
169
171
|
connection_closer: RealtimeCloser | null;
|
|
170
172
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sse_auth_guard.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/realtime/sse_auth_guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAGtD,OAAO,EAIN,KAAK,aAAa,EAClB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACxF,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE3D,2DAA2D;AAC3D,eAAO,MAAM,iBAAiB,cAAc,CAAC;AAE7C;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,4BAA4B,GAAI,CAAC,EAC7C,UAAU,kBAAkB,CAAC,CAAC,CAAC,KAC7B,gBAKD,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,eAAO,MAAM,qBAAqB,GAAI,CAAC,EACtC,UAAU,kBAAkB,CAAC,CAAC,CAAC,EAC/B,eAAe,MAAM,GAAG,IAAI,EAC5B,KAAK,MAAM,KACT,CAAC,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CA4DjC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC3B;;;;;OAKG;IACH,QAAQ,EAAE,kBAAkB,CAAC,eAAe,CAAC,CAAC;IAC9C,kFAAkF;IAClF,GAAG,EAAE,MAAM,CAAC;IACZ,yJAAyJ;IACzJ,cAAc,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;CAC/C;AAED;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,EAAE,KAAK,CAAC,SAAS,CAOlD,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,2BAA2B,KAAK,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,eAAO,MAAM,oBAAoB,GAAI,SAAS;IAC7C,mEAAmE;IACnE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ
|
|
1
|
+
{"version":3,"file":"sse_auth_guard.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/realtime/sse_auth_guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAGtD,OAAO,EAIN,KAAK,aAAa,EAClB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACxF,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE3D,2DAA2D;AAC3D,eAAO,MAAM,iBAAiB,cAAc,CAAC;AAE7C;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,4BAA4B,GAAI,CAAC,EAC7C,UAAU,kBAAkB,CAAC,CAAC,CAAC,KAC7B,gBAKD,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,eAAO,MAAM,qBAAqB,GAAI,CAAC,EACtC,UAAU,kBAAkB,CAAC,CAAC,CAAC,EAC/B,eAAe,MAAM,GAAG,IAAI,EAC5B,KAAK,MAAM,KACT,CAAC,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CA4DjC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC3B;;;;;OAKG;IACH,QAAQ,EAAE,kBAAkB,CAAC,eAAe,CAAC,CAAC;IAC9C,kFAAkF;IAClF,GAAG,EAAE,MAAM,CAAC;IACZ,yJAAyJ;IACzJ,cAAc,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;CAC/C;AAED;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,EAAE,KAAK,CAAC,SAAS,CAOlD,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,2BAA2B,KAAK,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,eAAO,MAAM,oBAAoB,GAAI,SAAS;IAC7C,mEAAmE;IACnE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;;;;OASG;IACH,iBAAiB,EAAE,cAAc,GAAG,IAAI,CAAC;IACzC;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,KAAG,WAgBH,CAAC"}
|
|
@@ -198,9 +198,18 @@ export interface AppServerOptions {
|
|
|
198
198
|
/**
|
|
199
199
|
* Optional: transform middleware specs before applying.
|
|
200
200
|
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
201
|
+
* Receives shallow copies of the trusted-proxy spec followed by the auth
|
|
202
|
+
* stack, in a fresh array — mutating them leaves the originals untouched.
|
|
203
|
+
* Add layers anywhere (before the proxy spec, between it and the auth
|
|
204
|
+
* stack, between the auth layers, or after), but keep each of those specs
|
|
205
|
+
* — its `handler`, not just its `name` — mounted once at its original path
|
|
206
|
+
* (`'*'` for the proxy, `AUTH_MIDDLEWARE_PATH` for auth) in its original
|
|
207
|
+
* order: the endpoint auth-scope check (`assert_endpoint_in_auth_scope`)
|
|
208
|
+
* and client-IP rate limiting (`get_client_ip`) assume it, so assembly
|
|
209
|
+
* throws (`assert_middleware_stack_mounted`) if the transform moves, drops,
|
|
210
|
+
* duplicates, reorders, wraps, or replaces one. The check pins where those
|
|
211
|
+
* layers sit, not what added layers do — a layer you add runs with full
|
|
212
|
+
* context access.
|
|
204
213
|
*/
|
|
205
214
|
transform_middleware?: (specs: Array<MiddlewareSpec>) => Array<MiddlewareSpec>;
|
|
206
215
|
/**
|
|
@@ -321,13 +330,14 @@ export interface AppServerOptions {
|
|
|
321
330
|
* after the route specs and before `post_route_middleware` and
|
|
322
331
|
* `static_serving`, so neither runs ahead of an upgrade.
|
|
323
332
|
*
|
|
324
|
-
* Duplicate `path` values across two `WsEndpointSpec`s
|
|
325
|
-
*
|
|
333
|
+
* Duplicate `path` values across two `WsEndpointSpec`s, and a `path` a
|
|
334
|
+
* GET `RouteSpec` already claims, throw at assembly before any endpoint
|
|
335
|
+
* mounts (Hono would silently shadow them otherwise).
|
|
326
336
|
*
|
|
327
337
|
* Every mounted transport is added to `deps.connection_closer`, so
|
|
328
338
|
* the revocation handlers' post-commit closes reach its sockets —
|
|
329
339
|
* unconditionally, since those closes are what ends a revoked
|
|
330
|
-
* credential's connections.
|
|
340
|
+
* credential's connections. `AppServer.close` removes it again.
|
|
331
341
|
*
|
|
332
342
|
* Each spec's `auth_guard?` defaults to `true` — the factory
|
|
333
343
|
* registers `create_ws_auth_guard` against the mounted transport via
|
|
@@ -415,8 +425,17 @@ export interface AppServer {
|
|
|
415
425
|
* `WsEndpointSpec.transport` or added by hand, since they are registered
|
|
416
426
|
* on the backend's closer and the backend is going away; a close that
|
|
417
427
|
* throws is logged and the shutdown goes on
|
|
418
|
-
* 3.
|
|
419
|
-
*
|
|
428
|
+
* 3. release what assembly acquired, last acquired first: remove the
|
|
429
|
+
* audit listeners `create_app_server` registered on `deps.audit` (the
|
|
430
|
+
* audit-log SSE listener, the WS auth guards, each
|
|
431
|
+
* `extra_audit_handlers` entry) and the closer members it added to
|
|
432
|
+
* `deps.connection_closer` (each mounted transport, the audit stream
|
|
433
|
+
* registry), and `dispose` the rate limiters it built for omitted
|
|
434
|
+
* options — never one passed in, which its caller owns. A release that
|
|
435
|
+
* throws is logged and the rest still run. The backend's emitter and
|
|
436
|
+
* closer are left as they were before assembly, so a failed assembly
|
|
437
|
+
* can be retried on the same backend, and a backend whose `close` you
|
|
438
|
+
* own (a test harness) can host another server
|
|
420
439
|
* 4. close the database connection (`AppBackend.close`)
|
|
421
440
|
*
|
|
422
441
|
* Idempotent: a second call settles with the first one's outcome (a failed
|
|
@@ -470,14 +489,22 @@ export declare const DEFAULT_MAX_BODY_SIZE: number;
|
|
|
470
489
|
* case; consumers can call `require_audit_sse(ctx)` / `require_audit_sse(server)`
|
|
471
490
|
* to assert the invariant.
|
|
472
491
|
*
|
|
473
|
-
*
|
|
474
|
-
*
|
|
492
|
+
* Assembly acquires a few things that outlive it — the rate limiters it
|
|
493
|
+
* builds, the listeners it registers on `deps.audit`, the members it adds to
|
|
494
|
+
* `deps.connection_closer` — and records a release for each as it goes. When
|
|
495
|
+
* assembly throws, every release recorded so far runs, last acquired first
|
|
496
|
+
* (one that throws is logged and the rest still run), and the original error
|
|
497
|
+
* is rethrown: a failed assembly leaves the backend's emitter and closer as
|
|
498
|
+
* it found them and no limiter timer running. When `auth_cleanup` is set, the
|
|
499
|
+
* auth cleanup schedule starts as the last step of assembly — nothing after
|
|
500
|
+
* it can throw, so an assembly that throws leaves no schedule running.
|
|
475
501
|
*
|
|
476
502
|
* The returned `close` owns shutdown: it stops that schedule, closes every
|
|
477
|
-
* live connection on the backend's closer,
|
|
478
|
-
*
|
|
503
|
+
* live connection on the backend's closer, runs the same releases, and
|
|
504
|
+
* closes the database (`AppServer.close`).
|
|
479
505
|
*
|
|
480
506
|
* @returns assembled Hono app, backend, surface build, and bootstrap status
|
|
507
|
+
* @throws Error from any assembly step, after releasing what assembly acquired
|
|
481
508
|
*/
|
|
482
509
|
export declare const create_app_server: (options: AppServerOptions) => Promise<AppServer>;
|
|
483
510
|
//# sourceMappingURL=app_server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app_server.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/server/app_server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,IAAI,EAAE,KAAK,OAAO,EAAE,MAAM,MAAM,CAAC;AAG1C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"app_server.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/server/app_server.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,7 +12,7 @@ import { logger } from 'hono/logger';
|
|
|
12
12
|
import { bodyLimit } from 'hono/body-limit';
|
|
13
13
|
import { z } from 'zod';
|
|
14
14
|
import { session_cookie_options } from '../auth/session_cookie.js';
|
|
15
|
-
import { create_audit_log_sse, audit_log_event_specs } from '../realtime/sse_auth_guard.js';
|
|
15
|
+
import { create_audit_log_sse, create_sse_connection_closer, audit_log_event_specs } from '../realtime/sse_auth_guard.js';
|
|
16
16
|
import { BaseServerEnv } from './env.js';
|
|
17
17
|
import { RateLimiter, announce_rate_limiters_disabled, default_login_ip_rate_limit, default_login_account_rate_limit, default_action_account_rate_limit, default_action_ip_rate_limit } from '../rate_limiter.js';
|
|
18
18
|
// Side-effect import: augments Hono's ContextVariableMap so consumers
|
|
@@ -26,7 +26,7 @@ import { apply_middleware_specs, apply_route_specs, prefix_route_specs } from '.
|
|
|
26
26
|
import { check_bootstrap_status, create_bootstrap_route_specs } from '../auth/bootstrap_routes.js';
|
|
27
27
|
import { create_surface_route_spec } from '../http/common_routes.js';
|
|
28
28
|
import { flush_pending_effects, flush_post_commit_effects } from '../http/pending_effects.js';
|
|
29
|
-
import { assert_endpoint_in_auth_scope, create_auth_middleware_specs } from '../auth/middleware.js';
|
|
29
|
+
import { assert_endpoint_in_auth_scope, assert_middleware_stack_mounted, create_auth_middleware_specs } from '../auth/middleware.js';
|
|
30
30
|
import { fuz_auth_guard_resolver } from '../auth/auth_guard_resolver.js';
|
|
31
31
|
import { create_fuz_authorization_handler } from '../auth/request_context.js';
|
|
32
32
|
import { ERROR_PAYLOAD_TOO_LARGE } from '../http/error_schemas.js';
|
|
@@ -80,16 +80,53 @@ export const DEFAULT_MAX_BODY_SIZE = 1024 * 1024;
|
|
|
80
80
|
* case; consumers can call `require_audit_sse(ctx)` / `require_audit_sse(server)`
|
|
81
81
|
* to assert the invariant.
|
|
82
82
|
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
83
|
+
* Assembly acquires a few things that outlive it — the rate limiters it
|
|
84
|
+
* builds, the listeners it registers on `deps.audit`, the members it adds to
|
|
85
|
+
* `deps.connection_closer` — and records a release for each as it goes. When
|
|
86
|
+
* assembly throws, every release recorded so far runs, last acquired first
|
|
87
|
+
* (one that throws is logged and the rest still run), and the original error
|
|
88
|
+
* is rethrown: a failed assembly leaves the backend's emitter and closer as
|
|
89
|
+
* it found them and no limiter timer running. When `auth_cleanup` is set, the
|
|
90
|
+
* auth cleanup schedule starts as the last step of assembly — nothing after
|
|
91
|
+
* it can throw, so an assembly that throws leaves no schedule running.
|
|
85
92
|
*
|
|
86
93
|
* The returned `close` owns shutdown: it stops that schedule, closes every
|
|
87
|
-
* live connection on the backend's closer,
|
|
88
|
-
*
|
|
94
|
+
* live connection on the backend's closer, runs the same releases, and
|
|
95
|
+
* closes the database (`AppServer.close`).
|
|
89
96
|
*
|
|
90
97
|
* @returns assembled Hono app, backend, surface build, and bootstrap status
|
|
98
|
+
* @throws Error from any assembly step, after releasing what assembly acquired
|
|
91
99
|
*/
|
|
92
100
|
export const create_app_server = async (options) => {
|
|
101
|
+
const releases = [];
|
|
102
|
+
try {
|
|
103
|
+
return await assemble_app_server(options, releases);
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
run_releases(releases, options.backend.deps.log, 'a failed assembly');
|
|
107
|
+
throw error;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* Run `releases` last-first and empty it. Each runs in its own `try`, so one
|
|
112
|
+
* that throws is logged and the rest still run.
|
|
113
|
+
*/
|
|
114
|
+
const run_releases = (releases, log, during) => {
|
|
115
|
+
for (const release of releases.splice(0).reverse()) {
|
|
116
|
+
try {
|
|
117
|
+
release();
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
log.error(`create_app_server: a release during ${during} failed:`, error);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* The body of `create_app_server`. Every acquisition that outlives assembly
|
|
126
|
+
* pushes its release onto `releases` as it happens, so a throw at any later
|
|
127
|
+
* step unwinds exactly what was acquired.
|
|
128
|
+
*/
|
|
129
|
+
const assemble_app_server = async (options, releases) => {
|
|
93
130
|
const { backend } = options;
|
|
94
131
|
const { deps } = backend;
|
|
95
132
|
const { log } = deps;
|
|
@@ -97,9 +134,9 @@ export const create_app_server = async (options) => {
|
|
|
97
134
|
// one is a default instance under 'enforced', `null` under
|
|
98
135
|
// 'disabled_for_testing'. One instance per surface — see
|
|
99
136
|
// `AppServerOptions.login_ip_rate_limiter` for why these are not a single
|
|
100
|
-
// shared bucket. The ones built here are the server's to dispose on
|
|
137
|
+
// shared bucket. The ones built here are the server's to dispose — on
|
|
138
|
+
// close, or when assembly fails.
|
|
101
139
|
const rate_limiter_mode = options.rate_limiters ?? 'enforced';
|
|
102
|
-
const built_rate_limiters = [];
|
|
103
140
|
const resolve_rate_limiter = (option, defaults) => {
|
|
104
141
|
if (option !== undefined)
|
|
105
142
|
return option;
|
|
@@ -108,7 +145,7 @@ export const create_app_server = async (options) => {
|
|
|
108
145
|
return null;
|
|
109
146
|
}
|
|
110
147
|
const limiter = new RateLimiter({ ...defaults });
|
|
111
|
-
|
|
148
|
+
releases.push(() => limiter.dispose());
|
|
112
149
|
return limiter;
|
|
113
150
|
};
|
|
114
151
|
const login_ip_rate_limiter = resolve_rate_limiter(options.login_ip_rate_limiter, default_login_ip_rate_limit);
|
|
@@ -121,16 +158,19 @@ export const create_app_server = async (options) => {
|
|
|
121
158
|
// Factory-managed audit SSE — registers a listener on the bound emitter
|
|
122
159
|
// so SSE fan-out runs alongside the consumer's `on_audit_event`
|
|
123
160
|
// without rebuilding `AppDeps`, and adds the registry to the backend's
|
|
124
|
-
// closer so revocations close its streams.
|
|
161
|
+
// closer so revocations close its streams. The closer membership is added
|
|
162
|
+
// here rather than through `create_audit_log_sse`'s option, so its remover
|
|
163
|
+
// is the server's.
|
|
125
164
|
const audit_sse = options.audit_log_sse
|
|
126
165
|
? create_audit_log_sse({
|
|
127
166
|
log,
|
|
128
167
|
role: typeof options.audit_log_sse === 'object' ? options.audit_log_sse.role : undefined,
|
|
129
|
-
connection_closer:
|
|
168
|
+
connection_closer: null
|
|
130
169
|
})
|
|
131
170
|
: null;
|
|
132
171
|
if (audit_sse) {
|
|
133
|
-
deps.
|
|
172
|
+
releases.push(deps.connection_closer.add(create_sse_connection_closer(audit_sse.registry)));
|
|
173
|
+
releases.push(deps.audit.add_listener(audit_sse.on_audit_event));
|
|
134
174
|
}
|
|
135
175
|
// Proxy middleware
|
|
136
176
|
const proxy_spec = create_proxy_middleware_spec({ ...options.proxy, log });
|
|
@@ -140,9 +180,13 @@ export const create_app_server = async (options) => {
|
|
|
140
180
|
session_options: options.session_options,
|
|
141
181
|
daemon_token_state: options.daemon_token_state
|
|
142
182
|
});
|
|
143
|
-
|
|
183
|
+
const stack_specs = [proxy_spec, ...auth_middleware];
|
|
184
|
+
let middleware_specs = stack_specs;
|
|
144
185
|
if (options.transform_middleware) {
|
|
145
|
-
|
|
186
|
+
// the transform gets copies in a fresh array, so mutating what it was
|
|
187
|
+
// handed can't rewrite the originals the check matches against
|
|
188
|
+
middleware_specs = options.transform_middleware(stack_specs.map((spec) => ({ ...spec })));
|
|
189
|
+
assert_middleware_stack_mounted(stack_specs, middleware_specs);
|
|
146
190
|
}
|
|
147
191
|
// Bootstrap status
|
|
148
192
|
// - undefined / 'disabled': no route mounted; placeholder status.
|
|
@@ -241,6 +285,27 @@ export const create_app_server = async (options) => {
|
|
|
241
285
|
factory_routes.push(create_surface_route_spec(surface_ref));
|
|
242
286
|
}
|
|
243
287
|
const route_specs = [...consumer_routes, ...factory_routes];
|
|
288
|
+
// WS path checks — pure data, so they run before anything mounts.
|
|
289
|
+
// `register_ws_endpoint` mounts a `GET path` upgrade route: a duplicate
|
|
290
|
+
// path, or one a `RouteSpec` already registered as `GET path`, would be
|
|
291
|
+
// silently shadowed by Hono's last-wins semantics — fail fast instead.
|
|
292
|
+
if (ws_mount) {
|
|
293
|
+
const route_spec_get_paths = new Set();
|
|
294
|
+
for (const r of route_specs) {
|
|
295
|
+
if (r.method === 'GET')
|
|
296
|
+
route_spec_get_paths.add(r.path);
|
|
297
|
+
}
|
|
298
|
+
const seen_paths = new Set();
|
|
299
|
+
for (const endpoint of ws_mount.endpoints) {
|
|
300
|
+
if (seen_paths.has(endpoint.path)) {
|
|
301
|
+
throw new Error(`create_app_server: duplicate ws_endpoints path: ${endpoint.path}`);
|
|
302
|
+
}
|
|
303
|
+
if (route_spec_get_paths.has(endpoint.path)) {
|
|
304
|
+
throw new Error(`create_app_server: ws_endpoints path collides with a GET RouteSpec: ${endpoint.path}`);
|
|
305
|
+
}
|
|
306
|
+
seen_paths.add(endpoint.path);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
244
309
|
// Surface + logging
|
|
245
310
|
const surface_middleware = options.post_route_middleware
|
|
246
311
|
? [...middleware_specs, ...options.post_route_middleware]
|
|
@@ -389,16 +454,6 @@ export const create_app_server = async (options) => {
|
|
|
389
454
|
// the adapter helper — built from this app, which Node's
|
|
390
455
|
// `createNodeWebSocket({app})` needs, and only when there is something to mount
|
|
391
456
|
const upgrade_websocket = ws_mount.create_upgrade_websocket(app);
|
|
392
|
-
// Cross-surface collision: `register_ws_endpoint` mounts a `GET path`
|
|
393
|
-
// upgrade route. If a `RouteSpec` already registered `GET path`,
|
|
394
|
-
// Hono's last-wins semantics would silently shadow the consumer's
|
|
395
|
-
// GET route — fail fast instead.
|
|
396
|
-
const route_spec_get_paths = new Set();
|
|
397
|
-
for (const r of route_specs) {
|
|
398
|
-
if (r.method === 'GET')
|
|
399
|
-
route_spec_get_paths.add(r.path);
|
|
400
|
-
}
|
|
401
|
-
const seen_paths = new Set();
|
|
402
457
|
// Dedupe `auth_guard` wiring by transport reference — two specs
|
|
403
458
|
// sharing one transport instance get a single listener,
|
|
404
459
|
// otherwise revocation events would fire `close_sockets_for_*`
|
|
@@ -409,13 +464,6 @@ export const create_app_server = async (options) => {
|
|
|
409
464
|
// disable, every spec sharing the transport must pass `auth_guard: false`.
|
|
410
465
|
const guarded_transports = new WeakSet();
|
|
411
466
|
for (const endpoint of ws_mount.endpoints) {
|
|
412
|
-
if (seen_paths.has(endpoint.path)) {
|
|
413
|
-
throw new Error(`create_app_server: duplicate ws_endpoints path: ${endpoint.path}`);
|
|
414
|
-
}
|
|
415
|
-
if (route_spec_get_paths.has(endpoint.path)) {
|
|
416
|
-
throw new Error(`create_app_server: ws_endpoints path collides with a GET RouteSpec: ${endpoint.path}`);
|
|
417
|
-
}
|
|
418
|
-
seen_paths.add(endpoint.path);
|
|
419
467
|
const { transport: endpoint_transport } = register_ws_endpoint({
|
|
420
468
|
app,
|
|
421
469
|
path: endpoint.path,
|
|
@@ -424,8 +472,8 @@ export const create_app_server = async (options) => {
|
|
|
424
472
|
db: deps.db,
|
|
425
473
|
actions: endpoint.actions,
|
|
426
474
|
transport: endpoint.transport,
|
|
427
|
-
//
|
|
428
|
-
connection_closer:
|
|
475
|
+
// added below instead, so the remover is the server's
|
|
476
|
+
connection_closer: null,
|
|
429
477
|
max_connections_per_account: endpoint.max_connections_per_account,
|
|
430
478
|
heartbeat: endpoint.heartbeat,
|
|
431
479
|
artificial_delay: endpoint.artificial_delay,
|
|
@@ -438,13 +486,15 @@ export const create_app_server = async (options) => {
|
|
|
438
486
|
action_account_rate_limiter
|
|
439
487
|
});
|
|
440
488
|
mounted_ws_endpoints[endpoint.path] = endpoint_transport;
|
|
489
|
+
// every revocation handler's close reaches this transport
|
|
490
|
+
releases.push(deps.connection_closer.add(endpoint_transport));
|
|
441
491
|
if (endpoint.auth_guard !== false && !guarded_transports.has(endpoint_transport)) {
|
|
442
492
|
guarded_transports.add(endpoint_transport);
|
|
443
|
-
deps.audit.add_listener(create_ws_auth_guard(endpoint_transport, log));
|
|
493
|
+
releases.push(deps.audit.add_listener(create_ws_auth_guard(endpoint_transport, log)));
|
|
444
494
|
}
|
|
445
495
|
if (endpoint.extra_audit_handlers?.length) {
|
|
446
496
|
for (const handler of endpoint.extra_audit_handlers) {
|
|
447
|
-
deps.audit.add_listener(handler);
|
|
497
|
+
releases.push(deps.audit.add_listener(handler));
|
|
448
498
|
}
|
|
449
499
|
}
|
|
450
500
|
}
|
|
@@ -461,8 +511,10 @@ export const create_app_server = async (options) => {
|
|
|
461
511
|
}
|
|
462
512
|
}
|
|
463
513
|
// Auth cleanup — opt-in, and last: nothing after it can throw, so a failed
|
|
464
|
-
// assembly never leaves a schedule running. Its
|
|
465
|
-
// `
|
|
514
|
+
// assembly never leaves a schedule running. Its own throw (an invalid
|
|
515
|
+
// `interval_ms`) comes before any pass starts, and unwinds `releases` like
|
|
516
|
+
// any other. Its closes go through `deps.connection_closer`, which the
|
|
517
|
+
// mounts above have filled.
|
|
466
518
|
const auth_cleanup = options.auth_cleanup
|
|
467
519
|
? start_auth_cleanup(deps, options.auth_cleanup === true ? undefined : options.auth_cleanup)
|
|
468
520
|
: null;
|
|
@@ -480,8 +532,9 @@ export const create_app_server = async (options) => {
|
|
|
480
532
|
catch (error) {
|
|
481
533
|
log.error('create_app_server: closing live connections on shutdown failed:', error);
|
|
482
534
|
}
|
|
483
|
-
|
|
484
|
-
|
|
535
|
+
// then what assembly acquired — the audit listeners and closer members
|
|
536
|
+
// this server added, and the limiters it built
|
|
537
|
+
run_releases(releases, log, 'shutdown');
|
|
485
538
|
await backend.close();
|
|
486
539
|
};
|
|
487
540
|
return {
|
package/dist/testing/CLAUDE.md
CHANGED
|
@@ -33,11 +33,11 @@ time (never runtime), where a throwing guard would break `vite build`.
|
|
|
33
33
|
- `stub_mw` — pass-through middleware (`async (_c, next) => next()`).
|
|
34
34
|
- `stub_app_deps` — frozen `AppDeps`, every capability throwing, `audit` a no-op `AuditEmitter` from `create_test_audit_emitter`, `connection_closer` an empty `RealtimeCloser`.
|
|
35
35
|
- `create_stub_app_deps()` — factory: fresh `AppDeps` with no-op keyring/password/`delete_file`, a `read_secure_file` that throws ENOENT (the no-token-file state), a `create_noop_stub` DB, silent `Logger`, no-op `audit`, an empty `connection_closer`.
|
|
36
|
-
- `create_test_audit_emitter()` — no-op `AuditEmitter`; `emit` / `emit_role_grant_target` no-op, `emit_pool` resolves immediately, `notify` no-op, `add_listener` throws (use `create_recording_audit_emitter` for a listener-accepting emitter), `listener_count` returns 0.
|
|
36
|
+
- `create_test_audit_emitter()` — no-op `AuditEmitter`; `emit` / `emit_role_grant_target` no-op, `emit_pool` resolves immediately, `notify` no-op, `add_listener` throws (use `create_recording_audit_emitter` for a listener-accepting emitter), `listener_count` returns 0, `drain_inflight` resolves immediately.
|
|
37
37
|
- `create_stub_audit_sse()` — no-op `AuditLogSse` for surface-test wiring without booting real SSE. `on_audit_event` no-op (nothing is broadcast); `registry` is a fresh `SubscriberRegistry` (live `.count` / `.close_*` for registry-state tests, isolated per call). For real SSE plumbing build via `create_audit_log_sse` against `create_test_app`.
|
|
38
|
-
- `create_stub_api_middleware({include_daemon_token?})` — stub `MiddlewareSpec[]` matching `create_auth_middleware_specs`'s output (origin/session/request_context/bearer_auth, optional daemon_token) for surface generation without booting real auth. See `auth/CLAUDE.md` §Middleware for the real stack.
|
|
38
|
+
- `create_stub_api_middleware({include_daemon_token?})` — stub `MiddlewareSpec[]` matching `create_auth_middleware_specs`'s output (origin/session/request_context/bearer_auth, optional daemon_token) for surface generation without booting real auth. Each spec gets its own pass-through handler (not the shared `stub_mw`), so `assert_middleware_stack_mounted` tells the layers apart. See `auth/CLAUDE.md` §Middleware for the real stack.
|
|
39
39
|
- `create_stub_app_server_context(session_options)` — stub `AppServerContext`; rate limiters null, `bootstrap_status.available: false`.
|
|
40
|
-
- `create_test_app_surface_spec(options)` — builds an `AppSurfaceSpec` mirroring `create_app_server`'s route assembly (consumer routes + stub middleware + surface generation). `CreateTestAppSurfaceSpecOptions`: `session_options`, `create_route_specs`, `env_schema?`, `event_specs?`, `rpc_endpoints?`, `ws_endpoints?`, `allowed_origins?`, `transform_middleware?`, `bootstrap?`. Throws, like `create_app_server`, on an endpoint path outside `AUTH_MIDDLEWARE_PATH` (`assert_endpoint_in_auth_scope`). Throws on a `ws_endpoints` spec with no `allowed_origins` of its own when no `allowed_origins` option is given (there is no server list to default from). Bootstrap is opt-in (symmetric with `create_app_server` — omit to skip; pass the same value as prod to mount routes at `bootstrap.route_prefix ?? '/api/account'`). Single source of truth for attack-surface tests — track `create_app_server` wiring changes here.
|
|
40
|
+
- `create_test_app_surface_spec(options)` — builds an `AppSurfaceSpec` mirroring `create_app_server`'s route assembly (consumer routes + stub middleware + surface generation). Its middleware list mirrors the real one — a stub `trusted_proxy` spec at `'*'`, then the stub auth stack — so every route's `applicable_middleware` starts with `trusted_proxy` (a route outside `/api/*` now lists just `['trusted_proxy']`), as on the live server. `CreateTestAppSurfaceSpecOptions`: `session_options`, `create_route_specs`, `env_schema?`, `event_specs?`, `rpc_endpoints?`, `ws_endpoints?`, `allowed_origins?`, `transform_middleware?`, `bootstrap?`. Throws, like `create_app_server`, on an endpoint path outside `AUTH_MIDDLEWARE_PATH` (`assert_endpoint_in_auth_scope`) and on a `transform_middleware` that moves, drops, duplicates, reorders, wraps, or replaces the stub proxy spec or a stub auth spec (`assert_middleware_stack_mounted`); the transform receives shallow copies in a fresh array, so an in-place mutation can't slip past the check. Throws on a `ws_endpoints` spec with no `allowed_origins` of its own when no `allowed_origins` option is given (there is no server list to default from). Bootstrap is opt-in (symmetric with `create_app_server` — omit to skip; pass the same value as prod to mount routes at `bootstrap.route_prefix ?? '/api/account'`). Single source of truth for attack-surface tests — track `create_app_server` wiring changes here.
|
|
41
41
|
|
|
42
42
|
Throwing stubs surface mock escape: a test that accidentally reaches into
|
|
43
43
|
stub territory breaks immediately with a label-scoped error rather than
|
|
@@ -100,7 +100,7 @@ mismatch.
|
|
|
100
100
|
### `audit_drift_guard.ts` — audit-emission validation
|
|
101
101
|
|
|
102
102
|
- `install_audit_drift_guard()` — `beforeEach` resets + `afterEach` zero-checks `audit_metadata_validation_failures` + `audit_unknown_event_type_failures` counters from `auth/audit_log_queries.ts`. Call once at the top of any `describe_db` block firing audit emits — production validation is fail-open, so without this any regression shipping a typo'd `event_type` or undeclared metadata field is silent. Pair with `await_pending_effects: true` (the `create_test_app` default) so fire-and-forget audit writes complete by response time.
|
|
103
|
-
- `create_recording_audit_emitter(calls_ref?)` — no-op `AuditEmitter` pushing every `emit` and `emit_pool` call into `calls`. Pass `calls_ref` to write into a caller-owned array; omit to let the helper allocate. Returns `{emitter, calls}` — destructure `emitter` as the `audit` dep and read `calls` to assert. Replaces per-file capturing emitters previously duplicated across `password_change.test.ts`, `audit_log.test.ts`, etc.
|
|
103
|
+
- `create_recording_audit_emitter(calls_ref?)` — no-op `AuditEmitter` pushing every `emit` and `emit_pool` call into `calls`. Pass `calls_ref` to write into a caller-owned array; omit to let the helper allocate. Returns `{emitter, calls}` — destructure `emitter` as the `audit` dep and read `calls` to assert. `add_listener` records (never fires) and returns a remover with the production semantics, so `listener_count` tracks what a server registered and released. Replaces per-file capturing emitters previously duplicated across `password_change.test.ts`, `audit_log.test.ts`, etc.
|
|
104
104
|
- `RecordingAuditEmitter` — `{emitter: AuditEmitter; calls: Array<AuditLogInput>}`.
|
|
105
105
|
|
|
106
106
|
### `connection_closer_helpers.ts` — `ConnectionCloser` test doubles
|
|
@@ -187,8 +187,9 @@ vitest project, once per run under `isolate: false`, ../../../docs/usage.md §Ra
|
|
|
187
187
|
the response returns so tests can assert on side effects inline), and silent
|
|
188
188
|
logger. Override via `app_options`. `create_test_app_for_bootstrap` disables
|
|
189
189
|
the limiters the same way. `cleanup()` is the assembled server's idempotent
|
|
190
|
-
`close` — it also closes the server's live connections
|
|
191
|
-
limiters it built
|
|
190
|
+
`close` — it also closes the server's live connections, disposes the
|
|
191
|
+
limiters it built, and removes the audit listeners and closer members it
|
|
192
|
+
added.
|
|
192
193
|
|
|
193
194
|
`auth_cleanup` is left at its default, **off**, here and in
|
|
194
195
|
`create_test_app_for_bootstrap`: a background pass would delete rows and
|
|
@@ -978,10 +979,11 @@ source of truth for wire-shape conformance.
|
|
|
978
979
|
same TCP write as the upgrade request reach the socket; `false` Bun, whose
|
|
979
980
|
HTTP parser answers such a request `400`, and `false` in-process, where there
|
|
980
981
|
is no socket to write raw bytes to).
|
|
981
|
-
`ws_account_actions`
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
982
|
+
`ws_account_actions` (the WS endpoint mounts the account actions — `true` on
|
|
983
|
+
fuz_app's own spine presets, `false` in the family defaults) gates the WS
|
|
984
|
+
round-trip suite's self-revocation case and, with `rpc_path`, its
|
|
985
|
+
WS-mutation audit case (which calls `_testing_drain_effects`);
|
|
986
|
+
`ws_self_revocation_reply` says what the self-revocation case requires: the reply ahead of the close (`true`, the TS
|
|
985
987
|
family) or the close alone (`false`, the Rust family, whose socket loop
|
|
986
988
|
drops the response once the connection is closed — a recorded divergence).
|
|
987
989
|
|
|
@@ -1126,11 +1128,15 @@ time**, so the negative upgrade cases assert the upgrade itself rejects, not
|
|
|
1126
1128
|
a per-message error; the close cases prove a revocation closes an
|
|
1127
1129
|
already-open socket, since per-message dispatch never re-checks credential
|
|
1128
1130
|
validity. Omit `rpc_path` to skip the close cases (consumers without the
|
|
1129
|
-
standard account and admin actions on their RPC endpoint).
|
|
1131
|
+
standard account and admin actions on their RPC endpoint). Two cases are gated
|
|
1130
1132
|
on `capabilities.ws_account_actions` (the WS endpoint mounts the account
|
|
1131
1133
|
actions): a socket that revokes its own sessions over that socket is closed
|
|
1132
1134
|
with `WS_CLOSE_SESSION_REVOKED`, and — where the backend declares
|
|
1133
|
-
`capabilities.ws_self_revocation_reply` — reads the reply first
|
|
1135
|
+
`capabilities.ws_self_revocation_reply` — reads the reply first; and (with
|
|
1136
|
+
`rpc_path`) a socket mints an API token over WS, and its `token_create` audit
|
|
1137
|
+
row is read back after `_testing_drain_effects` — a WS reply can precede its
|
|
1138
|
+
audit write, so the drain is the barrier (the binary mounts it via
|
|
1139
|
+
`create_testing_actions`).
|
|
1134
1140
|
Otherwise **consumer-agnostic** — it drives only the `heartbeat` protocol action
|
|
1135
1141
|
(guaranteed on every WS endpoint by `assert_ws_endpoints_include_protocol_actions`),
|
|
1136
1142
|
so it validates the transport without touching domain WS methods. Gated on
|
|
@@ -1449,18 +1455,25 @@ are `src/test/auth/cell_crud_parity.db.test.ts`
|
|
|
1449
1455
|
`testing_reset_actions.ts` TSDoc for the audit + WS fan-out rationale
|
|
1450
1456
|
that rejected a `_testing_seed_role_grant` shape.
|
|
1451
1457
|
|
|
1452
|
-
Same module also exports `create_testing_drain_effects_action()` — the
|
|
1458
|
+
Same module also exports `create_testing_drain_effects_action(audit)` — the
|
|
1453
1459
|
`_testing_drain_effects` RPC action (daemon-token-gated, like
|
|
1454
|
-
`_testing_reset`). It awaits
|
|
1455
|
-
|
|
1456
|
-
cross-process audit assertion fires before reading (no poll/sleep).
|
|
1457
|
-
|
|
1458
|
-
`
|
|
1459
|
-
|
|
1460
|
-
`
|
|
1461
|
-
|
|
1462
|
-
in
|
|
1463
|
-
|
|
1460
|
+
`_testing_reset`). It awaits `audit.drain_inflight()` so a following
|
|
1461
|
+
`audit_log_list` is authoritative — the deterministic barrier a
|
|
1462
|
+
cross-process audit assertion fires before reading (no poll/sleep). The
|
|
1463
|
+
emitter must be built with `create_audit_emitter({track_inflight: true})`
|
|
1464
|
+
(the spine binary's `audit_factory` does), or the drain resolves at once.
|
|
1465
|
+
The barrier is needed whatever the transport: HTTP on a binary running
|
|
1466
|
+
`await_pending_effects: true` settles a mutation's writes before
|
|
1467
|
+
responding, but WS replies before its effects flush, so a WS mutation's
|
|
1468
|
+
audit write can still be in flight when its reply arrives. The drain waits
|
|
1469
|
+
until no tracked `emit` write is outstanding — writes started while it
|
|
1470
|
+
waits included — the same wait-for-zero as the Rust spine's
|
|
1471
|
+
`AuditEmitter::drain_inflight` over `new_with_inflight_tracking`.
|
|
1472
|
+
`create_testing_actions` bundles it over `deps.audit`; suites that mount
|
|
1473
|
+
their own endpoint (e.g. the in-process
|
|
1474
|
+
`account_lifecycle_parity.db.test.ts`) add it directly, over a tracked
|
|
1475
|
+
emitter, so the shared suite body can call the barrier on every backend
|
|
1476
|
+
uniformly.
|
|
1464
1477
|
|
|
1465
1478
|
Also bundled: `_testing_mint_session` — mints a backdated-expiry
|
|
1466
1479
|
`auth_session` row for an account (via `mint_test_session` in `app_server.ts`)
|
|
@@ -302,7 +302,7 @@ export interface TestApp {
|
|
|
302
302
|
create_daemon_token_headers: (extra?: Record<string, string>) => Record<string, string>;
|
|
303
303
|
/** Create an additional account with credentials. */
|
|
304
304
|
create_account: (options?: CreateTestAppAccountArgs) => Promise<TestAccount>;
|
|
305
|
-
/** Cleanup resources — `AppServer.close`: stops an opted-in auth cleanup schedule, closes live connections, disposes the limiters the server built, then the backend's `close`. Idempotent. */
|
|
305
|
+
/** Cleanup resources — `AppServer.close`: stops an opted-in auth cleanup schedule, closes live connections, disposes the limiters the server built and removes the audit listeners and closer members it added, then the backend's `close`. Idempotent. */
|
|
306
306
|
cleanup: () => Promise<void>;
|
|
307
307
|
}
|
|
308
308
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app_server.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/app_server.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"app_server.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/app_server.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAE7B;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAGjC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAInD,OAAO,EAA4B,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE5E,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAU5D,OAAO,EAA+B,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC7F,OAAO,EAAkB,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAG3E,OAAO,EAEN,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAEN,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAOvD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAGhE;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,gBAIhC,CAAC;AAEF,gFAAgF;AAChF,eAAO,MAAM,kBAAkB,QAAiB,CAAC;AA0CjD;;;;;GAKG;AACH,MAAM,WAAW,uCAAuC;IACvD,EAAE,EAAE,EAAE,CAAC;IACP,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACtB,+FAA+F;IAC/F,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,2DAA2D;AAC3D,MAAM,MAAM,0BAA0B,GAAG,uCAAuC,CAAC;AAEjF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,oCAAoC,GAChD,SAAS,uCAAuC,KAC9C,OAAO,CAAC;IACV,OAAO,EAAE;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,KAAK,EAAE;QAAE,EAAE,EAAE,IAAI,CAAA;KAAE,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACvB,CAqDA,CAAC;AAEF,uCAAuC;AACvC,MAAM,WAAW,sBAAsB;IACtC,EAAE,EAAE,EAAE,CAAC;IACP,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,6CAA6C;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;;;;;OASG;IACH,kBAAkB,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iBAAiB,GAC7B,SAAS,sBAAsB,KAC7B,OAAO,CAAC;IAAE,cAAc,EAAE,MAAM,CAAA;CAAE,CAQpC,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,qBAAqB,GACjC,SAAS,0BAA0B,KACjC,OAAO,CAAC;IACV,OAAO,EAAE;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,KAAK,EAAE;QAAE,EAAE,EAAE,IAAI,CAAA;KAAE,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACvB,CAQA,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,aAAc,SAAQ,UAAU;IAChD,gCAAgC;IAChC,OAAO,EAAE;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,uCAAuC;IACvC,KAAK,EAAE;QAAE,EAAE,EAAE,IAAI,CAAA;KAAE,CAAC;IACpB,qCAAqC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,cAAc,EAAE,MAAM,CAAC;IACvB,+FAA+F;IAC/F,OAAO,EAAE,OAAO,CAAC;IACjB,4EAA4E;IAC5E,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACpC,mDAAmD;IACnD,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,kGAAkG;IAClG,EAAE,CAAC,EAAE,EAAE,CAAC;IACR,0FAA0F;IAC1F,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;;;OASG;IACH,oBAAoB,CAAC,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC;IACzD,yHAAyH;IACzH,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gDAAgD;IAChD,KAAK,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACtB;;;;;;;;;;;;;;OAcG;IACH,aAAa,CAAC,EAAE,YAAY,CAAC;CAC7B;AAkJD,eAAO,MAAM,sBAAsB,GAClC,SAAS,oBAAoB,KAC3B,OAAO,CAAC,aAAa,CA2BvB,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,oBAAoB;IACjE,yEAAyE;IACzE,kBAAkB,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IACpE;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,uBAAuB,CAAC;IACxC;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,EAAE,sBAAsB,CAAC;IACnC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,eAAe,CAAC;CAC9B;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,CACpC,IAAI,CACH,gBAAgB,EAChB,SAAS,GAAG,iBAAiB,GAAG,oBAAoB,GAAG,eAAe,GAAG,WAAW,CACpF,CACD,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,WAAW;IAC3B,OAAO,EAAE;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,KAAK,EAAE;QAAE,EAAE,EAAE,IAAI,CAAA;KAAE,CAAC;IACpB,mCAAmC;IACnC,cAAc,EAAE,MAAM,CAAC;IACvB,qCAAqC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,sBAAsB,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnF,8DAA8D;IAC9D,qBAAqB,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClF;AAED;;;;;GAKG;AACH,MAAM,WAAW,wBAAwB;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACtB,+FAA+F;IAC/F,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACvB,GAAG,EAAE,IAAI,CAAC;IACV,OAAO,EAAE,aAAa,CAAC;IACvB,YAAY,EAAE,cAAc,CAAC;IAC7B,OAAO,EAAE,UAAU,CAAC;IACpB,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAC9B,kEAAkE;IAClE,sBAAsB,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnF,gEAAgE;IAChE,qBAAqB,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClF,iEAAiE;IACjE,2BAA2B,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxF,qDAAqD;IACrD,cAAc,EAAE,CAAC,OAAO,CAAC,EAAE,wBAAwB,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAC7E,2PAA2P;IAC3P,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AAmBD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,eAAe,GAAU,SAAS,oBAAoB,KAAG,OAAO,CAAC,OAAO,CAiGpF,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,WAAW,gCAAgC;IAChD,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,kBAAkB,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IACpE,aAAa,CAAC,EAAE,uBAAuB,CAAC;IACxC,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,8EAA8E;IAC9E,SAAS,EAAE,oBAAoB,CAAC;IAChC;;;;OAIG;IACH,eAAe,EAAE,MAAM,CAAC;IACxB,EAAE,CAAC,EAAE,EAAE,CAAC;IACR,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,aAAa,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IACnC,GAAG,EAAE,IAAI,CAAC;IACV,OAAO,EAAE,UAAU,CAAC;IACpB,YAAY,EAAE,cAAc,CAAC;IAC7B,OAAO,EAAE,UAAU,CAAC;IACpB,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAC9B,0EAA0E;IAC1E,sBAAsB,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnF,4EAA4E;IAC5E,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,6BAA6B,GACzC,SAAS,gCAAgC,KACvC,OAAO,CAAC,mBAAmB,CAmE7B,CAAC"}
|
|
@@ -53,7 +53,7 @@ export interface StandardAttackSurfaceOptions {
|
|
|
53
53
|
snapshot_path: string;
|
|
54
54
|
/** Expected public routes, e.g. `['GET /health', 'POST /api/account/login']`. */
|
|
55
55
|
expected_public_routes: Array<string>;
|
|
56
|
-
/** Expected middleware names for API routes, e.g. `['origin', 'session', 'request_context', 'bearer_auth']`. */
|
|
56
|
+
/** Expected middleware names for API routes, e.g. `['trusted_proxy', 'origin', 'session', 'request_context', 'bearer_auth']`. */
|
|
57
57
|
expected_api_middleware: Array<string>;
|
|
58
58
|
/** All roles in the app (e.g. `['admin', 'keeper']`). */
|
|
59
59
|
roles: Array<string>;
|