@fuzdev/fuz_app 0.125.0 → 0.126.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 +57 -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/surface.d.ts +3 -1
- package/dist/http/surface.d.ts.map +1 -1
- package/dist/http/surface.js +15 -1
- package/dist/rate_limiter.d.ts +25 -3
- package/dist/rate_limiter.d.ts.map +1 -1
- package/dist/rate_limiter.js +4 -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 +127 -55
- package/dist/server/app_server.d.ts.map +1 -1
- package/dist/server/app_server.js +107 -60
- 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 +75 -17
- 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 +11 -12
- 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 +31 -0
- package/dist/testing/cross_backend/default_backend_configs.d.ts.map +1 -1
- package/dist/testing/cross_backend/default_backend_configs.js +31 -0
- 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 +15 -0
- 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 +3 -2
- package/dist/testing/cross_backend/testing_backdoor.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_backdoor.js +2 -1
- 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 +68 -37
- package/dist/testing/cross_backend/testing_server_core.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_server_core.js +20 -12
- 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 -0
- package/dist/testing/cross_backend/ts_spine_backend_config.d.ts.map +1 -1
- package/dist/testing/cross_backend/ts_spine_backend_config.js +9 -5
- 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/stubs.d.ts +14 -4
- package/dist/testing/stubs.d.ts.map +1 -1
- package/dist/testing/stubs.js +31 -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 +36 -6
- package/dist/testing/ws_round_trip.d.ts.map +1 -1
- package/dist/testing/ws_round_trip.js +28 -8
- 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`). 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,16 @@ 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`, the action limiters included — a limiter passed through
|
|
183
|
+
`app_options` wins over the mode, so a rate-limit test enables just the one it
|
|
184
|
+
pins), static daemon token state (no rotation, keeper already set),
|
|
183
185
|
**`await_pending_effects: true`** (fire-and-forget effects complete before
|
|
184
186
|
the response returns so tests can assert on side effects inline), and silent
|
|
185
|
-
logger. Override via `app_options`.
|
|
187
|
+
logger. Override via `app_options`. `create_test_app_for_bootstrap` disables
|
|
188
|
+
the limiters the same way. `cleanup()` is the assembled server's idempotent
|
|
189
|
+
`close` — it also closes the server's live connections and disposes the
|
|
190
|
+
limiters it built.
|
|
186
191
|
|
|
187
192
|
`auth_cleanup` is left at its default, **off**, here and in
|
|
188
193
|
`create_test_app_for_bootstrap`: a background pass would delete rows and
|
|
@@ -539,11 +544,12 @@ In-process test driver for `register_action_ws`. Consumers pass specs +
|
|
|
539
544
|
handlers, receive `{transport, connect()}` back. The full dispatch path is
|
|
540
545
|
exercised (per-action auth, input validation, `ctx.notify`, broadcast via
|
|
541
546
|
`BackendWebsocketTransport`, close-on-revoke), but Hono's wire upgrade is
|
|
542
|
-
skipped
|
|
547
|
+
skipped — there is no server, so no runtime adapter; the cross-process suites
|
|
548
|
+
cover real sockets.
|
|
543
549
|
|
|
544
550
|
Three layers:
|
|
545
551
|
|
|
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.
|
|
552
|
+
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
553
|
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
554
|
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.
|
|
549
555
|
|
|
@@ -675,8 +681,7 @@ the same `RpcEndpointsSuiteOption` union every DB-backed suite accepts
|
|
|
675
681
|
raw to the top-level `rpc_endpoints` slot on `CreateTestAppOptions` so
|
|
676
682
|
`create_app_server` resolves it per-test with the real ctx — the only way
|
|
677
683
|
action handlers can close over
|
|
678
|
-
`ctx.deps`
|
|
679
|
-
{app_settings: ctx.app_settings})`). Factory must return the same endpoint
|
|
684
|
+
`ctx.deps` (e.g. `create_standard_rpc_actions(ctx.deps)`). Factory must return the same endpoint
|
|
680
685
|
`path` regardless of ctx — `resolve_rpc_endpoints_for_setup` invokes it once
|
|
681
686
|
with a stub ctx for path lookup and `create_app_server` invokes it again
|
|
682
687
|
per-test for live dispatch.
|
|
@@ -1381,12 +1386,14 @@ are `src/test/auth/cell_crud_parity.db.test.ts`
|
|
|
1381
1386
|
request (`{result}` / `{error}` / `undefined` to swallow), the path
|
|
1382
1387
|
`describe_peer_ping_ws_tests` drives. With no `on_request` the seam is inert
|
|
1383
1388
|
(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?})`
|
|
1389
|
+
- `testing/transports/ws_transport.ts` — `create_ws_transport({base_url, ws_path, cookies, origin?, on_request?, headers?})`
|
|
1385
1390
|
builds a real-upgrade WS client using the `ws` npm package (optional
|
|
1386
1391
|
peerDep; consumers wiring cross-process tests `npm install --save-dev ws`).
|
|
1387
1392
|
Threads the keeper cookie onto the upgrade so per-action auth succeeds on
|
|
1388
1393
|
the first message. `on_request` (attached at construction, before the upgrade
|
|
1389
|
-
completes) answers server-initiated requests via the shared `deliver_inbound`.
|
|
1394
|
+
completes) answers server-initiated requests via the shared `deliver_inbound`. `headers`
|
|
1395
|
+
adds upgrade headers — e.g. an `X-Forwarded-For`, which a backend trusting the
|
|
1396
|
+
loopback proxy resolves as the connection's client IP for every message.
|
|
1390
1397
|
An open socket is not yet an *admitted* connection — both spines answer the
|
|
1391
1398
|
handshake, then re-read the credential, then admit, and deliver no
|
|
1392
1399
|
server-initiated message until then. `create_admitted_ws_transport(options)`
|
|
@@ -1693,6 +1700,57 @@ The in-process counterparts already exist (`describe_rate_limiting_tests` plus t
|
|
|
1693
1700
|
proxy middleware tests), so there's no in-process leg. `npm run test:cross:security`.
|
|
1694
1701
|
Cited property: `docs/security.md` §"Rate Limiting" + §"Trusted Proxy / Client IP".
|
|
1695
1702
|
|
|
1703
|
+
### Action rate-limit parity over WS — `cross_backend/ws_action_rate_limit.ts`
|
|
1704
|
+
|
|
1705
|
+
`describe_ws_action_rate_limit_cross_tests({setup_test, base_url, ws_path,
|
|
1706
|
+
rpc_path?, max_attempts})` — the imperative suite pinning **action rate
|
|
1707
|
+
limiting over a real WebSocket**, and its budget shared with HTTP RPC, on
|
|
1708
|
+
backends started with small shared action limiters (`max_attempts` is the cap
|
|
1709
|
+
they were started with, at least 2):
|
|
1710
|
+
|
|
1711
|
+
- **account axis over WS** — `account_token_create` (`rate_limit: 'account'`
|
|
1712
|
+
on both spines) with malformed params: `max_attempts` calls answer
|
|
1713
|
+
`invalid_params` (the throttle runs before params validation, so they charge),
|
|
1714
|
+
the next answers `rate_limited` with a positive `data.retry_after`.
|
|
1715
|
+
- **one account bucket across transports** — calls split between HTTP RPC and
|
|
1716
|
+
WS exhaust one budget; the call past it is refused on WS and on HTTP (`429`).
|
|
1717
|
+
- **IP axis keyed by the forwarded client IP** — `peer/ping` (`rate_limit:
|
|
1718
|
+
'ip'`, public) with malformed params from one `X-Forwarded-For` address, over
|
|
1719
|
+
anonymous HTTP and over a WS whose upgrade carried the header: refused past the
|
|
1720
|
+
cap on both transports, while a second address keeps its own bucket on both.
|
|
1721
|
+
- **account axis at the dispatchers** — `cell_create` (`rate_limit:
|
|
1722
|
+
'account'`, on both spines' RPC and WS mounts) with malformed params: refused
|
|
1723
|
+
past the cap over HTTP (`429`) and over WS (`rate_limited`), calls split
|
|
1724
|
+
between the two transports exhaust one budget, and a budget split between
|
|
1725
|
+
`cell_create` and `account_token_create` is one bucket.
|
|
1726
|
+
|
|
1727
|
+
Isolation without a limiter reset: each account case runs on the fresh keeper
|
|
1728
|
+
the per-test `_testing_reset` seeds (a new account id), and the IP case uses
|
|
1729
|
+
TEST-NET-2 addresses nothing else sends. The backends are started by the
|
|
1730
|
+
`enable_action_rate_limit` + `action_rate_limit_max_attempts` options on both
|
|
1731
|
+
backend configs (`ts_spine_*_backend_config`, `rust_spine_stub_backend_config`),
|
|
1732
|
+
which set `ACTION_RATE_LIMIT_ENABLED_ENV` (`FUZ_ACTION_RATE_LIMIT_ENABLED`) and
|
|
1733
|
+
`ACTION_RATE_LIMIT_MAX_ATTEMPTS_ENV` (`FUZ_ACTION_RATE_LIMIT_MAX_ATTEMPTS`) from
|
|
1734
|
+
`default_backend_configs.ts` — both spine binaries build one IP + one account
|
|
1735
|
+
limiter (the action defaults' windows, the cap replacing both
|
|
1736
|
+
`max_attempts`) shared by RPC and WS, and refuse to boot on a cap without the
|
|
1737
|
+
flag. Off, the TS spine builds no action limiter, and the Rust stub keeps its
|
|
1738
|
+
default posture: its auth families charge an always-on per-account limiter at
|
|
1739
|
+
the production cap, its dispatchers none. 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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"}
|
|
@@ -260,7 +260,9 @@ export const create_test_app_server = async (options) => {
|
|
|
260
260
|
* Create a fully assembled test app with a Hono server, middleware, and routes.
|
|
261
261
|
*
|
|
262
262
|
* Combines `create_test_app_server` + `create_app_server` into a single call.
|
|
263
|
-
* Disables rate
|
|
263
|
+
* Disables every rate limiter (`rate_limiters: 'disabled_for_testing'`) and
|
|
264
|
+
* logging by default (test-friendly). A limiter passed through `app_options`
|
|
265
|
+
* wins over the mode, so a rate-limit test enables just the one it pins.
|
|
264
266
|
*
|
|
265
267
|
* A fresh Hono app is created each call — middleware closures bind to the
|
|
266
268
|
* server's deps (db, keyring), so reuse across servers is unsafe.
|
|
@@ -286,11 +288,9 @@ export const create_test_app = async (options) => {
|
|
|
286
288
|
allowed_origins: [/^http:\/\/localhost/],
|
|
287
289
|
proxy: { trusted_proxies: ['127.0.0.1'], get_connection_ip: () => '127.0.0.1' },
|
|
288
290
|
env_schema: z.object({}),
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
login_account_rate_limiter: null,
|
|
293
|
-
signup_account_rate_limiter: null,
|
|
291
|
+
// every limiter off unless `app_options` passes one — a rate-limit test
|
|
292
|
+
// enables just the limiter it pins
|
|
293
|
+
rate_limiters: 'disabled_for_testing',
|
|
294
294
|
await_pending_effects: true,
|
|
295
295
|
daemon_token_state,
|
|
296
296
|
rpc_endpoints: options.rpc_endpoints,
|
|
@@ -372,7 +372,8 @@ export const create_test_app = async (options) => {
|
|
|
372
372
|
* accounts. The fs stubs return `options.bootstrap_token` when the
|
|
373
373
|
* bootstrap handler reads `bootstrap.token_path`, so a `POST /bootstrap`
|
|
374
374
|
* with `{token: bootstrap_token, username, password}` reaches the
|
|
375
|
-
* success branch.
|
|
375
|
+
* success branch. Rate limiters are disabled the way `create_test_app`
|
|
376
|
+
* disables them — a limiter in `app_options` wins.
|
|
376
377
|
*
|
|
377
378
|
* Pair with `describe_bootstrap_success_tests` for the consumer-runnable
|
|
378
379
|
* suite that drives the full happy path + adjacent assertions on
|
|
@@ -422,11 +423,9 @@ export const create_test_app_for_bootstrap = async (options) => {
|
|
|
422
423
|
allowed_origins: [/^http:\/\/localhost/],
|
|
423
424
|
proxy: { trusted_proxies: ['127.0.0.1'], get_connection_ip: () => '127.0.0.1' },
|
|
424
425
|
env_schema: z.object({}),
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
login_account_rate_limiter: null,
|
|
429
|
-
signup_account_rate_limiter: null,
|
|
426
|
+
// every limiter off unless `app_options` passes one — a rate-limit test
|
|
427
|
+
// enables just the limiter it pins
|
|
428
|
+
rate_limiters: 'disabled_for_testing',
|
|
430
429
|
await_pending_effects: true,
|
|
431
430
|
daemon_token_state,
|
|
432
431
|
rpc_endpoints: options.rpc_endpoints,
|
|
@@ -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
|
*/
|
|
@@ -47,6 +47,37 @@ import { type TestBackendPaths } from './build_test_backend_paths.js';
|
|
|
47
47
|
* mirroring how `testing_spine_server_node.ts` re-declares `TS_SPINE_DIR_ENV`.)
|
|
48
48
|
*/
|
|
49
49
|
export declare const LOGIN_RATE_LIMIT_ENABLED_ENV = "FUZ_LOGIN_RATE_LIMIT_ENABLED";
|
|
50
|
+
/**
|
|
51
|
+
* Env var both spine binaries read to enable their action rate limiters
|
|
52
|
+
* (`'true'` on / unset off) — one per-IP and one per-account limiter, shared by
|
|
53
|
+
* the RPC and WS endpoints (and, on the Rust stub, the auth-family handlers
|
|
54
|
+
* that charge in-handler). The cross-language contract for the action
|
|
55
|
+
* rate-limit cross suite (`ws_action_rate_limit.ts`); same delivery as
|
|
56
|
+
* `LOGIN_RATE_LIMIT_ENABLED_ENV`. Off, the TS spine builds no action limiter
|
|
57
|
+
* and the Rust stub keeps its default posture (only its auth families charge,
|
|
58
|
+
* against an always-on per-account limiter at the production cap).
|
|
59
|
+
*/
|
|
60
|
+
export declare const ACTION_RATE_LIMIT_ENABLED_ENV = "FUZ_ACTION_RATE_LIMIT_ENABLED";
|
|
61
|
+
/**
|
|
62
|
+
* Env var replacing both action limiters' `max_attempts` (a positive integer;
|
|
63
|
+
* the windows stay `default_action_ip_rate_limit`'s /
|
|
64
|
+
* `default_action_account_rate_limit`'s). Both spine binaries refuse to boot
|
|
65
|
+
* when it is set without `ACTION_RATE_LIMIT_ENABLED_ENV` or is not a positive
|
|
66
|
+
* integer, so a suite never asserts a throttle the backend didn't build.
|
|
67
|
+
*/
|
|
68
|
+
export declare const ACTION_RATE_LIMIT_MAX_ATTEMPTS_ENV = "FUZ_ACTION_RATE_LIMIT_MAX_ATTEMPTS";
|
|
69
|
+
/** Options for {@link action_rate_limit_env}. */
|
|
70
|
+
export interface ActionRateLimitEnvOptions {
|
|
71
|
+
readonly enable_action_rate_limit?: boolean;
|
|
72
|
+
readonly action_rate_limit_max_attempts?: number;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The `extra_env` entries carrying the action rate-limit toggles, shared by the
|
|
76
|
+
* TS and Rust backend configs so one option pair drives both impls.
|
|
77
|
+
* `action_rate_limit_max_attempts` is passed through even without the enable
|
|
78
|
+
* flag, so the binary refuses the combination instead of the harness hiding it.
|
|
79
|
+
*/
|
|
80
|
+
export declare const action_rate_limit_env: (options: ActionRateLimitEnvOptions) => Record<string, string>;
|
|
50
81
|
/**
|
|
51
82
|
* Capabilities shared by TS-family backends — same canonical implementation,
|
|
52
83
|
* 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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"}
|
|
@@ -13,6 +13,37 @@ import { default_test_bootstrap_token, default_test_cookie_keys, default_test_ke
|
|
|
13
13
|
* mirroring how `testing_spine_server_node.ts` re-declares `TS_SPINE_DIR_ENV`.)
|
|
14
14
|
*/
|
|
15
15
|
export const LOGIN_RATE_LIMIT_ENABLED_ENV = 'FUZ_LOGIN_RATE_LIMIT_ENABLED';
|
|
16
|
+
/**
|
|
17
|
+
* Env var both spine binaries read to enable their action rate limiters
|
|
18
|
+
* (`'true'` on / unset off) — one per-IP and one per-account limiter, shared by
|
|
19
|
+
* the RPC and WS endpoints (and, on the Rust stub, the auth-family handlers
|
|
20
|
+
* that charge in-handler). The cross-language contract for the action
|
|
21
|
+
* rate-limit cross suite (`ws_action_rate_limit.ts`); same delivery as
|
|
22
|
+
* `LOGIN_RATE_LIMIT_ENABLED_ENV`. Off, the TS spine builds no action limiter
|
|
23
|
+
* and the Rust stub keeps its default posture (only its auth families charge,
|
|
24
|
+
* against an always-on per-account limiter at the production cap).
|
|
25
|
+
*/
|
|
26
|
+
export const ACTION_RATE_LIMIT_ENABLED_ENV = 'FUZ_ACTION_RATE_LIMIT_ENABLED';
|
|
27
|
+
/**
|
|
28
|
+
* Env var replacing both action limiters' `max_attempts` (a positive integer;
|
|
29
|
+
* the windows stay `default_action_ip_rate_limit`'s /
|
|
30
|
+
* `default_action_account_rate_limit`'s). Both spine binaries refuse to boot
|
|
31
|
+
* when it is set without `ACTION_RATE_LIMIT_ENABLED_ENV` or is not a positive
|
|
32
|
+
* integer, so a suite never asserts a throttle the backend didn't build.
|
|
33
|
+
*/
|
|
34
|
+
export const ACTION_RATE_LIMIT_MAX_ATTEMPTS_ENV = 'FUZ_ACTION_RATE_LIMIT_MAX_ATTEMPTS';
|
|
35
|
+
/**
|
|
36
|
+
* The `extra_env` entries carrying the action rate-limit toggles, shared by the
|
|
37
|
+
* TS and Rust backend configs so one option pair drives both impls.
|
|
38
|
+
* `action_rate_limit_max_attempts` is passed through even without the enable
|
|
39
|
+
* flag, so the binary refuses the combination instead of the harness hiding it.
|
|
40
|
+
*/
|
|
41
|
+
export const action_rate_limit_env = (options) => ({
|
|
42
|
+
...(options.enable_action_rate_limit ? { [ACTION_RATE_LIMIT_ENABLED_ENV]: 'true' } : {}),
|
|
43
|
+
...(options.action_rate_limit_max_attempts !== undefined
|
|
44
|
+
? { [ACTION_RATE_LIMIT_MAX_ATTEMPTS_ENV]: String(options.action_rate_limit_max_attempts) }
|
|
45
|
+
: {})
|
|
46
|
+
});
|
|
16
47
|
/**
|
|
17
48
|
* Capabilities shared by TS-family backends — same canonical implementation,
|
|
18
49
|
* 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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import '../assert_dev_env.js';
|
|
2
2
|
import { peer_ping_action } from '../../actions/peer_ping.js';
|
|
3
|
+
import { protocol_actions } from '../../actions/protocol.js';
|
|
3
4
|
import { create_standard_rpc_actions } from '../../auth/standard_rpc_actions.js';
|
|
4
5
|
import { create_all_cell_actions } from '../../auth/all_cell_actions.js';
|
|
5
6
|
import { create_actor_lookup_actions } from '../../auth/actor_lookup_actions.js';
|
|
@@ -7,7 +8,6 @@ import { create_actor_search_actions } from '../../auth/actor_search_actions.js'
|
|
|
7
8
|
import { create_testing_action_manifest_action, create_testing_actions } from './testing_reset_actions.js';
|
|
8
9
|
import { test_cell_gated_create_authorize } from './test_cell_gated_create_authorize.js';
|
|
9
10
|
import { spine_roles, spine_session_options } from './default_spine_surface.js';
|
|
10
|
-
import { SPINE_RPC_PATH } from './spine_surface_constants.js';
|
|
11
11
|
/**
|
|
12
12
|
* Build the complete live RPC action list the spine test binary mounts on
|
|
13
13
|
* its single endpoint: the declared `create_standard_rpc_actions` bundle plus
|
|
@@ -54,12 +54,29 @@ export const build_full_spine_rpc_actions = (deps, options) => {
|
|
|
54
54
|
return actions;
|
|
55
55
|
};
|
|
56
56
|
/**
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
57
|
+
* Build the full live mount for both of the spine binary's endpoints: the
|
|
58
|
+
* RPC list, and the WS list that serves the same actions behind the protocol
|
|
59
|
+
* actions.
|
|
60
|
+
*
|
|
61
|
+
* The Rust `testing_spine_stub` serves one action registry on RPC and WS, so
|
|
62
|
+
* mounting the full list on WS keeps the two spines' WS method sets equal —
|
|
63
|
+
* the cell verbs among them, whose dispatcher-charged rate limit
|
|
64
|
+
* `describe_ws_action_rate_limit_cross_tests` drives over a socket. The one
|
|
65
|
+
* difference is `cancel`: a registered protocol action on TS, read-loop-owned
|
|
66
|
+
* (never dispatched) on Rust.
|
|
67
|
+
*
|
|
68
|
+
* @param deps - the backend `AppDeps`
|
|
69
|
+
* @param options - daemon-token state + optional WS notification sender
|
|
70
|
+
* @returns the RPC and WS action lists, built once and sharing handler instances
|
|
62
71
|
*/
|
|
63
|
-
export const
|
|
64
|
-
|
|
65
|
-
|
|
72
|
+
export const build_full_spine_mount = (deps, options) => {
|
|
73
|
+
const rpc_actions = build_full_spine_rpc_actions(deps, options);
|
|
74
|
+
const protocol_methods = new Set(protocol_actions.map((action) => action.spec.method));
|
|
75
|
+
return {
|
|
76
|
+
rpc_actions,
|
|
77
|
+
ws_actions: [
|
|
78
|
+
...protocol_actions,
|
|
79
|
+
...rpc_actions.filter((action) => !protocol_methods.has(action.spec.method))
|
|
80
|
+
]
|
|
81
|
+
};
|
|
82
|
+
};
|
|
@@ -51,6 +51,21 @@ export interface SpineStubBackendConfigOptions {
|
|
|
51
51
|
* TS spine binary wires the equivalent set unconditionally.
|
|
52
52
|
*/
|
|
53
53
|
readonly trusted_proxies?: string;
|
|
54
|
+
/**
|
|
55
|
+
* Enable the action rate limiters (`FUZ_ACTION_RATE_LIMIT_ENABLED=true`) —
|
|
56
|
+
* one per-IP and one per-account limiter shared by the RPC and WS
|
|
57
|
+
* endpoints. Off by default, like `enable_login_rate_limit`; set only for
|
|
58
|
+
* the dedicated security cross project, which drives them through
|
|
59
|
+
* `ws_action_rate_limit.ts`. Mirrors `TsSpineBackendConfigOptions.enable_action_rate_limit`.
|
|
60
|
+
*/
|
|
61
|
+
readonly enable_action_rate_limit?: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Replace both action limiters' `max_attempts`
|
|
64
|
+
* (`FUZ_ACTION_RATE_LIMIT_MAX_ATTEMPTS`) so a suite reaches the cap in a few
|
|
65
|
+
* calls. Requires `enable_action_rate_limit` — the binary refuses to boot
|
|
66
|
+
* otherwise. Mirrors `TsSpineBackendConfigOptions.action_rate_limit_max_attempts`.
|
|
67
|
+
*/
|
|
68
|
+
readonly action_rate_limit_max_attempts?: number;
|
|
54
69
|
}
|
|
55
70
|
/**
|
|
56
71
|
* Build the `BackendConfig` for `testing_spine_stub`. Resolves the binary
|