@fuzdev/fuz_app 0.126.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 +2 -3
- package/dist/http/CLAUDE.md +3 -3
- package/dist/http/surface.d.ts +12 -11
- package/dist/http/surface.d.ts.map +1 -1
- package/dist/http/surface.js +1 -15
- package/dist/rate_limiter.d.ts +19 -1
- package/dist/rate_limiter.d.ts.map +1 -1
- package/dist/rate_limiter.js +23 -0
- package/dist/server/app_server.d.ts +2 -1
- package/dist/server/app_server.d.ts.map +1 -1
- package/dist/server/app_server.js +13 -11
- package/dist/testing/CLAUDE.md +16 -16
- package/dist/testing/app_server.d.ts.map +1 -1
- package/dist/testing/app_server.js +15 -14
- package/dist/testing/cross_backend/default_backend_configs.d.ts +3 -34
- package/dist/testing/cross_backend/default_backend_configs.d.ts.map +1 -1
- package/dist/testing/cross_backend/default_backend_configs.js +1 -31
- package/dist/testing/cross_backend/rust_spine_stub_backend_config.d.ts +1 -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 +3 -3
- 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 +49 -5
- package/dist/testing/cross_backend/testing_server_core.d.ts +11 -11
- package/dist/testing/cross_backend/testing_server_core.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_server_core.js +2 -2
- package/dist/testing/cross_backend/ts_spine_backend_config.d.ts +0 -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 +2 -4
- package/dist/testing/cross_backend/ws_action_rate_limit.d.ts +1 -1
- package/dist/testing/cross_backend/ws_action_rate_limit.d.ts.map +1 -1
- package/dist/testing/middleware.d.ts.map +1 -1
- package/dist/testing/middleware.js +4 -3
- package/dist/testing/stubs.d.ts +5 -2
- package/dist/testing/stubs.d.ts.map +1 -1
- package/dist/testing/stubs.js +19 -4
- package/dist/testing/ws_round_trip.d.ts +7 -31
- package/dist/testing/ws_round_trip.d.ts.map +1 -1
- package/dist/testing/ws_round_trip.js +0 -38
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rust_spine_stub_backend_config.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/rust_spine_stub_backend_config.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AA0C9B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"rust_spine_stub_backend_config.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/rust_spine_stub_backend_config.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AA0C9B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAYzD,uGAAuG;AACvG,eAAO,MAAM,uBAAuB,oCAAoC,CAAC;AAEzE;;;;;;GAMG;AACH,eAAO,MAAM,gCAAgC,6CAA6C,CAAC;AAE3F;;;;;GAKG;AACH,eAAO,MAAM,wCAAwC,6CAA6C,CAAC;AAqBnG,kGAAkG;AAClG,eAAO,MAAM,4BAA4B,OAAO,CAAC;AAEjD,0FAA0F;AAC1F,eAAO,MAAM,oCAAoC,sDACG,CAAC;AAErD,MAAM,WAAW,6BAA6B;IAC7C,8DAA8D;IAC9D,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;;;OAOG;IACH,QAAQ,CAAC,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAC3C;;;;;;OAMG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC;;;;;;OAMG;IACH,QAAQ,CAAC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IAC5C;;;;;OAKG;IACH,QAAQ,CAAC,8BAA8B,CAAC,EAAE,MAAM,CAAC;CACjD;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,8BAA8B,GAC1C,UAAS,6BAAkC,KACzC,aAmDF,CAAC"}
|
|
@@ -38,8 +38,8 @@ import '../assert_dev_env.js';
|
|
|
38
38
|
*/
|
|
39
39
|
import { fileURLToPath } from 'node:url';
|
|
40
40
|
import { build_test_backend_paths } from './build_test_backend_paths.js';
|
|
41
|
-
import { SPINE_EXPECTED_SCHEMA_URL } from './spine_surface_constants.js';
|
|
42
|
-
import {
|
|
41
|
+
import { LOGIN_RATE_LIMIT_ENABLED_ENV, SPINE_EXPECTED_SCHEMA_URL } from './spine_surface_constants.js';
|
|
42
|
+
import { action_rate_limit_env, make_default_rust_backend_config, rust_default_capabilities } from './default_backend_configs.js';
|
|
43
43
|
/** Env var naming the prebuilt `testing_spine_stub` binary. Required when `binary_path` is omitted. */
|
|
44
44
|
export const RUST_SPINE_STUB_BIN_ENV = 'FUZ_TESTING_RUST_SPINE_STUB_BIN';
|
|
45
45
|
/**
|
|
@@ -53,7 +53,7 @@ export const RUST_SPINE_STUB_DATABASE_URL_ENV = 'FUZ_TESTING_RUST_SPINE_STUB_DAT
|
|
|
53
53
|
/**
|
|
54
54
|
* Env var the stub reads for the absolute path of the committed
|
|
55
55
|
* `expected_schema.json` its `/ready` gate introspects against. Pointed at the
|
|
56
|
-
* **same** fixture the TS spine reads (
|
|
56
|
+
* **same** fixture the TS spine reads (`SPINE_EXPECTED_SCHEMA_URL`) —
|
|
57
57
|
* column-presence is engine-portable, so one file is the cross-impl contract.
|
|
58
58
|
*/
|
|
59
59
|
export const RUST_SPINE_STUB_EXPECTED_SCHEMA_PATH_ENV = 'FUZ_RUST_SPINE_STUB_EXPECTED_SCHEMA_PATH';
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import '../assert_dev_env.js';
|
|
2
2
|
/**
|
|
3
|
-
* Pure spine-surface
|
|
4
|
-
*
|
|
3
|
+
* Pure spine-surface constants — wire paths, roles, the fixture URL, and the
|
|
4
|
+
* env-var names the backend configs set for the spawned spine binaries. A
|
|
5
|
+
* hono-free leaf split out of `default_spine_surface.ts`.
|
|
5
6
|
*
|
|
6
7
|
* Cross-process suite modules (which drive a separately-spawned backend binary
|
|
7
8
|
* over HTTP) need only the wire path / role / fixture-URL, not the in-process
|
|
@@ -10,7 +11,13 @@ import '../assert_dev_env.js';
|
|
|
10
11
|
* `session_middleware` → `hono/cookie` — onto a backend-spawning consumer with
|
|
11
12
|
* no `hono` peer installed (a Rust-only spine consumer). Keeping these constants
|
|
12
13
|
* on this handler-free leaf lets such a consumer import the path without the
|
|
13
|
-
* peer. `default_spine_surface.ts`
|
|
14
|
+
* peer. `default_spine_surface.ts` imports the ones it uses from here.
|
|
15
|
+
*
|
|
16
|
+
* The env-var names live here so both sides of each contract share one
|
|
17
|
+
* constant: the backend configs that set them (`default_backend_configs.ts`,
|
|
18
|
+
* `ts_spine_backend_config.ts`, `rust_spine_stub_backend_config.ts`) and the
|
|
19
|
+
* spawned TS spine binary that reads them, which imports this leaf rather than
|
|
20
|
+
* the config builders.
|
|
14
21
|
*
|
|
15
22
|
* @module
|
|
16
23
|
*/
|
|
@@ -56,4 +63,37 @@ export declare const SPINE_PARTICIPANT_ROLE = "participant";
|
|
|
56
63
|
* engine-portable, so one fixture is the cross-impl contract.
|
|
57
64
|
*/
|
|
58
65
|
export declare const SPINE_EXPECTED_SCHEMA_URL: URL;
|
|
66
|
+
/**
|
|
67
|
+
* Env var both spine binaries read to enable their login rate limiters
|
|
68
|
+
* (`'true'` on / unset off). The cross-language contract for the login-security
|
|
69
|
+
* cross project: the TS binary reads it via `runtime.env_get` (a test-only flag,
|
|
70
|
+
* not in `BaseServerEnv`); the Rust `testing_spine_stub` reads it via
|
|
71
|
+
* `std::env::var` — so one backend-config option drives both impls
|
|
72
|
+
* (`ts_spine_backend_config` and `rust_spine_stub_backend_config` set it).
|
|
73
|
+
*/
|
|
74
|
+
export declare const LOGIN_RATE_LIMIT_ENABLED_ENV = "FUZ_LOGIN_RATE_LIMIT_ENABLED";
|
|
75
|
+
/**
|
|
76
|
+
* Env var both spine binaries read to enable their action rate limiters
|
|
77
|
+
* (`'true'` on / unset off) — one per-IP and one per-account limiter, shared by
|
|
78
|
+
* the RPC and WS endpoints (and, on the Rust stub, the auth-family handlers
|
|
79
|
+
* that charge in-handler). The cross-language contract for the action
|
|
80
|
+
* rate-limit cross suite (`ws_action_rate_limit.ts`); same delivery as
|
|
81
|
+
* `LOGIN_RATE_LIMIT_ENABLED_ENV`. Off, neither spine builds an action
|
|
82
|
+
* limiter.
|
|
83
|
+
*/
|
|
84
|
+
export declare const ACTION_RATE_LIMIT_ENABLED_ENV = "FUZ_ACTION_RATE_LIMIT_ENABLED";
|
|
85
|
+
/**
|
|
86
|
+
* Env var replacing both action limiters' `max_attempts` (a positive integer;
|
|
87
|
+
* the windows stay `default_action_ip_rate_limit`'s /
|
|
88
|
+
* `default_action_account_rate_limit`'s). Both spine binaries refuse to boot
|
|
89
|
+
* when it is set without `ACTION_RATE_LIMIT_ENABLED_ENV` or is not a positive
|
|
90
|
+
* integer, so a suite never asserts a throttle the backend didn't build.
|
|
91
|
+
*/
|
|
92
|
+
export declare const ACTION_RATE_LIMIT_MAX_ATTEMPTS_ENV = "FUZ_ACTION_RATE_LIMIT_MAX_ATTEMPTS";
|
|
93
|
+
/**
|
|
94
|
+
* Env var naming the TS spine backend's root dir, set by
|
|
95
|
+
* `ts_spine_backend_config`; the spawned binary writes its daemon token to
|
|
96
|
+
* `{dir}/run/daemon_token`, which must match `bootstrap.daemon_token_path`.
|
|
97
|
+
*/
|
|
98
|
+
export declare const TS_SPINE_DIR_ENV = "FUZ_TESTING_TS_SPINE_DIR";
|
|
59
99
|
//# sourceMappingURL=spine_surface_constants.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spine_surface_constants.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/spine_surface_constants.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B
|
|
1
|
+
{"version":3,"file":"spine_surface_constants.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/spine_surface_constants.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,iEAAiE;AACjE,eAAO,MAAM,cAAc,aAAa,CAAC;AAEzC;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,4BAA4B,CAAC;AAExD;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,gBAAgB,CAAC;AAEpD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,gBAAgB,CAAC;AAEpD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,yBAAyB,EAAE,GAAwD,CAAC;AAEjG;;;;;;;GAOG;AACH,eAAO,MAAM,4BAA4B,iCAAiC,CAAC;AAE3E;;;;;;;;GAQG;AACH,eAAO,MAAM,6BAA6B,kCAAkC,CAAC;AAE7E;;;;;;GAMG;AACH,eAAO,MAAM,kCAAkC,uCAAuC,CAAC;AAEvF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,6BAA6B,CAAC"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import '../assert_dev_env.js';
|
|
2
2
|
/**
|
|
3
|
-
* Pure spine-surface
|
|
4
|
-
*
|
|
3
|
+
* Pure spine-surface constants — wire paths, roles, the fixture URL, and the
|
|
4
|
+
* env-var names the backend configs set for the spawned spine binaries. A
|
|
5
|
+
* hono-free leaf split out of `default_spine_surface.ts`.
|
|
5
6
|
*
|
|
6
7
|
* Cross-process suite modules (which drive a separately-spawned backend binary
|
|
7
8
|
* over HTTP) need only the wire path / role / fixture-URL, not the in-process
|
|
@@ -10,7 +11,13 @@ import '../assert_dev_env.js';
|
|
|
10
11
|
* `session_middleware` → `hono/cookie` — onto a backend-spawning consumer with
|
|
11
12
|
* no `hono` peer installed (a Rust-only spine consumer). Keeping these constants
|
|
12
13
|
* on this handler-free leaf lets such a consumer import the path without the
|
|
13
|
-
* peer. `default_spine_surface.ts`
|
|
14
|
+
* peer. `default_spine_surface.ts` imports the ones it uses from here.
|
|
15
|
+
*
|
|
16
|
+
* The env-var names live here so both sides of each contract share one
|
|
17
|
+
* constant: the backend configs that set them (`default_backend_configs.ts`,
|
|
18
|
+
* `ts_spine_backend_config.ts`, `rust_spine_stub_backend_config.ts`) and the
|
|
19
|
+
* spawned TS spine binary that reads them, which imports this leaf rather than
|
|
20
|
+
* the config builders.
|
|
14
21
|
*
|
|
15
22
|
* @module
|
|
16
23
|
*/
|
|
@@ -56,3 +63,36 @@ export const SPINE_PARTICIPANT_ROLE = 'participant';
|
|
|
56
63
|
* engine-portable, so one fixture is the cross-impl contract.
|
|
57
64
|
*/
|
|
58
65
|
export const SPINE_EXPECTED_SCHEMA_URL = new URL('./expected_schema.json', import.meta.url);
|
|
66
|
+
/**
|
|
67
|
+
* Env var both spine binaries read to enable their login rate limiters
|
|
68
|
+
* (`'true'` on / unset off). The cross-language contract for the login-security
|
|
69
|
+
* cross project: the TS binary reads it via `runtime.env_get` (a test-only flag,
|
|
70
|
+
* not in `BaseServerEnv`); the Rust `testing_spine_stub` reads it via
|
|
71
|
+
* `std::env::var` — so one backend-config option drives both impls
|
|
72
|
+
* (`ts_spine_backend_config` and `rust_spine_stub_backend_config` set it).
|
|
73
|
+
*/
|
|
74
|
+
export const LOGIN_RATE_LIMIT_ENABLED_ENV = 'FUZ_LOGIN_RATE_LIMIT_ENABLED';
|
|
75
|
+
/**
|
|
76
|
+
* Env var both spine binaries read to enable their action rate limiters
|
|
77
|
+
* (`'true'` on / unset off) — one per-IP and one per-account limiter, shared by
|
|
78
|
+
* the RPC and WS endpoints (and, on the Rust stub, the auth-family handlers
|
|
79
|
+
* that charge in-handler). The cross-language contract for the action
|
|
80
|
+
* rate-limit cross suite (`ws_action_rate_limit.ts`); same delivery as
|
|
81
|
+
* `LOGIN_RATE_LIMIT_ENABLED_ENV`. Off, neither spine builds an action
|
|
82
|
+
* limiter.
|
|
83
|
+
*/
|
|
84
|
+
export const ACTION_RATE_LIMIT_ENABLED_ENV = 'FUZ_ACTION_RATE_LIMIT_ENABLED';
|
|
85
|
+
/**
|
|
86
|
+
* Env var replacing both action limiters' `max_attempts` (a positive integer;
|
|
87
|
+
* the windows stay `default_action_ip_rate_limit`'s /
|
|
88
|
+
* `default_action_account_rate_limit`'s). Both spine binaries refuse to boot
|
|
89
|
+
* when it is set without `ACTION_RATE_LIMIT_ENABLED_ENV` or is not a positive
|
|
90
|
+
* integer, so a suite never asserts a throttle the backend didn't build.
|
|
91
|
+
*/
|
|
92
|
+
export const ACTION_RATE_LIMIT_MAX_ATTEMPTS_ENV = 'FUZ_ACTION_RATE_LIMIT_MAX_ATTEMPTS';
|
|
93
|
+
/**
|
|
94
|
+
* Env var naming the TS spine backend's root dir, set by
|
|
95
|
+
* `ts_spine_backend_config`; the spawned binary writes its daemon token to
|
|
96
|
+
* `{dir}/run/daemon_token`, which must match `bootstrap.daemon_token_path`.
|
|
97
|
+
*/
|
|
98
|
+
export const TS_SPINE_DIR_ENV = 'FUZ_TESTING_TS_SPINE_DIR';
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import '../assert_dev_env.js';
|
|
2
2
|
import type { RpcPathCrossSuiteOptions } from './setup.js';
|
|
3
3
|
/** Options for the testing-backdoor negative-credential suite. */
|
|
4
|
-
export
|
|
4
|
+
export interface TestingBackdoorCrossTestOptions extends RpcPathCrossSuiteOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Where the backend's WebSocket endpoint is, for the session-socket cases.
|
|
7
|
+
* Pass it when the backend serves the `_testing_*` actions on its WS
|
|
8
|
+
* endpoint too; omitted, those cases are skipped.
|
|
9
|
+
*/
|
|
10
|
+
readonly ws?: {
|
|
11
|
+
/** Base URL the backend is reachable at (e.g. `http://localhost:1178`). */
|
|
12
|
+
readonly base_url: string;
|
|
13
|
+
/** WebSocket endpoint path on the backend (e.g. `/api/ws`). */
|
|
14
|
+
readonly ws_path: string;
|
|
15
|
+
/** Origin for the upgrade. Defaults to `base_url`. */
|
|
16
|
+
readonly origin?: string;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
5
19
|
export declare const describe_testing_backdoor_cross_tests: (options: TestingBackdoorCrossTestOptions) => void;
|
|
6
20
|
//# sourceMappingURL=testing_backdoor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing_backdoor.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/testing_backdoor.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"testing_backdoor.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/testing_backdoor.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AA2E9B,OAAO,KAAK,EAAE,wBAAwB,EAAe,MAAM,YAAY,CAAC;AA0ExE,kEAAkE;AAClE,MAAM,WAAW,+BAAgC,SAAQ,wBAAwB;IAChF;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,EAAE;QACb,2EAA2E;QAC3E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,+DAA+D;QAC/D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QACzB,sDAAsD;QACtD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;KACzB,CAAC;CACF;AAED,eAAO,MAAM,qCAAqC,GACjD,SAAS,+BAA+B,KACtC,IAyEF,CAAC"}
|
|
@@ -29,6 +29,14 @@ import '../assert_dev_env.js';
|
|
|
29
29
|
* `credential_type_required` — same ceiling; an api token cannot reach
|
|
30
30
|
* keeper operations.
|
|
31
31
|
*
|
|
32
|
+
* Over WebSocket (when `ws` is supplied), the same methods sent on a socket
|
|
33
|
+
* opened with the keeper's **session** cookie answer the same `forbidden`
|
|
34
|
+
* error with `credential_type_required`: the upgrade admits a session, but
|
|
35
|
+
* each message runs the same per-action gates as HTTP RPC, so a socket is no
|
|
36
|
+
* way around the daemon-token channel. Anonymous and bearer have no WS case —
|
|
37
|
+
* an anonymous upgrade is refused before any message, and the upgrade client
|
|
38
|
+
* threads cookies.
|
|
39
|
+
*
|
|
32
40
|
* Each method is sent with **valid** params so each case varies only the
|
|
33
41
|
* credential. (Validation runs after the gates — the order is 401 → authz →
|
|
34
42
|
* 403 → 429 → 400 — so the shapes are belt-and-suspenders here rather than load-
|
|
@@ -45,7 +53,9 @@ import '../assert_dev_env.js';
|
|
|
45
53
|
* binary, not the in-process app — like the ws/sse suites. Wire from a
|
|
46
54
|
* `*.cross.test.ts`. Requires the standard `_testing_*` actions mounted (the
|
|
47
55
|
* same precondition `default_cross_process_setup` already imposes for its
|
|
48
|
-
* per-test `_testing_reset`); ungated, since every cross
|
|
56
|
+
* per-test `_testing_reset`); the HTTP cases are ungated, since every cross
|
|
57
|
+
* backend mounts them, and the WS cases run when `ws` is passed — for a
|
|
58
|
+
* backend that also serves them on its WS endpoint.
|
|
49
59
|
*
|
|
50
60
|
* `$lib`-free by contract (relative specifiers only), like the sibling
|
|
51
61
|
* cross-backend suites.
|
|
@@ -54,7 +64,11 @@ import '../assert_dev_env.js';
|
|
|
54
64
|
*/
|
|
55
65
|
import { describe, test, assert } from 'vitest';
|
|
56
66
|
import { ERROR_CREDENTIAL_TYPE_REQUIRED } from '../../http/error_schemas.js';
|
|
67
|
+
import { JSONRPC_ERROR_CODES } from '../../http/jsonrpc_errors.js';
|
|
57
68
|
import { rpc_call } from '../rpc_helpers.js';
|
|
69
|
+
import { create_admitted_ws_transport } from '../transports/ws_transport.js';
|
|
70
|
+
import { is_response_for } from '../transports/ws_client.js';
|
|
71
|
+
import { test_if } from './capabilities.js';
|
|
58
72
|
import { SPINE_RPC_PATH } from './spine_surface_constants.js';
|
|
59
73
|
/** A well-formed UUID that never names a real row. */
|
|
60
74
|
const NIL_UUID = '00000000-0000-0000-0000-000000000000';
|
|
@@ -81,18 +95,21 @@ const principals = [
|
|
|
81
95
|
{
|
|
82
96
|
name: 'anonymous',
|
|
83
97
|
status: 401,
|
|
98
|
+
code: JSONRPC_ERROR_CODES.unauthenticated,
|
|
84
99
|
// Fresh jar so the keeper cookie (cross-process) can't leak in.
|
|
85
100
|
resolve: (f) => ({ transport: f.fresh_transport(), headers: {} })
|
|
86
101
|
},
|
|
87
102
|
{
|
|
88
103
|
name: 'session',
|
|
89
104
|
status: 403,
|
|
105
|
+
code: JSONRPC_ERROR_CODES.forbidden,
|
|
90
106
|
reason: ERROR_CREDENTIAL_TYPE_REQUIRED,
|
|
91
107
|
resolve: (f) => ({ transport: f.transport, headers: f.create_session_headers() })
|
|
92
108
|
},
|
|
93
109
|
{
|
|
94
110
|
name: 'bearer',
|
|
95
111
|
status: 403,
|
|
112
|
+
code: JSONRPC_ERROR_CODES.forbidden,
|
|
96
113
|
reason: ERROR_CREDENTIAL_TYPE_REQUIRED,
|
|
97
114
|
// Bearer is discarded in a browser context, so suppress Origin (empty
|
|
98
115
|
// jar + no Origin) — the credential must actually resolve so the refusal
|
|
@@ -105,7 +122,7 @@ const principals = [
|
|
|
105
122
|
}
|
|
106
123
|
];
|
|
107
124
|
export const describe_testing_backdoor_cross_tests = (options) => {
|
|
108
|
-
const { setup_test } = options;
|
|
125
|
+
const { setup_test, ws } = options;
|
|
109
126
|
const rpc_path = options.rpc_path ?? SPINE_RPC_PATH;
|
|
110
127
|
describe('testing backdoor credential gate parity', () => {
|
|
111
128
|
for (const { method, params } of backdoor_methods) {
|
|
@@ -125,12 +142,39 @@ export const describe_testing_backdoor_cross_tests = (options) => {
|
|
|
125
142
|
assert.ok(!res.ok, `${label}: expected denial (${principal.status}) but the call succeeded`);
|
|
126
143
|
assert.strictEqual(res.status, principal.status, `${label}: status`);
|
|
127
144
|
// `!res.ok` narrows `res` to the error variant for `res.error`.
|
|
128
|
-
if (
|
|
129
|
-
|
|
130
|
-
|
|
145
|
+
if (!res.ok) {
|
|
146
|
+
assert.strictEqual(res.error.code, principal.code, `${label}: error.code`);
|
|
147
|
+
if (principal.reason !== undefined) {
|
|
148
|
+
const reason = res.error.data?.reason;
|
|
149
|
+
assert.strictEqual(reason, principal.reason, `${label}: error.data.reason`);
|
|
150
|
+
}
|
|
131
151
|
}
|
|
132
152
|
});
|
|
133
153
|
}
|
|
134
154
|
}
|
|
155
|
+
for (const { method, params } of backdoor_methods) {
|
|
156
|
+
test_if(ws !== undefined, `${method} over a session socket → forbidden ${ERROR_CREDENTIAL_TYPE_REQUIRED}`, async () => {
|
|
157
|
+
const fixture = await setup_test();
|
|
158
|
+
const client = await create_admitted_ws_transport({
|
|
159
|
+
base_url: ws.base_url,
|
|
160
|
+
ws_path: ws.ws_path,
|
|
161
|
+
cookies: fixture.transport.cookies(),
|
|
162
|
+
origin: ws.origin
|
|
163
|
+
});
|
|
164
|
+
try {
|
|
165
|
+
const id = `backdoor_${method}`;
|
|
166
|
+
await client.send({ jsonrpc: '2.0', id, method, params });
|
|
167
|
+
const frame = await client.wait_for(is_response_for(id));
|
|
168
|
+
const label = `${method} session socket`;
|
|
169
|
+
assert.ok(frame.error, `${label}: expected a credential_type_required error but the call succeeded`);
|
|
170
|
+
assert.strictEqual(frame.error.code, JSONRPC_ERROR_CODES.forbidden, `${label}: code`);
|
|
171
|
+
const reason = frame.error.data?.reason;
|
|
172
|
+
assert.strictEqual(reason, ERROR_CREDENTIAL_TYPE_REQUIRED, `${label}: error.data.reason`);
|
|
173
|
+
}
|
|
174
|
+
finally {
|
|
175
|
+
await client.close();
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
}
|
|
135
179
|
});
|
|
136
180
|
};
|
|
@@ -9,13 +9,13 @@ import '../assert_dev_env.js';
|
|
|
9
9
|
* orchestration — stale-daemon check, daemon-info write, serve, post-serve
|
|
10
10
|
* WS attach, graceful shutdown — and delegates the runtime-boundary
|
|
11
11
|
* primitives (HTTP serve, WS upgrade construction, signals, pid, exit) to a
|
|
12
|
-
*
|
|
12
|
+
* `TestingServerAdapter`. The shipped adapters are
|
|
13
13
|
* `testing/cross_backend/testing_server_node.ts` (`@hono/node-server` + `@hono/node-ws`),
|
|
14
14
|
* `testing/cross_backend/testing_server_deno.ts` (`Deno.serve` + `@hono/deno`), and
|
|
15
15
|
* `testing/cross_backend/testing_server_bun.ts` (`Bun.serve` + `@hono/bun`).
|
|
16
16
|
*
|
|
17
17
|
* The app itself — routes, RPC, DB, `_testing_reset`, WS endpoints — is the
|
|
18
|
-
* caller's
|
|
18
|
+
* caller's `StartTestingServerOptions.build_app` seam, so this core
|
|
19
19
|
* stays domain-free. WebSocket endpoints mount through `create_app_server`'s
|
|
20
20
|
* `ws_endpoints`: `build_app` asks its context to prepare the runtime's
|
|
21
21
|
* upgrade helper and passes the resulting factory as
|
|
@@ -49,7 +49,7 @@ export interface ServeHandle {
|
|
|
49
49
|
/** Adapter-specific server ref for post-serve hooks. Type-erased at the seam. */
|
|
50
50
|
native?: unknown;
|
|
51
51
|
}
|
|
52
|
-
/** Options for
|
|
52
|
+
/** Options for `TestingServerAdapter.prepare_websocket`. */
|
|
53
53
|
export interface PrepareWebsocketOptions {
|
|
54
54
|
/**
|
|
55
55
|
* Largest inbound WebSocket message, in bytes — pass the largest
|
|
@@ -70,7 +70,7 @@ export interface PrepareWebsocketOptions {
|
|
|
70
70
|
*
|
|
71
71
|
* `create_upgrade_websocket` is the factory a build passes to
|
|
72
72
|
* `create_app_server` as `AppServerOptions.create_upgrade_websocket`.
|
|
73
|
-
* `attach_to_server` runs after `serve()` returns a
|
|
73
|
+
* `attach_to_server` runs after `serve()` returns a `ServeHandle` —
|
|
74
74
|
* Node uses it for `injectWebSocket(server)`, and it does nothing when the
|
|
75
75
|
* factory was never called (no `ws_endpoints`); Deno and Bun leave it
|
|
76
76
|
* undefined.
|
|
@@ -83,7 +83,7 @@ export interface PreparedWebsocket {
|
|
|
83
83
|
* Runtime adapter contract for the test-binary entry. Each adapter
|
|
84
84
|
* (`testing/cross_backend/testing_server_node.ts`, `testing/cross_backend/testing_server_deno.ts`,
|
|
85
85
|
* `testing/cross_backend/testing_server_bun.ts`) implements this and hands the shape to
|
|
86
|
-
*
|
|
86
|
+
* `start_testing_server`.
|
|
87
87
|
*/
|
|
88
88
|
export interface TestingServerAdapter {
|
|
89
89
|
/** Human-readable runtime label for log output (e.g. `"Node"`, `"Deno"`). */
|
|
@@ -94,7 +94,7 @@ export interface TestingServerAdapter {
|
|
|
94
94
|
get_connection_ip: (c: Context) => string | undefined;
|
|
95
95
|
/** Prepare the runtime's WS upgrade helper and its post-serve attach step. */
|
|
96
96
|
prepare_websocket: (options?: PrepareWebsocketOptions) => PreparedWebsocket;
|
|
97
|
-
/** Bind `app.fetch` to `port` on `hostname`; return a
|
|
97
|
+
/** Bind `app.fetch` to `port` on `hostname`; return a `ServeHandle`. */
|
|
98
98
|
serve: (options: {
|
|
99
99
|
fetch: Hono['fetch'];
|
|
100
100
|
port: number;
|
|
@@ -107,7 +107,7 @@ export interface TestingServerAdapter {
|
|
|
107
107
|
/** Forceful exit on graceful-shutdown completion or fatal error. */
|
|
108
108
|
exit: (code: number) => never;
|
|
109
109
|
}
|
|
110
|
-
/** What the core hands a
|
|
110
|
+
/** What the core hands a `StartTestingServerOptions.build_app` seam. */
|
|
111
111
|
export interface BuildTestingAppContext {
|
|
112
112
|
/**
|
|
113
113
|
* Prepare the runtime adapter's WS upgrade helper and return the factory
|
|
@@ -120,7 +120,7 @@ export interface BuildTestingAppContext {
|
|
|
120
120
|
*/
|
|
121
121
|
prepare_websocket: (options?: PrepareWebsocketOptions) => (app: Hono) => UpgradeWebSocket;
|
|
122
122
|
}
|
|
123
|
-
/** The assembled app a
|
|
123
|
+
/** The assembled app a `StartTestingServerOptions.build_app` seam returns. */
|
|
124
124
|
export interface BuiltTestingApp {
|
|
125
125
|
/** The assembled Hono app (HTTP routes, RPC, and WS endpoints already mounted). */
|
|
126
126
|
app: Hono;
|
|
@@ -131,7 +131,7 @@ export interface BuiltTestingApp {
|
|
|
131
131
|
*/
|
|
132
132
|
close: () => Promise<void>;
|
|
133
133
|
}
|
|
134
|
-
/** Options for
|
|
134
|
+
/** Options for `start_testing_server`. */
|
|
135
135
|
export interface StartTestingServerOptions {
|
|
136
136
|
/** Runtime-boundary adapter (Node or Deno). */
|
|
137
137
|
adapter: TestingServerAdapter;
|
|
@@ -173,8 +173,8 @@ export declare const is_loopback_host: (host: string) => boolean;
|
|
|
173
173
|
*
|
|
174
174
|
* Mirrors a production `start_server` at the surface level — stale-daemon
|
|
175
175
|
* check, daemon-info write, bind, graceful shutdown — but the app is the
|
|
176
|
-
* caller's no-domain (or domain)
|
|
177
|
-
* and the runtime boundary is the
|
|
176
|
+
* caller's no-domain (or domain) `StartTestingServerOptions.build_app`
|
|
177
|
+
* and the runtime boundary is the `TestingServerAdapter`. Refuses any
|
|
178
178
|
* non-loopback bind host (the test binary must stay on loopback — see
|
|
179
179
|
* `is_loopback_host`).
|
|
180
180
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing_server_core.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/testing_server_core.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAU,KAAK,MAAM,IAAI,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAG5E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEzD;;;;;;;;GAQG;AACH,MAAM,WAAW,WAAW;IAC3B,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,iFAAiF;IACjF,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,
|
|
1
|
+
{"version":3,"file":"testing_server_core.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/testing_server_core.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,8 +19,8 @@ export const is_loopback_host = (host) => {
|
|
|
19
19
|
*
|
|
20
20
|
* Mirrors a production `start_server` at the surface level — stale-daemon
|
|
21
21
|
* check, daemon-info write, bind, graceful shutdown — but the app is the
|
|
22
|
-
* caller's no-domain (or domain)
|
|
23
|
-
* and the runtime boundary is the
|
|
22
|
+
* caller's no-domain (or domain) `StartTestingServerOptions.build_app`
|
|
23
|
+
* and the runtime boundary is the `TestingServerAdapter`. Refuses any
|
|
24
24
|
* non-loopback bind host (the test binary must stay on loopback — see
|
|
25
25
|
* `is_loopback_host`).
|
|
26
26
|
*/
|
|
@@ -17,8 +17,6 @@ import '../assert_dev_env.js';
|
|
|
17
17
|
* @module
|
|
18
18
|
*/
|
|
19
19
|
import type { BackendConfig } from './backend_config.js';
|
|
20
|
-
/** Env var naming the backend root dir; `{dir}/run/daemon_token` must match `bootstrap.daemon_token_path`. */
|
|
21
|
-
export declare const TS_SPINE_DIR_ENV = "FUZ_TESTING_TS_SPINE_DIR";
|
|
22
20
|
/** Default port for the Node TS spine binary — slots beside the Rust `spine_stub` (1177). */
|
|
23
21
|
export declare const TS_SPINE_NODE_DEFAULT_PORT = 1178;
|
|
24
22
|
/** Default port for the Deno TS spine binary. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ts_spine_backend_config.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/ts_spine_backend_config.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"ts_spine_backend_config.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/ts_spine_backend_config.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAsDzD,6FAA6F;AAC7F,eAAO,MAAM,0BAA0B,OAAO,CAAC;AAE/C,iDAAiD;AACjD,eAAO,MAAM,0BAA0B,OAAO,CAAC;AAE/C,gDAAgD;AAChD,eAAO,MAAM,yBAAyB,OAAO,CAAC;AAE9C,yDAAyD;AACzD,eAAO,MAAM,mBAAmB,wDAAwD,CAAC;AAEzF,yDAAyD;AACzD,eAAO,MAAM,mBAAmB,wDAAwD,CAAC;AAEzF,wDAAwD;AACxD,eAAO,MAAM,kBAAkB,uDAAuD,CAAC;AAEvF,MAAM,WAAW,2BAA2B;IAC3C,mFAAmF;IACnF,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,8DAA8D;IAC9D,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B;;;;;;;;;OASG;IACH,QAAQ,CAAC,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAC3C;;;;;;OAMG;IACH,QAAQ,CAAC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IAC5C;;;;;OAKG;IACH,QAAQ,CAAC,8BAA8B,CAAC,EAAE,MAAM,CAAC;CACjD;AAWD;;;GAGG;AACH,eAAO,MAAM,4BAA4B,GACxC,UAAS,2BAAgC,KACvC,aAoBF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,2BAA2B,GACvC,UAAS,2BAAgC,KACvC,aAoBF,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,4BAA4B,GACxC,UAAS,2BAAgC,KACvC,aAiCF,CAAC"}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import '../assert_dev_env.js';
|
|
2
2
|
import { build_test_backend_paths } from './build_test_backend_paths.js';
|
|
3
|
-
import {
|
|
4
|
-
import { SPINE_SSE_PATH } from './spine_surface_constants.js';
|
|
5
|
-
/** Env var naming the backend root dir; `{dir}/run/daemon_token` must match `bootstrap.daemon_token_path`. */
|
|
6
|
-
export const TS_SPINE_DIR_ENV = 'FUZ_TESTING_TS_SPINE_DIR';
|
|
3
|
+
import { action_rate_limit_env, make_default_ts_backend_config, ts_default_capabilities } from './default_backend_configs.js';
|
|
4
|
+
import { LOGIN_RATE_LIMIT_ENABLED_ENV, SPINE_SSE_PATH, TS_SPINE_DIR_ENV } from './spine_surface_constants.js';
|
|
7
5
|
/**
|
|
8
6
|
* Capabilities for the TS spine binary — `ts_default_capabilities` plus `sse`
|
|
9
7
|
* (the binary wires `audit_log_sse`), `ready` (the binary live-mounts the
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import '../assert_dev_env.js';
|
|
2
2
|
import type { SetupTest } from './setup.js';
|
|
3
|
-
/** Options for
|
|
3
|
+
/** Options for `describe_ws_action_rate_limit_cross_tests`. */
|
|
4
4
|
export interface WsActionRateLimitCrossTestOptions {
|
|
5
5
|
/** Per-test fixture producer (cross-process only — see the module doc). */
|
|
6
6
|
readonly setup_test: SetupTest;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ws_action_rate_limit.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/ws_action_rate_limit.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAmE9B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAyC5C
|
|
1
|
+
{"version":3,"file":"ws_action_rate_limit.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/ws_action_rate_limit.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAmE9B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAyC5C,+DAA+D;AAC/D,MAAM,WAAW,iCAAiC;IACjD,2EAA2E;IAC3E,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC;IAC/B,2EAA2E;IAC3E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,gDAAgD;IAChD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,yEAAyE;IACzE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC9B;AAkBD;;;;GAIG;AACH,eAAO,MAAM,yCAAyC,GACrD,SAAS,iCAAiC,KACxC,IAqRF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAE7B;;;;;;;;GAQG;AAEH,OAAO,EAAE,EAAE,EAA0B,MAAM,QAAQ,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/middleware.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,7 @@ import { vi, test, assert, describe } from 'vitest';
|
|
|
12
12
|
import { Hono } from 'hono';
|
|
13
13
|
import { Logger } from '@fuzdev/fuz_util/log.ts';
|
|
14
14
|
import { create_bearer_auth_middleware } from '../auth/bearer_auth.js';
|
|
15
|
+
import { AUTH_MIDDLEWARE_PATH } from '../auth/middleware.js';
|
|
15
16
|
import { query_validate_api_token } from '../auth/api_token_queries.js';
|
|
16
17
|
import { query_account_by_id, query_actor_by_id, query_active_actors_by_account } from '../auth/account_queries.js';
|
|
17
18
|
import { query_role_grant_find_active_for_actor } from '../auth/role_grant_queries.js';
|
|
@@ -117,7 +118,7 @@ export const create_bearer_auth_test_app = (tc) => {
|
|
|
117
118
|
c.set('client_ip', TEST_CLIENT_IP);
|
|
118
119
|
await next();
|
|
119
120
|
});
|
|
120
|
-
app.use(
|
|
121
|
+
app.use(AUTH_MIDDLEWARE_PATH, bearer_middleware);
|
|
121
122
|
// route handler echoes the account-grain identity the middleware writes
|
|
122
123
|
// (bearer auth sets `ACCOUNT_ID_KEY` + `CREDENTIAL_TYPE_KEY` +
|
|
123
124
|
// `AUTH_API_TOKEN_ID_KEY`; it never builds the full request context —
|
|
@@ -230,8 +231,8 @@ export const create_test_middleware_stack_app = (options) => {
|
|
|
230
231
|
const bearer_mw = create_bearer_auth_middleware(STUB_DEPS, new Logger('test', { level: 'off' }));
|
|
231
232
|
const app = new Hono();
|
|
232
233
|
app.use('*', proxy_mw);
|
|
233
|
-
app.use(
|
|
234
|
-
app.use(
|
|
234
|
+
app.use(AUTH_MIDDLEWARE_PATH, origin_mw);
|
|
235
|
+
app.use(AUTH_MIDDLEWARE_PATH, bearer_mw);
|
|
235
236
|
// echo route for assertions — exposes the account-grain identity bearer
|
|
236
237
|
// auth writes (`ACCOUNT_ID_KEY`); the full request context is the
|
|
237
238
|
// dispatcher's authorization phase concern, not middleware.
|
package/dist/testing/stubs.d.ts
CHANGED
|
@@ -132,7 +132,8 @@ export interface CreateTestAppSurfaceSpecOptions {
|
|
|
132
132
|
* The server's origin allowlist — `AppServerOptions.allowed_origins`.
|
|
133
133
|
* Read only as the default for a `ws_endpoints` spec that declares no
|
|
134
134
|
* `allowed_origins`, as `create_app_server` does; required when any spec
|
|
135
|
-
* omits its own,
|
|
135
|
+
* omits its own — without it, such a spec throws, since the surface records
|
|
136
|
+
* the exact patterns the upgrade gate matches.
|
|
136
137
|
*/
|
|
137
138
|
allowed_origins?: ReadonlyArray<RegExp>;
|
|
138
139
|
/** Transform middleware array (e.g., zap's `extend_middleware_for_zap_binary`). */
|
|
@@ -167,7 +168,9 @@ export interface CreateTestAppSurfaceSpecOptions {
|
|
|
167
168
|
*
|
|
168
169
|
* @param options - surface spec options
|
|
169
170
|
* @returns the surface spec for the standard suites
|
|
170
|
-
* @throws Error when an endpoint path is outside `AUTH_MIDDLEWARE_PATH
|
|
171
|
+
* @throws Error when an endpoint path is outside `AUTH_MIDDLEWARE_PATH`, or a
|
|
172
|
+
* `ws_endpoints` spec declares no `allowed_origins` and no `allowed_origins`
|
|
173
|
+
* option is given
|
|
171
174
|
*/
|
|
172
175
|
export declare const create_test_app_surface_spec: (options: CreateTestAppSurfaceSpecOptions) => AppSurfaceSpec;
|
|
173
176
|
//# sourceMappingURL=stubs.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stubs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/stubs.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAa7B,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAE7B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAEjE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACjC,OAAO,EAAsB,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAG3E,OAAO,EAEN,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,
|
|
1
|
+
{"version":3,"file":"stubs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/stubs.ts"],"names":[],"mappings":"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"}
|
package/dist/testing/stubs.js
CHANGED
|
@@ -213,6 +213,21 @@ export const create_stub_app_server_context = (session_options) => {
|
|
|
213
213
|
audit_sse: null
|
|
214
214
|
};
|
|
215
215
|
};
|
|
216
|
+
/**
|
|
217
|
+
* Narrow a WS endpoint spec that carries its own `allowed_origins` — the only
|
|
218
|
+
* way it resolves when no server list is given to default from.
|
|
219
|
+
*
|
|
220
|
+
* @throws Error when the spec declares no `allowed_origins`
|
|
221
|
+
*/
|
|
222
|
+
const to_self_resolved_ws_endpoint = (endpoint) => {
|
|
223
|
+
const { allowed_origins } = endpoint;
|
|
224
|
+
if (!allowed_origins) {
|
|
225
|
+
throw new Error(`create_test_app_surface_spec: ws endpoint ${endpoint.path} has no allowed_origins — ` +
|
|
226
|
+
"pass the server's list as create_test_app_surface_spec's allowed_origins option, " +
|
|
227
|
+
'or set allowed_origins on the spec');
|
|
228
|
+
}
|
|
229
|
+
return { ...endpoint, allowed_origins };
|
|
230
|
+
};
|
|
216
231
|
/**
|
|
217
232
|
* Create an `AppSurfaceSpec` for the standard testing suites.
|
|
218
233
|
*
|
|
@@ -232,7 +247,9 @@ export const create_stub_app_server_context = (session_options) => {
|
|
|
232
247
|
*
|
|
233
248
|
* @param options - surface spec options
|
|
234
249
|
* @returns the surface spec for the standard suites
|
|
235
|
-
* @throws Error when an endpoint path is outside `AUTH_MIDDLEWARE_PATH
|
|
250
|
+
* @throws Error when an endpoint path is outside `AUTH_MIDDLEWARE_PATH`, or a
|
|
251
|
+
* `ws_endpoints` spec declares no `allowed_origins` and no `allowed_origins`
|
|
252
|
+
* option is given
|
|
236
253
|
*/
|
|
237
254
|
export const create_test_app_surface_spec = (options) => {
|
|
238
255
|
const ctx = create_stub_app_server_context(options.session_options);
|
|
@@ -255,11 +272,9 @@ export const create_test_app_surface_spec = (options) => {
|
|
|
255
272
|
// Resolve ws endpoints (mirrors create_app_server). Surface-only —
|
|
256
273
|
// no `register_ws_endpoint` call here, so no `create_upgrade_websocket` needed.
|
|
257
274
|
const declared_ws_endpoints = typeof options.ws_endpoints === 'function' ? options.ws_endpoints(ctx) : options.ws_endpoints;
|
|
258
|
-
// without the server's list, an origin-less spec reaches surface
|
|
259
|
-
// generation unresolved and throws there
|
|
260
275
|
const resolved_ws_endpoints = options.allowed_origins
|
|
261
276
|
? resolve_ws_endpoints(declared_ws_endpoints, options.allowed_origins)
|
|
262
|
-
: declared_ws_endpoints;
|
|
277
|
+
: declared_ws_endpoints?.map(to_self_resolved_ws_endpoint);
|
|
263
278
|
for (const endpoint of resolved_ws_endpoints ?? []) {
|
|
264
279
|
assert_endpoint_in_auth_scope('ws_endpoints', endpoint.path);
|
|
265
280
|
}
|