@fuzdev/fuz_app 0.140.0 → 0.142.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 +72 -22
- package/dist/actions/action_rpc.d.ts +5 -1
- package/dist/actions/action_rpc.d.ts.map +1 -1
- package/dist/actions/action_rpc.js +9 -1
- package/dist/actions/connection_closer.d.ts +44 -4
- package/dist/actions/connection_closer.d.ts.map +1 -1
- package/dist/actions/connection_closer.js +33 -3
- package/dist/actions/perform_action.d.ts +10 -0
- package/dist/actions/perform_action.d.ts.map +1 -1
- package/dist/actions/perform_action.js +23 -9
- package/dist/actions/register_action_ws.d.ts +42 -6
- package/dist/actions/register_action_ws.d.ts.map +1 -1
- package/dist/actions/register_action_ws.js +87 -19
- package/dist/actions/register_ws_endpoint.d.ts +15 -6
- package/dist/actions/register_ws_endpoint.d.ts.map +1 -1
- package/dist/actions/register_ws_endpoint.js +10 -4
- package/dist/actions/socket.svelte.d.ts +19 -4
- package/dist/actions/socket.svelte.d.ts.map +1 -1
- package/dist/actions/socket.svelte.js +31 -4
- package/dist/actions/transports.d.ts +30 -1
- package/dist/actions/transports.d.ts.map +1 -1
- package/dist/actions/transports.js +30 -1
- package/dist/actions/transports_ws_auth_guard.d.ts +13 -6
- package/dist/actions/transports_ws_auth_guard.d.ts.map +1 -1
- package/dist/actions/transports_ws_auth_guard.js +24 -10
- package/dist/actions/transports_ws_backend.d.ts +51 -5
- package/dist/actions/transports_ws_backend.d.ts.map +1 -1
- package/dist/actions/transports_ws_backend.js +62 -9
- package/dist/actions/ws_endpoint_spec.d.ts +11 -10
- package/dist/actions/ws_endpoint_spec.d.ts.map +1 -1
- package/dist/auth/CLAUDE.md +44 -22
- package/dist/auth/account_actions.d.ts.map +1 -1
- package/dist/auth/account_actions.js +12 -1
- package/dist/auth/account_route_schema.d.ts +1 -0
- package/dist/auth/account_route_schema.d.ts.map +1 -1
- package/dist/auth/account_route_schema.js +12 -0
- package/dist/auth/account_routes.d.ts +7 -2
- package/dist/auth/account_routes.d.ts.map +1 -1
- package/dist/auth/account_routes.js +240 -187
- package/dist/auth/admin_action_specs.d.ts +6 -1
- package/dist/auth/admin_action_specs.d.ts.map +1 -1
- package/dist/auth/admin_action_specs.js +6 -1
- package/dist/auth/admin_actions.d.ts.map +1 -1
- package/dist/auth/admin_actions.js +14 -2
- package/dist/auth/api_token.d.ts +20 -0
- package/dist/auth/api_token.d.ts.map +1 -1
- package/dist/auth/api_token.js +21 -1
- package/dist/auth/api_token_queries.d.ts +22 -4
- package/dist/auth/api_token_queries.d.ts.map +1 -1
- package/dist/auth/api_token_queries.js +11 -6
- package/dist/auth/audit_log_routes.d.ts +10 -0
- package/dist/auth/audit_log_routes.d.ts.map +1 -1
- package/dist/auth/audit_log_routes.js +20 -0
- package/dist/auth/audit_log_schema.d.ts +30 -5
- package/dist/auth/audit_log_schema.d.ts.map +1 -1
- package/dist/auth/audit_log_schema.js +30 -0
- package/dist/auth/bearer_auth.d.ts +4 -2
- package/dist/auth/bearer_auth.d.ts.map +1 -1
- package/dist/auth/bearer_auth.js +19 -8
- package/dist/auth/bootstrap_route_schema.d.ts +1 -0
- package/dist/auth/bootstrap_route_schema.d.ts.map +1 -1
- package/dist/auth/bootstrap_route_schema.js +1 -0
- package/dist/auth/bootstrap_routes.d.ts.map +1 -1
- package/dist/auth/bootstrap_routes.js +85 -76
- package/dist/auth/cell_action_specs.d.ts +7 -3
- package/dist/auth/cell_action_specs.d.ts.map +1 -1
- package/dist/auth/cell_action_specs.js +9 -5
- package/dist/auth/cell_actions.d.ts +3 -3
- package/dist/auth/cell_actions.d.ts.map +1 -1
- package/dist/auth/cell_actions.js +67 -38
- package/dist/auth/cell_authorize.d.ts +69 -8
- package/dist/auth/cell_authorize.d.ts.map +1 -1
- package/dist/auth/cell_authorize.js +89 -9
- package/dist/auth/cell_field_action_specs.d.ts +5 -4
- package/dist/auth/cell_field_action_specs.d.ts.map +1 -1
- package/dist/auth/cell_field_action_specs.js +7 -7
- package/dist/auth/cell_field_actions.d.ts +7 -5
- package/dist/auth/cell_field_actions.d.ts.map +1 -1
- package/dist/auth/cell_field_actions.js +24 -22
- package/dist/auth/cell_grant_action_specs.d.ts +6 -0
- package/dist/auth/cell_grant_action_specs.d.ts.map +1 -1
- package/dist/auth/cell_grant_action_specs.js +6 -0
- package/dist/auth/cell_grant_actions.d.ts +3 -1
- package/dist/auth/cell_grant_actions.d.ts.map +1 -1
- package/dist/auth/cell_grant_actions.js +16 -2
- package/dist/auth/cell_item_action_specs.d.ts +5 -4
- package/dist/auth/cell_item_action_specs.d.ts.map +1 -1
- package/dist/auth/cell_item_action_specs.js +7 -7
- package/dist/auth/cell_item_actions.d.ts +6 -5
- package/dist/auth/cell_item_actions.d.ts.map +1 -1
- package/dist/auth/cell_item_actions.js +23 -22
- package/dist/auth/cell_relation_list_limit.d.ts +20 -0
- package/dist/auth/cell_relation_list_limit.d.ts.map +1 -0
- package/dist/auth/cell_relation_list_limit.js +27 -0
- package/dist/auth/cell_relation_visibility.d.ts +4 -3
- package/dist/auth/cell_relation_visibility.d.ts.map +1 -1
- package/dist/auth/cell_relation_visibility.js +6 -5
- package/dist/auth/cell_steward.d.ts +45 -0
- package/dist/auth/cell_steward.d.ts.map +1 -0
- package/dist/auth/cell_steward.js +53 -0
- package/dist/auth/cleanup.d.ts +9 -9
- package/dist/auth/cleanup.js +9 -9
- package/dist/auth/credential_deadline.d.ts +95 -0
- package/dist/auth/credential_deadline.d.ts.map +1 -0
- package/dist/auth/credential_deadline.js +139 -0
- package/dist/auth/daemon_token_middleware.d.ts.map +1 -1
- package/dist/auth/daemon_token_middleware.js +4 -1
- package/dist/auth/middleware.d.ts +90 -12
- package/dist/auth/middleware.d.ts.map +1 -1
- package/dist/auth/middleware.js +115 -16
- package/dist/auth/request_context.d.ts +8 -2
- package/dist/auth/request_context.d.ts.map +1 -1
- package/dist/auth/request_context.js +20 -4
- package/dist/auth/resolved_auth.d.ts +13 -2
- package/dist/auth/resolved_auth.d.ts.map +1 -1
- package/dist/auth/resolved_auth.js +5 -4
- package/dist/auth/role_grant_offer_action_specs.d.ts +5 -0
- package/dist/auth/role_grant_offer_action_specs.d.ts.map +1 -1
- package/dist/auth/role_grant_offer_action_specs.js +6 -1
- package/dist/auth/role_grant_offer_actions.d.ts.map +1 -1
- package/dist/auth/role_grant_offer_actions.js +23 -16
- package/dist/auth/role_grant_offer_queries.d.ts +8 -6
- package/dist/auth/role_grant_offer_queries.d.ts.map +1 -1
- package/dist/auth/role_grant_offer_queries.js +16 -8
- package/dist/auth/session_cookie.d.ts +4 -0
- package/dist/auth/session_cookie.d.ts.map +1 -1
- package/dist/auth/session_cookie.js +3 -2
- package/dist/auth/session_middleware.d.ts +1 -1
- package/dist/auth/session_middleware.d.ts.map +1 -1
- package/dist/auth/session_middleware.js +4 -1
- package/dist/auth/session_queries.d.ts +19 -2
- package/dist/auth/session_queries.d.ts.map +1 -1
- package/dist/auth/session_queries.js +8 -2
- package/dist/auth/signup_route_schema.d.ts.map +1 -1
- package/dist/auth/signup_route_schema.js +1 -0
- package/dist/auth/signup_routes.d.ts +4 -3
- package/dist/auth/signup_routes.d.ts.map +1 -1
- package/dist/auth/signup_routes.js +157 -134
- package/dist/auth/token_scope.d.ts +7 -1
- package/dist/auth/token_scope.d.ts.map +1 -1
- package/dist/auth/token_scope.js +8 -2
- package/dist/db/CLAUDE.md +32 -19
- package/dist/db/cell_ddl.d.ts +1 -2
- package/dist/db/cell_ddl.d.ts.map +1 -1
- package/dist/db/cell_ddl.js +1 -2
- package/dist/db/cell_field_queries.d.ts +20 -18
- package/dist/db/cell_field_queries.d.ts.map +1 -1
- package/dist/db/cell_field_queries.js +28 -22
- package/dist/db/cell_item_queries.d.ts +20 -14
- package/dist/db/cell_item_queries.d.ts.map +1 -1
- package/dist/db/cell_item_queries.js +28 -18
- package/dist/db/cell_moderation.d.ts +67 -0
- package/dist/db/cell_moderation.d.ts.map +1 -0
- package/dist/db/cell_moderation.js +66 -0
- package/dist/db/cell_queries.d.ts +44 -14
- package/dist/db/cell_queries.d.ts.map +1 -1
- package/dist/db/cell_queries.js +68 -45
- package/dist/db/cell_view_sql.d.ts +102 -0
- package/dist/db/cell_view_sql.d.ts.map +1 -0
- package/dist/db/cell_view_sql.js +112 -0
- package/dist/db/db_pg.d.ts +1 -1
- package/dist/db/db_pg.js +1 -1
- package/dist/hono_context.d.ts +23 -0
- package/dist/hono_context.d.ts.map +1 -1
- package/dist/hono_context.js +19 -0
- package/dist/http/CLAUDE.md +41 -15
- package/dist/http/auth_shape.d.ts +5 -2
- package/dist/http/auth_shape.d.ts.map +1 -1
- package/dist/http/auth_shape.js +5 -2
- package/dist/http/ip_canonical.d.ts +30 -3
- package/dist/http/ip_canonical.d.ts.map +1 -1
- package/dist/http/ip_canonical.js +50 -3
- package/dist/http/middleware_spec.d.ts +16 -0
- package/dist/http/middleware_spec.d.ts.map +1 -1
- package/dist/http/origin.d.ts +113 -18
- package/dist/http/origin.d.ts.map +1 -1
- package/dist/http/origin.js +247 -127
- package/dist/http/route_spec.d.ts +21 -0
- package/dist/http/route_spec.d.ts.map +1 -1
- package/dist/http/schema_helpers.d.ts +22 -0
- package/dist/http/schema_helpers.d.ts.map +1 -1
- package/dist/http/schema_helpers.js +24 -0
- package/dist/http/surface.d.ts +6 -1
- package/dist/http/surface.d.ts.map +1 -1
- package/dist/http/surface.js +12 -5
- package/dist/primitive_schemas.d.ts +10 -1
- package/dist/primitive_schemas.d.ts.map +1 -1
- package/dist/primitive_schemas.js +11 -2
- package/dist/rate_limiter.d.ts +179 -12
- package/dist/rate_limiter.d.ts.map +1 -1
- package/dist/rate_limiter.js +352 -42
- package/dist/realtime/sse_auth_guard.d.ts +22 -6
- package/dist/realtime/sse_auth_guard.d.ts.map +1 -1
- package/dist/realtime/sse_auth_guard.js +31 -12
- package/dist/realtime/subscriber_registry.d.ts +10 -1
- package/dist/realtime/subscriber_registry.d.ts.map +1 -1
- package/dist/realtime/subscriber_registry.js +10 -1
- package/dist/server/app_server.d.ts +20 -7
- package/dist/server/app_server.d.ts.map +1 -1
- package/dist/server/app_server.js +8 -3
- package/dist/server/env.d.ts +2 -1
- package/dist/server/env.d.ts.map +1 -1
- package/dist/server/env.js +7 -17
- package/dist/server/serve_fact_route.d.ts +8 -4
- package/dist/server/serve_fact_route.d.ts.map +1 -1
- package/dist/server/serve_fact_route.js +16 -6
- package/dist/testing/CLAUDE.md +164 -25
- package/dist/testing/adversarial_headers.d.ts.map +1 -1
- package/dist/testing/adversarial_headers.js +13 -6
- package/dist/testing/connection_closer_helpers.d.ts +6 -1
- package/dist/testing/connection_closer_helpers.d.ts.map +1 -1
- package/dist/testing/connection_closer_helpers.js +4 -0
- package/dist/testing/cross_backend/account_lifecycle.d.ts.map +1 -1
- package/dist/testing/cross_backend/account_lifecycle.js +37 -2
- package/dist/testing/cross_backend/body_size.d.ts.map +1 -1
- package/dist/testing/cross_backend/body_size.js +14 -65
- package/dist/testing/cross_backend/capabilities.d.ts +26 -2
- package/dist/testing/cross_backend/capabilities.d.ts.map +1 -1
- package/dist/testing/cross_backend/capabilities.js +9 -3
- package/dist/testing/cross_backend/cell_gated_create.d.ts +38 -0
- package/dist/testing/cross_backend/cell_gated_create.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_gated_create.js +401 -5
- package/dist/testing/cross_backend/cell_relations.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_relations.js +145 -2
- package/dist/testing/cross_backend/conformance_case.d.ts +11 -3
- package/dist/testing/cross_backend/conformance_case.d.ts.map +1 -1
- package/dist/testing/cross_backend/conformance_case.js +6 -0
- package/dist/testing/cross_backend/conformance_table.d.ts.map +1 -1
- package/dist/testing/cross_backend/conformance_table.js +20 -19
- package/dist/testing/cross_backend/credential_deadline.d.ts +25 -0
- package/dist/testing/cross_backend/credential_deadline.d.ts.map +1 -0
- package/dist/testing/cross_backend/credential_deadline.js +185 -0
- package/dist/testing/cross_backend/default_backend_configs.d.ts.map +1 -1
- package/dist/testing/cross_backend/default_backend_configs.js +13 -2
- package/dist/testing/cross_backend/expected_schema.json +0 -1
- package/dist/testing/cross_backend/full_spine_mount.d.ts +3 -0
- package/dist/testing/cross_backend/full_spine_mount.d.ts.map +1 -1
- package/dist/testing/cross_backend/full_spine_mount.js +7 -1
- package/dist/testing/cross_backend/login_security.d.ts +16 -0
- package/dist/testing/cross_backend/login_security.d.ts.map +1 -1
- package/dist/testing/cross_backend/login_security.js +154 -0
- package/dist/testing/cross_backend/narrowed_api_token.d.ts +23 -0
- package/dist/testing/cross_backend/narrowed_api_token.d.ts.map +1 -0
- package/dist/testing/cross_backend/narrowed_api_token.js +40 -0
- package/dist/testing/cross_backend/origin.d.ts.map +1 -1
- package/dist/testing/cross_backend/origin.js +6 -26
- package/dist/testing/cross_backend/origin_conformance.d.ts +152 -0
- package/dist/testing/cross_backend/origin_conformance.d.ts.map +1 -0
- package/dist/testing/cross_backend/origin_conformance.js +136 -0
- package/dist/testing/cross_backend/origin_conformance.json +1679 -0
- package/dist/testing/cross_backend/origin_scope.d.ts +16 -0
- package/dist/testing/cross_backend/origin_scope.d.ts.map +1 -0
- package/dist/testing/cross_backend/origin_scope.js +140 -0
- package/dist/testing/cross_backend/query_shape.d.ts.map +1 -1
- package/dist/testing/cross_backend/query_shape.js +24 -2
- package/dist/testing/cross_backend/role_grant_cross_helpers.d.ts +35 -0
- package/dist/testing/cross_backend/role_grant_cross_helpers.d.ts.map +1 -0
- package/dist/testing/cross_backend/role_grant_cross_helpers.js +64 -0
- package/dist/testing/cross_backend/role_grant_offer_notification_ws.d.ts +8 -0
- 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 +44 -33
- package/dist/testing/cross_backend/role_grant_participation.d.ts.map +1 -1
- package/dist/testing/cross_backend/role_grant_participation.js +64 -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 +6 -4
- package/dist/testing/cross_backend/spine_surface_constants.d.ts +20 -1
- package/dist/testing/cross_backend/spine_surface_constants.d.ts.map +1 -1
- package/dist/testing/cross_backend/spine_surface_constants.js +23 -1
- package/dist/testing/cross_backend/testing_backdoor.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_backdoor.js +20 -7
- package/dist/testing/cross_backend/testing_reset_actions.d.ts +180 -5
- package/dist/testing/cross_backend/testing_reset_actions.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_reset_actions.js +154 -5
- package/dist/testing/cross_backend/token_scope_surface.d.ts.map +1 -1
- package/dist/testing/cross_backend/token_scope_surface.js +25 -21
- package/dist/testing/cross_backend/transport_composition.d.ts +60 -0
- package/dist/testing/cross_backend/transport_composition.d.ts.map +1 -0
- package/dist/testing/cross_backend/transport_composition.js +364 -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 +21 -6
- package/dist/testing/cross_backend/ws_action_rate_limit.d.ts.map +1 -1
- package/dist/testing/cross_backend/ws_action_rate_limit.js +21 -1
- package/dist/testing/cross_backend/ws_role_gated.d.ts +38 -0
- package/dist/testing/cross_backend/ws_role_gated.d.ts.map +1 -0
- package/dist/testing/cross_backend/ws_role_gated.js +142 -0
- package/dist/testing/entities.d.ts +23 -0
- package/dist/testing/entities.d.ts.map +1 -1
- package/dist/testing/entities.js +37 -0
- package/dist/testing/integration.d.ts.map +1 -1
- package/dist/testing/integration.js +3 -1
- package/dist/testing/middleware.d.ts +10 -0
- package/dist/testing/middleware.d.ts.map +1 -1
- package/dist/testing/middleware.js +31 -7
- package/dist/testing/schema_introspect.js +1 -1
- package/dist/testing/schema_parity.d.ts +4 -3
- package/dist/testing/schema_parity.d.ts.map +1 -1
- package/dist/testing/schema_parity.js +4 -3
- package/dist/testing/schema_ready_fixture.d.ts +2 -4
- package/dist/testing/schema_ready_fixture.d.ts.map +1 -1
- package/dist/testing/schema_ready_fixture.js +2 -4
- package/dist/testing/stubs.d.ts +16 -3
- package/dist/testing/stubs.d.ts.map +1 -1
- package/dist/testing/stubs.js +20 -7
- package/dist/testing/surface_invariants.js +2 -2
- package/dist/ui/auth_state.svelte.d.ts +10 -0
- package/dist/ui/auth_state.svelte.d.ts.map +1 -1
- package/dist/ui/auth_state.svelte.js +22 -4
- package/package.json +1 -1
- package/dist/db/cell_history_ddl.d.ts +0 -38
- package/dist/db/cell_history_ddl.d.ts.map +0 -1
- package/dist/db/cell_history_ddl.js +0 -61
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import '../assert_dev_env.js';
|
|
2
|
+
/**
|
|
3
|
+
* Cross-process **role-gated WebSocket** suite — a socket admitted by an
|
|
4
|
+
* endpoint's role gate (`register_ws_endpoint`'s `required_roles`) loses it
|
|
5
|
+
* with the role.
|
|
6
|
+
*
|
|
7
|
+
* A role gate decides who may hold a socket, and so who receives the
|
|
8
|
+
* endpoint's server pushes, which reach every admitted connection with no
|
|
9
|
+
* per-recipient filter. So both spines record the gating roles on each
|
|
10
|
+
* registration and close the account's gated sockets when a global grant of a
|
|
11
|
+
* listed role is revoked — with `WS_CLOSE_PERMISSION_REVOKED`, not the
|
|
12
|
+
* session-revoked code, since the credential is still good — and send nothing
|
|
13
|
+
* after the close. The ungated sockets of the same account, on the same
|
|
14
|
+
* transport, stay open: the gate is per endpoint, not per account. A scoped
|
|
15
|
+
* grant never admits at a role gate, so revoking one closes nothing.
|
|
16
|
+
*
|
|
17
|
+
* Runs against a backend that mounts, beside its ungated `ws_path`, a second
|
|
18
|
+
* endpoint at `gated_ws_path` gated on `gated_roles` — which must include
|
|
19
|
+
* `ROLE_ADMIN` (the revoked global grant) and a role that can be granted both
|
|
20
|
+
* globally and scoped (the scoped revoke). fuz_app's spine binaries mount
|
|
21
|
+
* `SPINE_ROLE_GATED_WS_PATH` gated on `SPINE_ROLE_GATED_WS_ROLES`. Gated on
|
|
22
|
+
* `capabilities.ws` and `capabilities.ws_role_gated`; cross-process only.
|
|
23
|
+
*
|
|
24
|
+
* @module
|
|
25
|
+
*/
|
|
26
|
+
import { assert, describe } from 'vitest';
|
|
27
|
+
import { assert_rejects } from '@fuzdev/fuz_util/testing.ts';
|
|
28
|
+
import { heartbeat_action_spec } from '../../actions/heartbeat.js';
|
|
29
|
+
import { WS_CLOSE_PERMISSION_REVOKED, WS_CLOSE_PERMISSION_REVOKED_REASON } from '../../actions/transports.js';
|
|
30
|
+
import { ROLE_ADMIN } from '../../auth/role_schema.js';
|
|
31
|
+
import { ROLE_GRANT_OFFER_RECEIVED_NOTIFICATION_METHOD } from '../../auth/role_grant_offer_notifications.js';
|
|
32
|
+
import { rpc_call } from '../rpc_helpers.js';
|
|
33
|
+
import { is_notification_with } from '../transports/ws_client.js';
|
|
34
|
+
import { create_admitted_ws_transport, create_ws_transport } from '../transports/ws_transport.js';
|
|
35
|
+
import { test_if } from './capabilities.js';
|
|
36
|
+
import { create_active_role_grant, create_pending_role_grant_offer } from './role_grant_cross_helpers.js';
|
|
37
|
+
import { SPINE_RPC_PATH } from './spine_surface_constants.js';
|
|
38
|
+
/** How long a socket that must stay open is watched for a close it must not get. */
|
|
39
|
+
const STAYS_OPEN_MS = 1500;
|
|
40
|
+
/**
|
|
41
|
+
* Register the role-gated WebSocket suite: a revoked global grant of a gating
|
|
42
|
+
* role closes the account's gated socket with `WS_CLOSE_PERMISSION_REVOKED`,
|
|
43
|
+
* its ungated socket stays open and still receives the account's pushes, and
|
|
44
|
+
* a re-upgrade is refused at the gate; a scoped revoke of a gating role
|
|
45
|
+
* closes nothing.
|
|
46
|
+
*
|
|
47
|
+
* That the closed registration is sent nothing more is beyond what a client
|
|
48
|
+
* can observe once it has read the close frame, so the suite does not claim
|
|
49
|
+
* it: each spine's own transport tests pin it.
|
|
50
|
+
*/
|
|
51
|
+
export const describe_ws_role_gated_cross_tests = (options) => {
|
|
52
|
+
const { setup_test, capabilities, base_url, ws_path, gated_ws_path, gated_roles, scoped_role, rpc_path = SPINE_RPC_PATH } = options;
|
|
53
|
+
const enabled = capabilities.ws && capabilities.ws_role_gated;
|
|
54
|
+
if (enabled && (!gated_roles.includes(ROLE_ADMIN) || !gated_roles.includes(scoped_role))) {
|
|
55
|
+
throw new Error(`describe_ws_role_gated_cross_tests: gated_roles must include ${ROLE_ADMIN} and ${scoped_role}`);
|
|
56
|
+
}
|
|
57
|
+
const rpc = (fixture, method, params, headers = fixture.create_session_headers()) => rpc_call({ app: fixture.transport, path: rpc_path, method, params, headers });
|
|
58
|
+
const cookie_of = (account) => {
|
|
59
|
+
const { cookie } = account.create_session_headers();
|
|
60
|
+
assert.ok(cookie, 'expected a session cookie for the WS upgrade');
|
|
61
|
+
return cookie;
|
|
62
|
+
};
|
|
63
|
+
const open = (path, account) => create_admitted_ws_transport({
|
|
64
|
+
base_url,
|
|
65
|
+
ws_path: path,
|
|
66
|
+
cookies: [cookie_of(account)],
|
|
67
|
+
origin: base_url
|
|
68
|
+
});
|
|
69
|
+
describe('role-gated websocket (cross-process)', () => {
|
|
70
|
+
test_if(enabled, 'revoking a global grant of a gating role closes the gated socket with WS_CLOSE_PERMISSION_REVOKED', async () => {
|
|
71
|
+
const fixture = await setup_test();
|
|
72
|
+
const target = await fixture.create_account({ roles: [ROLE_ADMIN] });
|
|
73
|
+
const role_grant_id = await create_active_role_grant(fixture, target, { rpc_path });
|
|
74
|
+
const gated = await open(gated_ws_path, target);
|
|
75
|
+
const ungated = await open(ws_path, target);
|
|
76
|
+
try {
|
|
77
|
+
const revoked = await rpc(fixture, 'role_grant_revoke', {
|
|
78
|
+
actor_id: target.actor.id,
|
|
79
|
+
role_grant_id
|
|
80
|
+
});
|
|
81
|
+
assert.isTrue(revoked.ok, `revoke failed: ${JSON.stringify(revoked)}`);
|
|
82
|
+
assert.ok(await gated.wait_for_close(5000), 'the gated socket did not close');
|
|
83
|
+
assert.strictEqual(gated.close_code, WS_CLOSE_PERMISSION_REVOKED);
|
|
84
|
+
assert.strictEqual(gated.close_reason, WS_CLOSE_PERMISSION_REVOKED_REASON);
|
|
85
|
+
// a push to the account still reaches its ungated socket, and the
|
|
86
|
+
// closed client records nothing more
|
|
87
|
+
const received_before = gated.messages.length;
|
|
88
|
+
await create_pending_role_grant_offer(fixture, target.account.id, fixture.create_session_headers(), { rpc_path });
|
|
89
|
+
await ungated.wait_for(is_notification_with(ROLE_GRANT_OFFER_RECEIVED_NOTIFICATION_METHOD, (p) => p.offer.to_account_id === target.account.id), 5000);
|
|
90
|
+
assert.strictEqual(gated.messages.length, received_before);
|
|
91
|
+
// the account's ungated socket on the same backend stays open
|
|
92
|
+
assert.strictEqual(ungated.close_code, null);
|
|
93
|
+
assert.deepStrictEqual(await ungated.request(2, heartbeat_action_spec.method, {}), {});
|
|
94
|
+
// and the gate refuses the account a new gated socket
|
|
95
|
+
await assert_rejects(() => create_ws_transport({
|
|
96
|
+
base_url,
|
|
97
|
+
ws_path: gated_ws_path,
|
|
98
|
+
cookies: [cookie_of(target)],
|
|
99
|
+
origin: base_url
|
|
100
|
+
}), /403/);
|
|
101
|
+
}
|
|
102
|
+
finally {
|
|
103
|
+
await gated.close();
|
|
104
|
+
await ungated.close();
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
test_if(enabled, 'a scoped revoke of a gating role closes nothing', async () => {
|
|
108
|
+
const fixture = await setup_test();
|
|
109
|
+
// a global grant of `scoped_role` admits the socket — which proves the
|
|
110
|
+
// endpoint lists it, so the scoped revoke below is one of a gating role
|
|
111
|
+
const target = await fixture.create_account();
|
|
112
|
+
const assign = async (scope) => {
|
|
113
|
+
const assigned = await rpc(fixture, 'role_grant_assign', {
|
|
114
|
+
to_account_id: target.account.id,
|
|
115
|
+
role: scoped_role,
|
|
116
|
+
...scope
|
|
117
|
+
});
|
|
118
|
+
if (!assigned.ok)
|
|
119
|
+
assert.fail(`assign failed: ${JSON.stringify(assigned)}`);
|
|
120
|
+
return assigned.result.role_grant_id;
|
|
121
|
+
};
|
|
122
|
+
await assign({});
|
|
123
|
+
const role_grant_id = await assign({
|
|
124
|
+
scope_kind: 'space',
|
|
125
|
+
scope_id: '33333333-3333-4333-8333-333333333333'
|
|
126
|
+
});
|
|
127
|
+
const gated = await open(gated_ws_path, target);
|
|
128
|
+
try {
|
|
129
|
+
const revoked = await rpc(fixture, 'role_grant_revoke', {
|
|
130
|
+
actor_id: target.actor.id,
|
|
131
|
+
role_grant_id
|
|
132
|
+
});
|
|
133
|
+
assert.isTrue(revoked.ok, `revoke failed: ${JSON.stringify(revoked)}`);
|
|
134
|
+
assert.isFalse(await gated.wait_for_close(STAYS_OPEN_MS), `closed with ${gated.close_code} on a scoped revoke`);
|
|
135
|
+
assert.deepStrictEqual(await gated.request(2, heartbeat_action_spec.method, {}), {});
|
|
136
|
+
}
|
|
137
|
+
finally {
|
|
138
|
+
await gated.close();
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
};
|
|
@@ -2,6 +2,7 @@ import './assert_dev_env.js';
|
|
|
2
2
|
import type { Account, Actor, RoleGrant } from '../auth/account_schema.js';
|
|
3
3
|
import type { AuditLogEvent } from '../auth/audit_log_schema.js';
|
|
4
4
|
import type { RequestActorContext } from '../auth/request_context.js';
|
|
5
|
+
import type { ValidatedApiToken } from '../auth/api_token_queries.js';
|
|
5
6
|
/** Override type for `create_test_account` — id-like fields accept plain `string`. */
|
|
6
7
|
export type TestAccountOverrides = Partial<Omit<Account, 'id' | 'created_by' | 'updated_by'>> & {
|
|
7
8
|
id?: string;
|
|
@@ -45,4 +46,26 @@ export type TestAuditEventOverrides = Partial<Omit<AuditLogEvent, 'id' | 'actor_
|
|
|
45
46
|
};
|
|
46
47
|
/** Create a test `AuditLogEvent` with sensible defaults. */
|
|
47
48
|
export declare const create_test_audit_event: (overrides?: TestAuditEventOverrides) => AuditLogEvent;
|
|
49
|
+
/**
|
|
50
|
+
* Create a well-formed raw API token for tests that need a bearer value to
|
|
51
|
+
* pass the `is_api_token_shaped` precheck and reach token validation. The
|
|
52
|
+
* body is `label` padded with `A` to the generated length, so distinct labels
|
|
53
|
+
* give distinct tokens and a token in a failure message reads back to its
|
|
54
|
+
* test. Not a real credential — it authenticates only where a test mocks the
|
|
55
|
+
* lookup.
|
|
56
|
+
*
|
|
57
|
+
* @param label - base64url characters (`A-Z a-z 0-9 - _`) that start the token body
|
|
58
|
+
* @returns `API_TOKEN_PREFIX` plus an `API_TOKEN_BODY_LENGTH`-char body
|
|
59
|
+
* @throws Error when `label` is longer than the body or not base64url
|
|
60
|
+
*/
|
|
61
|
+
export declare const create_test_raw_api_token: (label?: string) => string;
|
|
62
|
+
/** Override type for `create_test_validated_api_token` — `account_id` accepts plain `string`. */
|
|
63
|
+
export type TestValidatedApiTokenOverrides = Partial<Omit<ValidatedApiToken, 'account_id'>> & {
|
|
64
|
+
account_id?: string;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Create a test `ValidatedApiToken` — what `query_validate_api_token` returns
|
|
68
|
+
* for a live token — with a `full` scope by default.
|
|
69
|
+
*/
|
|
70
|
+
export declare const create_test_validated_api_token: (overrides?: TestValidatedApiTokenOverrides) => ValidatedApiToken;
|
|
48
71
|
//# sourceMappingURL=entities.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entities.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/entities.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAiB7B,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAC3E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEtE,sFAAsF;AACtF,MAAM,MAAM,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,GAAG,YAAY,GAAG,YAAY,CAAC,CAAC,GAAG;IAC/F,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,mBAAmB,GAAI,YAAY,oBAAoB,KAAG,OAarE,CAAC;AAEH,oFAAoF;AACpF,MAAM,MAAM,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,GAAG,YAAY,GAAG,YAAY,CAAC,CAAC,GAAG;IAC3F,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF,oDAAoD;AACpD,eAAO,MAAM,iBAAiB,GAAI,YAAY,kBAAkB,KAAG,KAUjE,CAAC;AAEH,yFAAyF;AACzF,MAAM,MAAM,sBAAsB,GAAG,OAAO,CAC3C,IAAI,CACH,SAAS,EACT,IAAI,GAAG,UAAU,GAAG,YAAY,GAAG,UAAU,GAAG,YAAY,GAAG,YAAY,GAAG,iBAAiB,CAC/F,CACD,GAAG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,CAAC;AAEF,wDAAwD;AACxD,eAAO,MAAM,sBAAsB,GAAI,YAAY,sBAAsB,KAAG,SAgB3E,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAC/B,cAAa,KAAK,CAAC,sBAAsB,CAAQ,KAC/C,mBAID,CAAC;AAEH,0FAA0F;AAC1F,MAAM,MAAM,uBAAuB,GAAG,OAAO,CAC5C,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,UAAU,GAAG,YAAY,GAAG,mBAAmB,GAAG,iBAAiB,CAAC,CAC/F,GAAG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,uBAAuB,GAAI,YAAY,uBAAuB,KAAG,aAa5E,CAAC"}
|
|
1
|
+
{"version":3,"file":"entities.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/entities.ts"],"names":[],"mappings":"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"}
|
package/dist/testing/entities.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import './assert_dev_env.js';
|
|
2
|
+
import { API_TOKEN_BODY_LENGTH, API_TOKEN_PREFIX } from '../auth/api_token.js';
|
|
3
|
+
import { token_scope_full } from '../auth/token_scope.js';
|
|
2
4
|
/** Create a test `Account` with sensible defaults. */
|
|
3
5
|
export const create_test_account = (overrides) => ({
|
|
4
6
|
id: 'acct-test',
|
|
@@ -68,3 +70,38 @@ export const create_test_audit_event = (overrides) => ({
|
|
|
68
70
|
metadata: null,
|
|
69
71
|
...overrides
|
|
70
72
|
});
|
|
73
|
+
/**
|
|
74
|
+
* Create a well-formed raw API token for tests that need a bearer value to
|
|
75
|
+
* pass the `is_api_token_shaped` precheck and reach token validation. The
|
|
76
|
+
* body is `label` padded with `A` to the generated length, so distinct labels
|
|
77
|
+
* give distinct tokens and a token in a failure message reads back to its
|
|
78
|
+
* test. Not a real credential — it authenticates only where a test mocks the
|
|
79
|
+
* lookup.
|
|
80
|
+
*
|
|
81
|
+
* @param label - base64url characters (`A-Z a-z 0-9 - _`) that start the token body
|
|
82
|
+
* @returns `API_TOKEN_PREFIX` plus an `API_TOKEN_BODY_LENGTH`-char body
|
|
83
|
+
* @throws Error when `label` is longer than the body or not base64url
|
|
84
|
+
*/
|
|
85
|
+
export const create_test_raw_api_token = (label = 'test') => {
|
|
86
|
+
if (label.length > API_TOKEN_BODY_LENGTH || !/^[A-Za-z0-9_-]*$/.test(label)) {
|
|
87
|
+
throw new Error(`create_test_raw_api_token: label must be at most ${API_TOKEN_BODY_LENGTH} base64url chars, got '${label}'`);
|
|
88
|
+
}
|
|
89
|
+
return API_TOKEN_PREFIX + label.padEnd(API_TOKEN_BODY_LENGTH, 'A');
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* Create a test `ValidatedApiToken` — what `query_validate_api_token` returns
|
|
93
|
+
* for a live token — with a `full` scope by default.
|
|
94
|
+
*/
|
|
95
|
+
export const create_test_validated_api_token = (overrides) => ({
|
|
96
|
+
id: 'tok_test',
|
|
97
|
+
account_id: 'acct-test',
|
|
98
|
+
name: 'test token',
|
|
99
|
+
token_hash: 'hash',
|
|
100
|
+
expires_at: null,
|
|
101
|
+
last_used_at: null,
|
|
102
|
+
last_used_ip: null,
|
|
103
|
+
created_at: '2024-01-01T00:00:00Z',
|
|
104
|
+
scope: token_scope_full(),
|
|
105
|
+
expires_in_ms: null,
|
|
106
|
+
...overrides
|
|
107
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integration.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/integration.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAsB7B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAMhE,OAAO,EAKN,KAAK,uBAAuB,EAC5B,MAAM,kBAAkB,CAAC;AAkB1B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,EAAW,KAAK,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAKpF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"integration.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/integration.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAsB7B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAMhE,OAAO,EAKN,KAAK,uBAAuB,EAC5B,MAAM,kBAAkB,CAAC;AAkB1B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,EAAW,KAAK,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAKpF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAI1D;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC9C;;;;OAIG;IACH,UAAU,EAAE,SAAS,CAAC;IACtB;;;;;;;;;OASG;IACH,cAAc,EAAE,cAAc,CAAC;IAC/B,kEAAkE;IAClE,YAAY,EAAE,mBAAmB,CAAC;IAClC;;;;OAIG;IACH,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC;;;;;;;;;;;;OAYG;IACH,aAAa,EAAE,uBAAuB,CAAC;IACvC;;;;;;;OAOG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,eAAO,MAAM,mCAAmC,GAC/C,SAAS,8BAA8B,KACrC,IAy+CF,CAAC"}
|
|
@@ -27,6 +27,7 @@ import { LoginOutput, AccountStatusOutput } from '../auth/account_route_schema.j
|
|
|
27
27
|
import { test_if } from './cross_backend/capabilities.js';
|
|
28
28
|
import { assert_iso8601_seconds, assert_iso8601_seconds_nullable } from './cross_backend/wire_shapes.js';
|
|
29
29
|
import { DEFAULT_TEST_PASSWORD } from './test_credentials.js';
|
|
30
|
+
import { create_test_raw_api_token } from './entities.js';
|
|
30
31
|
/**
|
|
31
32
|
* Standard integration test suite for fuz_app auth routes.
|
|
32
33
|
*
|
|
@@ -611,7 +612,8 @@ export const describe_standard_integration_tests = (options) => {
|
|
|
611
612
|
path: rpc_path,
|
|
612
613
|
spec: account_verify_action_spec,
|
|
613
614
|
params: undefined,
|
|
614
|
-
|
|
615
|
+
// well-formed, so the refusal is the lookup's, not the shape precheck's
|
|
616
|
+
headers: { authorization: `Bearer ${create_test_raw_api_token('invalid')}` },
|
|
615
617
|
suppress_default_origin: true
|
|
616
618
|
});
|
|
617
619
|
assert.strictEqual(res.status, 401);
|
|
@@ -12,6 +12,7 @@ import { vi } from 'vitest';
|
|
|
12
12
|
import { Hono } from 'hono';
|
|
13
13
|
import type { z } from 'zod';
|
|
14
14
|
import { type RequestContext } from '../auth/request_context.js';
|
|
15
|
+
import type { TokenScope } from '../auth/token_scope.js';
|
|
15
16
|
/** Mock configuration for bearer auth middleware test setup. */
|
|
16
17
|
export interface BearerAuthTestOptions {
|
|
17
18
|
/** Test description. */
|
|
@@ -45,6 +46,14 @@ export interface BearerAuthTestCase extends BearerAuthTestOptions {
|
|
|
45
46
|
expected_account_id?: string;
|
|
46
47
|
/** If set, assert `AUTH_API_TOKEN_ID_KEY` was set to this value after a successful bearer auth. */
|
|
47
48
|
expected_api_token_id?: string;
|
|
49
|
+
/** If set, assert `TOKEN_SCOPE_KEY` was set to this scope after a successful bearer auth. */
|
|
50
|
+
expected_token_scope?: TokenScope;
|
|
51
|
+
/**
|
|
52
|
+
* If set, assert `CREDENTIAL_DEADLINE_KEY` after a successful bearer auth:
|
|
53
|
+
* `null` for none (an eternal token), or the milliseconds it should lie
|
|
54
|
+
* ahead, within a second.
|
|
55
|
+
*/
|
|
56
|
+
expected_credential_deadline_ms?: number | null;
|
|
48
57
|
/** If true, assert the pre-existing session `ACCOUNT_ID_KEY` and credential type are preserved. */
|
|
49
58
|
assert_context_preserved?: boolean;
|
|
50
59
|
/** Optional callback for custom spy assertions on the mocks bundle. */
|
|
@@ -118,6 +127,7 @@ export interface TestMiddlewareStackApp {
|
|
|
118
127
|
* @returns the app and mock spies (reconfigure via `mockImplementation` for valid-token paths)
|
|
119
128
|
* @mutates module-level `vi.mock` registrations for the four bearer-auth query
|
|
120
129
|
* modules — each call resets the spies before wiring the stack.
|
|
130
|
+
* @throws Error when `allowed_origins` is not a valid allowlist
|
|
121
131
|
*/
|
|
122
132
|
export declare const create_test_middleware_stack_app: (options?: TestMiddlewareStackOptions) => TestMiddlewareStackApp;
|
|
123
133
|
//# sourceMappingURL=middleware.d.ts.map
|
|
@@ -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,15 +12,15 @@ 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
|
+
import { AUTH_MIDDLEWARE_PATH, ORIGIN_MIDDLEWARE_PATH } from '../auth/middleware.js';
|
|
16
16
|
import { query_validate_api_token } from '../auth/api_token_queries.js';
|
|
17
17
|
import { query_account_by_id, query_actor_by_id, query_active_actors_by_account } from '../auth/account_queries.js';
|
|
18
18
|
import { query_role_grant_find_active_for_actor } from '../auth/role_grant_queries.js';
|
|
19
19
|
import { create_proxy_middleware } from '../http/proxy.js';
|
|
20
20
|
import { get_client_ip } from '../http/client_ip.js';
|
|
21
|
-
import { verify_request_source, parse_allowed_origins } from '../http/origin.js';
|
|
21
|
+
import { verify_request_source, parse_allowed_origins, format_allowed_origins_error } from '../http/origin.js';
|
|
22
22
|
import { REQUEST_CONTEXT_KEY } from '../auth/request_context.js';
|
|
23
|
-
import { ACCOUNT_ID_KEY, AUTH_API_TOKEN_ID_KEY, CREDENTIAL_TYPE_KEY, TEST_CONTEXT_PRESET_KEY } from '../hono_context.js';
|
|
23
|
+
import { ACCOUNT_ID_KEY, AUTH_API_TOKEN_ID_KEY, CREDENTIAL_DEADLINE_KEY, CREDENTIAL_TYPE_KEY, TEST_CONTEXT_PRESET_KEY, TOKEN_SCOPE_KEY } from '../hono_context.js';
|
|
24
24
|
import { ApiError } from '../http/error_schemas.js';
|
|
25
25
|
// Mock the query modules so test cases can control return values.
|
|
26
26
|
// vi.mock() is hoisted by vitest, so these run before any imports resolve.
|
|
@@ -121,19 +121,25 @@ export const create_bearer_auth_test_app = (tc) => {
|
|
|
121
121
|
app.use(AUTH_MIDDLEWARE_PATH, bearer_middleware);
|
|
122
122
|
// route handler echoes the account-grain identity the middleware writes
|
|
123
123
|
// (bearer auth sets `ACCOUNT_ID_KEY` + `CREDENTIAL_TYPE_KEY` +
|
|
124
|
-
// `AUTH_API_TOKEN_ID_KEY`; it never builds the full request context —
|
|
124
|
+
// `AUTH_API_TOKEN_ID_KEY` + `TOKEN_SCOPE_KEY`; it never builds the full request context —
|
|
125
125
|
// that is the dispatcher's authorization phase). `request_context_set`
|
|
126
126
|
// is only true when a test pre-populates it via `pre_context`.
|
|
127
127
|
app.get('/api/test', (c) => {
|
|
128
128
|
const account_id = c.get(ACCOUNT_ID_KEY);
|
|
129
129
|
const cred = c.get(CREDENTIAL_TYPE_KEY);
|
|
130
130
|
const api_token_id = c.get(AUTH_API_TOKEN_ID_KEY);
|
|
131
|
+
const token_scope = c.get(TOKEN_SCOPE_KEY);
|
|
132
|
+
const credential_deadline = c.get(CREDENTIAL_DEADLINE_KEY) ?? null;
|
|
131
133
|
const ctx = c.get(REQUEST_CONTEXT_KEY);
|
|
132
134
|
return c.json({
|
|
133
135
|
ok: true,
|
|
134
136
|
account_id: account_id ?? null,
|
|
135
137
|
credential_type: cred ?? null,
|
|
136
138
|
api_token_id: api_token_id ?? null,
|
|
139
|
+
token_scope: token_scope ?? null,
|
|
140
|
+
// how far ahead the deadline lies, since the monotonic value itself
|
|
141
|
+
// means nothing outside this process
|
|
142
|
+
credential_deadline_in_ms: credential_deadline === null ? null : credential_deadline - performance.now(),
|
|
137
143
|
request_context_set: ctx != null
|
|
138
144
|
});
|
|
139
145
|
});
|
|
@@ -182,6 +188,20 @@ export const describe_bearer_auth_cases = (suite_name, cases) => {
|
|
|
182
188
|
if (tc.expected_api_token_id !== undefined) {
|
|
183
189
|
assert.strictEqual(body.api_token_id, tc.expected_api_token_id, 'AUTH_API_TOKEN_ID_KEY should match the validated api_token.id');
|
|
184
190
|
}
|
|
191
|
+
if (tc.expected_token_scope !== undefined) {
|
|
192
|
+
assert.deepStrictEqual(body.token_scope, tc.expected_token_scope, 'TOKEN_SCOPE_KEY should be the scope the validated api_token carries');
|
|
193
|
+
}
|
|
194
|
+
if (tc.expected_credential_deadline_ms !== undefined) {
|
|
195
|
+
if (tc.expected_credential_deadline_ms === null) {
|
|
196
|
+
assert.strictEqual(body.credential_deadline_in_ms, null, 'CREDENTIAL_DEADLINE_KEY should be null for a token with no expiry');
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
const ahead = body.credential_deadline_in_ms;
|
|
200
|
+
assert.ok(typeof ahead === 'number' &&
|
|
201
|
+
ahead <= tc.expected_credential_deadline_ms &&
|
|
202
|
+
ahead > tc.expected_credential_deadline_ms - 1000, `CREDENTIAL_DEADLINE_KEY should lie ${tc.expected_credential_deadline_ms}ms ahead, got ${String(ahead)}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
185
205
|
if (tc.assert_context_preserved) {
|
|
186
206
|
assert.ok(body.account_id, 'pre-existing account_id should be preserved');
|
|
187
207
|
assert.strictEqual(body.credential_type, 'session', 'credential type should remain session');
|
|
@@ -205,6 +225,7 @@ export const TEST_MIDDLEWARE_PATH = '/api/test';
|
|
|
205
225
|
* @returns the app and mock spies (reconfigure via `mockImplementation` for valid-token paths)
|
|
206
226
|
* @mutates module-level `vi.mock` registrations for the four bearer-auth query
|
|
207
227
|
* modules — each call resets the spies before wiring the stack.
|
|
228
|
+
* @throws Error when `allowed_origins` is not a valid allowlist
|
|
208
229
|
*/
|
|
209
230
|
export const create_test_middleware_stack_app = (options) => {
|
|
210
231
|
const trusted_proxies = options?.trusted_proxies ?? ['10.0.0.1'];
|
|
@@ -226,12 +247,15 @@ export const create_test_middleware_stack_app = (options) => {
|
|
|
226
247
|
trusted_proxies,
|
|
227
248
|
get_connection_ip: get_connection_ip
|
|
228
249
|
});
|
|
229
|
-
const
|
|
230
|
-
|
|
250
|
+
const parsed_origins = parse_allowed_origins(allowed_origins_str);
|
|
251
|
+
if (!parsed_origins.ok) {
|
|
252
|
+
throw new Error(`create_test_middleware_stack_app: invalid allowed_origins: ${parsed_origins.errors.map(format_allowed_origins_error).join('; ')}`);
|
|
253
|
+
}
|
|
254
|
+
const origin_mw = verify_request_source(parsed_origins.origins);
|
|
231
255
|
const bearer_mw = create_bearer_auth_middleware(STUB_DEPS, new Logger('test', { level: 'off' }));
|
|
232
256
|
const app = new Hono();
|
|
233
257
|
app.use('*', proxy_mw);
|
|
234
|
-
app.use(
|
|
258
|
+
app.use(ORIGIN_MIDDLEWARE_PATH, origin_mw);
|
|
235
259
|
app.use(AUTH_MIDDLEWARE_PATH, bearer_mw);
|
|
236
260
|
// echo route for assertions — exposes the account-grain identity bearer
|
|
237
261
|
// auth writes (`ACCOUNT_ID_KEY`); the full request context is the
|
|
@@ -105,7 +105,7 @@ export const SchemaSnapshot = z.object({
|
|
|
105
105
|
* to the schema snapshot — is a gated fact, not a latent interop break.
|
|
106
106
|
*/
|
|
107
107
|
export const MigrationTrackerEntry = z.object({
|
|
108
|
-
/** Migration namespace (e.g. `
|
|
108
|
+
/** Migration namespace (e.g. `fuz_auth`, `fuz_cell`). */
|
|
109
109
|
namespace: z.string(),
|
|
110
110
|
/** Migration name within the namespace (e.g. `full_cell_schema`). */
|
|
111
111
|
name: z.string(),
|
|
@@ -175,9 +175,10 @@ export declare const format_migration_tracker_diffs: (diffs: ReadonlyArray<Migra
|
|
|
175
175
|
* re-bootstrapping). This catches what `assert_schema_snapshots_equal` is blind
|
|
176
176
|
* to by design: the snapshot excludes the tracker, so a migration-name or
|
|
177
177
|
* partitioning divergence that yields an identical *schema* (e.g. `cell_v0` vs
|
|
178
|
-
* `full_cell_schema`, or
|
|
179
|
-
* parity but breaks the runner's positional name-prefix
|
|
180
|
-
* (`name-divergence-at-N`). The error names the impls and lists
|
|
178
|
+
* `full_cell_schema`, or a table bundled into one namespace vs isolated in its
|
|
179
|
+
* own) passes schema parity but breaks the runner's positional name-prefix
|
|
180
|
+
* check at boot (`name-divergence-at-N`). The error names the impls and lists
|
|
181
|
+
* every diff.
|
|
181
182
|
*/
|
|
182
183
|
export declare const assert_migration_trackers_equal: (a: MigrationTracker, b: MigrationTracker, labels?: SchemaDiffLabels) => void;
|
|
183
184
|
//# sourceMappingURL=schema_parity.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema_parity.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/schema_parity.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAE7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,KAAK,EACX,cAAc,EAEd,gBAAgB,EAChB,cAAc,EAGd,MAAM,wBAAwB,CAAC;AAEhC,6EAA6E;AAC7E,MAAM,MAAM,UAAU,GACnB;IAAE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACrF;IACA,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACvB,GACD;IACA,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,cAAc,CAAC;IACrC,QAAQ,CAAC,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,CAAC,EAAE,OAAO,CAAC;CACnB,GACD;IACA,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACtB,GACD;IACA,QAAQ,CAAC,IAAI,EAAE,0BAA0B,CAAC;IAC1C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;CAClB,GACD;IACA,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC3B,GACD;IACA,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,QAAQ,CAAC,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CAChD,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC3F;IACA,QAAQ,CAAC,IAAI,EAAE,4BAA4B,CAAC;IAC5C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;CAClB,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACxF;IACA,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAClC,QAAQ,CAAC,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACjC,CAAC;AAEL;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,GAAI,GAAG,cAAc,EAAE,GAAG,cAAc,KAAG,KAAK,CAAC,UAAU,CAiD5F,CAAC;AAqHF,qEAAqE;AACrE,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAC/B,OAAO,aAAa,CAAC,UAAU,CAAC,EAChC,SAAQ,gBAAqB,KAC3B,MAoEF,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,6BAA6B,GACzC,GAAG,cAAc,EACjB,GAAG,cAAc,EACjB,SAAQ,gBAAqB,KAC3B,IAUF,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,GAC7B;IACA,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;IACrC,QAAQ,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACrB,GACD;IACA,QAAQ,CAAC,IAAI,EAAE,0BAA0B,CAAC;IAC1C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAIL;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GACnC,GAAG,gBAAgB,EACnB,GAAG,gBAAgB,KACjB,KAAK,CAAC,oBAAoB,CAwC5B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,8BAA8B,GAC1C,OAAO,aAAa,CAAC,oBAAoB,CAAC,EAC1C,SAAQ,gBAAqB,KAC3B,MAyBF,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"schema_parity.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/schema_parity.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAE7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,KAAK,EACX,cAAc,EAEd,gBAAgB,EAChB,cAAc,EAGd,MAAM,wBAAwB,CAAC;AAEhC,6EAA6E;AAC7E,MAAM,MAAM,UAAU,GACnB;IAAE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACrF;IACA,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACvB,GACD;IACA,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,cAAc,CAAC;IACrC,QAAQ,CAAC,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,CAAC,EAAE,OAAO,CAAC;CACnB,GACD;IACA,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACtB,GACD;IACA,QAAQ,CAAC,IAAI,EAAE,0BAA0B,CAAC;IAC1C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;CAClB,GACD;IACA,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC3B,GACD;IACA,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,QAAQ,CAAC,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CAChD,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC3F;IACA,QAAQ,CAAC,IAAI,EAAE,4BAA4B,CAAC;IAC5C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;CAClB,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACxF;IACA,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAClC,QAAQ,CAAC,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACjC,CAAC;AAEL;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,GAAI,GAAG,cAAc,EAAE,GAAG,cAAc,KAAG,KAAK,CAAC,UAAU,CAiD5F,CAAC;AAqHF,qEAAqE;AACrE,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAC/B,OAAO,aAAa,CAAC,UAAU,CAAC,EAChC,SAAQ,gBAAqB,KAC3B,MAoEF,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,6BAA6B,GACzC,GAAG,cAAc,EACjB,GAAG,cAAc,EACjB,SAAQ,gBAAqB,KAC3B,IAUF,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,GAC7B;IACA,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;IACrC,QAAQ,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACrB,GACD;IACA,QAAQ,CAAC,IAAI,EAAE,0BAA0B,CAAC;IAC1C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAIL;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GACnC,GAAG,gBAAgB,EACnB,GAAG,gBAAgB,KACjB,KAAK,CAAC,oBAAoB,CAwC5B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,8BAA8B,GAC1C,OAAO,aAAa,CAAC,oBAAoB,CAAC,EAC1C,SAAQ,gBAAqB,KAC3B,MAyBF,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,+BAA+B,GAC3C,GAAG,gBAAgB,EACnB,GAAG,gBAAgB,EACnB,SAAQ,gBAAqB,KAC3B,IAUF,CAAC"}
|
|
@@ -304,9 +304,10 @@ export const format_migration_tracker_diffs = (diffs, labels = {}) => {
|
|
|
304
304
|
* re-bootstrapping). This catches what `assert_schema_snapshots_equal` is blind
|
|
305
305
|
* to by design: the snapshot excludes the tracker, so a migration-name or
|
|
306
306
|
* partitioning divergence that yields an identical *schema* (e.g. `cell_v0` vs
|
|
307
|
-
* `full_cell_schema`, or
|
|
308
|
-
* parity but breaks the runner's positional name-prefix
|
|
309
|
-
* (`name-divergence-at-N`). The error names the impls and lists
|
|
307
|
+
* `full_cell_schema`, or a table bundled into one namespace vs isolated in its
|
|
308
|
+
* own) passes schema parity but breaks the runner's positional name-prefix
|
|
309
|
+
* check at boot (`name-divergence-at-N`). The error names the impls and lists
|
|
310
|
+
* every diff.
|
|
310
311
|
*/
|
|
311
312
|
export const assert_migration_trackers_equal = (a, b, labels = {}) => {
|
|
312
313
|
const diffs = diff_migration_trackers(a, b);
|
|
@@ -35,10 +35,8 @@ export interface SyncExpectedSchemaFixtureResult {
|
|
|
35
35
|
* ```
|
|
36
36
|
*
|
|
37
37
|
* When `update` writes the fixture it emits raw `JSON.stringify` (one array
|
|
38
|
-
* element per line)
|
|
39
|
-
*
|
|
40
|
-
* the regenerated file. (The content is identical either way — the regen test
|
|
41
|
-
* compares values, not formatting.)
|
|
38
|
+
* element per line). `gro format` leaves JSON untouched and the regen test compares values, not
|
|
39
|
+
* formatting, so the layout is cosmetic.
|
|
42
40
|
*
|
|
43
41
|
* @returns the live column map and the committed map (post-write when `update`)
|
|
44
42
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema_ready_fixture.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/schema_ready_fixture.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAmB7B,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAwB,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAElF,kDAAkD;AAClD,MAAM,WAAW,gCAAgC;IAChD,+EAA+E;IAC/E,EAAE,EAAE,EAAE,CAAC;IACP,gFAAgF;IAChF,WAAW,EAAE,GAAG,GAAG,MAAM,CAAC;IAC1B;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,kFAAkF;AAClF,MAAM,WAAW,+BAA+B;IAC/C,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACpC,mEAAmE;IACnE,SAAS,EAAE,cAAc,CAAC;CAC1B;AAED
|
|
1
|
+
{"version":3,"file":"schema_ready_fixture.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/schema_ready_fixture.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAmB7B,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAwB,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAElF,kDAAkD;AAClD,MAAM,WAAW,gCAAgC;IAChD,+EAA+E;IAC/E,EAAE,EAAE,EAAE,CAAC;IACP,gFAAgF;IAChF,WAAW,EAAE,GAAG,GAAG,MAAM,CAAC;IAC1B;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,kFAAkF;AAClF,MAAM,WAAW,+BAA+B;IAC/C,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACpC,mEAAmE;IACnE,SAAS,EAAE,cAAc,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,4BAA4B,GACxC,SAAS,gCAAgC,KACvC,OAAO,CAAC,+BAA+B,CAQzC,CAAC"}
|
|
@@ -30,10 +30,8 @@ import { query_public_columns } from '../db/schema_ready.js';
|
|
|
30
30
|
* ```
|
|
31
31
|
*
|
|
32
32
|
* When `update` writes the fixture it emits raw `JSON.stringify` (one array
|
|
33
|
-
* element per line)
|
|
34
|
-
*
|
|
35
|
-
* the regenerated file. (The content is identical either way — the regen test
|
|
36
|
-
* compares values, not formatting.)
|
|
33
|
+
* element per line). `gro format` leaves JSON untouched and the regen test compares values, not
|
|
34
|
+
* formatting, so the layout is cosmetic.
|
|
37
35
|
*
|
|
38
36
|
* @returns the live column map and the committed map (post-write when `update`)
|
|
39
37
|
*/
|
package/dist/testing/stubs.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import './assert_dev_env.js';
|
|
2
2
|
import type { z } from 'zod';
|
|
3
3
|
import type { SessionOptions } from '../auth/session_cookie.js';
|
|
4
|
-
import type { MiddlewareSpec } from '../http/middleware_spec.js';
|
|
4
|
+
import type { MiddlewareCarveOut, MiddlewareSpec } from '../http/middleware_spec.js';
|
|
5
5
|
import type { AppDeps } from '../auth/deps.js';
|
|
6
6
|
import type { AuditEmitter } from '../auth/audit_emitter.js';
|
|
7
7
|
import type { BootstrapServerOptions } from '../server/app_server.js';
|
|
@@ -111,6 +111,8 @@ export declare const create_stub_app_backend: (options?: CreateStubAppBackendOpt
|
|
|
111
111
|
export declare const create_stub_api_middleware: (options?: {
|
|
112
112
|
/** Include the daemon_token middleware layer. */
|
|
113
113
|
include_daemon_token?: boolean;
|
|
114
|
+
/** The origin check's carve-outs, as `create_auth_middleware_specs` records them. */
|
|
115
|
+
origin_carve_outs?: ReadonlyArray<MiddlewareCarveOut>;
|
|
114
116
|
}) => Array<MiddlewareSpec>;
|
|
115
117
|
/**
|
|
116
118
|
* Create a stub `AppServerContext` for attack surface testing.
|
|
@@ -169,6 +171,14 @@ export interface CreateTestAppSurfaceSpecOptions {
|
|
|
169
171
|
* (`assert_middleware_stack_mounted`).
|
|
170
172
|
*/
|
|
171
173
|
transform_middleware?: (specs: Array<MiddlewareSpec>) => Array<MiddlewareSpec>;
|
|
174
|
+
/**
|
|
175
|
+
* The origin check's carve-outs — `AppServerOptions.origin_carve_outs`.
|
|
176
|
+
* Recorded on the stub origin spec, so the surface leaves the check's `403`
|
|
177
|
+
* off the carved-out routes as the live server's does; refused, like
|
|
178
|
+
* `create_app_server`, when one has no reason or overlaps the auth
|
|
179
|
+
* middleware's scope.
|
|
180
|
+
*/
|
|
181
|
+
origin_carve_outs?: Array<MiddlewareCarveOut>;
|
|
172
182
|
/**
|
|
173
183
|
* Bootstrap config — symmetric with `AppServerOptions.bootstrap`. Discriminated
|
|
174
184
|
* by `mode`: `'disabled'` skips the route (same as omission), `'surface_only'`
|
|
@@ -212,7 +222,9 @@ export interface CreateTestAppSurfaceSpecOptions {
|
|
|
212
222
|
* `GET /api/surface` (with `surface_route: true`), then surface
|
|
213
223
|
* generation — including its
|
|
214
224
|
* refusal of an `rpc_endpoints` or `ws_endpoints` path outside the auth
|
|
215
|
-
* middleware's scope (`assert_endpoint_in_auth_scope`)
|
|
225
|
+
* middleware's scope (`assert_endpoint_in_auth_scope`), of a route that
|
|
226
|
+
* reads or mints a credential outside it
|
|
227
|
+
* (`assert_credential_routes_in_auth_scope`), and of a
|
|
216
228
|
* `transform_middleware` that doesn't keep the proxy and auth stack mounted
|
|
217
229
|
* (`assert_middleware_stack_mounted`). The middleware list mirrors the real
|
|
218
230
|
* one: a stub `trusted_proxy` spec at `'*'`, then the stub auth stack (with
|
|
@@ -222,7 +234,8 @@ export interface CreateTestAppSurfaceSpecOptions {
|
|
|
222
234
|
*
|
|
223
235
|
* @param options - surface spec options
|
|
224
236
|
* @returns the surface spec for the standard suites
|
|
225
|
-
* @throws Error when an endpoint path
|
|
237
|
+
* @throws Error when an endpoint path, or a route that reads or mints a
|
|
238
|
+
* credential, is outside `AUTH_MIDDLEWARE_PATH`, a
|
|
226
239
|
* `ws_endpoints` spec declares no `allowed_origins` and no `allowed_origins`
|
|
227
240
|
* option is given, or `transform_middleware` moves, drops, duplicates,
|
|
228
241
|
* reorders, wraps, or replaces the stub proxy spec or a stub auth spec
|
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"stubs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/stubs.ts"],"names":[],"mappings":"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"}
|