@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.
- package/dist/actions/CLAUDE.md +56 -20
- package/dist/actions/action_rpc.d.ts +14 -11
- package/dist/actions/action_rpc.d.ts.map +1 -1
- package/dist/actions/action_rpc.js +5 -4
- package/dist/actions/connection_closer.d.ts +13 -3
- package/dist/actions/connection_closer.d.ts.map +1 -1
- package/dist/actions/connection_closer.js +7 -5
- package/dist/actions/register_action_ws.d.ts +18 -13
- package/dist/actions/register_action_ws.d.ts.map +1 -1
- package/dist/actions/register_action_ws.js +8 -6
- package/dist/actions/register_ws_endpoint.d.ts +6 -3
- package/dist/actions/register_ws_endpoint.d.ts.map +1 -1
- package/dist/actions/register_ws_endpoint.js +6 -3
- package/dist/actions/transports.d.ts +9 -0
- package/dist/actions/transports.d.ts.map +1 -1
- package/dist/actions/transports.js +9 -0
- package/dist/actions/transports_ws_backend.d.ts +15 -0
- package/dist/actions/transports_ws_backend.d.ts.map +1 -1
- package/dist/actions/transports_ws_backend.js +25 -5
- package/dist/actions/ws_endpoint_spec.d.ts +24 -4
- package/dist/actions/ws_endpoint_spec.d.ts.map +1 -1
- package/dist/actions/ws_endpoint_spec.js +15 -1
- package/dist/auth/middleware.d.ts +29 -1
- package/dist/auth/middleware.d.ts.map +1 -1
- package/dist/auth/middleware.js +35 -1
- package/dist/http/CLAUDE.md +3 -3
- package/dist/http/surface.d.ts +12 -9
- package/dist/http/surface.d.ts.map +1 -1
- package/dist/rate_limiter.d.ts +43 -3
- package/dist/rate_limiter.d.ts.map +1 -1
- package/dist/rate_limiter.js +27 -3
- package/dist/realtime/sse_auth_guard.d.ts +2 -1
- package/dist/realtime/sse_auth_guard.d.ts.map +1 -1
- package/dist/realtime/sse_auth_guard.js +4 -2
- package/dist/realtime/subscriber_registry.d.ts +12 -0
- package/dist/realtime/subscriber_registry.d.ts.map +1 -1
- package/dist/realtime/subscriber_registry.js +18 -2
- package/dist/server/app_server.d.ts +128 -55
- package/dist/server/app_server.d.ts.map +1 -1
- package/dist/server/app_server.js +110 -61
- package/dist/server/app_server_context.d.ts +17 -9
- package/dist/server/app_server_context.d.ts.map +1 -1
- package/dist/testing/CLAUDE.md +83 -25
- package/dist/testing/app_server.d.ts +6 -3
- package/dist/testing/app_server.d.ts.map +1 -1
- package/dist/testing/app_server.js +20 -20
- package/dist/testing/connection_closer_helpers.d.ts +10 -4
- package/dist/testing/connection_closer_helpers.d.ts.map +1 -1
- package/dist/testing/connection_closer_helpers.js +4 -0
- package/dist/testing/cross_backend/capabilities.d.ts +3 -3
- package/dist/testing/cross_backend/default_backend_configs.d.ts +12 -12
- package/dist/testing/cross_backend/default_backend_configs.d.ts.map +1 -1
- package/dist/testing/cross_backend/default_backend_configs.js +11 -10
- package/dist/testing/cross_backend/full_spine_mount.d.ts +35 -11
- package/dist/testing/cross_backend/full_spine_mount.d.ts.map +1 -1
- package/dist/testing/cross_backend/full_spine_mount.js +26 -9
- package/dist/testing/cross_backend/rust_spine_stub_backend_config.d.ts +16 -1
- package/dist/testing/cross_backend/rust_spine_stub_backend_config.d.ts.map +1 -1
- package/dist/testing/cross_backend/rust_spine_stub_backend_config.js +5 -4
- package/dist/testing/cross_backend/spine_surface_constants.d.ts +43 -3
- package/dist/testing/cross_backend/spine_surface_constants.d.ts.map +1 -1
- package/dist/testing/cross_backend/spine_surface_constants.js +43 -3
- package/dist/testing/cross_backend/testing_backdoor.d.ts +15 -1
- package/dist/testing/cross_backend/testing_backdoor.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_backdoor.js +51 -6
- package/dist/testing/cross_backend/testing_reset_actions.d.ts +6 -3
- package/dist/testing/cross_backend/testing_reset_actions.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_reset_actions.js +6 -3
- package/dist/testing/cross_backend/testing_server_bun.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_server_bun.js +5 -1
- package/dist/testing/cross_backend/testing_server_core.d.ts +72 -41
- package/dist/testing/cross_backend/testing_server_core.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_server_core.js +22 -14
- package/dist/testing/cross_backend/testing_server_deno.js +1 -1
- package/dist/testing/cross_backend/testing_server_node.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_server_node.js +20 -7
- package/dist/testing/cross_backend/ts_spine_backend_config.d.ts +15 -2
- package/dist/testing/cross_backend/ts_spine_backend_config.d.ts.map +1 -1
- package/dist/testing/cross_backend/ts_spine_backend_config.js +10 -8
- package/dist/testing/cross_backend/ws_action_rate_limit.d.ts +26 -0
- package/dist/testing/cross_backend/ws_action_rate_limit.d.ts.map +1 -0
- package/dist/testing/cross_backend/ws_action_rate_limit.js +261 -0
- package/dist/testing/middleware.d.ts.map +1 -1
- package/dist/testing/middleware.js +4 -3
- package/dist/testing/stubs.d.ts +17 -4
- package/dist/testing/stubs.d.ts.map +1 -1
- package/dist/testing/stubs.js +46 -13
- package/dist/testing/transports/ws_transport.d.ts +7 -0
- package/dist/testing/transports/ws_transport.d.ts.map +1 -1
- package/dist/testing/transports/ws_transport.js +1 -1
- package/dist/testing/ws_round_trip.d.ts +43 -37
- package/dist/testing/ws_round_trip.d.ts.map +1 -1
- package/dist/testing/ws_round_trip.js +28 -46
- 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
|
|
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"}
|
package/dist/testing/CLAUDE.md
CHANGED
|
@@ -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
|
|
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({})`,
|
|
182
|
-
|
|
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
|
|
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).
|
|
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`
|
|
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
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
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
|
|
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)`
|
|
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`
|
|
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
|
|
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
|
|
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":"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
|
|
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
|
|
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
|
-
/**
|
|
4
|
-
|
|
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: "
|
|
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
|
|
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
|
-
*
|
|
190
|
-
*
|
|
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 —
|
|
6
|
-
* and
|
|
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
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
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
|
|
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;
|
|
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
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
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
|
|
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.
|
|
25
|
-
*
|
|
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
|
-
|
|
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
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
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
|
|
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
|
|
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"}
|