@fuzdev/fuz_app 0.55.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 +211 -155
- 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 +19 -0
- package/dist/actions/action_codegen.d.ts.map +1 -1
- package/dist/actions/action_codegen.js +20 -14
- 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 +110 -44
- package/dist/actions/action_rpc.d.ts.map +1 -1
- package/dist/actions/action_rpc.js +92 -287
- 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 +44 -38
- 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 +2 -10
- package/dist/actions/register_ws_endpoint.d.ts.map +1 -1
- package/dist/actions/register_ws_endpoint.js +32 -10
- 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 +673 -442
- 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 +8 -14
- package/dist/auth/account_actions.d.ts.map +1 -1
- package/dist/auth/account_actions.js +26 -32
- package/dist/auth/account_queries.d.ts +46 -13
- package/dist/auth/account_queries.d.ts.map +1 -1
- package/dist/auth/account_queries.js +73 -33
- package/dist/auth/account_routes.d.ts +4 -3
- package/dist/auth/account_routes.d.ts.map +1 -1
- package/dist/auth/account_routes.js +58 -33
- package/dist/auth/account_schema.d.ts +46 -54
- package/dist/auth/account_schema.d.ts.map +1 -1
- package/dist/auth/account_schema.js +21 -48
- package/dist/auth/admin_action_specs.d.ts +55 -21
- package/dist/auth/admin_action_specs.d.ts.map +1 -1
- package/dist/auth/admin_action_specs.js +42 -26
- package/dist/auth/admin_actions.d.ts +14 -21
- package/dist/auth/admin_actions.d.ts.map +1 -1
- package/dist/auth/admin_actions.js +47 -44
- 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 -87
- package/dist/auth/audit_log_queries.d.ts.map +1 -1
- package/dist/auth/audit_log_queries.js +17 -96
- 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 +48 -42
- package/dist/auth/audit_log_schema.d.ts.map +1 -1
- package/dist/auth/audit_log_schema.js +56 -43
- 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/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 -47
- 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 +1 -1
- package/dist/auth/daemon_token_middleware.js +3 -3
- 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 -32
- 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 +5 -2
- package/dist/auth/migrations.d.ts +22 -7
- package/dist/auth/migrations.d.ts.map +1 -1
- package/dist/auth/migrations.js +64 -25
- package/dist/auth/request_context.d.ts +157 -170
- package/dist/auth/request_context.d.ts.map +1 -1
- package/dist/auth/request_context.js +224 -268
- package/dist/auth/{permit_offer_action_specs.d.ts → role_grant_offer_action_specs.d.ts} +130 -100
- 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/{permit_offer_actions.js → role_grant_offer_actions.js} +153 -140
- package/dist/auth/{permit_offer_notifications.d.ts → role_grant_offer_notifications.d.ts} +80 -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/{permit_offer_queries.d.ts → role_grant_offer_queries.d.ts} +64 -64
- package/dist/auth/role_grant_offer_queries.d.ts.map +1 -0
- package/dist/auth/{permit_offer_queries.js → role_grant_offer_queries.js} +136 -123
- 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} +55 -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 +4 -1
- package/dist/auth/self_service_role_action_specs.d.ts.map +1 -1
- package/dist/auth/self_service_role_action_specs.js +2 -2
- package/dist/auth/self_service_role_actions.d.ts +35 -29
- package/dist/auth/self_service_role_actions.d.ts.map +1 -1
- package/dist/auth/self_service_role_actions.js +58 -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 +1 -1
- package/dist/db/migrate.js +1 -1
- package/dist/dev/setup.d.ts +2 -2
- package/dist/dev/setup.d.ts.map +1 -1
- package/dist/dev/setup.js +4 -4
- package/dist/env/load.d.ts +1 -1
- package/dist/env/load.js +1 -1
- package/dist/hono_context.d.ts +27 -45
- package/dist/hono_context.d.ts.map +1 -1
- package/dist/hono_context.js +14 -28
- package/dist/http/CLAUDE.md +235 -121
- 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 +56 -34
- package/dist/http/error_schemas.d.ts.map +1 -1
- package/dist/http/error_schemas.js +63 -28
- 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 +89 -75
- package/dist/http/route_spec.d.ts.map +1 -1
- package/dist/http/route_spec.js +54 -72
- package/dist/http/schema_helpers.d.ts +3 -14
- package/dist/http/schema_helpers.d.ts.map +1 -1
- package/dist/http/schema_helpers.js +2 -14
- package/dist/http/surface.d.ts +2 -10
- package/dist/http/surface.d.ts.map +1 -1
- package/dist/http/surface.js +3 -4
- 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 +35 -40
- package/dist/server/validate_nginx.d.ts +1 -1
- package/dist/server/validate_nginx.js +1 -1
- package/dist/testing/CLAUDE.md +50 -38
- 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 +87 -85
- 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 +16 -15
- 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 +36 -36
- 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 +22 -19
- 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 +8 -7
- package/dist/testing/entities.d.ts.map +1 -1
- package/dist/testing/entities.js +21 -18
- package/dist/testing/integration.d.ts.map +1 -1
- package/dist/testing/integration.js +13 -14
- package/dist/testing/integration_helpers.d.ts +4 -4
- package/dist/testing/integration_helpers.d.ts.map +1 -1
- package/dist/testing/integration_helpers.js +20 -18
- package/dist/testing/middleware.d.ts +4 -4
- package/dist/testing/middleware.d.ts.map +1 -1
- package/dist/testing/middleware.js +12 -11
- package/dist/testing/rpc_attack_surface.d.ts.map +1 -1
- package/dist/testing/rpc_attack_surface.js +40 -24
- 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 +19 -11
- 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 +60 -60
- package/dist/ui/{PermitOfferForm.svelte → RoleGrantOfferForm.svelte} +27 -26
- package/dist/ui/{PermitOfferForm.svelte.d.ts → RoleGrantOfferForm.svelte.d.ts} +7 -7
- 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 +18 -18
- package/dist/ui/admin_accounts_state.svelte.d.ts.map +1 -1
- package/dist/ui/admin_accounts_state.svelte.js +16 -16
- 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} +30 -30
- 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} +18 -18
- 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 -258
- 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_notifications.d.ts.map +0 -1
- package/dist/auth/permit_offer_notifications.js +0 -182
- package/dist/auth/permit_offer_queries.d.ts.map +0 -1
- package/dist/auth/permit_offer_schema.d.ts +0 -125
- package/dist/auth/permit_offer_schema.d.ts.map +0 -1
- package/dist/auth/permit_queries.d.ts +0 -222
- package/dist/auth/permit_queries.d.ts.map +0 -1
- package/dist/auth/permit_queries.js +0 -305
- 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 -27
- package/dist/auth/route_guards.d.ts.map +0 -1
- package/dist/auth/route_guards.js +0 -38
- 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.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
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* @module
|
|
13
13
|
*/
|
|
14
14
|
import { z } from 'zod';
|
|
15
|
-
import type
|
|
15
|
+
import { type RouteAuth } from './auth_shape.js';
|
|
16
16
|
/** Request body failed Zod validation. */
|
|
17
17
|
export declare const ERROR_INVALID_REQUEST_BODY: "invalid_request_body";
|
|
18
18
|
/** Request body is not valid JSON or not an object. */
|
|
@@ -25,6 +25,16 @@ export declare const ERROR_INVALID_QUERY_PARAMS: "invalid_query_params";
|
|
|
25
25
|
export declare const ERROR_AUTHENTICATION_REQUIRED: "authentication_required";
|
|
26
26
|
/** Authenticated but missing required role. */
|
|
27
27
|
export declare const ERROR_INSUFFICIENT_PERMISSIONS: "insufficient_permissions";
|
|
28
|
+
/**
|
|
29
|
+
* Route requires a credential type the request didn't arrive on.
|
|
30
|
+
* Symmetric with `ERROR_INSUFFICIENT_PERMISSIONS` + `required_roles`:
|
|
31
|
+
* the body carries `required_credential_types: ReadonlyArray<string>`
|
|
32
|
+
* — what the route demanded, not what arrived. Today the only
|
|
33
|
+
* credential gate is keeper (`['daemon_token']`); future gates
|
|
34
|
+
* (`agent_token`, `group_actor_token`) reuse the same literal and
|
|
35
|
+
* label themselves through the array.
|
|
36
|
+
*/
|
|
37
|
+
export declare const ERROR_CREDENTIAL_TYPE_REQUIRED: "credential_type_required";
|
|
28
38
|
/** Rate limiter rejected the request. */
|
|
29
39
|
export declare const ERROR_RATE_LIMIT_EXCEEDED: "rate_limit_exceeded";
|
|
30
40
|
/** Username or password is wrong (intentionally vague for enumeration prevention). */
|
|
@@ -74,8 +84,6 @@ export declare const ERROR_NO_ACTORS_ON_ACCOUNT: "no_actors_on_account";
|
|
|
74
84
|
* `ERROR_NO_ACTORS_ON_ACCOUNT` (the actor list enumerated empty).
|
|
75
85
|
*/
|
|
76
86
|
export declare const ERROR_ACCOUNT_VANISHED: "account_vanished";
|
|
77
|
-
/** Keeper routes require daemon_token credential type. */
|
|
78
|
-
export declare const ERROR_KEEPER_REQUIRES_DAEMON_TOKEN: "keeper_requires_daemon_token";
|
|
79
87
|
/** Daemon token header present but malformed or not matching current/previous token. */
|
|
80
88
|
export declare const ERROR_INVALID_DAEMON_TOKEN: "invalid_daemon_token";
|
|
81
89
|
/** Daemon token valid but keeper account not yet resolved (pre-bootstrap). */
|
|
@@ -104,8 +112,8 @@ export declare const ERROR_INVITE_ACCOUNT_EXISTS_USERNAME: "invite_account_exist
|
|
|
104
112
|
export declare const ERROR_INVITE_ACCOUNT_EXISTS_EMAIL: "invite_account_exists_email";
|
|
105
113
|
/** Admin tried to grant a role that is not web-grantable. */
|
|
106
114
|
export declare const ERROR_ROLE_NOT_WEB_GRANTABLE: "role_not_web_grantable";
|
|
107
|
-
/**
|
|
108
|
-
export declare const
|
|
115
|
+
/** Role grant ID not found or not owned by the target actor. */
|
|
116
|
+
export declare const ERROR_ROLE_GRANT_NOT_FOUND: "role_grant_not_found";
|
|
109
117
|
/** Query parameter `event_type` is not a valid audit event type. */
|
|
110
118
|
export declare const ERROR_INVALID_EVENT_TYPE: "invalid_event_type";
|
|
111
119
|
/** DELETE blocked by a foreign key constraint. */
|
|
@@ -137,18 +145,37 @@ export declare const ValidationError: z.ZodObject<{
|
|
|
137
145
|
}, z.core.$loose>>;
|
|
138
146
|
}, z.core.$loose>;
|
|
139
147
|
export type ValidationError = z.infer<typeof ValidationError>;
|
|
140
|
-
/**
|
|
148
|
+
/**
|
|
149
|
+
* Permission error — returned by `require_role()` and the dispatcher's
|
|
150
|
+
* post-authorization role gate when the actor's role_grants don't include any
|
|
151
|
+
* of the route's `auth.roles`.
|
|
152
|
+
*
|
|
153
|
+
* `required_roles` carries the full disjunction the route declared
|
|
154
|
+
* (`auth.roles` from the new flat-record shape). Single-role specs surface
|
|
155
|
+
* as a one-element array; multi-role disjunctions show every admittable
|
|
156
|
+
* role so clients can render targeted copy ("requires admin or steward").
|
|
157
|
+
*/
|
|
141
158
|
export declare const PermissionError: z.ZodObject<{
|
|
142
159
|
error: z.ZodLiteral<"insufficient_permissions">;
|
|
143
|
-
|
|
160
|
+
required_roles: z.ZodReadonly<z.ZodArray<z.ZodString>>;
|
|
144
161
|
}, z.core.$loose>;
|
|
145
162
|
export type PermissionError = z.infer<typeof PermissionError>;
|
|
146
|
-
/**
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
163
|
+
/**
|
|
164
|
+
* Credential-type error — returned by the dispatcher's post-authorization
|
|
165
|
+
* credential gate (and the `require_credential_types` REST middleware) when
|
|
166
|
+
* the request's credential type isn't in the route's
|
|
167
|
+
* `auth.credential_types` allowlist.
|
|
168
|
+
*
|
|
169
|
+
* `required_credential_types` carries what the route declared
|
|
170
|
+
* (`['daemon_token']` for keeper; future gates carry their own labels).
|
|
171
|
+
* Symmetric with `PermissionError`'s `required_roles`: clients see what
|
|
172
|
+
* the route demanded, not what their credential is.
|
|
173
|
+
*/
|
|
174
|
+
export declare const CredentialTypeRequiredError: z.ZodObject<{
|
|
175
|
+
error: z.ZodLiteral<"credential_type_required">;
|
|
176
|
+
required_credential_types: z.ZodReadonly<z.ZodArray<z.ZodString>>;
|
|
150
177
|
}, z.core.$loose>;
|
|
151
|
-
export type
|
|
178
|
+
export type CredentialTypeRequiredError = z.infer<typeof CredentialTypeRequiredError>;
|
|
152
179
|
/** Rate limit error — returned when a rate limiter rejects the request. */
|
|
153
180
|
export declare const RateLimitError: z.ZodObject<{
|
|
154
181
|
error: z.ZodLiteral<"rate_limit_exceeded">;
|
|
@@ -169,7 +196,7 @@ export type ForeignKeyError = z.infer<typeof ForeignKeyError>;
|
|
|
169
196
|
* Authorization-phase failure shapes. Surfaced when the dispatcher's
|
|
170
197
|
* `apply_authorization_phase` rejects a request before the handler runs —
|
|
171
198
|
* the route is acting-aware (input declares `acting?: ActingActor` or
|
|
172
|
-
* auth requires
|
|
199
|
+
* auth requires role_grants), but actor resolution failed.
|
|
173
200
|
*
|
|
174
201
|
* 400: `actor_required` (with `available[]`) for unspecified-actor on
|
|
175
202
|
* a multi-actor account; `actor_not_on_account` for a supplied actor
|
|
@@ -180,7 +207,7 @@ export type ForeignKeyError = z.infer<typeof ForeignKeyError>;
|
|
|
180
207
|
* race (account/actor row deleted between credential validation and
|
|
181
208
|
* the dispatcher's follow-up read).
|
|
182
209
|
*
|
|
183
|
-
* Used by `derive_error_schemas` when `
|
|
210
|
+
* Used by `derive_error_schemas` when `auth.actor !== 'none'` so the
|
|
184
211
|
* merged error surface matches what the dispatcher actually emits.
|
|
185
212
|
*/
|
|
186
213
|
export declare const ActorRequiredError: z.ZodObject<{
|
|
@@ -232,24 +259,20 @@ export type RateLimitKey = z.infer<typeof RateLimitKey>;
|
|
|
232
259
|
* Route handlers can declare additional error schemas via `RouteSpec.errors`;
|
|
233
260
|
* explicit entries override auto-derived ones for the same status code.
|
|
234
261
|
*
|
|
235
|
-
* Derivation rules:
|
|
236
|
-
* - **Has input
|
|
237
|
-
* -
|
|
238
|
-
* -
|
|
239
|
-
*
|
|
240
|
-
* -
|
|
241
|
-
* -
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
* `
|
|
247
|
-
*
|
|
248
|
-
*
|
|
249
|
-
* `acting_aware` is computed at the merge call site (it requires inspecting
|
|
250
|
-
* the input schema for `acting?: ActingActor`, which lives in `auth/`). This
|
|
251
|
-
* keeps `http/` auth-agnostic — the per-route flag flows in via the optional
|
|
252
|
-
* `is_acting_aware` callback on `apply_route_specs` / `generate_app_surface`.
|
|
262
|
+
* Derivation rules under the new flat-record auth shape:
|
|
263
|
+
* - **Has input / params / query schema**: 400 (`ValidationError`).
|
|
264
|
+
* - **`auth.account === 'required'`** or **`auth.actor === 'required'`**: 401
|
|
265
|
+
* (`ApiError`) — pre-validation 401 fires when the credential isn't there.
|
|
266
|
+
* `'optional'` does not derive 401.
|
|
267
|
+
* - **`auth.roles?.length`**: 403 (`PermissionError` carrying `required_roles`).
|
|
268
|
+
* - **`auth.credential_types?.length`**: 403 (`CredentialTypeRequiredError`
|
|
269
|
+
* carrying `required_credential_types` — symmetric with `PermissionError`).
|
|
270
|
+
* Today the only credential gate is keeper; future gates reuse the literal.
|
|
271
|
+
* - **`auth.actor !== 'none'`** (`'optional'` or `'required'`): extends 400
|
|
272
|
+
* with `ActorRequiredError` / `ActorNotOnAccountError` and adds 500 union
|
|
273
|
+
* of `NoActorsOnAccountError` / `AccountVanishedError`. The dispatcher's
|
|
274
|
+
* authorization phase emits these whenever it tries to resolve an actor.
|
|
275
|
+
* - **rate_limit**: 429 (`RateLimitError` with `retry_after`).
|
|
253
276
|
*/
|
|
254
277
|
export interface DeriveErrorSchemasOptions {
|
|
255
278
|
auth: RouteAuth;
|
|
@@ -257,7 +280,6 @@ export interface DeriveErrorSchemasOptions {
|
|
|
257
280
|
has_params?: boolean;
|
|
258
281
|
has_query?: boolean;
|
|
259
282
|
rate_limit?: RateLimitKey;
|
|
260
|
-
acting_aware?: boolean;
|
|
261
283
|
}
|
|
262
|
-
export declare const derive_error_schemas: ({ auth, has_input, has_params, has_query, rate_limit,
|
|
284
|
+
export declare const derive_error_schemas: ({ auth, has_input, has_params, has_query, rate_limit, }: DeriveErrorSchemasOptions) => RouteErrorSchemas;
|
|
263
285
|
//# sourceMappingURL=error_schemas.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error_schemas.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/error_schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"error_schemas.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/error_schemas.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* @module
|
|
13
13
|
*/
|
|
14
14
|
import { z } from 'zod';
|
|
15
|
+
import { needs_actor } from './auth_shape.js';
|
|
15
16
|
// --- Core: Validation (auto-derived by route spec middleware) ---
|
|
16
17
|
/** Request body failed Zod validation. */
|
|
17
18
|
export const ERROR_INVALID_REQUEST_BODY = 'invalid_request_body';
|
|
@@ -26,6 +27,16 @@ export const ERROR_INVALID_QUERY_PARAMS = 'invalid_query_params';
|
|
|
26
27
|
export const ERROR_AUTHENTICATION_REQUIRED = 'authentication_required';
|
|
27
28
|
/** Authenticated but missing required role. */
|
|
28
29
|
export const ERROR_INSUFFICIENT_PERMISSIONS = 'insufficient_permissions';
|
|
30
|
+
/**
|
|
31
|
+
* Route requires a credential type the request didn't arrive on.
|
|
32
|
+
* Symmetric with `ERROR_INSUFFICIENT_PERMISSIONS` + `required_roles`:
|
|
33
|
+
* the body carries `required_credential_types: ReadonlyArray<string>`
|
|
34
|
+
* — what the route demanded, not what arrived. Today the only
|
|
35
|
+
* credential gate is keeper (`['daemon_token']`); future gates
|
|
36
|
+
* (`agent_token`, `group_actor_token`) reuse the same literal and
|
|
37
|
+
* label themselves through the array.
|
|
38
|
+
*/
|
|
39
|
+
export const ERROR_CREDENTIAL_TYPE_REQUIRED = 'credential_type_required';
|
|
29
40
|
/** Rate limiter rejected the request. */
|
|
30
41
|
export const ERROR_RATE_LIMIT_EXCEEDED = 'rate_limit_exceeded';
|
|
31
42
|
/** Username or password is wrong (intentionally vague for enumeration prevention). */
|
|
@@ -77,8 +88,6 @@ export const ERROR_NO_ACTORS_ON_ACCOUNT = 'no_actors_on_account';
|
|
|
77
88
|
*/
|
|
78
89
|
export const ERROR_ACCOUNT_VANISHED = 'account_vanished';
|
|
79
90
|
// --- Keeper / daemon token ---
|
|
80
|
-
/** Keeper routes require daemon_token credential type. */
|
|
81
|
-
export const ERROR_KEEPER_REQUIRES_DAEMON_TOKEN = 'keeper_requires_daemon_token';
|
|
82
91
|
/** Daemon token header present but malformed or not matching current/previous token. */
|
|
83
92
|
export const ERROR_INVALID_DAEMON_TOKEN = 'invalid_daemon_token';
|
|
84
93
|
/** Daemon token valid but keeper account not yet resolved (pre-bootstrap). */
|
|
@@ -110,8 +119,8 @@ export const ERROR_INVITE_ACCOUNT_EXISTS_EMAIL = 'invite_account_exists_email';
|
|
|
110
119
|
// --- Admin routes ---
|
|
111
120
|
/** Admin tried to grant a role that is not web-grantable. */
|
|
112
121
|
export const ERROR_ROLE_NOT_WEB_GRANTABLE = 'role_not_web_grantable';
|
|
113
|
-
/**
|
|
114
|
-
export const
|
|
122
|
+
/** Role grant ID not found or not owned by the target actor. */
|
|
123
|
+
export const ERROR_ROLE_GRANT_NOT_FOUND = 'role_grant_not_found';
|
|
115
124
|
/** Query parameter `event_type` is not a valid audit event type. */
|
|
116
125
|
export const ERROR_INVALID_EVENT_TYPE = 'invalid_event_type';
|
|
117
126
|
// --- DB table browser ---
|
|
@@ -142,15 +151,34 @@ export const ValidationError = z.looseObject({
|
|
|
142
151
|
path: z.array(z.union([z.string(), z.number()])),
|
|
143
152
|
})),
|
|
144
153
|
});
|
|
145
|
-
/**
|
|
154
|
+
/**
|
|
155
|
+
* Permission error — returned by `require_role()` and the dispatcher's
|
|
156
|
+
* post-authorization role gate when the actor's role_grants don't include any
|
|
157
|
+
* of the route's `auth.roles`.
|
|
158
|
+
*
|
|
159
|
+
* `required_roles` carries the full disjunction the route declared
|
|
160
|
+
* (`auth.roles` from the new flat-record shape). Single-role specs surface
|
|
161
|
+
* as a one-element array; multi-role disjunctions show every admittable
|
|
162
|
+
* role so clients can render targeted copy ("requires admin or steward").
|
|
163
|
+
*/
|
|
146
164
|
export const PermissionError = z.looseObject({
|
|
147
165
|
error: z.literal(ERROR_INSUFFICIENT_PERMISSIONS),
|
|
148
|
-
|
|
166
|
+
required_roles: z.array(z.string()).readonly(),
|
|
149
167
|
});
|
|
150
|
-
/**
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
168
|
+
/**
|
|
169
|
+
* Credential-type error — returned by the dispatcher's post-authorization
|
|
170
|
+
* credential gate (and the `require_credential_types` REST middleware) when
|
|
171
|
+
* the request's credential type isn't in the route's
|
|
172
|
+
* `auth.credential_types` allowlist.
|
|
173
|
+
*
|
|
174
|
+
* `required_credential_types` carries what the route declared
|
|
175
|
+
* (`['daemon_token']` for keeper; future gates carry their own labels).
|
|
176
|
+
* Symmetric with `PermissionError`'s `required_roles`: clients see what
|
|
177
|
+
* the route demanded, not what their credential is.
|
|
178
|
+
*/
|
|
179
|
+
export const CredentialTypeRequiredError = z.looseObject({
|
|
180
|
+
error: z.literal(ERROR_CREDENTIAL_TYPE_REQUIRED),
|
|
181
|
+
required_credential_types: z.array(z.string()).readonly(),
|
|
154
182
|
});
|
|
155
183
|
/** Rate limit error — returned when a rate limiter rejects the request. */
|
|
156
184
|
export const RateLimitError = z.looseObject({
|
|
@@ -169,7 +197,7 @@ export const ForeignKeyError = z.looseObject({
|
|
|
169
197
|
* Authorization-phase failure shapes. Surfaced when the dispatcher's
|
|
170
198
|
* `apply_authorization_phase` rejects a request before the handler runs —
|
|
171
199
|
* the route is acting-aware (input declares `acting?: ActingActor` or
|
|
172
|
-
* auth requires
|
|
200
|
+
* auth requires role_grants), but actor resolution failed.
|
|
173
201
|
*
|
|
174
202
|
* 400: `actor_required` (with `available[]`) for unspecified-actor on
|
|
175
203
|
* a multi-actor account; `actor_not_on_account` for a supplied actor
|
|
@@ -180,7 +208,7 @@ export const ForeignKeyError = z.looseObject({
|
|
|
180
208
|
* race (account/actor row deleted between credential validation and
|
|
181
209
|
* the dispatcher's follow-up read).
|
|
182
210
|
*
|
|
183
|
-
* Used by `derive_error_schemas` when `
|
|
211
|
+
* Used by `derive_error_schemas` when `auth.actor !== 'none'` so the
|
|
184
212
|
* merged error surface matches what the dispatcher actually emits.
|
|
185
213
|
*/
|
|
186
214
|
export const ActorRequiredError = z.looseObject({
|
|
@@ -207,10 +235,10 @@ export const AccountVanishedError = z.looseObject({
|
|
|
207
235
|
* - `'both'` — both keys.
|
|
208
236
|
*/
|
|
209
237
|
export const RateLimitKey = z.enum(['ip', 'account', 'both']);
|
|
210
|
-
export const derive_error_schemas = ({ auth, has_input = false, has_params = false, has_query = false, rate_limit,
|
|
238
|
+
export const derive_error_schemas = ({ auth, has_input = false, has_params = false, has_query = false, rate_limit, }) => {
|
|
211
239
|
const errors = {};
|
|
212
240
|
const has_validation = has_input || has_params || has_query;
|
|
213
|
-
if (
|
|
241
|
+
if (needs_actor(auth)) {
|
|
214
242
|
errors[400] = has_validation
|
|
215
243
|
? z.union([ValidationError, ActorRequiredError, ActorNotOnAccountError])
|
|
216
244
|
: z.union([ActorRequiredError, ActorNotOnAccountError]);
|
|
@@ -219,20 +247,27 @@ export const derive_error_schemas = ({ auth, has_input = false, has_params = fal
|
|
|
219
247
|
else if (has_validation) {
|
|
220
248
|
errors[400] = ValidationError;
|
|
221
249
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
250
|
+
// 401 fires when the dispatcher's pre-validation gate rejects an
|
|
251
|
+
// unauthenticated caller — `account === 'required'` (no credential) or
|
|
252
|
+
// `actor === 'required'` (no credential to resolve an actor against,
|
|
253
|
+
// per registry-time invariant 3 forbidding accountless actors in v1).
|
|
254
|
+
if (auth.account === 'required' || auth.actor === 'required') {
|
|
255
|
+
errors[401] = ApiError;
|
|
256
|
+
}
|
|
257
|
+
// 403 fires when `auth.roles` or `auth.credential_types` rejects a
|
|
258
|
+
// resolved request context. With both axes set, the 403 body could be
|
|
259
|
+
// either shape — emit the union so DEV-mode error-schema validation
|
|
260
|
+
// accepts whichever the dispatcher produced.
|
|
261
|
+
const has_role_gate = !!auth.roles?.length;
|
|
262
|
+
const has_credential_gate = !!auth.credential_types?.length;
|
|
263
|
+
if (has_role_gate && has_credential_gate) {
|
|
264
|
+
errors[403] = z.union([PermissionError, CredentialTypeRequiredError]);
|
|
265
|
+
}
|
|
266
|
+
else if (has_role_gate) {
|
|
267
|
+
errors[403] = PermissionError;
|
|
268
|
+
}
|
|
269
|
+
else if (has_credential_gate) {
|
|
270
|
+
errors[403] = CredentialTypeRequiredError;
|
|
236
271
|
}
|
|
237
272
|
if (rate_limit) {
|
|
238
273
|
errors[429] = RateLimitError;
|
|
@@ -1,33 +1,86 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Two-queue side-effect machinery for request handlers.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* `pending_effects` runs after the response is sent (see the request-context
|
|
7
|
-
* middleware), so this helper is the canonical home for post-commit fan-out.
|
|
4
|
+
* Handlers register fire-and-forget work in one of two queues, distinguished
|
|
5
|
+
* by their timing contract:
|
|
8
6
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
7
|
+
* - `pending_effects: Array<Promise<void>>` — eager. Producers push pool
|
|
8
|
+
* writes that are already in flight (audit emits, session-touch UPDATE,
|
|
9
|
+
* api-token usage tracking). The pool write is rollback-resilient by
|
|
10
|
+
* virtue of running outside the request transaction; pushing the
|
|
11
|
+
* in-flight handle lets test mode (`await_pending_effects: true`) await
|
|
12
|
+
* it.
|
|
13
|
+
* - `post_commit_effects: Array<() => void | Promise<void>>` — deferred.
|
|
14
|
+
* Producers go through `emit_after_commit(ctx, fn)`; the flush
|
|
15
|
+
* middleware is the only site that ever invokes the thunk, and it does
|
|
16
|
+
* so after the request handler (and its wrapping `db.transaction`)
|
|
17
|
+
* returns. Used for WS sends and any work that must observe a committed
|
|
18
|
+
* transaction.
|
|
19
|
+
*
|
|
20
|
+
* The split exists because the two shapes encode different contracts:
|
|
21
|
+
* eager pushers are saying "wait for this work that's already started";
|
|
22
|
+
* thunk pushers are saying "run this after the handler returns." Burying
|
|
23
|
+
* both behind one `Array<PendingEffect>` made `c.var.pending_effects.push(x)`
|
|
24
|
+
* ambiguous at the call site. With separate queues, the field name is
|
|
25
|
+
* the contract.
|
|
26
|
+
*
|
|
27
|
+
* Both `RouteContext` (HTTP routes) and `ActionContext` (RPC + WS
|
|
28
|
+
* actions) carry both queues by convention, so this module stays in
|
|
29
|
+
* `http/` (every transport depends on it).
|
|
12
30
|
*
|
|
13
31
|
* @module
|
|
14
32
|
*/
|
|
15
33
|
import type { Logger } from '@fuzdev/fuz_util/log.js';
|
|
16
|
-
/**
|
|
17
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Minimal structural context required by `emit_after_commit`. Both
|
|
36
|
+
* `RouteContext` and `ActionContext` satisfy this — they each carry
|
|
37
|
+
* `log` and `post_commit_effects`.
|
|
38
|
+
*/
|
|
39
|
+
export interface EmitAfterCommitContext {
|
|
18
40
|
log: Logger;
|
|
19
|
-
|
|
41
|
+
post_commit_effects: Array<() => void | Promise<void>>;
|
|
20
42
|
}
|
|
21
43
|
/**
|
|
22
44
|
* Defer a side effect until after the handler's transaction commits.
|
|
23
45
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
46
|
+
* Pushes a raw thunk onto `ctx.post_commit_effects` — the flush
|
|
47
|
+
* middleware (in `server/app_server.ts` and the per-message WS dispatcher)
|
|
48
|
+
* is the only site that ever invokes `fn`. This is load-bearing: a
|
|
49
|
+
* previous implementation queued `Promise.resolve().then(fn)`, which
|
|
50
|
+
* JavaScript's microtask scheduler drains before the wrapping
|
|
51
|
+
* `await db.query('COMMIT')` resumes — `fn` fired mid-transaction and a
|
|
52
|
+
* rollback would leak a notification for state that never landed.
|
|
53
|
+
*
|
|
54
|
+
* The thunk shape closes that gap by deferring the work to flush time.
|
|
55
|
+
* The flush owns the per-thunk `try/catch` + `log.error` so any
|
|
56
|
+
* directly-pushed thunk (tests included) cannot escape the safety net.
|
|
57
|
+
*
|
|
58
|
+
* @param ctx - context carrying `log` and the `post_commit_effects` queue
|
|
59
|
+
* @param fn - side effect to run after commit; may return `void` or `Promise<void>`
|
|
60
|
+
* @mutates `ctx.post_commit_effects` - appends `fn` verbatim
|
|
61
|
+
*/
|
|
62
|
+
export declare const emit_after_commit: (ctx: EmitAfterCommitContext, fn: () => void | Promise<void>) => void;
|
|
63
|
+
/**
|
|
64
|
+
* Drain an eager `pending_effects` queue: `Promise.allSettled` the
|
|
65
|
+
* in-flight handles, route every rejection through `log.error`, and
|
|
66
|
+
* fan out to `on_rejection` when supplied (production wires this to
|
|
67
|
+
* `on_effect_error` for monitoring).
|
|
68
|
+
*
|
|
69
|
+
* Returned promise resolves once every effect has settled. Never
|
|
70
|
+
* rejects. No-op when `effects` is empty (common on read-only
|
|
71
|
+
* requests).
|
|
72
|
+
*
|
|
73
|
+
* Symmetric with `flush_post_commit_effects` for the deferred queue.
|
|
74
|
+
*/
|
|
75
|
+
export declare const flush_pending_effects: (effects: ReadonlyArray<Promise<void>>, log: Logger, on_rejection?: (reason: unknown) => void) => Promise<void>;
|
|
76
|
+
/**
|
|
77
|
+
* Drain a `post_commit_effects` queue: invoke each thunk under
|
|
78
|
+
* `try/catch`, collect any returned promises, and `Promise.allSettled`
|
|
79
|
+
* them. Synchronous throws and async rejections are routed through
|
|
80
|
+
* `log.error` so one failing effect cannot starve siblings.
|
|
27
81
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* @mutates `ctx.pending_effects` - appends a never-rejecting promise wrapping `fn`
|
|
82
|
+
* Returned promise resolves once every thunk has finished. Never
|
|
83
|
+
* rejects.
|
|
31
84
|
*/
|
|
32
|
-
export declare const
|
|
85
|
+
export declare const flush_post_commit_effects: (effects: ReadonlyArray<() => void | Promise<void>>, log: Logger) => Promise<void>;
|
|
33
86
|
//# sourceMappingURL=pending_effects.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pending_effects.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/pending_effects.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"pending_effects.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/pending_effects.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAEpD;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,mBAAmB,EAAE,KAAK,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;CACvD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,iBAAiB,GAC7B,KAAK,sBAAsB,EAC3B,IAAI,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAC5B,IAEF,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,qBAAqB,GACjC,SAAS,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EACrC,KAAK,MAAM,EACX,eAAe,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,KACtC,OAAO,CAAC,IAAI,CASd,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,GACrC,SAAS,aAAa,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,EAClD,KAAK,MAAM,KACT,OAAO,CAAC,IAAI,CAiBd,CAAC"}
|
|
@@ -1,35 +1,104 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Two-queue side-effect machinery for request handlers.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* `pending_effects` runs after the response is sent (see the request-context
|
|
7
|
-
* middleware), so this helper is the canonical home for post-commit fan-out.
|
|
4
|
+
* Handlers register fire-and-forget work in one of two queues, distinguished
|
|
5
|
+
* by their timing contract:
|
|
8
6
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
7
|
+
* - `pending_effects: Array<Promise<void>>` — eager. Producers push pool
|
|
8
|
+
* writes that are already in flight (audit emits, session-touch UPDATE,
|
|
9
|
+
* api-token usage tracking). The pool write is rollback-resilient by
|
|
10
|
+
* virtue of running outside the request transaction; pushing the
|
|
11
|
+
* in-flight handle lets test mode (`await_pending_effects: true`) await
|
|
12
|
+
* it.
|
|
13
|
+
* - `post_commit_effects: Array<() => void | Promise<void>>` — deferred.
|
|
14
|
+
* Producers go through `emit_after_commit(ctx, fn)`; the flush
|
|
15
|
+
* middleware is the only site that ever invokes the thunk, and it does
|
|
16
|
+
* so after the request handler (and its wrapping `db.transaction`)
|
|
17
|
+
* returns. Used for WS sends and any work that must observe a committed
|
|
18
|
+
* transaction.
|
|
19
|
+
*
|
|
20
|
+
* The split exists because the two shapes encode different contracts:
|
|
21
|
+
* eager pushers are saying "wait for this work that's already started";
|
|
22
|
+
* thunk pushers are saying "run this after the handler returns." Burying
|
|
23
|
+
* both behind one `Array<PendingEffect>` made `c.var.pending_effects.push(x)`
|
|
24
|
+
* ambiguous at the call site. With separate queues, the field name is
|
|
25
|
+
* the contract.
|
|
26
|
+
*
|
|
27
|
+
* Both `RouteContext` (HTTP routes) and `ActionContext` (RPC + WS
|
|
28
|
+
* actions) carry both queues by convention, so this module stays in
|
|
29
|
+
* `http/` (every transport depends on it).
|
|
12
30
|
*
|
|
13
31
|
* @module
|
|
14
32
|
*/
|
|
15
33
|
/**
|
|
16
34
|
* Defer a side effect until after the handler's transaction commits.
|
|
17
35
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
36
|
+
* Pushes a raw thunk onto `ctx.post_commit_effects` — the flush
|
|
37
|
+
* middleware (in `server/app_server.ts` and the per-message WS dispatcher)
|
|
38
|
+
* is the only site that ever invokes `fn`. This is load-bearing: a
|
|
39
|
+
* previous implementation queued `Promise.resolve().then(fn)`, which
|
|
40
|
+
* JavaScript's microtask scheduler drains before the wrapping
|
|
41
|
+
* `await db.query('COMMIT')` resumes — `fn` fired mid-transaction and a
|
|
42
|
+
* rollback would leak a notification for state that never landed.
|
|
21
43
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
44
|
+
* The thunk shape closes that gap by deferring the work to flush time.
|
|
45
|
+
* The flush owns the per-thunk `try/catch` + `log.error` so any
|
|
46
|
+
* directly-pushed thunk (tests included) cannot escape the safety net.
|
|
47
|
+
*
|
|
48
|
+
* @param ctx - context carrying `log` and the `post_commit_effects` queue
|
|
49
|
+
* @param fn - side effect to run after commit; may return `void` or `Promise<void>`
|
|
50
|
+
* @mutates `ctx.post_commit_effects` - appends `fn` verbatim
|
|
25
51
|
*/
|
|
26
52
|
export const emit_after_commit = (ctx, fn) => {
|
|
27
|
-
ctx.
|
|
53
|
+
ctx.post_commit_effects.push(fn);
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Drain an eager `pending_effects` queue: `Promise.allSettled` the
|
|
57
|
+
* in-flight handles, route every rejection through `log.error`, and
|
|
58
|
+
* fan out to `on_rejection` when supplied (production wires this to
|
|
59
|
+
* `on_effect_error` for monitoring).
|
|
60
|
+
*
|
|
61
|
+
* Returned promise resolves once every effect has settled. Never
|
|
62
|
+
* rejects. No-op when `effects` is empty (common on read-only
|
|
63
|
+
* requests).
|
|
64
|
+
*
|
|
65
|
+
* Symmetric with `flush_post_commit_effects` for the deferred queue.
|
|
66
|
+
*/
|
|
67
|
+
export const flush_pending_effects = async (effects, log, on_rejection) => {
|
|
68
|
+
if (effects.length === 0)
|
|
69
|
+
return;
|
|
70
|
+
const results = await Promise.allSettled(effects);
|
|
71
|
+
for (const result of results) {
|
|
72
|
+
if (result.status === 'rejected') {
|
|
73
|
+
log.error('pending effect rejected:', result.reason);
|
|
74
|
+
on_rejection?.(result.reason);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* Drain a `post_commit_effects` queue: invoke each thunk under
|
|
80
|
+
* `try/catch`, collect any returned promises, and `Promise.allSettled`
|
|
81
|
+
* them. Synchronous throws and async rejections are routed through
|
|
82
|
+
* `log.error` so one failing effect cannot starve siblings.
|
|
83
|
+
*
|
|
84
|
+
* Returned promise resolves once every thunk has finished. Never
|
|
85
|
+
* rejects.
|
|
86
|
+
*/
|
|
87
|
+
export const flush_post_commit_effects = async (effects, log) => {
|
|
88
|
+
const promises = [];
|
|
89
|
+
for (const fn of effects) {
|
|
28
90
|
try {
|
|
29
|
-
fn();
|
|
91
|
+
const result = fn();
|
|
92
|
+
if (result instanceof Promise) {
|
|
93
|
+
promises.push(result.catch((err) => {
|
|
94
|
+
log.error('post-commit side effect failed:', err);
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
30
97
|
}
|
|
31
98
|
catch (err) {
|
|
32
|
-
|
|
99
|
+
log.error('post-commit side effect failed:', err);
|
|
33
100
|
}
|
|
34
|
-
}
|
|
101
|
+
}
|
|
102
|
+
if (promises.length)
|
|
103
|
+
await Promise.allSettled(promises);
|
|
35
104
|
};
|