@fuzdev/fuz_app 0.54.0 → 0.56.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (348) hide show
  1. package/dist/actions/CLAUDE.md +214 -103
  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 +32 -0
  6. package/dist/actions/action_codegen.d.ts.map +1 -1
  7. package/dist/actions/action_codegen.js +35 -15
  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 +141 -22
  11. package/dist/actions/action_rpc.d.ts.map +1 -1
  12. package/dist/actions/action_rpc.js +106 -187
  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 +46 -40
  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 +15 -10
  34. package/dist/actions/register_ws_endpoint.d.ts.map +1 -1
  35. package/dist/actions/register_ws_endpoint.js +54 -7
  36. package/dist/actions/transports.d.ts.map +1 -1
  37. package/dist/actions/transports.js +0 -4
  38. package/dist/actions/transports_ws_auth_guard.d.ts +1 -1
  39. package/dist/actions/transports_ws_auth_guard.js +1 -1
  40. package/dist/actions/transports_ws_backend.d.ts +1 -1
  41. package/dist/actions/transports_ws_backend.js +1 -1
  42. package/dist/auth/CLAUDE.md +794 -410
  43. package/dist/auth/account_action_specs.d.ts +28 -7
  44. package/dist/auth/account_action_specs.d.ts.map +1 -1
  45. package/dist/auth/account_action_specs.js +7 -7
  46. package/dist/auth/account_actions.d.ts +7 -13
  47. package/dist/auth/account_actions.d.ts.map +1 -1
  48. package/dist/auth/account_actions.js +26 -35
  49. package/dist/auth/account_queries.d.ts +52 -16
  50. package/dist/auth/account_queries.d.ts.map +1 -1
  51. package/dist/auth/account_queries.js +87 -38
  52. package/dist/auth/account_routes.d.ts +9 -11
  53. package/dist/auth/account_routes.d.ts.map +1 -1
  54. package/dist/auth/account_routes.js +118 -46
  55. package/dist/auth/account_schema.d.ts +46 -35
  56. package/dist/auth/account_schema.d.ts.map +1 -1
  57. package/dist/auth/account_schema.js +21 -28
  58. package/dist/auth/admin_action_specs.d.ts +100 -32
  59. package/dist/auth/admin_action_specs.d.ts.map +1 -1
  60. package/dist/auth/admin_action_specs.js +64 -33
  61. package/dist/auth/admin_actions.d.ts +13 -19
  62. package/dist/auth/admin_actions.d.ts.map +1 -1
  63. package/dist/auth/admin_actions.js +37 -41
  64. package/dist/auth/audit_emitter.d.ts +160 -0
  65. package/dist/auth/audit_emitter.d.ts.map +1 -0
  66. package/dist/auth/audit_emitter.js +83 -0
  67. package/dist/auth/audit_log_queries.d.ts +17 -48
  68. package/dist/auth/audit_log_queries.d.ts.map +1 -1
  69. package/dist/auth/audit_log_queries.js +20 -56
  70. package/dist/auth/audit_log_routes.d.ts +1 -1
  71. package/dist/auth/audit_log_routes.d.ts.map +1 -1
  72. package/dist/auth/audit_log_routes.js +7 -3
  73. package/dist/auth/audit_log_schema.d.ts +92 -32
  74. package/dist/auth/audit_log_schema.d.ts.map +1 -1
  75. package/dist/auth/audit_log_schema.js +75 -46
  76. package/dist/auth/auth_guard_resolver.d.ts +44 -0
  77. package/dist/auth/auth_guard_resolver.d.ts.map +1 -0
  78. package/dist/auth/auth_guard_resolver.js +56 -0
  79. package/dist/auth/bearer_auth.d.ts +9 -7
  80. package/dist/auth/bearer_auth.d.ts.map +1 -1
  81. package/dist/auth/bearer_auth.js +13 -21
  82. package/dist/auth/bootstrap_account.d.ts +7 -7
  83. package/dist/auth/bootstrap_account.d.ts.map +1 -1
  84. package/dist/auth/bootstrap_account.js +7 -7
  85. package/dist/auth/bootstrap_routes.d.ts.map +1 -1
  86. package/dist/auth/bootstrap_routes.js +11 -10
  87. package/dist/auth/cleanup.d.ts +20 -26
  88. package/dist/auth/cleanup.d.ts.map +1 -1
  89. package/dist/auth/cleanup.js +33 -42
  90. package/dist/auth/credential_type_schema.d.ts +115 -0
  91. package/dist/auth/credential_type_schema.d.ts.map +1 -0
  92. package/dist/auth/credential_type_schema.js +127 -0
  93. package/dist/auth/daemon_token_middleware.d.ts +23 -11
  94. package/dist/auth/daemon_token_middleware.d.ts.map +1 -1
  95. package/dist/auth/daemon_token_middleware.js +28 -22
  96. package/dist/auth/ddl.d.ts +2 -2
  97. package/dist/auth/ddl.d.ts.map +1 -1
  98. package/dist/auth/ddl.js +6 -6
  99. package/dist/auth/deps.d.ts +7 -18
  100. package/dist/auth/deps.d.ts.map +1 -1
  101. package/dist/auth/grant_path_schema.d.ts +117 -0
  102. package/dist/auth/grant_path_schema.d.ts.map +1 -0
  103. package/dist/auth/grant_path_schema.js +137 -0
  104. package/dist/auth/invite_queries.d.ts +12 -1
  105. package/dist/auth/invite_queries.d.ts.map +1 -1
  106. package/dist/auth/invite_queries.js +12 -1
  107. package/dist/auth/invite_schema.d.ts +1 -1
  108. package/dist/auth/invite_schema.d.ts.map +1 -1
  109. package/dist/auth/invite_schema.js +1 -1
  110. package/dist/auth/middleware.d.ts.map +1 -1
  111. package/dist/auth/middleware.js +9 -4
  112. package/dist/auth/migrations.d.ts +37 -14
  113. package/dist/auth/migrations.d.ts.map +1 -1
  114. package/dist/auth/migrations.js +79 -32
  115. package/dist/auth/request_context.d.ts +331 -61
  116. package/dist/auth/request_context.d.ts.map +1 -1
  117. package/dist/auth/request_context.js +378 -95
  118. package/dist/auth/{permit_offer_action_specs.d.ts → role_grant_offer_action_specs.d.ts} +163 -94
  119. package/dist/auth/role_grant_offer_action_specs.d.ts.map +1 -0
  120. package/dist/auth/role_grant_offer_action_specs.js +262 -0
  121. package/dist/auth/role_grant_offer_actions.d.ts +104 -0
  122. package/dist/auth/role_grant_offer_actions.d.ts.map +1 -0
  123. package/dist/auth/role_grant_offer_actions.js +473 -0
  124. package/dist/auth/{permit_offer_notifications.d.ts → role_grant_offer_notifications.d.ts} +90 -70
  125. package/dist/auth/role_grant_offer_notifications.d.ts.map +1 -0
  126. package/dist/auth/role_grant_offer_notifications.js +182 -0
  127. package/dist/auth/role_grant_offer_queries.d.ts +242 -0
  128. package/dist/auth/role_grant_offer_queries.d.ts.map +1 -0
  129. package/dist/auth/role_grant_offer_queries.js +533 -0
  130. package/dist/auth/role_grant_offer_schema.d.ts +150 -0
  131. package/dist/auth/role_grant_offer_schema.d.ts.map +1 -0
  132. package/dist/auth/{permit_offer_schema.js → role_grant_offer_schema.js} +60 -36
  133. package/dist/auth/role_grant_queries.d.ts +231 -0
  134. package/dist/auth/role_grant_queries.d.ts.map +1 -0
  135. package/dist/auth/role_grant_queries.js +320 -0
  136. package/dist/auth/role_schema.d.ts +150 -40
  137. package/dist/auth/role_schema.d.ts.map +1 -1
  138. package/dist/auth/role_schema.js +144 -45
  139. package/dist/auth/scope_kind_schema.d.ts +96 -0
  140. package/dist/auth/scope_kind_schema.d.ts.map +1 -0
  141. package/dist/auth/scope_kind_schema.js +94 -0
  142. package/dist/auth/self_service_role_action_specs.d.ts +6 -1
  143. package/dist/auth/self_service_role_action_specs.d.ts.map +1 -1
  144. package/dist/auth/self_service_role_action_specs.js +3 -1
  145. package/dist/auth/self_service_role_actions.d.ts +34 -27
  146. package/dist/auth/self_service_role_actions.d.ts.map +1 -1
  147. package/dist/auth/self_service_role_actions.js +68 -48
  148. package/dist/auth/session_cookie.d.ts +43 -6
  149. package/dist/auth/session_cookie.d.ts.map +1 -1
  150. package/dist/auth/session_cookie.js +31 -5
  151. package/dist/auth/session_middleware.d.ts +37 -3
  152. package/dist/auth/session_middleware.d.ts.map +1 -1
  153. package/dist/auth/session_middleware.js +33 -7
  154. package/dist/auth/signup_routes.d.ts.map +1 -1
  155. package/dist/auth/signup_routes.js +48 -19
  156. package/dist/auth/standard_action_specs.d.ts +2 -2
  157. package/dist/auth/standard_action_specs.js +4 -4
  158. package/dist/auth/standard_rpc_actions.d.ts +23 -19
  159. package/dist/auth/standard_rpc_actions.d.ts.map +1 -1
  160. package/dist/auth/standard_rpc_actions.js +12 -12
  161. package/dist/db/migrate.d.ts +12 -8
  162. package/dist/db/migrate.d.ts.map +1 -1
  163. package/dist/db/migrate.js +10 -7
  164. package/dist/dev/setup.d.ts +2 -2
  165. package/dist/dev/setup.d.ts.map +1 -1
  166. package/dist/dev/setup.js +9 -7
  167. package/dist/env/load.d.ts +1 -1
  168. package/dist/env/load.js +1 -1
  169. package/dist/hono_context.d.ts +64 -5
  170. package/dist/hono_context.d.ts.map +1 -1
  171. package/dist/hono_context.js +38 -2
  172. package/dist/http/CLAUDE.md +264 -87
  173. package/dist/http/auth_shape.d.ts +191 -0
  174. package/dist/http/auth_shape.d.ts.map +1 -0
  175. package/dist/http/auth_shape.js +237 -0
  176. package/dist/http/common_routes.js +3 -3
  177. package/dist/http/db_routes.d.ts +4 -0
  178. package/dist/http/db_routes.d.ts.map +1 -1
  179. package/dist/http/db_routes.js +44 -7
  180. package/dist/http/error_schemas.d.ts +132 -19
  181. package/dist/http/error_schemas.d.ts.map +1 -1
  182. package/dist/http/error_schemas.js +132 -40
  183. package/dist/http/jsonrpc_errors.d.ts +27 -2
  184. package/dist/http/jsonrpc_errors.d.ts.map +1 -1
  185. package/dist/http/jsonrpc_errors.js +26 -2
  186. package/dist/http/pending_effects.d.ts +71 -18
  187. package/dist/http/pending_effects.d.ts.map +1 -1
  188. package/dist/http/pending_effects.js +87 -18
  189. package/dist/http/proxy.d.ts +52 -5
  190. package/dist/http/proxy.d.ts.map +1 -1
  191. package/dist/http/proxy.js +92 -14
  192. package/dist/http/route_spec.d.ts +113 -41
  193. package/dist/http/route_spec.d.ts.map +1 -1
  194. package/dist/http/route_spec.js +130 -52
  195. package/dist/http/schema_helpers.d.ts +3 -2
  196. package/dist/http/schema_helpers.d.ts.map +1 -1
  197. package/dist/http/schema_helpers.js +9 -2
  198. package/dist/http/surface.d.ts +2 -1
  199. package/dist/http/surface.d.ts.map +1 -1
  200. package/dist/http/surface.js +1 -2
  201. package/dist/http/surface_query.d.ts +39 -35
  202. package/dist/http/surface_query.d.ts.map +1 -1
  203. package/dist/http/surface_query.js +79 -36
  204. package/dist/primitive_schemas.d.ts +39 -0
  205. package/dist/primitive_schemas.d.ts.map +1 -0
  206. package/dist/primitive_schemas.js +40 -0
  207. package/dist/realtime/sse_auth_guard.d.ts +5 -5
  208. package/dist/realtime/sse_auth_guard.js +9 -9
  209. package/dist/runtime/mock.d.ts +1 -1
  210. package/dist/runtime/mock.js +1 -1
  211. package/dist/server/app_backend.d.ts +14 -11
  212. package/dist/server/app_backend.d.ts.map +1 -1
  213. package/dist/server/app_backend.js +12 -8
  214. package/dist/server/app_server.d.ts +7 -7
  215. package/dist/server/app_server.d.ts.map +1 -1
  216. package/dist/server/app_server.js +36 -31
  217. package/dist/server/validate_nginx.d.ts +1 -1
  218. package/dist/server/validate_nginx.js +1 -1
  219. package/dist/testing/CLAUDE.md +73 -55
  220. package/dist/testing/admin_integration.d.ts +5 -6
  221. package/dist/testing/admin_integration.d.ts.map +1 -1
  222. package/dist/testing/admin_integration.js +100 -96
  223. package/dist/testing/adversarial_headers.js +1 -1
  224. package/dist/testing/app_server.d.ts +11 -14
  225. package/dist/testing/app_server.d.ts.map +1 -1
  226. package/dist/testing/app_server.js +18 -17
  227. package/dist/testing/assertions.d.ts.map +1 -1
  228. package/dist/testing/assertions.js +2 -1
  229. package/dist/testing/attack_surface.d.ts.map +1 -1
  230. package/dist/testing/attack_surface.js +15 -9
  231. package/dist/testing/audit_completeness.d.ts +2 -2
  232. package/dist/testing/audit_completeness.d.ts.map +1 -1
  233. package/dist/testing/audit_completeness.js +53 -39
  234. package/dist/testing/auth_apps.d.ts +5 -4
  235. package/dist/testing/auth_apps.d.ts.map +1 -1
  236. package/dist/testing/auth_apps.js +28 -22
  237. package/dist/testing/data_exposure.d.ts.map +1 -1
  238. package/dist/testing/data_exposure.js +5 -5
  239. package/dist/testing/db.d.ts +1 -1
  240. package/dist/testing/db.d.ts.map +1 -1
  241. package/dist/testing/db.js +4 -4
  242. package/dist/testing/db_entities.d.ts +22 -0
  243. package/dist/testing/db_entities.d.ts.map +1 -0
  244. package/dist/testing/db_entities.js +28 -0
  245. package/dist/testing/entities.d.ts +10 -8
  246. package/dist/testing/entities.d.ts.map +1 -1
  247. package/dist/testing/entities.js +22 -18
  248. package/dist/testing/integration.d.ts.map +1 -1
  249. package/dist/testing/integration.js +13 -14
  250. package/dist/testing/integration_helpers.d.ts +8 -6
  251. package/dist/testing/integration_helpers.d.ts.map +1 -1
  252. package/dist/testing/integration_helpers.js +29 -23
  253. package/dist/testing/middleware.d.ts +15 -11
  254. package/dist/testing/middleware.d.ts.map +1 -1
  255. package/dist/testing/middleware.js +75 -32
  256. package/dist/testing/rpc_attack_surface.d.ts.map +1 -1
  257. package/dist/testing/rpc_attack_surface.js +40 -24
  258. package/dist/testing/rpc_helpers.d.ts.map +1 -1
  259. package/dist/testing/rpc_helpers.js +3 -1
  260. package/dist/testing/rpc_round_trip.d.ts +1 -1
  261. package/dist/testing/rpc_round_trip.d.ts.map +1 -1
  262. package/dist/testing/rpc_round_trip.js +14 -13
  263. package/dist/testing/sse_round_trip.d.ts +3 -4
  264. package/dist/testing/sse_round_trip.d.ts.map +1 -1
  265. package/dist/testing/sse_round_trip.js +7 -11
  266. package/dist/testing/standard.d.ts +1 -1
  267. package/dist/testing/stubs.d.ts +25 -0
  268. package/dist/testing/stubs.d.ts.map +1 -1
  269. package/dist/testing/stubs.js +43 -2
  270. package/dist/testing/surface_invariants.d.ts +2 -2
  271. package/dist/testing/ws_round_trip.d.ts +12 -13
  272. package/dist/testing/ws_round_trip.d.ts.map +1 -1
  273. package/dist/testing/ws_round_trip.js +24 -12
  274. package/dist/ui/AdminAccounts.svelte +23 -20
  275. package/dist/ui/AdminOverview.svelte +15 -13
  276. package/dist/ui/AdminOverview.svelte.d.ts.map +1 -1
  277. package/dist/ui/{AdminPermitHistory.svelte → AdminRoleGrantHistory.svelte} +12 -12
  278. package/dist/ui/AdminRoleGrantHistory.svelte.d.ts +4 -0
  279. package/dist/ui/AdminRoleGrantHistory.svelte.d.ts.map +1 -0
  280. package/dist/ui/BootstrapForm.svelte +1 -1
  281. package/dist/ui/CLAUDE.md +65 -59
  282. package/dist/ui/{PermitOfferForm.svelte → RoleGrantOfferForm.svelte} +37 -22
  283. package/dist/ui/RoleGrantOfferForm.svelte.d.ts +20 -0
  284. package/dist/ui/RoleGrantOfferForm.svelte.d.ts.map +1 -0
  285. package/dist/ui/{PermitOfferHistory.svelte → RoleGrantOfferHistory.svelte} +12 -12
  286. package/dist/ui/{PermitOfferHistory.svelte.d.ts → RoleGrantOfferHistory.svelte.d.ts} +4 -4
  287. package/dist/ui/RoleGrantOfferHistory.svelte.d.ts.map +1 -0
  288. package/dist/ui/{PermitOfferInbox.svelte → RoleGrantOfferInbox.svelte} +14 -14
  289. package/dist/ui/{PermitOfferInbox.svelte.d.ts → RoleGrantOfferInbox.svelte.d.ts} +4 -4
  290. package/dist/ui/RoleGrantOfferInbox.svelte.d.ts.map +1 -0
  291. package/dist/ui/SignupForm.svelte +1 -1
  292. package/dist/ui/SurfaceExplorer.svelte +35 -15
  293. package/dist/ui/SurfaceExplorer.svelte.d.ts.map +1 -1
  294. package/dist/ui/account_sessions_state.svelte.d.ts +2 -3
  295. package/dist/ui/account_sessions_state.svelte.d.ts.map +1 -1
  296. package/dist/ui/account_sessions_state.svelte.js +2 -3
  297. package/dist/ui/admin_accounts_state.svelte.d.ts +25 -18
  298. package/dist/ui/admin_accounts_state.svelte.d.ts.map +1 -1
  299. package/dist/ui/admin_accounts_state.svelte.js +28 -17
  300. package/dist/ui/admin_rpc_adapters.d.ts +20 -20
  301. package/dist/ui/admin_rpc_adapters.d.ts.map +1 -1
  302. package/dist/ui/admin_rpc_adapters.js +17 -17
  303. package/dist/ui/admin_sessions_state.svelte.d.ts +2 -2
  304. package/dist/ui/admin_sessions_state.svelte.js +2 -2
  305. package/dist/ui/audit_log_state.svelte.d.ts +7 -7
  306. package/dist/ui/audit_log_state.svelte.d.ts.map +1 -1
  307. package/dist/ui/audit_log_state.svelte.js +6 -6
  308. package/dist/ui/auth_state.svelte.d.ts +3 -3
  309. package/dist/ui/auth_state.svelte.d.ts.map +1 -1
  310. package/dist/ui/auth_state.svelte.js +6 -6
  311. package/dist/ui/format_scope.d.ts +2 -2
  312. package/dist/ui/format_scope.js +2 -2
  313. package/dist/ui/{permit_offers_state.svelte.d.ts → role_grant_offers_state.svelte.d.ts} +39 -31
  314. package/dist/ui/role_grant_offers_state.svelte.d.ts.map +1 -0
  315. package/dist/ui/{permit_offers_state.svelte.js → role_grant_offers_state.svelte.js} +25 -19
  316. package/dist/ui/ui_format.js +2 -2
  317. package/package.json +3 -3
  318. package/dist/auth/permit_offer_action_specs.d.ts.map +0 -1
  319. package/dist/auth/permit_offer_action_specs.js +0 -227
  320. package/dist/auth/permit_offer_actions.d.ts +0 -110
  321. package/dist/auth/permit_offer_actions.d.ts.map +0 -1
  322. package/dist/auth/permit_offer_actions.js +0 -452
  323. package/dist/auth/permit_offer_notifications.d.ts.map +0 -1
  324. package/dist/auth/permit_offer_notifications.js +0 -182
  325. package/dist/auth/permit_offer_queries.d.ts +0 -183
  326. package/dist/auth/permit_offer_queries.d.ts.map +0 -1
  327. package/dist/auth/permit_offer_queries.js +0 -408
  328. package/dist/auth/permit_offer_schema.d.ts +0 -103
  329. package/dist/auth/permit_offer_schema.d.ts.map +0 -1
  330. package/dist/auth/permit_queries.d.ts +0 -210
  331. package/dist/auth/permit_queries.d.ts.map +0 -1
  332. package/dist/auth/permit_queries.js +0 -294
  333. package/dist/auth/require_keeper.d.ts +0 -20
  334. package/dist/auth/require_keeper.d.ts.map +0 -1
  335. package/dist/auth/require_keeper.js +0 -35
  336. package/dist/auth/route_guards.d.ts +0 -21
  337. package/dist/auth/route_guards.d.ts.map +0 -1
  338. package/dist/auth/route_guards.js +0 -32
  339. package/dist/auth/session_lifecycle.d.ts +0 -37
  340. package/dist/auth/session_lifecycle.d.ts.map +0 -1
  341. package/dist/auth/session_lifecycle.js +0 -29
  342. package/dist/ui/AdminPermitHistory.svelte.d.ts +0 -4
  343. package/dist/ui/AdminPermitHistory.svelte.d.ts.map +0 -1
  344. package/dist/ui/PermitOfferForm.svelte.d.ts +0 -14
  345. package/dist/ui/PermitOfferForm.svelte.d.ts.map +0 -1
  346. package/dist/ui/PermitOfferHistory.svelte.d.ts.map +0 -1
  347. package/dist/ui/PermitOfferInbox.svelte.d.ts.map +0 -1
  348. package/dist/ui/permit_offers_state.svelte.d.ts.map +0 -1
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Bound audit-emit capability.
3
+ *
4
+ * `AuditEmitter` closes over the pool-level `Db`, the `on_audit_event`
5
+ * subscriber chain, and the optional `AuditLogConfig` at backend-assembly
6
+ * time. Consumers reach for `deps.audit.emit(ctx, input)` and never see the
7
+ * pool — handlers cannot accidentally emit an audit event against the
8
+ * request's transactional `db` (which would be rolled back with the parent
9
+ * on a handler throw).
10
+ *
11
+ * Four methods cover every fan-out shape the auth domain needs:
12
+ *
13
+ * - `emit(ctx, input)` — fire-and-forget pool write. Pushes the in-flight
14
+ * promise onto `ctx.pending_effects` for post-response flushing. Errors are
15
+ * logged, never thrown. Returns `void` so callers don't pile up `void`
16
+ * keywords or accidentally `await` something whose handle is already in
17
+ * `pending_effects`.
18
+ * - `emit_role_grant_target(ctx, auth, input)` — wrapper that lifts the
19
+ * `actor_id` / `account_id` / `ip` boilerplate every role-grant-shape audit
20
+ * site repeated. Delegates to `emit`.
21
+ * - `emit_pool(input)` — awaitable pool write for code paths without a
22
+ * `pending_effects` queue (cleanup sweeps, ad-hoc maintenance scripts).
23
+ * Same write-then-notify semantics as `emit`, just synchronous-with-await.
24
+ * - `notify(event)` — fan out an already-written audit row (e.g. rows
25
+ * returned by `query_accept_offer` that were inserted in-transaction by
26
+ * the query layer). Runs every listener on the chain; per-listener throws
27
+ * are isolated.
28
+ *
29
+ * The chain is mutable so server assembly can append additional listeners
30
+ * (e.g. the audit-log SSE registry composed by `create_app_server`) after
31
+ * the backend is built but before the first request runs.
32
+ *
33
+ * @module
34
+ */
35
+ import type { Logger } from '@fuzdev/fuz_util/log.js';
36
+ import type { Uuid } from '@fuzdev/fuz_util/id.js';
37
+ import type { Db } from '../db/db.js';
38
+ import type { RequestActorContext } from './request_context.js';
39
+ import { type AuditLogConfig, type AuditLogEvent, type AuditLogInput } from './audit_log_schema.js';
40
+ /**
41
+ * Per-request context required by `AuditEmitter.emit` — just the eager
42
+ * `pending_effects` queue. The bound emitter carries its own `log`
43
+ * reference inside the closure, so per-call contexts don't need one.
44
+ *
45
+ * Audit emits are eager-only by design: the bound emitter fires the
46
+ * pool write immediately and pushes the in-flight `Promise<void>` here.
47
+ * They never go through `emit_after_commit` — pool-routed audit writes
48
+ * are already rollback-resilient because they run outside the request
49
+ * transaction, so the post-commit timing the deferred queue provides
50
+ * would only delay forensic visibility without any safety benefit.
51
+ *
52
+ * Both `RouteContext` and `ActionContext` structurally satisfy this
53
+ * shape (they each carry `pending_effects`), so handlers pass `route`
54
+ * / `ctx` directly.
55
+ */
56
+ export interface AuditEmitterContext {
57
+ pending_effects: Array<Promise<void>>;
58
+ }
59
+ /**
60
+ * Context required by `AuditEmitter.emit_role_grant_target` — adds
61
+ * `client_ip` so the helper can lift the `ip: ctx.client_ip`
62
+ * boilerplate every role-grant-shape emit site repeated.
63
+ */
64
+ export interface AuditEmitRoleGrantContext extends AuditEmitterContext {
65
+ /** Resolved client IP from the trusted-proxy middleware — `'unknown'` if not resolved. */
66
+ client_ip: string;
67
+ }
68
+ /**
69
+ * Bound audit-emit capability. Built once at backend assembly via
70
+ * `create_audit_emitter`; lives on `AppDeps.audit` so factories never see
71
+ * the pool.
72
+ */
73
+ export interface AuditEmitter {
74
+ /**
75
+ * Fire-and-forget audit write via the captured pool.
76
+ *
77
+ * The in-flight promise is pushed onto `ctx.pending_effects` so tests
78
+ * with `await_pending_effects: true` can assert side effects inline.
79
+ * Errors are logged, never thrown. Successful writes fan out to every
80
+ * listener on the chain (`notify`).
81
+ *
82
+ * Returns `void` deliberately — the in-flight promise is already on
83
+ * `ctx.pending_effects`, and exposing it would tempt callers to `await`
84
+ * (sequencing audit writes onto the response hot path) or sprinkle
85
+ * `void` to placate `no-floating-promises`. For awaitable writes from
86
+ * code paths without `pending_effects`, use `emit_pool`.
87
+ *
88
+ * @mutates `audit_log` table - inserts the row via the captured pool
89
+ * @mutates `ctx.pending_effects` - appends the in-flight settled promise
90
+ */
91
+ emit<T extends string>(ctx: AuditEmitterContext, input: AuditLogInput<T>): void;
92
+ /**
93
+ * Emit a role-grant-shape audit event with `actor_id` / `account_id` /
94
+ * `ip` lifted from `auth` + `ctx`. Delegates to `emit`.
95
+ *
96
+ * Use for any event populating one of the `target_*_id` columns.
97
+ * Reach for the lower-level `emit` only when the event is non-role-grant
98
+ * shape (e.g. `app_settings_update`, bootstrap, signup).
99
+ */
100
+ emit_role_grant_target<T extends string>(ctx: AuditEmitRoleGrantContext, auth: RequestActorContext, input: {
101
+ event_type: T;
102
+ target_account_id: Uuid | null;
103
+ target_actor_id: Uuid | null;
104
+ metadata: AuditLogInput<T>['metadata'];
105
+ outcome?: 'success' | 'failure';
106
+ }): void;
107
+ /**
108
+ * Awaitable pool write for code paths without a `pending_effects` queue.
109
+ *
110
+ * Same write-then-notify semantics as `emit`. Errors are logged and
111
+ * swallowed (resolved void), so callers can sequence sweeps with
112
+ * `await audit.emit_pool(...)` without try/catch boilerplate. The
113
+ * primary user is `auth/cleanup.ts` — sweeps have no per-request
114
+ * `pending_effects` to attach to.
115
+ *
116
+ * @mutates `audit_log` table - inserts the row via the captured pool
117
+ */
118
+ emit_pool<T extends string>(input: AuditLogInput<T>): Promise<void>;
119
+ /**
120
+ * Fan out an already-written audit row to the listener chain.
121
+ *
122
+ * Use only when the row was inserted in-transaction by a query helper
123
+ * that returned the `AuditLogEvent` (e.g. `query_accept_offer.audit_events`).
124
+ * Per-listener exceptions are caught and logged; one failing listener
125
+ * does not starve siblings.
126
+ */
127
+ notify(event: AuditLogEvent): void;
128
+ /**
129
+ * Mutable subscriber chain. Append at server assembly to compose the
130
+ * factory-managed audit-log SSE on top of the consumer's
131
+ * `on_audit_event` callback without shallow-copying `AppDeps`.
132
+ */
133
+ readonly on_event_chain: Array<(event: AuditLogEvent) => void>;
134
+ }
135
+ /** Options for `create_audit_emitter`. */
136
+ export interface CreateAuditEmitterOptions {
137
+ /** Pool-level `Db`. Captured by every emit call. */
138
+ db: Db;
139
+ /** Logger for write + listener-callback failures. */
140
+ log: Logger;
141
+ /**
142
+ * Initial subscriber appended to `on_event_chain`. Omit for backends
143
+ * that compose listeners post-assembly (e.g. via `audit_log_sse`).
144
+ */
145
+ on_audit_event?: ((event: AuditLogEvent) => void) | null;
146
+ /**
147
+ * Audit-log config. Defaults to `BUILTIN_AUDIT_LOG_CONFIG`. Consumer-
148
+ * extended configs from `create_audit_log_config({extra_events})` get
149
+ * registered here once at backend assembly.
150
+ */
151
+ audit_log_config?: AuditLogConfig;
152
+ }
153
+ /**
154
+ * Build a bound `AuditEmitter`. Called once at `create_app_backend` time.
155
+ *
156
+ * @param options - pool, logger, optional initial subscriber, optional config
157
+ * @returns the bound emitter; closes over the pool + config + listener chain
158
+ */
159
+ export declare const create_audit_emitter: (options: CreateAuditEmitterOptions) => AuditEmitter;
160
+ //# sourceMappingURL=audit_emitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit_emitter.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/audit_emitter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AACpD,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,wBAAwB,CAAC;AAEjD,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,aAAa,CAAC;AACpC,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,sBAAsB,CAAC;AAE9D,OAAO,EAEN,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,MAAM,uBAAuB,CAAC;AAE/B;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,mBAAmB;IACnC,eAAe,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;CACtC;AAED;;;;GAIG;AACH,MAAM,WAAW,yBAA0B,SAAQ,mBAAmB;IACrE,0FAA0F;IAC1F,SAAS,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC5B;;;;;;;;;;;;;;;;OAgBG;IACH,IAAI,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,EAAE,mBAAmB,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAChF;;;;;;;OAOG;IACH,sBAAsB,CAAC,CAAC,SAAS,MAAM,EACtC,GAAG,EAAE,yBAAyB,EAC9B,IAAI,EAAE,mBAAmB,EACzB,KAAK,EAAE;QACN,UAAU,EAAE,CAAC,CAAC;QACd,iBAAiB,EAAE,IAAI,GAAG,IAAI,CAAC;QAC/B,eAAe,EAAE,IAAI,GAAG,IAAI,CAAC;QAC7B,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;QACvC,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;KAChC,GACC,IAAI,CAAC;IACR;;;;;;;;;;OAUG;IACH,SAAS,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE;;;;;;;OAOG;IACH,MAAM,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;IACnC;;;;OAIG;IACH,QAAQ,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC,CAAC;CAC/D;AAED,0CAA0C;AAC1C,MAAM,WAAW,yBAAyB;IACzC,oDAAoD;IACpD,EAAE,EAAE,EAAE,CAAC;IACP,qDAAqD;IACrD,GAAG,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IACzD;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,cAAc,CAAC;CAClC;AAED;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,GAAI,SAAS,yBAAyB,KAAG,YAoDzE,CAAC"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Bound audit-emit capability.
3
+ *
4
+ * `AuditEmitter` closes over the pool-level `Db`, the `on_audit_event`
5
+ * subscriber chain, and the optional `AuditLogConfig` at backend-assembly
6
+ * time. Consumers reach for `deps.audit.emit(ctx, input)` and never see the
7
+ * pool — handlers cannot accidentally emit an audit event against the
8
+ * request's transactional `db` (which would be rolled back with the parent
9
+ * on a handler throw).
10
+ *
11
+ * Four methods cover every fan-out shape the auth domain needs:
12
+ *
13
+ * - `emit(ctx, input)` — fire-and-forget pool write. Pushes the in-flight
14
+ * promise onto `ctx.pending_effects` for post-response flushing. Errors are
15
+ * logged, never thrown. Returns `void` so callers don't pile up `void`
16
+ * keywords or accidentally `await` something whose handle is already in
17
+ * `pending_effects`.
18
+ * - `emit_role_grant_target(ctx, auth, input)` — wrapper that lifts the
19
+ * `actor_id` / `account_id` / `ip` boilerplate every role-grant-shape audit
20
+ * site repeated. Delegates to `emit`.
21
+ * - `emit_pool(input)` — awaitable pool write for code paths without a
22
+ * `pending_effects` queue (cleanup sweeps, ad-hoc maintenance scripts).
23
+ * Same write-then-notify semantics as `emit`, just synchronous-with-await.
24
+ * - `notify(event)` — fan out an already-written audit row (e.g. rows
25
+ * returned by `query_accept_offer` that were inserted in-transaction by
26
+ * the query layer). Runs every listener on the chain; per-listener throws
27
+ * are isolated.
28
+ *
29
+ * The chain is mutable so server assembly can append additional listeners
30
+ * (e.g. the audit-log SSE registry composed by `create_app_server`) after
31
+ * the backend is built but before the first request runs.
32
+ *
33
+ * @module
34
+ */
35
+ import { query_audit_log } from './audit_log_queries.js';
36
+ import { BUILTIN_AUDIT_LOG_CONFIG, } from './audit_log_schema.js';
37
+ /**
38
+ * Build a bound `AuditEmitter`. Called once at `create_app_backend` time.
39
+ *
40
+ * @param options - pool, logger, optional initial subscriber, optional config
41
+ * @returns the bound emitter; closes over the pool + config + listener chain
42
+ */
43
+ export const create_audit_emitter = (options) => {
44
+ const { db, log, audit_log_config = BUILTIN_AUDIT_LOG_CONFIG } = options;
45
+ const on_event_chain = [];
46
+ if (options.on_audit_event)
47
+ on_event_chain.push(options.on_audit_event);
48
+ const notify = (event) => {
49
+ for (const listener of on_event_chain) {
50
+ try {
51
+ listener(event);
52
+ }
53
+ catch (err) {
54
+ log.error('Audit log listener failed:', err);
55
+ }
56
+ }
57
+ };
58
+ const emit_pool = async (input) => {
59
+ try {
60
+ const event = await query_audit_log({ db }, input, audit_log_config);
61
+ notify(event);
62
+ }
63
+ catch (err) {
64
+ log.error('Audit log write failed:', err);
65
+ }
66
+ };
67
+ const emit = (ctx, input) => {
68
+ ctx.pending_effects.push(emit_pool(input));
69
+ };
70
+ const emit_role_grant_target = (ctx, auth, input) => {
71
+ emit(ctx, {
72
+ event_type: input.event_type,
73
+ actor_id: auth.actor.id,
74
+ account_id: auth.account.id,
75
+ outcome: input.outcome,
76
+ target_account_id: input.target_account_id,
77
+ target_actor_id: input.target_actor_id,
78
+ ip: ctx.client_ip,
79
+ metadata: input.metadata,
80
+ });
81
+ };
82
+ return { emit, emit_role_grant_target, emit_pool, notify, on_event_chain };
83
+ };
@@ -1,20 +1,18 @@
1
1
  /**
2
2
  * Audit log database queries.
3
3
  *
4
- * Records and retrieves auth mutation events for security monitoring.
5
- * All write operations should use `audit_log_fire_and_forget` to
6
- * ensure audit logging never blocks or breaks auth flows.
7
- *
8
- * Rollback resilience: `audit_log_fire_and_forget` writes to `background_db`
9
- * (pool-level), not the handler's transaction-scoped `db`, so audit entries
10
- * persist even when the request transaction rolls back.
4
+ * Records and retrieves auth mutation events for security monitoring. The
5
+ * canonical fire-and-forget entry point is `AppDeps.audit.emit(ctx, input)`
6
+ * (see `auth/audit_emitter.ts`) it closes over the pool so audit rows
7
+ * persist even when the request transaction rolls back. This module only
8
+ * exposes the in-transaction `query_*` primitives and the drift counters;
9
+ * the bound emitter writes through `query_audit_log` against its captured
10
+ * pool.
11
11
  *
12
12
  * @module
13
13
  */
14
14
  import type { QueryDeps } from '../db/query_deps.js';
15
- import type { RouteContext } from '../http/route_spec.js';
16
- import type { AppDeps } from './deps.js';
17
- import { type AuditLogConfig, type AuditLogEvent, type AuditLogInput, type AuditLogListOptions, type AuditLogEventWithUsernamesJson, type PermitHistoryEventJson } from './audit_log_schema.js';
15
+ import { type AuditLogConfig, type AuditLogEvent, type AuditLogInput, type AuditLogListOptions, type AuditLogEventWithUsernamesJson, type RoleGrantHistoryEventJson } from './audit_log_schema.js';
18
16
  /** Number of audit metadata validation failures observed since process start. */
19
17
  export declare const get_audit_metadata_validation_failures: () => number;
20
18
  /** Reset the counter — for tests only. */
@@ -32,6 +30,12 @@ export declare const reset_audit_unknown_event_type_failures: () => void;
32
30
  * but write the row anyway. Consumers extend the recognized set via
33
31
  * `create_audit_log_config({extra_events})`.
34
32
  *
33
+ * In-transaction call site for query helpers that must atomically write the
34
+ * row alongside other mutations (e.g. `query_accept_offer`). Fire-and-forget
35
+ * call sites should reach for `AppDeps.audit.emit` instead — that wrapper
36
+ * closes over the pool so audit rows persist when the parent transaction
37
+ * rolls back.
38
+ *
35
39
  * @param deps - query dependencies
36
40
  * @param input - the audit event to record
37
41
  * @param config - audit-log config. Defaults to `BUILTIN_AUDIT_LOG_CONFIG`.
@@ -57,22 +61,14 @@ export declare const query_audit_log_list: (deps: QueryDeps, options?: AuditLogL
57
61
  */
58
62
  export declare const query_audit_log_list_with_usernames: (deps: QueryDeps, options?: AuditLogListOptions) => Promise<Array<AuditLogEventWithUsernamesJson>>;
59
63
  /**
60
- * List audit log entries related to an account (as actor or target).
61
- *
62
- * @param deps - query dependencies
63
- * @param account_id - the account to query for
64
- * @param limit - maximum entries to return
65
- */
66
- export declare const query_audit_log_list_for_account: (deps: QueryDeps, account_id: string, limit?: number) => Promise<Array<AuditLogEvent>>;
67
- /**
68
- * List permit grant/revoke events with resolved usernames.
64
+ * List role_grant grant/revoke events with resolved usernames.
69
65
  *
70
66
  * @param deps - query dependencies
71
67
  * @param limit - maximum entries to return
72
68
  * @param offset - number of entries to skip
73
- * @returns permit history events with `username` and `target_username`
69
+ * @returns role_grant history events with `username` and `target_username`
74
70
  */
75
- export declare const query_audit_log_list_permit_history: (deps: QueryDeps, limit?: number, offset?: number) => Promise<Array<PermitHistoryEventJson>>;
71
+ export declare const query_audit_log_list_role_grant_history: (deps: QueryDeps, limit?: number, offset?: number) => Promise<Array<RoleGrantHistoryEventJson>>;
76
72
  /**
77
73
  * Delete audit log entries older than the given date.
78
74
  *
@@ -82,31 +78,4 @@ export declare const query_audit_log_list_permit_history: (deps: QueryDeps, limi
82
78
  * @mutates `audit_log` table - deletes every row with `created_at < before`
83
79
  */
84
80
  export declare const query_audit_log_cleanup_before: (deps: QueryDeps, before: Date) => Promise<number>;
85
- /**
86
- * Capabilities required by `audit_log_fire_and_forget`.
87
- *
88
- * Defined as a slice of `AppDeps` so call sites can pass the surrounding deps
89
- * bundle directly without a structural-compatibility coincidence. The bundled
90
- * shape replaces the prior `(log, on_audit_event, config?)` positional args
91
- * — consumers that forgot the trailing `config` would silently fall back to
92
- * `BUILTIN_AUDIT_LOG_CONFIG` and skip metadata validation for their own
93
- * event types. `audit_log_config` is optional on `AppDeps` and defaults to
94
- * `BUILTIN_AUDIT_LOG_CONFIG` inside `audit_log_fire_and_forget` when absent.
95
- */
96
- export type AuditLogFireAndForgetDeps = Pick<AppDeps, 'log' | 'on_audit_event' | 'audit_log_config'>;
97
- /**
98
- * Log an audit event without blocking the caller.
99
- *
100
- * Errors are logged — audit logging never breaks auth flows. Uses
101
- * `background_db` so entries persist even when the request transaction
102
- * rolls back. Write and `on_audit_event` callback failures are logged separately.
103
- *
104
- * @param route - `background_db` and `pending_effects` from the route context
105
- * @param input - the audit event to record
106
- * @param deps - logger, `on_audit_event` callback, and optional `audit_log_config`
107
- * @returns the settled promise (callers may ignore it)
108
- * @mutates `audit_log` table - inserts a row via `background_db` (independent of the request transaction)
109
- * @mutates `route.pending_effects` - pushes the in-flight settled promise for test flushing
110
- */
111
- export declare const audit_log_fire_and_forget: <T extends string>(route: Pick<RouteContext, "background_db" | "pending_effects">, input: AuditLogInput<T>, deps: AuditLogFireAndForgetDeps) => Promise<void>;
112
81
  //# sourceMappingURL=audit_log_queries.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"audit_log_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/audit_log_queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAEnD,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,uBAAuB,CAAC;AACxD,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,WAAW,CAAC;AACvC,OAAO,EAGN,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,8BAA8B,EACnC,KAAK,sBAAsB,EAC3B,MAAM,uBAAuB,CAAC;AAa/B,iFAAiF;AACjF,eAAO,MAAM,sCAAsC,QAAO,MACvB,CAAC;AAEpC,0CAA0C;AAC1C,eAAO,MAAM,wCAAwC,QAAO,IAE3D,CAAC;AAYF,gFAAgF;AAChF,eAAO,MAAM,qCAAqC,QAAO,MACvB,CAAC;AAEnC,0CAA0C;AAC1C,eAAO,MAAM,uCAAuC,QAAO,IAE1D,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,eAAe,GAAU,CAAC,SAAS,MAAM,EACrD,MAAM,SAAS,EACf,OAAO,aAAa,CAAC,CAAC,CAAC,EACvB,SAAQ,cAAyC,KAC/C,OAAO,CAAC,aAAa,CAmCvB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAChC,MAAM,SAAS,EACf,UAAU,mBAAmB,KAC3B,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAwC9B,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,mCAAmC,GAC/C,MAAM,SAAS,EACf,UAAU,mBAAmB,KAC3B,OAAO,CAAC,KAAK,CAAC,8BAA8B,CAAC,CA8C/C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,gCAAgC,GAC5C,MAAM,SAAS,EACf,YAAY,MAAM,EAClB,cAA+B,KAC7B,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAO9B,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,mCAAmC,GAC/C,MAAM,SAAS,EACf,cAA+B,EAC/B,eAAU,KACR,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAYvC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,8BAA8B,GAC1C,MAAM,SAAS,EACf,QAAQ,IAAI,KACV,OAAO,CAAC,MAAM,CAMhB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,MAAM,yBAAyB,GAAG,IAAI,CAC3C,OAAO,EACP,KAAK,GAAG,gBAAgB,GAAG,kBAAkB,CAC7C,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,yBAAyB,GAAI,CAAC,SAAS,MAAM,EACzD,OAAO,IAAI,CAAC,YAAY,EAAE,eAAe,GAAG,iBAAiB,CAAC,EAC9D,OAAO,aAAa,CAAC,CAAC,CAAC,EACvB,MAAM,yBAAyB,KAC7B,OAAO,CAAC,IAAI,CAed,CAAC"}
1
+ {"version":3,"file":"audit_log_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/audit_log_queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EAGN,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,8BAA8B,EACnC,KAAK,yBAAyB,EAC9B,MAAM,uBAAuB,CAAC;AAa/B,iFAAiF;AACjF,eAAO,MAAM,sCAAsC,QAAO,MACvB,CAAC;AAEpC,0CAA0C;AAC1C,eAAO,MAAM,wCAAwC,QAAO,IAE3D,CAAC;AAYF,gFAAgF;AAChF,eAAO,MAAM,qCAAqC,QAAO,MACvB,CAAC;AAEnC,0CAA0C;AAC1C,eAAO,MAAM,uCAAuC,QAAO,IAE1D,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,eAAe,GAAU,CAAC,SAAS,MAAM,EACrD,MAAM,SAAS,EACf,OAAO,aAAa,CAAC,CAAC,CAAC,EACvB,SAAQ,cAAyC,KAC/C,OAAO,CAAC,aAAa,CAoCvB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAChC,MAAM,SAAS,EACf,UAAU,mBAAmB,KAC3B,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAwC9B,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,mCAAmC,GAC/C,MAAM,SAAS,EACf,UAAU,mBAAmB,KAC3B,OAAO,CAAC,KAAK,CAAC,8BAA8B,CAAC,CA8C/C,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,uCAAuC,GACnD,MAAM,SAAS,EACf,cAA+B,EAC/B,eAAU,KACR,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAY1C,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,8BAA8B,GAC1C,MAAM,SAAS,EACf,QAAQ,IAAI,KACV,OAAO,CAAC,MAAM,CAMhB,CAAC"}
@@ -1,13 +1,13 @@
1
1
  /**
2
2
  * Audit log database queries.
3
3
  *
4
- * Records and retrieves auth mutation events for security monitoring.
5
- * All write operations should use `audit_log_fire_and_forget` to
6
- * ensure audit logging never blocks or breaks auth flows.
7
- *
8
- * Rollback resilience: `audit_log_fire_and_forget` writes to `background_db`
9
- * (pool-level), not the handler's transaction-scoped `db`, so audit entries
10
- * persist even when the request transaction rolls back.
4
+ * Records and retrieves auth mutation events for security monitoring. The
5
+ * canonical fire-and-forget entry point is `AppDeps.audit.emit(ctx, input)`
6
+ * (see `auth/audit_emitter.ts`) it closes over the pool so audit rows
7
+ * persist even when the request transaction rolls back. This module only
8
+ * exposes the in-transaction `query_*` primitives and the drift counters;
9
+ * the bound emitter writes through `query_audit_log` against its captured
10
+ * pool.
11
11
  *
12
12
  * @module
13
13
  */
@@ -53,6 +53,12 @@ export const reset_audit_unknown_event_type_failures = () => {
53
53
  * but write the row anyway. Consumers extend the recognized set via
54
54
  * `create_audit_log_config({extra_events})`.
55
55
  *
56
+ * In-transaction call site for query helpers that must atomically write the
57
+ * row alongside other mutations (e.g. `query_accept_offer`). Fire-and-forget
58
+ * call sites should reach for `AppDeps.audit.emit` instead — that wrapper
59
+ * closes over the pool so audit rows persist when the parent transaction
60
+ * rolls back.
61
+ *
56
62
  * @param deps - query dependencies
57
63
  * @param input - the audit event to record
58
64
  * @param config - audit-log config. Defaults to `BUILTIN_AUDIT_LOG_CONFIG`.
@@ -75,14 +81,15 @@ export const query_audit_log = async (deps, input, config = BUILTIN_AUDIT_LOG_CO
75
81
  }
76
82
  }
77
83
  }
78
- const rows = await deps.db.query(`INSERT INTO audit_log (event_type, outcome, actor_id, account_id, target_account_id, ip, metadata)
79
- VALUES ($1, $2, $3, $4, $5, $6, $7)
84
+ const rows = await deps.db.query(`INSERT INTO audit_log (event_type, outcome, actor_id, account_id, target_account_id, target_actor_id, ip, metadata)
85
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
80
86
  RETURNING *`, [
81
87
  input.event_type,
82
88
  input.outcome ?? 'success',
83
89
  input.actor_id ?? null,
84
90
  input.account_id ?? null,
85
91
  input.target_account_id ?? null,
92
+ input.target_actor_id ?? null,
86
93
  input.ip ?? null,
87
94
  input.metadata ? JSON.stringify(input.metadata) : null,
88
95
  ]);
@@ -171,33 +178,21 @@ export const query_audit_log_list_with_usernames = async (deps, options) => {
171
178
  ${where} ORDER BY al.seq DESC LIMIT $${param_index++} OFFSET $${param_index}`, [...params, limit, offset]);
172
179
  };
173
180
  /**
174
- * List audit log entries related to an account (as actor or target).
175
- *
176
- * @param deps - query dependencies
177
- * @param account_id - the account to query for
178
- * @param limit - maximum entries to return
179
- */
180
- export const query_audit_log_list_for_account = async (deps, account_id, limit = AUDIT_LOG_DEFAULT_LIMIT) => {
181
- return deps.db.query(`SELECT * FROM audit_log
182
- WHERE account_id = $1 OR target_account_id = $1
183
- ORDER BY seq DESC LIMIT $2`, [account_id, limit]);
184
- };
185
- /**
186
- * List permit grant/revoke events with resolved usernames.
181
+ * List role_grant grant/revoke events with resolved usernames.
187
182
  *
188
183
  * @param deps - query dependencies
189
184
  * @param limit - maximum entries to return
190
185
  * @param offset - number of entries to skip
191
- * @returns permit history events with `username` and `target_username`
186
+ * @returns role_grant history events with `username` and `target_username`
192
187
  */
193
- export const query_audit_log_list_permit_history = async (deps, limit = AUDIT_LOG_DEFAULT_LIMIT, offset = 0) => {
188
+ export const query_audit_log_list_role_grant_history = async (deps, limit = AUDIT_LOG_DEFAULT_LIMIT, offset = 0) => {
194
189
  return deps.db.query(`SELECT al.*,
195
190
  a1.username AS username,
196
191
  a2.username AS target_username
197
192
  FROM audit_log al
198
193
  LEFT JOIN account a1 ON a1.id = al.account_id
199
194
  LEFT JOIN account a2 ON a2.id = al.target_account_id
200
- WHERE al.event_type IN ('permit_grant', 'permit_revoke')
195
+ WHERE al.event_type IN ('role_grant_create', 'role_grant_revoke')
201
196
  ORDER BY al.seq DESC LIMIT $1 OFFSET $2`, [limit, offset]);
202
197
  };
203
198
  /**
@@ -212,34 +207,3 @@ export const query_audit_log_cleanup_before = async (deps, before) => {
212
207
  const rows = await deps.db.query(`DELETE FROM audit_log WHERE created_at < $1 RETURNING id`, [before.toISOString()]);
213
208
  return rows.length;
214
209
  };
215
- /**
216
- * Log an audit event without blocking the caller.
217
- *
218
- * Errors are logged — audit logging never breaks auth flows. Uses
219
- * `background_db` so entries persist even when the request transaction
220
- * rolls back. Write and `on_audit_event` callback failures are logged separately.
221
- *
222
- * @param route - `background_db` and `pending_effects` from the route context
223
- * @param input - the audit event to record
224
- * @param deps - logger, `on_audit_event` callback, and optional `audit_log_config`
225
- * @returns the settled promise (callers may ignore it)
226
- * @mutates `audit_log` table - inserts a row via `background_db` (independent of the request transaction)
227
- * @mutates `route.pending_effects` - pushes the in-flight settled promise for test flushing
228
- */
229
- export const audit_log_fire_and_forget = (route, input, deps) => {
230
- const { log, on_audit_event, audit_log_config = BUILTIN_AUDIT_LOG_CONFIG } = deps;
231
- const p = query_audit_log({ db: route.background_db }, input, audit_log_config)
232
- .then((event) => {
233
- try {
234
- on_audit_event(event);
235
- }
236
- catch (callback_err) {
237
- log.error('Audit log on_audit_event callback failed:', callback_err);
238
- }
239
- })
240
- .catch((err) => {
241
- log.error('Audit log write failed:', err);
242
- });
243
- route.pending_effects.push(p);
244
- return p;
245
- };
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Audit log SSE stream route.
3
3
  *
4
- * The two list-reads (`audit_log_list`, `audit_log_permit_history`) moved to
4
+ * The two list-reads (`audit_log_list`, `audit_log_role_grant_history`) moved to
5
5
  * RPC in `auth/admin_actions.ts`, and the admin session listing moved to
6
6
  * `admin_session_list` on the same file. What remains here is the optional
7
7
  * `GET /audit/stream` SSE route — streams aren't an action-kind, so they
@@ -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;AAGH,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAEpD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAsB,KAAK,SAAS,EAAE,KAAK,eAAe,EAAC,MAAM,oBAAoB,CAAC;AAC7F,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,oCAAoC,CAAC;AAIzE,yCAAyC;AACzC,MAAM,WAAW,oBAAoB;IACpC,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,MAAM,CAAC,EAAE;QACR,SAAS,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB,KAAK,MAAM,IAAI,CAAC;QAC1F,GAAG,EAAE,MAAM,CAAC;KACZ,CAAC;CACF;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,4BAA4B,GAAI,UAAU,oBAAoB,KAAG,KAAK,CAAC,SAAS,CAgC5F,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;AAGH,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAEpD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAsB,KAAK,SAAS,EAAE,KAAK,eAAe,EAAC,MAAM,oBAAoB,CAAC;AAC7F,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,oCAAoC,CAAC;AAQzE,yCAAyC;AACzC,MAAM,WAAW,oBAAoB;IACpC,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,MAAM,CAAC,EAAE;QACR,SAAS,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB,KAAK,MAAM,IAAI,CAAC;QAC1F,GAAG,EAAE,MAAM,CAAC;KACZ,CAAC;CACF;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,4BAA4B,GAAI,UAAU,oBAAoB,KAAG,KAAK,CAAC,SAAS,CAiC5F,CAAC"}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Audit log SSE stream route.
3
3
  *
4
- * The two list-reads (`audit_log_list`, `audit_log_permit_history`) moved to
4
+ * The two list-reads (`audit_log_list`, `audit_log_role_grant_history`) moved to
5
5
  * RPC in `auth/admin_actions.ts`, and the admin session listing moved to
6
6
  * `admin_session_list` on the same file. What remains here is the optional
7
7
  * `GET /audit/stream` SSE route — streams aren't an action-kind, so they
@@ -15,6 +15,9 @@ import { z } from 'zod';
15
15
  import { create_sse_response } from '../realtime/sse.js';
16
16
  import { AUTH_SESSION_TOKEN_HASH_KEY, require_request_context } from './request_context.js';
17
17
  import { AUDIT_LOG_CHANNEL } from '../realtime/sse_auth_guard.js';
18
+ import { ActingActor } from '../http/auth_shape.js';
19
+ /** Query schema for the audit-log SSE route — multi-actor admins pass `?acting=<uuid>`. */
20
+ const AuditStreamQuery = z.strictObject({ acting: ActingActor });
18
21
  /**
19
22
  * Create the optional audit-log SSE route spec.
20
23
  *
@@ -33,15 +36,16 @@ export const create_audit_log_route_specs = (options) => {
33
36
  {
34
37
  method: 'GET',
35
38
  path: '/audit/stream',
36
- auth: { type: 'role', role },
39
+ auth: { account: 'required', actor: 'required', roles: [role] },
37
40
  description: 'Subscribe to realtime audit log events',
41
+ query: AuditStreamQuery,
38
42
  input: z.null(),
39
43
  output: z.null(), // SSE — no JSON response
40
44
  handler: (c) => {
41
45
  const ctx = require_request_context(c);
42
46
  // scope = session hash (capped → tabs-per-session limit and
43
47
  // session-specific `session_revoke` close). groups = [account_id]
44
- // (uncapped → coarse close on permit_revoke / session_revoke_all
48
+ // (uncapped → coarse close on role_grant_revoke / session_revoke_all
45
49
  // / password_change).
46
50
  const token_hash = c.get(AUTH_SESSION_TOKEN_HASH_KEY) ?? null;
47
51
  const { response, stream } = create_sse_response(c, log);