@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.
Files changed (311) hide show
  1. package/dist/actions/CLAUDE.md +72 -22
  2. package/dist/actions/action_rpc.d.ts +5 -1
  3. package/dist/actions/action_rpc.d.ts.map +1 -1
  4. package/dist/actions/action_rpc.js +9 -1
  5. package/dist/actions/connection_closer.d.ts +44 -4
  6. package/dist/actions/connection_closer.d.ts.map +1 -1
  7. package/dist/actions/connection_closer.js +33 -3
  8. package/dist/actions/perform_action.d.ts +10 -0
  9. package/dist/actions/perform_action.d.ts.map +1 -1
  10. package/dist/actions/perform_action.js +23 -9
  11. package/dist/actions/register_action_ws.d.ts +42 -6
  12. package/dist/actions/register_action_ws.d.ts.map +1 -1
  13. package/dist/actions/register_action_ws.js +87 -19
  14. package/dist/actions/register_ws_endpoint.d.ts +15 -6
  15. package/dist/actions/register_ws_endpoint.d.ts.map +1 -1
  16. package/dist/actions/register_ws_endpoint.js +10 -4
  17. package/dist/actions/socket.svelte.d.ts +19 -4
  18. package/dist/actions/socket.svelte.d.ts.map +1 -1
  19. package/dist/actions/socket.svelte.js +31 -4
  20. package/dist/actions/transports.d.ts +30 -1
  21. package/dist/actions/transports.d.ts.map +1 -1
  22. package/dist/actions/transports.js +30 -1
  23. package/dist/actions/transports_ws_auth_guard.d.ts +13 -6
  24. package/dist/actions/transports_ws_auth_guard.d.ts.map +1 -1
  25. package/dist/actions/transports_ws_auth_guard.js +24 -10
  26. package/dist/actions/transports_ws_backend.d.ts +51 -5
  27. package/dist/actions/transports_ws_backend.d.ts.map +1 -1
  28. package/dist/actions/transports_ws_backend.js +62 -9
  29. package/dist/actions/ws_endpoint_spec.d.ts +11 -10
  30. package/dist/actions/ws_endpoint_spec.d.ts.map +1 -1
  31. package/dist/auth/CLAUDE.md +44 -22
  32. package/dist/auth/account_actions.d.ts.map +1 -1
  33. package/dist/auth/account_actions.js +12 -1
  34. package/dist/auth/account_route_schema.d.ts +1 -0
  35. package/dist/auth/account_route_schema.d.ts.map +1 -1
  36. package/dist/auth/account_route_schema.js +12 -0
  37. package/dist/auth/account_routes.d.ts +7 -2
  38. package/dist/auth/account_routes.d.ts.map +1 -1
  39. package/dist/auth/account_routes.js +240 -187
  40. package/dist/auth/admin_action_specs.d.ts +6 -1
  41. package/dist/auth/admin_action_specs.d.ts.map +1 -1
  42. package/dist/auth/admin_action_specs.js +6 -1
  43. package/dist/auth/admin_actions.d.ts.map +1 -1
  44. package/dist/auth/admin_actions.js +14 -2
  45. package/dist/auth/api_token.d.ts +20 -0
  46. package/dist/auth/api_token.d.ts.map +1 -1
  47. package/dist/auth/api_token.js +21 -1
  48. package/dist/auth/api_token_queries.d.ts +22 -4
  49. package/dist/auth/api_token_queries.d.ts.map +1 -1
  50. package/dist/auth/api_token_queries.js +11 -6
  51. package/dist/auth/audit_log_routes.d.ts +10 -0
  52. package/dist/auth/audit_log_routes.d.ts.map +1 -1
  53. package/dist/auth/audit_log_routes.js +20 -0
  54. package/dist/auth/audit_log_schema.d.ts +30 -5
  55. package/dist/auth/audit_log_schema.d.ts.map +1 -1
  56. package/dist/auth/audit_log_schema.js +30 -0
  57. package/dist/auth/bearer_auth.d.ts +4 -2
  58. package/dist/auth/bearer_auth.d.ts.map +1 -1
  59. package/dist/auth/bearer_auth.js +19 -8
  60. package/dist/auth/bootstrap_route_schema.d.ts +1 -0
  61. package/dist/auth/bootstrap_route_schema.d.ts.map +1 -1
  62. package/dist/auth/bootstrap_route_schema.js +1 -0
  63. package/dist/auth/bootstrap_routes.d.ts.map +1 -1
  64. package/dist/auth/bootstrap_routes.js +85 -76
  65. package/dist/auth/cell_action_specs.d.ts +7 -3
  66. package/dist/auth/cell_action_specs.d.ts.map +1 -1
  67. package/dist/auth/cell_action_specs.js +9 -5
  68. package/dist/auth/cell_actions.d.ts +3 -3
  69. package/dist/auth/cell_actions.d.ts.map +1 -1
  70. package/dist/auth/cell_actions.js +67 -38
  71. package/dist/auth/cell_authorize.d.ts +69 -8
  72. package/dist/auth/cell_authorize.d.ts.map +1 -1
  73. package/dist/auth/cell_authorize.js +89 -9
  74. package/dist/auth/cell_field_action_specs.d.ts +5 -4
  75. package/dist/auth/cell_field_action_specs.d.ts.map +1 -1
  76. package/dist/auth/cell_field_action_specs.js +7 -7
  77. package/dist/auth/cell_field_actions.d.ts +7 -5
  78. package/dist/auth/cell_field_actions.d.ts.map +1 -1
  79. package/dist/auth/cell_field_actions.js +24 -22
  80. package/dist/auth/cell_grant_action_specs.d.ts +6 -0
  81. package/dist/auth/cell_grant_action_specs.d.ts.map +1 -1
  82. package/dist/auth/cell_grant_action_specs.js +6 -0
  83. package/dist/auth/cell_grant_actions.d.ts +3 -1
  84. package/dist/auth/cell_grant_actions.d.ts.map +1 -1
  85. package/dist/auth/cell_grant_actions.js +16 -2
  86. package/dist/auth/cell_item_action_specs.d.ts +5 -4
  87. package/dist/auth/cell_item_action_specs.d.ts.map +1 -1
  88. package/dist/auth/cell_item_action_specs.js +7 -7
  89. package/dist/auth/cell_item_actions.d.ts +6 -5
  90. package/dist/auth/cell_item_actions.d.ts.map +1 -1
  91. package/dist/auth/cell_item_actions.js +23 -22
  92. package/dist/auth/cell_relation_list_limit.d.ts +20 -0
  93. package/dist/auth/cell_relation_list_limit.d.ts.map +1 -0
  94. package/dist/auth/cell_relation_list_limit.js +27 -0
  95. package/dist/auth/cell_relation_visibility.d.ts +4 -3
  96. package/dist/auth/cell_relation_visibility.d.ts.map +1 -1
  97. package/dist/auth/cell_relation_visibility.js +6 -5
  98. package/dist/auth/cell_steward.d.ts +45 -0
  99. package/dist/auth/cell_steward.d.ts.map +1 -0
  100. package/dist/auth/cell_steward.js +53 -0
  101. package/dist/auth/cleanup.d.ts +9 -9
  102. package/dist/auth/cleanup.js +9 -9
  103. package/dist/auth/credential_deadline.d.ts +95 -0
  104. package/dist/auth/credential_deadline.d.ts.map +1 -0
  105. package/dist/auth/credential_deadline.js +139 -0
  106. package/dist/auth/daemon_token_middleware.d.ts.map +1 -1
  107. package/dist/auth/daemon_token_middleware.js +4 -1
  108. package/dist/auth/middleware.d.ts +90 -12
  109. package/dist/auth/middleware.d.ts.map +1 -1
  110. package/dist/auth/middleware.js +115 -16
  111. package/dist/auth/request_context.d.ts +8 -2
  112. package/dist/auth/request_context.d.ts.map +1 -1
  113. package/dist/auth/request_context.js +20 -4
  114. package/dist/auth/resolved_auth.d.ts +13 -2
  115. package/dist/auth/resolved_auth.d.ts.map +1 -1
  116. package/dist/auth/resolved_auth.js +5 -4
  117. package/dist/auth/role_grant_offer_action_specs.d.ts +5 -0
  118. package/dist/auth/role_grant_offer_action_specs.d.ts.map +1 -1
  119. package/dist/auth/role_grant_offer_action_specs.js +6 -1
  120. package/dist/auth/role_grant_offer_actions.d.ts.map +1 -1
  121. package/dist/auth/role_grant_offer_actions.js +23 -16
  122. package/dist/auth/role_grant_offer_queries.d.ts +8 -6
  123. package/dist/auth/role_grant_offer_queries.d.ts.map +1 -1
  124. package/dist/auth/role_grant_offer_queries.js +16 -8
  125. package/dist/auth/session_cookie.d.ts +4 -0
  126. package/dist/auth/session_cookie.d.ts.map +1 -1
  127. package/dist/auth/session_cookie.js +3 -2
  128. package/dist/auth/session_middleware.d.ts +1 -1
  129. package/dist/auth/session_middleware.d.ts.map +1 -1
  130. package/dist/auth/session_middleware.js +4 -1
  131. package/dist/auth/session_queries.d.ts +19 -2
  132. package/dist/auth/session_queries.d.ts.map +1 -1
  133. package/dist/auth/session_queries.js +8 -2
  134. package/dist/auth/signup_route_schema.d.ts.map +1 -1
  135. package/dist/auth/signup_route_schema.js +1 -0
  136. package/dist/auth/signup_routes.d.ts +4 -3
  137. package/dist/auth/signup_routes.d.ts.map +1 -1
  138. package/dist/auth/signup_routes.js +157 -134
  139. package/dist/auth/token_scope.d.ts +7 -1
  140. package/dist/auth/token_scope.d.ts.map +1 -1
  141. package/dist/auth/token_scope.js +8 -2
  142. package/dist/db/CLAUDE.md +32 -19
  143. package/dist/db/cell_ddl.d.ts +1 -2
  144. package/dist/db/cell_ddl.d.ts.map +1 -1
  145. package/dist/db/cell_ddl.js +1 -2
  146. package/dist/db/cell_field_queries.d.ts +20 -18
  147. package/dist/db/cell_field_queries.d.ts.map +1 -1
  148. package/dist/db/cell_field_queries.js +28 -22
  149. package/dist/db/cell_item_queries.d.ts +20 -14
  150. package/dist/db/cell_item_queries.d.ts.map +1 -1
  151. package/dist/db/cell_item_queries.js +28 -18
  152. package/dist/db/cell_moderation.d.ts +67 -0
  153. package/dist/db/cell_moderation.d.ts.map +1 -0
  154. package/dist/db/cell_moderation.js +66 -0
  155. package/dist/db/cell_queries.d.ts +44 -14
  156. package/dist/db/cell_queries.d.ts.map +1 -1
  157. package/dist/db/cell_queries.js +68 -45
  158. package/dist/db/cell_view_sql.d.ts +102 -0
  159. package/dist/db/cell_view_sql.d.ts.map +1 -0
  160. package/dist/db/cell_view_sql.js +112 -0
  161. package/dist/db/db_pg.d.ts +1 -1
  162. package/dist/db/db_pg.js +1 -1
  163. package/dist/hono_context.d.ts +23 -0
  164. package/dist/hono_context.d.ts.map +1 -1
  165. package/dist/hono_context.js +19 -0
  166. package/dist/http/CLAUDE.md +41 -15
  167. package/dist/http/auth_shape.d.ts +5 -2
  168. package/dist/http/auth_shape.d.ts.map +1 -1
  169. package/dist/http/auth_shape.js +5 -2
  170. package/dist/http/ip_canonical.d.ts +30 -3
  171. package/dist/http/ip_canonical.d.ts.map +1 -1
  172. package/dist/http/ip_canonical.js +50 -3
  173. package/dist/http/middleware_spec.d.ts +16 -0
  174. package/dist/http/middleware_spec.d.ts.map +1 -1
  175. package/dist/http/origin.d.ts +113 -18
  176. package/dist/http/origin.d.ts.map +1 -1
  177. package/dist/http/origin.js +247 -127
  178. package/dist/http/route_spec.d.ts +21 -0
  179. package/dist/http/route_spec.d.ts.map +1 -1
  180. package/dist/http/schema_helpers.d.ts +22 -0
  181. package/dist/http/schema_helpers.d.ts.map +1 -1
  182. package/dist/http/schema_helpers.js +24 -0
  183. package/dist/http/surface.d.ts +6 -1
  184. package/dist/http/surface.d.ts.map +1 -1
  185. package/dist/http/surface.js +12 -5
  186. package/dist/primitive_schemas.d.ts +10 -1
  187. package/dist/primitive_schemas.d.ts.map +1 -1
  188. package/dist/primitive_schemas.js +11 -2
  189. package/dist/rate_limiter.d.ts +179 -12
  190. package/dist/rate_limiter.d.ts.map +1 -1
  191. package/dist/rate_limiter.js +352 -42
  192. package/dist/realtime/sse_auth_guard.d.ts +22 -6
  193. package/dist/realtime/sse_auth_guard.d.ts.map +1 -1
  194. package/dist/realtime/sse_auth_guard.js +31 -12
  195. package/dist/realtime/subscriber_registry.d.ts +10 -1
  196. package/dist/realtime/subscriber_registry.d.ts.map +1 -1
  197. package/dist/realtime/subscriber_registry.js +10 -1
  198. package/dist/server/app_server.d.ts +20 -7
  199. package/dist/server/app_server.d.ts.map +1 -1
  200. package/dist/server/app_server.js +8 -3
  201. package/dist/server/env.d.ts +2 -1
  202. package/dist/server/env.d.ts.map +1 -1
  203. package/dist/server/env.js +7 -17
  204. package/dist/server/serve_fact_route.d.ts +8 -4
  205. package/dist/server/serve_fact_route.d.ts.map +1 -1
  206. package/dist/server/serve_fact_route.js +16 -6
  207. package/dist/testing/CLAUDE.md +164 -25
  208. package/dist/testing/adversarial_headers.d.ts.map +1 -1
  209. package/dist/testing/adversarial_headers.js +13 -6
  210. package/dist/testing/connection_closer_helpers.d.ts +6 -1
  211. package/dist/testing/connection_closer_helpers.d.ts.map +1 -1
  212. package/dist/testing/connection_closer_helpers.js +4 -0
  213. package/dist/testing/cross_backend/account_lifecycle.d.ts.map +1 -1
  214. package/dist/testing/cross_backend/account_lifecycle.js +37 -2
  215. package/dist/testing/cross_backend/body_size.d.ts.map +1 -1
  216. package/dist/testing/cross_backend/body_size.js +14 -65
  217. package/dist/testing/cross_backend/capabilities.d.ts +26 -2
  218. package/dist/testing/cross_backend/capabilities.d.ts.map +1 -1
  219. package/dist/testing/cross_backend/capabilities.js +9 -3
  220. package/dist/testing/cross_backend/cell_gated_create.d.ts +38 -0
  221. package/dist/testing/cross_backend/cell_gated_create.d.ts.map +1 -1
  222. package/dist/testing/cross_backend/cell_gated_create.js +401 -5
  223. package/dist/testing/cross_backend/cell_relations.d.ts.map +1 -1
  224. package/dist/testing/cross_backend/cell_relations.js +145 -2
  225. package/dist/testing/cross_backend/conformance_case.d.ts +11 -3
  226. package/dist/testing/cross_backend/conformance_case.d.ts.map +1 -1
  227. package/dist/testing/cross_backend/conformance_case.js +6 -0
  228. package/dist/testing/cross_backend/conformance_table.d.ts.map +1 -1
  229. package/dist/testing/cross_backend/conformance_table.js +20 -19
  230. package/dist/testing/cross_backend/credential_deadline.d.ts +25 -0
  231. package/dist/testing/cross_backend/credential_deadline.d.ts.map +1 -0
  232. package/dist/testing/cross_backend/credential_deadline.js +185 -0
  233. package/dist/testing/cross_backend/default_backend_configs.d.ts.map +1 -1
  234. package/dist/testing/cross_backend/default_backend_configs.js +13 -2
  235. package/dist/testing/cross_backend/expected_schema.json +0 -1
  236. package/dist/testing/cross_backend/full_spine_mount.d.ts +3 -0
  237. package/dist/testing/cross_backend/full_spine_mount.d.ts.map +1 -1
  238. package/dist/testing/cross_backend/full_spine_mount.js +7 -1
  239. package/dist/testing/cross_backend/login_security.d.ts +16 -0
  240. package/dist/testing/cross_backend/login_security.d.ts.map +1 -1
  241. package/dist/testing/cross_backend/login_security.js +154 -0
  242. package/dist/testing/cross_backend/narrowed_api_token.d.ts +23 -0
  243. package/dist/testing/cross_backend/narrowed_api_token.d.ts.map +1 -0
  244. package/dist/testing/cross_backend/narrowed_api_token.js +40 -0
  245. package/dist/testing/cross_backend/origin.d.ts.map +1 -1
  246. package/dist/testing/cross_backend/origin.js +6 -26
  247. package/dist/testing/cross_backend/origin_conformance.d.ts +152 -0
  248. package/dist/testing/cross_backend/origin_conformance.d.ts.map +1 -0
  249. package/dist/testing/cross_backend/origin_conformance.js +136 -0
  250. package/dist/testing/cross_backend/origin_conformance.json +1679 -0
  251. package/dist/testing/cross_backend/origin_scope.d.ts +16 -0
  252. package/dist/testing/cross_backend/origin_scope.d.ts.map +1 -0
  253. package/dist/testing/cross_backend/origin_scope.js +140 -0
  254. package/dist/testing/cross_backend/query_shape.d.ts.map +1 -1
  255. package/dist/testing/cross_backend/query_shape.js +24 -2
  256. package/dist/testing/cross_backend/role_grant_cross_helpers.d.ts +35 -0
  257. package/dist/testing/cross_backend/role_grant_cross_helpers.d.ts.map +1 -0
  258. package/dist/testing/cross_backend/role_grant_cross_helpers.js +64 -0
  259. package/dist/testing/cross_backend/role_grant_offer_notification_ws.d.ts +8 -0
  260. package/dist/testing/cross_backend/role_grant_offer_notification_ws.d.ts.map +1 -1
  261. package/dist/testing/cross_backend/role_grant_offer_notification_ws.js +44 -33
  262. package/dist/testing/cross_backend/role_grant_participation.d.ts.map +1 -1
  263. package/dist/testing/cross_backend/role_grant_participation.js +64 -0
  264. package/dist/testing/cross_backend/rust_spine_stub_backend_config.d.ts.map +1 -1
  265. package/dist/testing/cross_backend/rust_spine_stub_backend_config.js +6 -4
  266. package/dist/testing/cross_backend/spine_surface_constants.d.ts +20 -1
  267. package/dist/testing/cross_backend/spine_surface_constants.d.ts.map +1 -1
  268. package/dist/testing/cross_backend/spine_surface_constants.js +23 -1
  269. package/dist/testing/cross_backend/testing_backdoor.d.ts.map +1 -1
  270. package/dist/testing/cross_backend/testing_backdoor.js +20 -7
  271. package/dist/testing/cross_backend/testing_reset_actions.d.ts +180 -5
  272. package/dist/testing/cross_backend/testing_reset_actions.d.ts.map +1 -1
  273. package/dist/testing/cross_backend/testing_reset_actions.js +154 -5
  274. package/dist/testing/cross_backend/token_scope_surface.d.ts.map +1 -1
  275. package/dist/testing/cross_backend/token_scope_surface.js +25 -21
  276. package/dist/testing/cross_backend/transport_composition.d.ts +60 -0
  277. package/dist/testing/cross_backend/transport_composition.d.ts.map +1 -0
  278. package/dist/testing/cross_backend/transport_composition.js +364 -0
  279. package/dist/testing/cross_backend/ts_spine_backend_config.d.ts.map +1 -1
  280. package/dist/testing/cross_backend/ts_spine_backend_config.js +21 -6
  281. package/dist/testing/cross_backend/ws_action_rate_limit.d.ts.map +1 -1
  282. package/dist/testing/cross_backend/ws_action_rate_limit.js +21 -1
  283. package/dist/testing/cross_backend/ws_role_gated.d.ts +38 -0
  284. package/dist/testing/cross_backend/ws_role_gated.d.ts.map +1 -0
  285. package/dist/testing/cross_backend/ws_role_gated.js +142 -0
  286. package/dist/testing/entities.d.ts +23 -0
  287. package/dist/testing/entities.d.ts.map +1 -1
  288. package/dist/testing/entities.js +37 -0
  289. package/dist/testing/integration.d.ts.map +1 -1
  290. package/dist/testing/integration.js +3 -1
  291. package/dist/testing/middleware.d.ts +10 -0
  292. package/dist/testing/middleware.d.ts.map +1 -1
  293. package/dist/testing/middleware.js +31 -7
  294. package/dist/testing/schema_introspect.js +1 -1
  295. package/dist/testing/schema_parity.d.ts +4 -3
  296. package/dist/testing/schema_parity.d.ts.map +1 -1
  297. package/dist/testing/schema_parity.js +4 -3
  298. package/dist/testing/schema_ready_fixture.d.ts +2 -4
  299. package/dist/testing/schema_ready_fixture.d.ts.map +1 -1
  300. package/dist/testing/schema_ready_fixture.js +2 -4
  301. package/dist/testing/stubs.d.ts +16 -3
  302. package/dist/testing/stubs.d.ts.map +1 -1
  303. package/dist/testing/stubs.js +20 -7
  304. package/dist/testing/surface_invariants.js +2 -2
  305. package/dist/ui/auth_state.svelte.d.ts +10 -0
  306. package/dist/ui/auth_state.svelte.d.ts.map +1 -1
  307. package/dist/ui/auth_state.svelte.js +22 -4
  308. package/package.json +1 -1
  309. package/dist/db/cell_history_ddl.d.ts +0 -38
  310. package/dist/db/cell_history_ddl.d.ts.map +0 -1
  311. 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). No `admin_` prefix — the
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":"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"}
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;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;CAYF,CAAC;AAEtC;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;CAiBD,CAAC;AAEtC;;;;;;;GAOG;AACH,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;CAYJ,CAAC;AAEtC,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;CAUJ,CAAC;AAEtC,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;CAWP,CAAC;AAEtC;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,EAAE,KAAK,CAAC,yBAAyB,CAenE,CAAC"}
@@ -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). No `admin_` prefix — the
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;AAG/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,CAogBjB,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 { jsonrpc_errors } from '../http/jsonrpc_errors.js';
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. Tombstones the
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)) {
@@ -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"}
@@ -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. Updates `last_used_at` and `last_used_ip` on success
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<ApiToken | undefined>;
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;AAEpD,OAAO,EAAE,KAAK,UAAU,EAAmD,MAAM,kBAAkB,CAAC;AAEpG,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;;;;;;;;;;;;;;GAcG;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,QAAQ,GAAG,SAAS,CAgC9B,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"}
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. Updates `last_used_at` and `last_used_ip` on success
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)} FROM api_token
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
- if (parse_stored_token_scope(row.scope) === null) {
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;AAU7E,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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,4BAA4B,GAAI,UAAU,oBAAoB,KAAG,KAAK,CAAC,SAAS,CAsG5F,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, not what a transport must do about
66
- * it. The two listeners differ on `role` on purpose: a WebSocket message is
67
- * re-authorized per dispatch, so the socket stays open and its next message
68
- * is refused, while a stream is authorized once at open and must be closed.
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":"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"}
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 `AUTH_API_TOKEN_ID_KEY` on success
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;AAUtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAIrD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,eAAO,MAAM,6BAA6B,GAAI,MAAM,SAAS,EAAE,KAAK,MAAM,KAAG,iBAuE5E,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"}
@@ -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 { parse_stored_token_scope, token_scope_full } from './token_scope.js';
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 `AUTH_API_TOKEN_ID_KEY` on success
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
- // `query_validate_api_token` is fail-closed on an unreadable scope, so a
109
- // token that got this far has a readable one. The `?? token_scope_full()`
110
- // is unreachable defensive cover, not a fallback with meaning.
111
- c.set(TOKEN_SCOPE_KEY, parse_stored_token_scope(api_token.scope) ?? token_scope_full());
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
  };
@@ -46,6 +46,7 @@ export declare const bootstrap_route_shape: {
46
46
  account: "none";
47
47
  actor: "none";
48
48
  };
49
+ mints_credential: true;
49
50
  description: string;
50
51
  transaction: false;
51
52
  input: z.ZodObject<{
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiBI,CAAC"}
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;AAExE,OAAO,EAAgC,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACpF,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,CAmHjB,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"}