@fuzdev/fuz_app 0.125.0 → 0.127.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.
Files changed (94) hide show
  1. package/dist/actions/CLAUDE.md +56 -20
  2. package/dist/actions/action_rpc.d.ts +14 -11
  3. package/dist/actions/action_rpc.d.ts.map +1 -1
  4. package/dist/actions/action_rpc.js +5 -4
  5. package/dist/actions/connection_closer.d.ts +13 -3
  6. package/dist/actions/connection_closer.d.ts.map +1 -1
  7. package/dist/actions/connection_closer.js +7 -5
  8. package/dist/actions/register_action_ws.d.ts +18 -13
  9. package/dist/actions/register_action_ws.d.ts.map +1 -1
  10. package/dist/actions/register_action_ws.js +8 -6
  11. package/dist/actions/register_ws_endpoint.d.ts +6 -3
  12. package/dist/actions/register_ws_endpoint.d.ts.map +1 -1
  13. package/dist/actions/register_ws_endpoint.js +6 -3
  14. package/dist/actions/transports.d.ts +9 -0
  15. package/dist/actions/transports.d.ts.map +1 -1
  16. package/dist/actions/transports.js +9 -0
  17. package/dist/actions/transports_ws_backend.d.ts +15 -0
  18. package/dist/actions/transports_ws_backend.d.ts.map +1 -1
  19. package/dist/actions/transports_ws_backend.js +25 -5
  20. package/dist/actions/ws_endpoint_spec.d.ts +24 -4
  21. package/dist/actions/ws_endpoint_spec.d.ts.map +1 -1
  22. package/dist/actions/ws_endpoint_spec.js +15 -1
  23. package/dist/auth/middleware.d.ts +29 -1
  24. package/dist/auth/middleware.d.ts.map +1 -1
  25. package/dist/auth/middleware.js +35 -1
  26. package/dist/http/CLAUDE.md +3 -3
  27. package/dist/http/surface.d.ts +12 -9
  28. package/dist/http/surface.d.ts.map +1 -1
  29. package/dist/rate_limiter.d.ts +43 -3
  30. package/dist/rate_limiter.d.ts.map +1 -1
  31. package/dist/rate_limiter.js +27 -3
  32. package/dist/realtime/sse_auth_guard.d.ts +2 -1
  33. package/dist/realtime/sse_auth_guard.d.ts.map +1 -1
  34. package/dist/realtime/sse_auth_guard.js +4 -2
  35. package/dist/realtime/subscriber_registry.d.ts +12 -0
  36. package/dist/realtime/subscriber_registry.d.ts.map +1 -1
  37. package/dist/realtime/subscriber_registry.js +18 -2
  38. package/dist/server/app_server.d.ts +128 -55
  39. package/dist/server/app_server.d.ts.map +1 -1
  40. package/dist/server/app_server.js +110 -61
  41. package/dist/server/app_server_context.d.ts +17 -9
  42. package/dist/server/app_server_context.d.ts.map +1 -1
  43. package/dist/testing/CLAUDE.md +83 -25
  44. package/dist/testing/app_server.d.ts +6 -3
  45. package/dist/testing/app_server.d.ts.map +1 -1
  46. package/dist/testing/app_server.js +20 -20
  47. package/dist/testing/connection_closer_helpers.d.ts +10 -4
  48. package/dist/testing/connection_closer_helpers.d.ts.map +1 -1
  49. package/dist/testing/connection_closer_helpers.js +4 -0
  50. package/dist/testing/cross_backend/capabilities.d.ts +3 -3
  51. package/dist/testing/cross_backend/default_backend_configs.d.ts +12 -12
  52. package/dist/testing/cross_backend/default_backend_configs.d.ts.map +1 -1
  53. package/dist/testing/cross_backend/default_backend_configs.js +11 -10
  54. package/dist/testing/cross_backend/full_spine_mount.d.ts +35 -11
  55. package/dist/testing/cross_backend/full_spine_mount.d.ts.map +1 -1
  56. package/dist/testing/cross_backend/full_spine_mount.js +26 -9
  57. package/dist/testing/cross_backend/rust_spine_stub_backend_config.d.ts +16 -1
  58. package/dist/testing/cross_backend/rust_spine_stub_backend_config.d.ts.map +1 -1
  59. package/dist/testing/cross_backend/rust_spine_stub_backend_config.js +5 -4
  60. package/dist/testing/cross_backend/spine_surface_constants.d.ts +43 -3
  61. package/dist/testing/cross_backend/spine_surface_constants.d.ts.map +1 -1
  62. package/dist/testing/cross_backend/spine_surface_constants.js +43 -3
  63. package/dist/testing/cross_backend/testing_backdoor.d.ts +15 -1
  64. package/dist/testing/cross_backend/testing_backdoor.d.ts.map +1 -1
  65. package/dist/testing/cross_backend/testing_backdoor.js +51 -6
  66. package/dist/testing/cross_backend/testing_reset_actions.d.ts +6 -3
  67. package/dist/testing/cross_backend/testing_reset_actions.d.ts.map +1 -1
  68. package/dist/testing/cross_backend/testing_reset_actions.js +6 -3
  69. package/dist/testing/cross_backend/testing_server_bun.d.ts.map +1 -1
  70. package/dist/testing/cross_backend/testing_server_bun.js +5 -1
  71. package/dist/testing/cross_backend/testing_server_core.d.ts +72 -41
  72. package/dist/testing/cross_backend/testing_server_core.d.ts.map +1 -1
  73. package/dist/testing/cross_backend/testing_server_core.js +22 -14
  74. package/dist/testing/cross_backend/testing_server_deno.js +1 -1
  75. package/dist/testing/cross_backend/testing_server_node.d.ts.map +1 -1
  76. package/dist/testing/cross_backend/testing_server_node.js +20 -7
  77. package/dist/testing/cross_backend/ts_spine_backend_config.d.ts +15 -2
  78. package/dist/testing/cross_backend/ts_spine_backend_config.d.ts.map +1 -1
  79. package/dist/testing/cross_backend/ts_spine_backend_config.js +10 -8
  80. package/dist/testing/cross_backend/ws_action_rate_limit.d.ts +26 -0
  81. package/dist/testing/cross_backend/ws_action_rate_limit.d.ts.map +1 -0
  82. package/dist/testing/cross_backend/ws_action_rate_limit.js +261 -0
  83. package/dist/testing/middleware.d.ts.map +1 -1
  84. package/dist/testing/middleware.js +4 -3
  85. package/dist/testing/stubs.d.ts +17 -4
  86. package/dist/testing/stubs.d.ts.map +1 -1
  87. package/dist/testing/stubs.js +46 -13
  88. package/dist/testing/transports/ws_transport.d.ts +7 -0
  89. package/dist/testing/transports/ws_transport.d.ts.map +1 -1
  90. package/dist/testing/transports/ws_transport.js +1 -1
  91. package/dist/testing/ws_round_trip.d.ts +43 -37
  92. package/dist/testing/ws_round_trip.d.ts.map +1 -1
  93. package/dist/testing/ws_round_trip.js +28 -46
  94. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"app_server_context.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/server/app_server_context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAEjE,8CAA8C;AAC9C,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,UAAU,CAAC;IACpB,gBAAgB,EAAE,eAAe,CAAC;IAClC,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC;;;;OAIG;IACH,qBAAqB,EAAE,WAAW,GAAG,IAAI,CAAC;IAC1C,6EAA6E;IAC7E,sBAAsB,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3C,gFAAgF;IAChF,yBAAyB,EAAE,WAAW,GAAG,IAAI,CAAC;IAC9C,iFAAiF;IACjF,0BAA0B,EAAE,WAAW,GAAG,IAAI,CAAC;IAC/C,kFAAkF;IAClF,2BAA2B,EAAE,WAAW,GAAG,IAAI,CAAC;IAChD,uGAAuG;IACvG,sBAAsB,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3C,0GAA0G;IAC1G,2BAA2B,EAAE,WAAW,GAAG,IAAI,CAAC;IAChD;;;;OAIG;IACH,SAAS,EAAE,WAAW,GAAG,IAAI,CAAC;CAC9B"}
1
+ {"version":3,"file":"app_server_context.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/server/app_server_context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAEjE,8CAA8C;AAC9C,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,UAAU,CAAC;IACpB,gBAAgB,EAAE,eAAe,CAAC;IAClC,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC;;;;;;;;;OASG;IACH,qBAAqB,EAAE,WAAW,GAAG,IAAI,CAAC;IAC1C,wDAAwD;IACxD,sBAAsB,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3C,2DAA2D;IAC3D,yBAAyB,EAAE,WAAW,GAAG,IAAI,CAAC;IAC9C,4DAA4D;IAC5D,0BAA0B,EAAE,WAAW,GAAG,IAAI,CAAC;IAC/C,6DAA6D;IAC7D,2BAA2B,EAAE,WAAW,GAAG,IAAI,CAAC;IAChD,iGAAiG;IACjG,sBAAsB,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3C;;;OAGG;IACH,2BAA2B,EAAE,WAAW,GAAG,IAAI,CAAC;IAChD;;;;OAIG;IACH,SAAS,EAAE,WAAW,GAAG,IAAI,CAAC;CAC9B"}
@@ -36,8 +36,8 @@ time (never runtime), where a throwing guard would break `vite build`.
36
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.
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
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.
39
- - `create_stub_app_server_context(session_options)` — stub `AppServerContext`; rate limiters null, `bootstrap_status.available: false`, `app_settings.open_signup: 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?`, `transform_middleware?`, `bootstrap?`. 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.
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.
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
@@ -105,9 +105,9 @@ mismatch.
105
105
 
106
106
  ### `connection_closer_helpers.ts` — `ConnectionCloser` test doubles
107
107
 
108
- - `create_recording_closer()` — `{closer, calls}`; every method on `closer` records `{method, id}` into `calls` and closes nothing. To see a handler's closes, add it to the backend's closer (`ctx.deps.connection_closer.add(closer)`) or build the factory's deps with it. The closes are queued post-commit, so they have run by the time a `create_test_app` response is in hand (`await_pending_effects: true` flushes both queues).
108
+ - `create_recording_closer()` — `{closer, calls}`; every method on `closer` records `{method, id}` into `calls` and closes nothing (`close_all_sockets` records `{method: 'all', id: null}`). To see a handler's closes, add it to the backend's closer (`ctx.deps.connection_closer.add(closer)`) or build the factory's deps with it. The closes are queued post-commit, so they have run by the time a `create_test_app` response is in hand (`await_pending_effects: true` flushes both queues).
109
109
  - `assert_close_call(call, method, id)` — pins `{method, id}` on a recorded close call; handles the missing-element case.
110
- - `RecordedClose` — `{method: 'session' | 'token' | 'account', id}`.
110
+ - `RecordedClose` — `{method: 'session' | 'token' | 'account', id: string} | {method: 'all', id: null}`.
111
111
  - `RecordingCloser` — `{closer, calls}`.
112
112
 
113
113
  ## Database — `db.ts`
@@ -178,11 +178,17 @@ Types:
178
178
 
179
179
  `create_test_app` hard-codes the test-friendly `AppServerOptions`:
180
180
  `allowed_origins: [/^http:\/\/localhost/]`, stub proxy pinned to `127.0.0.1`,
181
- `env_schema: z.object({})`, every rate limiter `null`, static daemon token
182
- state (no rotation, keeper already set),
181
+ `env_schema: z.object({})`, `rate_limiters: 'disabled_for_testing'` (every
182
+ rate limiter `null` — a limiter passed through `app_options` wins over the
183
+ mode, so a rate-limit test enables just the one it pins; the mode's stderr
184
+ banner prints once per module instance — once per test file in an isolated
185
+ vitest project, once per run under `isolate: false`, ../../../docs/usage.md §Rate limiters), static daemon token state (no rotation, keeper already set),
183
186
  **`await_pending_effects: true`** (fire-and-forget effects complete before
184
187
  the response returns so tests can assert on side effects inline), and silent
185
- logger. Override via `app_options`.
188
+ logger. Override via `app_options`. `create_test_app_for_bootstrap` disables
189
+ the limiters the same way. `cleanup()` is the assembled server's idempotent
190
+ `close` — it also closes the server's live connections and disposes the
191
+ limiters it built.
186
192
 
187
193
  `auth_cleanup` is left at its default, **off**, here and in
188
194
  `create_test_app_for_bootstrap`: a background pass would delete rows and
@@ -539,13 +545,14 @@ In-process test driver for `register_action_ws`. Consumers pass specs +
539
545
  handlers, receive `{transport, connect()}` back. The full dispatch path is
540
546
  exercised (per-action auth, input validation, `ctx.notify`, broadcast via
541
547
  `BackendWebsocketTransport`, close-on-revoke), but Hono's wire upgrade is
542
- skipped (the Node test runtime has no `@hono/node-ws` adapter).
548
+ skipped — there is no server, so no runtime adapter; the cross-process suites
549
+ cover real sockets.
543
550
 
544
551
  Three layers:
545
552
 
546
- 1. **Primitives** — `create_fake_ws()`, `create_fake_hono_context(opts)`, `create_stub_upgrade()`, `MinimalActionEnvironment`, `dispatch_ws_message(on_message, event, ws)`. The fake context sets the keys the production auth middleware sets — `AUTH_SESSION_TOKEN_HASH_KEY` included, as `hash_session_token(auth_session_id)` — because the dispatcher reads the credential through `get_resolved_auth(c)`; a hand-built upgrade context must do the same.
553
+ 1. **Primitives** — `create_fake_ws()`, `create_fake_hono_context(opts)`, `create_stub_upgrade()`, `MinimalActionEnvironment`, `dispatch_ws_message(on_message, event, ws)`. The fake context sets the keys the production auth middleware sets — `AUTH_SESSION_TOKEN_HASH_KEY` included, as `hash_session_token(auth_session_id)` — because the dispatcher reads the credential through `get_resolved_auth(c)`; a hand-built upgrade context must do the same. `create_stub_upgrade()` stands in for a runtime adapter's `upgradeWebSocket`: it passes a request without `Upgrade: websocket` to `next()`, and records an upgrade request — its real `Context` and the endpoint's events factory — in `upgrades`, answering `200`. So a test can send `app.request('/api/ws', {headers: {upgrade: 'websocket', cookie | authorization, origin, 'x-forwarded-for'}})` through an assembled app's whole middleware chain and build the socket's events from the `Context` that chain produced (`src/test/server/create_app_server_ws_endpoints.dispatch.db.test.ts`); `get_create_events()` still returns the last mounted factory, for a hand-built context.
547
554
  2. **Harness** — `create_ws_test_harness({actions, transport?, heartbeat?, log?, on_socket_open?, on_socket_close?})` → `WsTestHarness`. `connect(identity?)` is async and resolves after the connection is admitted and `on_socket_open` completes, so broadcasts sent immediately after `await harness.connect()` reach the client. The harness pre-bakes its `RequestContext` (`TEST_CONTEXT_PRESET_KEY`), which also skips the admission credential re-read — there are no session or token rows behind a harness identity — so tests of the re-read itself drive `register_action_ws` with a real database and no preset (`src/test/actions/register_action_ws.admission.db.test.ts`). The harness threads its own `create_stub_db()` into the dispatcher's `db` slot so handlers declaring `side_effects: true` execute under the same transaction wrap they would in production (the stub's `transaction(fn)` synchronously calls `fn(stub_db)`); domain deps reach handlers via factory closures, the same way HTTP RPC factories already wire them. Audit fan-out runs through whatever `audit` emitter the consumer supplied to its action factory closure (typically `create_test_audit_emitter()` for unit harnesses).
548
- 3. **Round-trip helpers** — predicates + wire-frame types live in `transports/ws_client.ts` (shared with the cross-process `ws_transport.ts` impl): `is_notification(method)`, `is_notification_with<P>(method, match)` (type-guard combinator — narrows `wait_for` return type), `is_response_for(id)`, `JsonrpcNotificationFrame<P>` / `JsonrpcSuccessResponseFrame<R>` / `JsonrpcErrorResponseFrame<D>` (typed wire-frame shapes distinct from the runtime Zod schemas in `http/jsonrpc.ts` — generic over `params` / `result` / `data` so tests narrow without casts). `build_broadcast_api<TApi>({harness, specs})` (in `ws_round_trip.ts`) wires a typed broadcast API against the harness transport.
555
+ 3. **Round-trip helpers** — predicates + wire-frame types live in `transports/ws_client.ts` (shared with the cross-process `ws_transport.ts` impl): `is_notification(method)`, `is_notification_with<P>(method, match)` (type-guard combinator — narrows `wait_for` return type), `is_response_for(id)`, `JsonrpcNotificationFrame<P>` / `JsonrpcSuccessResponseFrame<R>` / `JsonrpcErrorResponseFrame<D>` (typed wire-frame shapes distinct from the runtime Zod schemas in `http/jsonrpc.ts` — generic over `params` / `result` / `data` so tests narrow without casts).
549
556
 
550
557
  `WsClient` (in `transports/ws_client.ts`):
551
558
  `{send, request<R>, close, messages, wait_for, wait_for_close, close_code, close_reason}`.
@@ -566,8 +573,6 @@ of undefined`). `wait_for(predicate, timeout_ms?)` checks already-received
566
573
  messages first, then waits for new arrivals (default 1000ms); drops the
567
574
  waiter on timeout so the `waiters` array doesn't grow.
568
575
 
569
- `keeper_identity()` — convenience for `{credential_type: 'daemon_token', roles: [ROLE_KEEPER]}`.
570
-
571
576
  ## Data exposure + rate limiting
572
577
 
573
578
  ### `data_exposure.ts` — `describe_data_exposure_tests`
@@ -675,8 +680,7 @@ the same `RpcEndpointsSuiteOption` union every DB-backed suite accepts
675
680
  raw to the top-level `rpc_endpoints` slot on `CreateTestAppOptions` so
676
681
  `create_app_server` resolves it per-test with the real ctx — the only way
677
682
  action handlers can close over
678
- `ctx.deps` / `ctx.app_settings` (e.g. `create_standard_rpc_actions(ctx.deps,
679
- {app_settings: ctx.app_settings})`). Factory must return the same endpoint
683
+ `ctx.deps` (e.g. `create_standard_rpc_actions(ctx.deps)`). Factory must return the same endpoint
680
684
  `path` regardless of ctx — `resolve_rpc_endpoints_for_setup` invokes it once
681
685
  with a stub ctx for path lookup and `create_app_server` invokes it again
682
686
  per-test for live dispatch.
@@ -1381,12 +1385,14 @@ are `src/test/auth/cell_crud_parity.db.test.ts`
1381
1385
  request (`{result}` / `{error}` / `undefined` to swallow), the path
1382
1386
  `describe_peer_ping_ws_tests` drives. With no `on_request` the seam is inert
1383
1387
  (a server-initiated request flows to `messages` as before).
1384
- - `testing/transports/ws_transport.ts` — `create_ws_transport({base_url, ws_path, cookies, origin?, on_request?})`
1388
+ - `testing/transports/ws_transport.ts` — `create_ws_transport({base_url, ws_path, cookies, origin?, on_request?, headers?})`
1385
1389
  builds a real-upgrade WS client using the `ws` npm package (optional
1386
1390
  peerDep; consumers wiring cross-process tests `npm install --save-dev ws`).
1387
1391
  Threads the keeper cookie onto the upgrade so per-action auth succeeds on
1388
1392
  the first message. `on_request` (attached at construction, before the upgrade
1389
- completes) answers server-initiated requests via the shared `deliver_inbound`.
1393
+ completes) answers server-initiated requests via the shared `deliver_inbound`. `headers`
1394
+ adds upgrade headers — e.g. an `X-Forwarded-For`, which a backend trusting the
1395
+ loopback proxy resolves as the connection's client IP for every message.
1390
1396
  An open socket is not yet an *admitted* connection — both spines answer the
1391
1397
  handshake, then re-read the credential, then admit, and deliver no
1392
1398
  server-initiated message until then. `create_admitted_ws_transport(options)`
@@ -1587,12 +1593,15 @@ drift-guarded by `src/test/cross_backend/spine_expected_schema.db.test.ts`
1587
1593
 
1588
1594
  ### Testing-backdoor credential gate — `cross_backend/testing_backdoor.ts`
1589
1595
 
1590
- `describe_testing_backdoor_cross_tests({setup_test, rpc_path?})` —
1596
+ `describe_testing_backdoor_cross_tests({setup_test, rpc_path?, ws?})` —
1591
1597
  the negative-credential parity suite for the `_testing_*` backdoor actions.
1592
- For each of `_testing_reset` / `_testing_mint_session` / `_testing_put_fact` /
1593
- `_testing_schema_snapshot` (the three privileged writes plus the schema-dump
1594
- read) it fires three principals over real HTTP: **anonymous** → 401, **session** →
1595
- 403 `credential_type_required`, **bearer** → 403 `credential_type_required` —
1598
+ For each `_testing_*` action except `_testing_drain_effects` (the three
1599
+ privileged writes plus the three introspection reads) it fires three principals over real HTTP: **anonymous** →
1600
+ 401 `unauthenticated`, **session** → 403 `forbidden` `credential_type_required`,
1601
+ **bearer** → 403 `forbidden` `credential_type_required` — and, when `ws`
1602
+ (`{base_url, ws_path, origin?}`) is passed, sends each on a socket opened with
1603
+ the keeper's session cookie, which answers the same `forbidden`
1604
+ `credential_type_required` (a socket is no way around the daemon-token channel) —
1596
1605
  proving the daemon-token gate that fences each backdoor action holds end-to-end
1597
1606
  on the real dispatcher (the spec-derived `describe_rpc_attack_surface_tests`
1598
1607
  never enumerates them because they're off the declared surface). Each method is
@@ -1693,6 +1702,55 @@ The in-process counterparts already exist (`describe_rate_limiting_tests` plus t
1693
1702
  proxy middleware tests), so there's no in-process leg. `npm run test:cross:security`.
1694
1703
  Cited property: `docs/security.md` §"Rate Limiting" + §"Trusted Proxy / Client IP".
1695
1704
 
1705
+ ### Action rate-limit parity over WS — `cross_backend/ws_action_rate_limit.ts`
1706
+
1707
+ `describe_ws_action_rate_limit_cross_tests({setup_test, base_url, ws_path,
1708
+ rpc_path?, max_attempts})` — the imperative suite pinning **action rate
1709
+ limiting over a real WebSocket**, and its budget shared with HTTP RPC, on
1710
+ backends started with small shared action limiters (`max_attempts` is the cap
1711
+ they were started with, at least 2):
1712
+
1713
+ - **account axis over WS** — `account_token_create` (`rate_limit: 'account'`
1714
+ on both spines) with malformed params: `max_attempts` calls answer
1715
+ `invalid_params` (the throttle runs before params validation, so they charge),
1716
+ the next answers `rate_limited` with a positive `data.retry_after`.
1717
+ - **one account bucket across transports** — calls split between HTTP RPC and
1718
+ WS exhaust one budget; the call past it is refused on WS and on HTTP (`429`).
1719
+ - **IP axis keyed by the forwarded client IP** — `peer/ping` (`rate_limit:
1720
+ 'ip'`, public) with malformed params from one `X-Forwarded-For` address, over
1721
+ anonymous HTTP and over a WS whose upgrade carried the header: refused past the
1722
+ cap on both transports, while a second address keeps its own bucket on both.
1723
+ - **account axis at the dispatchers** — `cell_create` (`rate_limit:
1724
+ 'account'`, on both spines' RPC and WS mounts) with malformed params: refused
1725
+ past the cap over HTTP (`429`) and over WS (`rate_limited`), calls split
1726
+ between the two transports exhaust one budget, and a budget split between
1727
+ `cell_create` and `account_token_create` is one bucket.
1728
+
1729
+ Isolation without a limiter reset: each account case runs on the fresh keeper
1730
+ the per-test `_testing_reset` seeds (a new account id), and the IP case uses
1731
+ TEST-NET-2 addresses nothing else sends. The backends are started by the
1732
+ `enable_action_rate_limit` + `action_rate_limit_max_attempts` options on both
1733
+ backend configs (`ts_spine_*_backend_config`, `rust_spine_stub_backend_config`),
1734
+ which set `ACTION_RATE_LIMIT_ENABLED_ENV` (`FUZ_ACTION_RATE_LIMIT_ENABLED`) and
1735
+ `ACTION_RATE_LIMIT_MAX_ATTEMPTS_ENV` (`FUZ_ACTION_RATE_LIMIT_MAX_ATTEMPTS`) from
1736
+ `spine_surface_constants.ts` — both spine binaries build one IP + one account
1737
+ limiter (the action defaults' windows, the cap replacing both
1738
+ `max_attempts`) shared by RPC and WS, and refuse to boot on a cap without the
1739
+ flag. Off, neither spine builds an action limiter. Runs under the
1740
+ `cross_backend_security` dual-spawn beside the login-security suite. The TS
1741
+ spine charges every classed action in its dispatcher; the Rust stub charges
1742
+ `account_token_create` and the other auth-family specs inside their handlers
1743
+ and every other classed spec at its dispatcher states, the same limiter instances at both sites. So
1744
+ the `account_token_create` cases pin the Rust in-handler site, the IP case the
1745
+ Rust WS dispatcher's IP axis, and the `cell_create` cases the account axis of
1746
+ both Rust dispatchers, RPC and WS — reachable over WS on both spines because
1747
+ the TS spine serves its full action set on `/api/ws`, as the Rust stub serves
1748
+ one registry on both transports. The IP case's addresses are fixed per
1749
+ process and their bucket outlives `_testing_reset`, so a vitest retry of it
1750
+ would fail.
1751
+ Cross-process only; fuz_app's own wiring is
1752
+ `src/test/cross_backend/ws_action_rate_limit.cross.test.ts`.
1753
+
1696
1754
  ### Role-gated participation parity — `cross_backend/role_grant_participation.ts`
1697
1755
 
1698
1756
  The role-gated-participation capstone — TS↔Rust agreement that an **app-defined
@@ -1742,15 +1800,15 @@ The reusable shape for standing up a **spawnable TS** cross-process test
1742
1800
  binary (the TS analog of the Rust `testing_spine_stub`), so consumers don't
1743
1801
  re-roll the serve / daemon-info / WS-attach / drain boilerplate:
1744
1802
 
1745
- - `testing/cross_backend/testing_server_core.ts` — `start_testing_server({adapter, daemon_name, host, port, app_version?, build_app})`. Owns the runtime-neutral orchestration: open-host refusal, stale-daemon check, daemon-info write, `serve`, post-serve WS attach, graceful drain. Domain-free — the app is the caller's `build_app(): Promise<BuiltTestingApp>` seam (`{app, close, mount_websocket?}`). `mount_websocket(upgrade)` is invoked after the app exists + the adapter prepared WS (the mount-after-app order Node's `@hono/node-ws` forces — `create_app_server`'s `ws_endpoints` auto-mount can't be used on Node). Exports the `TestingServerAdapter` / `ServeHandle` / `PreparedWebsocket` interfaces.
1746
- - `testing/cross_backend/testing_server_node.ts` — `create_node_testing_adapter()` (`@hono/node-server` + `@hono/node-ws`). Optional peer deps (like `ws`); only test binaries import them.
1803
+ - `testing/cross_backend/testing_server_core.ts` — `start_testing_server({adapter, daemon_name, host, port, app_version?, build_app})`. Owns the runtime-neutral orchestration: open-host refusal, stale-daemon check, daemon-info write, `serve`, post-serve WS attach, graceful shutdown. Domain-free — the app is the caller's `build_app(context: BuildTestingAppContext): Promise<BuiltTestingApp>` seam (`{app, close}`). WebSocket endpoints mount through `create_app_server`'s `ws_endpoints` on every runtime: the build calls `context.prepare_websocket({max_message_bytes?})`, which asks the adapter for a `PreparedWebsocket` (`{create_upgrade_websocket: (app) => UpgradeWebSocket, attach_to_server?}`) and returns its factory, to pass as `create_upgrade_websocket`; the core runs each `attach_to_server` once `serve` returns (Node's `injectWebSocket`). Shutdown starts the listener's `shutdown` (stop accepting), runs `close` — which must end live WebSockets, as `AppServer.close` does — then awaits the drain, since open sockets would otherwise hold it. Exports the `TestingServerAdapter` (`prepare_websocket: (options?: PrepareWebsocketOptions) => PreparedWebsocket`) / `ServeHandle` / `PreparedWebsocket` / `PrepareWebsocketOptions` / `BuildTestingAppContext` interfaces.
1804
+ - `testing/cross_backend/testing_server_node.ts` — `create_node_testing_adapter()` (`@hono/node-server` + `@hono/node-ws`). Optional peer deps (like `ws`); only test binaries import them. Its factory sets the `ws` server's `maxPayload` to `max_message_bytes` (default `DEFAULT_WS_MAX_MESSAGE_BYTES`) — `@hono/node-ws` takes no option for it, and `ws`'s own default is 100 MiB — so an oversized message is refused at the frame layer (still `WS_CLOSE_MESSAGE_TOO_BIG`) before it is buffered whole. Deno and Bun ignore the option and keep the per-message check alone.
1747
1805
  - `testing/cross_backend/testing_server_deno.ts` — `create_deno_testing_adapter()` (`Deno.serve` + `@hono/deno`, an optional peer dep; `Deno` declared locally so it typechecks under the Node toolchain). Spawn the entry with `--sloppy-imports` (Deno doesn't do `.js`→`.ts`; Gro's loader does, so the Node path needs no flag).
1748
1806
  - `testing/cross_backend/testing_server_bun.ts` — `create_bun_testing_adapter()` (`Bun.serve` + `@hono/bun`'s module-level `getConnInfo`, `upgradeWebSocket`, and `websocket`; `Bun.serve` declared locally so it typechecks under the Node toolchain). Needs the optional `@hono/bun` peer dep (the counterpart to Node's `@hono/node-server` + `@hono/node-ws`; `Bun.serve` is built in), and Bun resolves `.js`→`.ts` natively (no flag, unlike Deno). Reuses `create_node_runtime` (Bun implements the `node:fs`/`node:process` surface). WS is module-level + stateless (like Deno) — the `websocket` handler is threaded into `serve`, where `Bun.serve` wants it, so no post-serve attach.
1749
1807
  - `testing/cross_backend/default_spine_surface.ts` — the canonical no-domain spine surface (account/admin/audit/signup + bootstrap): `spine_session_options`, `spine_roles`, `create_spine_route_specs`, `spine_rpc_endpoints`, `create_spine_surface_spec`. This is the **declared** surface — the `create_standard_rpc_actions` bundle the spec-derived suites auto-enumerate. `$lib`-free (it's reached by the spawned binary under Gro's loader, which doesn't resolve `$lib`), so keep it on relative imports. Shared by the spine_stub cross test, the TS cross tests, and the binary.
1750
- - `testing/cross_backend/full_spine_mount.ts` — `build_full_spine_rpc_actions(deps, options)` / `full_spine_rpc_endpoints(ctx, options)` — the **full** live RPC mount: the declared bundle **plus** the off-declared-surface families the binary live-mounts (`_testing_*` backdoors, the cell verb set, the opt-in `actor_lookup` / `actor_search` resolvers). Single-sources what was an inline assembly in `testing_spine_server.ts`, so the binary and the `spine_method_coverage` reconciliation test build the same list. Also `$lib`-free.
1808
+ - `testing/cross_backend/full_spine_mount.ts` — `build_full_spine_rpc_actions(deps, options)` — the **full** live RPC mount: the declared bundle **plus** the off-declared-surface families the binary live-mounts (`_testing_*` backdoors, the cell verb set, the opt-in `actor_lookup` / `actor_search` resolvers). `build_full_spine_mount(deps, options)` builds it once for both of the binary's endpoints, returning `FullSpineMount` (`{rpc_actions, ws_actions}`): the WS list is `protocol_actions` plus every RPC action not already among them, twinning the Rust `testing_spine_stub`, which serves one registry on RPC and WS (the one difference is `cancel` — a registered protocol action on TS, owned by the read loop on Rust). Single-sources the mount so the binary and the `spine_method_coverage` reconciliation test build the same list. Also `$lib`-free.
1751
1809
  - `testing/cross_backend/ts_spine_backend_config.ts` — `ts_spine_node_backend_config()` / `ts_spine_deno_backend_config()` / `ts_spine_bun_backend_config()` presets (in-memory PGlite, no external infra), the TS analog of `rust_spine_stub_backend_config()`.
1752
1810
 
1753
- fuz_app's own binary wiring (`src/test/cross_backend/testing_spine_server{,_node,_deno,_bun}.ts`) is the worked example: ~one `build_app` over `create_app_backend` + `create_app_server` + `full_spine_rpc_endpoints` + a WS mount, reusing `default_spine_surface`. The `_node`/`_deno`/`_bun` entries differ only in which adapter they wire — `build_spine_app` is runtime-agnostic. It leaves `create_app_server`'s `auth_cleanup` off, as the Rust `testing_spine_stub` leaves its twin unscheduled: a background pass would delete rows and write audit rows under a running suite. A consumer's cross-process test binary may schedule it when nothing its suites seed is already expired (the conformance table's `expired_session` principal seeds a backdated session row); an in-process harness leaves it off.
1811
+ fuz_app's own binary wiring (`src/test/cross_backend/testing_spine_server{,_node,_deno,_bun}.ts`) is the worked example: ~one `build_app` over `create_app_backend` + `create_app_server` (`rate_limiters: 'disabled_for_testing'` plus whichever login / action limiters its env toggles built, `build_full_spine_mount`'s two lists on one `rpc_endpoints` entry and one `ws_endpoints` entry, whose `transport` is also the role-grant-offer `notification_sender`), reusing `default_spine_surface`. `src/test/cross_backend/testing_spine_server.db.test.ts` builds it with the Node adapter in-process and asserts its surface lists `/api/ws` and passes the surface invariants. The `_node`/`_deno`/`_bun` entries differ only in which adapter they wire — `build_spine_app` is runtime-agnostic. It leaves `create_app_server`'s `auth_cleanup` off, as the Rust `testing_spine_stub` leaves its twin unscheduled: a background pass would delete rows and write audit rows under a running suite. A consumer's cross-process test binary may schedule it when nothing its suites seed is already expired (the conformance table's `expired_session` principal seeds a backdated session row); an in-process harness leaves it off.
1754
1812
 
1755
1813
  ### Live-method coverage reconciliation — `method_coverage.ts`
1756
1814
 
@@ -302,14 +302,16 @@ 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, then the backend's `close`). */
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. */
306
306
  cleanup: () => Promise<void>;
307
307
  }
308
308
  /**
309
309
  * Create a fully assembled test app with a Hono server, middleware, and routes.
310
310
  *
311
311
  * Combines `create_test_app_server` + `create_app_server` into a single call.
312
- * Disables rate limiters and logging by default (test-friendly).
312
+ * Disables every rate limiter (`rate_limiters: 'disabled_for_testing'`) and
313
+ * logging by default (test-friendly). A limiter passed through `app_options`
314
+ * wins over the mode, so a rate-limit test enables just the one it pins.
313
315
  *
314
316
  * A fresh Hono app is created each call — middleware closures bind to the
315
317
  * server's deps (db, keyring), so reuse across servers is unsafe.
@@ -369,7 +371,8 @@ export interface TestAppForBootstrap {
369
371
  * accounts. The fs stubs return `options.bootstrap_token` when the
370
372
  * bootstrap handler reads `bootstrap.token_path`, so a `POST /bootstrap`
371
373
  * with `{token: bootstrap_token, username, password}` reaches the
372
- * success branch.
374
+ * success branch. Rate limiters are disabled the way `create_test_app`
375
+ * disables them — a limiter in `app_options` wins.
373
376
  *
374
377
  * Pair with `describe_bootstrap_success_tests` for the consumer-runnable
375
378
  * suite that drives the full happy path + adjacent assertions on
@@ -1 +1 @@
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,kHAAkH;IAClH,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,eAAe,GAAU,SAAS,oBAAoB,KAAG,OAAO,CAAC,OAAO,CAyGpF,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;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,6BAA6B,GACzC,SAAS,gCAAgC,KACvC,OAAO,CAAC,mBAAmB,CA2E7B,CAAC"}
1
+ {"version":3,"file":"app_server.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/app_server.ts"],"names":[],"mappings":"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"}
@@ -256,11 +256,26 @@ export const create_test_app_server = async (options) => {
256
256
  cleanup: () => backend.close()
257
257
  };
258
258
  };
259
+ /**
260
+ * The `create_app_server` options both test-app builders share — a fresh
261
+ * object per call, spread ahead of the per-builder options and `app_options`.
262
+ */
263
+ const test_app_server_base_options = () => ({
264
+ allowed_origins: [/^http:\/\/localhost/],
265
+ proxy: { trusted_proxies: ['127.0.0.1'], get_connection_ip: () => '127.0.0.1' },
266
+ env_schema: z.object({}),
267
+ // every limiter off unless `app_options` passes one — a rate-limit test
268
+ // enables just the limiter it pins
269
+ rate_limiters: 'disabled_for_testing',
270
+ await_pending_effects: true
271
+ });
259
272
  /**
260
273
  * Create a fully assembled test app with a Hono server, middleware, and routes.
261
274
  *
262
275
  * Combines `create_test_app_server` + `create_app_server` into a single call.
263
- * Disables rate limiters and logging by default (test-friendly).
276
+ * Disables every rate limiter (`rate_limiters: 'disabled_for_testing'`) and
277
+ * logging by default (test-friendly). A limiter passed through `app_options`
278
+ * wins over the mode, so a rate-limit test enables just the one it pins.
264
279
  *
265
280
  * A fresh Hono app is created each call — middleware closures bind to the
266
281
  * server's deps (db, keyring), so reuse across servers is unsafe.
@@ -281,17 +296,9 @@ export const create_test_app = async (options) => {
281
296
  keeper_account_id: test_server.account.id
282
297
  };
283
298
  const result = await create_app_server({
299
+ ...test_app_server_base_options(),
284
300
  backend: test_server,
285
301
  session_options: options.session_options,
286
- allowed_origins: [/^http:\/\/localhost/],
287
- proxy: { trusted_proxies: ['127.0.0.1'], get_connection_ip: () => '127.0.0.1' },
288
- env_schema: z.object({}),
289
- login_ip_rate_limiter: null,
290
- signup_ip_rate_limiter: null,
291
- bootstrap_ip_rate_limiter: null,
292
- login_account_rate_limiter: null,
293
- signup_account_rate_limiter: null,
294
- await_pending_effects: true,
295
302
  daemon_token_state,
296
303
  rpc_endpoints: options.rpc_endpoints,
297
304
  bootstrap: options.bootstrap,
@@ -372,7 +379,8 @@ export const create_test_app = async (options) => {
372
379
  * accounts. The fs stubs return `options.bootstrap_token` when the
373
380
  * bootstrap handler reads `bootstrap.token_path`, so a `POST /bootstrap`
374
381
  * with `{token: bootstrap_token, username, password}` reaches the
375
- * success branch.
382
+ * success branch. Rate limiters are disabled the way `create_test_app`
383
+ * disables them — a limiter in `app_options` wins.
376
384
  *
377
385
  * Pair with `describe_bootstrap_success_tests` for the consumer-runnable
378
386
  * suite that drives the full happy path + adjacent assertions on
@@ -417,17 +425,9 @@ export const create_test_app_for_bootstrap = async (options) => {
417
425
  keeper_account_id: null
418
426
  };
419
427
  const result = await create_app_server({
428
+ ...test_app_server_base_options(),
420
429
  backend,
421
430
  session_options,
422
- allowed_origins: [/^http:\/\/localhost/],
423
- proxy: { trusted_proxies: ['127.0.0.1'], get_connection_ip: () => '127.0.0.1' },
424
- env_schema: z.object({}),
425
- login_ip_rate_limiter: null,
426
- signup_ip_rate_limiter: null,
427
- bootstrap_ip_rate_limiter: null,
428
- login_account_rate_limiter: null,
429
- signup_account_rate_limiter: null,
430
- await_pending_effects: true,
431
431
  daemon_token_state,
432
432
  rpc_endpoints: options.rpc_endpoints,
433
433
  bootstrap,
@@ -1,10 +1,16 @@
1
1
  import './assert_dev_env.js';
2
2
  import type { ConnectionCloser } from '../actions/connection_closer.js';
3
- /** Record of a single `ConnectionCloser` method invocation. */
4
- export interface RecordedClose {
3
+ /**
4
+ * Record of a single `ConnectionCloser` method invocation — a credential
5
+ * close carries the id it was given, `close_all_sockets` (`'all'`) none.
6
+ */
7
+ export type RecordedClose = {
5
8
  method: 'session' | 'token' | 'account';
6
9
  id: string;
7
- }
10
+ } | {
11
+ method: 'all';
12
+ id: null;
13
+ };
8
14
  export interface RecordingCloser {
9
15
  closer: ConnectionCloser;
10
16
  calls: Array<RecordedClose>;
@@ -27,5 +33,5 @@ export declare const create_recording_closer: () => RecordingCloser;
27
33
  * `calls` array directly (`calls[0]`) and let this helper handle the
28
34
  * missing-element case.
29
35
  */
30
- export declare const assert_close_call: (call: RecordedClose | undefined, method: "session" | "token" | "account", id: string) => void;
36
+ export declare const assert_close_call: (call: RecordedClose | undefined, method: RecordedClose["method"], id: string | null) => void;
31
37
  //# sourceMappingURL=connection_closer_helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"connection_closer_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/connection_closer_helpers.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAI7B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAExE,+DAA+D;AAC/D,MAAM,WAAW,aAAa;IAC7B,MAAM,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IACxC,EAAE,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,eAAe;IAC/B,MAAM,EAAE,gBAAgB,CAAC;IACzB,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;CAC5B;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,uBAAuB,QAAO,eAiB1C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAC7B,MAAM,aAAa,GAAG,SAAS,EAC/B,QAAQ,SAAS,GAAG,OAAO,GAAG,SAAS,EACvC,IAAI,MAAM,KACR,IAIF,CAAC"}
1
+ {"version":3,"file":"connection_closer_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/connection_closer_helpers.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAI7B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAExE;;;GAGG;AACH,MAAM,MAAM,aAAa,GACxB;IAAE,MAAM,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,KAAK,CAAC;IAAC,EAAE,EAAE,IAAI,CAAA;CAAE,CAAC;AAEvF,MAAM,WAAW,eAAe;IAC/B,MAAM,EAAE,gBAAgB,CAAC;IACzB,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;CAC5B;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,uBAAuB,QAAO,eAqB1C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAC7B,MAAM,aAAa,GAAG,SAAS,EAC/B,QAAQ,aAAa,CAAC,QAAQ,CAAC,EAC/B,IAAI,MAAM,GAAG,IAAI,KACf,IAIF,CAAC"}
@@ -24,6 +24,10 @@ export const create_recording_closer = () => {
24
24
  close_sockets_for_account: (id) => {
25
25
  calls.push({ method: 'account', id });
26
26
  return 1;
27
+ },
28
+ close_all_sockets: () => {
29
+ calls.push({ method: 'all', id: null });
30
+ return 1;
27
31
  }
28
32
  };
29
33
  return { closer, calls };
@@ -185,9 +185,9 @@ export interface BackendCapabilities {
185
185
  * `describe_cross_process_ws_tests`: the socket reads the reply to its
186
186
  * request, then is closed with `WS_CLOSE_SESSION_REVOKED`.
187
187
  *
188
- * `true` on fuz_app's own spine presets — the TS spine binary mounts
189
- * `create_account_actions` on `/api/ws`, and the Rust `testing_spine_stub`
190
- * serves one action registry on RPC and WS. `false` in the family defaults:
188
+ * `true` on fuz_app's own spine presets — the TS spine binary mounts its
189
+ * full action set on `/api/ws`, and the Rust `testing_spine_stub` serves
190
+ * one action registry on RPC and WS. `false` in the family defaults:
191
191
  * a consumer's WS endpoint carries whatever its domain mounts, so it opts in
192
192
  * once the account actions are there.
193
193
  */
@@ -2,8 +2,8 @@ import '../assert_dev_env.js';
2
2
  /**
3
3
  * Family-shared `BackendConfig` builders for cross-process test backends.
4
4
  *
5
- * Two consumer-facing factories — {@link make_default_ts_backend_config}
6
- * and {@link make_default_rust_backend_config} — own the common shape
5
+ * Two consumer-facing factories — `make_default_ts_backend_config`
6
+ * and `make_default_rust_backend_config` — own the common shape
7
7
  * for the JS-runtime (Deno/Node on V8) and Rust families respectively.
8
8
  * Per-backend factories in consumer projects compose a small
9
9
  * declaration against one of these and add consumer-specific env vars
@@ -35,18 +35,18 @@ import '../assert_dev_env.js';
35
35
  import type { BackendBootstrapConfig, BackendConfig } from './backend_config.js';
36
36
  import type { BackendCapabilities, BackendShapeNotes } from './capabilities.js';
37
37
  import { type TestBackendPaths } from './build_test_backend_paths.js';
38
+ /** Options for `action_rate_limit_env`. */
39
+ export interface ActionRateLimitEnvOptions {
40
+ readonly enable_action_rate_limit?: boolean;
41
+ readonly action_rate_limit_max_attempts?: number;
42
+ }
38
43
  /**
39
- * Env var both spine binaries read to enable their login rate limiters
40
- * (`'true'` on / unset off). The cross-language contract for the login-security
41
- * cross project: the TS binary reads it via `runtime.env_get` (a test-only flag,
42
- * not in `BaseServerEnv`); the Rust `testing_spine_stub` reads it via
43
- * `std::env::var` — so one backend-config option drives both impls. Shared home
44
- * here because both `ts_spine_backend_config` and `rust_spine_stub_backend_config`
45
- * already import this module. (The spawned TS binary re-declares the literal
46
- * locally — it can't import this module, which transitively pulls `vitest` —
47
- * mirroring how `testing_spine_server_node.ts` re-declares `TS_SPINE_DIR_ENV`.)
44
+ * The `extra_env` entries carrying the action rate-limit toggles, shared by the
45
+ * TS and Rust backend configs so one option pair drives both impls.
46
+ * `action_rate_limit_max_attempts` is passed through even without the enable
47
+ * flag, so the binary refuses the combination instead of the harness hiding it.
48
48
  */
49
- export declare const LOGIN_RATE_LIMIT_ENABLED_ENV = "FUZ_LOGIN_RATE_LIMIT_ENABLED";
49
+ export declare const action_rate_limit_env: (options: ActionRateLimitEnvOptions) => Record<string, string>;
50
50
  /**
51
51
  * Capabilities shared by TS-family backends — same canonical implementation,
52
52
  * same feature set. The non-gating wiring facts (`bearer_auth` /
@@ -1 +1 @@
1
- {"version":3,"file":"default_backend_configs.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/default_backend_configs.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACjF,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,EAA4B,KAAK,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAQhG;;;;;;;;;;GAUG;AACH,eAAO,MAAM,4BAA4B,iCAAiC,CAAC;AAE3E;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,EAAE,mBAsCpC,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,EAAE,mBAgCtC,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,EAAE,iBAInC,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,EAAE,iBAIrC,CAAC;AAeH,MAAM,WAAW,iCAAiC;IACjD,gFAAgF;IAChF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,sCAAsC;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4DAA4D;IAC5D,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC9C,oDAAoD;IACpD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,iEAAiE;IACjE,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACtD,6CAA6C;IAC7C,QAAQ,CAAC,YAAY,CAAC,EAAE,mBAAmB,CAAC;IAC5C,wEAAwE;IACxE,QAAQ,CAAC,KAAK,CAAC,EAAE,gBAAgB,CAAC;IAClC,sEAAsE;IACtE,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC,CAAC;IAC/D;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B;;;;;;OAMG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,GAC1C,MAAM,iCAAiC,KACrC,aAoCF,CAAC;AAEF,MAAM,WAAW,mCAAmC;IACnD,gFAAgF;IAChF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,sCAAsC;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4DAA4D;IAC5D,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC9C;;;;OAIG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,iEAAiE;IACjE,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACtD,+CAA+C;IAC/C,QAAQ,CAAC,YAAY,CAAC,EAAE,mBAAmB,CAAC;IAC5C,wEAAwE;IACxE,QAAQ,CAAC,KAAK,CAAC,EAAE,gBAAgB,CAAC;IAClC,sEAAsE;IACtE,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC,CAAC;IAC/D;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,GAC5C,MAAM,mCAAmC,KACvC,aA4CF,CAAC"}
1
+ {"version":3,"file":"default_backend_configs.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/default_backend_configs.ts"],"names":[],"mappings":"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"}
@@ -1,18 +1,19 @@
1
1
  import '../assert_dev_env.js';
2
2
  import { build_test_backend_paths } from './build_test_backend_paths.js';
3
3
  import { default_test_bootstrap_token, default_test_cookie_keys, default_test_keeper_password, default_test_keeper_username } from './default_secrets.js';
4
+ import { ACTION_RATE_LIMIT_ENABLED_ENV, ACTION_RATE_LIMIT_MAX_ATTEMPTS_ENV } from './spine_surface_constants.js';
4
5
  /**
5
- * Env var both spine binaries read to enable their login rate limiters
6
- * (`'true'` on / unset off). The cross-language contract for the login-security
7
- * cross project: the TS binary reads it via `runtime.env_get` (a test-only flag,
8
- * not in `BaseServerEnv`); the Rust `testing_spine_stub` reads it via
9
- * `std::env::var` — so one backend-config option drives both impls. Shared home
10
- * here because both `ts_spine_backend_config` and `rust_spine_stub_backend_config`
11
- * already import this module. (The spawned TS binary re-declares the literal
12
- * locally — it can't import this module, which transitively pulls `vitest` —
13
- * mirroring how `testing_spine_server_node.ts` re-declares `TS_SPINE_DIR_ENV`.)
6
+ * The `extra_env` entries carrying the action rate-limit toggles, shared by the
7
+ * TS and Rust backend configs so one option pair drives both impls.
8
+ * `action_rate_limit_max_attempts` is passed through even without the enable
9
+ * flag, so the binary refuses the combination instead of the harness hiding it.
14
10
  */
15
- export const LOGIN_RATE_LIMIT_ENABLED_ENV = 'FUZ_LOGIN_RATE_LIMIT_ENABLED';
11
+ export const action_rate_limit_env = (options) => ({
12
+ ...(options.enable_action_rate_limit ? { [ACTION_RATE_LIMIT_ENABLED_ENV]: 'true' } : {}),
13
+ ...(options.action_rate_limit_max_attempts !== undefined
14
+ ? { [ACTION_RATE_LIMIT_MAX_ATTEMPTS_ENV]: String(options.action_rate_limit_max_attempts) }
15
+ : {})
16
+ });
16
17
  /**
17
18
  * Capabilities shared by TS-family backends — same canonical implementation,
18
19
  * same feature set. The non-gating wiring facts (`bearer_auth` /
@@ -21,8 +21,13 @@ import '../assert_dev_env.js';
21
21
  * Single-sourcing the mount here lets the binary, the in-process parity
22
22
  * setup, and the `spine_method_coverage` reconciliation test all build the
23
23
  * same list — so a method can never be mounted in one place and forgotten
24
- * in another. The reconciliation test enumerates `build_full_spine_rpc_actions`
25
- * with stub deps and asserts the live method set equals the tagged coverage
24
+ * in another.
25
+ *
26
+ * The binary's WS endpoint serves the same list: `build_full_spine_mount`
27
+ * builds it once and hands the WS mount the protocol actions plus every RPC
28
+ * action, twinning the Rust `testing_spine_stub`, which compiles one action
29
+ * registry and serves it on both transports. The reconciliation test
30
+ * enumerates `build_full_spine_rpc_actions` with stub deps and asserts the live method set equals the tagged coverage
26
31
  * manifest; see `src/test/cross_backend/spine_method_coverage.ts`.
27
32
  *
28
33
  * **`$lib`-free by contract** — like `default_spine_surface.ts`, this module
@@ -33,12 +38,11 @@ import '../assert_dev_env.js';
33
38
  * @module
34
39
  */
35
40
  import type { RpcAction } from '../../actions/action_rpc.js';
41
+ import type { Action } from '../../actions/action_types.js';
36
42
  import type { AppDeps } from '../../auth/deps.js';
37
43
  import type { DaemonTokenState } from '../../auth/daemon_token.js';
38
44
  import type { NotificationSender } from '../../auth/role_grant_offer_notifications.js';
39
- import type { RpcEndpointSpec } from '../../http/surface.js';
40
- import type { AppServerContext } from '../../server/app_server_context.js';
41
- /** Options for {@link build_full_spine_rpc_actions} / {@link full_spine_rpc_endpoints}. */
45
+ /** Options for `build_full_spine_rpc_actions` / `build_full_spine_mount`. */
42
46
  export interface FullSpineMountOptions {
43
47
  /**
44
48
  * Daemon-token runtime state threaded into `create_testing_actions` — the
@@ -70,12 +74,32 @@ export interface FullSpineMountOptions {
70
74
  * @returns every `RpcAction` the binary exposes, in mount order
71
75
  */
72
76
  export declare const build_full_spine_rpc_actions: (deps: AppDeps, options: FullSpineMountOptions) => Array<RpcAction>;
77
+ /** The spine binary's RPC and WS action sets, built from one action list. */
78
+ export interface FullSpineMount {
79
+ /** Every action on the RPC endpoint — `build_full_spine_rpc_actions`'s list. */
80
+ readonly rpc_actions: Array<RpcAction>;
81
+ /**
82
+ * The WS endpoint's actions: `protocol_actions` first, then every RPC
83
+ * action not already among them (`peer/ping` is on both lists). The same
84
+ * handler instances as `rpc_actions`.
85
+ */
86
+ readonly ws_actions: Array<Action>;
87
+ }
73
88
  /**
74
- * Factory-form full mount at {@link SPINE_RPC_PATH}, the shape
75
- * `create_app_server`'s `rpc_endpoints` slot accepts. The spine binary wires
76
- * this directly; the surface builder (`create_spine_surface_spec`) keeps using
77
- * the narrower `spine_rpc_endpoints` so the declared surface stays the
78
- * standard bundle only.
89
+ * Build the full live mount for both of the spine binary's endpoints: the
90
+ * RPC list, and the WS list that serves the same actions behind the protocol
91
+ * actions.
92
+ *
93
+ * The Rust `testing_spine_stub` serves one action registry on RPC and WS, so
94
+ * mounting the full list on WS keeps the two spines' WS method sets equal —
95
+ * the cell verbs among them, whose dispatcher-charged rate limit
96
+ * `describe_ws_action_rate_limit_cross_tests` drives over a socket. The one
97
+ * difference is `cancel`: a registered protocol action on TS, read-loop-owned
98
+ * (never dispatched) on Rust.
99
+ *
100
+ * @param deps - the backend `AppDeps`
101
+ * @param options - daemon-token state + optional WS notification sender
102
+ * @returns the RPC and WS action lists, built once and sharing handler instances
79
103
  */
80
- export declare const full_spine_rpc_endpoints: (ctx: AppServerContext, options: FullSpineMountOptions) => Array<RpcEndpointSpec>;
104
+ export declare const build_full_spine_mount: (deps: AppDeps, options: FullSpineMountOptions) => FullSpineMount;
81
105
  //# sourceMappingURL=full_spine_mount.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"full_spine_mount.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/full_spine_mount.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAE7D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8CAA8C,CAAC;AAKvF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAS3E,2FAA2F;AAC3F,MAAM,WAAW,qBAAqB;IACrC;;;;;;OAMG;IACH,QAAQ,CAAC,kBAAkB,EAAE,gBAAgB,CAAC;IAC9C;;;;OAIG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;CACzD;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,4BAA4B,GACxC,MAAM,OAAO,EACb,SAAS,qBAAqB,KAC5B,KAAK,CAAC,SAAS,CAoCjB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,GACpC,KAAK,gBAAgB,EACrB,SAAS,qBAAqB,KAC5B,KAAK,CAAC,eAAe,CAEvB,CAAC"}
1
+ {"version":3,"file":"full_spine_mount.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/full_spine_mount.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AAG5D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8CAA8C,CAAC;AAYvF,6EAA6E;AAC7E,MAAM,WAAW,qBAAqB;IACrC;;;;;;OAMG;IACH,QAAQ,CAAC,kBAAkB,EAAE,gBAAgB,CAAC;IAC9C;;;;OAIG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;CACzD;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,4BAA4B,GACxC,MAAM,OAAO,EACb,SAAS,qBAAqB,KAC5B,KAAK,CAAC,SAAS,CAoCjB,CAAC;AAEF,6EAA6E;AAC7E,MAAM,WAAW,cAAc;IAC9B,gFAAgF;IAChF,QAAQ,CAAC,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IACvC;;;;OAIG;IACH,QAAQ,CAAC,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CACnC;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,sBAAsB,GAClC,MAAM,OAAO,EACb,SAAS,qBAAqB,KAC5B,cAUF,CAAC"}