@fuzdev/fuz_app 0.104.0 → 0.106.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/actions/CLAUDE.md +2 -2
- package/dist/actions/action_bridge.d.ts.map +1 -1
- package/dist/actions/action_bridge.js +2 -2
- package/dist/actions/action_codegen.d.ts.map +1 -1
- package/dist/actions/action_codegen.js +3 -3
- package/dist/actions/action_dispatcher.d.ts.map +1 -1
- package/dist/actions/action_dispatcher.js +3 -3
- package/dist/actions/action_event.d.ts.map +1 -1
- package/dist/actions/action_event.js +11 -11
- package/dist/actions/action_event_data.d.ts.map +1 -1
- package/dist/actions/action_event_data.js +2 -2
- package/dist/actions/action_event_helpers.d.ts.map +1 -1
- package/dist/actions/action_event_helpers.js +2 -2
- package/dist/actions/action_event_types.d.ts.map +1 -1
- package/dist/actions/action_event_types.js +4 -4
- package/dist/actions/action_rpc.d.ts.map +1 -1
- package/dist/actions/action_rpc.js +14 -13
- package/dist/actions/action_spec.d.ts.map +1 -1
- package/dist/actions/action_spec.js +6 -6
- package/dist/actions/action_types.d.ts.map +1 -1
- package/dist/actions/broadcast_api.d.ts.map +1 -1
- package/dist/actions/broadcast_api.js +1 -1
- package/dist/actions/cancel.d.ts.map +1 -1
- package/dist/actions/cancel.js +3 -3
- package/dist/actions/compile_action_registry.d.ts.map +1 -1
- package/dist/actions/frontend_rpc_client.d.ts.map +1 -1
- package/dist/actions/frontend_rpc_client.js +3 -3
- package/dist/actions/heartbeat.d.ts.map +1 -1
- package/dist/actions/heartbeat.js +2 -2
- package/dist/actions/peer_ping.d.ts.map +1 -1
- package/dist/actions/peer_ping.js +6 -6
- package/dist/actions/peer_request.d.ts.map +1 -1
- package/dist/actions/perform_action.d.ts +8 -0
- package/dist/actions/perform_action.d.ts.map +1 -1
- package/dist/actions/perform_action.js +41 -23
- package/dist/actions/protocol.d.ts.map +1 -1
- package/dist/actions/protocol.js +1 -1
- package/dist/actions/register_action_ws.d.ts.map +1 -1
- package/dist/actions/register_action_ws.js +39 -12
- package/dist/actions/register_ws_endpoint.d.ts.map +1 -1
- package/dist/actions/register_ws_endpoint.js +3 -3
- package/dist/actions/request_tracker.svelte.d.ts.map +1 -1
- package/dist/actions/request_tracker.svelte.js +2 -2
- package/dist/actions/rpc_client.d.ts.map +1 -1
- package/dist/actions/rpc_client.js +7 -7
- package/dist/actions/socket.svelte.d.ts.map +1 -1
- package/dist/actions/socket.svelte.js +4 -3
- package/dist/actions/transports.d.ts.map +1 -1
- package/dist/actions/transports_http.d.ts.map +1 -1
- package/dist/actions/transports_http.js +7 -7
- package/dist/actions/transports_ws.d.ts.map +1 -1
- package/dist/actions/transports_ws.js +3 -3
- package/dist/actions/transports_ws_auth_guard.d.ts +4 -4
- package/dist/actions/transports_ws_auth_guard.d.ts.map +1 -1
- package/dist/actions/transports_ws_auth_guard.js +5 -5
- package/dist/actions/transports_ws_backend.d.ts.map +1 -1
- package/dist/actions/transports_ws_backend.js +2 -2
- package/dist/actions/ws_endpoint_spec.d.ts +2 -2
- package/dist/actions/ws_endpoint_spec.d.ts.map +1 -1
- package/dist/auth/CLAUDE.md +11 -7
- package/dist/auth/account_action_specs.d.ts +32 -9
- package/dist/auth/account_action_specs.d.ts.map +1 -1
- package/dist/auth/account_action_specs.js +35 -23
- package/dist/auth/account_actions.d.ts +3 -3
- package/dist/auth/account_actions.d.ts.map +1 -1
- package/dist/auth/account_actions.js +25 -12
- package/dist/auth/account_queries.d.ts.map +1 -1
- package/dist/auth/account_queries.js +6 -6
- package/dist/auth/account_route_schema.d.ts.map +1 -1
- package/dist/auth/account_route_schema.js +19 -19
- package/dist/auth/account_routes.d.ts +2 -2
- package/dist/auth/account_routes.d.ts.map +1 -1
- package/dist/auth/account_routes.js +27 -27
- package/dist/auth/account_schema.d.ts +26 -2
- package/dist/auth/account_schema.d.ts.map +1 -1
- package/dist/auth/account_schema.js +28 -10
- package/dist/auth/actor_lookup_action_specs.d.ts.map +1 -1
- package/dist/auth/actor_lookup_action_specs.js +5 -5
- package/dist/auth/actor_lookup_actions.d.ts +4 -2
- package/dist/auth/actor_lookup_actions.d.ts.map +1 -1
- package/dist/auth/actor_lookup_actions.js +3 -3
- package/dist/auth/actor_lookup_queries.d.ts.map +1 -1
- package/dist/auth/actor_search_action_specs.d.ts.map +1 -1
- package/dist/auth/actor_search_action_specs.js +6 -6
- package/dist/auth/actor_search_actions.d.ts +4 -2
- package/dist/auth/actor_search_actions.d.ts.map +1 -1
- package/dist/auth/actor_search_actions.js +5 -5
- package/dist/auth/actor_search_queries.d.ts.map +1 -1
- package/dist/auth/admin_action_specs.d.ts +2 -2
- package/dist/auth/admin_action_specs.d.ts.map +1 -1
- package/dist/auth/admin_action_specs.js +55 -55
- package/dist/auth/admin_actions.d.ts +5 -5
- package/dist/auth/admin_actions.d.ts.map +1 -1
- package/dist/auth/admin_actions.js +45 -44
- package/dist/auth/all_action_spec_registries.d.ts.map +1 -1
- package/dist/auth/all_action_spec_registries.js +1 -1
- package/dist/auth/all_cell_actions.d.ts.map +1 -1
- package/dist/auth/all_cell_actions.js +1 -1
- package/dist/auth/api_token.d.ts.map +1 -1
- package/dist/auth/api_token_queries.d.ts +9 -3
- package/dist/auth/api_token_queries.d.ts.map +1 -1
- package/dist/auth/api_token_queries.js +29 -8
- package/dist/auth/app_settings_queries.d.ts.map +1 -1
- package/dist/auth/app_settings_schema.d.ts.map +1 -1
- package/dist/auth/app_settings_schema.js +3 -3
- package/dist/auth/audit_emitter.d.ts +28 -20
- package/dist/auth/audit_emitter.d.ts.map +1 -1
- package/dist/auth/audit_emitter.js +37 -19
- package/dist/auth/audit_log_ddl.js +1 -1
- package/dist/auth/audit_log_queries.d.ts.map +1 -1
- package/dist/auth/audit_log_queries.js +2 -2
- package/dist/auth/audit_log_route_schema.d.ts.map +1 -1
- package/dist/auth/audit_log_route_schema.js +1 -1
- package/dist/auth/audit_log_routes.d.ts.map +1 -1
- package/dist/auth/audit_log_routes.js +12 -4
- package/dist/auth/audit_log_schema.d.ts +2 -2
- package/dist/auth/audit_log_schema.d.ts.map +1 -1
- package/dist/auth/audit_log_schema.js +69 -68
- package/dist/auth/auth_ddl.js +3 -3
- package/dist/auth/auth_guard_resolver.d.ts.map +1 -1
- package/dist/auth/bearer_auth.d.ts.map +1 -1
- package/dist/auth/bearer_auth.js +6 -1
- package/dist/auth/bootstrap_account.d.ts.map +1 -1
- package/dist/auth/bootstrap_account.js +5 -5
- package/dist/auth/bootstrap_route_schema.d.ts.map +1 -1
- package/dist/auth/bootstrap_route_schema.js +6 -6
- package/dist/auth/bootstrap_routes.d.ts.map +1 -1
- package/dist/auth/bootstrap_routes.js +7 -7
- package/dist/auth/cell_action_specs.d.ts +1 -1
- package/dist/auth/cell_action_specs.d.ts.map +1 -1
- package/dist/auth/cell_action_specs.js +47 -47
- package/dist/auth/cell_actions.d.ts +2 -2
- package/dist/auth/cell_actions.d.ts.map +1 -1
- package/dist/auth/cell_actions.js +37 -37
- package/dist/auth/cell_audit_action_specs.d.ts.map +1 -1
- package/dist/auth/cell_audit_action_specs.js +4 -4
- package/dist/auth/cell_audit_actions.d.ts.map +1 -1
- package/dist/auth/cell_audit_actions.js +3 -3
- package/dist/auth/cell_audit_events.d.ts.map +1 -1
- package/dist/auth/cell_audit_events.js +5 -5
- package/dist/auth/cell_audit_metadata.d.ts.map +1 -1
- package/dist/auth/cell_audit_metadata.js +3 -3
- package/dist/auth/cell_authorize.d.ts.map +1 -1
- package/dist/auth/cell_data_schema.d.ts.map +1 -1
- package/dist/auth/cell_data_schema.js +1 -1
- package/dist/auth/cell_field_action_specs.d.ts.map +1 -1
- package/dist/auth/cell_field_action_specs.js +16 -16
- package/dist/auth/cell_field_actions.d.ts +2 -2
- package/dist/auth/cell_field_actions.d.ts.map +1 -1
- package/dist/auth/cell_field_actions.js +11 -11
- package/dist/auth/cell_field_audit_metadata.d.ts.map +1 -1
- package/dist/auth/cell_field_audit_metadata.js +2 -2
- package/dist/auth/cell_grant_action_specs.d.ts.map +1 -1
- package/dist/auth/cell_grant_action_specs.js +15 -15
- package/dist/auth/cell_grant_actions.d.ts +2 -2
- package/dist/auth/cell_grant_actions.d.ts.map +1 -1
- package/dist/auth/cell_grant_actions.js +12 -12
- package/dist/auth/cell_grant_audit_metadata.d.ts.map +1 -1
- package/dist/auth/cell_grant_audit_metadata.js +3 -3
- package/dist/auth/cell_item_action_specs.d.ts +6 -2
- package/dist/auth/cell_item_action_specs.d.ts.map +1 -1
- package/dist/auth/cell_item_action_specs.js +25 -21
- package/dist/auth/cell_item_actions.d.ts +2 -2
- package/dist/auth/cell_item_actions.d.ts.map +1 -1
- package/dist/auth/cell_item_actions.js +14 -14
- package/dist/auth/cell_item_audit_metadata.d.ts.map +1 -1
- package/dist/auth/cell_item_audit_metadata.js +3 -3
- package/dist/auth/cell_relation_visibility.d.ts.map +1 -1
- package/dist/auth/cleanup.d.ts.map +1 -1
- package/dist/auth/cleanup.js +2 -2
- package/dist/auth/credential_type_schema.d.ts.map +1 -1
- package/dist/auth/credential_type_schema.js +5 -5
- package/dist/auth/daemon_token.d.ts.map +1 -1
- package/dist/auth/daemon_token_middleware.d.ts.map +1 -1
- package/dist/auth/daemon_token_middleware.js +7 -3
- package/dist/auth/deps.d.ts +20 -5
- package/dist/auth/deps.d.ts.map +1 -1
- package/dist/auth/grant_path_schema.d.ts.map +1 -1
- package/dist/auth/grant_path_schema.js +8 -8
- package/dist/auth/invite_queries.d.ts.map +1 -1
- package/dist/auth/invite_schema.d.ts.map +1 -1
- package/dist/auth/invite_schema.js +2 -2
- package/dist/auth/keyring.d.ts.map +1 -1
- package/dist/auth/keyring.js +1 -1
- package/dist/auth/middleware.d.ts.map +1 -1
- package/dist/auth/middleware.js +7 -7
- package/dist/auth/migrations.d.ts.map +1 -1
- package/dist/auth/migrations.js +54 -19
- package/dist/auth/password.d.ts.map +1 -1
- package/dist/auth/password_argon2.d.ts.map +1 -1
- package/dist/auth/password_argon2.js +2 -2
- package/dist/auth/request_context.d.ts +18 -0
- package/dist/auth/request_context.d.ts.map +1 -1
- package/dist/auth/request_context.js +33 -7
- package/dist/auth/role_grant_offer_action_specs.d.ts +12 -0
- package/dist/auth/role_grant_offer_action_specs.d.ts.map +1 -1
- package/dist/auth/role_grant_offer_action_specs.js +47 -36
- package/dist/auth/role_grant_offer_actions.d.ts +7 -4
- package/dist/auth/role_grant_offer_actions.d.ts.map +1 -1
- package/dist/auth/role_grant_offer_actions.js +43 -43
- package/dist/auth/role_grant_offer_notifications.d.ts.map +1 -1
- package/dist/auth/role_grant_offer_notifications.js +13 -13
- package/dist/auth/role_grant_offer_queries.d.ts +1 -1
- package/dist/auth/role_grant_offer_queries.d.ts.map +1 -1
- package/dist/auth/role_grant_offer_queries.js +11 -11
- package/dist/auth/role_grant_offer_schema.d.ts.map +1 -1
- package/dist/auth/role_grant_offer_schema.js +7 -7
- package/dist/auth/role_grant_queries.d.ts.map +1 -1
- package/dist/auth/role_grant_queries.js +3 -3
- package/dist/auth/role_schema.d.ts.map +1 -1
- package/dist/auth/role_schema.js +7 -7
- package/dist/auth/scope_kind_schema.d.ts.map +1 -1
- package/dist/auth/self_service_role_action_specs.d.ts +7 -0
- package/dist/auth/self_service_role_action_specs.d.ts.map +1 -1
- package/dist/auth/self_service_role_action_specs.js +12 -6
- package/dist/auth/self_service_role_actions.d.ts +3 -3
- package/dist/auth/self_service_role_actions.d.ts.map +1 -1
- package/dist/auth/self_service_role_actions.js +9 -9
- package/dist/auth/session_cookie.d.ts.map +1 -1
- package/dist/auth/session_cookie.js +3 -3
- package/dist/auth/session_middleware.d.ts.map +1 -1
- package/dist/auth/session_middleware.js +4 -4
- package/dist/auth/session_queries.d.ts +14 -4
- package/dist/auth/session_queries.d.ts.map +1 -1
- package/dist/auth/session_queries.js +13 -3
- package/dist/auth/signup_route_schema.d.ts.map +1 -1
- package/dist/auth/signup_route_schema.js +6 -6
- package/dist/auth/signup_routes.d.ts.map +1 -1
- package/dist/auth/signup_routes.js +11 -11
- package/dist/auth/standard_action_specs.d.ts.map +1 -1
- package/dist/auth/standard_action_specs.js +1 -1
- package/dist/auth/standard_rpc_actions.d.ts +4 -4
- package/dist/auth/standard_rpc_actions.d.ts.map +1 -1
- package/dist/auth/standard_rpc_actions.js +3 -3
- package/dist/auth/token_scope.d.ts +155 -0
- package/dist/auth/token_scope.d.ts.map +1 -0
- package/dist/auth/token_scope.js +190 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/daemon.d.ts.map +1 -1
- package/dist/cli/daemon.js +3 -3
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +1 -1
- package/dist/cli/logger.d.ts.map +1 -1
- package/dist/cli/logger.js +1 -1
- package/dist/cli/util.d.ts.map +1 -1
- package/dist/cli/util.js +1 -1
- package/dist/db/CLAUDE.md +1 -1
- package/dist/db/cell_audit_queries.d.ts.map +1 -1
- package/dist/db/cell_audit_queries.js +1 -1
- package/dist/db/cell_ddl.d.ts.map +1 -1
- package/dist/db/cell_ddl.js +7 -7
- package/dist/db/cell_field_queries.d.ts.map +1 -1
- package/dist/db/cell_grant_queries.d.ts.map +1 -1
- package/dist/db/cell_grant_queries.js +1 -1
- package/dist/db/cell_history_ddl.d.ts.map +1 -1
- package/dist/db/cell_history_ddl.js +4 -4
- package/dist/db/cell_item_queries.d.ts.map +1 -1
- package/dist/db/cell_queries.d.ts +1 -1
- package/dist/db/cell_queries.d.ts.map +1 -1
- package/dist/db/cell_queries.js +3 -3
- package/dist/db/create_db.d.ts.map +1 -1
- package/dist/db/create_db.js +1 -1
- package/dist/db/db.d.ts.map +1 -1
- package/dist/db/db_pg.d.ts.map +1 -1
- package/dist/db/db_pg.js +1 -1
- package/dist/db/db_pglite.d.ts.map +1 -1
- package/dist/db/db_pglite.js +1 -1
- package/dist/db/fact_ddl.d.ts.map +1 -1
- package/dist/db/fact_ddl.js +3 -3
- package/dist/db/fact_disk_storage.d.ts +1 -1
- package/dist/db/fact_disk_storage.d.ts.map +1 -1
- package/dist/db/fact_disk_storage.js +6 -6
- package/dist/db/fact_queries.d.ts +1 -1
- package/dist/db/fact_queries.d.ts.map +1 -1
- package/dist/db/fact_queries.js +2 -2
- package/dist/db/fact_store.d.ts +1 -1
- package/dist/db/fact_store.d.ts.map +1 -1
- package/dist/db/fact_store.js +9 -9
- package/dist/db/fact_store_errors.d.ts.map +1 -1
- package/dist/db/file_fact_url.d.ts +1 -1
- package/dist/db/file_fact_url.d.ts.map +1 -1
- package/dist/db/file_fact_url.js +1 -1
- package/dist/db/migrate.d.ts.map +1 -1
- package/dist/db/pg_error.d.ts.map +1 -1
- package/dist/db/query_deps.d.ts.map +1 -1
- package/dist/db/schema_ready.d.ts.map +1 -1
- package/dist/db/schema_ready.js +2 -2
- package/dist/db/status.d.ts.map +1 -1
- package/dist/db/status.js +6 -6
- package/dist/dev/setup.d.ts.map +1 -1
- package/dist/dev/setup.js +6 -6
- package/dist/env/dotenv.d.ts.map +1 -1
- package/dist/env/load.d.ts.map +1 -1
- package/dist/env/resolve.d.ts.map +1 -1
- package/dist/hono_context.d.ts +23 -0
- package/dist/hono_context.d.ts.map +1 -1
- package/dist/hono_context.js +16 -2
- package/dist/http/auth_shape.d.ts.map +1 -1
- package/dist/http/auth_shape.js +6 -6
- package/dist/http/client_ip.d.ts.map +1 -1
- package/dist/http/common_routes.d.ts.map +1 -1
- package/dist/http/common_routes.js +8 -8
- package/dist/http/db_routes.d.ts.map +1 -1
- package/dist/http/db_routes.js +27 -23
- package/dist/http/error_schemas.d.ts +13 -1
- package/dist/http/error_schemas.d.ts.map +1 -1
- package/dist/http/error_schemas.js +25 -13
- package/dist/http/jsonrpc.d.ts.map +1 -1
- package/dist/http/jsonrpc.js +9 -9
- package/dist/http/jsonrpc_errors.d.ts.map +1 -1
- package/dist/http/jsonrpc_errors.js +21 -21
- package/dist/http/jsonrpc_helpers.d.ts.map +1 -1
- package/dist/http/jsonrpc_helpers.js +7 -7
- package/dist/http/middleware_spec.d.ts.map +1 -1
- package/dist/http/origin.d.ts.map +1 -1
- package/dist/http/pending_effects.d.ts.map +1 -1
- package/dist/http/proxy.d.ts.map +1 -1
- package/dist/http/proxy.js +1 -1
- package/dist/http/route_spec.d.ts.map +1 -1
- package/dist/http/route_spec.js +6 -6
- package/dist/http/schema_helpers.d.ts.map +1 -1
- package/dist/http/schema_helpers.js +1 -1
- package/dist/http/surface.d.ts.map +1 -1
- package/dist/http/surface.js +11 -11
- package/dist/http/surface_query.d.ts.map +1 -1
- package/dist/http/surface_query.js +1 -1
- package/dist/primitive_schemas.d.ts.map +1 -1
- package/dist/primitive_schemas.js +1 -1
- package/dist/rate_limiter.d.ts.map +1 -1
- package/dist/rate_limiter.js +4 -4
- package/dist/realtime/sse.d.ts.map +1 -1
- package/dist/realtime/sse.js +2 -2
- package/dist/realtime/sse_auth_guard.d.ts +4 -4
- package/dist/realtime/sse_auth_guard.d.ts.map +1 -1
- package/dist/realtime/sse_auth_guard.js +8 -8
- package/dist/realtime/subscriber_registry.d.ts.map +1 -1
- package/dist/runtime/deno.d.ts.map +1 -1
- package/dist/runtime/deno.js +7 -7
- package/dist/runtime/deps.d.ts.map +1 -1
- package/dist/runtime/fs.d.ts.map +1 -1
- package/dist/runtime/mock.d.ts.map +1 -1
- package/dist/runtime/mock.js +3 -3
- package/dist/runtime/node.d.ts.map +1 -1
- package/dist/runtime/node.js +7 -7
- package/dist/schema_meta.d.ts.map +1 -1
- package/dist/server/app_backend.d.ts +3 -3
- package/dist/server/app_backend.d.ts.map +1 -1
- package/dist/server/app_backend.js +3 -3
- package/dist/server/app_server.d.ts +6 -6
- package/dist/server/app_server.d.ts.map +1 -1
- package/dist/server/app_server.js +32 -32
- package/dist/server/app_server_context.d.ts.map +1 -1
- package/dist/server/env.d.ts.map +1 -1
- package/dist/server/env.js +9 -9
- package/dist/server/file_fact_fetcher.d.ts.map +1 -1
- package/dist/server/file_fact_fetcher.js +1 -1
- package/dist/server/serve_fact_route.d.ts.map +1 -1
- package/dist/server/serve_fact_route.js +23 -13
- package/dist/server/startup.d.ts.map +1 -1
- package/dist/server/static.d.ts.map +1 -1
- package/dist/server/x_accel.d.ts +2 -4
- package/dist/server/x_accel.d.ts.map +1 -1
- package/dist/server/x_accel.js +3 -5
- package/dist/testing/CLAUDE.md +2 -2
- package/dist/testing/admin_integration.d.ts.map +1 -1
- package/dist/testing/admin_integration.js +64 -64
- package/dist/testing/adversarial_404.d.ts.map +1 -1
- package/dist/testing/adversarial_404.js +1 -1
- package/dist/testing/adversarial_headers.d.ts.map +1 -1
- package/dist/testing/adversarial_headers.js +15 -15
- package/dist/testing/adversarial_input.d.ts.map +1 -1
- package/dist/testing/adversarial_input.js +22 -22
- package/dist/testing/app_server.d.ts.map +1 -1
- package/dist/testing/app_server.js +34 -33
- package/dist/testing/assertions.d.ts.map +1 -1
- package/dist/testing/attack_surface.d.ts.map +1 -1
- package/dist/testing/attack_surface.js +12 -12
- package/dist/testing/audit_completeness.d.ts.map +1 -1
- package/dist/testing/audit_completeness.js +42 -42
- package/dist/testing/audit_drift_guard.d.ts +3 -1
- package/dist/testing/audit_drift_guard.d.ts.map +1 -1
- package/dist/testing/audit_drift_guard.js +12 -6
- package/dist/testing/auth_apps.d.ts.map +1 -1
- package/dist/testing/auth_apps.js +4 -4
- package/dist/testing/bootstrap_success.d.ts.map +1 -1
- package/dist/testing/bootstrap_success.js +11 -11
- package/dist/testing/connection_closer_helpers.d.ts.map +1 -1
- package/dist/testing/connection_closer_helpers.js +1 -1
- package/dist/testing/cross_backend/account_lifecycle.d.ts.map +1 -1
- package/dist/testing/cross_backend/account_lifecycle.js +1 -1
- package/dist/testing/cross_backend/action_manifest.d.ts.map +1 -1
- package/dist/testing/cross_backend/action_manifest.js +4 -4
- package/dist/testing/cross_backend/action_manifest_parity.d.ts.map +1 -1
- package/dist/testing/cross_backend/actor_lookup.d.ts.map +1 -1
- package/dist/testing/cross_backend/actor_lookup.js +3 -3
- package/dist/testing/cross_backend/actor_search.d.ts.map +1 -1
- package/dist/testing/cross_backend/actor_search.js +5 -5
- package/dist/testing/cross_backend/app_settings.d.ts.map +1 -1
- package/dist/testing/cross_backend/app_settings.js +6 -6
- package/dist/testing/cross_backend/backend_config.d.ts.map +1 -1
- package/dist/testing/cross_backend/bench/bench_report.d.ts.map +1 -1
- package/dist/testing/cross_backend/bench/bench_report.js +5 -5
- package/dist/testing/cross_backend/bench/run_cross_impl_bench.d.ts.map +1 -1
- package/dist/testing/cross_backend/bench/run_cross_impl_bench.js +2 -2
- package/dist/testing/cross_backend/bench/scenario.d.ts.map +1 -1
- package/dist/testing/cross_backend/bench/scenario.js +1 -1
- package/dist/testing/cross_backend/body_size.d.ts.map +1 -1
- package/dist/testing/cross_backend/body_size.js +1 -1
- package/dist/testing/cross_backend/bootstrap_backend.d.ts.map +1 -1
- package/dist/testing/cross_backend/bootstrap_backend.js +2 -2
- package/dist/testing/cross_backend/build_test_backend_paths.js +1 -1
- package/dist/testing/cross_backend/capabilities.js +2 -2
- package/dist/testing/cross_backend/cell_cross_helpers.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_crud.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_crud.js +5 -2
- package/dist/testing/cross_backend/cell_gated_create.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_gated_create.js +8 -7
- package/dist/testing/cross_backend/cell_grant_role.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_grant_role.js +2 -2
- package/dist/testing/cross_backend/cell_relations.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_relations.js +13 -13
- package/dist/testing/cross_backend/conformance_case.d.ts +23 -0
- package/dist/testing/cross_backend/conformance_case.d.ts.map +1 -1
- package/dist/testing/cross_backend/conformance_case.js +32 -11
- package/dist/testing/cross_backend/conformance_table.d.ts.map +1 -1
- package/dist/testing/cross_backend/conformance_table.js +68 -15
- package/dist/testing/cross_backend/cookie_attributes.d.ts.map +1 -1
- package/dist/testing/cross_backend/cookie_attributes.js +4 -4
- package/dist/testing/cross_backend/create_cross_backend_global_setup.d.ts +1 -1
- package/dist/testing/cross_backend/create_cross_backend_global_setup.d.ts.map +1 -1
- package/dist/testing/cross_backend/create_cross_backend_global_setup.js +1 -1
- package/dist/testing/cross_backend/create_dual_spawn_global_setup.d.ts +1 -1
- package/dist/testing/cross_backend/create_dual_spawn_global_setup.d.ts.map +1 -1
- package/dist/testing/cross_backend/create_dual_spawn_global_setup.js +1 -1
- package/dist/testing/cross_backend/credential_header_robustness.js +1 -1
- package/dist/testing/cross_backend/default_backend_configs.d.ts.map +1 -1
- package/dist/testing/cross_backend/default_backend_configs.js +12 -12
- package/dist/testing/cross_backend/default_spine_surface.d.ts.map +1 -1
- package/dist/testing/cross_backend/default_spine_surface.js +9 -9
- package/dist/testing/cross_backend/expected_schema.json +1 -0
- package/dist/testing/cross_backend/fact_serving.d.ts.map +1 -1
- package/dist/testing/cross_backend/fact_serving.js +2 -2
- package/dist/testing/cross_backend/full_spine_mount.d.ts.map +1 -1
- package/dist/testing/cross_backend/full_spine_mount.js +4 -4
- package/dist/testing/cross_backend/identity_parity.d.ts.map +1 -1
- package/dist/testing/cross_backend/identity_parity.js +28 -24
- package/dist/testing/cross_backend/in_process_setup.d.ts.map +1 -1
- package/dist/testing/cross_backend/in_process_setup.js +9 -9
- package/dist/testing/cross_backend/login_security.d.ts.map +1 -1
- package/dist/testing/cross_backend/login_security.js +2 -2
- package/dist/testing/cross_backend/make_cross_backend_project.d.ts +1 -1
- package/dist/testing/cross_backend/make_cross_backend_project.d.ts.map +1 -1
- package/dist/testing/cross_backend/make_cross_backend_project.js +3 -3
- package/dist/testing/cross_backend/method_coverage.d.ts.map +1 -1
- package/dist/testing/cross_backend/origin.d.ts.map +1 -1
- package/dist/testing/cross_backend/origin.js +4 -4
- package/dist/testing/cross_backend/peer_ping_ws.d.ts.map +1 -1
- package/dist/testing/cross_backend/peer_ping_ws.js +6 -6
- package/dist/testing/cross_backend/ready.d.ts.map +1 -1
- package/dist/testing/cross_backend/role_grant_offer_enumeration.d.ts.map +1 -1
- package/dist/testing/cross_backend/role_grant_offer_enumeration.js +1 -1
- 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 +1 -1
- package/dist/testing/cross_backend/role_grant_participation.d.ts.map +1 -1
- package/dist/testing/cross_backend/rust_spine_stub_backend_config.d.ts.map +1 -1
- package/dist/testing/cross_backend/rust_spine_stub_backend_config.js +5 -5
- package/dist/testing/cross_backend/setup.d.ts.map +1 -1
- package/dist/testing/cross_backend/setup.js +41 -37
- package/dist/testing/cross_backend/spawn_backend.d.ts.map +1 -1
- package/dist/testing/cross_backend/spawn_backend.js +1 -1
- package/dist/testing/cross_backend/sse_round_trip.d.ts.map +1 -1
- package/dist/testing/cross_backend/sse_round_trip.js +10 -7
- package/dist/testing/cross_backend/standard.d.ts.map +1 -1
- package/dist/testing/cross_backend/standard.js +5 -5
- package/dist/testing/cross_backend/testing_backdoor.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_backdoor.js +7 -7
- package/dist/testing/cross_backend/testing_reset_actions.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_reset_actions.js +24 -23
- package/dist/testing/cross_backend/testing_server_bun.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_server_bun.js +3 -3
- package/dist/testing/cross_backend/testing_server_core.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_server_core.js +1 -1
- package/dist/testing/cross_backend/testing_server_deno.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_server_deno.js +1 -1
- package/dist/testing/cross_backend/testing_server_node.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_server_node.js +3 -3
- package/dist/testing/cross_backend/ts_spine_backend_config.d.ts.map +1 -1
- package/dist/testing/cross_backend/ts_spine_backend_config.js +13 -13
- package/dist/testing/cross_backend/ws_round_trip.d.ts.map +1 -1
- package/dist/testing/cross_backend/ws_round_trip.js +2 -2
- package/dist/testing/data_exposure.d.ts.map +1 -1
- package/dist/testing/data_exposure.js +8 -8
- package/dist/testing/db.d.ts.map +1 -1
- package/dist/testing/db.js +3 -3
- package/dist/testing/db_entities.d.ts.map +1 -1
- package/dist/testing/db_entities.js +1 -1
- package/dist/testing/entities.d.ts.map +1 -1
- package/dist/testing/entities.js +5 -5
- package/dist/testing/error_coverage.d.ts.map +1 -1
- package/dist/testing/integration.d.ts.map +1 -1
- package/dist/testing/integration.js +109 -109
- package/dist/testing/integration_helpers.d.ts.map +1 -1
- package/dist/testing/integration_helpers.js +3 -3
- package/dist/testing/middleware.d.ts.map +1 -1
- package/dist/testing/middleware.js +11 -11
- package/dist/testing/mock_fs.js +1 -1
- package/dist/testing/rate_limiting.d.ts.map +1 -1
- package/dist/testing/rate_limiting.js +23 -23
- package/dist/testing/role_grant_helpers.d.ts.map +1 -1
- package/dist/testing/role_grant_helpers.js +3 -3
- package/dist/testing/round_trip.d.ts.map +1 -1
- package/dist/testing/round_trip.js +6 -6
- package/dist/testing/rpc_attack_surface.d.ts.map +1 -1
- package/dist/testing/rpc_attack_surface.js +12 -12
- package/dist/testing/rpc_helpers.d.ts.map +1 -1
- package/dist/testing/rpc_helpers.js +11 -11
- package/dist/testing/rpc_round_trip.d.ts.map +1 -1
- package/dist/testing/rpc_round_trip.js +3 -3
- package/dist/testing/schema_generators.d.ts.map +1 -1
- package/dist/testing/schema_generators.js +3 -3
- package/dist/testing/schema_introspect.d.ts.map +1 -1
- package/dist/testing/schema_introspect.js +12 -12
- package/dist/testing/schema_parity.d.ts.map +1 -1
- package/dist/testing/schema_parity.js +7 -7
- package/dist/testing/schema_ready_fixture.d.ts.map +1 -1
- package/dist/testing/sse_round_trip.d.ts.map +1 -1
- package/dist/testing/sse_round_trip.js +8 -8
- package/dist/testing/standard.d.ts.map +1 -1
- package/dist/testing/standard.js +8 -8
- package/dist/testing/stubs.d.ts +6 -6
- package/dist/testing/stubs.d.ts.map +1 -1
- package/dist/testing/stubs.js +26 -23
- package/dist/testing/surface_invariants.d.ts.map +1 -1
- package/dist/testing/surface_invariants.js +5 -5
- package/dist/testing/testing_rate_limiter.d.ts.map +1 -1
- package/dist/testing/transports/bootstrap.d.ts.map +1 -1
- package/dist/testing/transports/bootstrap.js +4 -4
- package/dist/testing/transports/fetch_transport.d.ts.map +1 -1
- package/dist/testing/transports/sse_frame_reader.d.ts.map +1 -1
- package/dist/testing/transports/sse_transport.js +1 -1
- package/dist/testing/transports/ws_client.d.ts.map +1 -1
- package/dist/testing/transports/ws_client.js +1 -1
- package/dist/testing/transports/ws_transport.js +4 -4
- package/dist/testing/ws_round_trip.d.ts.map +1 -1
- package/dist/testing/ws_round_trip.js +21 -21
- package/dist/ui/AccountSessions.svelte +11 -11
- package/dist/ui/AdminAccounts.svelte +10 -10
- package/dist/ui/AdminAuditLog.svelte +14 -14
- package/dist/ui/AdminInvites.svelte +13 -13
- package/dist/ui/AdminOverview.svelte +22 -22
- package/dist/ui/AdminRoleGrantHistory.svelte +11 -11
- package/dist/ui/AdminSessions.svelte +12 -12
- package/dist/ui/AdminSettings.svelte +1 -1
- package/dist/ui/AdminSurface.svelte +3 -3
- package/dist/ui/AppShell.svelte +8 -8
- package/dist/ui/AppShell.svelte.d.ts.map +1 -1
- package/dist/ui/BootstrapForm.svelte +9 -9
- package/dist/ui/CLAUDE.md +1 -1
- package/dist/ui/ColumnLayout.svelte +2 -2
- package/dist/ui/ColumnLayout.svelte.d.ts.map +1 -1
- package/dist/ui/ConfirmButton.svelte +8 -8
- package/dist/ui/ConfirmButton.svelte.d.ts.map +1 -1
- package/dist/ui/Datatable.svelte +6 -6
- package/dist/ui/Datatable.svelte.d.ts.map +1 -1
- package/dist/ui/LoginForm.svelte +6 -6
- package/dist/ui/LogoutButton.svelte +2 -2
- package/dist/ui/LogoutButton.svelte.d.ts.map +1 -1
- package/dist/ui/MenuLink.svelte +5 -5
- package/dist/ui/MenuLink.svelte.d.ts.map +1 -1
- package/dist/ui/OpenSignupToggle.svelte +2 -2
- package/dist/ui/PopoverButton.svelte +10 -10
- package/dist/ui/PopoverButton.svelte.d.ts.map +1 -1
- package/dist/ui/RoleGrantOfferForm.svelte +8 -11
- package/dist/ui/RoleGrantOfferForm.svelte.d.ts.map +1 -1
- package/dist/ui/RoleGrantOfferHistory.svelte +11 -11
- package/dist/ui/RoleGrantOfferHistory.svelte.d.ts.map +1 -1
- package/dist/ui/RoleGrantOfferInbox.svelte +6 -6
- package/dist/ui/RoleGrantOfferInbox.svelte.d.ts.map +1 -1
- package/dist/ui/SignupForm.svelte +9 -9
- package/dist/ui/SurfaceExplorer.svelte +11 -11
- package/dist/ui/SurfaceExplorer.svelte.d.ts.map +1 -1
- package/dist/ui/account_sessions_state.svelte.d.ts.map +1 -1
- package/dist/ui/admin_accounts_state.svelte.d.ts.map +1 -1
- package/dist/ui/admin_accounts_state.svelte.js +2 -2
- package/dist/ui/admin_invites_state.svelte.d.ts.map +1 -1
- package/dist/ui/admin_rpc_adapters.d.ts.map +1 -1
- package/dist/ui/admin_rpc_adapters.js +5 -5
- package/dist/ui/admin_sessions_state.svelte.d.ts.map +1 -1
- package/dist/ui/app_settings_state.svelte.d.ts.map +1 -1
- package/dist/ui/async_slot.svelte.d.ts.map +1 -1
- package/dist/ui/audit_log_state.svelte.d.ts.map +1 -1
- package/dist/ui/audit_log_state.svelte.js +1 -1
- package/dist/ui/auth_state.svelte.js +4 -4
- package/dist/ui/form_state.svelte.d.ts.map +1 -1
- package/dist/ui/format_scope.d.ts.map +1 -1
- package/dist/ui/keyed_async_slot.svelte.d.ts.map +1 -1
- package/dist/ui/popover.svelte.d.ts.map +1 -1
- package/dist/ui/popover.svelte.js +1 -1
- package/dist/ui/position_helpers.js +1 -1
- package/dist/ui/role_grant_offers_state.svelte.d.ts.map +1 -1
- package/dist/ui/role_grant_offers_state.svelte.js +1 -1
- package/dist/ui/table_state.svelte.d.ts.map +1 -1
- package/dist/ui/ui_fetch.d.ts.map +1 -1
- package/dist/ui/ui_format.js +2 -2
- package/package.json +13 -12
- package/dist/server/fact_write.d.ts +0 -32
- package/dist/server/fact_write.d.ts.map +0 -1
- package/dist/server/fact_write.js +0 -56
- package/dist/server/validate_nginx.d.ts +0 -34
- package/dist/server/validate_nginx.d.ts.map +0 -1
- package/dist/server/validate_nginx.js +0 -169
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import type { Logger } from '@fuzdev/fuz_util/log.ts';
|
|
10
10
|
import type { QueryDeps } from '../db/query_deps.js';
|
|
11
|
-
import type { AuthSession } from './account_schema.js';
|
|
11
|
+
import type { AuthSession, SessionId } from './account_schema.js';
|
|
12
12
|
/** Session lifetime in milliseconds (30 days). */
|
|
13
13
|
export declare const AUTH_SESSION_LIFETIME_MS: number;
|
|
14
14
|
/** Extend session when it has less than this remaining (1 day in ms). */
|
|
@@ -16,10 +16,13 @@ export declare const AUTH_SESSION_EXTEND_THRESHOLD_MS: number;
|
|
|
16
16
|
/**
|
|
17
17
|
* Hash a session token to its storage key using blake3.
|
|
18
18
|
*
|
|
19
|
+
* The sole minting point for `SessionId` — `hash_blake3` returns bare hex, so
|
|
20
|
+
* the brand is applied here, where the value gains its meaning.
|
|
21
|
+
*
|
|
19
22
|
* @param token - the raw session token
|
|
20
23
|
* @returns hex-encoded blake3 hash
|
|
21
24
|
*/
|
|
22
|
-
export declare const hash_session_token: (token: string) =>
|
|
25
|
+
export declare const hash_session_token: (token: string) => SessionId;
|
|
23
26
|
/**
|
|
24
27
|
* Generate a cryptographically random session token.
|
|
25
28
|
*
|
|
@@ -103,8 +106,15 @@ export declare const query_session_list_for_account: (deps: QueryDeps, account_i
|
|
|
103
106
|
* - `POST /bootstrap` and `POST /signup` manage their own transactions
|
|
104
107
|
* and pass the transaction-scoped `deps` to `create_session_and_set_cookie`
|
|
105
108
|
*
|
|
106
|
-
* The transaction
|
|
107
|
-
*
|
|
109
|
+
* The transaction makes one creator's INSERT + enforce_limit pair atomic, but it
|
|
110
|
+
* does **not** serialize concurrent creators. Under Read Committed, two
|
|
111
|
+
* transactions can't see each other's uncommitted session row, so each computes
|
|
112
|
+
* its `OFFSET` eviction against a stale count, each preserves its own row, and
|
|
113
|
+
* both commit above `max_sessions`. A transaction is necessary here but not
|
|
114
|
+
* sufficient. Closing this needs one serialization point per
|
|
115
|
+
* `(account_id, credential_kind)` — a locked parent row or a transaction-scoped
|
|
116
|
+
* advisory lock — taken before count/evict/insert, plus a stable tie-breaker
|
|
117
|
+
* alongside `created_at` so the survivors are deterministic.
|
|
108
118
|
*
|
|
109
119
|
* @param deps - query dependencies (must be transaction-scoped)
|
|
110
120
|
* @param account_id - the account to enforce the limit for
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/session_queries.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"session_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/session_queries.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAGtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAElE,kDAAkD;AAClD,eAAO,MAAM,wBAAwB,QAA2B,CAAC;AAEjE,yEAAyE;AACzE,eAAO,MAAM,gCAAgC,QAAsB,CAAC;AAEpE;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,GAAI,OAAO,MAAM,KAAG,SAElD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,QAAO,MAEzC,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,GAChC,MAAM,SAAS,EACf,YAAY,MAAM,EAClB,YAAY,MAAM,EAClB,YAAY,IAAI,KACd,OAAO,CAAC,IAAI,CAMd,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GACnC,MAAM,SAAS,EACf,YAAY,MAAM,KAChB,OAAO,CAAC,WAAW,GAAG,SAAS,CAKjC,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,GAAU,MAAM,SAAS,EAAE,YAAY,MAAM,KAAG,OAAO,CAAC,IAAI,CAY3F,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,qCAAqC,GACjD,MAAM,SAAS,EACf,YAAY,MAAM,KAChB,OAAO,CAAC,IAAI,CAEd,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gCAAgC,GAC5C,MAAM,SAAS,EACf,YAAY,MAAM,EAClB,YAAY,MAAM,KAChB,OAAO,CAAC,OAAO,CAMjB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,oCAAoC,GAChD,MAAM,SAAS,EACf,YAAY,MAAM,KAChB,OAAO,CAAC,MAAM,CAMhB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,8BAA8B,GAC1C,MAAM,SAAS,EACf,YAAY,MAAM,EAClB,cAAU,KACR,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAK5B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,2BAA2B,GACvC,MAAM,SAAS,EACf,YAAY,MAAM,EAClB,cAAc,MAAM,KAClB,OAAO,CAAC,MAAM,CAYhB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,GACzC,MAAM,SAAS,EACf,cAAW,KACT,OAAO,CAAC,KAAK,CAAC,WAAW,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CASnD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,6BAA6B,GAAU,MAAM,SAAS,KAAG,OAAO,CAAC,MAAM,CAKnF,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,6BAA6B,GACzC,MAAM,SAAS,EACf,YAAY,MAAM,EAClB,iBAAiB,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,EACjD,KAAK,MAAM,KACT,OAAO,CAAC,IAAI,CAMd,CAAC"}
|
|
@@ -15,6 +15,9 @@ export const AUTH_SESSION_EXTEND_THRESHOLD_MS = 24 * 60 * 60 * 1000;
|
|
|
15
15
|
/**
|
|
16
16
|
* Hash a session token to its storage key using blake3.
|
|
17
17
|
*
|
|
18
|
+
* The sole minting point for `SessionId` — `hash_blake3` returns bare hex, so
|
|
19
|
+
* the brand is applied here, where the value gains its meaning.
|
|
20
|
+
*
|
|
18
21
|
* @param token - the raw session token
|
|
19
22
|
* @returns hex-encoded blake3 hash
|
|
20
23
|
*/
|
|
@@ -42,7 +45,7 @@ export const query_create_session = async (deps, token_hash, account_id, expires
|
|
|
42
45
|
await deps.db.query(`INSERT INTO auth_session (id, account_id, expires_at) VALUES ($1, $2, $3)`, [
|
|
43
46
|
token_hash,
|
|
44
47
|
account_id,
|
|
45
|
-
expires_at.toISOString()
|
|
48
|
+
expires_at.toISOString()
|
|
46
49
|
]);
|
|
47
50
|
};
|
|
48
51
|
/**
|
|
@@ -133,8 +136,15 @@ export const query_session_list_for_account = async (deps, account_id, limit = 5
|
|
|
133
136
|
* - `POST /bootstrap` and `POST /signup` manage their own transactions
|
|
134
137
|
* and pass the transaction-scoped `deps` to `create_session_and_set_cookie`
|
|
135
138
|
*
|
|
136
|
-
* The transaction
|
|
137
|
-
*
|
|
139
|
+
* The transaction makes one creator's INSERT + enforce_limit pair atomic, but it
|
|
140
|
+
* does **not** serialize concurrent creators. Under Read Committed, two
|
|
141
|
+
* transactions can't see each other's uncommitted session row, so each computes
|
|
142
|
+
* its `OFFSET` eviction against a stale count, each preserves its own row, and
|
|
143
|
+
* both commit above `max_sessions`. A transaction is necessary here but not
|
|
144
|
+
* sufficient. Closing this needs one serialization point per
|
|
145
|
+
* `(account_id, credential_kind)` — a locked parent row or a transaction-scoped
|
|
146
|
+
* advisory lock — taken before count/evict/insert, plus a stable tie-breaker
|
|
147
|
+
* alongside `created_at` so the survivors are deterministic.
|
|
138
148
|
*
|
|
139
149
|
* @param deps - query dependencies (must be transaction-scoped)
|
|
140
150
|
* @param account_id - the account to enforce the limit for
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signup_route_schema.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/signup_route_schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"signup_route_schema.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/signup_route_schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAQvD,wHAAwH;AACxH,eAAO,MAAM,WAAW;;;;kBAItB,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEtD;;;;;;GAMG;AACH,eAAO,MAAM,YAAY;;;;;;;;;kBAIvB,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAExD,4EAA4E;AAC5E,MAAM,WAAW,uBAAuB;IACvC,iFAAiF;IACjF,2BAA2B,EAAE,OAAO,CAAC;CACrC;AAED;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,GACrC,SAAS,uBAAuB,KAC9B,IAAI,CAAC,SAAS,EAAE,SAAS,CAgB1B,CAAC"}
|
|
@@ -15,12 +15,12 @@ import { z } from 'zod';
|
|
|
15
15
|
import { Uuid } from '@fuzdev/fuz_util/id.ts';
|
|
16
16
|
import { Username, Email } from '../primitive_schemas.js';
|
|
17
17
|
import { Password } from './password.js';
|
|
18
|
-
import { ERROR_NO_MATCHING_INVITE, ERROR_SIGNUP_CONFLICT, ERROR_INVALID_JSON_BODY, ERROR_INVALID_REQUEST_BODY
|
|
18
|
+
import { ERROR_NO_MATCHING_INVITE, ERROR_SIGNUP_CONFLICT, ERROR_INVALID_JSON_BODY, ERROR_INVALID_REQUEST_BODY } from '../http/error_schemas.js';
|
|
19
19
|
/** Input for `POST /signup`. `email` is optional (absent or `null` = no email) and must match any referenced invite. */
|
|
20
20
|
export const SignupInput = z.strictObject({
|
|
21
21
|
username: Username,
|
|
22
22
|
password: Password,
|
|
23
|
-
email: Email.nullish()
|
|
23
|
+
email: Email.nullish()
|
|
24
24
|
});
|
|
25
25
|
/**
|
|
26
26
|
* Output for `POST /signup`.
|
|
@@ -32,7 +32,7 @@ export const SignupInput = z.strictObject({
|
|
|
32
32
|
export const SignupOutput = z.strictObject({
|
|
33
33
|
ok: z.literal(true),
|
|
34
34
|
account: z.strictObject({ id: Uuid, username: Username }),
|
|
35
|
-
actor: z.strictObject({ id: Uuid })
|
|
35
|
+
actor: z.strictObject({ id: Uuid })
|
|
36
36
|
});
|
|
37
37
|
/**
|
|
38
38
|
* The `POST /signup` route shape minus its handler — pure hono-free data.
|
|
@@ -51,9 +51,9 @@ export const create_signup_route_shape = (options) => ({
|
|
|
51
51
|
rate_limit: options.signup_account_rate_limited ? 'both' : 'ip',
|
|
52
52
|
errors: {
|
|
53
53
|
400: z.looseObject({
|
|
54
|
-
error: z.enum([ERROR_INVALID_JSON_BODY, ERROR_INVALID_REQUEST_BODY])
|
|
54
|
+
error: z.enum([ERROR_INVALID_JSON_BODY, ERROR_INVALID_REQUEST_BODY])
|
|
55
55
|
}),
|
|
56
56
|
403: z.looseObject({ error: z.literal(ERROR_NO_MATCHING_INVITE) }),
|
|
57
|
-
409: z.looseObject({ error: z.literal(ERROR_SIGNUP_CONFLICT) })
|
|
58
|
-
}
|
|
57
|
+
409: z.looseObject({ error: z.literal(ERROR_SIGNUP_CONFLICT) })
|
|
58
|
+
}
|
|
59
59
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signup_routes.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/signup_routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAaH,OAAO,
|
|
1
|
+
{"version":3,"file":"signup_routes.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/signup_routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAaH,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAExE,OAAO,EAAgC,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACpF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAGlD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAEnE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAEhD;;;;;;;GAOG;AACH,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAQhD;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,uBAAuB;IAClE,6FAA6F;IAC7F,2BAA2B,EAAE,WAAW,GAAG,IAAI,CAAC;IAChD;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAID;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,GACrC,MAAM,gBAAgB,EACtB,SAAS,kBAAkB,KACzB,KAAK,CAAC,SAAS,CA4KjB,CAAC"}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import { create_session_and_set_cookie } from './session_middleware.js';
|
|
11
11
|
import { query_create_account_with_actor } from './account_queries.js';
|
|
12
12
|
import { query_app_settings_load } from './app_settings_queries.js';
|
|
13
|
-
import { query_invite_find_unclaimed_match_for_update, query_invite_claim_unscoped
|
|
13
|
+
import { query_invite_find_unclaimed_match_for_update, query_invite_claim_unscoped } from './invite_queries.js';
|
|
14
14
|
import { create_signup_route_shape } from './signup_route_schema.js';
|
|
15
15
|
import { get_route_input } from '../http/route_spec.js';
|
|
16
16
|
import { get_client_ip } from '../http/client_ip.js';
|
|
@@ -55,11 +55,11 @@ const signup_fail_delay = (floor_ms, jitter_ms) => {
|
|
|
55
55
|
*/
|
|
56
56
|
export const create_signup_route_specs = (deps, options) => {
|
|
57
57
|
const { keyring, password } = deps;
|
|
58
|
-
const { session_options, ip_rate_limiter, signup_account_rate_limiter, signup_fail_floor_ms = DEFAULT_SIGNUP_FAIL_FLOOR_MS, signup_fail_jitter_ms = DEFAULT_SIGNUP_FAIL_JITTER_MS
|
|
58
|
+
const { session_options, ip_rate_limiter, signup_account_rate_limiter, signup_fail_floor_ms = DEFAULT_SIGNUP_FAIL_FLOOR_MS, signup_fail_jitter_ms = DEFAULT_SIGNUP_FAIL_JITTER_MS } = options;
|
|
59
59
|
return [
|
|
60
60
|
{
|
|
61
61
|
...create_signup_route_shape({
|
|
62
|
-
signup_account_rate_limited: signup_account_rate_limiter !== null
|
|
62
|
+
signup_account_rate_limited: signup_account_rate_limiter !== null
|
|
63
63
|
}),
|
|
64
64
|
handler: async (c, route) => {
|
|
65
65
|
// Per-IP rate limit check (before any work). 429 stays fast.
|
|
@@ -112,8 +112,8 @@ export const create_signup_route_specs = (deps, options) => {
|
|
|
112
112
|
reason,
|
|
113
113
|
...(invite && { invite_id: invite.id }),
|
|
114
114
|
...(email != null && { email }),
|
|
115
|
-
...(open_signup && { open_signup: true })
|
|
116
|
-
}
|
|
115
|
+
...(open_signup && { open_signup: true })
|
|
116
|
+
}
|
|
117
117
|
});
|
|
118
118
|
};
|
|
119
119
|
let result;
|
|
@@ -136,7 +136,7 @@ export const create_signup_route_specs = (deps, options) => {
|
|
|
136
136
|
const { account, actor } = await query_create_account_with_actor(tx_deps, {
|
|
137
137
|
username,
|
|
138
138
|
password_hash,
|
|
139
|
-
email
|
|
139
|
+
email
|
|
140
140
|
});
|
|
141
141
|
if (invite) {
|
|
142
142
|
// Guaranteed to succeed: FOR UPDATE held the row
|
|
@@ -150,7 +150,7 @@ export const create_signup_route_specs = (deps, options) => {
|
|
|
150
150
|
deps: tx_deps,
|
|
151
151
|
c,
|
|
152
152
|
account_id: account.id,
|
|
153
|
-
session_options
|
|
153
|
+
session_options
|
|
154
154
|
});
|
|
155
155
|
return { account, actor };
|
|
156
156
|
});
|
|
@@ -194,15 +194,15 @@ export const create_signup_route_specs = (deps, options) => {
|
|
|
194
194
|
event_type: 'signup',
|
|
195
195
|
account_id: result.account.id,
|
|
196
196
|
ip: get_client_ip(c),
|
|
197
|
-
metadata: invite ? { invite_id: invite.id, username } : { open_signup: true, username }
|
|
197
|
+
metadata: invite ? { invite_id: invite.id, username } : { open_signup: true, username }
|
|
198
198
|
});
|
|
199
199
|
return c.json({
|
|
200
200
|
ok: true,
|
|
201
201
|
account: { id: result.account.id, username: result.account.username },
|
|
202
|
-
actor: { id: result.actor.id }
|
|
202
|
+
actor: { id: result.actor.id }
|
|
203
203
|
});
|
|
204
|
-
}
|
|
205
|
-
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
206
|
];
|
|
207
207
|
};
|
|
208
208
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"standard_action_specs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/standard_action_specs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"standard_action_specs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/standard_action_specs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAK3E;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,EAAE,aAAa,CAAC,yBAAyB,CAI9E,CAAC"}
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
import { type AdminActionOptions } from './admin_actions.js';
|
|
22
22
|
import { type RoleGrantOfferActionOptions } from './role_grant_offer_actions.js';
|
|
23
23
|
import { type AccountActionOptions } from './account_actions.js';
|
|
24
|
-
import type {
|
|
24
|
+
import type { ActionFactoryDeps } from './deps.js';
|
|
25
25
|
import type { NotificationSender } from './role_grant_offer_notifications.js';
|
|
26
26
|
import type { RpcAction } from '../actions/action_rpc.js';
|
|
27
27
|
/**
|
|
@@ -38,12 +38,12 @@ export interface StandardRpcActionsOptions extends AdminActionOptions, RoleGrant
|
|
|
38
38
|
/**
|
|
39
39
|
* Dependencies for `create_standard_rpc_actions`.
|
|
40
40
|
*
|
|
41
|
-
* Stack-standard `
|
|
41
|
+
* Stack-standard `ActionFactoryDeps` (`log`, `audit`) plus an optional
|
|
42
42
|
* `notification_sender` consumed only by the role-grant-offer sub-factory
|
|
43
43
|
* for WS fan-out. Admin and account sub-factories ignore
|
|
44
44
|
* `notification_sender`.
|
|
45
45
|
*/
|
|
46
|
-
export interface StandardRpcActionsDeps extends
|
|
46
|
+
export interface StandardRpcActionsDeps extends ActionFactoryDeps {
|
|
47
47
|
notification_sender?: NotificationSender | null;
|
|
48
48
|
}
|
|
49
49
|
/**
|
|
@@ -54,7 +54,7 @@ export interface StandardRpcActionsDeps extends Pick<RouteFactoryDeps, 'log' | '
|
|
|
54
54
|
* and `create_account_actions(deps, {max_tokens})`. The shared `roles`
|
|
55
55
|
* option flows to admin + role-grant-offer.
|
|
56
56
|
*
|
|
57
|
-
* @param deps - `StandardRpcActionsDeps` (`log`, `audit` from `
|
|
57
|
+
* @param deps - `StandardRpcActionsDeps` (`log`, `audit` from `ActionFactoryDeps`; optional `notification_sender` for WS fan-out)
|
|
58
58
|
* @param options - role schema, role-grant-offer config, account config
|
|
59
59
|
* @returns RPC actions to pass as `rpc_endpoints` or spread into `create_rpc_endpoint`
|
|
60
60
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"standard_rpc_actions.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/standard_rpc_actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"standard_rpc_actions.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/standard_rpc_actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAwB,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACnF,OAAO,EAEN,KAAK,2BAA2B,EAChC,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAA0B,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACzF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAE1D;;;;;;;;GAQG;AACH,MAAM,WAAW,yBAChB,SAAQ,kBAAkB,EAAE,2BAA2B,EAAE,oBAAoB;CAAG;AAEjF;;;;;;;GAOG;AACH,MAAM,WAAW,sBAAuB,SAAQ,iBAAiB;IAChE,mBAAmB,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;CAChD;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,2BAA2B,GACvC,MAAM,sBAAsB,EAC5B,UAAS,yBAA8B,KACrC,KAAK,CAAC,SAAS,CAIjB,CAAC"}
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* @module
|
|
20
20
|
*/
|
|
21
21
|
import { create_admin_actions } from './admin_actions.js';
|
|
22
|
-
import { create_role_grant_offer_actions
|
|
22
|
+
import { create_role_grant_offer_actions } from './role_grant_offer_actions.js';
|
|
23
23
|
import { create_account_actions } from './account_actions.js';
|
|
24
24
|
/**
|
|
25
25
|
* Build the combined admin + role-grant-offer + account RPC action set.
|
|
@@ -29,12 +29,12 @@ import { create_account_actions } from './account_actions.js';
|
|
|
29
29
|
* and `create_account_actions(deps, {max_tokens})`. The shared `roles`
|
|
30
30
|
* option flows to admin + role-grant-offer.
|
|
31
31
|
*
|
|
32
|
-
* @param deps - `StandardRpcActionsDeps` (`log`, `audit` from `
|
|
32
|
+
* @param deps - `StandardRpcActionsDeps` (`log`, `audit` from `ActionFactoryDeps`; optional `notification_sender` for WS fan-out)
|
|
33
33
|
* @param options - role schema, role-grant-offer config, account config
|
|
34
34
|
* @returns RPC actions to pass as `rpc_endpoints` or spread into `create_rpc_endpoint`
|
|
35
35
|
*/
|
|
36
36
|
export const create_standard_rpc_actions = (deps, options = {}) => [
|
|
37
37
|
...create_admin_actions(deps, options),
|
|
38
38
|
...create_role_grant_offer_actions(deps, options),
|
|
39
|
-
...create_account_actions(deps, options)
|
|
39
|
+
...create_account_actions(deps, options)
|
|
40
40
|
];
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `TokenScope` — the per-credential authority narrowing stored on
|
|
3
|
+
* `api_token.scope`.
|
|
4
|
+
*
|
|
5
|
+
* Twin of the Rust spine's `fuz_auth::token_scope`. The stored document is the
|
|
6
|
+
* wire contract; both spines read the same `api_token.scope` JSONB, so the
|
|
7
|
+
* `kind` strings, the field names, and the version constant must match exactly.
|
|
8
|
+
*
|
|
9
|
+
* ## The whole vocabulary
|
|
10
|
+
*
|
|
11
|
+
* Two variants, and three rules:
|
|
12
|
+
*
|
|
13
|
+
* 1. **`full` must be spelled at mint.** `account_token_create` takes a required
|
|
14
|
+
* `scope`, the column is `NOT NULL`, and session / daemon-token credentials
|
|
15
|
+
* resolve to `full` by construction. There is no absent state — which is the
|
|
16
|
+
* whole point. The 2026-02 `scope` column stored `full` / `read` / `write`
|
|
17
|
+
* and nothing enforced them; the reason that was worse than nothing is that
|
|
18
|
+
* the absent/unenforced case was indistinguishable from a decision.
|
|
19
|
+
* 2. **`methods` denies every method it does not list.** An empty list is legal
|
|
20
|
+
* and renders the token inert for RPC — unlike an empty `credential_types`
|
|
21
|
+
* allowlist, which is rejected because it renders an *action* unreachable.
|
|
22
|
+
* 3. **A narrowed token is RPC-only.** `methods` denies every non-RPC spine
|
|
23
|
+
* surface outright — the db-admin browser, the bare-hash fact read, the
|
|
24
|
+
* audit SSE stream, and the WS upgrade. See `token_scope_admits_non_rpc`.
|
|
25
|
+
*
|
|
26
|
+
* @module
|
|
27
|
+
*/
|
|
28
|
+
import { z } from 'zod';
|
|
29
|
+
/** Current `TokenScope` document version. Must match the Rust `TOKEN_SCOPE_VERSION`. */
|
|
30
|
+
export declare const TOKEN_SCOPE_VERSION = 1;
|
|
31
|
+
/**
|
|
32
|
+
* Serialized-document cap. Matches the Rust `MAX_TOKEN_SCOPE_BYTES` and
|
|
33
|
+
* fuz_forge's `MAX_POLICY_BYTES`.
|
|
34
|
+
*/
|
|
35
|
+
export declare const MAX_TOKEN_SCOPE_BYTES: number;
|
|
36
|
+
/**
|
|
37
|
+
* The stored `api_token.scope` document.
|
|
38
|
+
*
|
|
39
|
+
* `grandfathered` is a fact about the *row* — the `api_token_scope` migration
|
|
40
|
+
* wrote it; no minter chose it — that only the token list cares about. The
|
|
41
|
+
* enforcement path never branches on it, which is what stops "grandfathered"
|
|
42
|
+
* from becoming a third authority level.
|
|
43
|
+
*
|
|
44
|
+
* Strict on both arms so a v2 document carrying a grant arm a v1 reader doesn't
|
|
45
|
+
* understand is refused rather than parsed as permissively-narrower-than-stored.
|
|
46
|
+
* The discriminated union also refuses the contradiction
|
|
47
|
+
* `{kind: 'full', methods: [...]}`.
|
|
48
|
+
*/
|
|
49
|
+
export declare const TokenScope: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
50
|
+
version: z.ZodLiteral<1>;
|
|
51
|
+
kind: z.ZodLiteral<"full">;
|
|
52
|
+
grandfathered: z.ZodOptional<z.ZodBoolean>;
|
|
53
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
54
|
+
version: z.ZodLiteral<1>;
|
|
55
|
+
kind: z.ZodLiteral<"methods">;
|
|
56
|
+
methods: z.ZodArray<z.ZodString>;
|
|
57
|
+
grandfathered: z.ZodOptional<z.ZodBoolean>;
|
|
58
|
+
}, z.core.$strict>], "kind">;
|
|
59
|
+
export type TokenScope = z.infer<typeof TokenScope>;
|
|
60
|
+
/**
|
|
61
|
+
* The `scope` input accepted by `account_token_create` — the stored shape minus
|
|
62
|
+
* the row-owned fields.
|
|
63
|
+
*
|
|
64
|
+
* A minter cannot set `version` or `grandfathered`: the first is stamped by
|
|
65
|
+
* `token_scope_full` / `token_scope_methods`, and the second is the migration's
|
|
66
|
+
* mark for tokens that predate scoping. Letting a caller forge `grandfathered`
|
|
67
|
+
* would turn a tracked debt into a laundered one.
|
|
68
|
+
*/
|
|
69
|
+
export declare const TokenScopeInput: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
70
|
+
kind: z.ZodLiteral<"full">;
|
|
71
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
72
|
+
kind: z.ZodLiteral<"methods">;
|
|
73
|
+
methods: z.ZodArray<z.ZodString>;
|
|
74
|
+
}, z.core.$strict>], "kind">;
|
|
75
|
+
export type TokenScopeInput = z.infer<typeof TokenScopeInput>;
|
|
76
|
+
/** A deliberately-minted full-authority scope. */
|
|
77
|
+
export declare const token_scope_full: () => TokenScope;
|
|
78
|
+
/** A narrowed scope over `methods`. */
|
|
79
|
+
export declare const token_scope_methods: (methods: Array<string>) => TokenScope;
|
|
80
|
+
/** Build the stored scope from a mint-time input. */
|
|
81
|
+
export declare const token_scope_from_input: (input: TokenScopeInput) => TokenScope;
|
|
82
|
+
/**
|
|
83
|
+
* Does `scope` admit dispatching `method`?
|
|
84
|
+
*
|
|
85
|
+
* Consulted by `perform_action` between the credential gate and the role gate.
|
|
86
|
+
*/
|
|
87
|
+
export declare const token_scope_admits_method: (scope: TokenScope, method: string) => boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Does `scope` admit a non-RPC spine surface?
|
|
90
|
+
*
|
|
91
|
+
* **Rule 3, and it is the load-bearing one.** A method-name allowlist alone
|
|
92
|
+
* would have been a false promise: the db-admin browser serves paginated rows of
|
|
93
|
+
* any `public` table (including `account.password_hash`, `auth_session`, and
|
|
94
|
+
* `api_token`) plus row `DELETE`, gated on a global role a bearer credential
|
|
95
|
+
* satisfies. A token whose UI badge read "scoped to `cell_get`" could still
|
|
96
|
+
* delete an account row.
|
|
97
|
+
*
|
|
98
|
+
* So a narrowed token reaches no non-RPC surface at all. Strictly more
|
|
99
|
+
* restrictive than naming each surface, no vocabulary to maintain, and one
|
|
100
|
+
* sentence a user can hold: *a scoped token is RPC-only*.
|
|
101
|
+
*/
|
|
102
|
+
export declare const token_scope_admits_non_rpc: (scope: TokenScope) => boolean;
|
|
103
|
+
/** Surfaces gated by rule 3. Capability strings match the Rust `TokenSurface`. */
|
|
104
|
+
export declare const TOKEN_SURFACE_CAPABILITIES: {
|
|
105
|
+
readonly db_admin: "surface:db_admin";
|
|
106
|
+
readonly fact_bare: "surface:fact_bare";
|
|
107
|
+
readonly audit_stream: "surface:audit_stream";
|
|
108
|
+
readonly ws_upgrade: "surface:ws_upgrade";
|
|
109
|
+
};
|
|
110
|
+
export type TokenSurface = keyof typeof TOKEN_SURFACE_CAPABILITIES;
|
|
111
|
+
/**
|
|
112
|
+
* Build the flat denial body a non-RPC surface returns when a narrowed token
|
|
113
|
+
* reaches it: `{error: 'token_scope_required', required_scope: 'surface:<name>'}`
|
|
114
|
+
* at 403.
|
|
115
|
+
*
|
|
116
|
+
* One shape for every surface, matching the Rust
|
|
117
|
+
* `token_scope_surface_denied_response`. These are REST-ish routes whose
|
|
118
|
+
* sibling denials are already flat, so the JSON-RPC envelope stays with the
|
|
119
|
+
* dispatcher's per-method gate and stops there.
|
|
120
|
+
*/
|
|
121
|
+
export declare const token_scope_surface_denied_body: (surface: TokenSurface) => {
|
|
122
|
+
error: "token_scope_required";
|
|
123
|
+
required_scope: string;
|
|
124
|
+
};
|
|
125
|
+
/** Stable label for the token list / UI. */
|
|
126
|
+
export declare const token_scope_label: (scope: TokenScope) => string;
|
|
127
|
+
/**
|
|
128
|
+
* Parse a stored document, enforcing the size cap and the schema.
|
|
129
|
+
*
|
|
130
|
+
* **Fail-closed**: returns `null` on an unreadable document, and every caller on
|
|
131
|
+
* the enforcement path treats `null` as "refuse the credential" rather than
|
|
132
|
+
* "allow everything". fuz_forge's hydrate path deliberately widens on a DB blip
|
|
133
|
+
* — safe there only because a role gate still applies. Here the scope *is* the
|
|
134
|
+
* gate, so widening on a parse failure would hand a narrowed token full
|
|
135
|
+
* authority exactly when something is already wrong.
|
|
136
|
+
*/
|
|
137
|
+
export declare const parse_token_scope: (raw: string) => TokenScope | null;
|
|
138
|
+
/**
|
|
139
|
+
* Serialize for storage, enforcing the size cap.
|
|
140
|
+
*
|
|
141
|
+
* Throws on an over-cap document — the mint path maps that to a 400, matching
|
|
142
|
+
* the Rust side's `TokenScopeError::TooLarge`.
|
|
143
|
+
*/
|
|
144
|
+
export declare const serialize_token_scope: (scope: TokenScope) => string;
|
|
145
|
+
/**
|
|
146
|
+
* Read a stored `api_token.scope` value back into a `TokenScope`, or `null`
|
|
147
|
+
* when the document is unreadable.
|
|
148
|
+
*
|
|
149
|
+
* The DB driver may hand `scope` back already-parsed (JSONB → object) or as
|
|
150
|
+
* text depending on backend, so both are normalized here rather than at each
|
|
151
|
+
* call site. Lives here rather than beside the queries so the pure scope module
|
|
152
|
+
* owns every parse — and so mocking the query module doesn't drag this along.
|
|
153
|
+
*/
|
|
154
|
+
export declare const parse_stored_token_scope: (value: unknown) => TokenScope | null;
|
|
155
|
+
//# sourceMappingURL=token_scope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token_scope.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/token_scope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,wFAAwF;AACxF,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAAW,CAAC;AAE9C;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,UAAU;;;;;;;;;4BAYrB,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAEpD;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe;;;;;4BAG1B,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAE9D,kDAAkD;AAClD,eAAO,MAAM,gBAAgB,QAAO,UAGlC,CAAC;AAEH,uCAAuC;AACvC,eAAO,MAAM,mBAAmB,GAAI,SAAS,KAAK,CAAC,MAAM,CAAC,KAAG,UAI3D,CAAC;AAEH,qDAAqD;AACrD,eAAO,MAAM,sBAAsB,GAAI,OAAO,eAAe,KAAG,UACgB,CAAC;AAEjF;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,GAAI,OAAO,UAAU,EAAE,QAAQ,MAAM,KAAG,OACtB,CAAC;AAEzD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,0BAA0B,GAAI,OAAO,UAAU,KAAG,OAAgC,CAAC;AAEhG,kFAAkF;AAClF,eAAO,MAAM,0BAA0B;;;;;CAK7B,CAAC;AACX,MAAM,MAAM,YAAY,GAAG,MAAM,OAAO,0BAA0B,CAAC;AAEnE;;;;;;;;;GASG;AACH,eAAO,MAAM,+BAA+B,GAC3C,SAAS,YAAY,KACnB;IAAE,KAAK,EAAE,sBAAsB,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAGxD,CAAC;AAEH,4CAA4C;AAC5C,eAAO,MAAM,iBAAiB,GAAI,OAAO,UAAU,KAAG,MAGrD,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,GAAI,KAAK,MAAM,KAAG,UAAU,GAAG,IAU5D,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,GAAI,OAAO,UAAU,KAAG,MAQzD,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,wBAAwB,GAAI,OAAO,OAAO,KAAG,UAAU,GAAG,IAQtE,CAAC"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `TokenScope` — the per-credential authority narrowing stored on
|
|
3
|
+
* `api_token.scope`.
|
|
4
|
+
*
|
|
5
|
+
* Twin of the Rust spine's `fuz_auth::token_scope`. The stored document is the
|
|
6
|
+
* wire contract; both spines read the same `api_token.scope` JSONB, so the
|
|
7
|
+
* `kind` strings, the field names, and the version constant must match exactly.
|
|
8
|
+
*
|
|
9
|
+
* ## The whole vocabulary
|
|
10
|
+
*
|
|
11
|
+
* Two variants, and three rules:
|
|
12
|
+
*
|
|
13
|
+
* 1. **`full` must be spelled at mint.** `account_token_create` takes a required
|
|
14
|
+
* `scope`, the column is `NOT NULL`, and session / daemon-token credentials
|
|
15
|
+
* resolve to `full` by construction. There is no absent state — which is the
|
|
16
|
+
* whole point. The 2026-02 `scope` column stored `full` / `read` / `write`
|
|
17
|
+
* and nothing enforced them; the reason that was worse than nothing is that
|
|
18
|
+
* the absent/unenforced case was indistinguishable from a decision.
|
|
19
|
+
* 2. **`methods` denies every method it does not list.** An empty list is legal
|
|
20
|
+
* and renders the token inert for RPC — unlike an empty `credential_types`
|
|
21
|
+
* allowlist, which is rejected because it renders an *action* unreachable.
|
|
22
|
+
* 3. **A narrowed token is RPC-only.** `methods` denies every non-RPC spine
|
|
23
|
+
* surface outright — the db-admin browser, the bare-hash fact read, the
|
|
24
|
+
* audit SSE stream, and the WS upgrade. See `token_scope_admits_non_rpc`.
|
|
25
|
+
*
|
|
26
|
+
* @module
|
|
27
|
+
*/
|
|
28
|
+
import { z } from 'zod';
|
|
29
|
+
/** Current `TokenScope` document version. Must match the Rust `TOKEN_SCOPE_VERSION`. */
|
|
30
|
+
export const TOKEN_SCOPE_VERSION = 1;
|
|
31
|
+
/**
|
|
32
|
+
* Serialized-document cap. Matches the Rust `MAX_TOKEN_SCOPE_BYTES` and
|
|
33
|
+
* fuz_forge's `MAX_POLICY_BYTES`.
|
|
34
|
+
*/
|
|
35
|
+
export const MAX_TOKEN_SCOPE_BYTES = 4 * 1024;
|
|
36
|
+
/**
|
|
37
|
+
* The stored `api_token.scope` document.
|
|
38
|
+
*
|
|
39
|
+
* `grandfathered` is a fact about the *row* — the `api_token_scope` migration
|
|
40
|
+
* wrote it; no minter chose it — that only the token list cares about. The
|
|
41
|
+
* enforcement path never branches on it, which is what stops "grandfathered"
|
|
42
|
+
* from becoming a third authority level.
|
|
43
|
+
*
|
|
44
|
+
* Strict on both arms so a v2 document carrying a grant arm a v1 reader doesn't
|
|
45
|
+
* understand is refused rather than parsed as permissively-narrower-than-stored.
|
|
46
|
+
* The discriminated union also refuses the contradiction
|
|
47
|
+
* `{kind: 'full', methods: [...]}`.
|
|
48
|
+
*/
|
|
49
|
+
export const TokenScope = z.discriminatedUnion('kind', [
|
|
50
|
+
z.strictObject({
|
|
51
|
+
version: z.literal(TOKEN_SCOPE_VERSION),
|
|
52
|
+
kind: z.literal('full'),
|
|
53
|
+
grandfathered: z.boolean().optional()
|
|
54
|
+
}),
|
|
55
|
+
z.strictObject({
|
|
56
|
+
version: z.literal(TOKEN_SCOPE_VERSION),
|
|
57
|
+
kind: z.literal('methods'),
|
|
58
|
+
methods: z.array(z.string()),
|
|
59
|
+
grandfathered: z.boolean().optional()
|
|
60
|
+
})
|
|
61
|
+
]);
|
|
62
|
+
/**
|
|
63
|
+
* The `scope` input accepted by `account_token_create` — the stored shape minus
|
|
64
|
+
* the row-owned fields.
|
|
65
|
+
*
|
|
66
|
+
* A minter cannot set `version` or `grandfathered`: the first is stamped by
|
|
67
|
+
* `token_scope_full` / `token_scope_methods`, and the second is the migration's
|
|
68
|
+
* mark for tokens that predate scoping. Letting a caller forge `grandfathered`
|
|
69
|
+
* would turn a tracked debt into a laundered one.
|
|
70
|
+
*/
|
|
71
|
+
export const TokenScopeInput = z.discriminatedUnion('kind', [
|
|
72
|
+
z.strictObject({ kind: z.literal('full') }),
|
|
73
|
+
z.strictObject({ kind: z.literal('methods'), methods: z.array(z.string()) })
|
|
74
|
+
]);
|
|
75
|
+
/** A deliberately-minted full-authority scope. */
|
|
76
|
+
export const token_scope_full = () => ({
|
|
77
|
+
version: TOKEN_SCOPE_VERSION,
|
|
78
|
+
kind: 'full'
|
|
79
|
+
});
|
|
80
|
+
/** A narrowed scope over `methods`. */
|
|
81
|
+
export const token_scope_methods = (methods) => ({
|
|
82
|
+
version: TOKEN_SCOPE_VERSION,
|
|
83
|
+
kind: 'methods',
|
|
84
|
+
methods
|
|
85
|
+
});
|
|
86
|
+
/** Build the stored scope from a mint-time input. */
|
|
87
|
+
export const token_scope_from_input = (input) => input.kind === 'full' ? token_scope_full() : token_scope_methods(input.methods);
|
|
88
|
+
/**
|
|
89
|
+
* Does `scope` admit dispatching `method`?
|
|
90
|
+
*
|
|
91
|
+
* Consulted by `perform_action` between the credential gate and the role gate.
|
|
92
|
+
*/
|
|
93
|
+
export const token_scope_admits_method = (scope, method) => scope.kind === 'full' || scope.methods.includes(method);
|
|
94
|
+
/**
|
|
95
|
+
* Does `scope` admit a non-RPC spine surface?
|
|
96
|
+
*
|
|
97
|
+
* **Rule 3, and it is the load-bearing one.** A method-name allowlist alone
|
|
98
|
+
* would have been a false promise: the db-admin browser serves paginated rows of
|
|
99
|
+
* any `public` table (including `account.password_hash`, `auth_session`, and
|
|
100
|
+
* `api_token`) plus row `DELETE`, gated on a global role a bearer credential
|
|
101
|
+
* satisfies. A token whose UI badge read "scoped to `cell_get`" could still
|
|
102
|
+
* delete an account row.
|
|
103
|
+
*
|
|
104
|
+
* So a narrowed token reaches no non-RPC surface at all. Strictly more
|
|
105
|
+
* restrictive than naming each surface, no vocabulary to maintain, and one
|
|
106
|
+
* sentence a user can hold: *a scoped token is RPC-only*.
|
|
107
|
+
*/
|
|
108
|
+
export const token_scope_admits_non_rpc = (scope) => scope.kind === 'full';
|
|
109
|
+
/** Surfaces gated by rule 3. Capability strings match the Rust `TokenSurface`. */
|
|
110
|
+
export const TOKEN_SURFACE_CAPABILITIES = {
|
|
111
|
+
db_admin: 'surface:db_admin',
|
|
112
|
+
fact_bare: 'surface:fact_bare',
|
|
113
|
+
audit_stream: 'surface:audit_stream',
|
|
114
|
+
ws_upgrade: 'surface:ws_upgrade'
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* Build the flat denial body a non-RPC surface returns when a narrowed token
|
|
118
|
+
* reaches it: `{error: 'token_scope_required', required_scope: 'surface:<name>'}`
|
|
119
|
+
* at 403.
|
|
120
|
+
*
|
|
121
|
+
* One shape for every surface, matching the Rust
|
|
122
|
+
* `token_scope_surface_denied_response`. These are REST-ish routes whose
|
|
123
|
+
* sibling denials are already flat, so the JSON-RPC envelope stays with the
|
|
124
|
+
* dispatcher's per-method gate and stops there.
|
|
125
|
+
*/
|
|
126
|
+
export const token_scope_surface_denied_body = (surface) => ({
|
|
127
|
+
error: 'token_scope_required',
|
|
128
|
+
required_scope: TOKEN_SURFACE_CAPABILITIES[surface]
|
|
129
|
+
});
|
|
130
|
+
/** Stable label for the token list / UI. */
|
|
131
|
+
export const token_scope_label = (scope) => {
|
|
132
|
+
if (scope.kind === 'full')
|
|
133
|
+
return scope.grandfathered ? 'full (grandfathered)' : 'full';
|
|
134
|
+
return `${scope.methods.length} methods`;
|
|
135
|
+
};
|
|
136
|
+
/**
|
|
137
|
+
* Parse a stored document, enforcing the size cap and the schema.
|
|
138
|
+
*
|
|
139
|
+
* **Fail-closed**: returns `null` on an unreadable document, and every caller on
|
|
140
|
+
* the enforcement path treats `null` as "refuse the credential" rather than
|
|
141
|
+
* "allow everything". fuz_forge's hydrate path deliberately widens on a DB blip
|
|
142
|
+
* — safe there only because a role gate still applies. Here the scope *is* the
|
|
143
|
+
* gate, so widening on a parse failure would hand a narrowed token full
|
|
144
|
+
* authority exactly when something is already wrong.
|
|
145
|
+
*/
|
|
146
|
+
export const parse_token_scope = (raw) => {
|
|
147
|
+
if (raw.length > MAX_TOKEN_SCOPE_BYTES)
|
|
148
|
+
return null;
|
|
149
|
+
let value;
|
|
150
|
+
try {
|
|
151
|
+
value = JSON.parse(raw);
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
const parsed = TokenScope.safeParse(value);
|
|
157
|
+
return parsed.success ? parsed.data : null;
|
|
158
|
+
};
|
|
159
|
+
/**
|
|
160
|
+
* Serialize for storage, enforcing the size cap.
|
|
161
|
+
*
|
|
162
|
+
* Throws on an over-cap document — the mint path maps that to a 400, matching
|
|
163
|
+
* the Rust side's `TokenScopeError::TooLarge`.
|
|
164
|
+
*/
|
|
165
|
+
export const serialize_token_scope = (scope) => {
|
|
166
|
+
const json = JSON.stringify(scope);
|
|
167
|
+
if (json.length > MAX_TOKEN_SCOPE_BYTES) {
|
|
168
|
+
throw new Error(`token scope document is ${json.length} bytes, exceeding the ${MAX_TOKEN_SCOPE_BYTES} byte cap`);
|
|
169
|
+
}
|
|
170
|
+
return json;
|
|
171
|
+
};
|
|
172
|
+
/**
|
|
173
|
+
* Read a stored `api_token.scope` value back into a `TokenScope`, or `null`
|
|
174
|
+
* when the document is unreadable.
|
|
175
|
+
*
|
|
176
|
+
* The DB driver may hand `scope` back already-parsed (JSONB → object) or as
|
|
177
|
+
* text depending on backend, so both are normalized here rather than at each
|
|
178
|
+
* call site. Lives here rather than beside the queries so the pure scope module
|
|
179
|
+
* owns every parse — and so mocking the query module doesn't drag this along.
|
|
180
|
+
*/
|
|
181
|
+
export const parse_stored_token_scope = (value) => {
|
|
182
|
+
if (typeof value === 'string')
|
|
183
|
+
return parse_token_scope(value);
|
|
184
|
+
// `JSON.stringify(undefined)` returns `undefined`, not a string — so a row
|
|
185
|
+
// missing the column entirely must be caught here rather than reaching
|
|
186
|
+
// `parse_token_scope` and throwing on `.length`. Absent is *unreadable*,
|
|
187
|
+
// which is fail-closed: the caller refuses the credential.
|
|
188
|
+
const json = JSON.stringify(value);
|
|
189
|
+
return json === undefined ? null : parse_token_scope(json);
|
|
190
|
+
};
|