@fuzdev/fuz_app 0.54.0 → 0.56.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 +214 -103
- package/dist/actions/action_bridge.d.ts +8 -5
- package/dist/actions/action_bridge.d.ts.map +1 -1
- package/dist/actions/action_bridge.js +1 -11
- package/dist/actions/action_codegen.d.ts +32 -0
- package/dist/actions/action_codegen.d.ts.map +1 -1
- package/dist/actions/action_codegen.js +35 -15
- package/dist/actions/action_registry.d.ts.map +1 -1
- package/dist/actions/action_registry.js +5 -2
- package/dist/actions/action_rpc.d.ts +141 -22
- package/dist/actions/action_rpc.d.ts.map +1 -1
- package/dist/actions/action_rpc.js +106 -187
- package/dist/actions/action_spec.d.ts +55 -16
- package/dist/actions/action_spec.d.ts.map +1 -1
- package/dist/actions/action_spec.js +16 -11
- package/dist/actions/action_types.d.ts +28 -60
- package/dist/actions/action_types.d.ts.map +1 -1
- package/dist/actions/action_types.js +13 -5
- package/dist/actions/broadcast_api.d.ts +2 -2
- package/dist/actions/broadcast_api.js +2 -2
- package/dist/actions/compile_action_registry.d.ts +50 -0
- package/dist/actions/compile_action_registry.d.ts.map +1 -0
- package/dist/actions/compile_action_registry.js +69 -0
- package/dist/actions/heartbeat.d.ts +8 -4
- package/dist/actions/heartbeat.d.ts.map +1 -1
- package/dist/actions/heartbeat.js +5 -4
- package/dist/actions/perform_action.d.ts +145 -0
- package/dist/actions/perform_action.d.ts.map +1 -0
- package/dist/actions/perform_action.js +258 -0
- package/dist/actions/register_action_ws.d.ts +46 -40
- package/dist/actions/register_action_ws.d.ts.map +1 -1
- package/dist/actions/register_action_ws.js +101 -159
- package/dist/actions/register_ws_endpoint.d.ts +15 -10
- package/dist/actions/register_ws_endpoint.d.ts.map +1 -1
- package/dist/actions/register_ws_endpoint.js +54 -7
- package/dist/actions/transports.d.ts.map +1 -1
- package/dist/actions/transports.js +0 -4
- package/dist/actions/transports_ws_auth_guard.d.ts +1 -1
- package/dist/actions/transports_ws_auth_guard.js +1 -1
- package/dist/actions/transports_ws_backend.d.ts +1 -1
- package/dist/actions/transports_ws_backend.js +1 -1
- package/dist/auth/CLAUDE.md +794 -410
- package/dist/auth/account_action_specs.d.ts +28 -7
- package/dist/auth/account_action_specs.d.ts.map +1 -1
- package/dist/auth/account_action_specs.js +7 -7
- package/dist/auth/account_actions.d.ts +7 -13
- package/dist/auth/account_actions.d.ts.map +1 -1
- package/dist/auth/account_actions.js +26 -35
- package/dist/auth/account_queries.d.ts +52 -16
- package/dist/auth/account_queries.d.ts.map +1 -1
- package/dist/auth/account_queries.js +87 -38
- package/dist/auth/account_routes.d.ts +9 -11
- package/dist/auth/account_routes.d.ts.map +1 -1
- package/dist/auth/account_routes.js +118 -46
- package/dist/auth/account_schema.d.ts +46 -35
- package/dist/auth/account_schema.d.ts.map +1 -1
- package/dist/auth/account_schema.js +21 -28
- package/dist/auth/admin_action_specs.d.ts +100 -32
- package/dist/auth/admin_action_specs.d.ts.map +1 -1
- package/dist/auth/admin_action_specs.js +64 -33
- package/dist/auth/admin_actions.d.ts +13 -19
- package/dist/auth/admin_actions.d.ts.map +1 -1
- package/dist/auth/admin_actions.js +37 -41
- package/dist/auth/audit_emitter.d.ts +160 -0
- package/dist/auth/audit_emitter.d.ts.map +1 -0
- package/dist/auth/audit_emitter.js +83 -0
- package/dist/auth/audit_log_queries.d.ts +17 -48
- package/dist/auth/audit_log_queries.d.ts.map +1 -1
- package/dist/auth/audit_log_queries.js +20 -56
- package/dist/auth/audit_log_routes.d.ts +1 -1
- package/dist/auth/audit_log_routes.d.ts.map +1 -1
- package/dist/auth/audit_log_routes.js +7 -3
- package/dist/auth/audit_log_schema.d.ts +92 -32
- package/dist/auth/audit_log_schema.d.ts.map +1 -1
- package/dist/auth/audit_log_schema.js +75 -46
- package/dist/auth/auth_guard_resolver.d.ts +44 -0
- package/dist/auth/auth_guard_resolver.d.ts.map +1 -0
- package/dist/auth/auth_guard_resolver.js +56 -0
- package/dist/auth/bearer_auth.d.ts +9 -7
- package/dist/auth/bearer_auth.d.ts.map +1 -1
- package/dist/auth/bearer_auth.js +13 -21
- package/dist/auth/bootstrap_account.d.ts +7 -7
- package/dist/auth/bootstrap_account.d.ts.map +1 -1
- package/dist/auth/bootstrap_account.js +7 -7
- package/dist/auth/bootstrap_routes.d.ts.map +1 -1
- package/dist/auth/bootstrap_routes.js +11 -10
- package/dist/auth/cleanup.d.ts +20 -26
- package/dist/auth/cleanup.d.ts.map +1 -1
- package/dist/auth/cleanup.js +33 -42
- package/dist/auth/credential_type_schema.d.ts +115 -0
- package/dist/auth/credential_type_schema.d.ts.map +1 -0
- package/dist/auth/credential_type_schema.js +127 -0
- package/dist/auth/daemon_token_middleware.d.ts +23 -11
- package/dist/auth/daemon_token_middleware.d.ts.map +1 -1
- package/dist/auth/daemon_token_middleware.js +28 -22
- package/dist/auth/ddl.d.ts +2 -2
- package/dist/auth/ddl.d.ts.map +1 -1
- package/dist/auth/ddl.js +6 -6
- package/dist/auth/deps.d.ts +7 -18
- package/dist/auth/deps.d.ts.map +1 -1
- package/dist/auth/grant_path_schema.d.ts +117 -0
- package/dist/auth/grant_path_schema.d.ts.map +1 -0
- package/dist/auth/grant_path_schema.js +137 -0
- package/dist/auth/invite_queries.d.ts +12 -1
- package/dist/auth/invite_queries.d.ts.map +1 -1
- package/dist/auth/invite_queries.js +12 -1
- package/dist/auth/invite_schema.d.ts +1 -1
- package/dist/auth/invite_schema.d.ts.map +1 -1
- package/dist/auth/invite_schema.js +1 -1
- package/dist/auth/middleware.d.ts.map +1 -1
- package/dist/auth/middleware.js +9 -4
- package/dist/auth/migrations.d.ts +37 -14
- package/dist/auth/migrations.d.ts.map +1 -1
- package/dist/auth/migrations.js +79 -32
- package/dist/auth/request_context.d.ts +331 -61
- package/dist/auth/request_context.d.ts.map +1 -1
- package/dist/auth/request_context.js +378 -95
- package/dist/auth/{permit_offer_action_specs.d.ts → role_grant_offer_action_specs.d.ts} +163 -94
- package/dist/auth/role_grant_offer_action_specs.d.ts.map +1 -0
- package/dist/auth/role_grant_offer_action_specs.js +262 -0
- package/dist/auth/role_grant_offer_actions.d.ts +104 -0
- package/dist/auth/role_grant_offer_actions.d.ts.map +1 -0
- package/dist/auth/role_grant_offer_actions.js +473 -0
- package/dist/auth/{permit_offer_notifications.d.ts → role_grant_offer_notifications.d.ts} +90 -70
- package/dist/auth/role_grant_offer_notifications.d.ts.map +1 -0
- package/dist/auth/role_grant_offer_notifications.js +182 -0
- package/dist/auth/role_grant_offer_queries.d.ts +242 -0
- package/dist/auth/role_grant_offer_queries.d.ts.map +1 -0
- package/dist/auth/role_grant_offer_queries.js +533 -0
- package/dist/auth/role_grant_offer_schema.d.ts +150 -0
- package/dist/auth/role_grant_offer_schema.d.ts.map +1 -0
- package/dist/auth/{permit_offer_schema.js → role_grant_offer_schema.js} +60 -36
- package/dist/auth/role_grant_queries.d.ts +231 -0
- package/dist/auth/role_grant_queries.d.ts.map +1 -0
- package/dist/auth/role_grant_queries.js +320 -0
- package/dist/auth/role_schema.d.ts +150 -40
- package/dist/auth/role_schema.d.ts.map +1 -1
- package/dist/auth/role_schema.js +144 -45
- package/dist/auth/scope_kind_schema.d.ts +96 -0
- package/dist/auth/scope_kind_schema.d.ts.map +1 -0
- package/dist/auth/scope_kind_schema.js +94 -0
- package/dist/auth/self_service_role_action_specs.d.ts +6 -1
- package/dist/auth/self_service_role_action_specs.d.ts.map +1 -1
- package/dist/auth/self_service_role_action_specs.js +3 -1
- package/dist/auth/self_service_role_actions.d.ts +34 -27
- package/dist/auth/self_service_role_actions.d.ts.map +1 -1
- package/dist/auth/self_service_role_actions.js +68 -48
- package/dist/auth/session_cookie.d.ts +43 -6
- package/dist/auth/session_cookie.d.ts.map +1 -1
- package/dist/auth/session_cookie.js +31 -5
- package/dist/auth/session_middleware.d.ts +37 -3
- package/dist/auth/session_middleware.d.ts.map +1 -1
- package/dist/auth/session_middleware.js +33 -7
- package/dist/auth/signup_routes.d.ts.map +1 -1
- package/dist/auth/signup_routes.js +48 -19
- package/dist/auth/standard_action_specs.d.ts +2 -2
- package/dist/auth/standard_action_specs.js +4 -4
- package/dist/auth/standard_rpc_actions.d.ts +23 -19
- package/dist/auth/standard_rpc_actions.d.ts.map +1 -1
- package/dist/auth/standard_rpc_actions.js +12 -12
- package/dist/db/migrate.d.ts +12 -8
- package/dist/db/migrate.d.ts.map +1 -1
- package/dist/db/migrate.js +10 -7
- package/dist/dev/setup.d.ts +2 -2
- package/dist/dev/setup.d.ts.map +1 -1
- package/dist/dev/setup.js +9 -7
- package/dist/env/load.d.ts +1 -1
- package/dist/env/load.js +1 -1
- package/dist/hono_context.d.ts +64 -5
- package/dist/hono_context.d.ts.map +1 -1
- package/dist/hono_context.js +38 -2
- package/dist/http/CLAUDE.md +264 -87
- package/dist/http/auth_shape.d.ts +191 -0
- package/dist/http/auth_shape.d.ts.map +1 -0
- package/dist/http/auth_shape.js +237 -0
- package/dist/http/common_routes.js +3 -3
- package/dist/http/db_routes.d.ts +4 -0
- package/dist/http/db_routes.d.ts.map +1 -1
- package/dist/http/db_routes.js +44 -7
- package/dist/http/error_schemas.d.ts +132 -19
- package/dist/http/error_schemas.d.ts.map +1 -1
- package/dist/http/error_schemas.js +132 -40
- package/dist/http/jsonrpc_errors.d.ts +27 -2
- package/dist/http/jsonrpc_errors.d.ts.map +1 -1
- package/dist/http/jsonrpc_errors.js +26 -2
- package/dist/http/pending_effects.d.ts +71 -18
- package/dist/http/pending_effects.d.ts.map +1 -1
- package/dist/http/pending_effects.js +87 -18
- package/dist/http/proxy.d.ts +52 -5
- package/dist/http/proxy.d.ts.map +1 -1
- package/dist/http/proxy.js +92 -14
- package/dist/http/route_spec.d.ts +113 -41
- package/dist/http/route_spec.d.ts.map +1 -1
- package/dist/http/route_spec.js +130 -52
- package/dist/http/schema_helpers.d.ts +3 -2
- package/dist/http/schema_helpers.d.ts.map +1 -1
- package/dist/http/schema_helpers.js +9 -2
- package/dist/http/surface.d.ts +2 -1
- package/dist/http/surface.d.ts.map +1 -1
- package/dist/http/surface.js +1 -2
- package/dist/http/surface_query.d.ts +39 -35
- package/dist/http/surface_query.d.ts.map +1 -1
- package/dist/http/surface_query.js +79 -36
- package/dist/primitive_schemas.d.ts +39 -0
- package/dist/primitive_schemas.d.ts.map +1 -0
- package/dist/primitive_schemas.js +40 -0
- package/dist/realtime/sse_auth_guard.d.ts +5 -5
- package/dist/realtime/sse_auth_guard.js +9 -9
- package/dist/runtime/mock.d.ts +1 -1
- package/dist/runtime/mock.js +1 -1
- package/dist/server/app_backend.d.ts +14 -11
- package/dist/server/app_backend.d.ts.map +1 -1
- package/dist/server/app_backend.js +12 -8
- package/dist/server/app_server.d.ts +7 -7
- package/dist/server/app_server.d.ts.map +1 -1
- package/dist/server/app_server.js +36 -31
- package/dist/server/validate_nginx.d.ts +1 -1
- package/dist/server/validate_nginx.js +1 -1
- package/dist/testing/CLAUDE.md +73 -55
- package/dist/testing/admin_integration.d.ts +5 -6
- package/dist/testing/admin_integration.d.ts.map +1 -1
- package/dist/testing/admin_integration.js +100 -96
- package/dist/testing/adversarial_headers.js +1 -1
- package/dist/testing/app_server.d.ts +11 -14
- package/dist/testing/app_server.d.ts.map +1 -1
- package/dist/testing/app_server.js +18 -17
- package/dist/testing/assertions.d.ts.map +1 -1
- package/dist/testing/assertions.js +2 -1
- package/dist/testing/attack_surface.d.ts.map +1 -1
- package/dist/testing/attack_surface.js +15 -9
- package/dist/testing/audit_completeness.d.ts +2 -2
- package/dist/testing/audit_completeness.d.ts.map +1 -1
- package/dist/testing/audit_completeness.js +53 -39
- package/dist/testing/auth_apps.d.ts +5 -4
- package/dist/testing/auth_apps.d.ts.map +1 -1
- package/dist/testing/auth_apps.js +28 -22
- package/dist/testing/data_exposure.d.ts.map +1 -1
- package/dist/testing/data_exposure.js +5 -5
- package/dist/testing/db.d.ts +1 -1
- package/dist/testing/db.d.ts.map +1 -1
- package/dist/testing/db.js +4 -4
- package/dist/testing/db_entities.d.ts +22 -0
- package/dist/testing/db_entities.d.ts.map +1 -0
- package/dist/testing/db_entities.js +28 -0
- package/dist/testing/entities.d.ts +10 -8
- package/dist/testing/entities.d.ts.map +1 -1
- package/dist/testing/entities.js +22 -18
- package/dist/testing/integration.d.ts.map +1 -1
- package/dist/testing/integration.js +13 -14
- package/dist/testing/integration_helpers.d.ts +8 -6
- package/dist/testing/integration_helpers.d.ts.map +1 -1
- package/dist/testing/integration_helpers.js +29 -23
- package/dist/testing/middleware.d.ts +15 -11
- package/dist/testing/middleware.d.ts.map +1 -1
- package/dist/testing/middleware.js +75 -32
- package/dist/testing/rpc_attack_surface.d.ts.map +1 -1
- package/dist/testing/rpc_attack_surface.js +40 -24
- package/dist/testing/rpc_helpers.d.ts.map +1 -1
- package/dist/testing/rpc_helpers.js +3 -1
- package/dist/testing/rpc_round_trip.d.ts +1 -1
- package/dist/testing/rpc_round_trip.d.ts.map +1 -1
- package/dist/testing/rpc_round_trip.js +14 -13
- package/dist/testing/sse_round_trip.d.ts +3 -4
- package/dist/testing/sse_round_trip.d.ts.map +1 -1
- package/dist/testing/sse_round_trip.js +7 -11
- package/dist/testing/standard.d.ts +1 -1
- package/dist/testing/stubs.d.ts +25 -0
- package/dist/testing/stubs.d.ts.map +1 -1
- package/dist/testing/stubs.js +43 -2
- package/dist/testing/surface_invariants.d.ts +2 -2
- package/dist/testing/ws_round_trip.d.ts +12 -13
- package/dist/testing/ws_round_trip.d.ts.map +1 -1
- package/dist/testing/ws_round_trip.js +24 -12
- package/dist/ui/AdminAccounts.svelte +23 -20
- package/dist/ui/AdminOverview.svelte +15 -13
- package/dist/ui/AdminOverview.svelte.d.ts.map +1 -1
- package/dist/ui/{AdminPermitHistory.svelte → AdminRoleGrantHistory.svelte} +12 -12
- package/dist/ui/AdminRoleGrantHistory.svelte.d.ts +4 -0
- package/dist/ui/AdminRoleGrantHistory.svelte.d.ts.map +1 -0
- package/dist/ui/BootstrapForm.svelte +1 -1
- package/dist/ui/CLAUDE.md +65 -59
- package/dist/ui/{PermitOfferForm.svelte → RoleGrantOfferForm.svelte} +37 -22
- package/dist/ui/RoleGrantOfferForm.svelte.d.ts +20 -0
- package/dist/ui/RoleGrantOfferForm.svelte.d.ts.map +1 -0
- package/dist/ui/{PermitOfferHistory.svelte → RoleGrantOfferHistory.svelte} +12 -12
- package/dist/ui/{PermitOfferHistory.svelte.d.ts → RoleGrantOfferHistory.svelte.d.ts} +4 -4
- package/dist/ui/RoleGrantOfferHistory.svelte.d.ts.map +1 -0
- package/dist/ui/{PermitOfferInbox.svelte → RoleGrantOfferInbox.svelte} +14 -14
- package/dist/ui/{PermitOfferInbox.svelte.d.ts → RoleGrantOfferInbox.svelte.d.ts} +4 -4
- package/dist/ui/RoleGrantOfferInbox.svelte.d.ts.map +1 -0
- package/dist/ui/SignupForm.svelte +1 -1
- package/dist/ui/SurfaceExplorer.svelte +35 -15
- package/dist/ui/SurfaceExplorer.svelte.d.ts.map +1 -1
- package/dist/ui/account_sessions_state.svelte.d.ts +2 -3
- package/dist/ui/account_sessions_state.svelte.d.ts.map +1 -1
- package/dist/ui/account_sessions_state.svelte.js +2 -3
- package/dist/ui/admin_accounts_state.svelte.d.ts +25 -18
- package/dist/ui/admin_accounts_state.svelte.d.ts.map +1 -1
- package/dist/ui/admin_accounts_state.svelte.js +28 -17
- package/dist/ui/admin_rpc_adapters.d.ts +20 -20
- package/dist/ui/admin_rpc_adapters.d.ts.map +1 -1
- package/dist/ui/admin_rpc_adapters.js +17 -17
- package/dist/ui/admin_sessions_state.svelte.d.ts +2 -2
- package/dist/ui/admin_sessions_state.svelte.js +2 -2
- package/dist/ui/audit_log_state.svelte.d.ts +7 -7
- package/dist/ui/audit_log_state.svelte.d.ts.map +1 -1
- package/dist/ui/audit_log_state.svelte.js +6 -6
- package/dist/ui/auth_state.svelte.d.ts +3 -3
- package/dist/ui/auth_state.svelte.d.ts.map +1 -1
- package/dist/ui/auth_state.svelte.js +6 -6
- package/dist/ui/format_scope.d.ts +2 -2
- package/dist/ui/format_scope.js +2 -2
- package/dist/ui/{permit_offers_state.svelte.d.ts → role_grant_offers_state.svelte.d.ts} +39 -31
- package/dist/ui/role_grant_offers_state.svelte.d.ts.map +1 -0
- package/dist/ui/{permit_offers_state.svelte.js → role_grant_offers_state.svelte.js} +25 -19
- package/dist/ui/ui_format.js +2 -2
- package/package.json +3 -3
- package/dist/auth/permit_offer_action_specs.d.ts.map +0 -1
- package/dist/auth/permit_offer_action_specs.js +0 -227
- package/dist/auth/permit_offer_actions.d.ts +0 -110
- package/dist/auth/permit_offer_actions.d.ts.map +0 -1
- package/dist/auth/permit_offer_actions.js +0 -452
- package/dist/auth/permit_offer_notifications.d.ts.map +0 -1
- package/dist/auth/permit_offer_notifications.js +0 -182
- package/dist/auth/permit_offer_queries.d.ts +0 -183
- package/dist/auth/permit_offer_queries.d.ts.map +0 -1
- package/dist/auth/permit_offer_queries.js +0 -408
- package/dist/auth/permit_offer_schema.d.ts +0 -103
- package/dist/auth/permit_offer_schema.d.ts.map +0 -1
- package/dist/auth/permit_queries.d.ts +0 -210
- package/dist/auth/permit_queries.d.ts.map +0 -1
- package/dist/auth/permit_queries.js +0 -294
- package/dist/auth/require_keeper.d.ts +0 -20
- package/dist/auth/require_keeper.d.ts.map +0 -1
- package/dist/auth/require_keeper.js +0 -35
- package/dist/auth/route_guards.d.ts +0 -21
- package/dist/auth/route_guards.d.ts.map +0 -1
- package/dist/auth/route_guards.js +0 -32
- package/dist/auth/session_lifecycle.d.ts +0 -37
- package/dist/auth/session_lifecycle.d.ts.map +0 -1
- package/dist/auth/session_lifecycle.js +0 -29
- package/dist/ui/AdminPermitHistory.svelte.d.ts +0 -4
- package/dist/ui/AdminPermitHistory.svelte.d.ts.map +0 -1
- package/dist/ui/PermitOfferForm.svelte.d.ts +0 -14
- package/dist/ui/PermitOfferForm.svelte.d.ts.map +0 -1
- package/dist/ui/PermitOfferHistory.svelte.d.ts.map +0 -1
- package/dist/ui/PermitOfferInbox.svelte.d.ts.map +0 -1
- package/dist/ui/permit_offers_state.svelte.d.ts.map +0 -1
|
@@ -3,14 +3,14 @@ import './assert_dev_env.js';
|
|
|
3
3
|
* Standard admin integration test suite for fuz_app admin routes.
|
|
4
4
|
*
|
|
5
5
|
* `describe_standard_admin_integration_tests` creates a composable test suite
|
|
6
|
-
* that exercises admin account listing,
|
|
7
|
-
* surface — see `
|
|
6
|
+
* that exercises admin account listing, role_grant grant/revoke (via the RPC
|
|
7
|
+
* surface — see `role_grant_offer_create` / `role_grant_revoke`), session/token
|
|
8
8
|
* management, and audit log routes against a real PGlite database.
|
|
9
9
|
*
|
|
10
10
|
* Consumers call it with their route factory, session config, role schema,
|
|
11
11
|
* and RPC endpoint specs — all admin route tests come for free.
|
|
12
12
|
*
|
|
13
|
-
* Scope: admin *semantics* — cross-admin isolation,
|
|
13
|
+
* Scope: admin *semantics* — cross-admin isolation, role_grant grant/revoke
|
|
14
14
|
* flow, session/token revoke-all, audit writes. Output-schema conformance
|
|
15
15
|
* for admin methods is **not** the concern of this suite; it lives in:
|
|
16
16
|
*
|
|
@@ -27,6 +27,7 @@ import './assert_dev_env.js';
|
|
|
27
27
|
*/
|
|
28
28
|
import { describe, test, assert, afterAll } from 'vitest';
|
|
29
29
|
import { ROLE_KEEPER, ROLE_ADMIN } from '../auth/role_schema.js';
|
|
30
|
+
import { GRANT_PATH_ADMIN } from '../auth/grant_path_schema.js';
|
|
30
31
|
import { AUTH_MIGRATION_NS } from '../auth/migrations.js';
|
|
31
32
|
import { create_test_app } from './app_server.js';
|
|
32
33
|
import { create_pglite_factory, create_describe_db, AUTH_INTEGRATION_TRUNCATE_TABLES, } from './db.js';
|
|
@@ -34,18 +35,20 @@ import { find_auth_route } from './integration_helpers.js';
|
|
|
34
35
|
import { run_migrations } from '../db/migrate.js';
|
|
35
36
|
import { ErrorCoverageCollector, assert_error_coverage, DEFAULT_INTEGRATION_ERROR_COVERAGE, } from './error_coverage.js';
|
|
36
37
|
import { rpc_call_for_spec, require_rpc_endpoint_path, resolve_rpc_endpoints_for_setup, } from './rpc_helpers.js';
|
|
37
|
-
import {
|
|
38
|
-
import { admin_account_list_action_spec, admin_session_list_action_spec, admin_session_revoke_all_action_spec, admin_token_revoke_all_action_spec, audit_log_list_action_spec,
|
|
38
|
+
import { role_grant_offer_create_action_spec, role_grant_revoke_action_spec, } from '../auth/role_grant_offer_action_specs.js';
|
|
39
|
+
import { admin_account_list_action_spec, admin_session_list_action_spec, admin_session_revoke_all_action_spec, admin_token_revoke_all_action_spec, audit_log_list_action_spec, audit_log_role_grant_history_action_spec, } from '../auth/admin_action_specs.js';
|
|
39
40
|
import { account_token_create_action_spec, account_verify_action_spec, } from '../auth/account_action_specs.js';
|
|
40
|
-
import {
|
|
41
|
-
import {
|
|
42
|
-
import { query_accept_offer } from '../auth/permit_offer_queries.js';
|
|
41
|
+
import { query_create_role_grant } from '../auth/role_grant_queries.js';
|
|
42
|
+
import { query_accept_offer } from '../auth/role_grant_offer_queries.js';
|
|
43
43
|
/**
|
|
44
|
-
* Pick a
|
|
44
|
+
* Pick a role for admin-grant testing, preferring a non-admin app-defined
|
|
45
|
+
* role whose `RoleSpec.grant_paths` includes `'admin'` (the
|
|
46
|
+
* `GRANT_PATH_ADMIN` constant). Falls back to `ROLE_ADMIN` when no
|
|
47
|
+
* app-defined admin-grant-path role is registered.
|
|
45
48
|
*/
|
|
46
|
-
const pick_grantable_role = (
|
|
47
|
-
for (const [name,
|
|
48
|
-
if (
|
|
49
|
+
const pick_grantable_role = (role_specs) => {
|
|
50
|
+
for (const [name, spec] of role_specs) {
|
|
51
|
+
if (spec.grant_paths?.includes(GRANT_PATH_ADMIN) && name !== ROLE_ADMIN)
|
|
49
52
|
return name;
|
|
50
53
|
}
|
|
51
54
|
return ROLE_ADMIN; // fallback
|
|
@@ -66,17 +69,16 @@ const build_admin_test_app_options = (options, db, roles) => ({
|
|
|
66
69
|
/**
|
|
67
70
|
* Standard admin integration test suite for fuz_app admin routes.
|
|
68
71
|
*
|
|
69
|
-
* Exercises account listing,
|
|
72
|
+
* Exercises account listing, role_grant grant/revoke (via RPC), session
|
|
70
73
|
* management, token management, audit log reads, admin-to-admin
|
|
71
74
|
* isolation, and 401/403 error-coverage on the admin REST surface.
|
|
72
75
|
* Output-schema conformance is not in scope — see the module docstring
|
|
73
76
|
* for the suites that cover it.
|
|
74
77
|
*
|
|
75
78
|
* @throws Error at setup time when `options.rpc_endpoints` is empty — admin
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
* than `method not found` mid-suite.
|
|
79
|
+
* role_grant grant/revoke, session/token revoke-all, and audit-log reads
|
|
80
|
+
* are RPC-only. Hard-fails via `require_rpc_endpoint_path` so consumers
|
|
81
|
+
* see a clear setup error rather than `method not found` mid-suite.
|
|
80
82
|
*/
|
|
81
83
|
export const describe_standard_admin_integration_tests = (options) => {
|
|
82
84
|
// Hard-fail early so consumers see a clear setup error instead of a
|
|
@@ -92,30 +94,30 @@ export const describe_standard_admin_integration_tests = (options) => {
|
|
|
92
94
|
const describe_db = create_describe_db(factories, AUTH_INTEGRATION_TRUNCATE_TABLES);
|
|
93
95
|
describe_db('standard_admin_integration', (get_db) => {
|
|
94
96
|
const { cookie_name } = options.session_options;
|
|
95
|
-
const {
|
|
96
|
-
const grantable_role = pick_grantable_role(
|
|
97
|
+
const { role_specs } = options.roles;
|
|
98
|
+
const grantable_role = pick_grantable_role(role_specs);
|
|
97
99
|
// Error coverage tracking across test groups
|
|
98
100
|
const error_collector = new ErrorCoverageCollector();
|
|
99
101
|
let captured_route_specs = null;
|
|
100
102
|
afterAll(() => {
|
|
101
103
|
if (captured_route_specs) {
|
|
102
|
-
// Scope coverage to admin auth-related routes.
|
|
103
|
-
//
|
|
104
|
-
//
|
|
105
|
-
//
|
|
106
|
-
//
|
|
107
|
-
// path itself (admin methods live behind spec-level role auth).
|
|
104
|
+
// Scope coverage to admin auth-related routes. Account listing,
|
|
105
|
+
// session/token revoke-all, audit-log reads, and invite CRUD all
|
|
106
|
+
// live on the RPC surface; the only admin REST route remaining
|
|
107
|
+
// is the optional `GET /audit/stream` SSE (admin RPC methods
|
|
108
|
+
// live behind spec-level role auth on the shared endpoint path).
|
|
108
109
|
// The `/audit/stream` suffix tracks the hardcoded path in
|
|
109
110
|
// `auth/audit_log_routes.ts` — if consumers ever need to mount
|
|
110
111
|
// the audit SSE at a different suffix, promote this to an
|
|
111
112
|
// `audit_log_path_suffix` option on
|
|
112
113
|
// `StandardAdminIntegrationTestOptions`.
|
|
113
|
-
const admin_routes = captured_route_specs.filter((s) => s.path.endsWith('/audit/stream') && s.auth.
|
|
114
|
+
const admin_routes = captured_route_specs.filter((s) => s.path.endsWith('/audit/stream') && (s.auth.roles?.includes('admin') ?? false));
|
|
114
115
|
// Adaptive threshold: when the scoped admin REST surface is
|
|
115
|
-
// effectively empty (0–1 routes
|
|
116
|
-
// the 20% baseline is meaningless — a single
|
|
117
|
-
// can't be exercised against an error schema
|
|
118
|
-
// to 0.0%. Log an informational skip instead
|
|
116
|
+
// effectively empty (0–1 routes — typical for the RPC-first
|
|
117
|
+
// admin surface), the 20% baseline is meaningless — a single
|
|
118
|
+
// SSE route that can't be exercised against an error schema
|
|
119
|
+
// drops the ratio to 0.0%. Log an informational skip instead
|
|
120
|
+
// of asserting.
|
|
119
121
|
// The admin RPC surface is covered by
|
|
120
122
|
// `describe_rpc_round_trip_tests`, not this collector.
|
|
121
123
|
if (admin_routes.length <= 1) {
|
|
@@ -138,7 +140,7 @@ export const describe_standard_admin_integration_tests = (options) => {
|
|
|
138
140
|
});
|
|
139
141
|
/**
|
|
140
142
|
* Drive the full consent flow (admin offer → recipient accept) and
|
|
141
|
-
* return the materialized
|
|
143
|
+
* return the materialized role_grant id. Accept is a direct transactional
|
|
142
144
|
* `query_accept_offer` call because the suite focuses on the admin
|
|
143
145
|
* side; exercising the recipient's UI-wired accept path is covered by
|
|
144
146
|
* `describe_rpc_round_trip_tests` + fuz_app's own action suite.
|
|
@@ -147,14 +149,19 @@ export const describe_standard_admin_integration_tests = (options) => {
|
|
|
147
149
|
const res = await rpc_call_for_spec({
|
|
148
150
|
app: args.app,
|
|
149
151
|
path: rpc_path,
|
|
150
|
-
spec:
|
|
152
|
+
spec: role_grant_offer_create_action_spec,
|
|
151
153
|
params: { to_account_id: args.to_account_id, role: args.role },
|
|
152
154
|
headers: args.admin_headers,
|
|
153
155
|
});
|
|
154
|
-
assert.ok(res.ok, `
|
|
156
|
+
assert.ok(res.ok, `role_grant_offer_create failed: ${res.ok ? '' : JSON.stringify(res.error)}`);
|
|
155
157
|
const { offer } = res.result;
|
|
156
|
-
const accept_result = await get_db().transaction(async (tx) => query_accept_offer({ db: tx }, {
|
|
157
|
-
|
|
158
|
+
const accept_result = await get_db().transaction(async (tx) => query_accept_offer({ db: tx }, {
|
|
159
|
+
offer_id: offer.id,
|
|
160
|
+
to_account_id: args.to_account_id,
|
|
161
|
+
actor_id: args.to_actor_id,
|
|
162
|
+
ip: null,
|
|
163
|
+
}));
|
|
164
|
+
return { offer_id: offer.id, role_grant_id: accept_result.role_grant.id };
|
|
158
165
|
};
|
|
159
166
|
// --- 1. Admin account listing (RPC) ---
|
|
160
167
|
describe('admin account listing', () => {
|
|
@@ -165,7 +172,7 @@ export const describe_standard_admin_integration_tests = (options) => {
|
|
|
165
172
|
app: test_app.app,
|
|
166
173
|
path: rpc_path,
|
|
167
174
|
spec: admin_account_list_action_spec,
|
|
168
|
-
params:
|
|
175
|
+
params: {},
|
|
169
176
|
headers: test_app.create_session_headers(),
|
|
170
177
|
});
|
|
171
178
|
assert.ok(res.ok, `admin_account_list failed: ${res.ok ? '' : JSON.stringify(res.error)}`);
|
|
@@ -183,19 +190,19 @@ export const describe_standard_admin_integration_tests = (options) => {
|
|
|
183
190
|
app: test_app.app,
|
|
184
191
|
path: rpc_path,
|
|
185
192
|
spec: admin_account_list_action_spec,
|
|
186
|
-
params:
|
|
193
|
+
params: {},
|
|
187
194
|
headers: test_app.create_session_headers(),
|
|
188
195
|
});
|
|
189
196
|
assert.ok(!res.ok, 'Expected admin_account_list to fail for non-admin');
|
|
190
197
|
assert.strictEqual(res.status, 403);
|
|
191
198
|
});
|
|
192
199
|
});
|
|
193
|
-
// --- 2.
|
|
194
|
-
//
|
|
195
|
-
// `
|
|
200
|
+
// --- 2. Role grant create/revoke lifecycle ---
|
|
201
|
+
// Role grant create/revoke are RPC-only (see `role_grant_offer_create` /
|
|
202
|
+
// `role_grant_revoke`). End-to-end coverage lives in
|
|
196
203
|
// `describe_rpc_round_trip_tests` + fuz_app's own
|
|
197
|
-
// `
|
|
198
|
-
// `
|
|
204
|
+
// `role_grant_offer_actions.db.test.ts` /
|
|
205
|
+
// `role_grant_offer_actions.notifications.revoke.db.test.ts`. The
|
|
199
206
|
// audit/isolation groups below exercise them as preconditions for
|
|
200
207
|
// cross-cutting checks (event emission, admin-to-admin isolation).
|
|
201
208
|
// --- 3. Admin session management ---
|
|
@@ -207,7 +214,7 @@ export const describe_standard_admin_integration_tests = (options) => {
|
|
|
207
214
|
app: test_app.app,
|
|
208
215
|
path: rpc_path,
|
|
209
216
|
spec: admin_session_list_action_spec,
|
|
210
|
-
params:
|
|
217
|
+
params: {},
|
|
211
218
|
headers: test_app.create_session_headers(),
|
|
212
219
|
});
|
|
213
220
|
assert.ok(res.ok, `admin_session_list failed: ${res.ok ? '' : JSON.stringify(res.error)}`);
|
|
@@ -325,61 +332,60 @@ export const describe_standard_admin_integration_tests = (options) => {
|
|
|
325
332
|
});
|
|
326
333
|
test('audit log supports event_type filter', async () => {
|
|
327
334
|
const test_app = await create_test_app(build_admin_test_app_options(options, get_db()));
|
|
328
|
-
// Admin offer emits `
|
|
329
|
-
// `
|
|
335
|
+
// Admin offer emits `role_grant_offer_create`. The downstream
|
|
336
|
+
// `role_grant_create` only fires on accept — out of scope for this test.
|
|
330
337
|
const user_two = await test_app.create_account({ username: 'user_two' });
|
|
331
338
|
const offer_res = await rpc_call_for_spec({
|
|
332
339
|
app: test_app.app,
|
|
333
340
|
path: rpc_path,
|
|
334
|
-
spec:
|
|
341
|
+
spec: role_grant_offer_create_action_spec,
|
|
335
342
|
params: { to_account_id: user_two.account.id, role: grantable_role },
|
|
336
343
|
headers: test_app.create_session_headers(),
|
|
337
344
|
});
|
|
338
|
-
assert.ok(offer_res.ok, '
|
|
345
|
+
assert.ok(offer_res.ok, 'role_grant_offer_create should succeed');
|
|
339
346
|
const res = await rpc_call_for_spec({
|
|
340
347
|
app: test_app.app,
|
|
341
348
|
path: rpc_path,
|
|
342
349
|
spec: audit_log_list_action_spec,
|
|
343
|
-
params: { event_type: '
|
|
350
|
+
params: { event_type: 'role_grant_offer_create' },
|
|
344
351
|
headers: test_app.create_session_headers(),
|
|
345
352
|
});
|
|
346
353
|
assert.ok(res.ok, `audit_log_list failed: ${res.ok ? '' : JSON.stringify(res.error)}`);
|
|
347
|
-
assert.ok(res.result.events.length >= 1, 'Expected at least 1
|
|
354
|
+
assert.ok(res.result.events.length >= 1, 'Expected at least 1 role_grant_offer_create event');
|
|
348
355
|
for (const event of res.result.events) {
|
|
349
|
-
assert.strictEqual(event.event_type, '
|
|
356
|
+
assert.strictEqual(event.event_type, 'role_grant_offer_create');
|
|
350
357
|
}
|
|
351
358
|
});
|
|
352
|
-
test('admin can view
|
|
359
|
+
test('admin can view role_grant history', async () => {
|
|
353
360
|
const test_app = await create_test_app(build_admin_test_app_options(options, get_db()));
|
|
354
|
-
// Drive the full consent flow so `
|
|
355
|
-
// — `
|
|
361
|
+
// Drive the full consent flow so `role_grant_create` lands in the audit log
|
|
362
|
+
// — `query_audit_log_list_role_grant_history` filters to (role_grant_create, role_grant_revoke).
|
|
356
363
|
const user_two = await test_app.create_account({ username: 'user_two' });
|
|
357
364
|
await offer_and_accept({
|
|
358
365
|
app: test_app.app,
|
|
359
366
|
admin_headers: test_app.create_session_headers(),
|
|
360
367
|
to_account_id: user_two.account.id,
|
|
368
|
+
to_actor_id: user_two.actor.id,
|
|
361
369
|
role: grantable_role,
|
|
362
370
|
});
|
|
363
371
|
const res = await rpc_call_for_spec({
|
|
364
372
|
app: test_app.app,
|
|
365
373
|
path: rpc_path,
|
|
366
|
-
spec:
|
|
374
|
+
spec: audit_log_role_grant_history_action_spec,
|
|
367
375
|
params: {},
|
|
368
376
|
headers: test_app.create_session_headers(),
|
|
369
377
|
});
|
|
370
|
-
assert.ok(res.ok, `
|
|
371
|
-
assert.ok(res.result.events.length >= 1, 'Expected at least 1
|
|
378
|
+
assert.ok(res.ok, `audit_log_role_grant_history failed: ${res.ok ? '' : JSON.stringify(res.error)}`);
|
|
379
|
+
assert.ok(res.result.events.length >= 1, 'Expected at least 1 role_grant history event');
|
|
372
380
|
});
|
|
373
381
|
});
|
|
374
382
|
// --- 6. Admin audit trail ---
|
|
375
383
|
describe('admin audit trail', () => {
|
|
376
|
-
test('
|
|
384
|
+
test('role_grant revoke creates audit event', async () => {
|
|
377
385
|
const test_app = await create_test_app(build_admin_test_app_options(options, get_db()));
|
|
378
386
|
const user_two = await test_app.create_account({ username: 'user_two' });
|
|
379
|
-
const
|
|
380
|
-
|
|
381
|
-
const permit = await query_grant_permit({ db: get_db() }, {
|
|
382
|
-
actor_id: target_actor.id,
|
|
387
|
+
const role_grant = await query_create_role_grant({ db: get_db() }, {
|
|
388
|
+
actor_id: user_two.actor.id,
|
|
383
389
|
role: grantable_role,
|
|
384
390
|
granted_by: test_app.backend.actor.id,
|
|
385
391
|
});
|
|
@@ -387,22 +393,22 @@ export const describe_standard_admin_integration_tests = (options) => {
|
|
|
387
393
|
const revoke_res = await rpc_call_for_spec({
|
|
388
394
|
app: test_app.app,
|
|
389
395
|
path: rpc_path,
|
|
390
|
-
spec:
|
|
391
|
-
params: { actor_id:
|
|
396
|
+
spec: role_grant_revoke_action_spec,
|
|
397
|
+
params: { actor_id: user_two.actor.id, role_grant_id: role_grant.id },
|
|
392
398
|
headers: test_app.create_session_headers(),
|
|
393
399
|
});
|
|
394
|
-
assert.ok(revoke_res.ok, `
|
|
395
|
-
// Check audit log for
|
|
400
|
+
assert.ok(revoke_res.ok, `role_grant_revoke failed: ${revoke_res.ok ? '' : JSON.stringify(revoke_res.error)}`);
|
|
401
|
+
// Check audit log for role_grant_revoke event
|
|
396
402
|
const audit_res = await rpc_call_for_spec({
|
|
397
403
|
app: test_app.app,
|
|
398
404
|
path: rpc_path,
|
|
399
405
|
spec: audit_log_list_action_spec,
|
|
400
|
-
params: { event_type: '
|
|
406
|
+
params: { event_type: 'role_grant_revoke' },
|
|
401
407
|
headers: test_app.create_session_headers(),
|
|
402
408
|
});
|
|
403
409
|
assert.ok(audit_res.ok, `audit_log_list failed: ${audit_res.ok ? '' : JSON.stringify(audit_res.error)}`);
|
|
404
|
-
assert.ok(audit_res.result.events.length >= 1, 'Expected
|
|
405
|
-
assert.strictEqual(audit_res.result.events[0].event_type, '
|
|
410
|
+
assert.ok(audit_res.result.events.length >= 1, 'Expected role_grant_revoke audit event');
|
|
411
|
+
assert.strictEqual(audit_res.result.events[0].event_type, 'role_grant_revoke');
|
|
406
412
|
});
|
|
407
413
|
test('admin session revoke-all creates audit event', async () => {
|
|
408
414
|
const test_app = await create_test_app(build_admin_test_app_options(options, get_db()));
|
|
@@ -553,26 +559,25 @@ export const describe_standard_admin_integration_tests = (options) => {
|
|
|
553
559
|
},
|
|
554
560
|
});
|
|
555
561
|
}
|
|
556
|
-
// 3. offer
|
|
557
|
-
// consentful flow: offer + accept so both `
|
|
558
|
-
// `
|
|
559
|
-
const {
|
|
562
|
+
// 3. offer role_grant (admin offers grantable_role to user_two) — full
|
|
563
|
+
// consentful flow: offer + accept so both `role_grant_offer_create` and
|
|
564
|
+
// `role_grant_create` audit events land.
|
|
565
|
+
const { role_grant_id } = await offer_and_accept({
|
|
560
566
|
app: test_app.app,
|
|
561
567
|
admin_headers: test_app.create_session_headers(),
|
|
562
568
|
to_account_id: user_two.account.id,
|
|
569
|
+
to_actor_id: user_two.actor.id,
|
|
563
570
|
role: grantable_role,
|
|
564
571
|
});
|
|
565
|
-
// 4. revoke
|
|
566
|
-
const target_actor = await query_actor_by_account({ db: get_db() }, user_two.account.id);
|
|
567
|
-
assert.ok(target_actor);
|
|
572
|
+
// 4. revoke role_grant (RPC)
|
|
568
573
|
const revoke_res = await rpc_call_for_spec({
|
|
569
574
|
app: test_app.app,
|
|
570
575
|
path: rpc_path,
|
|
571
|
-
spec:
|
|
572
|
-
params: { actor_id:
|
|
576
|
+
spec: role_grant_revoke_action_spec,
|
|
577
|
+
params: { actor_id: user_two.actor.id, role_grant_id },
|
|
573
578
|
headers: test_app.create_session_headers(),
|
|
574
579
|
});
|
|
575
|
-
assert.ok(revoke_res.ok, `
|
|
580
|
+
assert.ok(revoke_res.ok, `role_grant_revoke failed: ${revoke_res.ok ? '' : JSON.stringify(revoke_res.error)}`);
|
|
576
581
|
// 5. create token (RPC)
|
|
577
582
|
const token_res = await rpc_call_for_spec({
|
|
578
583
|
app: test_app.app,
|
|
@@ -626,28 +631,28 @@ export const describe_standard_admin_integration_tests = (options) => {
|
|
|
626
631
|
assert.ok(audit_res.ok, `audit_log_list failed: ${audit_res.ok ? '' : JSON.stringify(audit_res.error)}`);
|
|
627
632
|
const events = audit_res.result.events;
|
|
628
633
|
// check that each operation produced at least one event.
|
|
629
|
-
// `
|
|
634
|
+
// `role_grant_offer_create` fires on the admin RPC; `role_grant_create`
|
|
630
635
|
// fires when the recipient accepts (driven by offer_and_accept).
|
|
631
636
|
const expected_types = [
|
|
632
637
|
'login',
|
|
633
638
|
'logout',
|
|
634
|
-
'
|
|
635
|
-
'
|
|
636
|
-
'
|
|
637
|
-
'
|
|
639
|
+
'role_grant_offer_create',
|
|
640
|
+
'role_grant_offer_accept',
|
|
641
|
+
'role_grant_create',
|
|
642
|
+
'role_grant_revoke',
|
|
638
643
|
'token_create',
|
|
639
644
|
'password_change',
|
|
640
645
|
];
|
|
641
646
|
for (const event_type of expected_types) {
|
|
642
647
|
const found = events.filter((e) => e.event_type === event_type);
|
|
643
648
|
assert.ok(found.length >= 1, `Expected at least 1 '${event_type}' audit event, found ${found.length}. ` +
|
|
644
|
-
`This may indicate
|
|
649
|
+
`This may indicate a deps.audit.emit call was removed from a handler.`);
|
|
645
650
|
}
|
|
646
651
|
});
|
|
647
652
|
});
|
|
648
653
|
// --- 8. Admin-to-admin isolation ---
|
|
649
654
|
describe('admin-to-admin isolation', () => {
|
|
650
|
-
test('admin B revoking own
|
|
655
|
+
test('admin B revoking own role_grant via RPC succeeds', async () => {
|
|
651
656
|
const test_app = await create_test_app(build_admin_test_app_options(options, get_db()));
|
|
652
657
|
captured_route_specs ??= test_app.route_specs;
|
|
653
658
|
// Bootstrap user is admin A. Create admin B.
|
|
@@ -655,22 +660,22 @@ export const describe_standard_admin_integration_tests = (options) => {
|
|
|
655
660
|
username: 'admin_b_iso',
|
|
656
661
|
roles: ['admin'],
|
|
657
662
|
});
|
|
658
|
-
// Seed an active
|
|
663
|
+
// Seed an active role_grant directly — the revoke IDOR check is the
|
|
659
664
|
// subject of this test, not the grant→accept cycle.
|
|
660
|
-
const
|
|
665
|
+
const role_grant = await query_create_role_grant({ db: get_db() }, {
|
|
661
666
|
actor_id: admin_b.actor.id,
|
|
662
667
|
role: grantable_role,
|
|
663
668
|
granted_by: test_app.backend.actor.id,
|
|
664
669
|
});
|
|
665
|
-
// Admin B revokes their own
|
|
670
|
+
// Admin B revokes their own role_grant via RPC — should succeed
|
|
666
671
|
const revoke_res = await rpc_call_for_spec({
|
|
667
672
|
app: test_app.app,
|
|
668
673
|
path: rpc_path,
|
|
669
|
-
spec:
|
|
670
|
-
params: { actor_id: admin_b.actor.id,
|
|
674
|
+
spec: role_grant_revoke_action_spec,
|
|
675
|
+
params: { actor_id: admin_b.actor.id, role_grant_id: role_grant.id },
|
|
671
676
|
headers: create_headers(admin_b.session_cookie),
|
|
672
677
|
});
|
|
673
|
-
assert.ok(revoke_res.ok, `
|
|
678
|
+
assert.ok(revoke_res.ok, `role_grant_revoke failed: ${revoke_res.ok ? '' : JSON.stringify(revoke_res.error)}`);
|
|
674
679
|
assert.strictEqual(revoke_res.result.revoked, true);
|
|
675
680
|
});
|
|
676
681
|
test('admin revoke-all sessions for another admin works', async () => {
|
|
@@ -727,7 +732,7 @@ export const describe_standard_admin_integration_tests = (options) => {
|
|
|
727
732
|
app: test_app.app,
|
|
728
733
|
path: rpc_path,
|
|
729
734
|
spec: admin_account_list_action_spec,
|
|
730
|
-
params:
|
|
735
|
+
params: {},
|
|
731
736
|
headers: create_headers(regular_user.session_cookie),
|
|
732
737
|
});
|
|
733
738
|
assert.ok(!res.ok, 'Expected admin_account_list to fail for non-admin');
|
|
@@ -739,14 +744,13 @@ export const describe_standard_admin_integration_tests = (options) => {
|
|
|
739
744
|
test('exercises 401/403 on admin routes for error coverage', async () => {
|
|
740
745
|
const test_app = await create_test_app(build_admin_test_app_options(options, get_db()));
|
|
741
746
|
captured_route_specs ??= test_app.route_specs;
|
|
742
|
-
//
|
|
743
|
-
//
|
|
744
|
-
// auth. The path-prefix carve is still the right scope here
|
|
747
|
+
// `/api/admin` is nearly empty — admin reads and mutations live
|
|
748
|
+
// on the RPC endpoint behind spec-level role auth. The path-prefix carve is still the right scope here
|
|
745
749
|
// because error coverage is tracked against REST `RouteSpec`s,
|
|
746
750
|
// not RPC method specs (`describe_rpc_round_trip_tests` covers
|
|
747
751
|
// the admin RPC surface separately).
|
|
748
752
|
const prefix = options.admin_prefix ?? '/api/admin';
|
|
749
|
-
const admin_routes = test_app.route_specs.filter((s) => s.path.startsWith(prefix) && s.auth.
|
|
753
|
+
const admin_routes = test_app.route_specs.filter((s) => s.path.startsWith(prefix) && (s.auth.roles?.includes('admin') ?? false));
|
|
750
754
|
// Hit admin routes without auth to exercise 401 error schemas.
|
|
751
755
|
for (const route of admin_routes) {
|
|
752
756
|
const res = await test_app.app.request(route.path, {
|
|
@@ -112,7 +112,7 @@ export const describe_standard_adversarial_headers = (suite_name, options, allow
|
|
|
112
112
|
}
|
|
113
113
|
if (tc.expected_status === 200) {
|
|
114
114
|
assert.strictEqual(body.ok, true, 'expected ok to be true for 200 response');
|
|
115
|
-
assert.strictEqual(body.
|
|
115
|
+
assert.strictEqual(body.account_id, null, 'expected account_id to be null (no auth)');
|
|
116
116
|
}
|
|
117
117
|
if (tc.validate_expectation === 'not_called') {
|
|
118
118
|
assert.strictEqual(mock_validate.mock.calls.length, 0, 'validate should not have been called — middleware should short-circuit');
|
|
@@ -53,7 +53,7 @@ export interface BootstrapTestAccountOptions {
|
|
|
53
53
|
* `create_test_app_server` and `TestApp.create_account`.
|
|
54
54
|
*
|
|
55
55
|
* @mutates the underlying `options.db` — inserts rows into `account`, `actor`,
|
|
56
|
-
* `
|
|
56
|
+
* `role_grant` (one per role), `api_token`, and `auth_session`.
|
|
57
57
|
*/
|
|
58
58
|
export declare const bootstrap_test_account: (options: BootstrapTestAccountOptions) => Promise<{
|
|
59
59
|
account: {
|
|
@@ -107,17 +107,16 @@ export interface TestAppServerOptions {
|
|
|
107
107
|
/** Roles to grant. Default: `[ROLE_KEEPER]`. */
|
|
108
108
|
roles?: Array<string>;
|
|
109
109
|
/**
|
|
110
|
-
* Backend audit event callback —
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
* Use to wire consumer SSE auth
|
|
114
|
-
* Default: no-op.
|
|
110
|
+
* Backend audit event callback — threaded into `create_audit_emitter` so
|
|
111
|
+
* it becomes the first listener on `backend.deps.audit.on_event_chain`.
|
|
112
|
+
* When `audit_log_sse: true` is passed to `create_app_server`, the SSE
|
|
113
|
+
* listener is appended after this one. Use to wire consumer SSE auth
|
|
114
|
+
* guards in tests. Default: no-op.
|
|
115
115
|
*/
|
|
116
116
|
on_audit_event?: (event: AuditLogEvent) => void;
|
|
117
117
|
/**
|
|
118
|
-
* Optional audit log config —
|
|
119
|
-
*
|
|
120
|
-
* spread of `backend.deps` (SSE branch) and the no-SSE alias branch alike.
|
|
118
|
+
* Optional audit log config — threaded into `create_audit_emitter` and
|
|
119
|
+
* captured inside `backend.deps.audit`'s closure.
|
|
121
120
|
*
|
|
122
121
|
* Use when the consumer registers extra event types via
|
|
123
122
|
* `create_audit_log_config({extra_events})` — without this, emits for
|
|
@@ -132,7 +131,7 @@ export interface TestAppServerOptions {
|
|
|
132
131
|
* Sets up:
|
|
133
132
|
* - Auth tables (via cached PGlite factory, or reuses existing `db`)
|
|
134
133
|
* - A keeper account with hashed password
|
|
135
|
-
* - Role
|
|
134
|
+
* - Role role_grants for each role in `options.roles`
|
|
136
135
|
* - An API token for Bearer auth
|
|
137
136
|
* - A session with a signed cookie value
|
|
138
137
|
*
|
|
@@ -143,10 +142,8 @@ export interface TestAppServerOptions {
|
|
|
143
142
|
* @returns a `TestAppServer` ready for HTTP testing
|
|
144
143
|
* @mutates the underlying database — when `db` is supplied, resets singleton
|
|
145
144
|
* state (`bootstrap_lock.bootstrapped`, `app_settings.open_signup`) before
|
|
146
|
-
* bootstrapping; in either branch inserts an account, actor, role
|
|
147
|
-
* API token, and session row.
|
|
148
|
-
* sets `backend.deps.audit_log_config` so `create_app_server`'s shallow
|
|
149
|
-
* spread picks it up.
|
|
145
|
+
* bootstrapping; in either branch inserts an account, actor, role role_grants,
|
|
146
|
+
* API token, and session row.
|
|
150
147
|
*/
|
|
151
148
|
export declare const create_test_app_server: (options: TestAppServerOptions) => Promise<TestAppServer>;
|
|
152
149
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app_server.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/app_server.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAE7B;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,MAAM,CAAC;AAG/B,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,wBAAwB,CAAC;AAGjD,OAAO,EAA2B,KAAK,OAAO,EAAC,MAAM,oBAAoB,CAAC;AAE1E,OAAO,KAAK,EAAC,EAAE,EAAE,MAAM,EAAC,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,qBAAqB,CAAC;AAU1D,OAAO,EAA8B,KAAK,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAG3F,OAAO,KAAK,EAAC,cAAc,EAAE,aAAa,EAAC,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"app_server.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/app_server.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAE7B;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,MAAM,CAAC;AAG/B,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,wBAAwB,CAAC;AAGjD,OAAO,EAA2B,KAAK,OAAO,EAAC,MAAM,oBAAoB,CAAC;AAE1E,OAAO,KAAK,EAAC,EAAE,EAAE,MAAM,EAAC,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,qBAAqB,CAAC;AAU1D,OAAO,EAA8B,KAAK,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAG3F,OAAO,KAAK,EAAC,cAAc,EAAE,aAAa,EAAC,MAAM,6BAA6B,CAAC;AAE/E,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAEN,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAC,UAAU,EAAE,cAAc,EAAC,MAAM,oBAAoB,CAAC;AACnE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAC;AAOrD,OAAO,KAAK,EAAC,uBAAuB,EAAC,MAAM,kBAAkB,CAAC;AAI9D;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,gBAIhC,CAAC;AAEF,gFAAgF;AAChF,eAAO,MAAM,kBAAkB,QAAiB,CAAC;AASjD;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC3C,EAAE,EAAE,EAAE,CAAC;IACP,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CACtB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB,GAClC,SAAS,2BAA2B,KAClC,OAAO,CAAC;IACV,OAAO,EAAE;QAAC,EAAE,EAAE,IAAI,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAC,CAAC;IACtC,KAAK,EAAE;QAAC,EAAE,EAAE,IAAI,CAAA;KAAC,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACvB,CAyCA,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,aAAc,SAAQ,UAAU;IAChD,gCAAgC;IAChC,OAAO,EAAE;QAAC,EAAE,EAAE,IAAI,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAC,CAAC;IACtC,uCAAuC;IACvC,KAAK,EAAE;QAAC,EAAE,EAAE,IAAI,CAAA;KAAC,CAAC;IAClB,qCAAqC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,cAAc,EAAE,MAAM,CAAC;IACvB,+FAA+F;IAC/F,OAAO,EAAE,OAAO,CAAC;IACjB,4EAA4E;IAC5E,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACpC,mDAAmD;IACnD,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,kGAAkG;IAClG,EAAE,CAAC,EAAE,EAAE,CAAC;IACR,0FAA0F;IAC1F,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yHAAyH;IACzH,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6EAA6E;IAC7E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gDAAgD;IAChD,KAAK,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACtB;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAChD;;;;;;;;OAQG;IACH,gBAAgB,CAAC,EAAE,cAAc,CAAC;CAClC;AAKD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,sBAAsB,GAClC,SAAS,oBAAoB,KAC3B,OAAO,CAAC,aAAa,CA+FvB,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,oBAAoB;IACjE,yEAAyE;IACzE,kBAAkB,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IACpE;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,uBAAuB,CAAC;IACxC,gHAAgH;IAChH,WAAW,CAAC,EAAE,OAAO,CACpB,IAAI,CAAC,gBAAgB,EAAE,SAAS,GAAG,iBAAiB,GAAG,oBAAoB,CAAC,CAC5E,CAAC;CACF;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,CACpC,IAAI,CAAC,gBAAgB,EAAE,SAAS,GAAG,iBAAiB,GAAG,oBAAoB,GAAG,eAAe,CAAC,CAC9F,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,WAAW;IAC3B,OAAO,EAAE;QAAC,EAAE,EAAE,IAAI,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAC,CAAC;IACtC,KAAK,EAAE;QAAC,EAAE,EAAE,IAAI,CAAA;KAAC,CAAC;IAClB,mCAAmC;IACnC,cAAc,EAAE,MAAM,CAAC;IACvB,qCAAqC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,sBAAsB,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnF,8DAA8D;IAC9D,qBAAqB,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClF;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACvB,GAAG,EAAE,IAAI,CAAC;IACV,OAAO,EAAE,aAAa,CAAC;IACvB,YAAY,EAAE,cAAc,CAAC;IAC7B,OAAO,EAAE,UAAU,CAAC;IACpB,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAC9B,kEAAkE;IAClE,sBAAsB,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnF,gEAAgE;IAChE,qBAAqB,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClF,iEAAiE;IACjE,2BAA2B,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxF,qDAAqD;IACrD,cAAc,EAAE,CAAC,OAAO,CAAC,EAAE;QAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,KAAK,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;KACtB,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAC3B,8DAA8D;IAC9D,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,eAAe,GAAU,SAAS,oBAAoB,KAAG,OAAO,CAAC,OAAO,CAyGpF,CAAC"}
|