@fuzdev/fuz_app 0.55.0 → 0.57.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 (333) hide show
  1. package/dist/actions/CLAUDE.md +211 -155
  2. package/dist/actions/action_bridge.d.ts +8 -5
  3. package/dist/actions/action_bridge.d.ts.map +1 -1
  4. package/dist/actions/action_bridge.js +1 -11
  5. package/dist/actions/action_codegen.d.ts +19 -0
  6. package/dist/actions/action_codegen.d.ts.map +1 -1
  7. package/dist/actions/action_codegen.js +20 -14
  8. package/dist/actions/action_registry.d.ts.map +1 -1
  9. package/dist/actions/action_registry.js +5 -2
  10. package/dist/actions/action_rpc.d.ts +110 -44
  11. package/dist/actions/action_rpc.d.ts.map +1 -1
  12. package/dist/actions/action_rpc.js +92 -287
  13. package/dist/actions/action_spec.d.ts +55 -16
  14. package/dist/actions/action_spec.d.ts.map +1 -1
  15. package/dist/actions/action_spec.js +16 -11
  16. package/dist/actions/action_types.d.ts +28 -60
  17. package/dist/actions/action_types.d.ts.map +1 -1
  18. package/dist/actions/action_types.js +13 -5
  19. package/dist/actions/broadcast_api.d.ts +2 -2
  20. package/dist/actions/broadcast_api.js +2 -2
  21. package/dist/actions/compile_action_registry.d.ts +50 -0
  22. package/dist/actions/compile_action_registry.d.ts.map +1 -0
  23. package/dist/actions/compile_action_registry.js +69 -0
  24. package/dist/actions/heartbeat.d.ts +8 -4
  25. package/dist/actions/heartbeat.d.ts.map +1 -1
  26. package/dist/actions/heartbeat.js +5 -4
  27. package/dist/actions/perform_action.d.ts +145 -0
  28. package/dist/actions/perform_action.d.ts.map +1 -0
  29. package/dist/actions/perform_action.js +258 -0
  30. package/dist/actions/register_action_ws.d.ts +44 -38
  31. package/dist/actions/register_action_ws.d.ts.map +1 -1
  32. package/dist/actions/register_action_ws.js +101 -159
  33. package/dist/actions/register_ws_endpoint.d.ts +2 -10
  34. package/dist/actions/register_ws_endpoint.d.ts.map +1 -1
  35. package/dist/actions/register_ws_endpoint.js +32 -10
  36. package/dist/actions/transports_ws_auth_guard.d.ts +1 -1
  37. package/dist/actions/transports_ws_auth_guard.js +1 -1
  38. package/dist/actions/transports_ws_backend.d.ts +1 -1
  39. package/dist/actions/transports_ws_backend.js +1 -1
  40. package/dist/auth/CLAUDE.md +673 -442
  41. package/dist/auth/account_action_specs.d.ts +28 -7
  42. package/dist/auth/account_action_specs.d.ts.map +1 -1
  43. package/dist/auth/account_action_specs.js +7 -7
  44. package/dist/auth/account_actions.d.ts +8 -14
  45. package/dist/auth/account_actions.d.ts.map +1 -1
  46. package/dist/auth/account_actions.js +26 -32
  47. package/dist/auth/account_queries.d.ts +46 -13
  48. package/dist/auth/account_queries.d.ts.map +1 -1
  49. package/dist/auth/account_queries.js +73 -33
  50. package/dist/auth/account_routes.d.ts +4 -3
  51. package/dist/auth/account_routes.d.ts.map +1 -1
  52. package/dist/auth/account_routes.js +58 -33
  53. package/dist/auth/account_schema.d.ts +46 -54
  54. package/dist/auth/account_schema.d.ts.map +1 -1
  55. package/dist/auth/account_schema.js +21 -48
  56. package/dist/auth/admin_action_specs.d.ts +55 -21
  57. package/dist/auth/admin_action_specs.d.ts.map +1 -1
  58. package/dist/auth/admin_action_specs.js +42 -26
  59. package/dist/auth/admin_actions.d.ts +14 -21
  60. package/dist/auth/admin_actions.d.ts.map +1 -1
  61. package/dist/auth/admin_actions.js +47 -44
  62. package/dist/auth/audit_emitter.d.ts +160 -0
  63. package/dist/auth/audit_emitter.d.ts.map +1 -0
  64. package/dist/auth/audit_emitter.js +83 -0
  65. package/dist/auth/audit_log_queries.d.ts +17 -87
  66. package/dist/auth/audit_log_queries.d.ts.map +1 -1
  67. package/dist/auth/audit_log_queries.js +17 -96
  68. package/dist/auth/audit_log_routes.d.ts +1 -1
  69. package/dist/auth/audit_log_routes.d.ts.map +1 -1
  70. package/dist/auth/audit_log_routes.js +7 -3
  71. package/dist/auth/audit_log_schema.d.ts +48 -42
  72. package/dist/auth/audit_log_schema.d.ts.map +1 -1
  73. package/dist/auth/audit_log_schema.js +56 -43
  74. package/dist/auth/auth_guard_resolver.d.ts +44 -0
  75. package/dist/auth/auth_guard_resolver.d.ts.map +1 -0
  76. package/dist/auth/auth_guard_resolver.js +56 -0
  77. package/dist/auth/bootstrap_account.d.ts +7 -7
  78. package/dist/auth/bootstrap_account.d.ts.map +1 -1
  79. package/dist/auth/bootstrap_account.js +7 -7
  80. package/dist/auth/bootstrap_routes.d.ts.map +1 -1
  81. package/dist/auth/bootstrap_routes.js +11 -10
  82. package/dist/auth/cleanup.d.ts +20 -26
  83. package/dist/auth/cleanup.d.ts.map +1 -1
  84. package/dist/auth/cleanup.js +33 -47
  85. package/dist/auth/credential_type_schema.d.ts +115 -0
  86. package/dist/auth/credential_type_schema.d.ts.map +1 -0
  87. package/dist/auth/credential_type_schema.js +127 -0
  88. package/dist/auth/daemon_token_middleware.d.ts +1 -1
  89. package/dist/auth/daemon_token_middleware.js +3 -3
  90. package/dist/auth/ddl.d.ts +2 -2
  91. package/dist/auth/ddl.d.ts.map +1 -1
  92. package/dist/auth/ddl.js +6 -6
  93. package/dist/auth/deps.d.ts +7 -32
  94. package/dist/auth/deps.d.ts.map +1 -1
  95. package/dist/auth/grant_path_schema.d.ts +117 -0
  96. package/dist/auth/grant_path_schema.d.ts.map +1 -0
  97. package/dist/auth/grant_path_schema.js +137 -0
  98. package/dist/auth/invite_queries.d.ts +12 -1
  99. package/dist/auth/invite_queries.d.ts.map +1 -1
  100. package/dist/auth/invite_queries.js +12 -1
  101. package/dist/auth/invite_schema.d.ts +1 -1
  102. package/dist/auth/invite_schema.d.ts.map +1 -1
  103. package/dist/auth/invite_schema.js +1 -1
  104. package/dist/auth/middleware.d.ts.map +1 -1
  105. package/dist/auth/middleware.js +5 -2
  106. package/dist/auth/migrations.d.ts +22 -7
  107. package/dist/auth/migrations.d.ts.map +1 -1
  108. package/dist/auth/migrations.js +64 -25
  109. package/dist/auth/request_context.d.ts +157 -170
  110. package/dist/auth/request_context.d.ts.map +1 -1
  111. package/dist/auth/request_context.js +224 -268
  112. package/dist/auth/{permit_offer_action_specs.d.ts → role_grant_offer_action_specs.d.ts} +130 -100
  113. package/dist/auth/role_grant_offer_action_specs.d.ts.map +1 -0
  114. package/dist/auth/role_grant_offer_action_specs.js +262 -0
  115. package/dist/auth/role_grant_offer_actions.d.ts +104 -0
  116. package/dist/auth/role_grant_offer_actions.d.ts.map +1 -0
  117. package/dist/auth/{permit_offer_actions.js → role_grant_offer_actions.js} +153 -140
  118. package/dist/auth/{permit_offer_notifications.d.ts → role_grant_offer_notifications.d.ts} +80 -70
  119. package/dist/auth/role_grant_offer_notifications.d.ts.map +1 -0
  120. package/dist/auth/role_grant_offer_notifications.js +182 -0
  121. package/dist/auth/{permit_offer_queries.d.ts → role_grant_offer_queries.d.ts} +64 -64
  122. package/dist/auth/role_grant_offer_queries.d.ts.map +1 -0
  123. package/dist/auth/{permit_offer_queries.js → role_grant_offer_queries.js} +136 -123
  124. package/dist/auth/role_grant_offer_schema.d.ts +150 -0
  125. package/dist/auth/role_grant_offer_schema.d.ts.map +1 -0
  126. package/dist/auth/{permit_offer_schema.js → role_grant_offer_schema.js} +55 -36
  127. package/dist/auth/role_grant_queries.d.ts +231 -0
  128. package/dist/auth/role_grant_queries.d.ts.map +1 -0
  129. package/dist/auth/role_grant_queries.js +320 -0
  130. package/dist/auth/role_schema.d.ts +150 -40
  131. package/dist/auth/role_schema.d.ts.map +1 -1
  132. package/dist/auth/role_schema.js +144 -45
  133. package/dist/auth/scope_kind_schema.d.ts +96 -0
  134. package/dist/auth/scope_kind_schema.d.ts.map +1 -0
  135. package/dist/auth/scope_kind_schema.js +94 -0
  136. package/dist/auth/self_service_role_action_specs.d.ts +4 -1
  137. package/dist/auth/self_service_role_action_specs.d.ts.map +1 -1
  138. package/dist/auth/self_service_role_action_specs.js +2 -2
  139. package/dist/auth/self_service_role_actions.d.ts +35 -29
  140. package/dist/auth/self_service_role_actions.d.ts.map +1 -1
  141. package/dist/auth/self_service_role_actions.js +58 -48
  142. package/dist/auth/session_cookie.d.ts +43 -6
  143. package/dist/auth/session_cookie.d.ts.map +1 -1
  144. package/dist/auth/session_cookie.js +31 -5
  145. package/dist/auth/session_middleware.d.ts +37 -3
  146. package/dist/auth/session_middleware.d.ts.map +1 -1
  147. package/dist/auth/session_middleware.js +33 -7
  148. package/dist/auth/signup_routes.d.ts.map +1 -1
  149. package/dist/auth/signup_routes.js +48 -19
  150. package/dist/auth/standard_action_specs.d.ts +2 -2
  151. package/dist/auth/standard_action_specs.js +4 -4
  152. package/dist/auth/standard_rpc_actions.d.ts +23 -19
  153. package/dist/auth/standard_rpc_actions.d.ts.map +1 -1
  154. package/dist/auth/standard_rpc_actions.js +12 -12
  155. package/dist/db/migrate.d.ts +1 -1
  156. package/dist/db/migrate.js +1 -1
  157. package/dist/dev/setup.d.ts +2 -2
  158. package/dist/dev/setup.d.ts.map +1 -1
  159. package/dist/dev/setup.js +4 -4
  160. package/dist/env/load.d.ts +1 -1
  161. package/dist/env/load.js +1 -1
  162. package/dist/hono_context.d.ts +27 -45
  163. package/dist/hono_context.d.ts.map +1 -1
  164. package/dist/hono_context.js +14 -28
  165. package/dist/http/CLAUDE.md +235 -121
  166. package/dist/http/auth_shape.d.ts +191 -0
  167. package/dist/http/auth_shape.d.ts.map +1 -0
  168. package/dist/http/auth_shape.js +237 -0
  169. package/dist/http/common_routes.js +3 -3
  170. package/dist/http/db_routes.d.ts +4 -0
  171. package/dist/http/db_routes.d.ts.map +1 -1
  172. package/dist/http/db_routes.js +44 -7
  173. package/dist/http/error_schemas.d.ts +72 -39
  174. package/dist/http/error_schemas.d.ts.map +1 -1
  175. package/dist/http/error_schemas.js +81 -33
  176. package/dist/http/pending_effects.d.ts +71 -18
  177. package/dist/http/pending_effects.d.ts.map +1 -1
  178. package/dist/http/pending_effects.js +87 -18
  179. package/dist/http/proxy.d.ts +52 -5
  180. package/dist/http/proxy.d.ts.map +1 -1
  181. package/dist/http/proxy.js +92 -14
  182. package/dist/http/route_spec.d.ts +89 -75
  183. package/dist/http/route_spec.d.ts.map +1 -1
  184. package/dist/http/route_spec.js +54 -72
  185. package/dist/http/schema_helpers.d.ts +3 -14
  186. package/dist/http/schema_helpers.d.ts.map +1 -1
  187. package/dist/http/schema_helpers.js +2 -14
  188. package/dist/http/surface.d.ts +2 -10
  189. package/dist/http/surface.d.ts.map +1 -1
  190. package/dist/http/surface.js +3 -4
  191. package/dist/http/surface_query.d.ts +39 -35
  192. package/dist/http/surface_query.d.ts.map +1 -1
  193. package/dist/http/surface_query.js +79 -36
  194. package/dist/primitive_schemas.d.ts +39 -0
  195. package/dist/primitive_schemas.d.ts.map +1 -0
  196. package/dist/primitive_schemas.js +40 -0
  197. package/dist/realtime/sse_auth_guard.d.ts +5 -5
  198. package/dist/realtime/sse_auth_guard.js +9 -9
  199. package/dist/runtime/mock.d.ts +1 -1
  200. package/dist/runtime/mock.js +1 -1
  201. package/dist/server/app_backend.d.ts +14 -11
  202. package/dist/server/app_backend.d.ts.map +1 -1
  203. package/dist/server/app_backend.js +12 -8
  204. package/dist/server/app_server.d.ts +7 -7
  205. package/dist/server/app_server.d.ts.map +1 -1
  206. package/dist/server/app_server.js +35 -40
  207. package/dist/server/validate_nginx.d.ts +1 -1
  208. package/dist/server/validate_nginx.js +1 -1
  209. package/dist/testing/CLAUDE.md +50 -38
  210. package/dist/testing/admin_integration.d.ts +5 -6
  211. package/dist/testing/admin_integration.d.ts.map +1 -1
  212. package/dist/testing/admin_integration.js +87 -85
  213. package/dist/testing/app_server.d.ts +11 -14
  214. package/dist/testing/app_server.d.ts.map +1 -1
  215. package/dist/testing/app_server.js +16 -15
  216. package/dist/testing/assertions.d.ts.map +1 -1
  217. package/dist/testing/assertions.js +2 -1
  218. package/dist/testing/attack_surface.d.ts.map +1 -1
  219. package/dist/testing/attack_surface.js +15 -9
  220. package/dist/testing/audit_completeness.d.ts +2 -2
  221. package/dist/testing/audit_completeness.d.ts.map +1 -1
  222. package/dist/testing/audit_completeness.js +36 -36
  223. package/dist/testing/auth_apps.d.ts +5 -4
  224. package/dist/testing/auth_apps.d.ts.map +1 -1
  225. package/dist/testing/auth_apps.js +22 -19
  226. package/dist/testing/data_exposure.d.ts.map +1 -1
  227. package/dist/testing/data_exposure.js +5 -5
  228. package/dist/testing/db.d.ts +1 -1
  229. package/dist/testing/db.d.ts.map +1 -1
  230. package/dist/testing/db.js +4 -4
  231. package/dist/testing/db_entities.d.ts +22 -0
  232. package/dist/testing/db_entities.d.ts.map +1 -0
  233. package/dist/testing/db_entities.js +28 -0
  234. package/dist/testing/entities.d.ts +8 -7
  235. package/dist/testing/entities.d.ts.map +1 -1
  236. package/dist/testing/entities.js +21 -18
  237. package/dist/testing/integration.d.ts.map +1 -1
  238. package/dist/testing/integration.js +13 -14
  239. package/dist/testing/integration_helpers.d.ts +4 -4
  240. package/dist/testing/integration_helpers.d.ts.map +1 -1
  241. package/dist/testing/integration_helpers.js +20 -18
  242. package/dist/testing/middleware.d.ts +4 -4
  243. package/dist/testing/middleware.d.ts.map +1 -1
  244. package/dist/testing/middleware.js +12 -11
  245. package/dist/testing/rpc_attack_surface.d.ts.map +1 -1
  246. package/dist/testing/rpc_attack_surface.js +40 -24
  247. package/dist/testing/rpc_round_trip.d.ts +1 -1
  248. package/dist/testing/rpc_round_trip.d.ts.map +1 -1
  249. package/dist/testing/rpc_round_trip.js +14 -13
  250. package/dist/testing/sse_round_trip.d.ts +3 -4
  251. package/dist/testing/sse_round_trip.d.ts.map +1 -1
  252. package/dist/testing/sse_round_trip.js +7 -11
  253. package/dist/testing/standard.d.ts +1 -1
  254. package/dist/testing/stubs.d.ts +25 -0
  255. package/dist/testing/stubs.d.ts.map +1 -1
  256. package/dist/testing/stubs.js +43 -2
  257. package/dist/testing/surface_invariants.d.ts +14 -6
  258. package/dist/testing/surface_invariants.d.ts.map +1 -1
  259. package/dist/testing/surface_invariants.js +119 -43
  260. package/dist/testing/ws_round_trip.d.ts +12 -13
  261. package/dist/testing/ws_round_trip.d.ts.map +1 -1
  262. package/dist/testing/ws_round_trip.js +19 -11
  263. package/dist/ui/AdminAccounts.svelte +23 -20
  264. package/dist/ui/AdminOverview.svelte +15 -13
  265. package/dist/ui/AdminOverview.svelte.d.ts.map +1 -1
  266. package/dist/ui/{AdminPermitHistory.svelte → AdminRoleGrantHistory.svelte} +12 -12
  267. package/dist/ui/AdminRoleGrantHistory.svelte.d.ts +4 -0
  268. package/dist/ui/AdminRoleGrantHistory.svelte.d.ts.map +1 -0
  269. package/dist/ui/BootstrapForm.svelte +1 -1
  270. package/dist/ui/CLAUDE.md +60 -60
  271. package/dist/ui/{PermitOfferForm.svelte → RoleGrantOfferForm.svelte} +27 -26
  272. package/dist/ui/{PermitOfferForm.svelte.d.ts → RoleGrantOfferForm.svelte.d.ts} +7 -7
  273. package/dist/ui/RoleGrantOfferForm.svelte.d.ts.map +1 -0
  274. package/dist/ui/{PermitOfferHistory.svelte → RoleGrantOfferHistory.svelte} +12 -12
  275. package/dist/ui/{PermitOfferHistory.svelte.d.ts → RoleGrantOfferHistory.svelte.d.ts} +4 -4
  276. package/dist/ui/RoleGrantOfferHistory.svelte.d.ts.map +1 -0
  277. package/dist/ui/{PermitOfferInbox.svelte → RoleGrantOfferInbox.svelte} +14 -14
  278. package/dist/ui/{PermitOfferInbox.svelte.d.ts → RoleGrantOfferInbox.svelte.d.ts} +4 -4
  279. package/dist/ui/RoleGrantOfferInbox.svelte.d.ts.map +1 -0
  280. package/dist/ui/SignupForm.svelte +1 -1
  281. package/dist/ui/SurfaceExplorer.svelte +35 -15
  282. package/dist/ui/SurfaceExplorer.svelte.d.ts.map +1 -1
  283. package/dist/ui/account_sessions_state.svelte.d.ts +2 -3
  284. package/dist/ui/account_sessions_state.svelte.d.ts.map +1 -1
  285. package/dist/ui/account_sessions_state.svelte.js +2 -3
  286. package/dist/ui/admin_accounts_state.svelte.d.ts +18 -18
  287. package/dist/ui/admin_accounts_state.svelte.d.ts.map +1 -1
  288. package/dist/ui/admin_accounts_state.svelte.js +16 -16
  289. package/dist/ui/admin_rpc_adapters.d.ts +20 -20
  290. package/dist/ui/admin_rpc_adapters.d.ts.map +1 -1
  291. package/dist/ui/admin_rpc_adapters.js +17 -17
  292. package/dist/ui/admin_sessions_state.svelte.d.ts +2 -2
  293. package/dist/ui/admin_sessions_state.svelte.js +2 -2
  294. package/dist/ui/audit_log_state.svelte.d.ts +7 -7
  295. package/dist/ui/audit_log_state.svelte.d.ts.map +1 -1
  296. package/dist/ui/audit_log_state.svelte.js +6 -6
  297. package/dist/ui/auth_state.svelte.d.ts +3 -3
  298. package/dist/ui/auth_state.svelte.d.ts.map +1 -1
  299. package/dist/ui/auth_state.svelte.js +6 -6
  300. package/dist/ui/format_scope.d.ts +2 -2
  301. package/dist/ui/format_scope.js +2 -2
  302. package/dist/ui/{permit_offers_state.svelte.d.ts → role_grant_offers_state.svelte.d.ts} +30 -30
  303. package/dist/ui/role_grant_offers_state.svelte.d.ts.map +1 -0
  304. package/dist/ui/{permit_offers_state.svelte.js → role_grant_offers_state.svelte.js} +18 -18
  305. package/dist/ui/ui_format.js +2 -2
  306. package/package.json +3 -3
  307. package/dist/auth/permit_offer_action_specs.d.ts.map +0 -1
  308. package/dist/auth/permit_offer_action_specs.js +0 -258
  309. package/dist/auth/permit_offer_actions.d.ts +0 -110
  310. package/dist/auth/permit_offer_actions.d.ts.map +0 -1
  311. package/dist/auth/permit_offer_notifications.d.ts.map +0 -1
  312. package/dist/auth/permit_offer_notifications.js +0 -182
  313. package/dist/auth/permit_offer_queries.d.ts.map +0 -1
  314. package/dist/auth/permit_offer_schema.d.ts +0 -125
  315. package/dist/auth/permit_offer_schema.d.ts.map +0 -1
  316. package/dist/auth/permit_queries.d.ts +0 -222
  317. package/dist/auth/permit_queries.d.ts.map +0 -1
  318. package/dist/auth/permit_queries.js +0 -305
  319. package/dist/auth/require_keeper.d.ts +0 -20
  320. package/dist/auth/require_keeper.d.ts.map +0 -1
  321. package/dist/auth/require_keeper.js +0 -35
  322. package/dist/auth/route_guards.d.ts +0 -27
  323. package/dist/auth/route_guards.d.ts.map +0 -1
  324. package/dist/auth/route_guards.js +0 -38
  325. package/dist/auth/session_lifecycle.d.ts +0 -37
  326. package/dist/auth/session_lifecycle.d.ts.map +0 -1
  327. package/dist/auth/session_lifecycle.js +0 -29
  328. package/dist/ui/AdminPermitHistory.svelte.d.ts +0 -4
  329. package/dist/ui/AdminPermitHistory.svelte.d.ts.map +0 -1
  330. package/dist/ui/PermitOfferForm.svelte.d.ts.map +0 -1
  331. package/dist/ui/PermitOfferHistory.svelte.d.ts.map +0 -1
  332. package/dist/ui/PermitOfferInbox.svelte.d.ts.map +0 -1
  333. package/dist/ui/permit_offers_state.svelte.d.ts.map +0 -1
@@ -1,17 +1,17 @@
1
1
  /**
2
- * Periodic auth cleanup — sweeps expired sessions and permit offers.
2
+ * Periodic auth cleanup — sweeps expired sessions and role_grant offers.
3
3
  *
4
4
  * Single entry point for consumers scheduling auth maintenance. Internally
5
5
  * runs every known sweep and emits the corresponding audit events so
6
6
  * consumer code only manages cadence, not per-task wiring.
7
7
  *
8
8
  * The per-task primitives remain exported from their home modules
9
- * (`query_session_cleanup_expired`, `query_permit_offer_sweep_expired`);
10
- * `cleanup_expired_permit_offers` here wraps the latter with the required
11
- * `permit_offer_expire` audit emission and is the piece most likely to be
9
+ * (`query_session_cleanup_expired`, `query_role_grant_offer_sweep_expired`);
10
+ * `cleanup_expired_role_grant_offers` here wraps the latter with the required
11
+ * `role_grant_offer_expire` audit emission and is the piece most likely to be
12
12
  * reused in a consumer's bespoke scheduler.
13
13
  *
14
- * Idempotency: the audit log has no tombstone on `permit_offer_expire`, so
14
+ * Idempotency: the audit log has no tombstone on `role_grant_offer_expire`, so
15
15
  * concurrent sweep runs double-audit. The expected deployment pattern is a
16
16
  * single scheduled invocation per instance — matching
17
17
  * `query_session_cleanup_expired`.
@@ -19,73 +19,59 @@
19
19
  * @module
20
20
  */
21
21
  import { query_session_cleanup_expired } from './session_queries.js';
22
- import { query_permit_offer_sweep_expired } from './permit_offer_queries.js';
23
- import { query_audit_log } from './audit_log_queries.js';
22
+ import { query_role_grant_offer_sweep_expired } from './role_grant_offer_queries.js';
24
23
  /**
25
- * Sweep expired permit offers and emit one `permit_offer_expire` audit
24
+ * Sweep expired role_grant offers and emit one `role_grant_offer_expire` audit
26
25
  * event per row.
27
26
  *
28
27
  * Returns the count of offers audit-stamped. The offer rows themselves are
29
28
  * preserved — offers carry audit value for the history view even after
30
- * expiry, and accepted rows are the provenance for the resulting permit
29
+ * expiry, and accepted rows are the provenance for the resulting role_grant
31
30
  * (deleting expired rows would not threaten that, but keeping them uniform
32
31
  * with the retention policy for terminal rows is simpler).
33
32
  *
34
- * @mutates `audit_log` table - inserts one `permit_offer_expire` row per swept offer
33
+ * @mutates `audit_log` table - inserts one `role_grant_offer_expire` row per swept offer
35
34
  */
36
- export const cleanup_expired_permit_offers = async (deps) => {
37
- const expired = await query_permit_offer_sweep_expired(deps);
38
- const { on_audit_event, audit_log_config } = deps;
35
+ export const cleanup_expired_role_grant_offers = async (deps) => {
36
+ const expired = await query_role_grant_offer_sweep_expired(deps);
39
37
  for (const offer of expired) {
40
- try {
41
- // `permit_offer_expire` populates `target_actor_id` only when the
42
- // offer was actor-targeted (`to_actor_id` set at create time).
43
- // Account-grain offers (no `to_actor_id`) never bound to a
44
- // specific actor and leave the field null.
45
- const event = await query_audit_log(deps, {
46
- event_type: 'permit_offer_expire',
47
- actor_id: offer.from_actor_id,
48
- target_account_id: offer.to_account_id,
49
- target_actor_id: offer.to_actor_id,
50
- ip: null,
51
- metadata: {
52
- offer_id: offer.id,
53
- role: offer.role,
54
- scope_id: offer.scope_id,
55
- },
56
- }, audit_log_config);
57
- if (on_audit_event) {
58
- try {
59
- on_audit_event(event);
60
- }
61
- catch (callback_err) {
62
- deps.log.error('on_audit_event callback failed:', callback_err);
63
- }
64
- }
65
- }
66
- catch (err) {
67
- // One failed audit write must not starve siblings — log and continue.
68
- deps.log.error('permit_offer_expire audit write failed:', err);
69
- }
38
+ // `role_grant_offer_expire` populates `target_actor_id` only when the
39
+ // offer was actor-targeted (`to_actor_id` set at create time).
40
+ // Account-grain offers (no `to_actor_id`) never bound to a
41
+ // specific actor and leave the field null.
42
+ // `emit_pool` swallows + logs both write errors and per-listener
43
+ // throws, so a single bad row never starves the rest of the sweep.
44
+ await deps.audit.emit_pool({
45
+ event_type: 'role_grant_offer_expire',
46
+ actor_id: offer.from_actor_id,
47
+ target_account_id: offer.to_account_id,
48
+ target_actor_id: offer.to_actor_id,
49
+ ip: null,
50
+ metadata: {
51
+ offer_id: offer.id,
52
+ role: offer.role,
53
+ scope_id: offer.scope_id,
54
+ },
55
+ });
70
56
  }
71
57
  return expired.length;
72
58
  };
73
59
  /**
74
- * Run every auth cleanup sweep — expired sessions and expired permit
60
+ * Run every auth cleanup sweep — expired sessions and expired role_grant
75
61
  * offers — and return the counts.
76
62
  *
77
63
  * Consumers call this from a scheduled task (setInterval, cron, etc.)
78
64
  * alongside their own domain cleanup. Errors from individual sweeps are
79
65
  * re-thrown so the caller's scheduler can log/alert; use the per-task
80
- * helpers (`query_session_cleanup_expired`, `cleanup_expired_permit_offers`)
66
+ * helpers (`query_session_cleanup_expired`, `cleanup_expired_role_grant_offers`)
81
67
  * directly if you need finer error isolation.
82
68
  *
83
69
  * @mutates `auth_session` table - deletes expired sessions
84
- * @mutates `audit_log` table - emits `permit_offer_expire` rows for expired offers
70
+ * @mutates `audit_log` table - emits `role_grant_offer_expire` rows for expired offers
85
71
  * @throws Error re-thrown from any sweep that fails (no per-sweep isolation here)
86
72
  */
87
73
  export const run_auth_cleanup = async (deps) => {
88
74
  const expired_sessions = await query_session_cleanup_expired(deps);
89
- const expired_offers = await cleanup_expired_permit_offers(deps);
75
+ const expired_offers = await cleanup_expired_role_grant_offers(deps);
90
76
  return { expired_sessions, expired_offers };
91
77
  };
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Credential-type registry — how a request was authenticated.
3
+ *
4
+ * Three builtins: `session` (cookie-based), `api_token` (HTTP Bearer
5
+ * token), `daemon_token` (filesystem proof for the keeper account).
6
+ * Open-string registry on top so consumers can declare additional
7
+ * credential types (e.g. `'sso_assertion'`, `'agent_token'`) without an
8
+ * upstream release. `RoleSpec.required_credential_types` references
9
+ * entries from this registry; v1 keeps the field informative-only
10
+ * (consumed by `auth/middleware.ts` and the dispatcher). Mirrors the
11
+ * open-registry pattern used for `RoleName`, `ScopeKindName`,
12
+ * `GrantPathName`, and `AuditEventTypeName`.
13
+ *
14
+ * The Hono-side wire-validated `CredentialType` Zod enum (in
15
+ * `hono_context.ts`) is the closed-set narrow type middleware sets on
16
+ * the context; the constants below are the source of truth for those
17
+ * three string values. Future builtin credential types added here
18
+ * propagate to the wire enum by editing the import list.
19
+ *
20
+ * @module
21
+ */
22
+ import { z } from 'zod';
23
+ /**
24
+ * Letter (lowercase a-z) start and end (or single letter), with letters
25
+ * and underscores in between. Mirrors `RoleName`, `ScopeKindName`,
26
+ * `GrantPathName`. Rejects empty strings, leading or trailing
27
+ * underscores, uppercase, and digits.
28
+ */
29
+ export declare const CREDENTIAL_TYPE_NAME_REGEX: RegExp;
30
+ /** Zod schema for valid credential-type name strings. */
31
+ export declare const CredentialTypeName: z.ZodString;
32
+ export type CredentialTypeName = z.infer<typeof CredentialTypeName>;
33
+ /** Cookie-based session credential. */
34
+ export declare const CREDENTIAL_TYPE_SESSION = "session";
35
+ /**
36
+ * HTTP `Authorization: Bearer` API token credential. The wire literal
37
+ * `'api_token'` aligns with the `api_token` storage table name; the
38
+ * constant is named `_API_TOKEN` (not `_BEARER`) to keep wire and
39
+ * storage nomenclature in lockstep.
40
+ */
41
+ export declare const CREDENTIAL_TYPE_API_TOKEN = "api_token";
42
+ /** Daemon-token credential — filesystem proof for the keeper account. */
43
+ export declare const CREDENTIAL_TYPE_DAEMON_TOKEN = "daemon_token";
44
+ /** The builtin credential-type names as a const tuple. */
45
+ export declare const BUILTIN_CREDENTIAL_TYPES: readonly ["session", "api_token", "daemon_token"];
46
+ /** Zod enum for builtin credential types only. */
47
+ export declare const BuiltinCredentialType: z.ZodEnum<{
48
+ daemon_token: "daemon_token";
49
+ session: "session";
50
+ api_token: "api_token";
51
+ }>;
52
+ export type BuiltinCredentialType = z.infer<typeof BuiltinCredentialType>;
53
+ /**
54
+ * Per-credential-type metadata. `description` is admin-UI-facing copy
55
+ * (mirrors `RoleSpec.description` and `ScopeKindMeta.description`).
56
+ * Open shape so v2 can extend without a breaking change.
57
+ */
58
+ export interface CredentialTypeMeta {
59
+ description?: string;
60
+ }
61
+ /**
62
+ * Builtin credential-type metadata. Not overridable by consumers.
63
+ *
64
+ * Typed `ReadonlyMap` for the contract — but JS Maps don't honor
65
+ * `Object.freeze` for `.set` / `.delete` / `.clear` (they mutate
66
+ * internal slots, not own properties), so freeze adds no runtime guard
67
+ * here. Read once at startup by `create_credential_type_schema`;
68
+ * runtime mutation has no effect on already-built schemas.
69
+ */
70
+ export declare const BUILTIN_CREDENTIAL_TYPE_META: ReadonlyMap<string, CredentialTypeMeta>;
71
+ /** The result of `create_credential_type_schema` — a Zod schema and metadata map. */
72
+ export interface CredentialTypeSchemaResult {
73
+ /**
74
+ * Zod schema that validates credential-type name strings against the
75
+ * registered set (builtins + consumer-declared). Use at I/O
76
+ * boundaries (admin UIs, codegen) and as the construction-time check
77
+ * inside `create_role_schema` for every
78
+ * `RoleSpec.required_credential_types` entry.
79
+ */
80
+ CredentialType: z.ZodType<string>;
81
+ /**
82
+ * Map of every registered credential-type to its metadata. Keyed by
83
+ * name. Read at startup by admin / codegen surfaces.
84
+ */
85
+ credential_types: ReadonlyMap<string, CredentialTypeMeta>;
86
+ }
87
+ /**
88
+ * Create a credential-type schema from the builtin set plus optional
89
+ * consumer-declared additions.
90
+ *
91
+ * Builtins (`session`, `api_token`, `daemon_token`) are always present;
92
+ * consumer entries that collide with a builtin name throw at
93
+ * construction. Pass the result into `create_role_schema`'s optional
94
+ * `credential_types` parameter so each role's
95
+ * `required_credential_types` entries are validated against this set
96
+ * at construction time.
97
+ *
98
+ * @param consumer_types - optional consumer-declared credential-type set with optional metadata
99
+ * @returns `{CredentialType, credential_types}` — Zod schema and metadata map
100
+ *
101
+ * @throws Error if any `consumer_types` key fails the `CredentialTypeName` regex, collides with a builtin name, or appears more than once
102
+ *
103
+ * @example
104
+ * ```ts
105
+ * // simple — builtins only
106
+ * const {CredentialType, credential_types} = create_credential_type_schema();
107
+ *
108
+ * // with consumer extensions
109
+ * const {CredentialType} = create_credential_type_schema({
110
+ * sso_assertion: {description: 'OIDC SSO assertion bound to an IdP-asserted account.'},
111
+ * });
112
+ * ```
113
+ */
114
+ export declare const create_credential_type_schema: (consumer_types?: Record<string, CredentialTypeMeta>) => CredentialTypeSchemaResult;
115
+ //# sourceMappingURL=credential_type_schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential_type_schema.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/credential_type_schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,QAAgC,CAAC;AAExE,yDAAyD;AACzD,eAAO,MAAM,kBAAkB,aAK7B,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAIpE,uCAAuC;AACvC,eAAO,MAAM,uBAAuB,YAAY,CAAC;AAEjD;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,cAAc,CAAC;AAErD,yEAAyE;AACzE,eAAO,MAAM,4BAA4B,iBAAiB,CAAC;AAE3D,0DAA0D;AAC1D,eAAO,MAAM,wBAAwB,mDAI3B,CAAC;AAEX,kDAAkD;AAClD,eAAO,MAAM,qBAAqB;;;;EAAmC,CAAC;AACtE,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAE1E;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,4BAA4B,EAAE,WAAW,CAAC,MAAM,EAAE,kBAAkB,CAa/E,CAAC;AAEH,qFAAqF;AACrF,MAAM,WAAW,0BAA0B;IAC1C;;;;;;OAMG;IACH,cAAc,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAClC;;;OAGG;IACH,gBAAgB,EAAE,WAAW,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;CAC1D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,6BAA6B,GACzC,iBAAgB,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAM,KACrD,0BA2BF,CAAC"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Credential-type registry — how a request was authenticated.
3
+ *
4
+ * Three builtins: `session` (cookie-based), `api_token` (HTTP Bearer
5
+ * token), `daemon_token` (filesystem proof for the keeper account).
6
+ * Open-string registry on top so consumers can declare additional
7
+ * credential types (e.g. `'sso_assertion'`, `'agent_token'`) without an
8
+ * upstream release. `RoleSpec.required_credential_types` references
9
+ * entries from this registry; v1 keeps the field informative-only
10
+ * (consumed by `auth/middleware.ts` and the dispatcher). Mirrors the
11
+ * open-registry pattern used for `RoleName`, `ScopeKindName`,
12
+ * `GrantPathName`, and `AuditEventTypeName`.
13
+ *
14
+ * The Hono-side wire-validated `CredentialType` Zod enum (in
15
+ * `hono_context.ts`) is the closed-set narrow type middleware sets on
16
+ * the context; the constants below are the source of truth for those
17
+ * three string values. Future builtin credential types added here
18
+ * propagate to the wire enum by editing the import list.
19
+ *
20
+ * @module
21
+ */
22
+ import { z } from 'zod';
23
+ /**
24
+ * Letter (lowercase a-z) start and end (or single letter), with letters
25
+ * and underscores in between. Mirrors `RoleName`, `ScopeKindName`,
26
+ * `GrantPathName`. Rejects empty strings, leading or trailing
27
+ * underscores, uppercase, and digits.
28
+ */
29
+ export const CREDENTIAL_TYPE_NAME_REGEX = /^[a-z][a-z_]*[a-z]$|^[a-z]$/;
30
+ /** Zod schema for valid credential-type name strings. */
31
+ export const CredentialTypeName = z
32
+ .string()
33
+ .regex(CREDENTIAL_TYPE_NAME_REGEX, 'Credential-type names must be lowercase letters and underscores (a-z_), no leading/trailing underscore');
34
+ // Builtin credential types — provided by fuz_app, always available.
35
+ /** Cookie-based session credential. */
36
+ export const CREDENTIAL_TYPE_SESSION = 'session';
37
+ /**
38
+ * HTTP `Authorization: Bearer` API token credential. The wire literal
39
+ * `'api_token'` aligns with the `api_token` storage table name; the
40
+ * constant is named `_API_TOKEN` (not `_BEARER`) to keep wire and
41
+ * storage nomenclature in lockstep.
42
+ */
43
+ export const CREDENTIAL_TYPE_API_TOKEN = 'api_token';
44
+ /** Daemon-token credential — filesystem proof for the keeper account. */
45
+ export const CREDENTIAL_TYPE_DAEMON_TOKEN = 'daemon_token';
46
+ /** The builtin credential-type names as a const tuple. */
47
+ export const BUILTIN_CREDENTIAL_TYPES = [
48
+ CREDENTIAL_TYPE_SESSION,
49
+ CREDENTIAL_TYPE_API_TOKEN,
50
+ CREDENTIAL_TYPE_DAEMON_TOKEN,
51
+ ];
52
+ /** Zod enum for builtin credential types only. */
53
+ export const BuiltinCredentialType = z.enum(BUILTIN_CREDENTIAL_TYPES);
54
+ /**
55
+ * Builtin credential-type metadata. Not overridable by consumers.
56
+ *
57
+ * Typed `ReadonlyMap` for the contract — but JS Maps don't honor
58
+ * `Object.freeze` for `.set` / `.delete` / `.clear` (they mutate
59
+ * internal slots, not own properties), so freeze adds no runtime guard
60
+ * here. Read once at startup by `create_credential_type_schema`;
61
+ * runtime mutation has no effect on already-built schemas.
62
+ */
63
+ export const BUILTIN_CREDENTIAL_TYPE_META = new Map([
64
+ [
65
+ CREDENTIAL_TYPE_SESSION,
66
+ { description: 'Cookie-based session credential, signed and validated server-side.' },
67
+ ],
68
+ [
69
+ CREDENTIAL_TYPE_API_TOKEN,
70
+ { description: 'HTTP Authorization: Bearer API token credential, hashed at rest.' },
71
+ ],
72
+ [
73
+ CREDENTIAL_TYPE_DAEMON_TOKEN,
74
+ { description: 'Filesystem-proof daemon-token credential, scoped to the keeper account.' },
75
+ ],
76
+ ]);
77
+ /**
78
+ * Create a credential-type schema from the builtin set plus optional
79
+ * consumer-declared additions.
80
+ *
81
+ * Builtins (`session`, `api_token`, `daemon_token`) are always present;
82
+ * consumer entries that collide with a builtin name throw at
83
+ * construction. Pass the result into `create_role_schema`'s optional
84
+ * `credential_types` parameter so each role's
85
+ * `required_credential_types` entries are validated against this set
86
+ * at construction time.
87
+ *
88
+ * @param consumer_types - optional consumer-declared credential-type set with optional metadata
89
+ * @returns `{CredentialType, credential_types}` — Zod schema and metadata map
90
+ *
91
+ * @throws Error if any `consumer_types` key fails the `CredentialTypeName` regex, collides with a builtin name, or appears more than once
92
+ *
93
+ * @example
94
+ * ```ts
95
+ * // simple — builtins only
96
+ * const {CredentialType, credential_types} = create_credential_type_schema();
97
+ *
98
+ * // with consumer extensions
99
+ * const {CredentialType} = create_credential_type_schema({
100
+ * sso_assertion: {description: 'OIDC SSO assertion bound to an IdP-asserted account.'},
101
+ * });
102
+ * ```
103
+ */
104
+ export const create_credential_type_schema = (consumer_types = {}) => {
105
+ const consumer_names = Object.keys(consumer_types);
106
+ const seen = new Set();
107
+ for (const name of consumer_names) {
108
+ const parsed = CredentialTypeName.safeParse(name);
109
+ if (!parsed.success) {
110
+ throw new Error(`Invalid credential-type name "${name}": ${parsed.error.issues[0].message}`);
111
+ }
112
+ if (BUILTIN_CREDENTIAL_TYPE_META.has(name)) {
113
+ throw new Error(`Consumer credential-type "${name}" collides with builtin credential-type`);
114
+ }
115
+ if (seen.has(name)) {
116
+ throw new Error(`Duplicate credential-type name "${name}"`);
117
+ }
118
+ seen.add(name);
119
+ }
120
+ const all_names = [...BUILTIN_CREDENTIAL_TYPES, ...consumer_names];
121
+ const CredentialType = z.enum(all_names);
122
+ const credential_types = new Map(BUILTIN_CREDENTIAL_TYPE_META);
123
+ for (const name of consumer_names) {
124
+ credential_types.set(name, consumer_types[name]);
125
+ }
126
+ return { CredentialType, credential_types };
127
+ };
@@ -42,7 +42,7 @@ export declare const get_daemon_token_path: (runtime: Pick<EnvDeps, "env_get">,
42
42
  export declare const write_daemon_token: (runtime: DaemonTokenWriteDeps, token_path: string, token: string) => Promise<void>;
43
43
  /**
44
44
  * Resolve the keeper account ID by querying for the account with an active
45
- * keeper permit.
45
+ * keeper role_grant.
46
46
  *
47
47
  * There is exactly one keeper account (the bootstrap account). Runs once
48
48
  * at server startup — the result is cached in
@@ -14,7 +14,7 @@ import { write_file_atomic } from '../runtime/fs.js';
14
14
  import { get_app_dir } from '../cli/config.js';
15
15
  import { ACCOUNT_ID_KEY, AUTH_API_TOKEN_ID_KEY, CREDENTIAL_TYPE_KEY } from '../hono_context.js';
16
16
  import { ERROR_INVALID_DAEMON_TOKEN, ERROR_KEEPER_ACCOUNT_NOT_CONFIGURED, } from '../http/error_schemas.js';
17
- import { query_permit_find_account_id_for_role } from './permit_queries.js';
17
+ import { query_role_grant_find_account_id_for_role } from './role_grant_queries.js';
18
18
  import { ROLE_KEEPER } from './role_schema.js';
19
19
  import { DaemonToken, DAEMON_TOKEN_HEADER, generate_daemon_token, validate_daemon_token, } from './daemon_token.js';
20
20
  /** Default rotation interval in milliseconds (30 seconds). */
@@ -48,7 +48,7 @@ export const write_daemon_token = async (runtime, token_path, token) => {
48
48
  };
49
49
  /**
50
50
  * Resolve the keeper account ID by querying for the account with an active
51
- * keeper permit.
51
+ * keeper role_grant.
52
52
  *
53
53
  * There is exactly one keeper account (the bootstrap account). Runs once
54
54
  * at server startup — the result is cached in
@@ -62,7 +62,7 @@ export const write_daemon_token = async (runtime, token_path, token) => {
62
62
  * @returns the keeper account ID, or `null` if no keeper exists yet (pre-bootstrap)
63
63
  */
64
64
  export const resolve_keeper_account_id = async (deps) => {
65
- return query_permit_find_account_id_for_role(deps, ROLE_KEEPER);
65
+ return query_role_grant_find_account_id_for_role(deps, ROLE_KEEPER);
66
66
  };
67
67
  /**
68
68
  * Start daemon token rotation.
@@ -9,8 +9,8 @@
9
9
  export declare const ACCOUNT_SCHEMA = "\nCREATE TABLE IF NOT EXISTS account (\n id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n username TEXT UNIQUE NOT NULL,\n email TEXT,\n email_verified BOOLEAN NOT NULL DEFAULT false,\n password_hash TEXT NOT NULL,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n created_by UUID,\n updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n updated_by UUID\n)";
10
10
  export declare const ACTOR_SCHEMA = "\nCREATE TABLE IF NOT EXISTS actor (\n id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n account_id UUID NOT NULL REFERENCES account(id) ON DELETE CASCADE,\n name TEXT NOT NULL,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n updated_at TIMESTAMPTZ,\n updated_by UUID REFERENCES actor(id) ON DELETE SET NULL\n)";
11
11
  export declare const ACTOR_INDEX = "\nCREATE INDEX IF NOT EXISTS idx_actor_account ON actor(account_id)";
12
- export declare const PERMIT_SCHEMA = "\nCREATE TABLE IF NOT EXISTS permit (\n id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n actor_id UUID NOT NULL REFERENCES actor(id) ON DELETE CASCADE,\n role TEXT NOT NULL,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n expires_at TIMESTAMPTZ,\n revoked_at TIMESTAMPTZ,\n revoked_by UUID REFERENCES actor(id) ON DELETE SET NULL,\n granted_by UUID REFERENCES actor(id) ON DELETE SET NULL\n)";
13
- export declare const PERMIT_INDEXES: string[];
12
+ export declare const ROLE_GRANT_SCHEMA = "\nCREATE TABLE IF NOT EXISTS role_grant (\n id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n actor_id UUID NOT NULL REFERENCES actor(id) ON DELETE CASCADE,\n role TEXT NOT NULL,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n expires_at TIMESTAMPTZ,\n revoked_at TIMESTAMPTZ,\n revoked_by UUID REFERENCES actor(id) ON DELETE SET NULL,\n granted_by UUID REFERENCES actor(id) ON DELETE SET NULL\n)";
13
+ export declare const ROLE_GRANT_INDEXES: string[];
14
14
  export declare const AUTH_SESSION_SCHEMA = "\nCREATE TABLE IF NOT EXISTS auth_session (\n id TEXT PRIMARY KEY,\n account_id UUID NOT NULL REFERENCES account(id) ON DELETE CASCADE,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n expires_at TIMESTAMPTZ NOT NULL,\n last_seen_at TIMESTAMPTZ NOT NULL DEFAULT NOW()\n)";
15
15
  export declare const AUTH_SESSION_INDEXES: string[];
16
16
  export declare const API_TOKEN_SCHEMA = "\nCREATE TABLE IF NOT EXISTS api_token (\n id TEXT PRIMARY KEY,\n account_id UUID NOT NULL REFERENCES account(id) ON DELETE CASCADE,\n name TEXT NOT NULL,\n token_hash TEXT NOT NULL,\n expires_at TIMESTAMPTZ,\n last_used_at TIMESTAMPTZ,\n last_used_ip TEXT,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()\n)";
@@ -1 +1 @@
1
- {"version":3,"file":"ddl.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/ddl.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,eAAO,MAAM,cAAc,8WAWzB,CAAC;AAEH,eAAO,MAAM,YAAY,mUAQvB,CAAC;AAEH,eAAO,MAAM,WAAW,wEAC0C,CAAC;AAEnE,eAAO,MAAM,aAAa,uZAUxB,CAAC;AAEH,eAAO,MAAM,cAAc,UAI1B,CAAC;AAEF,eAAO,MAAM,mBAAmB,0RAO9B,CAAC;AAEH,eAAO,MAAM,oBAAoB,UAGhC,CAAC;AAEF,eAAO,MAAM,gBAAgB,iUAU3B,CAAC;AAEH,eAAO,MAAM,mBAAmB,4GACsE,CAAC;AAEvG,eAAO,MAAM,yBAAyB,6FACiD,CAAC;AAExF,eAAO,MAAM,eAAe,gFAC8C,CAAC;AAE3E,eAAO,MAAM,qBAAqB,wJAIhC,CAAC;AAEH,6FAA6F;AAC7F,eAAO,MAAM,mBAAmB,yHAGP,CAAC;AAE1B,eAAO,MAAM,aAAa,6ZAUxB,CAAC;AAEH,eAAO,MAAM,cAAc,UAI1B,CAAC;AAEF,eAAO,MAAM,mBAAmB,oMAM9B,CAAC;AAEH,eAAO,MAAM,iBAAiB,sEACkC,CAAC"}
1
+ {"version":3,"file":"ddl.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/ddl.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,eAAO,MAAM,cAAc,8WAWzB,CAAC;AAEH,eAAO,MAAM,YAAY,mUAQvB,CAAC;AAEH,eAAO,MAAM,WAAW,wEAC0C,CAAC;AAEnE,eAAO,MAAM,iBAAiB,2ZAU5B,CAAC;AAEH,eAAO,MAAM,kBAAkB,UAI9B,CAAC;AAEF,eAAO,MAAM,mBAAmB,0RAO9B,CAAC;AAEH,eAAO,MAAM,oBAAoB,UAGhC,CAAC;AAEF,eAAO,MAAM,gBAAgB,iUAU3B,CAAC;AAEH,eAAO,MAAM,mBAAmB,4GACsE,CAAC;AAEvG,eAAO,MAAM,yBAAyB,6FACiD,CAAC;AAExF,eAAO,MAAM,eAAe,gFAC8C,CAAC;AAE3E,eAAO,MAAM,qBAAqB,wJAIhC,CAAC;AAEH,6FAA6F;AAC7F,eAAO,MAAM,mBAAmB,yHAGP,CAAC;AAE1B,eAAO,MAAM,aAAa,6ZAUxB,CAAC;AAEH,eAAO,MAAM,cAAc,UAI1B,CAAC;AAEF,eAAO,MAAM,mBAAmB,oMAM9B,CAAC;AAEH,eAAO,MAAM,iBAAiB,sEACkC,CAAC"}
package/dist/auth/ddl.js CHANGED
@@ -29,8 +29,8 @@ CREATE TABLE IF NOT EXISTS actor (
29
29
  )`;
30
30
  export const ACTOR_INDEX = `
31
31
  CREATE INDEX IF NOT EXISTS idx_actor_account ON actor(account_id)`;
32
- export const PERMIT_SCHEMA = `
33
- CREATE TABLE IF NOT EXISTS permit (
32
+ export const ROLE_GRANT_SCHEMA = `
33
+ CREATE TABLE IF NOT EXISTS role_grant (
34
34
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
35
35
  actor_id UUID NOT NULL REFERENCES actor(id) ON DELETE CASCADE,
36
36
  role TEXT NOT NULL,
@@ -40,10 +40,10 @@ CREATE TABLE IF NOT EXISTS permit (
40
40
  revoked_by UUID REFERENCES actor(id) ON DELETE SET NULL,
41
41
  granted_by UUID REFERENCES actor(id) ON DELETE SET NULL
42
42
  )`;
43
- export const PERMIT_INDEXES = [
44
- `CREATE INDEX IF NOT EXISTS idx_permit_actor ON permit(actor_id)`,
45
- `CREATE UNIQUE INDEX IF NOT EXISTS permit_actor_role_active_unique
46
- ON permit (actor_id, role) WHERE revoked_at IS NULL`,
43
+ export const ROLE_GRANT_INDEXES = [
44
+ `CREATE INDEX IF NOT EXISTS idx_role_grant_actor ON role_grant(actor_id)`,
45
+ `CREATE UNIQUE INDEX IF NOT EXISTS role_grant_actor_role_active_unique
46
+ ON role_grant (actor_id, role) WHERE revoked_at IS NULL`,
47
47
  ];
48
48
  export const AUTH_SESSION_SCHEMA = `
49
49
  CREATE TABLE IF NOT EXISTS auth_session (
@@ -12,7 +12,7 @@ import type { Keyring } from './keyring.js';
12
12
  import type { PasswordHashDeps } from './password.js';
13
13
  import type { Db } from '../db/db.js';
14
14
  import type { StatResult } from '../runtime/deps.js';
15
- import type { AuditLogConfig, AuditLogEvent } from './audit_log_schema.js';
15
+ import type { AuditEmitter } from './audit_emitter.js';
16
16
  /**
17
17
  * Stateless capabilities bundle for fuz_app backends.
18
18
  *
@@ -35,24 +35,13 @@ export interface AppDeps {
35
35
  /** Structured logger instance. */
36
36
  log: Logger;
37
37
  /**
38
- * Called after each audit log INSERT succeeds.
39
- * Use to broadcast audit events via SSE. Flows automatically to all
40
- * route factories that receive `deps` or `RouteFactoryDeps`.
41
- * Defaults to a noop when not wired to SSE.
38
+ * Bound audit emitter. Closes over the pool, the `on_audit_event`
39
+ * subscriber chain, and the optional `AuditLogConfig`. Built once at
40
+ * backend assembly via `create_audit_emitter` so handlers can never
41
+ * accidentally write audits against the request transaction there
42
+ * is no pool slot on the handler context.
42
43
  */
43
- on_audit_event: (event: AuditLogEvent) => void;
44
- /**
45
- * Audit-log config for `audit_log_fire_and_forget` and `query_audit_log`.
46
- * Built once at startup via `create_audit_log_config({extra_events})` to
47
- * register consumer event types. Optional — defaults to
48
- * `BUILTIN_AUDIT_LOG_CONFIG` when absent.
49
- *
50
- * Threaded through `AppDeps` (instead of a per-call positional arg) so
51
- * consumer handlers cannot silently fall back to the builtin config by
52
- * forgetting to pass theirs — the deps bundle carries it everywhere
53
- * fuz_app emits an audit event.
54
- */
55
- audit_log_config?: AuditLogConfig;
44
+ audit: AuditEmitter;
56
45
  }
57
46
  /**
58
47
  * Capabilities for route spec factories.
@@ -61,18 +50,4 @@ export interface AppDeps {
61
50
  * via `RouteContext`, so factories don't capture a pool-level `Db`.
62
51
  */
63
52
  export type RouteFactoryDeps = Omit<AppDeps, 'db'>;
64
- /**
65
- * Capabilities required by anything that emits audit events.
66
- *
67
- * The slice every audit-emitting site needs: `log` for sibling failure
68
- * reporting, `on_audit_event` for SSE/WS fan-out, and the optional
69
- * `audit_log_config` for consumer-extended event-type validation. Used
70
- * by `audit_log_fire_and_forget` / `emit_permit_target_event` (the
71
- * primitives) and by every action-factory deps type in `auth/`
72
- * (`AdminActionDeps`, `AccountActionDeps`, `PermitOfferActionDeps`,
73
- * `SelfServiceRoleActionDeps`) that runs through them. Lifted here so
74
- * the five factory deps stop spelling the same `Pick<RouteFactoryDeps,
75
- * 'log' | 'on_audit_event' | 'audit_log_config'>` independently.
76
- */
77
- export type AuditEmitDeps = Pick<AppDeps, 'log' | 'on_audit_event' | 'audit_log_config'>;
78
53
  //# sourceMappingURL=deps.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"deps.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/deps.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAEpD,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AAC1C,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,aAAa,CAAC;AACpC,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAC,cAAc,EAAE,aAAa,EAAC,MAAM,uBAAuB,CAAC;AAEzE;;;;;GAKG;AACH,MAAM,WAAW,OAAO;IACvB,+DAA+D;IAC/D,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IACnD,2BAA2B;IAC3B,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAClD,qBAAqB;IACrB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,0CAA0C;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,6EAA6E;IAC7E,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,yBAAyB;IACzB,EAAE,EAAE,EAAE,CAAC;IACP,kCAAkC;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;OAKG;IACH,cAAc,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC/C;;;;;;;;;;OAUG;IACH,gBAAgB,CAAC,EAAE,cAAc,CAAC;CAClC;AAED;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AAEnD;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,KAAK,GAAG,gBAAgB,GAAG,kBAAkB,CAAC,CAAC"}
1
+ {"version":3,"file":"deps.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/deps.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAEpD,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AAC1C,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,aAAa,CAAC;AACpC,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,oBAAoB,CAAC;AAErD;;;;;GAKG;AACH,MAAM,WAAW,OAAO;IACvB,+DAA+D;IAC/D,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IACnD,2BAA2B;IAC3B,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAClD,qBAAqB;IACrB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,0CAA0C;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,6EAA6E;IAC7E,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,yBAAyB;IACzB,EAAE,EAAE,EAAE,CAAC;IACP,kCAAkC;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;OAMG;IACH,KAAK,EAAE,YAAY,CAAC;CACpB;AAED;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC"}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Grant-path registry — the surfaces through which a role can be
3
+ * granted to an actor.
4
+ *
5
+ * Four builtins:
6
+ *
7
+ * - `admin` — granted by an admin via `role_grant_offer_create` (subject to
8
+ * the consumer's `authorize` callback) or admin-side direct grant.
9
+ * - `self_service` — toggled by the holder themselves via
10
+ * `self_service_role_set` (allowlisted by `eligible_roles`).
11
+ * - `system` — granted by system code paths (signup, automation, etc.)
12
+ * that don't fit either of the above.
13
+ * - `bootstrap` — granted exactly once during the bootstrap flow
14
+ * (`keeper`, `admin` on a fresh install).
15
+ *
16
+ * Open registry on top so consumers can declare additional paths
17
+ * (e.g. `'invite_only'`, `'sso_assertion'`) without an upstream release.
18
+ * `RoleSpec.grant_paths` references entries from this registry; the
19
+ * default for `admin_actions.grantable_roles` is `grant_paths.includes('admin')`,
20
+ * the default for `self_service_role_actions` eligibility is
21
+ * `grant_paths.includes('self_service')`. Mirrors the open-registry
22
+ * pattern used for `RoleName`, `ScopeKindName`, `CredentialTypeName`,
23
+ * and `AuditEventTypeName`.
24
+ *
25
+ * @module
26
+ */
27
+ import { z } from 'zod';
28
+ /**
29
+ * Letter (lowercase a-z) start and end (or single letter), with letters
30
+ * and underscores in between. Mirrors `RoleName`, `ScopeKindName`,
31
+ * `CredentialTypeName`. Rejects empty strings, leading or trailing
32
+ * underscores, uppercase, and digits.
33
+ */
34
+ export declare const GRANT_PATH_NAME_REGEX: RegExp;
35
+ /** Zod schema for valid grant-path name strings. */
36
+ export declare const GrantPathName: z.ZodString;
37
+ export type GrantPathName = z.infer<typeof GrantPathName>;
38
+ /** Admin-mediated grant — `role_grant_offer_create` plus admin-direct flows. */
39
+ export declare const GRANT_PATH_ADMIN = "admin";
40
+ /** Self-service grant — caller toggles their own role_grant via `self_service_role_set`. */
41
+ export declare const GRANT_PATH_SELF_SERVICE = "self_service";
42
+ /** System-mediated grant — signup hooks, automation, internal service flows. */
43
+ export declare const GRANT_PATH_SYSTEM = "system";
44
+ /** Bootstrap grant — one-shot flow during the keep's first-run bootstrap. */
45
+ export declare const GRANT_PATH_BOOTSTRAP = "bootstrap";
46
+ /** The builtin grant-path names as a const tuple. */
47
+ export declare const BUILTIN_GRANT_PATHS: readonly ["admin", "self_service", "system", "bootstrap"];
48
+ /** Zod enum for builtin grant paths only. */
49
+ export declare const BuiltinGrantPath: z.ZodEnum<{
50
+ admin: "admin";
51
+ self_service: "self_service";
52
+ system: "system";
53
+ bootstrap: "bootstrap";
54
+ }>;
55
+ export type BuiltinGrantPath = z.infer<typeof BuiltinGrantPath>;
56
+ /**
57
+ * Per-grant-path metadata. `description` is admin-UI-facing copy
58
+ * (mirrors `RoleSpec.description` and `ScopeKindMeta.description`).
59
+ * Open shape so v2 can extend without a breaking change.
60
+ */
61
+ export interface GrantPathMeta {
62
+ description?: string;
63
+ }
64
+ /**
65
+ * Builtin grant-path metadata. Not overridable by consumers.
66
+ *
67
+ * Typed `ReadonlyMap` for the contract — but JS Maps don't honor
68
+ * `Object.freeze` for `.set` / `.delete` / `.clear` (they mutate
69
+ * internal slots, not own properties), so freeze adds no runtime guard
70
+ * here. Read once at startup by `create_grant_path_schema`; runtime
71
+ * mutation has no effect on already-built schemas.
72
+ */
73
+ export declare const BUILTIN_GRANT_PATH_META: ReadonlyMap<string, GrantPathMeta>;
74
+ /** The result of `create_grant_path_schema` — a Zod schema and metadata map. */
75
+ export interface GrantPathSchemaResult {
76
+ /**
77
+ * Zod schema that validates grant-path name strings against the
78
+ * registered set (builtins + consumer-declared). Use at I/O
79
+ * boundaries (admin UIs, codegen) and as the construction-time check
80
+ * inside `create_role_schema` for every `RoleSpec.grant_paths`
81
+ * entry.
82
+ */
83
+ GrantPath: z.ZodType<string>;
84
+ /**
85
+ * Map of every registered grant-path to its metadata. Keyed by
86
+ * name. Read at startup by admin / codegen surfaces.
87
+ */
88
+ grant_paths: ReadonlyMap<string, GrantPathMeta>;
89
+ }
90
+ /**
91
+ * Create a grant-path schema from the builtin set plus optional
92
+ * consumer-declared additions.
93
+ *
94
+ * Builtins (`admin`, `self_service`, `system`, `bootstrap`) are always
95
+ * present; consumer entries that collide with a builtin name throw at
96
+ * construction. Pass the result into `create_role_schema`'s optional
97
+ * `grant_paths` parameter so each role's `grant_paths` entries are
98
+ * validated against this set at construction time.
99
+ *
100
+ * @param consumer_paths - optional consumer-declared grant-path set with optional metadata
101
+ * @returns `{GrantPath, grant_paths}` — Zod schema and metadata map
102
+ *
103
+ * @throws Error if any `consumer_paths` key fails the `GrantPathName` regex, collides with a builtin name, or appears more than once
104
+ *
105
+ * @example
106
+ * ```ts
107
+ * // simple — builtins only
108
+ * const {GrantPath, grant_paths} = create_grant_path_schema();
109
+ *
110
+ * // with consumer extensions
111
+ * const {GrantPath} = create_grant_path_schema({
112
+ * invite_only: {description: 'Granted by claiming a consumer-issued invite.'},
113
+ * });
114
+ * ```
115
+ */
116
+ export declare const create_grant_path_schema: (consumer_paths?: Record<string, GrantPathMeta>) => GrantPathSchemaResult;
117
+ //# sourceMappingURL=grant_path_schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grant_path_schema.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/grant_path_schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,QAAgC,CAAC;AAEnE,oDAAoD;AACpD,eAAO,MAAM,aAAa,aAKxB,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAI1D,gFAAgF;AAChF,eAAO,MAAM,gBAAgB,UAAU,CAAC;AAExC,4FAA4F;AAC5F,eAAO,MAAM,uBAAuB,iBAAiB,CAAC;AAEtD,gFAAgF;AAChF,eAAO,MAAM,iBAAiB,WAAW,CAAC;AAE1C,6EAA6E;AAC7E,eAAO,MAAM,oBAAoB,cAAc,CAAC;AAEhD,qDAAqD;AACrD,eAAO,MAAM,mBAAmB,2DAKtB,CAAC;AAEX,6CAA6C;AAC7C,eAAO,MAAM,gBAAgB;;;;;EAA8B,CAAC;AAC5D,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEhE;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAuBrE,CAAC;AAEH,gFAAgF;AAChF,MAAM,WAAW,qBAAqB;IACrC;;;;;;OAMG;IACH,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7B;;;OAGG;IACH,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;CAChD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,wBAAwB,GACpC,iBAAgB,MAAM,CAAC,MAAM,EAAE,aAAa,CAAM,KAChD,qBA2BF,CAAC"}