@fuzdev/fuz_app 0.147.0 → 0.148.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 +6 -4
- package/dist/actions/action_codegen.d.ts +15 -1
- package/dist/actions/action_codegen.d.ts.map +1 -1
- package/dist/actions/action_codegen.js +23 -2
- package/dist/actions/perform_action.js +1 -1
- package/dist/auth/cell_action_specs.d.ts +3 -1
- package/dist/auth/cell_action_specs.d.ts.map +1 -1
- package/dist/auth/cell_action_specs.js +5 -5
- package/dist/auth/cell_actions.d.ts.map +1 -1
- package/dist/auth/cell_actions.js +2 -3
- package/dist/auth/cell_data_schema.d.ts +1 -1
- package/dist/auth/cell_data_schema.js +1 -1
- package/dist/auth/cell_field_action_specs.d.ts +4 -3
- package/dist/auth/cell_field_action_specs.d.ts.map +1 -1
- package/dist/auth/cell_field_action_specs.js +5 -6
- package/dist/auth/cell_field_actions.d.ts.map +1 -1
- package/dist/auth/cell_field_actions.js +8 -1
- package/dist/auth/cell_item_action_specs.d.ts +4 -2
- package/dist/auth/cell_item_action_specs.d.ts.map +1 -1
- package/dist/auth/cell_item_action_specs.js +5 -5
- package/dist/auth/cell_item_actions.d.ts.map +1 -1
- package/dist/auth/cell_item_actions.js +8 -1
- package/dist/auth/role_grant_offer_action_specs.d.ts +2 -0
- package/dist/auth/role_grant_offer_action_specs.d.ts.map +1 -1
- package/dist/auth/role_grant_offer_action_specs.js +3 -1
- package/dist/primitive_schemas.d.ts +1 -1
- package/dist/primitive_schemas.d.ts.map +1 -1
- package/dist/primitive_schemas.js +2 -1
- package/dist/schema_meta.d.ts +20 -0
- package/dist/schema_meta.d.ts.map +1 -1
- package/dist/schema_meta.js +7 -1
- package/dist/testing/CLAUDE.md +720 -114
- package/dist/testing/admin_integration.d.ts.map +1 -1
- package/dist/testing/admin_integration.js +73 -5
- package/dist/testing/adversarial_input.d.ts +0 -47
- package/dist/testing/adversarial_input.d.ts.map +1 -1
- package/dist/testing/adversarial_input.js +4 -340
- package/dist/testing/adversarial_input_cases.d.ts +64 -0
- package/dist/testing/adversarial_input_cases.d.ts.map +1 -0
- package/dist/testing/adversarial_input_cases.js +348 -0
- package/dist/testing/audit_completeness.d.ts.map +1 -1
- package/dist/testing/audit_completeness.js +24 -20
- package/dist/testing/audit_drift_guard.d.ts +27 -1
- package/dist/testing/audit_drift_guard.d.ts.map +1 -1
- package/dist/testing/audit_drift_guard.js +50 -0
- package/dist/testing/cross_backend/account_lifecycle.d.ts.map +1 -1
- package/dist/testing/cross_backend/account_lifecycle.js +29 -12
- package/dist/testing/cross_backend/actor_lookup.d.ts.map +1 -1
- package/dist/testing/cross_backend/actor_lookup.js +7 -25
- package/dist/testing/cross_backend/app_settings.d.ts.map +1 -1
- package/dist/testing/cross_backend/app_settings.js +4 -6
- package/dist/testing/cross_backend/audit_cross_helpers.d.ts +51 -0
- package/dist/testing/cross_backend/audit_cross_helpers.d.ts.map +1 -0
- package/dist/testing/cross_backend/audit_cross_helpers.js +78 -0
- package/dist/testing/cross_backend/backend_config.d.ts +2 -1
- package/dist/testing/cross_backend/backend_config.d.ts.map +1 -1
- package/dist/testing/cross_backend/body_size.d.ts +6 -0
- package/dist/testing/cross_backend/body_size.d.ts.map +1 -1
- package/dist/testing/cross_backend/body_size.js +26 -44
- package/dist/testing/cross_backend/body_size_smuggling.d.ts +5 -0
- package/dist/testing/cross_backend/body_size_smuggling.d.ts.map +1 -1
- package/dist/testing/cross_backend/body_size_smuggling.js +7 -14
- package/dist/testing/cross_backend/build_test_backend_paths.d.ts +3 -1
- package/dist/testing/cross_backend/build_test_backend_paths.d.ts.map +1 -1
- package/dist/testing/cross_backend/capabilities.d.ts +55 -59
- package/dist/testing/cross_backend/capabilities.d.ts.map +1 -1
- package/dist/testing/cross_backend/capabilities.js +20 -23
- package/dist/testing/cross_backend/cargo_binary.d.ts +70 -0
- package/dist/testing/cross_backend/cargo_binary.d.ts.map +1 -0
- package/dist/testing/cross_backend/cargo_binary.js +148 -0
- package/dist/testing/cross_backend/cell_crud.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_crud.js +57 -1
- package/dist/testing/cross_backend/cell_gated_create.d.ts +0 -60
- package/dist/testing/cross_backend/cell_gated_create.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_gated_create.js +9 -487
- package/dist/testing/cross_backend/cell_grant_role.d.ts +14 -2
- package/dist/testing/cross_backend/cell_grant_role.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_grant_role.js +22 -12
- package/dist/testing/cross_backend/cell_moderate.d.ts +66 -0
- package/dist/testing/cross_backend/cell_moderate.d.ts.map +1 -0
- package/dist/testing/cross_backend/cell_moderate.js +511 -0
- package/dist/testing/cross_backend/cell_ref_admission.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_ref_admission.js +1 -1
- package/dist/testing/cross_backend/cell_relations.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_relations.js +40 -19
- package/dist/testing/cross_backend/conformance_case.d.ts +43 -4
- package/dist/testing/cross_backend/conformance_case.d.ts.map +1 -1
- package/dist/testing/cross_backend/conformance_case.js +29 -1
- package/dist/testing/cross_backend/conformance_rpc_auth.d.ts +93 -0
- package/dist/testing/cross_backend/conformance_rpc_auth.d.ts.map +1 -0
- package/dist/testing/cross_backend/conformance_rpc_auth.js +125 -0
- package/dist/testing/cross_backend/conformance_table.d.ts +144 -4
- package/dist/testing/cross_backend/conformance_table.d.ts.map +1 -1
- package/dist/testing/cross_backend/conformance_table.js +297 -65
- package/dist/testing/cross_backend/cookie_attributes.d.ts.map +1 -1
- package/dist/testing/cross_backend/cookie_attributes.js +3 -2
- package/dist/testing/cross_backend/create_cross_backend_global_setup.d.ts +38 -5
- package/dist/testing/cross_backend/create_cross_backend_global_setup.d.ts.map +1 -1
- package/dist/testing/cross_backend/create_cross_backend_global_setup.js +24 -3
- package/dist/testing/cross_backend/create_dual_spawn_global_setup.d.ts +5 -5
- package/dist/testing/cross_backend/create_dual_spawn_global_setup.d.ts.map +1 -1
- package/dist/testing/cross_backend/credential_deadline.d.ts +10 -6
- package/dist/testing/cross_backend/credential_deadline.d.ts.map +1 -1
- package/dist/testing/cross_backend/credential_deadline.js +32 -31
- package/dist/testing/cross_backend/credential_header_robustness.d.ts.map +1 -1
- package/dist/testing/cross_backend/credential_header_robustness.js +4 -6
- package/dist/testing/cross_backend/{cell_cross_helpers.d.ts → cross_rpc.d.ts} +12 -2
- package/dist/testing/cross_backend/cross_rpc.d.ts.map +1 -0
- package/dist/testing/cross_backend/{cell_cross_helpers.js → cross_rpc.js} +31 -7
- package/dist/testing/cross_backend/default_backend_configs.d.ts +56 -61
- package/dist/testing/cross_backend/default_backend_configs.d.ts.map +1 -1
- package/dist/testing/cross_backend/default_backend_configs.js +97 -91
- package/dist/testing/cross_backend/default_spine_surface.d.ts.map +1 -1
- package/dist/testing/cross_backend/default_spine_surface.js +2 -2
- package/dist/testing/cross_backend/differential.d.ts +126 -0
- package/dist/testing/cross_backend/differential.d.ts.map +1 -0
- package/dist/testing/cross_backend/differential.js +201 -0
- package/dist/testing/cross_backend/differential_normalize.d.ts +150 -0
- package/dist/testing/cross_backend/differential_normalize.d.ts.map +1 -0
- package/dist/testing/cross_backend/differential_normalize.js +153 -0
- package/dist/testing/cross_backend/fact_serving.d.ts.map +1 -1
- package/dist/testing/cross_backend/fact_serving.js +27 -17
- package/dist/testing/cross_backend/full_spine_mount.d.ts +15 -0
- package/dist/testing/cross_backend/full_spine_mount.d.ts.map +1 -1
- package/dist/testing/cross_backend/full_spine_mount.js +55 -1
- package/dist/testing/cross_backend/identity_parity.d.ts.map +1 -1
- package/dist/testing/cross_backend/identity_parity.js +6 -5
- package/dist/testing/cross_backend/in_process_setup.d.ts +12 -2
- package/dist/testing/cross_backend/in_process_setup.d.ts.map +1 -1
- package/dist/testing/cross_backend/in_process_setup.js +10 -7
- package/dist/testing/cross_backend/login_security.d.ts.map +1 -1
- package/dist/testing/cross_backend/login_security.js +13 -18
- package/dist/testing/cross_backend/origin.js +1 -1
- package/dist/testing/cross_backend/origin_conformance.js +1 -1
- package/dist/testing/cross_backend/origin_scope.d.ts +6 -0
- package/dist/testing/cross_backend/origin_scope.d.ts.map +1 -1
- package/dist/testing/cross_backend/origin_scope.js +13 -12
- package/dist/testing/cross_backend/peer_ping_ws.d.ts +2 -5
- package/dist/testing/cross_backend/peer_ping_ws.d.ts.map +1 -1
- package/dist/testing/cross_backend/peer_ping_ws.js +14 -24
- package/dist/testing/cross_backend/postgres_database.d.ts +85 -0
- package/dist/testing/cross_backend/postgres_database.d.ts.map +1 -0
- package/dist/testing/cross_backend/postgres_database.js +140 -0
- package/dist/testing/cross_backend/provided_context.d.ts +28 -0
- package/dist/testing/cross_backend/provided_context.d.ts.map +1 -0
- package/dist/testing/cross_backend/provided_context.js +35 -0
- package/dist/testing/cross_backend/query_shape.d.ts.map +1 -1
- package/dist/testing/cross_backend/query_shape.js +10 -12
- package/dist/testing/cross_backend/ready.js +2 -2
- package/dist/testing/cross_backend/revocation_drivers.d.ts +4 -3
- package/dist/testing/cross_backend/revocation_drivers.d.ts.map +1 -1
- package/dist/testing/cross_backend/revocation_drivers.js +1 -1
- package/dist/testing/cross_backend/role_grant_cross_helpers.d.ts +3 -2
- package/dist/testing/cross_backend/role_grant_cross_helpers.d.ts.map +1 -1
- package/dist/testing/cross_backend/role_grant_offer_lifecycle.d.ts +13 -0
- package/dist/testing/cross_backend/role_grant_offer_lifecycle.d.ts.map +1 -0
- package/dist/testing/cross_backend/role_grant_offer_lifecycle.js +203 -0
- package/dist/testing/cross_backend/role_grant_offer_notification_ws.d.ts +2 -5
- package/dist/testing/cross_backend/role_grant_offer_notification_ws.d.ts.map +1 -1
- package/dist/testing/cross_backend/role_grant_offer_notification_ws.js +203 -111
- package/dist/testing/cross_backend/role_grant_participation.d.ts +13 -0
- package/dist/testing/cross_backend/role_grant_participation.d.ts.map +1 -1
- package/dist/testing/cross_backend/role_grant_participation.js +32 -21
- package/dist/testing/cross_backend/role_grant_role_grammar.d.ts.map +1 -1
- package/dist/testing/cross_backend/role_grant_role_grammar.js +6 -9
- package/dist/testing/cross_backend/rpc_adversarial.d.ts +38 -0
- package/dist/testing/cross_backend/rpc_adversarial.d.ts.map +1 -0
- package/dist/testing/cross_backend/rpc_adversarial.js +292 -0
- package/dist/testing/cross_backend/rpc_success_fixtures.d.ts +24 -0
- package/dist/testing/cross_backend/rpc_success_fixtures.d.ts.map +1 -0
- package/dist/testing/cross_backend/rpc_success_fixtures.js +124 -0
- package/dist/testing/cross_backend/rust_spine_consumer_surface.d.ts +101 -0
- package/dist/testing/cross_backend/rust_spine_consumer_surface.d.ts.map +1 -0
- package/dist/testing/cross_backend/rust_spine_consumer_surface.js +113 -0
- package/dist/testing/cross_backend/rust_spine_stub_backend_config.d.ts +10 -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 +27 -18
- package/dist/testing/cross_backend/session_cap.d.ts +9 -8
- package/dist/testing/cross_backend/session_cap.d.ts.map +1 -1
- package/dist/testing/cross_backend/session_cap.js +9 -4
- package/dist/testing/cross_backend/session_cookie_codec.js +1 -1
- package/dist/testing/cross_backend/setup.d.ts +56 -54
- package/dist/testing/cross_backend/setup.d.ts.map +1 -1
- package/dist/testing/cross_backend/setup.js +29 -29
- package/dist/testing/cross_backend/simple_request.d.ts.map +1 -1
- package/dist/testing/cross_backend/simple_request.js +4 -4
- package/dist/testing/cross_backend/spawn_backend.d.ts +59 -10
- package/dist/testing/cross_backend/spawn_backend.d.ts.map +1 -1
- package/dist/testing/cross_backend/spawn_backend.js +219 -60
- package/dist/testing/cross_backend/spine_suites.d.ts +231 -0
- package/dist/testing/cross_backend/spine_suites.d.ts.map +1 -0
- package/dist/testing/cross_backend/spine_suites.js +626 -0
- package/dist/testing/cross_backend/spine_surface_constants.d.ts +29 -0
- package/dist/testing/cross_backend/spine_surface_constants.d.ts.map +1 -1
- package/dist/testing/cross_backend/spine_surface_constants.js +29 -0
- package/dist/testing/cross_backend/sse_round_trip.d.ts.map +1 -1
- package/dist/testing/cross_backend/sse_round_trip.js +3 -4
- package/dist/testing/cross_backend/standard.d.ts +18 -1
- package/dist/testing/cross_backend/standard.d.ts.map +1 -1
- package/dist/testing/cross_backend/standard.js +2 -0
- package/dist/testing/cross_backend/test_cell_gated_create_authorize.d.ts +24 -0
- package/dist/testing/cross_backend/test_cell_gated_create_authorize.d.ts.map +1 -1
- package/dist/testing/cross_backend/test_cell_gated_create_authorize.js +15 -0
- package/dist/testing/cross_backend/testing_backdoor.d.ts +2 -8
- package/dist/testing/cross_backend/testing_backdoor.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_backdoor.js +7 -10
- package/dist/testing/cross_backend/testing_reset_actions.d.ts +3 -2
- package/dist/testing/cross_backend/testing_reset_actions.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_reset_actions.js +8 -4
- package/dist/testing/cross_backend/testing_server_bun.js +1 -1
- package/dist/testing/cross_backend/token_lifetime.js +1 -1
- package/dist/testing/cross_backend/token_scope_surface.d.ts.map +1 -1
- package/dist/testing/cross_backend/token_scope_surface.js +9 -13
- package/dist/testing/cross_backend/transport_composition.d.ts +26 -2
- package/dist/testing/cross_backend/transport_composition.d.ts.map +1 -1
- package/dist/testing/cross_backend/transport_composition.js +81 -51
- package/dist/testing/cross_backend/ts_spine_backend_config.d.ts +8 -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 +17 -10
- package/dist/testing/cross_backend/ws_action_rate_limit.d.ts +2 -5
- package/dist/testing/cross_backend/ws_action_rate_limit.d.ts.map +1 -1
- package/dist/testing/cross_backend/ws_action_rate_limit.js +8 -14
- package/dist/testing/cross_backend/ws_connection_cap.d.ts +4 -9
- package/dist/testing/cross_backend/ws_connection_cap.d.ts.map +1 -1
- package/dist/testing/cross_backend/ws_connection_cap.js +11 -12
- package/dist/testing/cross_backend/ws_endpoint.d.ts +52 -0
- package/dist/testing/cross_backend/ws_endpoint.d.ts.map +1 -0
- package/dist/testing/cross_backend/ws_endpoint.js +54 -0
- package/dist/testing/cross_backend/ws_inbound_dispatch.d.ts +2 -5
- package/dist/testing/cross_backend/ws_inbound_dispatch.d.ts.map +1 -1
- package/dist/testing/cross_backend/ws_inbound_dispatch.js +9 -15
- package/dist/testing/cross_backend/ws_outbound_overflow.d.ts +2 -7
- package/dist/testing/cross_backend/ws_outbound_overflow.d.ts.map +1 -1
- package/dist/testing/cross_backend/ws_outbound_overflow.js +5 -9
- package/dist/testing/cross_backend/ws_role_gated.d.ts +4 -5
- package/dist/testing/cross_backend/ws_role_gated.d.ts.map +1 -1
- package/dist/testing/cross_backend/ws_role_gated.js +12 -21
- package/dist/testing/cross_backend/ws_round_trip.d.ts +12 -9
- package/dist/testing/cross_backend/ws_round_trip.d.ts.map +1 -1
- package/dist/testing/cross_backend/ws_round_trip.js +29 -34
- package/dist/testing/db_entities.d.ts +16 -3
- package/dist/testing/db_entities.d.ts.map +1 -1
- package/dist/testing/db_entities.js +28 -5
- package/dist/testing/integration_helpers.d.ts +61 -2
- package/dist/testing/integration_helpers.d.ts.map +1 -1
- package/dist/testing/integration_helpers.js +75 -18
- package/dist/testing/round_trip.d.ts +17 -0
- package/dist/testing/round_trip.d.ts.map +1 -1
- package/dist/testing/round_trip.js +67 -24
- package/dist/testing/rpc_attack_surface.d.ts.map +1 -1
- package/dist/testing/rpc_attack_surface.js +13 -138
- package/dist/testing/rpc_envelope_cases.d.ts +111 -0
- package/dist/testing/rpc_envelope_cases.d.ts.map +1 -0
- package/dist/testing/rpc_envelope_cases.js +240 -0
- package/dist/testing/rpc_helpers.d.ts +31 -0
- package/dist/testing/rpc_helpers.d.ts.map +1 -1
- package/dist/testing/rpc_helpers.js +35 -14
- package/dist/testing/rpc_round_trip.d.ts +62 -6
- package/dist/testing/rpc_round_trip.d.ts.map +1 -1
- package/dist/testing/rpc_round_trip.js +151 -39
- package/dist/testing/schema_generators.d.ts.map +1 -1
- package/dist/testing/schema_generators.js +22 -2
- package/dist/testing/standard.d.ts +26 -0
- package/dist/testing/standard.d.ts.map +1 -1
- package/dist/testing/standard.js +4 -1
- package/dist/testing/transports/raw_http.d.ts +21 -0
- package/dist/testing/transports/raw_http.d.ts.map +1 -1
- package/dist/testing/transports/raw_http.js +30 -0
- package/package.json +6 -4
- package/dist/testing/cross_backend/actor_search.d.ts +0 -6
- package/dist/testing/cross_backend/actor_search.d.ts.map +0 -1
- package/dist/testing/cross_backend/actor_search.js +0 -90
- package/dist/testing/cross_backend/cell_cross_helpers.d.ts.map +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import '../assert_dev_env.js';
|
|
2
2
|
import { bootstrap_backend } from './bootstrap_backend.js';
|
|
3
|
+
import { ensure_database_for_url } from './postgres_database.js';
|
|
3
4
|
import { serialize_bootstrapped_handle } from './setup.js';
|
|
4
5
|
/**
|
|
5
6
|
* Default project-name → backend-name reduction: strips the
|
|
@@ -8,19 +9,39 @@ import { serialize_bootstrapped_handle } from './setup.js';
|
|
|
8
9
|
* `cross_backend_ts_deno` → `deno` and `cross_backend_rust` → `rust`.
|
|
9
10
|
*/
|
|
10
11
|
const DEFAULT_PROJECT_NAME_PREFIX = /^cross_backend_(?:ts_)?/;
|
|
12
|
+
const default_cross_backend_global_setup_deps = {
|
|
13
|
+
ensure_database_for_url,
|
|
14
|
+
bootstrap_backend
|
|
15
|
+
};
|
|
11
16
|
/**
|
|
12
17
|
* Build a vitest `globalSetup` default export. Returns the
|
|
13
18
|
* `(project) => teardown` function vitest 4 expects.
|
|
19
|
+
*
|
|
20
|
+
* @param options - the configs, and what runs before the spawn
|
|
21
|
+
* @param deps - the database creator and the spawn, the shipped ones by default
|
|
22
|
+
* @throws Error when a `before_spawn` key names no config
|
|
14
23
|
*/
|
|
15
|
-
export const create_cross_backend_global_setup = ({ configs, derive_name = (project_name) => project_name.replace(DEFAULT_PROJECT_NAME_PREFIX, ''), provide_key = 'backend_handle' }) => {
|
|
24
|
+
export const create_cross_backend_global_setup = ({ configs, derive_name = (project_name) => project_name.replace(DEFAULT_PROJECT_NAME_PREFIX, ''), provide_key = 'backend_handle', ensure_databases = false, before_spawn = {} }, deps = default_cross_backend_global_setup_deps) => {
|
|
25
|
+
for (const name of Object.keys(before_spawn)) {
|
|
26
|
+
if (!Object.hasOwn(configs, name)) {
|
|
27
|
+
throw new Error(`create_cross_backend_global_setup: before_spawn names '${name}', which has no config — ` +
|
|
28
|
+
`expected one of: ${Object.keys(configs).join(', ')}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
16
31
|
return async (project) => {
|
|
17
32
|
const name = derive_name(project.name);
|
|
18
|
-
const factory = configs[name];
|
|
33
|
+
const factory = Object.hasOwn(configs, name) ? configs[name] : undefined;
|
|
19
34
|
if (!factory) {
|
|
20
35
|
throw new Error(`Could not derive backend config from vitest project '${project.name}' ` +
|
|
21
36
|
`(derived name '${name}') — expected one of: ${Object.keys(configs).join(', ')}`);
|
|
22
37
|
}
|
|
23
|
-
|
|
38
|
+
if (Object.hasOwn(before_spawn, name))
|
|
39
|
+
await before_spawn[name]();
|
|
40
|
+
const config = factory();
|
|
41
|
+
const database_url = config.env.DATABASE_URL;
|
|
42
|
+
if (ensure_databases && database_url !== undefined)
|
|
43
|
+
deps.ensure_database_for_url(database_url);
|
|
44
|
+
const bootstrapped = await deps.bootstrap_backend(config);
|
|
24
45
|
// vitest's `provide` is keyed on the consumer-augmented `ProvidedContext`;
|
|
25
46
|
// the generic key is a plain string, so cast past the keyof constraint.
|
|
26
47
|
project.provide(provide_key, serialize_bootstrapped_handle(bootstrapped));
|
|
@@ -19,15 +19,14 @@ import '../assert_dev_env.js';
|
|
|
19
19
|
* import {create_dual_spawn_global_setup} from
|
|
20
20
|
* '@fuzdev/fuz_app/testing/cross_backend/create_dual_spawn_global_setup.ts';
|
|
21
21
|
* import {deno_backend_config, rust_backend_config} from './my_backend_config.js';
|
|
22
|
-
* import './cross_test_types.js'; // augments the two provide keys
|
|
23
22
|
*
|
|
24
23
|
* export default create_dual_spawn_global_setup({
|
|
25
24
|
* configs: {a: deno_backend_config, b: rust_backend_config},
|
|
26
25
|
* });
|
|
27
26
|
* ```
|
|
28
27
|
*
|
|
29
|
-
* The `.cross.test.ts`
|
|
30
|
-
* `
|
|
28
|
+
* The `.cross.test.ts` reads both with `inject_parity_handles`
|
|
29
|
+
* (`provided_context.ts`, which declares the default keys) and asserts. Run this project in a
|
|
31
30
|
* later `groupOrder` than the single-backend projects (or with distinct
|
|
32
31
|
* ports) — it reuses both configs' ports, so it must not run concurrently
|
|
33
32
|
* with the per-backend projects.
|
|
@@ -49,8 +48,9 @@ export interface DualSpawnGlobalSetupOptions {
|
|
|
49
48
|
/**
|
|
50
49
|
* `project.provide` keys for the two serialized handles (read by
|
|
51
50
|
* `inject` in the test). Default `parity_handle_a` / `parity_handle_b`
|
|
52
|
-
* (the primary parity use
|
|
53
|
-
*
|
|
51
|
+
* (the primary parity use, declared on vitest's `ProvidedContext` by
|
|
52
|
+
* `provided_context.ts`); override for other dual-spawn gates, augmenting
|
|
53
|
+
* `ProvidedContext` for those keys yourself.
|
|
54
54
|
*/
|
|
55
55
|
readonly provide_keys?: {
|
|
56
56
|
readonly a: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create_dual_spawn_global_setup.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/create_dual_spawn_global_setup.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B
|
|
1
|
+
{"version":3,"file":"create_dual_spawn_global_setup.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/create_dual_spawn_global_setup.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAIzD,MAAM,WAAW,2BAA2B;IAC3C;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE;QAAE,QAAQ,CAAC,CAAC,EAAE,MAAM,aAAa,CAAC;QAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,aAAa,CAAA;KAAE,CAAC;IACvF;;;;;;OAMG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE;QAAE,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACnE;AAED;;GAEG;AACH,eAAO,MAAM,8BAA8B,GAAI,2BAG5C,2BAA2B,KAAG,CAAC,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,CAmBvF,CAAC"}
|
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
import '../assert_dev_env.js';
|
|
2
2
|
import { type BackendCapabilities } from './capabilities.js';
|
|
3
3
|
import type { SetupTest } from './setup.js';
|
|
4
|
+
import { type WsEndpointTarget } from './ws_endpoint.js';
|
|
4
5
|
/** Configuration for `describe_credential_deadline_cross_tests`. */
|
|
5
|
-
export interface CredentialDeadlineCrossTestOptions {
|
|
6
|
-
/**
|
|
6
|
+
export interface CredentialDeadlineCrossTestOptions extends WsEndpointTarget {
|
|
7
|
+
/** Fixture producer (`default_cross_process_setup(handle)`), called once for the suite. */
|
|
7
8
|
readonly setup_test: SetupTest;
|
|
8
9
|
/** Backend capability flags — the WebSocket cases gate on `ws`, the stream case on `sse`. */
|
|
9
10
|
readonly capabilities: BackendCapabilities;
|
|
10
|
-
/** Base URL the backend is reachable at. */
|
|
11
|
-
readonly base_url: string;
|
|
12
|
-
/** The WebSocket endpoint path (e.g. `/api/ws`). */
|
|
13
|
-
readonly ws_path: string;
|
|
14
11
|
/** The audit-log stream path. Default `/api/admin/audit/stream`. */
|
|
15
12
|
readonly sse_path?: string;
|
|
16
13
|
/** JSON-RPC endpoint path. Default `SPINE_RPC_PATH`. */
|
|
17
14
|
readonly rpc_path?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Roles each account this suite opens a socket for is created with, for a
|
|
17
|
+
* backend whose WS upgrade requires a role (an admin-gated `/api/ws`
|
|
18
|
+
* refuses a roleless account's upgrade). Each must be admin-grantable — the
|
|
19
|
+
* fixture offers it. Default none.
|
|
20
|
+
*/
|
|
21
|
+
readonly ws_account_roles?: ReadonlyArray<string>;
|
|
18
22
|
}
|
|
19
23
|
/**
|
|
20
24
|
* Register the credential-deadline suite: a WebSocket on a session or an API
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credential_deadline.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/credential_deadline.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"credential_deadline.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/credential_deadline.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAwD9B,OAAO,EAAE,KAAK,mBAAmB,EAAW,MAAM,mBAAmB,CAAC;AAEtE,OAAO,KAAK,EAAE,SAAS,EAAe,MAAM,YAAY,CAAC;AAEzD,OAAO,EAAsC,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAkB7F,oEAAoE;AACpE,MAAM,WAAW,kCAAmC,SAAQ,gBAAgB;IAC3E,2FAA2F;IAC3F,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC;IAC/B,6FAA6F;IAC7F,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;IAC3C,oEAAoE;IACpE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,wDAAwD;IACxD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;OAKG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CAClD;AAED;;;;GAIG;AACH,eAAO,MAAM,wCAAwC,GACpD,SAAS,kCAAkC,KACzC,IAiKF,CAAC"}
|
|
@@ -29,12 +29,17 @@ import '../assert_dev_env.js';
|
|
|
29
29
|
* covers it below the wire — the Rust stream route on a widened credential
|
|
30
30
|
* gate, the TS deadline wait shared by both transports.
|
|
31
31
|
*
|
|
32
|
+
* The cases run concurrently, each on its own account under one reset for the
|
|
33
|
+
* suite: the seam shortens only the account it names, so each case waits out
|
|
34
|
+
* its own deadline and the suite takes about one. Every case keeps the full
|
|
35
|
+
* `expiry_seconds` margin — the "open short of the deadline" check needs it.
|
|
36
|
+
*
|
|
32
37
|
* Gated on `capabilities.ws` (cases 1, 2, 4) and `capabilities.sse` (case 3);
|
|
33
38
|
* cross-process only — the seam is mounted on the spine test binaries.
|
|
34
39
|
*
|
|
35
40
|
* @module
|
|
36
41
|
*/
|
|
37
|
-
import { assert, describe } from 'vitest';
|
|
42
|
+
import { assert, beforeAll, describe } from 'vitest';
|
|
38
43
|
import { heartbeat_action_spec } from '../../actions/heartbeat.js';
|
|
39
44
|
import { WS_CLOSE_CREDENTIAL_EXPIRED_REASON, WS_CLOSE_SESSION_REVOKED } from '../../actions/transports.js';
|
|
40
45
|
import { ROLE_ADMIN } from '../../auth/role_schema.js';
|
|
@@ -43,9 +48,8 @@ import { rpc_call_non_browser } from '../rpc_helpers.js';
|
|
|
43
48
|
import { create_sse_transport } from '../transports/sse_transport.js';
|
|
44
49
|
import { create_admitted_ws_transport } from '../transports/ws_transport.js';
|
|
45
50
|
import { test_if } from './capabilities.js';
|
|
46
|
-
import { SPINE_RPC_PATH } from './spine_surface_constants.js';
|
|
47
|
-
|
|
48
|
-
const DEFAULT_SSE_PATH = '/api/admin/audit/stream';
|
|
51
|
+
import { SPINE_RPC_PATH, SPINE_SSE_PATH } from './spine_surface_constants.js';
|
|
52
|
+
import { open_session_ws, to_session_cookie } from './ws_endpoint.js';
|
|
49
53
|
/** The shortened lifetime each case gives its credentials, in seconds. */
|
|
50
54
|
const EXPIRY_SECONDS = 2;
|
|
51
55
|
/**
|
|
@@ -65,7 +69,8 @@ const EARLIEST_CLOSE_MS = EXPIRY_SECONDS * 1000 - 300;
|
|
|
65
69
|
* audit stream on a session ends there, and the expiry seam never extends.
|
|
66
70
|
*/
|
|
67
71
|
export const describe_credential_deadline_cross_tests = (options) => {
|
|
68
|
-
const { setup_test, capabilities, base_url, ws_path, sse_path =
|
|
72
|
+
const { setup_test, capabilities, base_url, ws_path, sse_path = SPINE_SSE_PATH, rpc_path = SPINE_RPC_PATH, ws_account_roles = [] } = options;
|
|
73
|
+
const ws_account = { roles: [...ws_account_roles] };
|
|
69
74
|
/**
|
|
70
75
|
* Pull `account`'s credential expiries in to `seconds` from now through the
|
|
71
76
|
* daemon-token seam, returning when it was called.
|
|
@@ -85,11 +90,6 @@ export const describe_credential_deadline_cross_tests = (options) => {
|
|
|
85
90
|
const counts = result.result;
|
|
86
91
|
return { called_at, ...counts };
|
|
87
92
|
};
|
|
88
|
-
const cookie_of = (account) => {
|
|
89
|
-
const { cookie } = account.create_session_headers();
|
|
90
|
-
assert.ok(cookie, 'expected a session cookie');
|
|
91
|
-
return cookie;
|
|
92
|
-
};
|
|
93
93
|
/**
|
|
94
94
|
* Assert `client` is open short of the deadline, then closes with 4001
|
|
95
95
|
* "Credential expired" at it.
|
|
@@ -103,18 +103,24 @@ export const describe_credential_deadline_cross_tests = (options) => {
|
|
|
103
103
|
assert.strictEqual(client.close_code, WS_CLOSE_SESSION_REVOKED);
|
|
104
104
|
assert.strictEqual(client.close_reason, WS_CLOSE_CREDENTIAL_EXPIRED_REASON);
|
|
105
105
|
};
|
|
106
|
-
describe('credential deadline (cross-process)', () => {
|
|
106
|
+
describe.concurrent('credential deadline (cross-process)', () => {
|
|
107
|
+
// One reset for the suite: the cases share no state past it, since each
|
|
108
|
+
// mints its own account and the seam touches only that account.
|
|
109
|
+
let suite_fixture = null;
|
|
110
|
+
beforeAll(async () => {
|
|
111
|
+
if (capabilities.ws || capabilities.sse)
|
|
112
|
+
suite_fixture = await setup_test();
|
|
113
|
+
});
|
|
114
|
+
const get_fixture = () => {
|
|
115
|
+
assert.ok(suite_fixture, 'the suite fixture was not set up');
|
|
116
|
+
return suite_fixture;
|
|
117
|
+
};
|
|
107
118
|
test_if(capabilities.ws, 'a session socket closes with 4001 "Credential expired" at the deadline', async () => {
|
|
108
|
-
const fixture =
|
|
109
|
-
const account = await fixture.create_account();
|
|
119
|
+
const fixture = get_fixture();
|
|
120
|
+
const account = await fixture.create_account(ws_account);
|
|
110
121
|
const { called_at, sessions } = await shorten(fixture, account, EXPIRY_SECONDS);
|
|
111
122
|
assert.ok(sessions >= 1, 'the seam shortened the account session');
|
|
112
|
-
const client = await
|
|
113
|
-
base_url,
|
|
114
|
-
ws_path,
|
|
115
|
-
cookies: [cookie_of(account)],
|
|
116
|
-
origin: base_url
|
|
117
|
-
});
|
|
123
|
+
const client = await open_session_ws(options, account, { admitted: true });
|
|
118
124
|
try {
|
|
119
125
|
await assert_closes_at_deadline(client, called_at);
|
|
120
126
|
}
|
|
@@ -123,8 +129,8 @@ export const describe_credential_deadline_cross_tests = (options) => {
|
|
|
123
129
|
}
|
|
124
130
|
});
|
|
125
131
|
test_if(capabilities.ws, 'an API token socket closes with 4001 "Credential expired" at the deadline', async () => {
|
|
126
|
-
const fixture =
|
|
127
|
-
const account = await fixture.create_account();
|
|
132
|
+
const fixture = get_fixture();
|
|
133
|
+
const account = await fixture.create_account(ws_account);
|
|
128
134
|
const { called_at, api_tokens } = await shorten(fixture, account, EXPIRY_SECONDS);
|
|
129
135
|
assert.ok(api_tokens >= 1, 'the seam shortened the account API token');
|
|
130
136
|
// a bearer outside a browser context: no Origin, no cookie
|
|
@@ -143,13 +149,13 @@ export const describe_credential_deadline_cross_tests = (options) => {
|
|
|
143
149
|
}
|
|
144
150
|
});
|
|
145
151
|
test_if(capabilities.sse, 'a session audit stream ends at the deadline', async () => {
|
|
146
|
-
const fixture =
|
|
152
|
+
const fixture = get_fixture();
|
|
147
153
|
const account = await fixture.create_account({ roles: [ROLE_ADMIN] });
|
|
148
154
|
const { called_at } = await shorten(fixture, account, EXPIRY_SECONDS);
|
|
149
155
|
const sse = await create_sse_transport({
|
|
150
156
|
base_url,
|
|
151
157
|
sse_path,
|
|
152
|
-
cookies: [
|
|
158
|
+
cookies: [to_session_cookie(account)],
|
|
153
159
|
origin: base_url
|
|
154
160
|
});
|
|
155
161
|
try {
|
|
@@ -163,17 +169,12 @@ export const describe_credential_deadline_cross_tests = (options) => {
|
|
|
163
169
|
}
|
|
164
170
|
});
|
|
165
171
|
test_if(capabilities.ws, 'the expiry seam only shortens: a later expiry moves nothing', async () => {
|
|
166
|
-
const fixture =
|
|
167
|
-
const account = await fixture.create_account();
|
|
172
|
+
const fixture = get_fixture();
|
|
173
|
+
const account = await fixture.create_account(ws_account);
|
|
168
174
|
const { called_at } = await shorten(fixture, account, EXPIRY_SECONDS);
|
|
169
175
|
// asks for a minute; the credentials stay due at the first deadline
|
|
170
176
|
await shorten(fixture, account, 60);
|
|
171
|
-
const client = await
|
|
172
|
-
base_url,
|
|
173
|
-
ws_path,
|
|
174
|
-
cookies: [cookie_of(account)],
|
|
175
|
-
origin: base_url
|
|
176
|
-
});
|
|
177
|
+
const client = await open_session_ws(options, account, { admitted: true });
|
|
177
178
|
try {
|
|
178
179
|
await assert_closes_at_deadline(client, called_at);
|
|
179
180
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credential_header_robustness.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/credential_header_robustness.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"credential_header_robustness.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/credential_header_robustness.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AA6D9B,qGAAqG;AACrG,MAAM,WAAW,0CAA0C;IAC1D,mFAAmF;IACnF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,uDAAuD;IACvD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,6DAA6D;IAC7D,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC9B;AA6CD,eAAO,MAAM,iDAAiD,GAC7D,SAAS,0CAA0C,KACjD,IAkHF,CAAC"}
|
|
@@ -39,8 +39,8 @@ import '../assert_dev_env.js';
|
|
|
39
39
|
* Raw-socket by necessity (`fetch` can't emit duplicate or malformed headers),
|
|
40
40
|
* so — like `body_size_smuggling.ts` — this is **cross-process only** and
|
|
41
41
|
* fixture-free: it needs only the base URL, the RPC path, and a valid daemon
|
|
42
|
-
* token (`handle.daemon_token`,
|
|
43
|
-
* the `_testing_reset` channel
|
|
42
|
+
* token (`handle.daemon_token`, read once at spawn and static for the run, the
|
|
43
|
+
* same credential the `_testing_reset` channel uses). Cited property: `docs/security.md`
|
|
44
44
|
* §"Credential Type Hierarchy" (a leaked / conflicting credential header can't
|
|
45
45
|
* escalate the credential ceiling) + §"API Token Security" (bearer handling).
|
|
46
46
|
*
|
|
@@ -48,16 +48,14 @@ import '../assert_dev_env.js';
|
|
|
48
48
|
*/
|
|
49
49
|
import { describe, test, assert } from 'vitest';
|
|
50
50
|
import { DAEMON_TOKEN_HEADER } from '../../auth/daemon_token.js';
|
|
51
|
-
import { raw_http_count_responses, raw_http_exchange, raw_http_first_status } from '../transports/raw_http.js';
|
|
51
|
+
import { raw_http_count_responses, raw_http_exchange, raw_http_first_status, RAW_HTTP_READ_TIMEOUT_MS } from '../transports/raw_http.js';
|
|
52
52
|
import { SPINE_RPC_PATH } from './spine_surface_constants.js';
|
|
53
53
|
/** A well-formed UUID that never names a real row. */
|
|
54
54
|
const NIL_UUID = '00000000-0000-0000-0000-000000000000';
|
|
55
55
|
/** A value that is never a real credential — used for the conflicting / garbage copies. */
|
|
56
56
|
const GARBAGE_TOKEN = 'not-a-real-credential-value';
|
|
57
|
-
/** How long each raw exchange waits for the server to finish answering. */
|
|
58
|
-
const RAW_READ_TIMEOUT_MS = 2000;
|
|
59
57
|
/** Write `request_bytes` to a fresh raw socket and read until the server closes. */
|
|
60
|
-
const send_raw = async (base_url, request_bytes) => (await raw_http_exchange(base_url, request_bytes, { read_timeout_ms:
|
|
58
|
+
const send_raw = async (base_url, request_bytes) => (await raw_http_exchange(base_url, request_bytes, { read_timeout_ms: RAW_HTTP_READ_TIMEOUT_MS }))
|
|
61
59
|
.received;
|
|
62
60
|
const is_success_status = (status) => status >= 200 && status < 300;
|
|
63
61
|
/**
|
|
@@ -15,7 +15,17 @@ export interface RpcResult {
|
|
|
15
15
|
* POST a JSON-RPC call over a cross-process `FetchTransport` with the given
|
|
16
16
|
* auth headers. Distinct from `testing/rpc_helpers.ts`'s `app`-based `rpc_call`: this
|
|
17
17
|
* variant drives the cookie-jar `FetchTransport` the cross-backend harness
|
|
18
|
-
* spawns against, and returns the slim `RpcResult` the
|
|
18
|
+
* spawns against, and returns the slim `RpcResult` the suites read.
|
|
19
|
+
*
|
|
20
|
+
* @param transport - the transport to send on
|
|
21
|
+
* @param path - the RPC endpoint path
|
|
22
|
+
* @param method - the JSON-RPC method
|
|
23
|
+
* @param params - the request params
|
|
24
|
+
* @param headers - auth and other headers, merged over the JSON defaults
|
|
25
|
+
* @returns the response's `ok`, `result` and `error`
|
|
26
|
+
* @throws Error when the reply is not a JSON object — naming the method, the
|
|
27
|
+
* HTTP status and the head of the body, so a proxy page or a crash reads
|
|
28
|
+
* as what it is
|
|
19
29
|
*/
|
|
20
30
|
export declare const cross_rpc_call: (transport: FetchTransport, path: string, method: string, params: unknown, headers: Record<string, string>) => Promise<RpcResult>;
|
|
21
31
|
/** Pull `error.data.reason` off an RPC error envelope (undefined if absent). */
|
|
@@ -25,4 +35,4 @@ export declare const error_reason: (r: RpcResult) => unknown;
|
|
|
25
35
|
* output schema — the wire-shape parity gate. Returns the parsed output.
|
|
26
36
|
*/
|
|
27
37
|
export declare const expect_output: <T>(r: RpcResult, schema: z.ZodType<T>) => T;
|
|
28
|
-
//# sourceMappingURL=
|
|
38
|
+
//# sourceMappingURL=cross_rpc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cross_rpc.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/cross_rpc.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAgB9B,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAG7B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAEvE,qEAAqE;AACrE,MAAM,WAAW,SAAS;IACzB,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAC9F;AAKD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,cAAc,GAC1B,WAAW,cAAc,EACzB,MAAM,MAAM,EACZ,QAAQ,MAAM,EACd,QAAQ,OAAO,EACf,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAC7B,OAAO,CAAC,SAAS,CAmBnB,CAAC;AAEF,gFAAgF;AAChF,eAAO,MAAM,YAAY,GAAI,GAAG,SAAS,KAAG,OAG/B,CAAC;AAEd;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAI,CAAC,EAAE,GAAG,SAAS,EAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAG,CAUrE,CAAC"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import '../assert_dev_env.js';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
* (`testing/cross_backend/cell_crud.ts` + `testing/cross_backend/cell_relations.ts`).
|
|
3
|
+
* JSON-RPC call-site primitives for the cross-backend suites.
|
|
5
4
|
*
|
|
6
|
-
* The
|
|
7
|
-
*
|
|
5
|
+
* The stateful suites (the cell verbs, account lifecycle, role grants, tokens,
|
|
6
|
+
* facts, audit reads) POST raw JSON-RPC envelopes over a cross-process
|
|
7
|
+
* `FetchTransport`, threading ids and auth headers across calls, and parse
|
|
8
8
|
* every success `result` against the verb's declared Zod **output** schema —
|
|
9
9
|
* the wire-shape parity gate. A TS↔Rust envelope drift, not just a payload
|
|
10
10
|
* field drift, fails the assertion.
|
|
@@ -13,18 +13,42 @@ import '../assert_dev_env.js';
|
|
|
13
13
|
*/
|
|
14
14
|
import { assert } from 'vitest';
|
|
15
15
|
import { create_rpc_post_init } from '../rpc_helpers.js';
|
|
16
|
+
/** How much of a non-envelope reply body `cross_rpc_call`'s error quotes. */
|
|
17
|
+
const BODY_HEAD_LENGTH = 200;
|
|
16
18
|
/**
|
|
17
19
|
* POST a JSON-RPC call over a cross-process `FetchTransport` with the given
|
|
18
20
|
* auth headers. Distinct from `testing/rpc_helpers.ts`'s `app`-based `rpc_call`: this
|
|
19
21
|
* variant drives the cookie-jar `FetchTransport` the cross-backend harness
|
|
20
|
-
* spawns against, and returns the slim `RpcResult` the
|
|
22
|
+
* spawns against, and returns the slim `RpcResult` the suites read.
|
|
23
|
+
*
|
|
24
|
+
* @param transport - the transport to send on
|
|
25
|
+
* @param path - the RPC endpoint path
|
|
26
|
+
* @param method - the JSON-RPC method
|
|
27
|
+
* @param params - the request params
|
|
28
|
+
* @param headers - auth and other headers, merged over the JSON defaults
|
|
29
|
+
* @returns the response's `ok`, `result` and `error`
|
|
30
|
+
* @throws Error when the reply is not a JSON object — naming the method, the
|
|
31
|
+
* HTTP status and the head of the body, so a proxy page or a crash reads
|
|
32
|
+
* as what it is
|
|
21
33
|
*/
|
|
22
34
|
export const cross_rpc_call = async (transport, path, method, params, headers) => {
|
|
23
35
|
const init = create_rpc_post_init(method, params);
|
|
24
36
|
Object.assign(init.headers, headers);
|
|
25
37
|
const res = await transport(path, init);
|
|
26
|
-
const
|
|
27
|
-
|
|
38
|
+
const text = await res.text();
|
|
39
|
+
let body;
|
|
40
|
+
try {
|
|
41
|
+
body = JSON.parse(text);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
body = undefined;
|
|
45
|
+
}
|
|
46
|
+
if (body === null || typeof body !== 'object') {
|
|
47
|
+
throw new Error(`${method}: expected a JSON-RPC envelope, got status ${res.status} with body: ` +
|
|
48
|
+
JSON.stringify(text.slice(0, BODY_HEAD_LENGTH)));
|
|
49
|
+
}
|
|
50
|
+
const envelope = body;
|
|
51
|
+
return { ok: res.ok, result: envelope.result, error: envelope.error };
|
|
28
52
|
};
|
|
29
53
|
/** Pull `error.data.reason` off an RPC error envelope (undefined if absent). */
|
|
30
54
|
export const error_reason = (r) => r.error && typeof r.error.data === 'object' && r.error.data !== null
|
|
@@ -1,40 +1,24 @@
|
|
|
1
1
|
import '../assert_dev_env.js';
|
|
2
|
+
import type { BackendBootstrapConfig, BackendConfig } from './backend_config.js';
|
|
3
|
+
import type { BackendCapabilities, FamilyDefaultCapabilities } from './capabilities.js';
|
|
4
|
+
import { type TestBackendPaths } from './build_test_backend_paths.js';
|
|
2
5
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* Defaults baked in by family:
|
|
13
|
-
*
|
|
14
|
-
* - **TS** — `'memory://'` (in-memory pglet), 30s startup window. Its shape notes
|
|
15
|
-
* (`ts_default_shape_notes`) record `trusted_proxy: false` /
|
|
16
|
-
* `login_rate_limit: false` — the TS canonical path leaves those limiters
|
|
17
|
-
* null in test mode.
|
|
18
|
-
* - **Rust** — caller-supplied real Postgres URL (an in-process WASM database isn't reachable
|
|
19
|
-
* from `tokio-postgres`), 120s startup window (cargo first-build cost), the
|
|
20
|
-
* `FUZ_TESTING_RESET_DB_ON_STARTUP=true` self-wipe gate, and shape notes
|
|
21
|
-
* (`rust_default_shape_notes`) recording `trusted_proxy: true` +
|
|
22
|
-
* `login_rate_limit: true`.
|
|
23
|
-
*
|
|
24
|
-
* Both builders default `port_env_var` to `'PORT'`. Consumers whose
|
|
25
|
-
* binary reads a different name (e.g. zzz's `ZZZ_PORT`) override.
|
|
26
|
-
*
|
|
27
|
-
* Common across both families: `/api/rpc`, `/api/ws`, `/health`,
|
|
28
|
-
* `/api/account/bootstrap`, `cookie_name: 'fuz_session'`, the standard
|
|
29
|
-
* bootstrap block keyed off `default_test_*` constants. Builders call
|
|
30
|
-
* `build_test_backend_paths(name)` internally when the optional `paths`
|
|
31
|
-
* is omitted.
|
|
6
|
+
* The `HOST` both builders bind a backend to — loopback IPv4, since
|
|
7
|
+
* `localhost` can resolve to `::1` and a backend bound there misses a client
|
|
8
|
+
* that connects to `127.0.0.1` (the raw-socket suites, a git hook calling
|
|
9
|
+
* back). `base_url` stays `http://localhost:<port>`, which reaches it.
|
|
10
|
+
*/
|
|
11
|
+
export declare const DEFAULT_TEST_BACKEND_HOST = "127.0.0.1";
|
|
12
|
+
/**
|
|
13
|
+
* The directory a binary writing its daemon token to `{dir}/run/daemon_token`
|
|
14
|
+
* is given, so the token lands at `daemon_token_path`.
|
|
32
15
|
*
|
|
33
|
-
* @
|
|
16
|
+
* @param daemon_token_path - where the harness reads the token
|
|
17
|
+
* @returns the `{dir}` of that layout
|
|
18
|
+
* @throws Error when the path is not `.../run/daemon_token`, which no such
|
|
19
|
+
* directory can produce
|
|
34
20
|
*/
|
|
35
|
-
|
|
36
|
-
import type { BackendCapabilities, BackendShapeNotes } from './capabilities.js';
|
|
37
|
-
import { type TestBackendPaths } from './build_test_backend_paths.js';
|
|
21
|
+
export declare const to_daemon_token_dir: (daemon_token_path: string) => string;
|
|
38
22
|
/** Options for `action_rate_limit_env`. */
|
|
39
23
|
export interface ActionRateLimitEnvOptions {
|
|
40
24
|
readonly enable_action_rate_limit?: boolean;
|
|
@@ -48,33 +32,18 @@ export interface ActionRateLimitEnvOptions {
|
|
|
48
32
|
*/
|
|
49
33
|
export declare const action_rate_limit_env: (options: ActionRateLimitEnvOptions) => Record<string, string>;
|
|
50
34
|
/**
|
|
51
|
-
* Capabilities shared by TS-family backends —
|
|
52
|
-
*
|
|
53
|
-
*
|
|
35
|
+
* Capabilities shared by TS-family backends — only what the family
|
|
36
|
+
* guarantees: the declared spine surface's mounts and the behavior of its
|
|
37
|
+
* reference runtime, Node. Carries no `MountFlag`; each backend config states
|
|
38
|
+
* those itself (`FamilyDefaultCapabilities`).
|
|
54
39
|
*/
|
|
55
|
-
export declare const ts_default_capabilities:
|
|
40
|
+
export declare const ts_default_capabilities: FamilyDefaultCapabilities;
|
|
56
41
|
/**
|
|
57
|
-
* Capabilities for the Rust family
|
|
58
|
-
* `
|
|
59
|
-
*
|
|
42
|
+
* Capabilities for the Rust family — only what the family guarantees, as with
|
|
43
|
+
* `ts_default_capabilities`: the declared spine surface's mounts and the
|
|
44
|
+
* behavior of hyper. Carries no `MountFlag`.
|
|
60
45
|
*/
|
|
61
|
-
export declare const rust_default_capabilities:
|
|
62
|
-
/**
|
|
63
|
-
* Shape notes for TS-family backends — wiring facts, not gating flags.
|
|
64
|
-
* `trusted_proxy: false` (the test binary doesn't enable proxy parsing) and
|
|
65
|
-
* `login_rate_limit: false` (the TS canonical path leaves the limiter null in
|
|
66
|
-
* test mode); bearer auth is always wired. Documentation only — see
|
|
67
|
-
* `BackendShapeNotes`.
|
|
68
|
-
*/
|
|
69
|
-
export declare const ts_default_shape_notes: BackendShapeNotes;
|
|
70
|
-
/**
|
|
71
|
-
* Shape notes for Rust-family backends — wiring facts, not gating flags. Adds
|
|
72
|
-
* `trusted_proxy: true` (the Rust spine's client-IP middleware is always wired;
|
|
73
|
-
* the env-gate only chooses XFF vs the TCP peer IP) and `login_rate_limit: true`
|
|
74
|
-
* (env-gated bucket on `/login` + `/password`). Documentation only — see
|
|
75
|
-
* `BackendShapeNotes`.
|
|
76
|
-
*/
|
|
77
|
-
export declare const rust_default_shape_notes: BackendShapeNotes;
|
|
46
|
+
export declare const rust_default_capabilities: FamilyDefaultCapabilities;
|
|
78
47
|
export interface MakeDefaultTsBackendConfigOptions {
|
|
79
48
|
/** Diagnostic label; also used as the tmpdir prefix when `paths` is omitted. */
|
|
80
49
|
readonly name: string;
|
|
@@ -86,8 +55,12 @@ export interface MakeDefaultTsBackendConfigOptions {
|
|
|
86
55
|
readonly database_url?: string;
|
|
87
56
|
/** Merged on top of the generic env baseline; later keys win. */
|
|
88
57
|
readonly extra_env?: Readonly<Record<string, string>>;
|
|
89
|
-
/**
|
|
90
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Every capability, stated: spread `ts_default_capabilities` and add each
|
|
60
|
+
* `MountFlag`. Required, so a mount flag left out is a type error rather
|
|
61
|
+
* than a suite that silently skips.
|
|
62
|
+
*/
|
|
63
|
+
readonly capabilities: BackendCapabilities;
|
|
91
64
|
/** Pre-computed paths; defaults to `build_test_backend_paths(name)`. */
|
|
92
65
|
readonly paths?: TestBackendPaths;
|
|
93
66
|
/** Override individual bootstrap fields (username/password/token). */
|
|
@@ -106,6 +79,15 @@ export interface MakeDefaultTsBackendConfigOptions {
|
|
|
106
79
|
* `create_account` path (e.g. fuz_forge uses `'fuz_forge_session'`).
|
|
107
80
|
*/
|
|
108
81
|
readonly cookie_name?: string;
|
|
82
|
+
/**
|
|
83
|
+
* Env var naming the directory the binary writes its daemon token under
|
|
84
|
+
* (`{dir}/run/daemon_token`), e.g. `'MY_APP_DAEMON_TOKEN_DIR'`. Given, it
|
|
85
|
+
* is set to the directory that layout puts the token at the bootstrap's
|
|
86
|
+
* `daemon_token_path` (`to_daemon_token_dir`) — the file `spawn_backend`
|
|
87
|
+
* reads — and a path in another layout throws. Omit it for a binary that
|
|
88
|
+
* derives the path otherwise.
|
|
89
|
+
*/
|
|
90
|
+
readonly daemon_token_dir_env?: string;
|
|
109
91
|
}
|
|
110
92
|
/**
|
|
111
93
|
* Shared builder for TS-family backends (Deno + Node). Owns the common
|
|
@@ -129,8 +111,12 @@ export interface MakeDefaultRustBackendConfigOptions {
|
|
|
129
111
|
readonly database_url: string;
|
|
130
112
|
/** Merged on top of the generic env baseline; later keys win. */
|
|
131
113
|
readonly extra_env?: Readonly<Record<string, string>>;
|
|
132
|
-
/**
|
|
133
|
-
|
|
114
|
+
/**
|
|
115
|
+
* Every capability, stated: spread `rust_default_capabilities` and add each
|
|
116
|
+
* `MountFlag`. Required, so a mount flag left out is a type error rather
|
|
117
|
+
* than a suite that silently skips.
|
|
118
|
+
*/
|
|
119
|
+
readonly capabilities: BackendCapabilities;
|
|
134
120
|
/** Pre-computed paths; defaults to `build_test_backend_paths(name)`. */
|
|
135
121
|
readonly paths?: TestBackendPaths;
|
|
136
122
|
/** Override individual bootstrap fields (username/password/token). */
|
|
@@ -152,6 +138,15 @@ export interface MakeDefaultRustBackendConfigOptions {
|
|
|
152
138
|
* Must match the consumer's session config (see the TS builder's note).
|
|
153
139
|
*/
|
|
154
140
|
readonly cookie_name?: string;
|
|
141
|
+
/**
|
|
142
|
+
* Env var naming the directory the binary writes its daemon token under
|
|
143
|
+
* (`{dir}/run/daemon_token`), e.g. `'MY_APP_DAEMON_TOKEN_DIR'`. Given, it
|
|
144
|
+
* is set to the directory that layout puts the token at the bootstrap's
|
|
145
|
+
* `daemon_token_path` (`to_daemon_token_dir`) — the file `spawn_backend`
|
|
146
|
+
* reads — and a path in another layout throws. Omit it for a binary that
|
|
147
|
+
* derives the path otherwise.
|
|
148
|
+
*/
|
|
149
|
+
readonly daemon_token_dir_env?: string;
|
|
155
150
|
}
|
|
156
151
|
/**
|
|
157
152
|
* Shared builder for Rust-family backends. Owns the common env baseline
|
|
@@ -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;
|
|
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;AAqC9B,OAAO,KAAK,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACjF,OAAO,KAAK,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AACxF,OAAO,EAA4B,KAAK,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAehG;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,cAAc,CAAC;AAErD;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,GAAI,mBAAmB,MAAM,KAAG,MAS/D,CAAC;AAcF,2CAA2C;AAC3C,MAAM,WAAW,yBAAyB;IACzC,QAAQ,CAAC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IAC5C,QAAQ,CAAC,8BAA8B,CAAC,EAAE,MAAM,CAAC;CACjD;AAED;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,GACjC,SAAS,yBAAyB,KAChC,MAAM,CAAC,MAAM,EAAE,MAAM,CAKtB,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,EAAE,yBAgBpC,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,EAAE,yBAatC,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,mDAAmD;IACnD,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;;;;OAIG;IACH,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;IAC3C,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;IAC9B;;;;;;;OAOG;IACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;CACvC;AAED;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,GAC1C,MAAM,iCAAiC,KACrC,aAuCF,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;;;;OAIG;IACH,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;IAC3C,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;IAC9B;;;;;;;OAOG;IACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;CACvC;AAED;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,GAC5C,MAAM,mCAAmC,KACvC,aA+CF,CAAC"}
|