@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
@@ -3,14 +3,14 @@ import './assert_dev_env.js';
3
3
  * Standard admin integration test suite for fuz_app admin routes.
4
4
  *
5
5
  * `describe_standard_admin_integration_tests` creates a composable test suite
6
- * that exercises admin account listing, permit grant/revoke (via the RPC
7
- * surface — see `permit_offer_create` / `permit_revoke`), session/token
6
+ * that exercises admin account listing, role_grant grant/revoke (via the RPC
7
+ * surface — see `role_grant_offer_create` / `role_grant_revoke`), session/token
8
8
  * management, and audit log routes against a real PGlite database.
9
9
  *
10
10
  * Consumers call it with their route factory, session config, role schema,
11
11
  * and RPC endpoint specs — all admin route tests come for free.
12
12
  *
13
- * Scope: admin *semantics* — cross-admin isolation, permit grant/revoke
13
+ * Scope: admin *semantics* — cross-admin isolation, role_grant grant/revoke
14
14
  * flow, session/token revoke-all, audit writes. Output-schema conformance
15
15
  * for admin methods is **not** the concern of this suite; it lives in:
16
16
  *
@@ -27,6 +27,7 @@ import './assert_dev_env.js';
27
27
  */
28
28
  import { describe, test, assert, afterAll } from 'vitest';
29
29
  import { ROLE_KEEPER, ROLE_ADMIN } from '../auth/role_schema.js';
30
+ import { GRANT_PATH_ADMIN } from '../auth/grant_path_schema.js';
30
31
  import { AUTH_MIGRATION_NS } from '../auth/migrations.js';
31
32
  import { create_test_app } from './app_server.js';
32
33
  import { create_pglite_factory, create_describe_db, AUTH_INTEGRATION_TRUNCATE_TABLES, } from './db.js';
@@ -34,18 +35,20 @@ import { find_auth_route } from './integration_helpers.js';
34
35
  import { run_migrations } from '../db/migrate.js';
35
36
  import { ErrorCoverageCollector, assert_error_coverage, DEFAULT_INTEGRATION_ERROR_COVERAGE, } from './error_coverage.js';
36
37
  import { rpc_call_for_spec, require_rpc_endpoint_path, resolve_rpc_endpoints_for_setup, } from './rpc_helpers.js';
37
- import { permit_offer_create_action_spec, permit_revoke_action_spec, } from '../auth/permit_offer_action_specs.js';
38
- import { admin_account_list_action_spec, admin_session_list_action_spec, admin_session_revoke_all_action_spec, admin_token_revoke_all_action_spec, audit_log_list_action_spec, audit_log_permit_history_action_spec, } from '../auth/admin_action_specs.js';
38
+ import { role_grant_offer_create_action_spec, role_grant_revoke_action_spec, } from '../auth/role_grant_offer_action_specs.js';
39
+ import { admin_account_list_action_spec, admin_session_list_action_spec, admin_session_revoke_all_action_spec, admin_token_revoke_all_action_spec, audit_log_list_action_spec, audit_log_role_grant_history_action_spec, } from '../auth/admin_action_specs.js';
39
40
  import { account_token_create_action_spec, account_verify_action_spec, } from '../auth/account_action_specs.js';
40
- import { query_grant_permit } from '../auth/permit_queries.js';
41
- import { query_actor_by_account } from '../auth/account_queries.js';
42
- import { query_accept_offer } from '../auth/permit_offer_queries.js';
41
+ import { query_create_role_grant } from '../auth/role_grant_queries.js';
42
+ import { query_accept_offer } from '../auth/role_grant_offer_queries.js';
43
43
  /**
44
- * Pick a web-grantable role for testing, preferring a non-admin app-defined role.
44
+ * Pick a role for admin-grant testing, preferring a non-admin app-defined
45
+ * role whose `RoleSpec.grant_paths` includes `'admin'` (the
46
+ * `GRANT_PATH_ADMIN` constant). Falls back to `ROLE_ADMIN` when no
47
+ * app-defined admin-grant-path role is registered.
45
48
  */
46
- const pick_grantable_role = (role_options) => {
47
- for (const [name, opts] of role_options) {
48
- if (opts.web_grantable && name !== ROLE_ADMIN)
49
+ const pick_grantable_role = (role_specs) => {
50
+ for (const [name, spec] of role_specs) {
51
+ if (spec.grant_paths?.includes(GRANT_PATH_ADMIN) && name !== ROLE_ADMIN)
49
52
  return name;
50
53
  }
51
54
  return ROLE_ADMIN; // fallback
@@ -66,17 +69,16 @@ const build_admin_test_app_options = (options, db, roles) => ({
66
69
  /**
67
70
  * Standard admin integration test suite for fuz_app admin routes.
68
71
  *
69
- * Exercises account listing, permit grant/revoke (via RPC), session
72
+ * Exercises account listing, role_grant grant/revoke (via RPC), session
70
73
  * management, token management, audit log reads, admin-to-admin
71
74
  * isolation, and 401/403 error-coverage on the admin REST surface.
72
75
  * Output-schema conformance is not in scope — see the module docstring
73
76
  * for the suites that cover it.
74
77
  *
75
78
  * @throws Error at setup time when `options.rpc_endpoints` is empty — admin
76
- * permit grant/revoke, session/token revoke-all, and audit-log reads are
77
- * all RPC-only since the 2026-04-22 migration. Hard-fails via
78
- * `require_rpc_endpoint_path` so consumers see a clear setup error rather
79
- * than `method not found` mid-suite.
79
+ * role_grant grant/revoke, session/token revoke-all, and audit-log reads
80
+ * are RPC-only. Hard-fails via `require_rpc_endpoint_path` so consumers
81
+ * see a clear setup error rather than `method not found` mid-suite.
80
82
  */
81
83
  export const describe_standard_admin_integration_tests = (options) => {
82
84
  // Hard-fail early so consumers see a clear setup error instead of a
@@ -92,30 +94,30 @@ export const describe_standard_admin_integration_tests = (options) => {
92
94
  const describe_db = create_describe_db(factories, AUTH_INTEGRATION_TRUNCATE_TABLES);
93
95
  describe_db('standard_admin_integration', (get_db) => {
94
96
  const { cookie_name } = options.session_options;
95
- const { role_options } = options.roles;
96
- const grantable_role = pick_grantable_role(role_options);
97
+ const { role_specs } = options.roles;
98
+ const grantable_role = pick_grantable_role(role_specs);
97
99
  // Error coverage tracking across test groups
98
100
  const error_collector = new ErrorCoverageCollector();
99
101
  let captured_route_specs = null;
100
102
  afterAll(() => {
101
103
  if (captured_route_specs) {
102
- // Scope coverage to admin auth-related routes. Post-2026-04-23
103
- // RPC migration: account listing, session/token revoke-all,
104
- // audit-log reads, and invite CRUD are RPC-only. The only
105
- // admin REST route remaining is the optional
106
- // `GET /audit/stream` SSE, plus the shared RPC endpoint
107
- // path itself (admin methods live behind spec-level role auth).
104
+ // Scope coverage to admin auth-related routes. Account listing,
105
+ // session/token revoke-all, audit-log reads, and invite CRUD all
106
+ // live on the RPC surface; the only admin REST route remaining
107
+ // is the optional `GET /audit/stream` SSE (admin RPC methods
108
+ // live behind spec-level role auth on the shared endpoint path).
108
109
  // The `/audit/stream` suffix tracks the hardcoded path in
109
110
  // `auth/audit_log_routes.ts` — if consumers ever need to mount
110
111
  // the audit SSE at a different suffix, promote this to an
111
112
  // `audit_log_path_suffix` option on
112
113
  // `StandardAdminIntegrationTestOptions`.
113
- const admin_routes = captured_route_specs.filter((s) => s.path.endsWith('/audit/stream') && s.auth.type === 'role' && s.auth.role === 'admin');
114
+ const admin_routes = captured_route_specs.filter((s) => s.path.endsWith('/audit/stream') && (s.auth.roles?.includes('admin') ?? false));
114
115
  // Adaptive threshold: when the scoped admin REST surface is
115
- // effectively empty (0–1 routes, typical post-RPC-migration),
116
- // the 20% baseline is meaningless — a single SSE route that
117
- // can't be exercised against an error schema drops the ratio
118
- // to 0.0%. Log an informational skip instead of asserting.
116
+ // effectively empty (0–1 routes typical for the RPC-first
117
+ // admin surface), the 20% baseline is meaningless — a single
118
+ // SSE route that can't be exercised against an error schema
119
+ // drops the ratio to 0.0%. Log an informational skip instead
120
+ // of asserting.
119
121
  // The admin RPC surface is covered by
120
122
  // `describe_rpc_round_trip_tests`, not this collector.
121
123
  if (admin_routes.length <= 1) {
@@ -138,7 +140,7 @@ export const describe_standard_admin_integration_tests = (options) => {
138
140
  });
139
141
  /**
140
142
  * Drive the full consent flow (admin offer → recipient accept) and
141
- * return the materialized permit id. Accept is a direct transactional
143
+ * return the materialized role_grant id. Accept is a direct transactional
142
144
  * `query_accept_offer` call because the suite focuses on the admin
143
145
  * side; exercising the recipient's UI-wired accept path is covered by
144
146
  * `describe_rpc_round_trip_tests` + fuz_app's own action suite.
@@ -147,14 +149,19 @@ export const describe_standard_admin_integration_tests = (options) => {
147
149
  const res = await rpc_call_for_spec({
148
150
  app: args.app,
149
151
  path: rpc_path,
150
- spec: permit_offer_create_action_spec,
152
+ spec: role_grant_offer_create_action_spec,
151
153
  params: { to_account_id: args.to_account_id, role: args.role },
152
154
  headers: args.admin_headers,
153
155
  });
154
- assert.ok(res.ok, `permit_offer_create failed: ${res.ok ? '' : JSON.stringify(res.error)}`);
156
+ assert.ok(res.ok, `role_grant_offer_create failed: ${res.ok ? '' : JSON.stringify(res.error)}`);
155
157
  const { offer } = res.result;
156
- const accept_result = await get_db().transaction(async (tx) => query_accept_offer({ db: tx }, { offer_id: offer.id, to_account_id: args.to_account_id, ip: null }));
157
- return { offer_id: offer.id, permit_id: accept_result.permit.id };
158
+ const accept_result = await get_db().transaction(async (tx) => query_accept_offer({ db: tx }, {
159
+ offer_id: offer.id,
160
+ to_account_id: args.to_account_id,
161
+ actor_id: args.to_actor_id,
162
+ ip: null,
163
+ }));
164
+ return { offer_id: offer.id, role_grant_id: accept_result.role_grant.id };
158
165
  };
159
166
  // --- 1. Admin account listing (RPC) ---
160
167
  describe('admin account listing', () => {
@@ -165,7 +172,7 @@ export const describe_standard_admin_integration_tests = (options) => {
165
172
  app: test_app.app,
166
173
  path: rpc_path,
167
174
  spec: admin_account_list_action_spec,
168
- params: undefined,
175
+ params: {},
169
176
  headers: test_app.create_session_headers(),
170
177
  });
171
178
  assert.ok(res.ok, `admin_account_list failed: ${res.ok ? '' : JSON.stringify(res.error)}`);
@@ -183,19 +190,19 @@ export const describe_standard_admin_integration_tests = (options) => {
183
190
  app: test_app.app,
184
191
  path: rpc_path,
185
192
  spec: admin_account_list_action_spec,
186
- params: undefined,
193
+ params: {},
187
194
  headers: test_app.create_session_headers(),
188
195
  });
189
196
  assert.ok(!res.ok, 'Expected admin_account_list to fail for non-admin');
190
197
  assert.strictEqual(res.status, 403);
191
198
  });
192
199
  });
193
- // --- 2. Permit grant/revoke lifecycle ---
194
- // Permit grant/revoke are RPC-only (see `permit_offer_create` /
195
- // `permit_revoke`). End-to-end coverage lives in
200
+ // --- 2. Role grant create/revoke lifecycle ---
201
+ // Role grant create/revoke are RPC-only (see `role_grant_offer_create` /
202
+ // `role_grant_revoke`). End-to-end coverage lives in
196
203
  // `describe_rpc_round_trip_tests` + fuz_app's own
197
- // `permit_offer_actions.db.test.ts` /
198
- // `permit_offer_actions.notifications.revoke.db.test.ts`. The
204
+ // `role_grant_offer_actions.db.test.ts` /
205
+ // `role_grant_offer_actions.notifications.revoke.db.test.ts`. The
199
206
  // audit/isolation groups below exercise them as preconditions for
200
207
  // cross-cutting checks (event emission, admin-to-admin isolation).
201
208
  // --- 3. Admin session management ---
@@ -207,7 +214,7 @@ export const describe_standard_admin_integration_tests = (options) => {
207
214
  app: test_app.app,
208
215
  path: rpc_path,
209
216
  spec: admin_session_list_action_spec,
210
- params: undefined,
217
+ params: {},
211
218
  headers: test_app.create_session_headers(),
212
219
  });
213
220
  assert.ok(res.ok, `admin_session_list failed: ${res.ok ? '' : JSON.stringify(res.error)}`);
@@ -325,61 +332,60 @@ export const describe_standard_admin_integration_tests = (options) => {
325
332
  });
326
333
  test('audit log supports event_type filter', async () => {
327
334
  const test_app = await create_test_app(build_admin_test_app_options(options, get_db()));
328
- // Admin offer emits `permit_offer_create`. The downstream
329
- // `permit_grant` only fires on accept — out of scope for this test.
335
+ // Admin offer emits `role_grant_offer_create`. The downstream
336
+ // `role_grant_create` only fires on accept — out of scope for this test.
330
337
  const user_two = await test_app.create_account({ username: 'user_two' });
331
338
  const offer_res = await rpc_call_for_spec({
332
339
  app: test_app.app,
333
340
  path: rpc_path,
334
- spec: permit_offer_create_action_spec,
341
+ spec: role_grant_offer_create_action_spec,
335
342
  params: { to_account_id: user_two.account.id, role: grantable_role },
336
343
  headers: test_app.create_session_headers(),
337
344
  });
338
- assert.ok(offer_res.ok, 'permit_offer_create should succeed');
345
+ assert.ok(offer_res.ok, 'role_grant_offer_create should succeed');
339
346
  const res = await rpc_call_for_spec({
340
347
  app: test_app.app,
341
348
  path: rpc_path,
342
349
  spec: audit_log_list_action_spec,
343
- params: { event_type: 'permit_offer_create' },
350
+ params: { event_type: 'role_grant_offer_create' },
344
351
  headers: test_app.create_session_headers(),
345
352
  });
346
353
  assert.ok(res.ok, `audit_log_list failed: ${res.ok ? '' : JSON.stringify(res.error)}`);
347
- assert.ok(res.result.events.length >= 1, 'Expected at least 1 permit_offer_create event');
354
+ assert.ok(res.result.events.length >= 1, 'Expected at least 1 role_grant_offer_create event');
348
355
  for (const event of res.result.events) {
349
- assert.strictEqual(event.event_type, 'permit_offer_create');
356
+ assert.strictEqual(event.event_type, 'role_grant_offer_create');
350
357
  }
351
358
  });
352
- test('admin can view permit history', async () => {
359
+ test('admin can view role_grant history', async () => {
353
360
  const test_app = await create_test_app(build_admin_test_app_options(options, get_db()));
354
- // Drive the full consent flow so `permit_grant` lands in the audit log
355
- // — `query_audit_log_list_permit_history` filters to (permit_grant, permit_revoke).
361
+ // Drive the full consent flow so `role_grant_create` lands in the audit log
362
+ // — `query_audit_log_list_role_grant_history` filters to (role_grant_create, role_grant_revoke).
356
363
  const user_two = await test_app.create_account({ username: 'user_two' });
357
364
  await offer_and_accept({
358
365
  app: test_app.app,
359
366
  admin_headers: test_app.create_session_headers(),
360
367
  to_account_id: user_two.account.id,
368
+ to_actor_id: user_two.actor.id,
361
369
  role: grantable_role,
362
370
  });
363
371
  const res = await rpc_call_for_spec({
364
372
  app: test_app.app,
365
373
  path: rpc_path,
366
- spec: audit_log_permit_history_action_spec,
374
+ spec: audit_log_role_grant_history_action_spec,
367
375
  params: {},
368
376
  headers: test_app.create_session_headers(),
369
377
  });
370
- assert.ok(res.ok, `audit_log_permit_history failed: ${res.ok ? '' : JSON.stringify(res.error)}`);
371
- assert.ok(res.result.events.length >= 1, 'Expected at least 1 permit history event');
378
+ assert.ok(res.ok, `audit_log_role_grant_history failed: ${res.ok ? '' : JSON.stringify(res.error)}`);
379
+ assert.ok(res.result.events.length >= 1, 'Expected at least 1 role_grant history event');
372
380
  });
373
381
  });
374
382
  // --- 6. Admin audit trail ---
375
383
  describe('admin audit trail', () => {
376
- test('permit revoke creates audit event', async () => {
384
+ test('role_grant revoke creates audit event', async () => {
377
385
  const test_app = await create_test_app(build_admin_test_app_options(options, get_db()));
378
386
  const user_two = await test_app.create_account({ username: 'user_two' });
379
- const target_actor = await query_actor_by_account({ db: get_db() }, user_two.account.id);
380
- assert.ok(target_actor);
381
- const permit = await query_grant_permit({ db: get_db() }, {
382
- actor_id: target_actor.id,
387
+ const role_grant = await query_create_role_grant({ db: get_db() }, {
388
+ actor_id: user_two.actor.id,
383
389
  role: grantable_role,
384
390
  granted_by: test_app.backend.actor.id,
385
391
  });
@@ -387,22 +393,22 @@ export const describe_standard_admin_integration_tests = (options) => {
387
393
  const revoke_res = await rpc_call_for_spec({
388
394
  app: test_app.app,
389
395
  path: rpc_path,
390
- spec: permit_revoke_action_spec,
391
- params: { actor_id: target_actor.id, permit_id: permit.id },
396
+ spec: role_grant_revoke_action_spec,
397
+ params: { actor_id: user_two.actor.id, role_grant_id: role_grant.id },
392
398
  headers: test_app.create_session_headers(),
393
399
  });
394
- assert.ok(revoke_res.ok, `permit_revoke failed: ${revoke_res.ok ? '' : JSON.stringify(revoke_res.error)}`);
395
- // Check audit log for permit_revoke event
400
+ assert.ok(revoke_res.ok, `role_grant_revoke failed: ${revoke_res.ok ? '' : JSON.stringify(revoke_res.error)}`);
401
+ // Check audit log for role_grant_revoke event
396
402
  const audit_res = await rpc_call_for_spec({
397
403
  app: test_app.app,
398
404
  path: rpc_path,
399
405
  spec: audit_log_list_action_spec,
400
- params: { event_type: 'permit_revoke' },
406
+ params: { event_type: 'role_grant_revoke' },
401
407
  headers: test_app.create_session_headers(),
402
408
  });
403
409
  assert.ok(audit_res.ok, `audit_log_list failed: ${audit_res.ok ? '' : JSON.stringify(audit_res.error)}`);
404
- assert.ok(audit_res.result.events.length >= 1, 'Expected permit_revoke audit event');
405
- assert.strictEqual(audit_res.result.events[0].event_type, 'permit_revoke');
410
+ assert.ok(audit_res.result.events.length >= 1, 'Expected role_grant_revoke audit event');
411
+ assert.strictEqual(audit_res.result.events[0].event_type, 'role_grant_revoke');
406
412
  });
407
413
  test('admin session revoke-all creates audit event', async () => {
408
414
  const test_app = await create_test_app(build_admin_test_app_options(options, get_db()));
@@ -553,26 +559,25 @@ export const describe_standard_admin_integration_tests = (options) => {
553
559
  },
554
560
  });
555
561
  }
556
- // 3. offer permit (admin offers grantable_role to user_two) — full
557
- // consentful flow: offer + accept so both `permit_offer_create` and
558
- // `permit_grant` audit events land.
559
- const { permit_id } = await offer_and_accept({
562
+ // 3. offer role_grant (admin offers grantable_role to user_two) — full
563
+ // consentful flow: offer + accept so both `role_grant_offer_create` and
564
+ // `role_grant_create` audit events land.
565
+ const { role_grant_id } = await offer_and_accept({
560
566
  app: test_app.app,
561
567
  admin_headers: test_app.create_session_headers(),
562
568
  to_account_id: user_two.account.id,
569
+ to_actor_id: user_two.actor.id,
563
570
  role: grantable_role,
564
571
  });
565
- // 4. revoke permit (RPC)
566
- const target_actor = await query_actor_by_account({ db: get_db() }, user_two.account.id);
567
- assert.ok(target_actor);
572
+ // 4. revoke role_grant (RPC)
568
573
  const revoke_res = await rpc_call_for_spec({
569
574
  app: test_app.app,
570
575
  path: rpc_path,
571
- spec: permit_revoke_action_spec,
572
- params: { actor_id: target_actor.id, permit_id },
576
+ spec: role_grant_revoke_action_spec,
577
+ params: { actor_id: user_two.actor.id, role_grant_id },
573
578
  headers: test_app.create_session_headers(),
574
579
  });
575
- assert.ok(revoke_res.ok, `permit_revoke failed: ${revoke_res.ok ? '' : JSON.stringify(revoke_res.error)}`);
580
+ assert.ok(revoke_res.ok, `role_grant_revoke failed: ${revoke_res.ok ? '' : JSON.stringify(revoke_res.error)}`);
576
581
  // 5. create token (RPC)
577
582
  const token_res = await rpc_call_for_spec({
578
583
  app: test_app.app,
@@ -626,28 +631,28 @@ export const describe_standard_admin_integration_tests = (options) => {
626
631
  assert.ok(audit_res.ok, `audit_log_list failed: ${audit_res.ok ? '' : JSON.stringify(audit_res.error)}`);
627
632
  const events = audit_res.result.events;
628
633
  // check that each operation produced at least one event.
629
- // `permit_offer_create` fires on the admin RPC; `permit_grant`
634
+ // `role_grant_offer_create` fires on the admin RPC; `role_grant_create`
630
635
  // fires when the recipient accepts (driven by offer_and_accept).
631
636
  const expected_types = [
632
637
  'login',
633
638
  'logout',
634
- 'permit_offer_create',
635
- 'permit_offer_accept',
636
- 'permit_grant',
637
- 'permit_revoke',
639
+ 'role_grant_offer_create',
640
+ 'role_grant_offer_accept',
641
+ 'role_grant_create',
642
+ 'role_grant_revoke',
638
643
  'token_create',
639
644
  'password_change',
640
645
  ];
641
646
  for (const event_type of expected_types) {
642
647
  const found = events.filter((e) => e.event_type === event_type);
643
648
  assert.ok(found.length >= 1, `Expected at least 1 '${event_type}' audit event, found ${found.length}. ` +
644
- `This may indicate audit_log_fire_and_forget was removed from a handler.`);
649
+ `This may indicate a deps.audit.emit call was removed from a handler.`);
645
650
  }
646
651
  });
647
652
  });
648
653
  // --- 8. Admin-to-admin isolation ---
649
654
  describe('admin-to-admin isolation', () => {
650
- test('admin B revoking own permit via RPC succeeds', async () => {
655
+ test('admin B revoking own role_grant via RPC succeeds', async () => {
651
656
  const test_app = await create_test_app(build_admin_test_app_options(options, get_db()));
652
657
  captured_route_specs ??= test_app.route_specs;
653
658
  // Bootstrap user is admin A. Create admin B.
@@ -655,22 +660,22 @@ export const describe_standard_admin_integration_tests = (options) => {
655
660
  username: 'admin_b_iso',
656
661
  roles: ['admin'],
657
662
  });
658
- // Seed an active permit directly — the revoke IDOR check is the
663
+ // Seed an active role_grant directly — the revoke IDOR check is the
659
664
  // subject of this test, not the grant→accept cycle.
660
- const permit = await query_grant_permit({ db: get_db() }, {
665
+ const role_grant = await query_create_role_grant({ db: get_db() }, {
661
666
  actor_id: admin_b.actor.id,
662
667
  role: grantable_role,
663
668
  granted_by: test_app.backend.actor.id,
664
669
  });
665
- // Admin B revokes their own permit via RPC — should succeed
670
+ // Admin B revokes their own role_grant via RPC — should succeed
666
671
  const revoke_res = await rpc_call_for_spec({
667
672
  app: test_app.app,
668
673
  path: rpc_path,
669
- spec: permit_revoke_action_spec,
670
- params: { actor_id: admin_b.actor.id, permit_id: permit.id },
674
+ spec: role_grant_revoke_action_spec,
675
+ params: { actor_id: admin_b.actor.id, role_grant_id: role_grant.id },
671
676
  headers: create_headers(admin_b.session_cookie),
672
677
  });
673
- assert.ok(revoke_res.ok, `permit_revoke failed: ${revoke_res.ok ? '' : JSON.stringify(revoke_res.error)}`);
678
+ assert.ok(revoke_res.ok, `role_grant_revoke failed: ${revoke_res.ok ? '' : JSON.stringify(revoke_res.error)}`);
674
679
  assert.strictEqual(revoke_res.result.revoked, true);
675
680
  });
676
681
  test('admin revoke-all sessions for another admin works', async () => {
@@ -727,7 +732,7 @@ export const describe_standard_admin_integration_tests = (options) => {
727
732
  app: test_app.app,
728
733
  path: rpc_path,
729
734
  spec: admin_account_list_action_spec,
730
- params: undefined,
735
+ params: {},
731
736
  headers: create_headers(regular_user.session_cookie),
732
737
  });
733
738
  assert.ok(!res.ok, 'Expected admin_account_list to fail for non-admin');
@@ -739,14 +744,13 @@ export const describe_standard_admin_integration_tests = (options) => {
739
744
  test('exercises 401/403 on admin routes for error coverage', async () => {
740
745
  const test_app = await create_test_app(build_admin_test_app_options(options, get_db()));
741
746
  captured_route_specs ??= test_app.route_specs;
742
- // Post-RPC migration, `/api/admin` is nearly empty — admin reads
743
- // and mutations live on the RPC endpoint behind spec-level role
744
- // auth. The path-prefix carve is still the right scope here
747
+ // `/api/admin` is nearly empty — admin reads and mutations live
748
+ // on the RPC endpoint behind spec-level role auth. The path-prefix carve is still the right scope here
745
749
  // because error coverage is tracked against REST `RouteSpec`s,
746
750
  // not RPC method specs (`describe_rpc_round_trip_tests` covers
747
751
  // the admin RPC surface separately).
748
752
  const prefix = options.admin_prefix ?? '/api/admin';
749
- const admin_routes = test_app.route_specs.filter((s) => s.path.startsWith(prefix) && s.auth.type === 'role' && s.auth.role === 'admin');
753
+ const admin_routes = test_app.route_specs.filter((s) => s.path.startsWith(prefix) && (s.auth.roles?.includes('admin') ?? false));
750
754
  // Hit admin routes without auth to exercise 401 error schemas.
751
755
  for (const route of admin_routes) {
752
756
  const res = await test_app.app.request(route.path, {
@@ -112,7 +112,7 @@ export const describe_standard_adversarial_headers = (suite_name, options, allow
112
112
  }
113
113
  if (tc.expected_status === 200) {
114
114
  assert.strictEqual(body.ok, true, 'expected ok to be true for 200 response');
115
- assert.strictEqual(body.has_context, false, 'expected has_context to be false (no auth)');
115
+ assert.strictEqual(body.account_id, null, 'expected account_id to be null (no auth)');
116
116
  }
117
117
  if (tc.validate_expectation === 'not_called') {
118
118
  assert.strictEqual(mock_validate.mock.calls.length, 0, 'validate should not have been called — middleware should short-circuit');
@@ -53,7 +53,7 @@ export interface BootstrapTestAccountOptions {
53
53
  * `create_test_app_server` and `TestApp.create_account`.
54
54
  *
55
55
  * @mutates the underlying `options.db` — inserts rows into `account`, `actor`,
56
- * `permit` (one per role), `api_token`, and `auth_session`.
56
+ * `role_grant` (one per role), `api_token`, and `auth_session`.
57
57
  */
58
58
  export declare const bootstrap_test_account: (options: BootstrapTestAccountOptions) => Promise<{
59
59
  account: {
@@ -107,17 +107,16 @@ export interface TestAppServerOptions {
107
107
  /** Roles to grant. Default: `[ROLE_KEEPER]`. */
108
108
  roles?: Array<string>;
109
109
  /**
110
- * Backend audit event callback — wired into `backend.deps.on_audit_event`.
111
- * When `audit_log_sse: true` is passed to `create_app_server`, this runs
112
- * after the audit SSE broadcast (composed downstream by app_server).
113
- * Use to wire consumer SSE auth guards in tests.
114
- * Default: no-op.
110
+ * Backend audit event callback — threaded into `create_audit_emitter` so
111
+ * it becomes the first listener on `backend.deps.audit.on_event_chain`.
112
+ * When `audit_log_sse: true` is passed to `create_app_server`, the SSE
113
+ * listener is appended after this one. Use to wire consumer SSE auth
114
+ * guards in tests. Default: no-op.
115
115
  */
116
116
  on_audit_event?: (event: AuditLogEvent) => void;
117
117
  /**
118
- * Optional audit log config — written onto `backend.deps.audit_log_config`
119
- * before return so it lands in time for `create_app_server`'s shallow
120
- * spread of `backend.deps` (SSE branch) and the no-SSE alias branch alike.
118
+ * Optional audit log config — threaded into `create_audit_emitter` and
119
+ * captured inside `backend.deps.audit`'s closure.
121
120
  *
122
121
  * Use when the consumer registers extra event types via
123
122
  * `create_audit_log_config({extra_events})` — without this, emits for
@@ -132,7 +131,7 @@ export interface TestAppServerOptions {
132
131
  * Sets up:
133
132
  * - Auth tables (via cached PGlite factory, or reuses existing `db`)
134
133
  * - A keeper account with hashed password
135
- * - Role permits for each role in `options.roles`
134
+ * - Role role_grants for each role in `options.roles`
136
135
  * - An API token for Bearer auth
137
136
  * - A session with a signed cookie value
138
137
  *
@@ -143,10 +142,8 @@ export interface TestAppServerOptions {
143
142
  * @returns a `TestAppServer` ready for HTTP testing
144
143
  * @mutates the underlying database — when `db` is supplied, resets singleton
145
144
  * state (`bootstrap_lock.bootstrapped`, `app_settings.open_signup`) before
146
- * bootstrapping; in either branch inserts an account, actor, role permits,
147
- * API token, and session row. When `audit_log_config` is provided, also
148
- * sets `backend.deps.audit_log_config` so `create_app_server`'s shallow
149
- * spread picks it up.
145
+ * bootstrapping; in either branch inserts an account, actor, role role_grants,
146
+ * API token, and session row.
150
147
  */
151
148
  export declare const create_test_app_server: (options: TestAppServerOptions) => Promise<TestAppServer>;
152
149
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"app_server.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/app_server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"app_server.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/app_server.ts"],"names":[],"mappings":"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"}