@fuzdev/fuz_app 0.140.0 → 0.142.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/actions/CLAUDE.md +72 -22
- package/dist/actions/action_rpc.d.ts +5 -1
- package/dist/actions/action_rpc.d.ts.map +1 -1
- package/dist/actions/action_rpc.js +9 -1
- package/dist/actions/connection_closer.d.ts +44 -4
- package/dist/actions/connection_closer.d.ts.map +1 -1
- package/dist/actions/connection_closer.js +33 -3
- package/dist/actions/perform_action.d.ts +10 -0
- package/dist/actions/perform_action.d.ts.map +1 -1
- package/dist/actions/perform_action.js +23 -9
- package/dist/actions/register_action_ws.d.ts +42 -6
- package/dist/actions/register_action_ws.d.ts.map +1 -1
- package/dist/actions/register_action_ws.js +87 -19
- package/dist/actions/register_ws_endpoint.d.ts +15 -6
- package/dist/actions/register_ws_endpoint.d.ts.map +1 -1
- package/dist/actions/register_ws_endpoint.js +10 -4
- package/dist/actions/socket.svelte.d.ts +19 -4
- package/dist/actions/socket.svelte.d.ts.map +1 -1
- package/dist/actions/socket.svelte.js +31 -4
- package/dist/actions/transports.d.ts +30 -1
- package/dist/actions/transports.d.ts.map +1 -1
- package/dist/actions/transports.js +30 -1
- package/dist/actions/transports_ws_auth_guard.d.ts +13 -6
- package/dist/actions/transports_ws_auth_guard.d.ts.map +1 -1
- package/dist/actions/transports_ws_auth_guard.js +24 -10
- package/dist/actions/transports_ws_backend.d.ts +51 -5
- package/dist/actions/transports_ws_backend.d.ts.map +1 -1
- package/dist/actions/transports_ws_backend.js +62 -9
- package/dist/actions/ws_endpoint_spec.d.ts +11 -10
- package/dist/actions/ws_endpoint_spec.d.ts.map +1 -1
- package/dist/auth/CLAUDE.md +44 -22
- package/dist/auth/account_actions.d.ts.map +1 -1
- package/dist/auth/account_actions.js +12 -1
- package/dist/auth/account_route_schema.d.ts +1 -0
- package/dist/auth/account_route_schema.d.ts.map +1 -1
- package/dist/auth/account_route_schema.js +12 -0
- package/dist/auth/account_routes.d.ts +7 -2
- package/dist/auth/account_routes.d.ts.map +1 -1
- package/dist/auth/account_routes.js +240 -187
- package/dist/auth/admin_action_specs.d.ts +6 -1
- package/dist/auth/admin_action_specs.d.ts.map +1 -1
- package/dist/auth/admin_action_specs.js +6 -1
- package/dist/auth/admin_actions.d.ts.map +1 -1
- package/dist/auth/admin_actions.js +14 -2
- package/dist/auth/api_token.d.ts +20 -0
- package/dist/auth/api_token.d.ts.map +1 -1
- package/dist/auth/api_token.js +21 -1
- package/dist/auth/api_token_queries.d.ts +22 -4
- package/dist/auth/api_token_queries.d.ts.map +1 -1
- package/dist/auth/api_token_queries.js +11 -6
- package/dist/auth/audit_log_routes.d.ts +10 -0
- package/dist/auth/audit_log_routes.d.ts.map +1 -1
- package/dist/auth/audit_log_routes.js +20 -0
- package/dist/auth/audit_log_schema.d.ts +30 -5
- package/dist/auth/audit_log_schema.d.ts.map +1 -1
- package/dist/auth/audit_log_schema.js +30 -0
- package/dist/auth/bearer_auth.d.ts +4 -2
- package/dist/auth/bearer_auth.d.ts.map +1 -1
- package/dist/auth/bearer_auth.js +19 -8
- package/dist/auth/bootstrap_route_schema.d.ts +1 -0
- package/dist/auth/bootstrap_route_schema.d.ts.map +1 -1
- package/dist/auth/bootstrap_route_schema.js +1 -0
- package/dist/auth/bootstrap_routes.d.ts.map +1 -1
- package/dist/auth/bootstrap_routes.js +85 -76
- package/dist/auth/cell_action_specs.d.ts +7 -3
- package/dist/auth/cell_action_specs.d.ts.map +1 -1
- package/dist/auth/cell_action_specs.js +9 -5
- package/dist/auth/cell_actions.d.ts +3 -3
- package/dist/auth/cell_actions.d.ts.map +1 -1
- package/dist/auth/cell_actions.js +67 -38
- package/dist/auth/cell_authorize.d.ts +69 -8
- package/dist/auth/cell_authorize.d.ts.map +1 -1
- package/dist/auth/cell_authorize.js +89 -9
- package/dist/auth/cell_field_action_specs.d.ts +5 -4
- package/dist/auth/cell_field_action_specs.d.ts.map +1 -1
- package/dist/auth/cell_field_action_specs.js +7 -7
- package/dist/auth/cell_field_actions.d.ts +7 -5
- package/dist/auth/cell_field_actions.d.ts.map +1 -1
- package/dist/auth/cell_field_actions.js +24 -22
- package/dist/auth/cell_grant_action_specs.d.ts +6 -0
- package/dist/auth/cell_grant_action_specs.d.ts.map +1 -1
- package/dist/auth/cell_grant_action_specs.js +6 -0
- package/dist/auth/cell_grant_actions.d.ts +3 -1
- package/dist/auth/cell_grant_actions.d.ts.map +1 -1
- package/dist/auth/cell_grant_actions.js +16 -2
- package/dist/auth/cell_item_action_specs.d.ts +5 -4
- package/dist/auth/cell_item_action_specs.d.ts.map +1 -1
- package/dist/auth/cell_item_action_specs.js +7 -7
- package/dist/auth/cell_item_actions.d.ts +6 -5
- package/dist/auth/cell_item_actions.d.ts.map +1 -1
- package/dist/auth/cell_item_actions.js +23 -22
- package/dist/auth/cell_relation_list_limit.d.ts +20 -0
- package/dist/auth/cell_relation_list_limit.d.ts.map +1 -0
- package/dist/auth/cell_relation_list_limit.js +27 -0
- package/dist/auth/cell_relation_visibility.d.ts +4 -3
- package/dist/auth/cell_relation_visibility.d.ts.map +1 -1
- package/dist/auth/cell_relation_visibility.js +6 -5
- package/dist/auth/cell_steward.d.ts +45 -0
- package/dist/auth/cell_steward.d.ts.map +1 -0
- package/dist/auth/cell_steward.js +53 -0
- package/dist/auth/cleanup.d.ts +9 -9
- package/dist/auth/cleanup.js +9 -9
- package/dist/auth/credential_deadline.d.ts +95 -0
- package/dist/auth/credential_deadline.d.ts.map +1 -0
- package/dist/auth/credential_deadline.js +139 -0
- package/dist/auth/daemon_token_middleware.d.ts.map +1 -1
- package/dist/auth/daemon_token_middleware.js +4 -1
- package/dist/auth/middleware.d.ts +90 -12
- package/dist/auth/middleware.d.ts.map +1 -1
- package/dist/auth/middleware.js +115 -16
- package/dist/auth/request_context.d.ts +8 -2
- package/dist/auth/request_context.d.ts.map +1 -1
- package/dist/auth/request_context.js +20 -4
- package/dist/auth/resolved_auth.d.ts +13 -2
- package/dist/auth/resolved_auth.d.ts.map +1 -1
- package/dist/auth/resolved_auth.js +5 -4
- package/dist/auth/role_grant_offer_action_specs.d.ts +5 -0
- package/dist/auth/role_grant_offer_action_specs.d.ts.map +1 -1
- package/dist/auth/role_grant_offer_action_specs.js +6 -1
- package/dist/auth/role_grant_offer_actions.d.ts.map +1 -1
- package/dist/auth/role_grant_offer_actions.js +23 -16
- package/dist/auth/role_grant_offer_queries.d.ts +8 -6
- package/dist/auth/role_grant_offer_queries.d.ts.map +1 -1
- package/dist/auth/role_grant_offer_queries.js +16 -8
- package/dist/auth/session_cookie.d.ts +4 -0
- package/dist/auth/session_cookie.d.ts.map +1 -1
- package/dist/auth/session_cookie.js +3 -2
- package/dist/auth/session_middleware.d.ts +1 -1
- package/dist/auth/session_middleware.d.ts.map +1 -1
- package/dist/auth/session_middleware.js +4 -1
- package/dist/auth/session_queries.d.ts +19 -2
- package/dist/auth/session_queries.d.ts.map +1 -1
- package/dist/auth/session_queries.js +8 -2
- package/dist/auth/signup_route_schema.d.ts.map +1 -1
- package/dist/auth/signup_route_schema.js +1 -0
- package/dist/auth/signup_routes.d.ts +4 -3
- package/dist/auth/signup_routes.d.ts.map +1 -1
- package/dist/auth/signup_routes.js +157 -134
- package/dist/auth/token_scope.d.ts +7 -1
- package/dist/auth/token_scope.d.ts.map +1 -1
- package/dist/auth/token_scope.js +8 -2
- package/dist/db/CLAUDE.md +32 -19
- package/dist/db/cell_ddl.d.ts +1 -2
- package/dist/db/cell_ddl.d.ts.map +1 -1
- package/dist/db/cell_ddl.js +1 -2
- package/dist/db/cell_field_queries.d.ts +20 -18
- package/dist/db/cell_field_queries.d.ts.map +1 -1
- package/dist/db/cell_field_queries.js +28 -22
- package/dist/db/cell_item_queries.d.ts +20 -14
- package/dist/db/cell_item_queries.d.ts.map +1 -1
- package/dist/db/cell_item_queries.js +28 -18
- package/dist/db/cell_moderation.d.ts +67 -0
- package/dist/db/cell_moderation.d.ts.map +1 -0
- package/dist/db/cell_moderation.js +66 -0
- package/dist/db/cell_queries.d.ts +44 -14
- package/dist/db/cell_queries.d.ts.map +1 -1
- package/dist/db/cell_queries.js +68 -45
- package/dist/db/cell_view_sql.d.ts +102 -0
- package/dist/db/cell_view_sql.d.ts.map +1 -0
- package/dist/db/cell_view_sql.js +112 -0
- package/dist/db/db_pg.d.ts +1 -1
- package/dist/db/db_pg.js +1 -1
- package/dist/hono_context.d.ts +23 -0
- package/dist/hono_context.d.ts.map +1 -1
- package/dist/hono_context.js +19 -0
- package/dist/http/CLAUDE.md +41 -15
- package/dist/http/auth_shape.d.ts +5 -2
- package/dist/http/auth_shape.d.ts.map +1 -1
- package/dist/http/auth_shape.js +5 -2
- package/dist/http/ip_canonical.d.ts +30 -3
- package/dist/http/ip_canonical.d.ts.map +1 -1
- package/dist/http/ip_canonical.js +50 -3
- package/dist/http/middleware_spec.d.ts +16 -0
- package/dist/http/middleware_spec.d.ts.map +1 -1
- package/dist/http/origin.d.ts +113 -18
- package/dist/http/origin.d.ts.map +1 -1
- package/dist/http/origin.js +247 -127
- package/dist/http/route_spec.d.ts +21 -0
- package/dist/http/route_spec.d.ts.map +1 -1
- package/dist/http/schema_helpers.d.ts +22 -0
- package/dist/http/schema_helpers.d.ts.map +1 -1
- package/dist/http/schema_helpers.js +24 -0
- package/dist/http/surface.d.ts +6 -1
- package/dist/http/surface.d.ts.map +1 -1
- package/dist/http/surface.js +12 -5
- package/dist/primitive_schemas.d.ts +10 -1
- package/dist/primitive_schemas.d.ts.map +1 -1
- package/dist/primitive_schemas.js +11 -2
- package/dist/rate_limiter.d.ts +179 -12
- package/dist/rate_limiter.d.ts.map +1 -1
- package/dist/rate_limiter.js +352 -42
- package/dist/realtime/sse_auth_guard.d.ts +22 -6
- package/dist/realtime/sse_auth_guard.d.ts.map +1 -1
- package/dist/realtime/sse_auth_guard.js +31 -12
- package/dist/realtime/subscriber_registry.d.ts +10 -1
- package/dist/realtime/subscriber_registry.d.ts.map +1 -1
- package/dist/realtime/subscriber_registry.js +10 -1
- package/dist/server/app_server.d.ts +20 -7
- package/dist/server/app_server.d.ts.map +1 -1
- package/dist/server/app_server.js +8 -3
- package/dist/server/env.d.ts +2 -1
- package/dist/server/env.d.ts.map +1 -1
- package/dist/server/env.js +7 -17
- package/dist/server/serve_fact_route.d.ts +8 -4
- package/dist/server/serve_fact_route.d.ts.map +1 -1
- package/dist/server/serve_fact_route.js +16 -6
- package/dist/testing/CLAUDE.md +164 -25
- package/dist/testing/adversarial_headers.d.ts.map +1 -1
- package/dist/testing/adversarial_headers.js +13 -6
- package/dist/testing/connection_closer_helpers.d.ts +6 -1
- package/dist/testing/connection_closer_helpers.d.ts.map +1 -1
- package/dist/testing/connection_closer_helpers.js +4 -0
- package/dist/testing/cross_backend/account_lifecycle.d.ts.map +1 -1
- package/dist/testing/cross_backend/account_lifecycle.js +37 -2
- package/dist/testing/cross_backend/body_size.d.ts.map +1 -1
- package/dist/testing/cross_backend/body_size.js +14 -65
- package/dist/testing/cross_backend/capabilities.d.ts +26 -2
- package/dist/testing/cross_backend/capabilities.d.ts.map +1 -1
- package/dist/testing/cross_backend/capabilities.js +9 -3
- package/dist/testing/cross_backend/cell_gated_create.d.ts +38 -0
- package/dist/testing/cross_backend/cell_gated_create.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_gated_create.js +401 -5
- package/dist/testing/cross_backend/cell_relations.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_relations.js +145 -2
- package/dist/testing/cross_backend/conformance_case.d.ts +11 -3
- package/dist/testing/cross_backend/conformance_case.d.ts.map +1 -1
- package/dist/testing/cross_backend/conformance_case.js +6 -0
- package/dist/testing/cross_backend/conformance_table.d.ts.map +1 -1
- package/dist/testing/cross_backend/conformance_table.js +20 -19
- package/dist/testing/cross_backend/credential_deadline.d.ts +25 -0
- package/dist/testing/cross_backend/credential_deadline.d.ts.map +1 -0
- package/dist/testing/cross_backend/credential_deadline.js +185 -0
- package/dist/testing/cross_backend/default_backend_configs.d.ts.map +1 -1
- package/dist/testing/cross_backend/default_backend_configs.js +13 -2
- package/dist/testing/cross_backend/expected_schema.json +0 -1
- package/dist/testing/cross_backend/full_spine_mount.d.ts +3 -0
- package/dist/testing/cross_backend/full_spine_mount.d.ts.map +1 -1
- package/dist/testing/cross_backend/full_spine_mount.js +7 -1
- package/dist/testing/cross_backend/login_security.d.ts +16 -0
- package/dist/testing/cross_backend/login_security.d.ts.map +1 -1
- package/dist/testing/cross_backend/login_security.js +154 -0
- package/dist/testing/cross_backend/narrowed_api_token.d.ts +23 -0
- package/dist/testing/cross_backend/narrowed_api_token.d.ts.map +1 -0
- package/dist/testing/cross_backend/narrowed_api_token.js +40 -0
- package/dist/testing/cross_backend/origin.d.ts.map +1 -1
- package/dist/testing/cross_backend/origin.js +6 -26
- package/dist/testing/cross_backend/origin_conformance.d.ts +152 -0
- package/dist/testing/cross_backend/origin_conformance.d.ts.map +1 -0
- package/dist/testing/cross_backend/origin_conformance.js +136 -0
- package/dist/testing/cross_backend/origin_conformance.json +1679 -0
- package/dist/testing/cross_backend/origin_scope.d.ts +16 -0
- package/dist/testing/cross_backend/origin_scope.d.ts.map +1 -0
- package/dist/testing/cross_backend/origin_scope.js +140 -0
- package/dist/testing/cross_backend/query_shape.d.ts.map +1 -1
- package/dist/testing/cross_backend/query_shape.js +24 -2
- package/dist/testing/cross_backend/role_grant_cross_helpers.d.ts +35 -0
- package/dist/testing/cross_backend/role_grant_cross_helpers.d.ts.map +1 -0
- package/dist/testing/cross_backend/role_grant_cross_helpers.js +64 -0
- package/dist/testing/cross_backend/role_grant_offer_notification_ws.d.ts +8 -0
- package/dist/testing/cross_backend/role_grant_offer_notification_ws.d.ts.map +1 -1
- package/dist/testing/cross_backend/role_grant_offer_notification_ws.js +44 -33
- package/dist/testing/cross_backend/role_grant_participation.d.ts.map +1 -1
- package/dist/testing/cross_backend/role_grant_participation.js +64 -0
- package/dist/testing/cross_backend/rust_spine_stub_backend_config.d.ts.map +1 -1
- package/dist/testing/cross_backend/rust_spine_stub_backend_config.js +6 -4
- package/dist/testing/cross_backend/spine_surface_constants.d.ts +20 -1
- package/dist/testing/cross_backend/spine_surface_constants.d.ts.map +1 -1
- package/dist/testing/cross_backend/spine_surface_constants.js +23 -1
- package/dist/testing/cross_backend/testing_backdoor.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_backdoor.js +20 -7
- package/dist/testing/cross_backend/testing_reset_actions.d.ts +180 -5
- package/dist/testing/cross_backend/testing_reset_actions.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_reset_actions.js +154 -5
- package/dist/testing/cross_backend/token_scope_surface.d.ts.map +1 -1
- package/dist/testing/cross_backend/token_scope_surface.js +25 -21
- package/dist/testing/cross_backend/transport_composition.d.ts +60 -0
- package/dist/testing/cross_backend/transport_composition.d.ts.map +1 -0
- package/dist/testing/cross_backend/transport_composition.js +364 -0
- package/dist/testing/cross_backend/ts_spine_backend_config.d.ts.map +1 -1
- package/dist/testing/cross_backend/ts_spine_backend_config.js +21 -6
- package/dist/testing/cross_backend/ws_action_rate_limit.d.ts.map +1 -1
- package/dist/testing/cross_backend/ws_action_rate_limit.js +21 -1
- package/dist/testing/cross_backend/ws_role_gated.d.ts +38 -0
- package/dist/testing/cross_backend/ws_role_gated.d.ts.map +1 -0
- package/dist/testing/cross_backend/ws_role_gated.js +142 -0
- package/dist/testing/entities.d.ts +23 -0
- package/dist/testing/entities.d.ts.map +1 -1
- package/dist/testing/entities.js +37 -0
- package/dist/testing/integration.d.ts.map +1 -1
- package/dist/testing/integration.js +3 -1
- package/dist/testing/middleware.d.ts +10 -0
- package/dist/testing/middleware.d.ts.map +1 -1
- package/dist/testing/middleware.js +31 -7
- package/dist/testing/schema_introspect.js +1 -1
- package/dist/testing/schema_parity.d.ts +4 -3
- package/dist/testing/schema_parity.d.ts.map +1 -1
- package/dist/testing/schema_parity.js +4 -3
- package/dist/testing/schema_ready_fixture.d.ts +2 -4
- package/dist/testing/schema_ready_fixture.d.ts.map +1 -1
- package/dist/testing/schema_ready_fixture.js +2 -4
- package/dist/testing/stubs.d.ts +16 -3
- package/dist/testing/stubs.d.ts.map +1 -1
- package/dist/testing/stubs.js +20 -7
- package/dist/testing/surface_invariants.js +2 -2
- package/dist/ui/auth_state.svelte.d.ts +10 -0
- package/dist/ui/auth_state.svelte.d.ts.map +1 -1
- package/dist/ui/auth_state.svelte.js +22 -4
- package/package.json +1 -1
- package/dist/db/cell_history_ddl.d.ts +0 -38
- package/dist/db/cell_history_ddl.d.ts.map +0 -1
- package/dist/db/cell_history_ddl.js +0 -61
|
@@ -668,7 +668,12 @@ export declare const invite_delete_action_spec: {
|
|
|
668
668
|
/**
|
|
669
669
|
* Soft-delete an account (reversible tombstone). Self-or-admin: the
|
|
670
670
|
* caller may delete their own account; deleting another requires the
|
|
671
|
-
* admin role (handler-enforced elevation).
|
|
671
|
+
* admin role (handler-enforced elevation). The self path is session-only,
|
|
672
|
+
* also handler-enforced — the spec declares no `credential_types` so an
|
|
673
|
+
* admin deleting another account keeps any credential, and a self-delete
|
|
674
|
+
* over an API or daemon token gets the dispatcher's own 403
|
|
675
|
+
* `credential_type_required` (`required_credential_types: ['session']`),
|
|
676
|
+
* ahead of the keeper / last-admin guards. No `admin_` prefix — the
|
|
672
677
|
* privilege lives in the auth check, not the name, so self-service
|
|
673
678
|
* deletion stays open (`delete` = soft, `purge` = hard).
|
|
674
679
|
*/
|
|
@@ -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;AAgB3E,+BAA+B;AAC/B,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAE5C,8CAA8C;AAC9C,eAAO,MAAM,gCAAgC,KAAK,CAAC;AACnD,0CAA0C;AAC1C,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAIhD,sCAAsC;AACtC,eAAO,MAAM,qBAAqB;;;;;mBAoBrB,CAAC;AACd,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAE1E,uCAAuC;AACvC,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAGjC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAE5E,sCAAsC;AACtC,eAAO,MAAM,qBAAqB;;mBAIrB,CAAC;AACd,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAE1E,mGAAmG;AACnG,eAAO,MAAM,sBAAsB;;;;;;;;kBAEjC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAE5E,4CAA4C;AAC5C,eAAO,MAAM,0BAA0B;;;kBAGrC,CAAC;AACH,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAEpF,6CAA6C;AAC7C,eAAO,MAAM,2BAA2B;;;kBAGtC,CAAC;AACH,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEtF,0CAA0C;AAC1C,eAAO,MAAM,wBAAwB;;;kBAGnC,CAAC;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAEhF,2CAA2C;AAC3C,eAAO,MAAM,yBAAyB;;;kBAGpC,CAAC;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAElF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;mBA2BjB,CAAC;AACd,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAElE,mCAAmC;AACnC,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;kBAE7B,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEpE,gDAAgD;AAChD,eAAO,MAAM,6BAA6B;;;;mBAgB7B,CAAC;AACd,MAAM,MAAM,6BAA6B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAE1F,iDAAiD;AACjD,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;;kBAEzC,CAAC;AACH,MAAM,MAAM,8BAA8B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC;AAE5F,wFAAwF;AACxF,eAAO,MAAM,iBAAiB;;;;kBAS3B,CAAC;AACJ,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAElE,kCAAkC;AAClC,eAAO,MAAM,kBAAkB;;;;;;;;;;;kBAG7B,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEpE,+BAA+B;AAC/B,eAAO,MAAM,eAAe;;mBAIf,CAAC;AACd,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAE9D,2FAA2F;AAC3F,eAAO,MAAM,gBAAgB;;;;;;;;;;;;kBAE3B,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEhE,iCAAiC;AACjC,eAAO,MAAM,iBAAiB;;;kBAG5B,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAElE,kCAAkC;AAClC,eAAO,MAAM,kBAAkB;;kBAE7B,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEpE,oCAAoC;AACpC,eAAO,MAAM,mBAAmB;;mBAInB,CAAC;AACd,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEtE,qCAAqC;AACrC,eAAO,MAAM,oBAAoB;;;;;;;kBAE/B,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAExE,uCAAuC;AACvC,eAAO,MAAM,sBAAsB;;;kBAGjC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAE5E,wCAAwC;AACxC,eAAO,MAAM,uBAAuB;;;;;;;;kBAGlC,CAAC;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAE9E;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,EAAG,qBAA8B,CAAC;AAExE;;;;;;;;;GASG;AACH,eAAO,MAAM,0BAA0B,EAAG,sBAA+B,CAAC;AAE1E;;;;;;;;;GASG;AACH,eAAO,MAAM,8BAA8B,EAAG,0BAAmC,CAAC;AAElF;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB;;;mBAOlB,CAAC;AACd,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEpE,mCAAmC;AACnC,eAAO,MAAM,mBAAmB;;;kBAG9B,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEtE,0EAA0E;AAC1E,eAAO,MAAM,iBAAiB;;;;kBAM5B,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAElE,kCAAkC;AAClC,eAAO,MAAM,kBAAkB;;;kBAG7B,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEpE;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB;;;kBAG/B,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAExE,qCAAqC;AACrC,eAAO,MAAM,qBAAqB;;;kBAGhC,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAI1E;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAWN,CAAC;AAEtC;;;;GAIG;AACH,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;CAWN,CAAC;AAEtC,eAAO,MAAM,oCAAoC;;;;;;;;;;;;;;;;;;;;;CAWZ,CAAC;AAEtC,eAAO,MAAM,kCAAkC;;;;;;;;;;;;;;;;;;;;;CAWV,CAAC;AAEtC;;;;;;;GAOG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAWF,CAAC;AAEtC;;;;GAIG;AACH,eAAO,MAAM,wCAAwC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAWhB,CAAC;AAEtC,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAWD,CAAC;AAEtC;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAWC,CAAC;AAEtC,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;CAWD,CAAC;AAEtC
|
|
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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"}
|
|
@@ -412,7 +412,12 @@ export const invite_delete_action_spec = {
|
|
|
412
412
|
/**
|
|
413
413
|
* Soft-delete an account (reversible tombstone). Self-or-admin: the
|
|
414
414
|
* caller may delete their own account; deleting another requires the
|
|
415
|
-
* admin role (handler-enforced elevation).
|
|
415
|
+
* admin role (handler-enforced elevation). The self path is session-only,
|
|
416
|
+
* also handler-enforced — the spec declares no `credential_types` so an
|
|
417
|
+
* admin deleting another account keeps any credential, and a self-delete
|
|
418
|
+
* over an API or daemon token gets the dispatcher's own 403
|
|
419
|
+
* `credential_type_required` (`required_credential_types: ['session']`),
|
|
420
|
+
* ahead of the keeper / last-admin guards. No `admin_` prefix — the
|
|
416
421
|
* privilege lives in the auth check, not the name, so self-service
|
|
417
422
|
* deletion stays open (`delete` = soft, `purge` = hard).
|
|
418
423
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin_actions.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/admin_actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EAAuC,KAAK,SAAS,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"admin_actions.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/admin_actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EAAuC,KAAK,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAI/F,OAAO,EAKN,KAAK,gBAAgB,EACrB,MAAM,kBAAkB,CAAC;AAyC1B,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAC;AA0D3D,0CAA0C;AAC1C,MAAM,WAAW,kBAAkB;IAClC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,gBAAgB,CAAC;CACzB;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,oBAAoB,GAChC,MAAM,yBAAyB,EAC/B,UAAS,kBAAuB,KAC9B,KAAK,CAAC,SAAS,CA+gBjB,CAAC"}
|
|
@@ -30,7 +30,8 @@
|
|
|
30
30
|
*/
|
|
31
31
|
import { rpc_action } from '../actions/action_rpc.js';
|
|
32
32
|
import { queue_connection_close } from '../actions/connection_closer.js';
|
|
33
|
-
import {
|
|
33
|
+
import { credential_type_required_error } from '../actions/perform_action.js';
|
|
34
|
+
import { jsonrpc_errors, ThrownJsonrpcError } from '../http/jsonrpc_errors.js';
|
|
34
35
|
import { builtin_role_specs_by_name, list_roles_with_grant_path, ROLE_ADMIN, ROLE_KEEPER } from './role_schema.js';
|
|
35
36
|
import { has_scoped_role } from './request_context.js';
|
|
36
37
|
import { query_account_has_global_role, query_account_has_active_global_role, query_count_active_accounts_with_global_role } from './role_grant_queries.js';
|
|
@@ -279,13 +280,24 @@ export const create_admin_actions = (deps, options = {}) => {
|
|
|
279
280
|
}
|
|
280
281
|
};
|
|
281
282
|
// Soft-delete an account (reversible tombstone). Self-or-admin:
|
|
282
|
-
// deleting another account requires the admin role.
|
|
283
|
+
// deleting another account requires the admin role. A self-delete is
|
|
284
|
+
// session-only — enforced here, not on the spec, whose gate stays open so
|
|
285
|
+
// an admin deleting another account keeps any credential. Tombstones the
|
|
283
286
|
// account + its actor(s), revokes sessions/tokens, closes sockets, and
|
|
284
287
|
// emits `account_delete` + one `actor_delete` per soft-deleted actor —
|
|
285
288
|
// each carrying its identity snapshot. `delete` = soft.
|
|
286
289
|
const account_delete_handler = async (input, ctx) => {
|
|
287
290
|
const auth = ctx.auth;
|
|
291
|
+
// `Uuid` outputs lowercase, the form `auth.account.id` is in, so an
|
|
292
|
+
// uppercased own id still reads as self
|
|
288
293
|
const target_account_id = input.account_id ?? auth.account.id;
|
|
294
|
+
// Self path: a session only (API and daemon tokens alike), with the
|
|
295
|
+
// dispatcher's own credential-type refusal, before the guards below say
|
|
296
|
+
// anything about the account — a leaked token can't end its own account.
|
|
297
|
+
if (target_account_id === auth.account.id && ctx.credential_type !== 'session') {
|
|
298
|
+
const refusal = credential_type_required_error(['session']);
|
|
299
|
+
throw new ThrownJsonrpcError(refusal.code, refusal.message, refusal.data);
|
|
300
|
+
}
|
|
289
301
|
// Self-or-admin elevation: deleting someone else needs the **global**
|
|
290
302
|
// admin grant — a scoped `admin` row confers no cross-account authority.
|
|
291
303
|
if (target_account_id !== auth.account.id && !has_scoped_role(auth, ROLE_ADMIN, null)) {
|
package/dist/auth/api_token.d.ts
CHANGED
|
@@ -11,6 +11,26 @@
|
|
|
11
11
|
import { z } from 'zod';
|
|
12
12
|
/** Prefix for all fuz API tokens (enables secret scanning). */
|
|
13
13
|
export declare const API_TOKEN_PREFIX = "secret_fuz_token_";
|
|
14
|
+
/** Random bytes encoded into the raw token body (256 bits). */
|
|
15
|
+
export declare const API_TOKEN_ENTROPY_BYTES = 32;
|
|
16
|
+
/** Length of the unpadded base64url body that encodes `API_TOKEN_ENTROPY_BYTES`. */
|
|
17
|
+
export declare const API_TOKEN_BODY_LENGTH: number;
|
|
18
|
+
/**
|
|
19
|
+
* Regex for a raw API token: `API_TOKEN_PREFIX` plus exactly
|
|
20
|
+
* `API_TOKEN_BODY_LENGTH` base64url characters. Matches the format produced
|
|
21
|
+
* by `generate_api_token`.
|
|
22
|
+
*/
|
|
23
|
+
export declare const API_TOKEN_REGEX: RegExp;
|
|
24
|
+
/**
|
|
25
|
+
* Whether `raw` has the shape of a raw API token — the bearer path's precheck,
|
|
26
|
+
* so a value that cannot be a token costs no database work. A `true` says
|
|
27
|
+
* nothing about whether the token exists. Twin of the Rust spine's
|
|
28
|
+
* `is_api_token_shaped`.
|
|
29
|
+
*
|
|
30
|
+
* @param raw - the value from the `Authorization: Bearer` header
|
|
31
|
+
* @returns `true` when `raw` matches `API_TOKEN_REGEX`
|
|
32
|
+
*/
|
|
33
|
+
export declare const is_api_token_shaped: (raw: string) => boolean;
|
|
14
34
|
/**
|
|
15
35
|
* Regex for the public API token id (e.g. `tok_abC0_d-3xyzA`). Twelve
|
|
16
36
|
* base64url characters after the `tok_` prefix. Matches the format produced
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api_token.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/api_token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,+DAA+D;AAC/D,eAAO,MAAM,gBAAgB,sBAAsB,CAAC;AAEpD;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,QAA4B,CAAC;AAE5D,8CAA8C;AAC9C,eAAO,MAAM,UAAU,aAAuC,CAAC;AAC/D,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAEpD;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,KAAG,MAA4B,CAAC;AAE5E;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,QAAO;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAMpF,CAAC"}
|
|
1
|
+
{"version":3,"file":"api_token.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/api_token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,+DAA+D;AAC/D,eAAO,MAAM,gBAAgB,sBAAsB,CAAC;AAEpD,+DAA+D;AAC/D,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAE1C,oFAAoF;AACpF,eAAO,MAAM,qBAAqB,QAA+C,CAAC;AAElF;;;;GAIG;AACH,eAAO,MAAM,eAAe,QAE3B,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,GAAI,KAAK,MAAM,KAAG,OAAoC,CAAC;AAEvF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,QAA4B,CAAC;AAE5D,8CAA8C;AAC9C,eAAO,MAAM,UAAU,aAAuC,CAAC;AAC/D,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAEpD;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,KAAG,MAA4B,CAAC;AAE5E;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,QAAO;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAMpF,CAAC"}
|
package/dist/auth/api_token.js
CHANGED
|
@@ -13,6 +13,26 @@ import { hash_blake3 } from '@fuzdev/fuz_util/hash_blake3.ts';
|
|
|
13
13
|
import { generate_random_base64url } from '../crypto.js';
|
|
14
14
|
/** Prefix for all fuz API tokens (enables secret scanning). */
|
|
15
15
|
export const API_TOKEN_PREFIX = 'secret_fuz_token_';
|
|
16
|
+
/** Random bytes encoded into the raw token body (256 bits). */
|
|
17
|
+
export const API_TOKEN_ENTROPY_BYTES = 32;
|
|
18
|
+
/** Length of the unpadded base64url body that encodes `API_TOKEN_ENTROPY_BYTES`. */
|
|
19
|
+
export const API_TOKEN_BODY_LENGTH = Math.ceil((API_TOKEN_ENTROPY_BYTES * 4) / 3);
|
|
20
|
+
/**
|
|
21
|
+
* Regex for a raw API token: `API_TOKEN_PREFIX` plus exactly
|
|
22
|
+
* `API_TOKEN_BODY_LENGTH` base64url characters. Matches the format produced
|
|
23
|
+
* by `generate_api_token`.
|
|
24
|
+
*/
|
|
25
|
+
export const API_TOKEN_REGEX = new RegExp(`^${API_TOKEN_PREFIX}[A-Za-z0-9_-]{${API_TOKEN_BODY_LENGTH}}$`);
|
|
26
|
+
/**
|
|
27
|
+
* Whether `raw` has the shape of a raw API token — the bearer path's precheck,
|
|
28
|
+
* so a value that cannot be a token costs no database work. A `true` says
|
|
29
|
+
* nothing about whether the token exists. Twin of the Rust spine's
|
|
30
|
+
* `is_api_token_shaped`.
|
|
31
|
+
*
|
|
32
|
+
* @param raw - the value from the `Authorization: Bearer` header
|
|
33
|
+
* @returns `true` when `raw` matches `API_TOKEN_REGEX`
|
|
34
|
+
*/
|
|
35
|
+
export const is_api_token_shaped = (raw) => API_TOKEN_REGEX.test(raw);
|
|
16
36
|
/**
|
|
17
37
|
* Regex for the public API token id (e.g. `tok_abC0_d-3xyzA`). Twelve
|
|
18
38
|
* base64url characters after the `tok_` prefix. Matches the format produced
|
|
@@ -37,7 +57,7 @@ export const hash_api_token = (token) => hash_blake3(token);
|
|
|
37
57
|
* @returns the raw token, a public id, and the blake3 hash for storage
|
|
38
58
|
*/
|
|
39
59
|
export const generate_api_token = () => {
|
|
40
|
-
const raw = generate_random_base64url();
|
|
60
|
+
const raw = generate_random_base64url(API_TOKEN_ENTROPY_BYTES);
|
|
41
61
|
const token = `${API_TOKEN_PREFIX}${raw}`;
|
|
42
62
|
const token_hash = hash_api_token(token);
|
|
43
63
|
const id = `tok_${raw.slice(0, 12)}`;
|
|
@@ -7,6 +7,22 @@ import type { Logger } from '@fuzdev/fuz_util/log.ts';
|
|
|
7
7
|
import type { QueryDeps } from '../db/query_deps.js';
|
|
8
8
|
import type { ApiToken } from './account_schema.js';
|
|
9
9
|
import { type TokenScope } from './token_scope.js';
|
|
10
|
+
/**
|
|
11
|
+
* A live `api_token` row as `query_validate_api_token` returns it: the stored
|
|
12
|
+
* `scope` document already parsed, so a caller holds the narrowing the
|
|
13
|
+
* credential was minted with and never decides what an unreadable one means.
|
|
14
|
+
* The Rust twin's `ApiTokenRow` carries the parsed scope the same way.
|
|
15
|
+
*/
|
|
16
|
+
export type ValidatedApiToken = Omit<ApiToken, 'scope'> & {
|
|
17
|
+
scope: TokenScope;
|
|
18
|
+
/**
|
|
19
|
+
* Milliseconds until the token expires — `expires_at - NOW()`, measured on
|
|
20
|
+
* the database clock in the statement that found it live
|
|
21
|
+
* (`EXPIRES_IN_MS_SQL`); `null` for an eternal token. The Rust twin's
|
|
22
|
+
* `ApiTokenRow.expires_in`.
|
|
23
|
+
*/
|
|
24
|
+
expires_in_ms: number | null;
|
|
25
|
+
};
|
|
10
26
|
/** Extended deps for `query_validate_api_token` which needs a logger. */
|
|
11
27
|
export interface ApiTokenQueryDeps extends QueryDeps {
|
|
12
28
|
log: Logger;
|
|
@@ -32,21 +48,23 @@ export declare const API_TOKEN_COLUMNS: readonly ["id", "account_id", "name", "t
|
|
|
32
48
|
*/
|
|
33
49
|
export declare const query_create_api_token: (deps: QueryDeps, id: string, account_id: string, name: string, token_hash: string, scope: TokenScope, expires_at?: Date | null) => Promise<ApiToken>;
|
|
34
50
|
/**
|
|
35
|
-
* Validate a raw API token and return the token record.
|
|
51
|
+
* Validate a raw API token and return the token record with its scope parsed.
|
|
36
52
|
*
|
|
37
53
|
* Hashes the token with blake3, looks up the hash, and checks
|
|
38
|
-
* expiration
|
|
54
|
+
* expiration, reading how long the token has left on the database clock in
|
|
55
|
+
* the same statement. A row whose stored scope is unreadable is refused like an
|
|
56
|
+
* unknown hash. Updates `last_used_at` and `last_used_ip` on success
|
|
39
57
|
* (fire-and-forget — errors logged, never thrown).
|
|
40
58
|
*
|
|
41
59
|
* @param deps - query dependencies with logger
|
|
42
60
|
* @param raw_token - the raw API token from the Authorization header
|
|
43
61
|
* @param ip - the client IP address (for audit)
|
|
44
62
|
* @param pending_effects - optional array to register the usage-tracking effect for later awaiting
|
|
45
|
-
* @returns the token record if valid, or `undefined`
|
|
63
|
+
* @returns the token record with its parsed scope if valid, or `undefined`
|
|
46
64
|
* @mutates `api_token` row - fire-and-forget UPDATE of `last_used_at` / `last_used_ip` on a valid token
|
|
47
65
|
* @mutates `pending_effects` - pushes the in-flight tracking promise when provided
|
|
48
66
|
*/
|
|
49
|
-
export declare const query_validate_api_token: (deps: ApiTokenQueryDeps, raw_token: string, ip: string | undefined, pending_effects: Array<Promise<void>> | undefined) => Promise<
|
|
67
|
+
export declare const query_validate_api_token: (deps: ApiTokenQueryDeps, raw_token: string, ip: string | undefined, pending_effects: Array<Promise<void>> | undefined) => Promise<ValidatedApiToken | undefined>;
|
|
50
68
|
/**
|
|
51
69
|
* Look up the owning account of a live API token — one that still exists and
|
|
52
70
|
* has not expired — by its public id.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api_token_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/api_token_queries.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"api_token_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/api_token_queries.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGpD,OAAO,EAAE,KAAK,UAAU,EAAmD,MAAM,kBAAkB,CAAC;AAEpG;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,GAAG;IACzD,KAAK,EAAE,UAAU,CAAC;IAClB;;;;;OAKG;IACH,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,CAAC;AAEF,yEAAyE;AACzE,MAAM,WAAW,iBAAkB,SAAQ,SAAS;IACnD,GAAG,EAAE,MAAM,CAAC;CACZ;AAED;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,0HAUoB,CAAC;AA6BnD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,sBAAsB,GAClC,MAAM,SAAS,EACf,IAAI,MAAM,EACV,YAAY,MAAM,EAClB,MAAM,MAAM,EACZ,YAAY,MAAM,EAClB,OAAO,UAAU,EACjB,aAAa,IAAI,GAAG,IAAI,KACtB,OAAO,CAAC,QAAQ,CAelB,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,wBAAwB,GACpC,MAAM,iBAAiB,EACvB,WAAW,MAAM,EACjB,IAAI,MAAM,GAAG,SAAS,EACtB,iBAAiB,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,KAC/C,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAkCvC,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,4BAA4B,GACxC,MAAM,SAAS,EACf,IAAI,MAAM,KACR,OAAO,CAAC,MAAM,GAAG,SAAS,CAM5B,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,uCAAuC,GACnD,MAAM,SAAS,EACf,YAAY,MAAM,KAChB,OAAO,CAAC,MAAM,CAMhB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kCAAkC,GAC9C,MAAM,SAAS,EACf,IAAI,MAAM,EACV,YAAY,MAAM,KAChB,OAAO,CAAC,OAAO,CAMjB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,gCAAgC,GAC5C,MAAM,SAAS,EACf,YAAY,MAAM,KAChB,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC,CAM7C,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,6BAA6B,GACzC,MAAM,SAAS,EACf,YAAY,MAAM,EAClB,YAAY,MAAM,KAChB,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAYvB,CAAC"}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { assert_row } from '../db/assert_row.js';
|
|
7
7
|
import { columns_sql, iso8601_timestamp_expr, omit_columns } from '../db/sql_columns.js';
|
|
8
8
|
import { hash_api_token } from './api_token.js';
|
|
9
|
+
import { EXPIRES_IN_MS_SQL } from './credential_deadline.js';
|
|
9
10
|
import { parse_stored_token_scope, serialize_token_scope } from './token_scope.js';
|
|
10
11
|
/**
|
|
11
12
|
* The full `api_token` column set, named explicitly so a row read fails loud
|
|
@@ -74,23 +75,26 @@ export const query_create_api_token = async (deps, id, account_id, name, token_h
|
|
|
74
75
|
return assert_row(row, 'INSERT INTO api_token');
|
|
75
76
|
};
|
|
76
77
|
/**
|
|
77
|
-
* Validate a raw API token and return the token record.
|
|
78
|
+
* Validate a raw API token and return the token record with its scope parsed.
|
|
78
79
|
*
|
|
79
80
|
* Hashes the token with blake3, looks up the hash, and checks
|
|
80
|
-
* expiration
|
|
81
|
+
* expiration, reading how long the token has left on the database clock in
|
|
82
|
+
* the same statement. A row whose stored scope is unreadable is refused like an
|
|
83
|
+
* unknown hash. Updates `last_used_at` and `last_used_ip` on success
|
|
81
84
|
* (fire-and-forget — errors logged, never thrown).
|
|
82
85
|
*
|
|
83
86
|
* @param deps - query dependencies with logger
|
|
84
87
|
* @param raw_token - the raw API token from the Authorization header
|
|
85
88
|
* @param ip - the client IP address (for audit)
|
|
86
89
|
* @param pending_effects - optional array to register the usage-tracking effect for later awaiting
|
|
87
|
-
* @returns the token record if valid, or `undefined`
|
|
90
|
+
* @returns the token record with its parsed scope if valid, or `undefined`
|
|
88
91
|
* @mutates `api_token` row - fire-and-forget UPDATE of `last_used_at` / `last_used_ip` on a valid token
|
|
89
92
|
* @mutates `pending_effects` - pushes the in-flight tracking promise when provided
|
|
90
93
|
*/
|
|
91
94
|
export const query_validate_api_token = async (deps, raw_token, ip, pending_effects) => {
|
|
92
95
|
const token_hash = hash_api_token(raw_token);
|
|
93
|
-
const row = await deps.db.query_one(`SELECT ${columns_sql(API_TOKEN_COLUMNS, api_token_expr)}
|
|
96
|
+
const row = await deps.db.query_one(`SELECT ${columns_sql(API_TOKEN_COLUMNS, api_token_expr)}, ${EXPIRES_IN_MS_SQL} AS expires_in_ms
|
|
97
|
+
FROM api_token
|
|
94
98
|
WHERE token_hash = $1
|
|
95
99
|
AND ${API_TOKEN_IS_LIVE}`, [token_hash]);
|
|
96
100
|
if (!row)
|
|
@@ -99,7 +103,8 @@ export const query_validate_api_token = async (deps, raw_token, ip, pending_effe
|
|
|
99
103
|
// outcome as an unknown token hash. The scope *is* the gate here, so a parse
|
|
100
104
|
// failure must not fall through to full authority — that would hand a
|
|
101
105
|
// narrowed token everything precisely when something is already wrong.
|
|
102
|
-
|
|
106
|
+
const scope = parse_stored_token_scope(row.scope);
|
|
107
|
+
if (scope === null) {
|
|
103
108
|
deps.log.warn(`api_token.scope is unreadable for ${row.id}; refusing the credential`);
|
|
104
109
|
return undefined;
|
|
105
110
|
}
|
|
@@ -114,7 +119,7 @@ export const query_validate_api_token = async (deps, raw_token, ip, pending_effe
|
|
|
114
119
|
deps.log.error('Failed to update last_used_at:', err);
|
|
115
120
|
});
|
|
116
121
|
pending_effects?.push(p);
|
|
117
|
-
return row;
|
|
122
|
+
return { ...row, scope };
|
|
118
123
|
};
|
|
119
124
|
/**
|
|
120
125
|
* Look up the owning account of a live API token — one that still exists and
|
|
@@ -64,6 +64,16 @@ export interface AuditLogRouteOptions {
|
|
|
64
64
|
* Rust spine's `audit_stream_router`, which registers before its role read
|
|
65
65
|
* rather than repeating it.
|
|
66
66
|
*
|
|
67
|
+
* ## Credential deadline
|
|
68
|
+
*
|
|
69
|
+
* Expiry writes nothing a revocation listener could hear, so an admitted
|
|
70
|
+
* stream watches its own credential's expiry
|
|
71
|
+
* (`ResolvedAuth.credential_deadline` — for the session-only stock route, the
|
|
72
|
+
* earlier of the cookie's and the row's) and is closed at it, as a revoked
|
|
73
|
+
* stream is: the body ends with no final frame, and the client's reconnect
|
|
74
|
+
* meets the gates. The wait is `schedule_credential_deadline`'s chain of
|
|
75
|
+
* bounded timers, cancelled when the stream closes.
|
|
76
|
+
*
|
|
67
77
|
* @param options - optional stream wiring + role override
|
|
68
78
|
* @returns the SSE route spec (when `options.stream` is provided) or an empty array
|
|
69
79
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit_log_routes.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/audit_log_routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAUvD,OAAO,EAAuB,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC/E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"audit_log_routes.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/audit_log_routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAUvD,OAAO,EAAuB,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC/E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAW7E,yCAAyC;AACzC,MAAM,WAAW,oBAAoB;IACpC,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE;QACR,QAAQ,EAAE,kBAAkB,CAAC,eAAe,CAAC,CAAC;QAC9C,GAAG,EAAE,MAAM,CAAC;KACZ,CAAC;CACF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,eAAO,MAAM,4BAA4B,GAAI,UAAU,oBAAoB,KAAG,KAAK,CAAC,SAAS,CAmH5F,CAAC"}
|
|
@@ -17,6 +17,7 @@ import { create_audit_log_route_shape, DEFAULT_AUDIT_STREAM_ROLE } from './audit
|
|
|
17
17
|
import { create_sse_response } from '../realtime/sse.js';
|
|
18
18
|
import { AUTH_SESSION_TOKEN_HASH_KEY, has_scoped_role, refresh_role_grants, require_request_context } from './request_context.js';
|
|
19
19
|
import { get_resolved_auth, revalidate_resolved_auth } from './resolved_auth.js';
|
|
20
|
+
import { schedule_credential_deadline } from './credential_deadline.js';
|
|
20
21
|
import { AUDIT_LOG_CHANNEL } from '../realtime/sse_auth_guard.js';
|
|
21
22
|
/**
|
|
22
23
|
* Create the optional audit-log SSE route spec.
|
|
@@ -50,6 +51,16 @@ import { AUDIT_LOG_CHANNEL } from '../realtime/sse_auth_guard.js';
|
|
|
50
51
|
* Rust spine's `audit_stream_router`, which registers before its role read
|
|
51
52
|
* rather than repeating it.
|
|
52
53
|
*
|
|
54
|
+
* ## Credential deadline
|
|
55
|
+
*
|
|
56
|
+
* Expiry writes nothing a revocation listener could hear, so an admitted
|
|
57
|
+
* stream watches its own credential's expiry
|
|
58
|
+
* (`ResolvedAuth.credential_deadline` — for the session-only stock route, the
|
|
59
|
+
* earlier of the cookie's and the row's) and is closed at it, as a revoked
|
|
60
|
+
* stream is: the body ends with no final frame, and the client's reconnect
|
|
61
|
+
* meets the gates. The wait is `schedule_credential_deadline`'s chain of
|
|
62
|
+
* bounded timers, cancelled when the stream closes.
|
|
63
|
+
*
|
|
53
64
|
* @param options - optional stream wiring + role override
|
|
54
65
|
* @returns the SSE route spec (when `options.stream` is provided) or an empty array
|
|
55
66
|
*/
|
|
@@ -143,6 +154,15 @@ export const create_audit_log_route_specs = (options) => {
|
|
|
143
154
|
log.info('audit stream: closed before admission', ctx.account.id);
|
|
144
155
|
stream.close();
|
|
145
156
|
}
|
|
157
|
+
else {
|
|
158
|
+
// The stream ends when the credential it opened on expires —
|
|
159
|
+
// closed as a revocation closes it (TSDoc, "Credential
|
|
160
|
+
// deadline").
|
|
161
|
+
stream.on_close(schedule_credential_deadline(get_resolved_auth(c)?.credential_deadline ?? null, () => {
|
|
162
|
+
log.info('audit stream: credential expired', ctx.account.id);
|
|
163
|
+
stream.close();
|
|
164
|
+
}));
|
|
165
|
+
}
|
|
146
166
|
return response;
|
|
147
167
|
}
|
|
148
168
|
finally {
|
|
@@ -60,12 +60,15 @@ export type AuditEventType = z.infer<typeof AuditEventType>;
|
|
|
60
60
|
* row's `metadata.token_id`.
|
|
61
61
|
* - `account` — every connection of `target_account_id ?? account_id`.
|
|
62
62
|
* - `role` — the target account's connections gated on the row's
|
|
63
|
-
* `metadata.role
|
|
63
|
+
* `metadata.role`, when the revoked grant was global
|
|
64
|
+
* (`to_global_role_revocation`).
|
|
64
65
|
*
|
|
65
|
-
* The scope says what the row invalidated
|
|
66
|
-
*
|
|
67
|
-
* re-
|
|
68
|
-
*
|
|
66
|
+
* The scope says what the row invalidated; both listeners act on every scope
|
|
67
|
+
* alike. On `role` that matters for the WebSocket too: per-message dispatch
|
|
68
|
+
* re-authorizes each request against its own action, but a socket admitted by
|
|
69
|
+
* a role gate also receives every server push its endpoint sends, which no
|
|
70
|
+
* dispatch ever re-checks — so a socket that lost the gating role is closed,
|
|
71
|
+
* like a stream.
|
|
69
72
|
*
|
|
70
73
|
* Twin of the Rust spine's `RevocationScope`.
|
|
71
74
|
*/
|
|
@@ -97,6 +100,28 @@ export declare const audit_event_revocation_scopes: Readonly<Record<AuditEventTy
|
|
|
97
100
|
* with `queue_connection_close`.
|
|
98
101
|
*/
|
|
99
102
|
export declare const to_revocation_scope: (event_type: string) => RevocationScope;
|
|
103
|
+
/**
|
|
104
|
+
* The account and role a successful `role`-scope row took away, when the
|
|
105
|
+
* revoked grant was **global** — `null` otherwise.
|
|
106
|
+
*
|
|
107
|
+
* A role gate (`register_ws_endpoint`'s `required_roles`, the audit stream's
|
|
108
|
+
* `require_role`) admits on global grants only, so revoking a scoped grant
|
|
109
|
+
* takes away nothing a gate admitted on and closes nothing. A row with no
|
|
110
|
+
* `metadata.scope_id` reads as global: when unsure, closing is the safe side.
|
|
111
|
+
* The target is `target_account_id ?? account_id`, as for the `account` scope.
|
|
112
|
+
* Both revocation listeners read it, so a socket and a stream gated on one
|
|
113
|
+
* role close on the same rows.
|
|
114
|
+
*
|
|
115
|
+
* Twin of the Rust spine's `global_role_revocation`.
|
|
116
|
+
*
|
|
117
|
+
* @param event - a row whose scope is `role` (the caller dispatched on it)
|
|
118
|
+
* @returns the account and role to close on, or `null` when the row names no
|
|
119
|
+
* role or target, or revoked a scoped grant
|
|
120
|
+
*/
|
|
121
|
+
export declare const to_global_role_revocation: (event: AuditLogEvent) => {
|
|
122
|
+
account_id: Uuid;
|
|
123
|
+
role: string;
|
|
124
|
+
} | null;
|
|
100
125
|
/**
|
|
101
126
|
* Letter start, then letters, digits, `_`, `.`, `/`, `-`. Accepts snake_case,
|
|
102
127
|
* dotted, and namespaced consumer conventions; rejects empty strings, leading
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit_log_schema.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/audit_log_schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,IAAI,EAAS,MAAM,yBAAyB,CAAC;AAkBtD;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,6iBA6BnB,CAAC;AAEZ,wCAAwC;AACxC,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAA4B,CAAC;AACxD,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAE5D
|
|
1
|
+
{"version":3,"file":"audit_log_schema.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/audit_log_schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -119,6 +119,36 @@ export const audit_event_revocation_scopes = Object.freeze({
|
|
|
119
119
|
export const to_revocation_scope = (event_type) => Object.hasOwn(audit_event_revocation_scopes, event_type)
|
|
120
120
|
? audit_event_revocation_scopes[event_type]
|
|
121
121
|
: 'none';
|
|
122
|
+
/**
|
|
123
|
+
* The account and role a successful `role`-scope row took away, when the
|
|
124
|
+
* revoked grant was **global** — `null` otherwise.
|
|
125
|
+
*
|
|
126
|
+
* A role gate (`register_ws_endpoint`'s `required_roles`, the audit stream's
|
|
127
|
+
* `require_role`) admits on global grants only, so revoking a scoped grant
|
|
128
|
+
* takes away nothing a gate admitted on and closes nothing. A row with no
|
|
129
|
+
* `metadata.scope_id` reads as global: when unsure, closing is the safe side.
|
|
130
|
+
* The target is `target_account_id ?? account_id`, as for the `account` scope.
|
|
131
|
+
* Both revocation listeners read it, so a socket and a stream gated on one
|
|
132
|
+
* role close on the same rows.
|
|
133
|
+
*
|
|
134
|
+
* Twin of the Rust spine's `global_role_revocation`.
|
|
135
|
+
*
|
|
136
|
+
* @param event - a row whose scope is `role` (the caller dispatched on it)
|
|
137
|
+
* @returns the account and role to close on, or `null` when the row names no
|
|
138
|
+
* role or target, or revoked a scoped grant
|
|
139
|
+
*/
|
|
140
|
+
export const to_global_role_revocation = (event) => {
|
|
141
|
+
const role = event.metadata?.role;
|
|
142
|
+
if (typeof role !== 'string' || role.length === 0)
|
|
143
|
+
return null;
|
|
144
|
+
const scope_id = event.metadata?.scope_id;
|
|
145
|
+
if (scope_id !== undefined && scope_id !== null)
|
|
146
|
+
return null;
|
|
147
|
+
const account_id = event.target_account_id ?? event.account_id;
|
|
148
|
+
if (!account_id)
|
|
149
|
+
return null;
|
|
150
|
+
return { account_id, role };
|
|
151
|
+
};
|
|
122
152
|
/**
|
|
123
153
|
* Letter start, then letters, digits, `_`, `.`, `/`, `-`. Accepts snake_case,
|
|
124
154
|
* dotted, and namespaced consumer conventions; rejects empty strings, leading
|
|
@@ -20,7 +20,7 @@ import type { QueryDeps } from '../db/query_deps.js';
|
|
|
20
20
|
/**
|
|
21
21
|
* Create middleware that authenticates via bearer token.
|
|
22
22
|
*
|
|
23
|
-
* Soft-fails for invalid, expired, or empty tokens — calls `next()` without
|
|
23
|
+
* Soft-fails for malformed, invalid, expired, or empty tokens — calls `next()` without
|
|
24
24
|
* setting account identity, letting downstream auth enforcement (the RPC
|
|
25
25
|
* dispatcher's pre-authorization / post-authorization auth gates or
|
|
26
26
|
* `require_auth`) return a consistent JSON-RPC or route-level error. This
|
|
@@ -31,6 +31,8 @@ import type { QueryDeps } from '../db/query_deps.js';
|
|
|
31
31
|
* Discards bearer tokens when an `Origin` or `Referer` header is present —
|
|
32
32
|
* `next()` with no identity, as for a bad token — so browsers must use cookie
|
|
33
33
|
* auth, reducing attack surface.
|
|
34
|
+
* A token that fails the `is_api_token_shaped` precheck soft-fails before
|
|
35
|
+
* the database is touched.
|
|
34
36
|
* Auth scheme matching is case-insensitive per RFC 7235.
|
|
35
37
|
* On success, sets `c.var.auth_account_id`, `CREDENTIAL_TYPE_KEY = 'api_token'`,
|
|
36
38
|
* and `AUTH_API_TOKEN_ID_KEY`. Skips when an account is already authenticated
|
|
@@ -48,7 +50,7 @@ import type { QueryDeps } from '../db/query_deps.js';
|
|
|
48
50
|
*
|
|
49
51
|
* @param deps - query dependencies (pool-level db for middleware)
|
|
50
52
|
* @param log - the logger instance
|
|
51
|
-
* @mutates Hono context - sets `ACCOUNT_ID_KEY`, `CREDENTIAL_TYPE_KEY`, and `
|
|
53
|
+
* @mutates Hono context - sets `ACCOUNT_ID_KEY`, `CREDENTIAL_TYPE_KEY`, `AUTH_API_TOKEN_ID_KEY`, and `CREDENTIAL_DEADLINE_KEY` on success
|
|
52
54
|
*/
|
|
53
55
|
export declare const create_bearer_auth_middleware: (deps: QueryDeps, log: Logger) => MiddlewareHandler;
|
|
54
56
|
//# sourceMappingURL=bearer_auth.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bearer_auth.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/bearer_auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"bearer_auth.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/bearer_auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAYtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAIrD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,6BAA6B,GAAI,MAAM,SAAS,EAAE,KAAK,MAAM,KAAG,iBAgF5E,CAAC"}
|
package/dist/auth/bearer_auth.js
CHANGED
|
@@ -15,15 +15,16 @@
|
|
|
15
15
|
* @module
|
|
16
16
|
*/
|
|
17
17
|
import { DEV } from 'esm-env';
|
|
18
|
-
import { AUTH_API_TOKEN_ID_KEY, ACCOUNT_ID_KEY, CREDENTIAL_TYPE_KEY, TOKEN_SCOPE_KEY } from '../hono_context.js';
|
|
19
|
-
import {
|
|
18
|
+
import { AUTH_API_TOKEN_ID_KEY, ACCOUNT_ID_KEY, CREDENTIAL_DEADLINE_KEY, CREDENTIAL_TYPE_KEY, TOKEN_SCOPE_KEY } from '../hono_context.js';
|
|
19
|
+
import { credential_deadline_after } from './credential_deadline.js';
|
|
20
|
+
import { is_api_token_shaped } from './api_token.js';
|
|
20
21
|
import { query_validate_api_token } from './api_token_queries.js';
|
|
21
22
|
import { get_client_ip } from '../http/client_ip.js';
|
|
22
23
|
import { is_browser_context } from '../http/origin.js';
|
|
23
24
|
/**
|
|
24
25
|
* Create middleware that authenticates via bearer token.
|
|
25
26
|
*
|
|
26
|
-
* Soft-fails for invalid, expired, or empty tokens — calls `next()` without
|
|
27
|
+
* Soft-fails for malformed, invalid, expired, or empty tokens — calls `next()` without
|
|
27
28
|
* setting account identity, letting downstream auth enforcement (the RPC
|
|
28
29
|
* dispatcher's pre-authorization / post-authorization auth gates or
|
|
29
30
|
* `require_auth`) return a consistent JSON-RPC or route-level error. This
|
|
@@ -34,6 +35,8 @@ import { is_browser_context } from '../http/origin.js';
|
|
|
34
35
|
* Discards bearer tokens when an `Origin` or `Referer` header is present —
|
|
35
36
|
* `next()` with no identity, as for a bad token — so browsers must use cookie
|
|
36
37
|
* auth, reducing attack surface.
|
|
38
|
+
* A token that fails the `is_api_token_shaped` precheck soft-fails before
|
|
39
|
+
* the database is touched.
|
|
37
40
|
* Auth scheme matching is case-insensitive per RFC 7235.
|
|
38
41
|
* On success, sets `c.var.auth_account_id`, `CREDENTIAL_TYPE_KEY = 'api_token'`,
|
|
39
42
|
* and `AUTH_API_TOKEN_ID_KEY`. Skips when an account is already authenticated
|
|
@@ -51,7 +54,7 @@ import { is_browser_context } from '../http/origin.js';
|
|
|
51
54
|
*
|
|
52
55
|
* @param deps - query dependencies (pool-level db for middleware)
|
|
53
56
|
* @param log - the logger instance
|
|
54
|
-
* @mutates Hono context - sets `ACCOUNT_ID_KEY`, `CREDENTIAL_TYPE_KEY`, and `
|
|
57
|
+
* @mutates Hono context - sets `ACCOUNT_ID_KEY`, `CREDENTIAL_TYPE_KEY`, `AUTH_API_TOKEN_ID_KEY`, and `CREDENTIAL_DEADLINE_KEY` on success
|
|
55
58
|
*/
|
|
56
59
|
export const create_bearer_auth_middleware = (deps, log) => {
|
|
57
60
|
return async (c, next) => {
|
|
@@ -92,6 +95,13 @@ export const create_bearer_auth_middleware = (deps, log) => {
|
|
|
92
95
|
await next();
|
|
93
96
|
return;
|
|
94
97
|
}
|
|
98
|
+
// A value that cannot be a token soft-fails before any database work —
|
|
99
|
+
// no pool checkout, no query — so junk bearers cost nothing to refuse.
|
|
100
|
+
if (!is_api_token_shaped(raw_token)) {
|
|
101
|
+
log.debug('bearer auth soft-fail: malformed token');
|
|
102
|
+
await next();
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
95
105
|
// `ip` feeds the token's `last_used_ip` bookkeeping, not a limiter.
|
|
96
106
|
const ip = get_client_ip(c);
|
|
97
107
|
const api_token = await query_validate_api_token({ ...deps, log }, raw_token, ip, c.var.pending_effects);
|
|
@@ -105,10 +115,11 @@ export const create_bearer_auth_middleware = (deps, log) => {
|
|
|
105
115
|
c.set(ACCOUNT_ID_KEY, api_token.account_id);
|
|
106
116
|
c.set(CREDENTIAL_TYPE_KEY, 'api_token');
|
|
107
117
|
c.set(AUTH_API_TOKEN_ID_KEY, api_token.id);
|
|
108
|
-
//
|
|
109
|
-
//
|
|
110
|
-
|
|
111
|
-
|
|
118
|
+
// Parsed by the query, which refuses a token whose stored scope is
|
|
119
|
+
// unreadable — there is no default to fall back to.
|
|
120
|
+
c.set(TOKEN_SCOPE_KEY, api_token.scope);
|
|
121
|
+
// the row's expiry, read on the database clock; none for an eternal token
|
|
122
|
+
c.set(CREDENTIAL_DEADLINE_KEY, credential_deadline_after([api_token.expires_in_ms]));
|
|
112
123
|
await next();
|
|
113
124
|
};
|
|
114
125
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap_route_schema.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/bootstrap_route_schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAaxB,gFAAgF;AAChF,eAAO,MAAM,cAAc;;;;kBAIzB,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAE5D,iFAAiF;AACjF,eAAO,MAAM,eAAe;;;;;;;;;kBAI1B,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAE9D;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB
|
|
1
|
+
{"version":3,"file":"bootstrap_route_schema.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/bootstrap_route_schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAaxB,gFAAgF;AAChF,eAAO,MAAM,cAAc;;;;kBAIzB,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAE5D,iFAAiF;AACjF,eAAO,MAAM,eAAe;;;;;;;;;kBAI1B,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAE9D;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkBI,CAAC"}
|
|
@@ -39,6 +39,7 @@ export const bootstrap_route_shape = {
|
|
|
39
39
|
method: 'POST',
|
|
40
40
|
path: '/bootstrap',
|
|
41
41
|
auth: { account: 'none', actor: 'none' },
|
|
42
|
+
mints_credential: true,
|
|
42
43
|
description: 'Create initial keeper account (one-shot)',
|
|
43
44
|
transaction: false, // bootstrap_account manages its own transaction
|
|
44
45
|
input: BootstrapInput,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap_routes.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/bootstrap_routes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAEpC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,EAAqB,KAAK,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEzF,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"bootstrap_routes.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/bootstrap_routes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAEpC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,EAAqB,KAAK,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEzF,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAGxE,OAAO,EAGN,KAAK,WAAW,EAChB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAGlD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACrC,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,8EAA8E;IAC9E,gBAAgB,EAAE,eAAe,CAAC;IAClC;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,uBAAuB,EAAE,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E;;;;;;;;;;OAUG;IACH,yBAAyB,EAAE,WAAW,GAAG,IAAI,CAAC;CAC9C;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACxC,kFAAkF;IAClF,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IACxD,+EAA+E;IAC/E,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;IAC1B,GAAG,EAAE,MAAM,CAAC;CACZ;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,sBAAsB,GAClC,MAAM,wBAAwB,EAC9B,SAAS;IAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,KACpC,OAAO,CAAC,eAAe,CAyBzB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,GACxC,MAAM,gBAAgB,EACtB,SAAS,qBAAqB,KAC5B,KAAK,CAAC,SAAS,CA0HjB,CAAC"}
|