@fuzdev/fuz_app 0.147.0 → 0.149.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 +8 -6
- package/dist/actions/action_codegen.d.ts +15 -1
- package/dist/actions/action_codegen.d.ts.map +1 -1
- package/dist/actions/action_codegen.js +23 -2
- package/dist/actions/action_event.d.ts.map +1 -1
- package/dist/actions/action_event.js +14 -1
- package/dist/actions/perform_action.d.ts +17 -1
- package/dist/actions/perform_action.d.ts.map +1 -1
- package/dist/actions/perform_action.js +23 -3
- package/dist/auth/CLAUDE.md +3 -2
- package/dist/auth/account_action_specs.d.ts +12 -0
- package/dist/auth/account_action_specs.d.ts.map +1 -1
- package/dist/auth/account_action_specs.js +16 -2
- package/dist/auth/account_actions.d.ts.map +1 -1
- package/dist/auth/account_actions.js +7 -4
- package/dist/auth/admin_action_specs.d.ts.map +1 -1
- package/dist/auth/admin_action_specs.js +29 -8
- package/dist/auth/audit_emitter.d.ts +14 -0
- package/dist/auth/audit_emitter.d.ts.map +1 -1
- package/dist/auth/audit_emitter.js +5 -1
- package/dist/auth/cell_action_specs.d.ts +3 -1
- package/dist/auth/cell_action_specs.d.ts.map +1 -1
- package/dist/auth/cell_action_specs.js +5 -5
- package/dist/auth/cell_actions.d.ts.map +1 -1
- package/dist/auth/cell_actions.js +2 -3
- package/dist/auth/cell_data_schema.d.ts +1 -1
- package/dist/auth/cell_data_schema.js +1 -1
- package/dist/auth/cell_field_action_specs.d.ts +4 -3
- package/dist/auth/cell_field_action_specs.d.ts.map +1 -1
- package/dist/auth/cell_field_action_specs.js +5 -6
- package/dist/auth/cell_field_actions.d.ts.map +1 -1
- package/dist/auth/cell_field_actions.js +8 -1
- package/dist/auth/cell_item_action_specs.d.ts +4 -2
- package/dist/auth/cell_item_action_specs.d.ts.map +1 -1
- package/dist/auth/cell_item_action_specs.js +5 -5
- package/dist/auth/cell_item_actions.d.ts.map +1 -1
- package/dist/auth/cell_item_actions.js +8 -1
- package/dist/auth/role_grant_offer_action_specs.d.ts +2 -0
- package/dist/auth/role_grant_offer_action_specs.d.ts.map +1 -1
- package/dist/auth/role_grant_offer_action_specs.js +8 -4
- package/dist/http/CLAUDE.md +14 -2
- package/dist/http/error_schemas.d.ts +8 -0
- package/dist/http/error_schemas.d.ts.map +1 -1
- package/dist/http/error_schemas.js +12 -0
- package/dist/http/jsonrpc_errors.d.ts +40 -15
- package/dist/http/jsonrpc_errors.d.ts.map +1 -1
- package/dist/http/jsonrpc_errors.js +90 -35
- package/dist/primitive_schemas.d.ts +1 -1
- package/dist/primitive_schemas.d.ts.map +1 -1
- package/dist/primitive_schemas.js +2 -1
- package/dist/schema_meta.d.ts +80 -0
- package/dist/schema_meta.d.ts.map +1 -1
- package/dist/schema_meta.js +71 -1
- package/dist/testing/CLAUDE.md +853 -146
- package/dist/testing/admin_integration.d.ts.map +1 -1
- package/dist/testing/admin_integration.js +73 -5
- package/dist/testing/adversarial_input.d.ts +0 -47
- package/dist/testing/adversarial_input.d.ts.map +1 -1
- package/dist/testing/adversarial_input.js +4 -340
- package/dist/testing/adversarial_input_cases.d.ts +124 -0
- package/dist/testing/adversarial_input_cases.d.ts.map +1 -0
- package/dist/testing/adversarial_input_cases.js +393 -0
- package/dist/testing/audit_completeness.d.ts.map +1 -1
- package/dist/testing/audit_completeness.js +24 -20
- package/dist/testing/audit_drift_guard.d.ts +30 -3
- package/dist/testing/audit_drift_guard.d.ts.map +1 -1
- package/dist/testing/audit_drift_guard.js +55 -3
- package/dist/testing/cross_backend/account_lifecycle.d.ts.map +1 -1
- package/dist/testing/cross_backend/account_lifecycle.js +29 -12
- package/dist/testing/cross_backend/actor_lookup.d.ts.map +1 -1
- package/dist/testing/cross_backend/actor_lookup.js +7 -25
- package/dist/testing/cross_backend/app_settings.d.ts.map +1 -1
- package/dist/testing/cross_backend/app_settings.js +4 -6
- package/dist/testing/cross_backend/audit_cross_helpers.d.ts +57 -0
- package/dist/testing/cross_backend/audit_cross_helpers.d.ts.map +1 -0
- package/dist/testing/cross_backend/audit_cross_helpers.js +89 -0
- package/dist/testing/cross_backend/backend_config.d.ts +2 -1
- package/dist/testing/cross_backend/backend_config.d.ts.map +1 -1
- package/dist/testing/cross_backend/body_size.d.ts +6 -0
- package/dist/testing/cross_backend/body_size.d.ts.map +1 -1
- package/dist/testing/cross_backend/body_size.js +26 -44
- package/dist/testing/cross_backend/body_size_smuggling.d.ts +5 -0
- package/dist/testing/cross_backend/body_size_smuggling.d.ts.map +1 -1
- package/dist/testing/cross_backend/body_size_smuggling.js +7 -14
- package/dist/testing/cross_backend/build_test_backend_paths.d.ts +3 -1
- package/dist/testing/cross_backend/build_test_backend_paths.d.ts.map +1 -1
- package/dist/testing/cross_backend/capabilities.d.ts +78 -59
- package/dist/testing/cross_backend/capabilities.d.ts.map +1 -1
- package/dist/testing/cross_backend/capabilities.js +25 -24
- package/dist/testing/cross_backend/cargo_binary.d.ts +70 -0
- package/dist/testing/cross_backend/cargo_binary.d.ts.map +1 -0
- package/dist/testing/cross_backend/cargo_binary.js +148 -0
- package/dist/testing/cross_backend/cell_crud.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_crud.js +174 -3
- package/dist/testing/cross_backend/cell_gated_create.d.ts +0 -60
- package/dist/testing/cross_backend/cell_gated_create.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_gated_create.js +9 -487
- package/dist/testing/cross_backend/cell_grant_role.d.ts +14 -2
- package/dist/testing/cross_backend/cell_grant_role.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_grant_role.js +22 -12
- package/dist/testing/cross_backend/cell_moderate.d.ts +66 -0
- package/dist/testing/cross_backend/cell_moderate.d.ts.map +1 -0
- package/dist/testing/cross_backend/cell_moderate.js +511 -0
- package/dist/testing/cross_backend/cell_ref_admission.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_ref_admission.js +1 -1
- package/dist/testing/cross_backend/cell_relations.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_relations.js +40 -19
- package/dist/testing/cross_backend/conformance_case.d.ts +43 -4
- package/dist/testing/cross_backend/conformance_case.d.ts.map +1 -1
- package/dist/testing/cross_backend/conformance_case.js +29 -1
- package/dist/testing/cross_backend/conformance_rpc_auth.d.ts +93 -0
- package/dist/testing/cross_backend/conformance_rpc_auth.d.ts.map +1 -0
- package/dist/testing/cross_backend/conformance_rpc_auth.js +125 -0
- package/dist/testing/cross_backend/conformance_table.d.ts +144 -4
- package/dist/testing/cross_backend/conformance_table.d.ts.map +1 -1
- package/dist/testing/cross_backend/conformance_table.js +297 -65
- package/dist/testing/cross_backend/cookie_attributes.d.ts.map +1 -1
- package/dist/testing/cross_backend/cookie_attributes.js +3 -2
- package/dist/testing/cross_backend/create_cross_backend_global_setup.d.ts +38 -5
- package/dist/testing/cross_backend/create_cross_backend_global_setup.d.ts.map +1 -1
- package/dist/testing/cross_backend/create_cross_backend_global_setup.js +24 -3
- package/dist/testing/cross_backend/create_dual_spawn_global_setup.d.ts +5 -5
- package/dist/testing/cross_backend/create_dual_spawn_global_setup.d.ts.map +1 -1
- package/dist/testing/cross_backend/credential_deadline.d.ts +10 -6
- package/dist/testing/cross_backend/credential_deadline.d.ts.map +1 -1
- package/dist/testing/cross_backend/credential_deadline.js +32 -31
- package/dist/testing/cross_backend/credential_header_robustness.d.ts.map +1 -1
- package/dist/testing/cross_backend/credential_header_robustness.js +4 -6
- package/dist/testing/cross_backend/{cell_cross_helpers.d.ts → cross_rpc.d.ts} +14 -2
- package/dist/testing/cross_backend/cross_rpc.d.ts.map +1 -0
- package/dist/testing/cross_backend/{cell_cross_helpers.js → cross_rpc.js} +31 -7
- package/dist/testing/cross_backend/default_backend_configs.d.ts +58 -61
- package/dist/testing/cross_backend/default_backend_configs.d.ts.map +1 -1
- package/dist/testing/cross_backend/default_backend_configs.js +97 -91
- package/dist/testing/cross_backend/default_spine_surface.d.ts.map +1 -1
- package/dist/testing/cross_backend/default_spine_surface.js +2 -2
- package/dist/testing/cross_backend/differential.d.ts +126 -0
- package/dist/testing/cross_backend/differential.d.ts.map +1 -0
- package/dist/testing/cross_backend/differential.js +201 -0
- package/dist/testing/cross_backend/differential_normalize.d.ts +150 -0
- package/dist/testing/cross_backend/differential_normalize.d.ts.map +1 -0
- package/dist/testing/cross_backend/differential_normalize.js +153 -0
- package/dist/testing/cross_backend/fact_serving.d.ts.map +1 -1
- package/dist/testing/cross_backend/fact_serving.js +27 -17
- package/dist/testing/cross_backend/full_spine_mount.d.ts +15 -0
- package/dist/testing/cross_backend/full_spine_mount.d.ts.map +1 -1
- package/dist/testing/cross_backend/full_spine_mount.js +55 -1
- package/dist/testing/cross_backend/identity_parity.d.ts.map +1 -1
- package/dist/testing/cross_backend/identity_parity.js +6 -5
- package/dist/testing/cross_backend/in_process_setup.d.ts +12 -2
- package/dist/testing/cross_backend/in_process_setup.d.ts.map +1 -1
- package/dist/testing/cross_backend/in_process_setup.js +10 -7
- package/dist/testing/cross_backend/login_security.d.ts.map +1 -1
- package/dist/testing/cross_backend/login_security.js +13 -18
- package/dist/testing/cross_backend/origin.js +1 -1
- package/dist/testing/cross_backend/origin_conformance.js +1 -1
- package/dist/testing/cross_backend/origin_scope.d.ts +6 -0
- package/dist/testing/cross_backend/origin_scope.d.ts.map +1 -1
- package/dist/testing/cross_backend/origin_scope.js +13 -12
- package/dist/testing/cross_backend/peer_ping_ws.d.ts +2 -5
- package/dist/testing/cross_backend/peer_ping_ws.d.ts.map +1 -1
- package/dist/testing/cross_backend/peer_ping_ws.js +14 -24
- package/dist/testing/cross_backend/postgres_database.d.ts +85 -0
- package/dist/testing/cross_backend/postgres_database.d.ts.map +1 -0
- package/dist/testing/cross_backend/postgres_database.js +140 -0
- package/dist/testing/cross_backend/provided_context.d.ts +28 -0
- package/dist/testing/cross_backend/provided_context.d.ts.map +1 -0
- package/dist/testing/cross_backend/provided_context.js +35 -0
- package/dist/testing/cross_backend/query_shape.d.ts.map +1 -1
- package/dist/testing/cross_backend/query_shape.js +10 -12
- package/dist/testing/cross_backend/ready.js +2 -2
- package/dist/testing/cross_backend/revocation_drivers.d.ts +4 -3
- package/dist/testing/cross_backend/revocation_drivers.d.ts.map +1 -1
- package/dist/testing/cross_backend/revocation_drivers.js +1 -1
- package/dist/testing/cross_backend/role_grant_cross_helpers.d.ts +3 -2
- package/dist/testing/cross_backend/role_grant_cross_helpers.d.ts.map +1 -1
- package/dist/testing/cross_backend/role_grant_offer_lifecycle.d.ts +13 -0
- package/dist/testing/cross_backend/role_grant_offer_lifecycle.d.ts.map +1 -0
- package/dist/testing/cross_backend/role_grant_offer_lifecycle.js +203 -0
- package/dist/testing/cross_backend/role_grant_offer_notification_ws.d.ts +2 -5
- package/dist/testing/cross_backend/role_grant_offer_notification_ws.d.ts.map +1 -1
- package/dist/testing/cross_backend/role_grant_offer_notification_ws.js +203 -111
- package/dist/testing/cross_backend/role_grant_participation.d.ts +13 -0
- package/dist/testing/cross_backend/role_grant_participation.d.ts.map +1 -1
- package/dist/testing/cross_backend/role_grant_participation.js +32 -21
- package/dist/testing/cross_backend/role_grant_role_grammar.d.ts.map +1 -1
- package/dist/testing/cross_backend/role_grant_role_grammar.js +6 -9
- package/dist/testing/cross_backend/rpc_adversarial.d.ts +47 -0
- package/dist/testing/cross_backend/rpc_adversarial.d.ts.map +1 -0
- package/dist/testing/cross_backend/rpc_adversarial.js +302 -0
- package/dist/testing/cross_backend/rpc_success_fixtures.d.ts +24 -0
- package/dist/testing/cross_backend/rpc_success_fixtures.d.ts.map +1 -0
- package/dist/testing/cross_backend/rpc_success_fixtures.js +124 -0
- package/dist/testing/cross_backend/rust_spine_consumer_surface.d.ts +101 -0
- package/dist/testing/cross_backend/rust_spine_consumer_surface.d.ts.map +1 -0
- package/dist/testing/cross_backend/rust_spine_consumer_surface.js +113 -0
- package/dist/testing/cross_backend/rust_spine_stub_backend_config.d.ts +10 -0
- package/dist/testing/cross_backend/rust_spine_stub_backend_config.d.ts.map +1 -1
- package/dist/testing/cross_backend/rust_spine_stub_backend_config.js +33 -21
- package/dist/testing/cross_backend/session_cap.d.ts +9 -8
- package/dist/testing/cross_backend/session_cap.d.ts.map +1 -1
- package/dist/testing/cross_backend/session_cap.js +9 -4
- package/dist/testing/cross_backend/session_cookie_codec.js +1 -1
- package/dist/testing/cross_backend/setup.d.ts +58 -56
- package/dist/testing/cross_backend/setup.d.ts.map +1 -1
- package/dist/testing/cross_backend/setup.js +29 -29
- package/dist/testing/cross_backend/simple_request.d.ts.map +1 -1
- package/dist/testing/cross_backend/simple_request.js +4 -4
- package/dist/testing/cross_backend/spawn_backend.d.ts +59 -10
- package/dist/testing/cross_backend/spawn_backend.d.ts.map +1 -1
- package/dist/testing/cross_backend/spawn_backend.js +219 -60
- package/dist/testing/cross_backend/spine_suites.d.ts +311 -0
- package/dist/testing/cross_backend/spine_suites.d.ts.map +1 -0
- package/dist/testing/cross_backend/spine_suites.js +897 -0
- package/dist/testing/cross_backend/spine_surface_constants.d.ts +44 -0
- package/dist/testing/cross_backend/spine_surface_constants.d.ts.map +1 -1
- package/dist/testing/cross_backend/spine_surface_constants.js +53 -0
- package/dist/testing/cross_backend/sse_round_trip.d.ts.map +1 -1
- package/dist/testing/cross_backend/sse_round_trip.js +3 -4
- package/dist/testing/cross_backend/standard.d.ts +18 -1
- package/dist/testing/cross_backend/standard.d.ts.map +1 -1
- package/dist/testing/cross_backend/standard.js +2 -0
- package/dist/testing/cross_backend/test_cell_gated_create_authorize.d.ts +24 -0
- package/dist/testing/cross_backend/test_cell_gated_create_authorize.d.ts.map +1 -1
- package/dist/testing/cross_backend/test_cell_gated_create_authorize.js +15 -0
- package/dist/testing/cross_backend/testing_backdoor.d.ts +29 -12
- package/dist/testing/cross_backend/testing_backdoor.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_backdoor.js +143 -51
- package/dist/testing/cross_backend/testing_reset_actions.d.ts +30 -14
- package/dist/testing/cross_backend/testing_reset_actions.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_reset_actions.js +58 -37
- package/dist/testing/cross_backend/testing_server_bun.js +1 -1
- package/dist/testing/cross_backend/token_lifetime.js +1 -1
- package/dist/testing/cross_backend/token_scope_surface.d.ts.map +1 -1
- package/dist/testing/cross_backend/token_scope_surface.js +9 -13
- package/dist/testing/cross_backend/transport_composition.d.ts +26 -2
- package/dist/testing/cross_backend/transport_composition.d.ts.map +1 -1
- package/dist/testing/cross_backend/transport_composition.js +81 -51
- package/dist/testing/cross_backend/ts_spine_backend_config.d.ts +8 -0
- package/dist/testing/cross_backend/ts_spine_backend_config.d.ts.map +1 -1
- package/dist/testing/cross_backend/ts_spine_backend_config.js +23 -13
- package/dist/testing/cross_backend/ws_action_rate_limit.d.ts +2 -5
- package/dist/testing/cross_backend/ws_action_rate_limit.d.ts.map +1 -1
- package/dist/testing/cross_backend/ws_action_rate_limit.js +8 -14
- package/dist/testing/cross_backend/ws_connection_cap.d.ts +4 -9
- package/dist/testing/cross_backend/ws_connection_cap.d.ts.map +1 -1
- package/dist/testing/cross_backend/ws_connection_cap.js +11 -12
- package/dist/testing/cross_backend/ws_endpoint.d.ts +52 -0
- package/dist/testing/cross_backend/ws_endpoint.d.ts.map +1 -0
- package/dist/testing/cross_backend/ws_endpoint.js +54 -0
- package/dist/testing/cross_backend/ws_inbound_dispatch.d.ts +2 -5
- package/dist/testing/cross_backend/ws_inbound_dispatch.d.ts.map +1 -1
- package/dist/testing/cross_backend/ws_inbound_dispatch.js +9 -15
- package/dist/testing/cross_backend/ws_outbound_overflow.d.ts +2 -7
- package/dist/testing/cross_backend/ws_outbound_overflow.d.ts.map +1 -1
- package/dist/testing/cross_backend/ws_outbound_overflow.js +5 -9
- package/dist/testing/cross_backend/ws_role_gated.d.ts +4 -5
- package/dist/testing/cross_backend/ws_role_gated.d.ts.map +1 -1
- package/dist/testing/cross_backend/ws_role_gated.js +12 -21
- package/dist/testing/cross_backend/ws_round_trip.d.ts +12 -9
- package/dist/testing/cross_backend/ws_round_trip.d.ts.map +1 -1
- package/dist/testing/cross_backend/ws_round_trip.js +29 -34
- package/dist/testing/db_entities.d.ts +16 -3
- package/dist/testing/db_entities.d.ts.map +1 -1
- package/dist/testing/db_entities.js +28 -5
- package/dist/testing/integration_helpers.d.ts +61 -2
- package/dist/testing/integration_helpers.d.ts.map +1 -1
- package/dist/testing/integration_helpers.js +75 -18
- package/dist/testing/round_trip.d.ts +17 -0
- package/dist/testing/round_trip.d.ts.map +1 -1
- package/dist/testing/round_trip.js +67 -24
- package/dist/testing/rpc_attack_surface.d.ts +10 -0
- package/dist/testing/rpc_attack_surface.d.ts.map +1 -1
- package/dist/testing/rpc_attack_surface.js +27 -140
- package/dist/testing/rpc_envelope_cases.d.ts +114 -0
- package/dist/testing/rpc_envelope_cases.d.ts.map +1 -0
- package/dist/testing/rpc_envelope_cases.js +243 -0
- package/dist/testing/rpc_helpers.d.ts +31 -0
- package/dist/testing/rpc_helpers.d.ts.map +1 -1
- package/dist/testing/rpc_helpers.js +35 -14
- package/dist/testing/rpc_round_trip.d.ts +62 -6
- package/dist/testing/rpc_round_trip.d.ts.map +1 -1
- package/dist/testing/rpc_round_trip.js +151 -39
- package/dist/testing/schema_generators.d.ts +99 -2
- package/dist/testing/schema_generators.d.ts.map +1 -1
- package/dist/testing/schema_generators.js +261 -73
- package/dist/testing/standard.d.ts +26 -0
- package/dist/testing/standard.d.ts.map +1 -1
- package/dist/testing/standard.js +4 -1
- package/dist/testing/stubs.d.ts +4 -3
- package/dist/testing/stubs.d.ts.map +1 -1
- package/dist/testing/stubs.js +6 -4
- package/dist/testing/transports/raw_http.d.ts +21 -0
- package/dist/testing/transports/raw_http.d.ts.map +1 -1
- package/dist/testing/transports/raw_http.js +30 -0
- package/dist/zod.d.ts +9 -0
- package/dist/zod.d.ts.map +1 -1
- package/dist/zod.js +20 -0
- package/package.json +6 -4
- package/dist/testing/cross_backend/actor_search.d.ts +0 -6
- package/dist/testing/cross_backend/actor_search.d.ts.map +0 -1
- package/dist/testing/cross_backend/actor_search.js +0 -90
- package/dist/testing/cross_backend/cell_cross_helpers.d.ts.map +0 -1
package/dist/actions/CLAUDE.md
CHANGED
|
@@ -127,7 +127,7 @@ and options on each function's TSDoc.
|
|
|
127
127
|
- `get_executor_phases(spec, executor)` — phases an executor participates in for the spec.
|
|
128
128
|
- `get_handler_return_type` — TS type a phase handler must return; side-effect imports `ActionOutputs`.
|
|
129
129
|
- `generate_phase_handlers` — per-action typed handler-map fragment.
|
|
130
|
-
- `generate_actions_api_method_signature` — single source of truth for the typed `FrontendActionsApi` method shape.
|
|
130
|
+
- `generate_actions_api_method_signature` — single source of truth for the typed `FrontendActionsApi` method shape. Its `input?:` follows `action_input_is_optional` — the schema accepts `undefined`, or accepts `{}` and is not marked `.meta({empty_input_handler_guarded: true})` (`SchemaFieldMeta`, read by `is_empty_input_handler_guarded` in `schema_meta.ts` — set on `cell_get`, `cell_field_list` and `cell_item_list`, whose `{}` reaches a handler guard that refuses it with a declared reason, so their input stays required; a consumer marks its own the same way); an input-shape invariant test reads the same rule.
|
|
131
131
|
- `generate_action_method_enums` — up to nine `z.enum` + `z.infer` pairs.
|
|
132
132
|
- `generate_action_method_enum_block` — lower-level escape hatch for cross-product enums.
|
|
133
133
|
- `generate_typed_action_event_alias` — fixed-shape `TypedActionEvent<TMethod, TPhase, TStep>` alias.
|
|
@@ -219,9 +219,11 @@ auth/validation/dispatch pipeline is shared with the WebSocket dispatcher.
|
|
|
219
219
|
throttle, validate after — a caller the authority gates refuse never learns
|
|
220
220
|
the action's input shape, the coarse authority facts settle before the fine
|
|
221
221
|
ones, and a malformed flood burns the budget it should. The Rust spine's
|
|
222
|
-
dispatcher enforces the same order:
|
|
223
|
-
|
|
224
|
-
|
|
222
|
+
dispatcher enforces the same order: after the rate limit it refuses a
|
|
223
|
+
non-object `params` (which only `GET`'s `?params=` can carry past the
|
|
224
|
+
envelope) and validates the `acting` selector, and leaves every other field
|
|
225
|
+
to the handlers. So an anonymous `GET` with `?params=42` is a 401 on both
|
|
226
|
+
spines, and an authorized one is `invalid_params`.
|
|
225
227
|
|
|
226
228
|
Shim responsibilities (per-request):
|
|
227
229
|
|
|
@@ -306,7 +308,7 @@ Pipeline (401 → authz → 403 → 429 → 400 → handler):
|
|
|
306
308
|
2. Authorization phase — `apply_authorization_phase` against `account_id` + `read_acting(auth, raw_params)`, which takes the selector off the raw params (malformed reads as omitted) since validation runs later. Test escape hatch via `preset.request_context`
|
|
307
309
|
3. Post-authorization auth (403) — credential-type gate, then token scope, then role
|
|
308
310
|
4. Rate limit (429) — throttle-requests semantics, ahead of validation so malformed params charge the budget and a throttled caller pays no schema work
|
|
309
|
-
5. Validate params (400) — `spec.input.safeParse` with `z.void()` / `?? {}` rules; a `z.void()` input reads absent, `null` (GET `?params=null`), and `{}` alike as the no-arg call (`to_input_params` in `http/schema_helpers.ts`, via `to_void_params`, the twin of the Rust `require_void_params`; the peer receive path in `ActionDispatcher` runs the same normalizer) and refuses any other shape
|
|
311
|
+
5. Validate params (400) — `spec.input.safeParse` with `z.void()` / `?? {}` rules; a `z.void()` input reads absent, `null` (GET `?params=null`), and `{}` alike as the no-arg call (`to_input_params` in `http/schema_helpers.ts`, via `to_void_params`, the twin of the Rust `require_void_params`; the peer receive path in `ActionDispatcher` runs the same normalizer) and refuses any other shape. A refusal is `to_invalid_params_error`: the generic `invalid params`, `data.reason` when the first issue's field declares an `invalid_reason` in its `.meta()` and no issue sits on the input itself, such as an unknown key (`resolve_issues_invalid_reason`, `schema_meta.ts` — see ../../../docs/architecture.md §Error Schema System), and the Zod issues DEV-only
|
|
310
312
|
6. Dispatch + DEV output validation + error normalization — `spec.side_effects` picks transaction vs pool. `ThrownJsonrpcError` preserves code + data; generic throws become `internal_error`
|
|
311
313
|
|
|
312
314
|
`PerformActionInput` carries `account_id`, `credential_type`, `client_ip`,
|
|
@@ -1049,7 +1051,7 @@ high-level shapes that span modules:
|
|
|
1049
1051
|
- **39-variant discriminated union** — `ActionEventDataUnion<TMethod, TInput, TOutput>` across `kind` + `phase` + `step` (28 for `request_response`, 6 for `remote_notification`, 5 for `local_call`). Narrows `input` / `output` / `error` / `request` / `response` / `notification` / `progress` at each lifecycle point.
|
|
1050
1052
|
- **Step transitions** — `initial → parsed | failed`, `parsed → handling | failed`, `handling → handled | failed`, `handled`/`failed` terminal. `validate_step_transition(from, to)` throws on illegal moves.
|
|
1051
1053
|
- **Phase transitions** — chained: `send_request → receive_response`, `receive_request → send_response`; everything else terminal. `validate_phase_for_kind` + `validate_phase_transition` enforce.
|
|
1052
|
-
- **`ActionEvent.parse()`** — `initial → parsed` via `spec.input.safeParse`. Input validation failures **fail immediately** without routing through an error phase (client-side programming errors, not runtime conditions with handlers). Handler errors DO route through `send_error` / `receive_error`. On `receive_response` with error response, transitions to `receive_error` instead of failing; a success response's `result` is validated against `spec.output` (always, not DEV-only — it's inbound data; undeclared keys are dropped rather than refused, so an older client survives an added response field) and `output` becomes the parsed value, or the event moves to `receive_error` with an `internal_error` carrying `data: {reason: ERROR_RESPONSE_OUTPUT_INVALID, validation_errors}` — a remote contract break, deliberately distinct from the `invalid_params` / `validation_error` of bad caller input.
|
|
1054
|
+
- **`ActionEvent.parse()`** — `initial → parsed` via `spec.input.safeParse`. Input validation failures **fail immediately** without routing through an error phase (client-side programming errors, not runtime conditions with handlers); their `invalid_params` `data` is `{validation_errors, reason?}`, `reason` the declared `invalid_reason` the server would answer. Handler errors DO route through `send_error` / `receive_error`. On `receive_response` with error response, transitions to `receive_error` instead of failing; a success response's `result` is validated against `spec.output` (always, not DEV-only — it's inbound data; undeclared keys are dropped rather than refused, so an older client survives an added response field) and `output` becomes the parsed value, or the event moves to `receive_error` with an `internal_error` carrying `data: {reason: ERROR_RESPONSE_OUTPUT_INVALID, validation_errors}` — a remote contract break, deliberately distinct from the `invalid_params` / `validation_error` of bad caller input.
|
|
1053
1055
|
- **Handler throws** — `ThrownJsonrpcError` keeps code/message/data; any other throw becomes `internal_error` carrying the thrown message. When the error answers a remote caller (`receive_request` / `send_response`), the raw message goes through `dev_only` like the server dispatch core.
|
|
1054
1056
|
- **Protocol message creation is automatic** — transitioning `parsed → handling` on `send_request` materializes the outgoing `JsonrpcRequest` with a fresh `create_uuid()` id; on `send` (notification) it materializes the `JsonrpcNotification`.
|
|
1055
1057
|
|
|
@@ -144,6 +144,17 @@ export declare const to_action_spec_output_identifier: (method: string) => strin
|
|
|
144
144
|
* value/type lookups, which already accepts the raw method string.
|
|
145
145
|
*/
|
|
146
146
|
export declare const to_action_property_key: (method: string) => string;
|
|
147
|
+
/**
|
|
148
|
+
* Whether a caller may omit an action's input: its schema accepts `undefined`,
|
|
149
|
+
* or accepts `{}` (what an omitted input is validated as) and is not marked
|
|
150
|
+
* `empty_input_handler_guarded` (`SchemaFieldMeta`, read by
|
|
151
|
+
* `is_empty_input_handler_guarded`). The rule codegen emits `input?:` by and
|
|
152
|
+
* the input-shape invariant tests read.
|
|
153
|
+
*
|
|
154
|
+
* @param spec - the action spec
|
|
155
|
+
* @returns whether the typed surface makes the input optional
|
|
156
|
+
*/
|
|
157
|
+
export declare const action_input_is_optional: (spec: Pick<ActionSpecUnion, "input">) => boolean;
|
|
147
158
|
/**
|
|
148
159
|
* Generates one method line of the typed `FrontendActionsApi` interface for a
|
|
149
160
|
* single spec. Encapsulates the input/options/return-type signature shape so
|
|
@@ -181,7 +192,10 @@ ActingActor})` and other all-optional-fields strict objects. The second
|
|
|
181
192
|
* schema is asked to validate. A schema with required fields fails both
|
|
182
193
|
* probes and stays `input:` (required at the typed surface). Refinements
|
|
183
194
|
* and transforms run as part of `safeParse`, so their accept/reject
|
|
184
|
-
* decisions feed into the optional/required choice naturally.
|
|
195
|
+
* decisions feed into the optional/required choice naturally. An input
|
|
196
|
+
* marked `empty_input_handler_guarded` is the exception: its schema accepts
|
|
197
|
+
* `{}` but the handler refuses it, so it stays `input:`
|
|
198
|
+
* (`action_input_is_optional` is the one rule).
|
|
185
199
|
*
|
|
186
200
|
* @param options.sync_returns_value - When true (default), sync `local_call`
|
|
187
201
|
* methods return the output value directly; when false they're wrapped in
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action_codegen.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/action_codegen.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"action_codegen.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/action_codegen.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { UnreachableError } from '@fuzdev/fuz_util/error.ts';
|
|
2
2
|
import { zod_get_base_type } from '../zod.js';
|
|
3
|
+
import { is_empty_input_handler_guarded } from '../schema_meta.js';
|
|
3
4
|
import { ActionRegistry } from './action_registry.js';
|
|
4
5
|
/**
|
|
5
6
|
* Method names of fuz_app's protocol actions — `heartbeat` (auth-aware client
|
|
@@ -320,6 +321,23 @@ export const to_action_spec_output_identifier = (method) => `${to_action_spec_id
|
|
|
320
321
|
* value/type lookups, which already accepts the raw method string.
|
|
321
322
|
*/
|
|
322
323
|
export const to_action_property_key = (method) => /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(method) ? method : `'${method}'`;
|
|
324
|
+
/**
|
|
325
|
+
* Whether a caller may omit an action's input: its schema accepts `undefined`,
|
|
326
|
+
* or accepts `{}` (what an omitted input is validated as) and is not marked
|
|
327
|
+
* `empty_input_handler_guarded` (`SchemaFieldMeta`, read by
|
|
328
|
+
* `is_empty_input_handler_guarded`). The rule codegen emits `input?:` by and
|
|
329
|
+
* the input-shape invariant tests read.
|
|
330
|
+
*
|
|
331
|
+
* @param spec - the action spec
|
|
332
|
+
* @returns whether the typed surface makes the input optional
|
|
333
|
+
*/
|
|
334
|
+
export const action_input_is_optional = (spec) => {
|
|
335
|
+
if (spec.input.safeParse(undefined).success)
|
|
336
|
+
return true;
|
|
337
|
+
if (is_empty_input_handler_guarded(spec.input))
|
|
338
|
+
return false;
|
|
339
|
+
return spec.input.safeParse({}).success;
|
|
340
|
+
};
|
|
323
341
|
/**
|
|
324
342
|
* Generates one method line of the typed `FrontendActionsApi` interface for a
|
|
325
343
|
* single spec. Encapsulates the input/options/return-type signature shape so
|
|
@@ -357,7 +375,10 @@ ActingActor})` and other all-optional-fields strict objects. The second
|
|
|
357
375
|
* schema is asked to validate. A schema with required fields fails both
|
|
358
376
|
* probes and stays `input:` (required at the typed surface). Refinements
|
|
359
377
|
* and transforms run as part of `safeParse`, so their accept/reject
|
|
360
|
-
* decisions feed into the optional/required choice naturally.
|
|
378
|
+
* decisions feed into the optional/required choice naturally. An input
|
|
379
|
+
* marked `empty_input_handler_guarded` is the exception: its schema accepts
|
|
380
|
+
* `{}` but the handler refuses it, so it stays `input:`
|
|
381
|
+
* (`action_input_is_optional` is the one rule).
|
|
361
382
|
*
|
|
362
383
|
* @param options.sync_returns_value - When true (default), sync `local_call`
|
|
363
384
|
* methods return the output value directly; when false they're wrapped in
|
|
@@ -372,7 +393,7 @@ export const generate_actions_api_method_signature = (spec, imports, options) =>
|
|
|
372
393
|
const collections_path = options?.collections_path ?? DEFAULT_COLLECTIONS_PATH;
|
|
373
394
|
const innermost_type_name = zod_get_base_type(spec.input);
|
|
374
395
|
const has_input = innermost_type_name !== 'null' && innermost_type_name !== 'void';
|
|
375
|
-
const input_optional = has_input && (spec
|
|
396
|
+
const input_optional = has_input && action_input_is_optional(spec);
|
|
376
397
|
const input_param = has_input
|
|
377
398
|
? `input${input_optional ? '?' : ''}: ActionInputs['${spec.method}']`
|
|
378
399
|
: 'input?: void';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action_event.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/action_event.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAAE,gBAAgB,EAAc,eAAe,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"action_event.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/action_event.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAAE,gBAAgB,EAAc,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAiBtF,OAAO,KAAK,EACX,cAAc,EACd,sBAAsB,EACtB,mBAAmB,EAGnB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AACvF,OAAO,EAAmB,KAAK,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAapF;;;;GAIG;AACH,eAAO,MAAM,6BAA6B,EAAG,yBAAkC,CAAC;AAmBhF,MAAM,MAAM,yBAAyB,CAAC,OAAO,SAAS,MAAM,GAAG,MAAM,IAAI,CACxE,QAAQ,EAAE,oBAAoB,CAAC,OAAO,CAAC,EACvC,QAAQ,EAAE,oBAAoB,CAAC,OAAO,CAAC,EACvC,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,KACvB,IAAI,CAAC;AAEV;;GAEG;AACH,qBAAa,WAAW,CACvB,OAAO,SAAS,MAAM,GAAG,MAAM,EAC/B,MAAM,SAAS,gBAAgB,GAAG,gBAAgB,EAClD,KAAK,SAAS,eAAe,GAAG,eAAe;;IAK/C,QAAQ,CAAC,WAAW,EAAE,sBAAsB,CAAC;IAC7C;;;;;;OAMG;IACH,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG;QAAE,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC;IAErD,IAAI,IAAI,IAAI,oBAAoB,CAAC,OAAO,CAAC,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,KAAK,CAAA;KAAE,CAEzE;gBAGA,WAAW,EAAE,sBAAsB,EACnC,IAAI,EAAE,eAAe,EACrB,IAAI,EAAE,oBAAoB,CAAC,OAAO,CAAC;IAOpC,MAAM,IAAI,oBAAoB,CAAC,OAAO,CAAC;IAMvC;;;;;;OAMG;IACH,OAAO,CAAC,QAAQ,EAAE,yBAAyB,CAAC,OAAO,CAAC,GAAG,MAAM,IAAI;IAKjE;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAAC,OAAO,CAAC,GAAG,IAAI;IAUvD;;;;;;;;;;;;;;;;;OAiBG;IACH,KAAK,IAAI,IAAI;IAiEb;;;;;;;;;;OAUG;IAGG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAsCnC;;;;;;;OAOG;IACH,WAAW,IAAI,IAAI;IA8BnB;;;;;;;;;;OAUG;IACH,UAAU,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI;IAezC,WAAW,IAAI,OAAO;IAItB,eAAe,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;IAIxC,WAAW,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAQ1C,YAAY,CAAC,QAAQ,EAAE,sBAAsB,GAAG,IAAI;IAUpD,gBAAgB,CAAC,YAAY,EAAE,mBAAmB,GAAG,IAAI;CAgMzD;AAGD;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAAI,OAAO,SAAS,MAAM,GAAG,MAAM,EAClE,aAAa,sBAAsB,EACnC,MAAM,eAAe,EACrB,OAAO,OAAO,EACd,gBAAgB,gBAAgB,KAC9B,WAAW,CAAC,OAAO,CAmBrB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,6BAA6B,GAAI,OAAO,SAAS,MAAM,GAAG,MAAM,EAC5E,MAAM,oBAAoB,CAAC,OAAO,CAAC,EACnC,aAAa,sBAAsB,KACjC,WAAW,CAAC,OAAO,CAOrB,CAAC;AAIF,eAAO,MAAM,kBAAkB,GAC9B,UAAU,OAAO,EACjB,aAAa,sBAAsB,KACjC,WAGF,CAAC"}
|
|
@@ -12,6 +12,7 @@ import { to_error_message } from '@fuzdev/fuz_util/error.ts';
|
|
|
12
12
|
import { create_jsonrpc_request, create_jsonrpc_response, create_jsonrpc_error_response, create_jsonrpc_notification, to_jsonrpc_params, is_jsonrpc_error_response } from '../http/jsonrpc_helpers.js';
|
|
13
13
|
import { dev_only, jsonrpc_error_messages, ThrownJsonrpcError, UNKNOWN_ERROR_MESSAGE } from '../http/jsonrpc_errors.js';
|
|
14
14
|
import { safe_parse_dropping_unknown_keys } from '../http/schema_helpers.js';
|
|
15
|
+
import { resolve_issues_invalid_reason } from '../schema_meta.js';
|
|
15
16
|
import { ActionEventData } from './action_event_data.js';
|
|
16
17
|
import { validate_step_transition, validate_phase_transition, should_validate_output, is_action_complete, create_initial_data, get_initial_phase, is_request_response, is_send_request_with_parsed_input, is_notification_send_with_parsed_input } from './action_event_helpers.js';
|
|
17
18
|
/**
|
|
@@ -20,6 +21,18 @@ import { validate_step_transition, validate_phase_transition, should_validate_ou
|
|
|
20
21
|
* `invalid_params` / `validation_error` a caller's own bad input produces.
|
|
21
22
|
*/
|
|
22
23
|
export const ERROR_RESPONSE_OUTPUT_INVALID = 'response_output_invalid';
|
|
24
|
+
/**
|
|
25
|
+
* `error.data` for a local input parse failure: the issues, and the declared
|
|
26
|
+
* `invalid_reason` of the first issue's field — the reason the server would
|
|
27
|
+
* answer the same input with, so a caller matching `data.reason` reads one
|
|
28
|
+
* value whichever side refused.
|
|
29
|
+
*/
|
|
30
|
+
const to_local_invalid_params_data = (input, issues) => {
|
|
31
|
+
const reason = resolve_issues_invalid_reason(input, issues);
|
|
32
|
+
return reason === undefined
|
|
33
|
+
? { validation_errors: issues }
|
|
34
|
+
: { validation_errors: issues, reason };
|
|
35
|
+
};
|
|
23
36
|
/**
|
|
24
37
|
* Action event that manages the lifecycle of an action through its state machine.
|
|
25
38
|
*/
|
|
@@ -136,7 +149,7 @@ export class ActionEvent {
|
|
|
136
149
|
// Handler errors (network, server, business logic) DO transition to error phases.
|
|
137
150
|
this.#fail(
|
|
138
151
|
// no need to protect this info
|
|
139
|
-
jsonrpc_error_messages.invalid_params(`failed to parse input: ${z.prettifyError(parsed.error)}`,
|
|
152
|
+
jsonrpc_error_messages.invalid_params(`failed to parse input: ${z.prettifyError(parsed.error)}`, to_local_invalid_params_data(this.spec.input, parsed.error.issues)));
|
|
140
153
|
}
|
|
141
154
|
return this;
|
|
142
155
|
}
|
|
@@ -28,7 +28,10 @@
|
|
|
28
28
|
* sits behind the authority gates by choice rather than necessity: a
|
|
29
29
|
* caller those gates refuse is answered 403, not 429.
|
|
30
30
|
* 5. **Validate params (400)** — `spec.input.safeParse(raw_params)` with
|
|
31
|
-
* `z.void()` / `?? {}` rules (`to_input_params`).
|
|
31
|
+
* `z.void()` / `?? {}` rules (`to_input_params`). A refusal is the generic
|
|
32
|
+
* `invalid params`, with `data.reason` when the first issue's field
|
|
33
|
+
* declares an `invalid_reason` (`to_invalid_params_error`) and the Zod
|
|
34
|
+
* issues under DEV only. Runs **after** the authority gates: a
|
|
32
35
|
* 400 describing the action's input shape to a caller those gates
|
|
33
36
|
* refuse would confirm the method exists and describe how to call it,
|
|
34
37
|
* to a channel that should have learned nothing. Coarse authority
|
|
@@ -55,6 +58,7 @@
|
|
|
55
58
|
* @module
|
|
56
59
|
*/
|
|
57
60
|
import type { Logger } from '@fuzdev/fuz_util/log.ts';
|
|
61
|
+
import type { z } from 'zod';
|
|
58
62
|
import type { Uuid } from '../primitive_schemas.js';
|
|
59
63
|
import { type RequestContext } from '../auth/request_context.js';
|
|
60
64
|
import { type CredentialType } from '../hono_context.js';
|
|
@@ -163,6 +167,18 @@ export type PerformActionResult = {
|
|
|
163
167
|
* the harness omits `account_id`.
|
|
164
168
|
*/
|
|
165
169
|
export declare const perform_action: (input: PerformActionInput, deps: PerformActionDeps) => Promise<PerformActionResult>;
|
|
170
|
+
/**
|
|
171
|
+
* The `invalid_params` error an input validation failure answers: the generic
|
|
172
|
+
* `invalid params` message, `data.reason` when the field the first issue lands
|
|
173
|
+
* on declares an `invalid_reason` and no issue sits on the input itself
|
|
174
|
+
* (`resolve_issues_invalid_reason`), and the Zod issues under DEV only
|
|
175
|
+
* (`dev_only`). With no declared reason, production sends no `data` at all.
|
|
176
|
+
*
|
|
177
|
+
* @param input - the action's input schema
|
|
178
|
+
* @param issues - the failed parse's issues, in Zod's order
|
|
179
|
+
* @returns the JSON-RPC error object
|
|
180
|
+
*/
|
|
181
|
+
export declare const to_invalid_params_error: (input: z.ZodType, issues: ReadonlyArray<z.core.$ZodIssue>) => JsonrpcErrorObject;
|
|
166
182
|
/**
|
|
167
183
|
* The credential-type 403 — one builder, so the dispatcher's gate below and a
|
|
168
184
|
* handler that gates a credential channel on its input (`account_delete`'s
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"perform_action.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/perform_action.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"perform_action.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/perform_action.ts"],"names":[],"mappings":"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"}
|
|
@@ -28,7 +28,10 @@
|
|
|
28
28
|
* sits behind the authority gates by choice rather than necessity: a
|
|
29
29
|
* caller those gates refuse is answered 403, not 429.
|
|
30
30
|
* 5. **Validate params (400)** — `spec.input.safeParse(raw_params)` with
|
|
31
|
-
* `z.void()` / `?? {}` rules (`to_input_params`).
|
|
31
|
+
* `z.void()` / `?? {}` rules (`to_input_params`). A refusal is the generic
|
|
32
|
+
* `invalid params`, with `data.reason` when the first issue's field
|
|
33
|
+
* declares an `invalid_reason` (`to_invalid_params_error`) and the Zod
|
|
34
|
+
* issues under DEV only. Runs **after** the authority gates: a
|
|
32
35
|
* 400 describing the action's input shape to a caller those gates
|
|
33
36
|
* refuse would confirm the method exists and describe how to call it,
|
|
34
37
|
* to a channel that should have learned nothing. Coarse authority
|
|
@@ -57,6 +60,7 @@
|
|
|
57
60
|
import { DEV } from 'esm-env';
|
|
58
61
|
import { apply_authorization_phase, has_any_scoped_role } from '../auth/request_context.js';
|
|
59
62
|
import {} from '../hono_context.js';
|
|
63
|
+
import { resolve_issues_invalid_reason } from '../schema_meta.js';
|
|
60
64
|
import { to_input_params } from '../http/schema_helpers.js';
|
|
61
65
|
import { rate_limit_ip_key } from '../http/ip_canonical.js';
|
|
62
66
|
import { dispatch_with_post_commit_rollback } from '../http/pending_effects.js';
|
|
@@ -153,7 +157,7 @@ export const perform_action = async (input, deps) => {
|
|
|
153
157
|
const params = to_input_params(spec.input, raw_params);
|
|
154
158
|
const parse_result = spec.input.safeParse(params);
|
|
155
159
|
if (!parse_result.success) {
|
|
156
|
-
return error_result(
|
|
160
|
+
return error_result(to_invalid_params_error(spec.input, parse_result.error.issues));
|
|
157
161
|
}
|
|
158
162
|
const validated_input = parse_result.data;
|
|
159
163
|
// step 6: dispatch — transaction for mutations, pool for reads.
|
|
@@ -212,6 +216,22 @@ export const perform_action = async (input, deps) => {
|
|
|
212
216
|
return error_result(jsonrpc_error_messages.internal_error(dev_only(err instanceof Error ? err.message : undefined)));
|
|
213
217
|
}
|
|
214
218
|
};
|
|
219
|
+
/**
|
|
220
|
+
* The `invalid_params` error an input validation failure answers: the generic
|
|
221
|
+
* `invalid params` message, `data.reason` when the field the first issue lands
|
|
222
|
+
* on declares an `invalid_reason` and no issue sits on the input itself
|
|
223
|
+
* (`resolve_issues_invalid_reason`), and the Zod issues under DEV only
|
|
224
|
+
* (`dev_only`). With no declared reason, production sends no `data` at all.
|
|
225
|
+
*
|
|
226
|
+
* @param input - the action's input schema
|
|
227
|
+
* @param issues - the failed parse's issues, in Zod's order
|
|
228
|
+
* @returns the JSON-RPC error object
|
|
229
|
+
*/
|
|
230
|
+
export const to_invalid_params_error = (input, issues) => {
|
|
231
|
+
const reason = resolve_issues_invalid_reason(input, issues);
|
|
232
|
+
const issues_data = dev_only({ issues });
|
|
233
|
+
return jsonrpc_error_messages.invalid_params('invalid params', reason === undefined ? issues_data : { reason, ...issues_data });
|
|
234
|
+
};
|
|
215
235
|
const error_result = (error) => ({
|
|
216
236
|
kind: 'error',
|
|
217
237
|
error,
|
|
@@ -319,7 +339,7 @@ const check_action_auth_post_authorization = (auth, request_context, credential_
|
|
|
319
339
|
}
|
|
320
340
|
if (auth.roles?.length) {
|
|
321
341
|
if (!has_any_scoped_role(request_context, auth.roles, null)) {
|
|
322
|
-
return jsonrpc_error_messages.forbidden(
|
|
342
|
+
return jsonrpc_error_messages.forbidden('forbidden', {
|
|
323
343
|
reason: ERROR_INSUFFICIENT_PERMISSIONS,
|
|
324
344
|
required_roles: auth.roles
|
|
325
345
|
});
|
package/dist/auth/CLAUDE.md
CHANGED
|
@@ -130,6 +130,7 @@ its registered listeners + optional `AuditLogConfig`. Its methods:
|
|
|
130
130
|
- `add_listener(listener)` — listener registration, returning a remover for that registration (idempotent; the same function registered twice is two registrations, each with its own remover). Twin of Rust `fuz_auth` `AuditEmitter::add_listener` in firing order and snapshot-at-notify
|
|
131
131
|
- `listener_count()` — registered-listener count, for tests / diagnostics
|
|
132
132
|
- `drain_inflight()` — test-binary barrier: waits until no `emit` write is in flight, writes started while waiting included. Only an emitter built with `track_inflight: true` tracks; otherwise it resolves at once (production never tracks). Backs `_testing_drain_effects` (twin of Rust `AuditEmitter::drain_inflight` / `new_with_inflight_tracking`)
|
|
133
|
+
- `is_tracking_inflight()` — whether the emitter was built with `track_inflight: true`, i.e. whether `drain_inflight` can wait on anything. `_testing_drain_effects` reports it as `tracked`, and `cross_drain_effects` (every `list_audit_events` read) refuses `false` (twin of Rust `AuditEmitter::is_tracking_inflight`)
|
|
133
134
|
|
|
134
135
|
Listeners are closure-private; they change only through `add_listener` and
|
|
135
136
|
its removers. `create_app_server` registers the audit-log SSE listener,
|
|
@@ -615,7 +616,7 @@ fine — same as `role_grant_revoke`). `account_undelete` is admin-only —
|
|
|
615
616
|
reactivation has no self path because a soft-deleted account can't
|
|
616
617
|
authenticate.
|
|
617
618
|
|
|
618
|
-
- `admin_account_list_action_spec` — read; input `{limit?, offset?, include_deleted?}`; output `{accounts, grantable_roles}`. `include_deleted` (default false) surfaces soft-deleted rows (with `account.deleted_at` set) for the admin UI's reactivation view.
|
|
619
|
+
- `admin_account_list_action_spec` — read; input `{limit?, offset?, include_deleted?}`; output `{accounts, grantable_roles}`. On it and the other paged reads (`audit_log_list`, `audit_log_role_grant_history`, `role_grant_offer_history`) `limit` / `offset` declare `invalid_reason` `ERROR_LIMIT_INVALID` / `ERROR_OFFSET_INVALID` (`http/error_schemas.ts`), and `audit_log_list`'s `since_seq` / `outcome` `ERROR_SINCE_SEQ_INVALID` / `ERROR_OUTCOME_INVALID`: every refusal of the field carries it. `include_deleted` (default false) surfaces soft-deleted rows (with `account.deleted_at` set) for the admin UI's reactivation view.
|
|
619
620
|
- `account_delete_action_spec` — mutation (soft delete); self-or-admin (`{account, actor}`, handler elevates to admin when `account_id` ≠ self); the self path is session-only, handler-enforced ahead of the target guards (an API or daemon token gets the dispatcher's `ERROR_CREDENTIAL_TYPE_REQUIRED` 403 via `credential_type_required_error`), while an admin deleting another account keeps any credential; input `{account_id?}`; output `{ok, deleted}`. Tombstones account + actor(s), revokes sessions/tokens, emits `account_delete` + per-actor `actor_delete`. Refuses a keeper-role target (`ERROR_CANNOT_DELETE_KEEPER`) or the sole active admin (`ERROR_CANNOT_DELETE_LAST_ADMIN`) — both fail-loud with a failure-audit row.
|
|
620
621
|
- `account_purge_action_spec` — mutation (hard purge); keeper-only (`credential_types: ['daemon_token']` + `roles: ['keeper']`) + `confirm: true` + WARN; input `{account_id, confirm?}`; output `{ok, purged}`. Cascading delete; emits `account_purge` + per-actor `actor_purge` (identity snapshot survives in metadata since `audit_log` ids carry no FK). Refuses a keeper-role target (`ERROR_CANNOT_DELETE_KEEPER`) or the sole active admin (`ERROR_CANNOT_DELETE_LAST_ADMIN`).
|
|
621
622
|
- `account_undelete_action_spec` — mutation (reactivation, inverse of soft delete); admin-only (`roles: ['admin']` — no self path, a tombstoned account can't authenticate); input `{account_id}`; output `{ok, undeleted}`. Clears the `deleted_at` tombstone on the account + its actor(s), emits `account_undelete` + per-actor `actor_undelete`. Does not restore revoked sessions/tokens.
|
|
@@ -805,7 +806,7 @@ Options: `roles?: RoleSchemaResult` (drives admin-grant-path lookup),
|
|
|
805
806
|
- `account_session_list_action_spec` — read; input `z.void()`; output `{sessions}`.
|
|
806
807
|
- `account_session_revoke_action_spec` — mutation; input `{session_id}`; output `{ok, revoked}`.
|
|
807
808
|
- `account_session_revoke_all_action_spec` — mutation; input `z.void()`; output `{ok, count}`.
|
|
808
|
-
- `account_token_create_action_spec` — mutation; input `{name?, scope, lifetime}` (both `scope` and `lifetime` required — default-deny at mint on both axes; `name` at most `API_TOKEN_NAME_LENGTH_MAX` = 255 characters, since it is copied into the audit row); output `{ok, token, id, name, expires_at}`.
|
|
809
|
+
- `account_token_create_action_spec` — mutation; input `{name?, scope, lifetime}` (both `scope` and `lifetime` required — default-deny at mint on both axes; `name` at most `API_TOKEN_NAME_LENGTH_MAX` = 255 characters, since it is copied into the audit row); output `{ok, token, id, name, expires_at}`. `scope` / `lifetime` declare `invalid_reason` `ERROR_TOKEN_SCOPE_INVALID` / `ERROR_TOKEN_LIFETIME_INVALID`, so every refusal of either carries it — the handler's over-cap scope refusal included.
|
|
809
810
|
- `account_token_list_action_spec` — read; input `z.void()`; output `{tokens}`.
|
|
810
811
|
- `account_token_revoke_action_spec` — mutation; input `{token_id}`; output `{ok, revoked}`.
|
|
811
812
|
|
|
@@ -52,6 +52,18 @@ export type SessionRevokeAllOutput = z.infer<typeof SessionRevokeAllOutput>;
|
|
|
52
52
|
* the Rust spine's `API_TOKEN_NAME_LENGTH_MAX`.
|
|
53
53
|
*/
|
|
54
54
|
export declare const API_TOKEN_NAME_LENGTH_MAX = 255;
|
|
55
|
+
/**
|
|
56
|
+
* `error.data.reason` on any refusal of `account_token_create`'s `scope` —
|
|
57
|
+
* missing, `null`, an unknown `kind` or key, a malformed `methods`, an
|
|
58
|
+
* over-cap document. The field's declared `invalid_reason`.
|
|
59
|
+
*/
|
|
60
|
+
export declare const ERROR_TOKEN_SCOPE_INVALID: "token_scope_invalid";
|
|
61
|
+
/**
|
|
62
|
+
* `error.data.reason` on any refusal of `account_token_create`'s `lifetime` —
|
|
63
|
+
* missing, `null`, an unknown `kind` or key, a `days` out of range. The
|
|
64
|
+
* field's declared `invalid_reason`.
|
|
65
|
+
*/
|
|
66
|
+
export declare const ERROR_TOKEN_LIFETIME_INVALID: "token_lifetime_invalid";
|
|
55
67
|
/**
|
|
56
68
|
* Input for `account_token_create`.
|
|
57
69
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account_action_specs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/account_action_specs.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAW3E,6EAA6E;AAC7E,eAAO,MAAM,WAAW,WAAW,CAAC;AACpC,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEtD,uDAAuD;AACvD,eAAO,MAAM,gBAAgB,WAAW,CAAC;AACzC,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEhE,yCAAyC;AACzC,eAAO,MAAM,iBAAiB;;;;;;;kBAE5B,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAElE,2EAA2E;AAC3E,eAAO,MAAM,kBAAkB;;kBAE7B,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEpE,iFAAiF;AACjF,eAAO,MAAM,mBAAmB;;;kBAG9B,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEtE,6DAA6D;AAC7D,eAAO,MAAM,qBAAqB,WAAW,CAAC;AAC9C,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAE1E,+CAA+C;AAC/C,eAAO,MAAM,sBAAsB;;;kBAGjC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAE5E;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAE7C;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"account_action_specs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/account_action_specs.ts"],"names":[],"mappings":"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"}
|
|
@@ -45,6 +45,18 @@ export const SessionRevokeAllOutput = z.strictObject({
|
|
|
45
45
|
* the Rust spine's `API_TOKEN_NAME_LENGTH_MAX`.
|
|
46
46
|
*/
|
|
47
47
|
export const API_TOKEN_NAME_LENGTH_MAX = 255;
|
|
48
|
+
/**
|
|
49
|
+
* `error.data.reason` on any refusal of `account_token_create`'s `scope` —
|
|
50
|
+
* missing, `null`, an unknown `kind` or key, a malformed `methods`, an
|
|
51
|
+
* over-cap document. The field's declared `invalid_reason`.
|
|
52
|
+
*/
|
|
53
|
+
export const ERROR_TOKEN_SCOPE_INVALID = 'token_scope_invalid';
|
|
54
|
+
/**
|
|
55
|
+
* `error.data.reason` on any refusal of `account_token_create`'s `lifetime` —
|
|
56
|
+
* missing, `null`, an unknown `kind` or key, a `days` out of range. The
|
|
57
|
+
* field's declared `invalid_reason`.
|
|
58
|
+
*/
|
|
59
|
+
export const ERROR_TOKEN_LIFETIME_INVALID = 'token_lifetime_invalid';
|
|
48
60
|
/**
|
|
49
61
|
* Input for `account_token_create`.
|
|
50
62
|
*
|
|
@@ -69,11 +81,13 @@ export const TokenCreateInput = z.strictObject({
|
|
|
69
81
|
description: "What the token may do. `{kind:'full'}` for full account authority, or " +
|
|
70
82
|
"`{kind:'methods',methods:[…]}` to narrow it to named RPC methods — a " +
|
|
71
83
|
'narrowed token is RPC-only and reaches no non-RPC surface that reads ' +
|
|
72
|
-
'account data or carries authority.'
|
|
84
|
+
'account data or carries authority.',
|
|
85
|
+
invalid_reason: ERROR_TOKEN_SCOPE_INVALID
|
|
73
86
|
}),
|
|
74
87
|
lifetime: TokenLifetimeInput.meta({
|
|
75
88
|
description: "How long the token lives. `{kind:'eternal'}` never expires; " +
|
|
76
|
-
"`{kind:'ttl',days:N}` expires N days from mint."
|
|
89
|
+
"`{kind:'ttl',days:N}` expires N days from mint.",
|
|
90
|
+
invalid_reason: ERROR_TOKEN_LIFETIME_INVALID
|
|
77
91
|
})
|
|
78
92
|
});
|
|
79
93
|
/** Output for `account_token_create`. `token` is returned exactly once. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account_actions.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/account_actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,OAAO,EAAsC,KAAK,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAwB9F,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"account_actions.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/account_actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,OAAO,EAAsC,KAAK,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAwB9F,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAC;AA0B3D,4CAA4C;AAC5C,MAAM,WAAW,oBAAoB;IACpC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,GAClC,MAAM,yBAAyB,EAC/B,UAAS,oBAAyB,KAChC,KAAK,CAAC,SAAS,CAyLjB,CAAC"}
|
|
@@ -39,7 +39,7 @@ import { token_lifetime_to_expires_at } from './token_lifetime.js';
|
|
|
39
39
|
import { generate_api_token } from './api_token.js';
|
|
40
40
|
import { DEFAULT_MAX_TOKENS } from './account_route_schema.js';
|
|
41
41
|
import { to_iso8601_seconds } from '../timestamp.js';
|
|
42
|
-
import { account_verify_action_spec, account_session_list_action_spec, account_session_revoke_action_spec, account_session_revoke_all_action_spec, account_token_create_action_spec, account_token_list_action_spec, account_token_revoke_action_spec } from './account_action_specs.js';
|
|
42
|
+
import { account_verify_action_spec, account_session_list_action_spec, account_session_revoke_action_spec, account_session_revoke_all_action_spec, account_token_create_action_spec, account_token_list_action_spec, account_token_revoke_action_spec, ERROR_TOKEN_SCOPE_INVALID } from './account_action_specs.js';
|
|
43
43
|
/**
|
|
44
44
|
* Create the self-service account RPC actions.
|
|
45
45
|
*
|
|
@@ -111,13 +111,16 @@ export const create_account_actions = (deps, options = {}) => {
|
|
|
111
111
|
// a validation error upstream, not a full-authority token.
|
|
112
112
|
const scope = token_scope_from_input(input.scope);
|
|
113
113
|
// Over the stored-document cap is a malformed request, refused before
|
|
114
|
-
// any write (the insert would otherwise throw it as a 500)
|
|
115
|
-
//
|
|
114
|
+
// any write (the insert would otherwise throw it as a 500), with the
|
|
115
|
+
// reason the schema declares for every other `scope` refusal. Twin of
|
|
116
|
+
// the Rust spine's `invalid_params` on `TokenScopeError::TooLarge`.
|
|
116
117
|
try {
|
|
117
118
|
serialize_token_scope(scope);
|
|
118
119
|
}
|
|
119
120
|
catch (err) {
|
|
120
|
-
throw jsonrpc_errors.invalid_params(`invalid scope: ${to_error_message(err)}
|
|
121
|
+
throw jsonrpc_errors.invalid_params(`invalid scope: ${to_error_message(err)}`, {
|
|
122
|
+
reason: ERROR_TOKEN_SCOPE_INVALID
|
|
123
|
+
});
|
|
121
124
|
}
|
|
122
125
|
// `input.lifetime` is required for the same reason — an omitted lifetime
|
|
123
126
|
// is a validation error, never an eternal token.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin_action_specs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/admin_action_specs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"admin_action_specs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/admin_action_specs.ts"],"names":[],"mappings":"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"}
|
|
@@ -24,6 +24,7 @@ import { ActingActor } from '../http/auth_shape.js';
|
|
|
24
24
|
import { AdminSessionJson, AUDIT_LOG_DEFAULT_LIMIT, AuditEventTypeName, AuditLogEventWithUsernamesJson, AuditOutcome, RoleGrantHistoryEventJson } from './audit_log_schema.js';
|
|
25
25
|
import { InviteJson, InviteWithUsernamesJson } from './invite_schema.js';
|
|
26
26
|
import { AppSettingsWithUsernameJson } from './app_settings_schema.js';
|
|
27
|
+
import { ERROR_LIMIT_INVALID, ERROR_OFFSET_INVALID, ERROR_OUTCOME_INVALID, ERROR_SINCE_SEQ_INVALID } from '../http/error_schemas.js';
|
|
27
28
|
/** Max audit-log page size. */
|
|
28
29
|
export const AUDIT_LOG_LIST_LIMIT_MAX = 200;
|
|
29
30
|
/** Default `admin_account_list` page size. */
|
|
@@ -42,9 +43,15 @@ export const AdminAccountListInput = z
|
|
|
42
43
|
.max(ADMIN_ACCOUNT_LIST_LIMIT_MAX)
|
|
43
44
|
.nullish()
|
|
44
45
|
.meta({
|
|
45
|
-
description: `Max accounts to return (default ${ADMIN_ACCOUNT_LIST_DEFAULT_LIMIT}, max ${ADMIN_ACCOUNT_LIST_LIMIT_MAX})
|
|
46
|
+
description: `Max accounts to return (default ${ADMIN_ACCOUNT_LIST_DEFAULT_LIMIT}, max ${ADMIN_ACCOUNT_LIST_LIMIT_MAX}).`,
|
|
47
|
+
invalid_reason: ERROR_LIMIT_INVALID
|
|
46
48
|
}),
|
|
47
|
-
offset: z
|
|
49
|
+
offset: z
|
|
50
|
+
.number()
|
|
51
|
+
.int()
|
|
52
|
+
.min(0)
|
|
53
|
+
.nullish()
|
|
54
|
+
.meta({ description: 'Pagination offset.', invalid_reason: ERROR_OFFSET_INVALID }),
|
|
48
55
|
include_deleted: z.boolean().nullish().meta({
|
|
49
56
|
description: 'Include soft-deleted (tombstoned) accounts in the listing. Default false (active only). Used by the admin UI to surface accounts for reactivation via `account_undelete`.'
|
|
50
57
|
})
|
|
@@ -97,7 +104,8 @@ export const AuditLogListInput = z
|
|
|
97
104
|
description: 'Filter by event type. Accepts builtin or consumer-registered names (regex-validated).'
|
|
98
105
|
}),
|
|
99
106
|
outcome: AuditOutcome.nullish().meta({
|
|
100
|
-
description: 'Filter by outcome (`success` or `failure`).'
|
|
107
|
+
description: 'Filter by outcome (`success` or `failure`).',
|
|
108
|
+
invalid_reason: ERROR_OUTCOME_INVALID
|
|
101
109
|
}),
|
|
102
110
|
account_id: Uuid.nullish().meta({ description: 'Filter by actor account id.' }),
|
|
103
111
|
limit: z
|
|
@@ -107,11 +115,18 @@ export const AuditLogListInput = z
|
|
|
107
115
|
.max(AUDIT_LOG_LIST_LIMIT_MAX)
|
|
108
116
|
.nullish()
|
|
109
117
|
.meta({
|
|
110
|
-
description: `Max rows to return (default ${AUDIT_LOG_DEFAULT_LIMIT}, max ${AUDIT_LOG_LIST_LIMIT_MAX})
|
|
118
|
+
description: `Max rows to return (default ${AUDIT_LOG_DEFAULT_LIMIT}, max ${AUDIT_LOG_LIST_LIMIT_MAX}).`,
|
|
119
|
+
invalid_reason: ERROR_LIMIT_INVALID
|
|
111
120
|
}),
|
|
112
|
-
offset: z
|
|
121
|
+
offset: z
|
|
122
|
+
.number()
|
|
123
|
+
.int()
|
|
124
|
+
.min(0)
|
|
125
|
+
.nullish()
|
|
126
|
+
.meta({ description: 'Pagination offset.', invalid_reason: ERROR_OFFSET_INVALID }),
|
|
113
127
|
since_seq: z.number().int().min(0).nullish().meta({
|
|
114
|
-
description: 'Gap-fill from this seq forward. Used for SSE reconnection.'
|
|
128
|
+
description: 'Gap-fill from this seq forward. Used for SSE reconnection.',
|
|
129
|
+
invalid_reason: ERROR_SINCE_SEQ_INVALID
|
|
115
130
|
}),
|
|
116
131
|
acting: ActingActor
|
|
117
132
|
})
|
|
@@ -130,9 +145,15 @@ export const AuditLogRoleGrantHistoryInput = z
|
|
|
130
145
|
.max(AUDIT_LOG_LIST_LIMIT_MAX)
|
|
131
146
|
.nullish()
|
|
132
147
|
.meta({
|
|
133
|
-
description: `Max rows to return (default ${AUDIT_LOG_DEFAULT_LIMIT}, max ${AUDIT_LOG_LIST_LIMIT_MAX})
|
|
148
|
+
description: `Max rows to return (default ${AUDIT_LOG_DEFAULT_LIMIT}, max ${AUDIT_LOG_LIST_LIMIT_MAX}).`,
|
|
149
|
+
invalid_reason: ERROR_LIMIT_INVALID
|
|
134
150
|
}),
|
|
135
|
-
offset: z
|
|
151
|
+
offset: z
|
|
152
|
+
.number()
|
|
153
|
+
.int()
|
|
154
|
+
.min(0)
|
|
155
|
+
.nullish()
|
|
156
|
+
.meta({ description: 'Pagination offset.', invalid_reason: ERROR_OFFSET_INVALID }),
|
|
136
157
|
acting: ActingActor
|
|
137
158
|
})
|
|
138
159
|
.default({});
|
|
@@ -31,6 +31,8 @@
|
|
|
31
31
|
* throws are isolated.
|
|
32
32
|
* - `drain_inflight()` — test-binary barrier: await every in-flight `emit`
|
|
33
33
|
* write, on an emitter built with `track_inflight: true`.
|
|
34
|
+
* - `is_tracking_inflight()` — whether that barrier can wait on anything, so a
|
|
35
|
+
* test binary built without tracking is caught rather than racing.
|
|
34
36
|
*
|
|
35
37
|
* ## When listeners hear about a row
|
|
36
38
|
*
|
|
@@ -227,6 +229,18 @@ export interface AuditEmitter {
|
|
|
227
229
|
* to wait for. Twin of the Rust `fuz_auth` `AuditEmitter::drain_inflight`.
|
|
228
230
|
*/
|
|
229
231
|
drain_inflight(): Promise<void>;
|
|
232
|
+
/**
|
|
233
|
+
* Whether this emitter tracks its in-flight `emit` writes — `true` only
|
|
234
|
+
* when built with `track_inflight: true`. When `false`, `drain_inflight`
|
|
235
|
+
* resolves at once and waits on nothing.
|
|
236
|
+
*
|
|
237
|
+
* The `_testing_drain_effects` action reports it as `tracked`, and the
|
|
238
|
+
* `list_audit_events` reads refuse `false`: a test binary whose emitter was
|
|
239
|
+
* built without tracking would otherwise answer the drain at once and its
|
|
240
|
+
* audit reads would race the writes. Twin of the Rust `fuz_auth`
|
|
241
|
+
* `AuditEmitter::is_tracking_inflight`.
|
|
242
|
+
*/
|
|
243
|
+
is_tracking_inflight(): boolean;
|
|
230
244
|
}
|
|
231
245
|
/**
|
|
232
246
|
* Signature of `AuditEmitter.emit` — captured by the inner closure so
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit_emitter.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/audit_emitter.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"audit_emitter.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/audit_emitter.ts"],"names":[],"mappings":"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"}
|