@fuzdev/fuz_app 0.55.0 → 0.57.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (333) hide show
  1. package/dist/actions/CLAUDE.md +211 -155
  2. package/dist/actions/action_bridge.d.ts +8 -5
  3. package/dist/actions/action_bridge.d.ts.map +1 -1
  4. package/dist/actions/action_bridge.js +1 -11
  5. package/dist/actions/action_codegen.d.ts +19 -0
  6. package/dist/actions/action_codegen.d.ts.map +1 -1
  7. package/dist/actions/action_codegen.js +20 -14
  8. package/dist/actions/action_registry.d.ts.map +1 -1
  9. package/dist/actions/action_registry.js +5 -2
  10. package/dist/actions/action_rpc.d.ts +110 -44
  11. package/dist/actions/action_rpc.d.ts.map +1 -1
  12. package/dist/actions/action_rpc.js +92 -287
  13. package/dist/actions/action_spec.d.ts +55 -16
  14. package/dist/actions/action_spec.d.ts.map +1 -1
  15. package/dist/actions/action_spec.js +16 -11
  16. package/dist/actions/action_types.d.ts +28 -60
  17. package/dist/actions/action_types.d.ts.map +1 -1
  18. package/dist/actions/action_types.js +13 -5
  19. package/dist/actions/broadcast_api.d.ts +2 -2
  20. package/dist/actions/broadcast_api.js +2 -2
  21. package/dist/actions/compile_action_registry.d.ts +50 -0
  22. package/dist/actions/compile_action_registry.d.ts.map +1 -0
  23. package/dist/actions/compile_action_registry.js +69 -0
  24. package/dist/actions/heartbeat.d.ts +8 -4
  25. package/dist/actions/heartbeat.d.ts.map +1 -1
  26. package/dist/actions/heartbeat.js +5 -4
  27. package/dist/actions/perform_action.d.ts +145 -0
  28. package/dist/actions/perform_action.d.ts.map +1 -0
  29. package/dist/actions/perform_action.js +258 -0
  30. package/dist/actions/register_action_ws.d.ts +44 -38
  31. package/dist/actions/register_action_ws.d.ts.map +1 -1
  32. package/dist/actions/register_action_ws.js +101 -159
  33. package/dist/actions/register_ws_endpoint.d.ts +2 -10
  34. package/dist/actions/register_ws_endpoint.d.ts.map +1 -1
  35. package/dist/actions/register_ws_endpoint.js +32 -10
  36. package/dist/actions/transports_ws_auth_guard.d.ts +1 -1
  37. package/dist/actions/transports_ws_auth_guard.js +1 -1
  38. package/dist/actions/transports_ws_backend.d.ts +1 -1
  39. package/dist/actions/transports_ws_backend.js +1 -1
  40. package/dist/auth/CLAUDE.md +673 -442
  41. package/dist/auth/account_action_specs.d.ts +28 -7
  42. package/dist/auth/account_action_specs.d.ts.map +1 -1
  43. package/dist/auth/account_action_specs.js +7 -7
  44. package/dist/auth/account_actions.d.ts +8 -14
  45. package/dist/auth/account_actions.d.ts.map +1 -1
  46. package/dist/auth/account_actions.js +26 -32
  47. package/dist/auth/account_queries.d.ts +46 -13
  48. package/dist/auth/account_queries.d.ts.map +1 -1
  49. package/dist/auth/account_queries.js +73 -33
  50. package/dist/auth/account_routes.d.ts +4 -3
  51. package/dist/auth/account_routes.d.ts.map +1 -1
  52. package/dist/auth/account_routes.js +58 -33
  53. package/dist/auth/account_schema.d.ts +46 -54
  54. package/dist/auth/account_schema.d.ts.map +1 -1
  55. package/dist/auth/account_schema.js +21 -48
  56. package/dist/auth/admin_action_specs.d.ts +55 -21
  57. package/dist/auth/admin_action_specs.d.ts.map +1 -1
  58. package/dist/auth/admin_action_specs.js +42 -26
  59. package/dist/auth/admin_actions.d.ts +14 -21
  60. package/dist/auth/admin_actions.d.ts.map +1 -1
  61. package/dist/auth/admin_actions.js +47 -44
  62. package/dist/auth/audit_emitter.d.ts +160 -0
  63. package/dist/auth/audit_emitter.d.ts.map +1 -0
  64. package/dist/auth/audit_emitter.js +83 -0
  65. package/dist/auth/audit_log_queries.d.ts +17 -87
  66. package/dist/auth/audit_log_queries.d.ts.map +1 -1
  67. package/dist/auth/audit_log_queries.js +17 -96
  68. package/dist/auth/audit_log_routes.d.ts +1 -1
  69. package/dist/auth/audit_log_routes.d.ts.map +1 -1
  70. package/dist/auth/audit_log_routes.js +7 -3
  71. package/dist/auth/audit_log_schema.d.ts +48 -42
  72. package/dist/auth/audit_log_schema.d.ts.map +1 -1
  73. package/dist/auth/audit_log_schema.js +56 -43
  74. package/dist/auth/auth_guard_resolver.d.ts +44 -0
  75. package/dist/auth/auth_guard_resolver.d.ts.map +1 -0
  76. package/dist/auth/auth_guard_resolver.js +56 -0
  77. package/dist/auth/bootstrap_account.d.ts +7 -7
  78. package/dist/auth/bootstrap_account.d.ts.map +1 -1
  79. package/dist/auth/bootstrap_account.js +7 -7
  80. package/dist/auth/bootstrap_routes.d.ts.map +1 -1
  81. package/dist/auth/bootstrap_routes.js +11 -10
  82. package/dist/auth/cleanup.d.ts +20 -26
  83. package/dist/auth/cleanup.d.ts.map +1 -1
  84. package/dist/auth/cleanup.js +33 -47
  85. package/dist/auth/credential_type_schema.d.ts +115 -0
  86. package/dist/auth/credential_type_schema.d.ts.map +1 -0
  87. package/dist/auth/credential_type_schema.js +127 -0
  88. package/dist/auth/daemon_token_middleware.d.ts +1 -1
  89. package/dist/auth/daemon_token_middleware.js +3 -3
  90. package/dist/auth/ddl.d.ts +2 -2
  91. package/dist/auth/ddl.d.ts.map +1 -1
  92. package/dist/auth/ddl.js +6 -6
  93. package/dist/auth/deps.d.ts +7 -32
  94. package/dist/auth/deps.d.ts.map +1 -1
  95. package/dist/auth/grant_path_schema.d.ts +117 -0
  96. package/dist/auth/grant_path_schema.d.ts.map +1 -0
  97. package/dist/auth/grant_path_schema.js +137 -0
  98. package/dist/auth/invite_queries.d.ts +12 -1
  99. package/dist/auth/invite_queries.d.ts.map +1 -1
  100. package/dist/auth/invite_queries.js +12 -1
  101. package/dist/auth/invite_schema.d.ts +1 -1
  102. package/dist/auth/invite_schema.d.ts.map +1 -1
  103. package/dist/auth/invite_schema.js +1 -1
  104. package/dist/auth/middleware.d.ts.map +1 -1
  105. package/dist/auth/middleware.js +5 -2
  106. package/dist/auth/migrations.d.ts +22 -7
  107. package/dist/auth/migrations.d.ts.map +1 -1
  108. package/dist/auth/migrations.js +64 -25
  109. package/dist/auth/request_context.d.ts +157 -170
  110. package/dist/auth/request_context.d.ts.map +1 -1
  111. package/dist/auth/request_context.js +224 -268
  112. package/dist/auth/{permit_offer_action_specs.d.ts → role_grant_offer_action_specs.d.ts} +130 -100
  113. package/dist/auth/role_grant_offer_action_specs.d.ts.map +1 -0
  114. package/dist/auth/role_grant_offer_action_specs.js +262 -0
  115. package/dist/auth/role_grant_offer_actions.d.ts +104 -0
  116. package/dist/auth/role_grant_offer_actions.d.ts.map +1 -0
  117. package/dist/auth/{permit_offer_actions.js → role_grant_offer_actions.js} +153 -140
  118. package/dist/auth/{permit_offer_notifications.d.ts → role_grant_offer_notifications.d.ts} +80 -70
  119. package/dist/auth/role_grant_offer_notifications.d.ts.map +1 -0
  120. package/dist/auth/role_grant_offer_notifications.js +182 -0
  121. package/dist/auth/{permit_offer_queries.d.ts → role_grant_offer_queries.d.ts} +64 -64
  122. package/dist/auth/role_grant_offer_queries.d.ts.map +1 -0
  123. package/dist/auth/{permit_offer_queries.js → role_grant_offer_queries.js} +136 -123
  124. package/dist/auth/role_grant_offer_schema.d.ts +150 -0
  125. package/dist/auth/role_grant_offer_schema.d.ts.map +1 -0
  126. package/dist/auth/{permit_offer_schema.js → role_grant_offer_schema.js} +55 -36
  127. package/dist/auth/role_grant_queries.d.ts +231 -0
  128. package/dist/auth/role_grant_queries.d.ts.map +1 -0
  129. package/dist/auth/role_grant_queries.js +320 -0
  130. package/dist/auth/role_schema.d.ts +150 -40
  131. package/dist/auth/role_schema.d.ts.map +1 -1
  132. package/dist/auth/role_schema.js +144 -45
  133. package/dist/auth/scope_kind_schema.d.ts +96 -0
  134. package/dist/auth/scope_kind_schema.d.ts.map +1 -0
  135. package/dist/auth/scope_kind_schema.js +94 -0
  136. package/dist/auth/self_service_role_action_specs.d.ts +4 -1
  137. package/dist/auth/self_service_role_action_specs.d.ts.map +1 -1
  138. package/dist/auth/self_service_role_action_specs.js +2 -2
  139. package/dist/auth/self_service_role_actions.d.ts +35 -29
  140. package/dist/auth/self_service_role_actions.d.ts.map +1 -1
  141. package/dist/auth/self_service_role_actions.js +58 -48
  142. package/dist/auth/session_cookie.d.ts +43 -6
  143. package/dist/auth/session_cookie.d.ts.map +1 -1
  144. package/dist/auth/session_cookie.js +31 -5
  145. package/dist/auth/session_middleware.d.ts +37 -3
  146. package/dist/auth/session_middleware.d.ts.map +1 -1
  147. package/dist/auth/session_middleware.js +33 -7
  148. package/dist/auth/signup_routes.d.ts.map +1 -1
  149. package/dist/auth/signup_routes.js +48 -19
  150. package/dist/auth/standard_action_specs.d.ts +2 -2
  151. package/dist/auth/standard_action_specs.js +4 -4
  152. package/dist/auth/standard_rpc_actions.d.ts +23 -19
  153. package/dist/auth/standard_rpc_actions.d.ts.map +1 -1
  154. package/dist/auth/standard_rpc_actions.js +12 -12
  155. package/dist/db/migrate.d.ts +1 -1
  156. package/dist/db/migrate.js +1 -1
  157. package/dist/dev/setup.d.ts +2 -2
  158. package/dist/dev/setup.d.ts.map +1 -1
  159. package/dist/dev/setup.js +4 -4
  160. package/dist/env/load.d.ts +1 -1
  161. package/dist/env/load.js +1 -1
  162. package/dist/hono_context.d.ts +27 -45
  163. package/dist/hono_context.d.ts.map +1 -1
  164. package/dist/hono_context.js +14 -28
  165. package/dist/http/CLAUDE.md +235 -121
  166. package/dist/http/auth_shape.d.ts +191 -0
  167. package/dist/http/auth_shape.d.ts.map +1 -0
  168. package/dist/http/auth_shape.js +237 -0
  169. package/dist/http/common_routes.js +3 -3
  170. package/dist/http/db_routes.d.ts +4 -0
  171. package/dist/http/db_routes.d.ts.map +1 -1
  172. package/dist/http/db_routes.js +44 -7
  173. package/dist/http/error_schemas.d.ts +72 -39
  174. package/dist/http/error_schemas.d.ts.map +1 -1
  175. package/dist/http/error_schemas.js +81 -33
  176. package/dist/http/pending_effects.d.ts +71 -18
  177. package/dist/http/pending_effects.d.ts.map +1 -1
  178. package/dist/http/pending_effects.js +87 -18
  179. package/dist/http/proxy.d.ts +52 -5
  180. package/dist/http/proxy.d.ts.map +1 -1
  181. package/dist/http/proxy.js +92 -14
  182. package/dist/http/route_spec.d.ts +89 -75
  183. package/dist/http/route_spec.d.ts.map +1 -1
  184. package/dist/http/route_spec.js +54 -72
  185. package/dist/http/schema_helpers.d.ts +3 -14
  186. package/dist/http/schema_helpers.d.ts.map +1 -1
  187. package/dist/http/schema_helpers.js +2 -14
  188. package/dist/http/surface.d.ts +2 -10
  189. package/dist/http/surface.d.ts.map +1 -1
  190. package/dist/http/surface.js +3 -4
  191. package/dist/http/surface_query.d.ts +39 -35
  192. package/dist/http/surface_query.d.ts.map +1 -1
  193. package/dist/http/surface_query.js +79 -36
  194. package/dist/primitive_schemas.d.ts +39 -0
  195. package/dist/primitive_schemas.d.ts.map +1 -0
  196. package/dist/primitive_schemas.js +40 -0
  197. package/dist/realtime/sse_auth_guard.d.ts +5 -5
  198. package/dist/realtime/sse_auth_guard.js +9 -9
  199. package/dist/runtime/mock.d.ts +1 -1
  200. package/dist/runtime/mock.js +1 -1
  201. package/dist/server/app_backend.d.ts +14 -11
  202. package/dist/server/app_backend.d.ts.map +1 -1
  203. package/dist/server/app_backend.js +12 -8
  204. package/dist/server/app_server.d.ts +7 -7
  205. package/dist/server/app_server.d.ts.map +1 -1
  206. package/dist/server/app_server.js +35 -40
  207. package/dist/server/validate_nginx.d.ts +1 -1
  208. package/dist/server/validate_nginx.js +1 -1
  209. package/dist/testing/CLAUDE.md +50 -38
  210. package/dist/testing/admin_integration.d.ts +5 -6
  211. package/dist/testing/admin_integration.d.ts.map +1 -1
  212. package/dist/testing/admin_integration.js +87 -85
  213. package/dist/testing/app_server.d.ts +11 -14
  214. package/dist/testing/app_server.d.ts.map +1 -1
  215. package/dist/testing/app_server.js +16 -15
  216. package/dist/testing/assertions.d.ts.map +1 -1
  217. package/dist/testing/assertions.js +2 -1
  218. package/dist/testing/attack_surface.d.ts.map +1 -1
  219. package/dist/testing/attack_surface.js +15 -9
  220. package/dist/testing/audit_completeness.d.ts +2 -2
  221. package/dist/testing/audit_completeness.d.ts.map +1 -1
  222. package/dist/testing/audit_completeness.js +36 -36
  223. package/dist/testing/auth_apps.d.ts +5 -4
  224. package/dist/testing/auth_apps.d.ts.map +1 -1
  225. package/dist/testing/auth_apps.js +22 -19
  226. package/dist/testing/data_exposure.d.ts.map +1 -1
  227. package/dist/testing/data_exposure.js +5 -5
  228. package/dist/testing/db.d.ts +1 -1
  229. package/dist/testing/db.d.ts.map +1 -1
  230. package/dist/testing/db.js +4 -4
  231. package/dist/testing/db_entities.d.ts +22 -0
  232. package/dist/testing/db_entities.d.ts.map +1 -0
  233. package/dist/testing/db_entities.js +28 -0
  234. package/dist/testing/entities.d.ts +8 -7
  235. package/dist/testing/entities.d.ts.map +1 -1
  236. package/dist/testing/entities.js +21 -18
  237. package/dist/testing/integration.d.ts.map +1 -1
  238. package/dist/testing/integration.js +13 -14
  239. package/dist/testing/integration_helpers.d.ts +4 -4
  240. package/dist/testing/integration_helpers.d.ts.map +1 -1
  241. package/dist/testing/integration_helpers.js +20 -18
  242. package/dist/testing/middleware.d.ts +4 -4
  243. package/dist/testing/middleware.d.ts.map +1 -1
  244. package/dist/testing/middleware.js +12 -11
  245. package/dist/testing/rpc_attack_surface.d.ts.map +1 -1
  246. package/dist/testing/rpc_attack_surface.js +40 -24
  247. package/dist/testing/rpc_round_trip.d.ts +1 -1
  248. package/dist/testing/rpc_round_trip.d.ts.map +1 -1
  249. package/dist/testing/rpc_round_trip.js +14 -13
  250. package/dist/testing/sse_round_trip.d.ts +3 -4
  251. package/dist/testing/sse_round_trip.d.ts.map +1 -1
  252. package/dist/testing/sse_round_trip.js +7 -11
  253. package/dist/testing/standard.d.ts +1 -1
  254. package/dist/testing/stubs.d.ts +25 -0
  255. package/dist/testing/stubs.d.ts.map +1 -1
  256. package/dist/testing/stubs.js +43 -2
  257. package/dist/testing/surface_invariants.d.ts +14 -6
  258. package/dist/testing/surface_invariants.d.ts.map +1 -1
  259. package/dist/testing/surface_invariants.js +119 -43
  260. package/dist/testing/ws_round_trip.d.ts +12 -13
  261. package/dist/testing/ws_round_trip.d.ts.map +1 -1
  262. package/dist/testing/ws_round_trip.js +19 -11
  263. package/dist/ui/AdminAccounts.svelte +23 -20
  264. package/dist/ui/AdminOverview.svelte +15 -13
  265. package/dist/ui/AdminOverview.svelte.d.ts.map +1 -1
  266. package/dist/ui/{AdminPermitHistory.svelte → AdminRoleGrantHistory.svelte} +12 -12
  267. package/dist/ui/AdminRoleGrantHistory.svelte.d.ts +4 -0
  268. package/dist/ui/AdminRoleGrantHistory.svelte.d.ts.map +1 -0
  269. package/dist/ui/BootstrapForm.svelte +1 -1
  270. package/dist/ui/CLAUDE.md +60 -60
  271. package/dist/ui/{PermitOfferForm.svelte → RoleGrantOfferForm.svelte} +27 -26
  272. package/dist/ui/{PermitOfferForm.svelte.d.ts → RoleGrantOfferForm.svelte.d.ts} +7 -7
  273. package/dist/ui/RoleGrantOfferForm.svelte.d.ts.map +1 -0
  274. package/dist/ui/{PermitOfferHistory.svelte → RoleGrantOfferHistory.svelte} +12 -12
  275. package/dist/ui/{PermitOfferHistory.svelte.d.ts → RoleGrantOfferHistory.svelte.d.ts} +4 -4
  276. package/dist/ui/RoleGrantOfferHistory.svelte.d.ts.map +1 -0
  277. package/dist/ui/{PermitOfferInbox.svelte → RoleGrantOfferInbox.svelte} +14 -14
  278. package/dist/ui/{PermitOfferInbox.svelte.d.ts → RoleGrantOfferInbox.svelte.d.ts} +4 -4
  279. package/dist/ui/RoleGrantOfferInbox.svelte.d.ts.map +1 -0
  280. package/dist/ui/SignupForm.svelte +1 -1
  281. package/dist/ui/SurfaceExplorer.svelte +35 -15
  282. package/dist/ui/SurfaceExplorer.svelte.d.ts.map +1 -1
  283. package/dist/ui/account_sessions_state.svelte.d.ts +2 -3
  284. package/dist/ui/account_sessions_state.svelte.d.ts.map +1 -1
  285. package/dist/ui/account_sessions_state.svelte.js +2 -3
  286. package/dist/ui/admin_accounts_state.svelte.d.ts +18 -18
  287. package/dist/ui/admin_accounts_state.svelte.d.ts.map +1 -1
  288. package/dist/ui/admin_accounts_state.svelte.js +16 -16
  289. package/dist/ui/admin_rpc_adapters.d.ts +20 -20
  290. package/dist/ui/admin_rpc_adapters.d.ts.map +1 -1
  291. package/dist/ui/admin_rpc_adapters.js +17 -17
  292. package/dist/ui/admin_sessions_state.svelte.d.ts +2 -2
  293. package/dist/ui/admin_sessions_state.svelte.js +2 -2
  294. package/dist/ui/audit_log_state.svelte.d.ts +7 -7
  295. package/dist/ui/audit_log_state.svelte.d.ts.map +1 -1
  296. package/dist/ui/audit_log_state.svelte.js +6 -6
  297. package/dist/ui/auth_state.svelte.d.ts +3 -3
  298. package/dist/ui/auth_state.svelte.d.ts.map +1 -1
  299. package/dist/ui/auth_state.svelte.js +6 -6
  300. package/dist/ui/format_scope.d.ts +2 -2
  301. package/dist/ui/format_scope.js +2 -2
  302. package/dist/ui/{permit_offers_state.svelte.d.ts → role_grant_offers_state.svelte.d.ts} +30 -30
  303. package/dist/ui/role_grant_offers_state.svelte.d.ts.map +1 -0
  304. package/dist/ui/{permit_offers_state.svelte.js → role_grant_offers_state.svelte.js} +18 -18
  305. package/dist/ui/ui_format.js +2 -2
  306. package/package.json +3 -3
  307. package/dist/auth/permit_offer_action_specs.d.ts.map +0 -1
  308. package/dist/auth/permit_offer_action_specs.js +0 -258
  309. package/dist/auth/permit_offer_actions.d.ts +0 -110
  310. package/dist/auth/permit_offer_actions.d.ts.map +0 -1
  311. package/dist/auth/permit_offer_notifications.d.ts.map +0 -1
  312. package/dist/auth/permit_offer_notifications.js +0 -182
  313. package/dist/auth/permit_offer_queries.d.ts.map +0 -1
  314. package/dist/auth/permit_offer_schema.d.ts +0 -125
  315. package/dist/auth/permit_offer_schema.d.ts.map +0 -1
  316. package/dist/auth/permit_queries.d.ts +0 -222
  317. package/dist/auth/permit_queries.d.ts.map +0 -1
  318. package/dist/auth/permit_queries.js +0 -305
  319. package/dist/auth/require_keeper.d.ts +0 -20
  320. package/dist/auth/require_keeper.d.ts.map +0 -1
  321. package/dist/auth/require_keeper.js +0 -35
  322. package/dist/auth/route_guards.d.ts +0 -27
  323. package/dist/auth/route_guards.d.ts.map +0 -1
  324. package/dist/auth/route_guards.js +0 -38
  325. package/dist/auth/session_lifecycle.d.ts +0 -37
  326. package/dist/auth/session_lifecycle.d.ts.map +0 -1
  327. package/dist/auth/session_lifecycle.js +0 -29
  328. package/dist/ui/AdminPermitHistory.svelte.d.ts +0 -4
  329. package/dist/ui/AdminPermitHistory.svelte.d.ts.map +0 -1
  330. package/dist/ui/PermitOfferForm.svelte.d.ts.map +0 -1
  331. package/dist/ui/PermitOfferHistory.svelte.d.ts.map +0 -1
  332. package/dist/ui/PermitOfferInbox.svelte.d.ts.map +0 -1
  333. package/dist/ui/permit_offers_state.svelte.d.ts.map +0 -1
@@ -23,7 +23,7 @@ import { assert_surface_matches_snapshot, assert_surface_deterministic, assert_o
23
23
  import { merge_error_schemas } from '../http/schema_helpers.js';
24
24
  import { collect_middleware_errors } from '../http/surface.js';
25
25
  import { filter_protected_routes, filter_role_routes, filter_keeper_routes, } from '../http/surface_query.js';
26
- import { ERROR_AUTHENTICATION_REQUIRED, ERROR_INSUFFICIENT_PERMISSIONS, ERROR_KEEPER_REQUIRES_DAEMON_TOKEN, } from '../http/error_schemas.js';
26
+ import { ERROR_AUTHENTICATION_REQUIRED, ERROR_INSUFFICIENT_PERMISSIONS, ERROR_CREDENTIAL_TYPE_REQUIRED, } from '../http/error_schemas.js';
27
27
  // --- Adversarial test runner ---
28
28
  /**
29
29
  * Build a lookup from `"METHOD /path"` to merged error schemas (auto-derived + middleware + explicit).
@@ -79,12 +79,17 @@ export const describe_adversarial_auth = (options) => {
79
79
  });
80
80
  }
81
81
  });
82
- if (role_routes.length > 0) {
82
+ // Role-only routes (no credential gate). Keeper routes have a credential
83
+ // gate that fires before the role gate, so they get tested separately
84
+ // in the keeper block below.
85
+ const role_only_routes = role_routes.filter((r) => !(r.auth.credential_types?.length ?? 0));
86
+ if (role_only_routes.length > 0) {
83
87
  describe('wrong role → 403', () => {
84
- for (const route of role_routes) {
85
- const wrong_roles = roles.filter((r) => r !== route.auth.role);
88
+ for (const route of role_only_routes) {
89
+ const required_roles = route.auth.roles ?? [];
90
+ const wrong_roles = roles.filter((r) => !required_roles.includes(r));
86
91
  for (const wrong_role of wrong_roles) {
87
- test(`${route.method} ${route.path} (${wrong_role} instead of ${route.auth.role})`, async () => {
92
+ test(`${route.method} ${route.path} (${wrong_role} instead of ${required_roles.join('|')})`, async () => {
88
93
  const app = apps.by_role.get(wrong_role);
89
94
  if (!app)
90
95
  throw new Error(`No test app for role '${wrong_role}'`);
@@ -94,14 +99,14 @@ export const describe_adversarial_auth = (options) => {
94
99
  assert.strictEqual(res.status, 403, `${route.method} ${route.path}`);
95
100
  const body = await res.json();
96
101
  assert.strictEqual(body.error, ERROR_INSUFFICIENT_PERMISSIONS);
97
- assert.strictEqual(body.required_role, route.auth.role);
102
+ assert.deepStrictEqual(body.required_roles, required_roles);
98
103
  assert_error_schema_valid(error_schema_lookup, route, 403, body);
99
104
  });
100
105
  }
101
106
  }
102
107
  });
103
108
  describe('authenticated without role → 403', () => {
104
- for (const route of role_routes) {
109
+ for (const route of role_only_routes) {
105
110
  test(`${route.method} ${route.path}`, async () => {
106
111
  const res = await apps.authed.request(resolve_test_path(route.path), {
107
112
  method: route.method,
@@ -109,7 +114,7 @@ export const describe_adversarial_auth = (options) => {
109
114
  assert.strictEqual(res.status, 403, `${route.method} ${route.path}`);
110
115
  const body = await res.json();
111
116
  assert.strictEqual(body.error, ERROR_INSUFFICIENT_PERMISSIONS);
112
- assert.strictEqual(body.required_role, route.auth.role);
117
+ assert.deepStrictEqual(body.required_roles, route.auth.roles ?? []);
113
118
  assert_error_schema_valid(error_schema_lookup, route, 403, body);
114
119
  });
115
120
  }
@@ -126,7 +131,8 @@ export const describe_adversarial_auth = (options) => {
126
131
  });
127
132
  assert.strictEqual(res.status, 403, `${route.method} ${route.path}`);
128
133
  const body = await res.json();
129
- assert.strictEqual(body.error, ERROR_KEEPER_REQUIRES_DAEMON_TOKEN);
134
+ assert.strictEqual(body.error, ERROR_CREDENTIAL_TYPE_REQUIRED);
135
+ assert.deepStrictEqual(body.required_credential_types, route.auth.credential_types ?? []);
130
136
  assert_error_schema_valid(error_schema_lookup, route, 403, body);
131
137
  });
132
138
  }
@@ -15,7 +15,7 @@ export interface AuditCompletenessTestOptions {
15
15
  create_route_specs: (ctx: AppServerContext) => Array<RouteSpec>;
16
16
  /**
17
17
  * RPC endpoint specs — the source `RpcAction` arrays. Required; the
18
- * admin permit flow is RPC-only and the suite hard-fails without it.
18
+ * admin role_grant flow is RPC-only and the suite hard-fails without it.
19
19
  *
20
20
  * Accepts either an array (eager) or a factory
21
21
  * `(ctx: AppServerContext) => Array<RpcEndpointSpec>` — the factory form
@@ -39,7 +39,7 @@ export interface AuditCompletenessTestOptions {
39
39
  * database, then queries the `audit_log` table to verify events.
40
40
  *
41
41
  * @throws Error at setup time when `options.rpc_endpoints` is empty — the
42
- * mutation-audit tests drive permit flow, session/token revoke-all, and
42
+ * mutation-audit tests drive role_grant flow, session/token revoke-all, and
43
43
  * invite create/delete through their RPC action specs. Hard-fails via
44
44
  * `require_rpc_endpoint_path`.
45
45
  */
@@ -1 +1 @@
1
- {"version":3,"file":"audit_completeness.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/audit_completeness.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAkB7B,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAC;AAIrD,OAAO,EAGN,KAAK,eAAe,EAEpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAIN,KAAK,SAAS,EACd,MAAM,SAAS,CAAC;AAKjB,OAAO,EAIN,KAAK,uBAAuB,EAC5B,MAAM,kBAAkB,CAAC;AAqB1B;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC5C,4CAA4C;IAC5C,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,wDAAwD;IACxD,kBAAkB,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IAChE;;;;;;;;;;;OAWG;IACH,aAAa,EAAE,uBAAuB,CAAC;IACvC,iDAAiD;IACjD,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,qEAAqE;IACrE,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;CAChC;AAoDD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iCAAiC,GAAI,SAAS,4BAA4B,KAAG,IA8fzF,CAAC"}
1
+ {"version":3,"file":"audit_completeness.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/audit_completeness.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAkB7B,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAC;AAIrD,OAAO,EAGN,KAAK,eAAe,EAEpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAIN,KAAK,SAAS,EACd,MAAM,SAAS,CAAC;AAKjB,OAAO,EAIN,KAAK,uBAAuB,EAC5B,MAAM,kBAAkB,CAAC;AAqB1B;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC5C,4CAA4C;IAC5C,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,wDAAwD;IACxD,kBAAkB,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IAChE;;;;;;;;;;;OAWG;IACH,aAAa,EAAE,uBAAuB,CAAC;IACvC,iDAAiD;IACjD,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,qEAAqE;IACrE,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;CAChC;AAoDD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iCAAiC,GAAI,SAAS,4BAA4B,KAAG,IAkgBzF,CAAC"}
@@ -20,9 +20,9 @@ import { create_test_app, } from './app_server.js';
20
20
  import { create_pglite_factory, create_describe_db, AUTH_INTEGRATION_TRUNCATE_TABLES, } from './db.js';
21
21
  import { find_auth_route } from './integration_helpers.js';
22
22
  import { run_migrations } from '../db/migrate.js';
23
- import { query_accept_offer } from '../auth/permit_offer_queries.js';
23
+ import { query_accept_offer } from '../auth/role_grant_offer_queries.js';
24
24
  import { rpc_call_for_spec, require_rpc_endpoint_path, resolve_rpc_endpoints_for_setup, } from './rpc_helpers.js';
25
- import { permit_offer_create_action_spec, permit_revoke_action_spec, } from '../auth/permit_offer_action_specs.js';
25
+ import { role_grant_offer_create_action_spec, role_grant_revoke_action_spec, } from '../auth/role_grant_offer_action_specs.js';
26
26
  import { admin_session_revoke_all_action_spec, admin_token_revoke_all_action_spec, app_settings_update_action_spec, invite_create_action_spec, invite_delete_action_spec, } from '../auth/admin_action_specs.js';
27
27
  import { account_session_list_action_spec, account_session_revoke_action_spec, account_session_revoke_all_action_spec, account_token_create_action_spec, account_token_list_action_spec, account_token_revoke_action_spec, } from '../auth/account_action_specs.js';
28
28
  /** Query audit log events from the database. */
@@ -63,7 +63,7 @@ const json_session_headers = (test_app, extra) => test_app.create_session_header
63
63
  * database, then queries the `audit_log` table to verify events.
64
64
  *
65
65
  * @throws Error at setup time when `options.rpc_endpoints` is empty — the
66
- * mutation-audit tests drive permit flow, session/token revoke-all, and
66
+ * mutation-audit tests drive role_grant flow, session/token revoke-all, and
67
67
  * invite create/delete through their RPC action specs. Hard-fails via
68
68
  * `require_rpc_endpoint_path`.
69
69
  */
@@ -231,23 +231,23 @@ export const describe_audit_completeness_tests = (options) => {
231
231
  });
232
232
  // --- Admin routes ---
233
233
  describe('admin mutation audit events', () => {
234
- test('admin offer (RPC) + accept produces permit_offer_create and permit_grant events', async () => {
234
+ test('admin offer (RPC) + accept produces role_grant_offer_create and role_grant_create events', async () => {
235
235
  const test_app = await create_test_app(build_options(options, get_db()));
236
236
  const target = await test_app.create_account({ username: 'audit_target' });
237
237
  const offer_res = await rpc_call_for_spec({
238
238
  app: test_app.app,
239
239
  path: rpc_path,
240
- spec: permit_offer_create_action_spec,
240
+ spec: role_grant_offer_create_action_spec,
241
241
  params: { to_account_id: target.account.id, role: ROLE_ADMIN },
242
242
  headers: test_app.create_session_headers(),
243
243
  });
244
- assert.ok(offer_res.ok, `permit_offer_create failed: ${offer_res.ok ? '' : JSON.stringify(offer_res.error)}`);
244
+ assert.ok(offer_res.ok, `role_grant_offer_create failed: ${offer_res.ok ? '' : JSON.stringify(offer_res.error)}`);
245
245
  const { offer } = offer_res.result;
246
- // Admin offer emits `permit_offer_create` only — the permit doesn't
247
- // exist yet. Drive the accept to confirm `permit_grant` fires on the
246
+ // Admin offer emits `role_grant_offer_create` only — the role_grant doesn't
247
+ // exist yet. Drive the accept to confirm `role_grant_create` fires on the
248
248
  // downstream consent transition.
249
249
  const events_after_offer = await query_audit_events(test_app.backend.deps.db);
250
- assert_has_event(events_after_offer, 'permit_offer_create', 'permit_offer_create RPC');
250
+ assert_has_event(events_after_offer, 'role_grant_offer_create', 'role_grant_offer_create RPC');
251
251
  await get_db().transaction(async (tx) => {
252
252
  await query_accept_offer({ db: tx }, {
253
253
  offer_id: offer.id,
@@ -257,20 +257,20 @@ export const describe_audit_completeness_tests = (options) => {
257
257
  });
258
258
  });
259
259
  const events_after_accept = await query_audit_events(test_app.backend.deps.db);
260
- assert_has_event(events_after_accept, 'permit_grant', 'offer accept');
260
+ assert_has_event(events_after_accept, 'role_grant_create', 'offer accept');
261
261
  });
262
- test('permit revoke (RPC) produces permit_revoke event with both target columns', async () => {
262
+ test('role_grant revoke (RPC) produces role_grant_revoke event with both target columns', async () => {
263
263
  const test_app = await create_test_app(build_options(options, get_db()));
264
264
  const target = await test_app.create_account({ username: 'audit_revoke_target' });
265
- // Offer + accept to materialize a permit we can revoke.
265
+ // Offer + accept to materialize a role_grant we can revoke.
266
266
  const offer_res = await rpc_call_for_spec({
267
267
  app: test_app.app,
268
268
  path: rpc_path,
269
- spec: permit_offer_create_action_spec,
269
+ spec: role_grant_offer_create_action_spec,
270
270
  params: { to_account_id: target.account.id, role: ROLE_ADMIN },
271
271
  headers: test_app.create_session_headers(),
272
272
  });
273
- assert.ok(offer_res.ok, `permit_offer_create failed: ${offer_res.ok ? '' : JSON.stringify(offer_res.error)}`);
273
+ assert.ok(offer_res.ok, `role_grant_offer_create failed: ${offer_res.ok ? '' : JSON.stringify(offer_res.error)}`);
274
274
  const { offer } = offer_res.result;
275
275
  const accept_result = await get_db().transaction(async (tx) => {
276
276
  return query_accept_offer({ db: tx }, {
@@ -284,17 +284,17 @@ export const describe_audit_completeness_tests = (options) => {
284
284
  const revoke_res = await rpc_call_for_spec({
285
285
  app: test_app.app,
286
286
  path: rpc_path,
287
- spec: permit_revoke_action_spec,
288
- params: { actor_id: target.actor.id, permit_id: accept_result.permit.id },
287
+ spec: role_grant_revoke_action_spec,
288
+ params: { actor_id: target.actor.id, role_grant_id: accept_result.role_grant.id },
289
289
  headers: test_app.create_session_headers(),
290
290
  });
291
- assert.ok(revoke_res.ok, `permit_revoke failed: ${revoke_res.ok ? '' : JSON.stringify(revoke_res.error)}`);
291
+ assert.ok(revoke_res.ok, `role_grant_revoke failed: ${revoke_res.ok ? '' : JSON.stringify(revoke_res.error)}`);
292
292
  const events = await query_audit_events(test_app.backend.deps.db);
293
- assert_has_event(events, 'permit_revoke', 'permit_revoke RPC');
293
+ assert_has_event(events, 'role_grant_revoke', 'role_grant_revoke RPC');
294
294
  // Audit envelope must populate both target columns —
295
- // `permit_revoke` is the canonical actor-bound-subject event.
295
+ // `role_grant_revoke` is the canonical actor-bound-subject event.
296
296
  const revoke_rows = await test_app.backend.deps.db.query(`SELECT target_account_id, target_actor_id FROM audit_log
297
- WHERE event_type = 'permit_revoke' ORDER BY seq DESC LIMIT 1`);
297
+ WHERE event_type = 'role_grant_revoke' ORDER BY seq DESC LIMIT 1`);
298
298
  const row = revoke_rows[0];
299
299
  assert.strictEqual(row.target_account_id, target.account.id);
300
300
  assert.strictEqual(row.target_actor_id, target.actor.id);
@@ -416,9 +416,9 @@ export const describe_audit_completeness_tests = (options) => {
416
416
  'token_create',
417
417
  'token_revoke',
418
418
  'token_revoke_all',
419
- 'permit_offer_create',
420
- 'permit_grant',
421
- 'permit_revoke',
419
+ 'role_grant_offer_create',
420
+ 'role_grant_create',
421
+ 'role_grant_revoke',
422
422
  'invite_create',
423
423
  'invite_delete',
424
424
  'app_settings_update',
@@ -426,20 +426,20 @@ export const describe_audit_completeness_tests = (options) => {
426
426
  /** Event types excluded with justification. */
427
427
  const EXCLUDED_EVENT_TYPES = new Set([
428
428
  'bootstrap', // requires filesystem token — tested in bootstrap_account.db.test.ts
429
- // The remaining `permit_offer_*` events fire only via the RPC
430
- // endpoint or via downstream effects of `permit_revoke`. Direct
431
- // coverage lives in `permit_offer_queries.db.test.ts`,
432
- // `permit_offer_actions.db.test.ts`,
433
- // `permit_offer_actions.notifications.db.test.ts`, and
434
- // `permit_offer_actions.notifications.revoke.db.test.ts`.
435
- // `permit_offer_expire` fires from the cleanup sweep
436
- // (`cleanup_expired_permit_offers` in `auth/cleanup.ts`) —
429
+ // The remaining `role_grant_offer_*` events fire only via the RPC
430
+ // endpoint or via downstream effects of `role_grant_revoke`. Direct
431
+ // coverage lives in `role_grant_offer_queries.db.test.ts`,
432
+ // `role_grant_offer_actions.db.test.ts`,
433
+ // `role_grant_offer_actions.notifications.db.test.ts`, and
434
+ // `role_grant_offer_actions.notifications.revoke.db.test.ts`.
435
+ // `role_grant_offer_expire` fires from the cleanup sweep
436
+ // (`cleanup_expired_role_grant_offers` in `auth/cleanup.ts`) —
437
437
  // covered in `cleanup.db.test.ts`.
438
- 'permit_offer_accept',
439
- 'permit_offer_decline',
440
- 'permit_offer_retract',
441
- 'permit_offer_expire',
442
- 'permit_offer_supersede',
438
+ 'role_grant_offer_accept',
439
+ 'role_grant_offer_decline',
440
+ 'role_grant_offer_retract',
441
+ 'role_grant_offer_expire',
442
+ 'role_grant_offer_supersede',
443
443
  ]);
444
444
  test('all audit event types are covered or explicitly excluded', () => {
445
445
  const all_covered = new Set([...COVERED_EVENT_TYPES, ...EXCLUDED_EVENT_TYPES]);
@@ -8,11 +8,12 @@ import './assert_dev_env.js';
8
8
  * @module
9
9
  */
10
10
  import { Hono } from 'hono';
11
- import { type RouteSpec, type RouteAuth } from '../http/route_spec.js';
11
+ import { type RouteSpec } from '../http/route_spec.js';
12
+ import { type RouteAuth } from '../http/auth_shape.js';
12
13
  import { type RequestContext } from '../auth/request_context.js';
13
14
  import { type CredentialType } from '../hono_context.js';
14
15
  /**
15
- * Create a mock `RequestContext` with optional role permit.
16
+ * Create a mock `RequestContext` with optional role role_grant.
16
17
  */
17
18
  export declare const create_test_request_context: (role?: string) => RequestContext;
18
19
  /**
@@ -40,8 +41,8 @@ export declare const create_auth_test_apps: (route_specs: Array<RouteSpec>, role
40
41
  /**
41
42
  * Select the Hono test app with correct auth for a route.
42
43
  *
43
- * @throws Error if `auth.type === 'role'` and `auth.role` is not present in
44
- * `apps.by_role` — surfaces a missing entry in the `roles` array passed to
44
+ * @throws Error if `auth.roles` names a role not present in `apps.by_role` —
45
+ * surfaces a missing entry in the `roles` array passed to
45
46
  * `create_auth_test_apps`.
46
47
  */
47
48
  export declare const select_auth_app: (apps: AuthTestApps, auth: RouteAuth) => Hono;
@@ -1 +1 @@
1
- {"version":3,"file":"auth_apps.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/auth_apps.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAE7B;;;;;;;GAOG;AAEH,OAAO,EAAC,IAAI,EAAC,MAAM,MAAM,CAAC;AAG1B,OAAO,EAAoB,KAAK,SAAS,EAAE,KAAK,SAAS,EAAC,MAAM,uBAAuB,CAAC;AAExF,OAAO,EAGN,KAAK,cAAc,EACnB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAIN,KAAK,cAAc,EACnB,MAAM,oBAAoB,CAAC;AAI5B;;GAEG;AACH,eAAO,MAAM,2BAA2B,GAAI,OAAO,MAAM,KAAG,cAI1D,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,GACtC,aAAa,KAAK,CAAC,SAAS,CAAC,EAC7B,WAAW,cAAc,EACzB,kBAAkB,cAAc,KAC9B,IAsBF,CAAC;AAEF,sFAAsF;AACtF,MAAM,WAAW,YAAY;IAC5B,MAAM,EAAE,IAAI,CAAC;IACb,MAAM,EAAE,IAAI,CAAC;IACb,MAAM,EAAE,IAAI,CAAC;IACb,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;CAC3B;AAED;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,GACjC,aAAa,KAAK,CAAC,SAAS,CAAC,EAC7B,OAAO,KAAK,CAAC,MAAM,CAAC,KAClB,YAeF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,GAAI,MAAM,YAAY,EAAE,MAAM,SAAS,KAAG,IAcrE,CAAC;AAEF,6EAA6E;AAC7E,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,KAAG,MAA4C,CAAC"}
1
+ {"version":3,"file":"auth_apps.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/auth_apps.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAE7B;;;;;;;GAOG;AAEH,OAAO,EAAC,IAAI,EAAC,MAAM,MAAM,CAAC;AAG1B,OAAO,EAAoB,KAAK,SAAS,EAAC,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAiB,KAAK,SAAS,EAAC,MAAM,uBAAuB,CAAC;AAErE,OAAO,EAGN,KAAK,cAAc,EACnB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAIN,KAAK,cAAc,EACnB,MAAM,oBAAoB,CAAC;AAI5B;;GAEG;AACH,eAAO,MAAM,2BAA2B,GAAI,OAAO,MAAM,KAAG,cAI1D,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,GACtC,aAAa,KAAK,CAAC,SAAS,CAAC,EAC7B,WAAW,cAAc,EACzB,kBAAkB,cAAc,KAC9B,IAuBF,CAAC;AAEF,sFAAsF;AACtF,MAAM,WAAW,YAAY;IAC5B,MAAM,EAAE,IAAI,CAAC;IACb,MAAM,EAAE,IAAI,CAAC;IACb,MAAM,EAAE,IAAI,CAAC;IACb,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;CAC3B;AAED;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,GACjC,aAAa,KAAK,CAAC,SAAS,CAAC,EAC7B,OAAO,KAAK,CAAC,MAAM,CAAC,KAClB,YAeF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,GAAI,MAAM,YAAY,EAAE,MAAM,SAAS,KAAG,IAarE,CAAC;AAEF,6EAA6E;AAC7E,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,KAAG,MAA4C,CAAC"}
@@ -10,18 +10,19 @@ import './assert_dev_env.js';
10
10
  import { Hono } from 'hono';
11
11
  import { Logger } from '@fuzdev/fuz_util/log.js';
12
12
  import { apply_route_specs } from '../http/route_spec.js';
13
- import { fuz_auth_guard_resolver } from '../auth/route_guards.js';
13
+ import { is_public_auth } from '../http/auth_shape.js';
14
+ import { fuz_auth_guard_resolver } from '../auth/auth_guard_resolver.js';
14
15
  import { REQUEST_CONTEXT_KEY, create_fuz_authorization_handler, } from '../auth/request_context.js';
15
16
  import { ACCOUNT_ID_KEY, CREDENTIAL_TYPE_KEY, TEST_CONTEXT_PRESET_KEY, } from '../hono_context.js';
16
17
  import { create_stub_db } from './stubs.js';
17
- import { create_test_account, create_test_actor, create_test_permit } from './entities.js';
18
+ import { create_test_account, create_test_actor, create_test_role_grant } from './entities.js';
18
19
  /**
19
- * Create a mock `RequestContext` with optional role permit.
20
+ * Create a mock `RequestContext` with optional role role_grant.
20
21
  */
21
22
  export const create_test_request_context = (role) => ({
22
23
  account: create_test_account({ id: 'acc_1', username: 'testuser' }),
23
24
  actor: create_test_actor({ id: 'act_1', account_id: 'acc_1', name: 'testuser' }),
24
- permits: role ? [create_test_permit({ id: 'perm_1', actor_id: 'act_1', role })] : [],
25
+ role_grants: role ? [create_test_role_grant({ id: 'perm_1', actor_id: 'act_1', role })] : [],
25
26
  });
26
27
  /**
27
28
  * Create a Hono test app from route specs with optional auth context.
@@ -35,6 +36,7 @@ export const create_test_app_from_specs = (route_specs, auth_ctx, credential_typ
35
36
  const db = create_stub_db();
36
37
  app.use('/*', async (c, next) => {
37
38
  c.set('pending_effects', []);
39
+ c.set('post_commit_effects', []);
38
40
  if (auth_ctx) {
39
41
  c.set(ACCOUNT_ID_KEY, auth_ctx.account.id);
40
42
  c.set(REQUEST_CONTEXT_KEY, auth_ctx);
@@ -67,25 +69,26 @@ export const create_auth_test_apps = (route_specs, roles) => {
67
69
  /**
68
70
  * Select the Hono test app with correct auth for a route.
69
71
  *
70
- * @throws Error if `auth.type === 'role'` and `auth.role` is not present in
71
- * `apps.by_role` — surfaces a missing entry in the `roles` array passed to
72
+ * @throws Error if `auth.roles` names a role not present in `apps.by_role` —
73
+ * surfaces a missing entry in the `roles` array passed to
72
74
  * `create_auth_test_apps`.
73
75
  */
74
76
  export const select_auth_app = (apps, auth) => {
75
- switch (auth.type) {
76
- case 'none':
77
- return apps.public;
78
- case 'authenticated':
79
- return apps.authed;
80
- case 'keeper':
81
- return apps.keeper;
82
- case 'role': {
83
- const app = apps.by_role.get(auth.role);
84
- if (!app)
85
- throw new Error(`No test app for role '${auth.role}' — is it in the roles array?`);
86
- return app;
87
- }
77
+ if (is_public_auth(auth))
78
+ return apps.public;
79
+ if (auth.credential_types?.includes('daemon_token'))
80
+ return apps.keeper;
81
+ if (auth.roles?.length) {
82
+ // Multi-role disjunction: any of the named roles admits the caller.
83
+ // Tests pick the first role's app; consumers wanting per-role coverage
84
+ // should hit each role's app explicitly.
85
+ const role = auth.roles[0];
86
+ const app = apps.by_role.get(role);
87
+ if (!app)
88
+ throw new Error(`No test app for role '${role}' — is it in the roles array?`);
89
+ return app;
88
90
  }
91
+ return apps.authed;
89
92
  };
90
93
  /** Replace Hono route params (`:foo`) with dummy values for HTTP testing. */
91
94
  export const resolve_test_path = (path) => path.replace(/:(\w+)/g, 'test_$1');
@@ -1 +1 @@
1
- {"version":3,"file":"data_exposure.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/data_exposure.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAgB7B,OAAO,KAAK,EAAC,UAAU,EAAE,cAAc,EAAC,MAAM,oBAAoB,CAAC;AACnE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAC,gBAAgB,EAAE,gBAAgB,EAAC,MAAM,yBAAyB,CAAC;AAChF,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAG9D,OAAO,EAAwB,KAAK,SAAS,EAAC,MAAM,SAAS,CAAC;AAe9D;;;;;GAKG;AACH,eAAO,MAAM,kCAAkC,GAAI,QAAQ,OAAO,KAAG,GAAG,CAAC,MAAM,CAuB9E,CAAC;AAIF;;GAEG;AACH,eAAO,MAAM,yCAAyC,GACrD,SAAS,UAAU,EACnB,mBAAkB,aAAa,CAAC,MAAM,CAA6B,KACjE,IAWF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wCAAwC,GACpD,SAAS,UAAU,EACnB,oBAAmB,aAAa,CAAC,MAAM,CAA8B,KACnE,IAcF,CAAC;AAIF,kDAAkD;AAClD,MAAM,WAAW,uBAAuB;IACvC,4DAA4D;IAC5D,KAAK,EAAE,MAAM,cAAc,CAAC;IAC5B,wCAAwC;IACxC,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,4CAA4C;IAC5C,kBAAkB,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IAChE,2FAA2F;IAC3F,gBAAgB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACzC,iGAAiG;IACjG,iBAAiB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC1C,iDAAiD;IACjD,WAAW,CAAC,EAAE,OAAO,CACpB,IAAI,CAAC,gBAAgB,EAAE,SAAS,GAAG,iBAAiB,GAAG,oBAAoB,CAAC,CAC5E,CAAC;IACF,qEAAqE;IACrE,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAChC,kDAAkD;IAClD,WAAW,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CAC5B;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,4BAA4B,GAAI,SAAS,uBAAuB,KAAG,IAmC/E,CAAC"}
1
+ {"version":3,"file":"data_exposure.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/data_exposure.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAgB7B,OAAO,KAAK,EAAC,UAAU,EAAE,cAAc,EAAC,MAAM,oBAAoB,CAAC;AACnE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAC,gBAAgB,EAAE,gBAAgB,EAAC,MAAM,yBAAyB,CAAC;AAChF,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAG9D,OAAO,EAAwB,KAAK,SAAS,EAAC,MAAM,SAAS,CAAC;AAgB9D;;;;;GAKG;AACH,eAAO,MAAM,kCAAkC,GAAI,QAAQ,OAAO,KAAG,GAAG,CAAC,MAAM,CAuB9E,CAAC;AAIF;;GAEG;AACH,eAAO,MAAM,yCAAyC,GACrD,SAAS,UAAU,EACnB,mBAAkB,aAAa,CAAC,MAAM,CAA6B,KACjE,IAWF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wCAAwC,GACpD,SAAS,UAAU,EACnB,oBAAmB,aAAa,CAAC,MAAM,CAA8B,KACnE,IAcF,CAAC;AAIF,kDAAkD;AAClD,MAAM,WAAW,uBAAuB;IACvC,4DAA4D;IAC5D,KAAK,EAAE,MAAM,cAAc,CAAC;IAC5B,wCAAwC;IACxC,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,4CAA4C;IAC5C,kBAAkB,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IAChE,2FAA2F;IAC3F,gBAAgB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACzC,iGAAiG;IACjG,iBAAiB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC1C,iDAAiD;IACjD,WAAW,CAAC,EAAE,OAAO,CACpB,IAAI,CAAC,gBAAgB,EAAE,SAAS,GAAG,iBAAiB,GAAG,oBAAoB,CAAC,CAC5E,CAAC;IACF,qEAAqE;IACrE,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAChC,kDAAkD;IAClD,WAAW,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CAC5B;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,4BAA4B,GAAI,SAAS,uBAAuB,KAAG,IAmC/E,CAAC"}
@@ -18,6 +18,7 @@ import { resolve_valid_path, generate_valid_body } from './schema_generators.js'
18
18
  import { run_migrations } from '../db/migrate.js';
19
19
  import { AUTH_MIGRATION_NS } from '../auth/migrations.js';
20
20
  import { is_null_schema, is_strict_object_schema } from '../http/schema_helpers.js';
21
+ import { is_keeper_auth, is_public_auth } from '../http/auth_shape.js';
21
22
  import { SENSITIVE_FIELD_BLOCKLIST, ADMIN_ONLY_FIELD_BLOCKLIST, assert_no_sensitive_fields_in_json, pick_auth_headers, } from './integration_helpers.js';
22
23
  // --- Schema introspection ---
23
24
  /**
@@ -71,7 +72,7 @@ export const assert_output_schemas_no_sensitive_fields = (surface, sensitive_fie
71
72
  * Assert that non-admin route output schemas don't contain admin-only fields.
72
73
  */
73
74
  export const assert_non_admin_schemas_no_admin_fields = (surface, admin_only_fields = ADMIN_ONLY_FIELD_BLOCKLIST) => {
74
- const non_admin = surface.routes.filter((r) => r.auth.type !== 'keeper' && !(r.auth.type === 'role' && r.auth.role === 'admin'));
75
+ const non_admin = surface.routes.filter((r) => !is_keeper_auth(r.auth) && !(r.auth.roles?.includes('admin') ?? false));
75
76
  for (const route of non_admin) {
76
77
  if (route.output_schema === null)
77
78
  continue;
@@ -154,7 +155,7 @@ const describe_data_exposure_runtime_tests = (options) => {
154
155
  // Tests that don't fire authenticated requests run first — they don't
155
156
  // invalidate sessions and are independent of test order.
156
157
  test('unauthenticated error responses contain no sensitive fields', async () => {
157
- const protected_specs = test_app.route_specs.filter((s) => s.auth.type !== 'none');
158
+ const protected_specs = test_app.route_specs.filter((s) => !is_public_auth(s.auth));
158
159
  for (const spec of protected_specs) {
159
160
  const route_key = `${spec.method} ${spec.path}`;
160
161
  if (skip_set.has(route_key))
@@ -181,7 +182,7 @@ const describe_data_exposure_runtime_tests = (options) => {
181
182
  // Cross-privilege test runs before 2xx tests — admin routes reject
182
183
  // without calling handlers, so sessions stay intact.
183
184
  test('admin routes return 403 for non-admin user', async () => {
184
- const admin_specs = test_app.route_specs.filter((s) => s.auth.type === 'role' && s.auth.role === 'admin');
185
+ const admin_specs = test_app.route_specs.filter((s) => s.auth.roles?.includes('admin') ?? false);
185
186
  for (const spec of admin_specs) {
186
187
  const route_key = `${spec.method} ${spec.path}`;
187
188
  if (skip_set.has(route_key))
@@ -221,8 +222,7 @@ const describe_data_exposure_runtime_tests = (options) => {
221
222
  if (skip_set.has(route_key))
222
223
  continue;
223
224
  // keeper auth (daemon token) is strictly more privileged than admin
224
- const is_elevated = spec.auth.type === 'keeper' ||
225
- (spec.auth.type === 'role' && spec.auth.role === 'admin');
225
+ const is_elevated = is_keeper_auth(spec.auth) || (spec.auth.roles?.includes('admin') ?? false);
226
226
  const url = resolve_valid_path(spec.path, spec.params);
227
227
  const body = generate_valid_body(spec.input);
228
228
  const headers = pick_auth_headers(spec, test_app, authed_account, admin_account);
@@ -79,7 +79,7 @@ export declare const AUTH_INTEGRATION_TRUNCATE_TABLES: string[];
79
79
  *
80
80
  * When adding tables to `AUTH_MIGRATIONS`, add them here too.
81
81
  */
82
- export declare const AUTH_DROP_TABLES: readonly ["app_settings", "invite", "audit_log", "api_token", "auth_session", "permit", "permit_offer", "actor", "account", "bootstrap_lock"];
82
+ export declare const AUTH_DROP_TABLES: readonly ["app_settings", "invite", "audit_log", "api_token", "auth_session", "role_grant", "role_grant_offer", "actor", "account", "bootstrap_lock"];
83
83
  /**
84
84
  * Drop all auth tables and schema version tracking for a clean slate.
85
85
  *
@@ -1 +1 @@
1
- {"version":3,"file":"db.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/db.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AA6B7B,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,aAAa,CAAC;AAKpC;;GAEG;AACH,eAAO,MAAM,KAAK,SAA4B,CAAC;AAE/C;;GAEG;AACH,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,OAAO,CAAC,EAAE,CAAC,CAAC;IAC1B,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,GAAU,IAAI,EAAE,KAAG,OAAO,CAAC,IAAI,CAGvD,CAAC;AAMF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,qBAAqB,GAAI,aAAa,CAAC,EAAE,EAAE,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,KAAG,SAkB7E,CAAC;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,iBAAiB,GAC7B,aAAa,CAAC,EAAE,EAAE,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,EACtC,WAAW,MAAM,KACf,SA2DF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,UAQhC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,gCAAgC,UAAyC,CAAC;AAEvF;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,+IAWnB,CAAC;AAEX;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,GAAU,IAAI,EAAE,KAAG,OAAO,CAAC,IAAI,CAK3D,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,kBAAkB,GAC9B,WAAW,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,EACvC,iBAAiB,KAAK,CAAC,MAAM,CAAC,KAC5B,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,KAAK,IAAI,CAwBzD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB,GAAI,WAAW,KAAK,CAAC,SAAS,CAAC,KAAG,IAMnE,CAAC"}
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/db.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AA6B7B,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,aAAa,CAAC;AAKpC;;GAEG;AACH,eAAO,MAAM,KAAK,SAA4B,CAAC;AAE/C;;GAEG;AACH,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,OAAO,CAAC,EAAE,CAAC,CAAC;IAC1B,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,GAAU,IAAI,EAAE,KAAG,OAAO,CAAC,IAAI,CAGvD,CAAC;AAMF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,qBAAqB,GAAI,aAAa,CAAC,EAAE,EAAE,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,KAAG,SAkB7E,CAAC;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,iBAAiB,GAC7B,aAAa,CAAC,EAAE,EAAE,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,EACtC,WAAW,MAAM,KACf,SA2DF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,UAQhC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,gCAAgC,UAAyC,CAAC;AAEvF;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,uJAWnB,CAAC;AAEX;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,GAAU,IAAI,EAAE,KAAG,OAAO,CAAC,IAAI,CAK3D,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,kBAAkB,GAC9B,WAAW,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,EACvC,iBAAiB,KAAK,CAAC,MAAM,CAAC,KAC5B,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,KAAK,IAAI,CAwBzD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB,GAAI,WAAW,KAAK,CAAC,SAAS,CAAC,KAAG,IAMnE,CAAC"}
@@ -164,8 +164,8 @@ export const AUTH_TRUNCATE_TABLES = [
164
164
  'invite',
165
165
  'api_token',
166
166
  'auth_session',
167
- 'permit',
168
- 'permit_offer',
167
+ 'role_grant',
168
+ 'role_grant_offer',
169
169
  'actor',
170
170
  'account',
171
171
  ];
@@ -192,8 +192,8 @@ export const AUTH_DROP_TABLES = [
192
192
  'audit_log',
193
193
  'api_token',
194
194
  'auth_session',
195
- 'permit',
196
- 'permit_offer',
195
+ 'role_grant',
196
+ 'role_grant_offer',
197
197
  'actor',
198
198
  'account',
199
199
  'bootstrap_lock',
@@ -0,0 +1,22 @@
1
+ import './assert_dev_env.js';
2
+ import type { Account, Actor } from '../auth/account_schema.js';
3
+ import type { Db } from '../db/db.js';
4
+ /** The `{account, actor}` row pair returned by `create_test_account_with_actor`. */
5
+ export interface TestAccountWithActor {
6
+ account: Account;
7
+ actor: Actor;
8
+ }
9
+ /**
10
+ * Create an `account` + `actor` row pair in the database for tests.
11
+ *
12
+ * Wraps `query_create_account_with_actor` with a default `password_hash`
13
+ * so suites that don't exercise password verification can stay terse.
14
+ * Replaces the per-file `create_user` / `create_test_actor` /
15
+ * `create_test_account` helpers that had accumulated across the auth
16
+ * test suite.
17
+ */
18
+ export declare const create_test_account_with_actor: (db: Db, options: {
19
+ username: string;
20
+ password_hash?: string;
21
+ }) => Promise<TestAccountWithActor>;
22
+ //# sourceMappingURL=db_entities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db_entities.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/db_entities.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAoB7B,OAAO,KAAK,EAAC,OAAO,EAAE,KAAK,EAAC,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,aAAa,CAAC;AAEpC,oFAAoF;AACpF,MAAM,WAAW,oBAAoB;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,CAAC;CACb;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,8BAA8B,GAC1C,IAAI,EAAE,EACN,SAAS;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAC,KACjD,OAAO,CAAC,oBAAoB,CAI7B,CAAC"}
@@ -0,0 +1,28 @@
1
+ import './assert_dev_env.js';
2
+ /**
3
+ * DB-backed entity factories for tests that need real `account` + `actor`
4
+ * rows in the database.
5
+ *
6
+ * Companion to `entities.ts` — that file ships in-memory factories
7
+ * (`create_test_account`, `create_test_actor`) for tests that mock the
8
+ * DB; this file ships factories that hit a real `Db` so query-level
9
+ * tests don't reimplement the same `query_create_account_with_actor`
10
+ * wrapper in every file.
11
+ *
12
+ * For full-fledged test accounts that also need an API token + signed
13
+ * session cookie + role_grants, use `bootstrap_test_account` from
14
+ * `app_server.ts` instead.
15
+ *
16
+ * @module
17
+ */
18
+ import { query_create_account_with_actor } from '../auth/account_queries.js';
19
+ /**
20
+ * Create an `account` + `actor` row pair in the database for tests.
21
+ *
22
+ * Wraps `query_create_account_with_actor` with a default `password_hash`
23
+ * so suites that don't exercise password verification can stay terse.
24
+ * Replaces the per-file `create_user` / `create_test_actor` /
25
+ * `create_test_account` helpers that had accumulated across the auth
26
+ * test suite.
27
+ */
28
+ export const create_test_account_with_actor = async (db, options) => query_create_account_with_actor({ db }, { username: options.username, password_hash: options.password_hash ?? 'hash' });
@@ -1,5 +1,5 @@
1
1
  import './assert_dev_env.js';
2
- import type { Account, Actor, Permit } from '../auth/account_schema.js';
2
+ import type { Account, Actor, RoleGrant } from '../auth/account_schema.js';
3
3
  import type { AuditLogEvent } from '../auth/audit_log_schema.js';
4
4
  import type { RequestContext } from '../auth/request_context.js';
5
5
  /** Override type for `create_test_account` — id-like fields accept plain `string`. */
@@ -18,19 +18,20 @@ export type TestActorOverrides = Partial<Omit<Actor, 'id' | 'account_id' | 'upda
18
18
  };
19
19
  /** Create a test `Actor` with sensible defaults. */
20
20
  export declare const create_test_actor: (overrides?: TestActorOverrides) => Actor;
21
- /** Override type for `create_test_permit` — id-like fields accept plain `string`. */
22
- export type TestPermitOverrides = Partial<Omit<Permit, 'id' | 'actor_id' | 'scope_id' | 'revoked_by' | 'granted_by' | 'source_offer_id'>> & {
21
+ /** Override type for `create_test_role_grant` — id-like fields accept plain `string`. */
22
+ export type TestRoleGrantOverrides = Partial<Omit<RoleGrant, 'id' | 'actor_id' | 'scope_kind' | 'scope_id' | 'revoked_by' | 'granted_by' | 'source_offer_id'>> & {
23
23
  id?: string;
24
24
  actor_id?: string;
25
+ scope_kind?: string | null;
25
26
  scope_id?: string | null;
26
27
  revoked_by?: string | null;
27
28
  granted_by?: string | null;
28
29
  source_offer_id?: string | null;
29
30
  };
30
- /** Create a test `Permit` with sensible defaults. */
31
- export declare const create_test_permit: (overrides?: TestPermitOverrides) => Permit;
32
- /** Create a test `RequestContext` with permits from partial overrides. */
33
- export declare const create_test_context: (permits?: Array<TestPermitOverrides>) => RequestContext;
31
+ /** Create a test `RoleGrant` with sensible defaults. */
32
+ export declare const create_test_role_grant: (overrides?: TestRoleGrantOverrides) => RoleGrant;
33
+ /** Create a test `RequestContext` with role_grants from partial overrides. */
34
+ export declare const create_test_context: (role_grants?: Array<TestRoleGrantOverrides>) => RequestContext;
34
35
  /** Override type for `create_test_audit_event` — id-like fields accept plain `string`. */
35
36
  export type TestAuditEventOverrides = Partial<Omit<AuditLogEvent, 'id' | 'actor_id' | 'account_id' | 'target_account_id' | 'target_actor_id'>> & {
36
37
  id?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"entities.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/entities.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAiB7B,OAAO,KAAK,EAAC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAC,MAAM,2BAA2B,CAAC;AACtE,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,6BAA6B,CAAC;AAC/D,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,4BAA4B,CAAC;AAE/D,sFAAsF;AACtF,MAAM,MAAM,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,GAAG,YAAY,GAAG,YAAY,CAAC,CAAC,GAAG;IAC/F,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,mBAAmB,GAAI,YAAY,oBAAoB,KAAG,OAWrE,CAAC;AAEH,oFAAoF;AACpF,MAAM,MAAM,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,GAAG,YAAY,GAAG,YAAY,CAAC,CAAC,GAAG;IAC3F,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF,oDAAoD;AACpD,eAAO,MAAM,iBAAiB,GAAI,YAAY,kBAAkB,KAAG,KAQjE,CAAC;AAEH,qFAAqF;AACrF,MAAM,MAAM,mBAAmB,GAAG,OAAO,CACxC,IAAI,CAAC,MAAM,EAAE,IAAI,GAAG,UAAU,GAAG,UAAU,GAAG,YAAY,GAAG,YAAY,GAAG,iBAAiB,CAAC,CAC9F,GAAG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,CAAC;AAEF,qDAAqD;AACrD,eAAO,MAAM,kBAAkB,GAAI,YAAY,mBAAmB,KAAG,MAanE,CAAC;AAEH,0EAA0E;AAC1E,eAAO,MAAM,mBAAmB,GAC/B,UAAS,KAAK,CAAC,mBAAmB,CAAQ,KACxC,cAID,CAAC;AAEH,0FAA0F;AAC1F,MAAM,MAAM,uBAAuB,GAAG,OAAO,CAC5C,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,UAAU,GAAG,YAAY,GAAG,mBAAmB,GAAG,iBAAiB,CAAC,CAC/F,GAAG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,uBAAuB,GAAI,YAAY,uBAAuB,KAAG,aAa5E,CAAC"}
1
+ {"version":3,"file":"entities.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/entities.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAiB7B,OAAO,KAAK,EAAC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAC,MAAM,2BAA2B,CAAC;AACzE,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,6BAA6B,CAAC;AAC/D,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,4BAA4B,CAAC;AAE/D,sFAAsF;AACtF,MAAM,MAAM,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,GAAG,YAAY,GAAG,YAAY,CAAC,CAAC,GAAG;IAC/F,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,mBAAmB,GAAI,YAAY,oBAAoB,KAAG,OAWrE,CAAC;AAEH,oFAAoF;AACpF,MAAM,MAAM,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,GAAG,YAAY,GAAG,YAAY,CAAC,CAAC,GAAG;IAC3F,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF,oDAAoD;AACpD,eAAO,MAAM,iBAAiB,GAAI,YAAY,kBAAkB,KAAG,KAQjE,CAAC;AAEH,yFAAyF;AACzF,MAAM,MAAM,sBAAsB,GAAG,OAAO,CAC3C,IAAI,CACH,SAAS,EACT,IAAI,GAAG,UAAU,GAAG,YAAY,GAAG,UAAU,GAAG,YAAY,GAAG,YAAY,GAAG,iBAAiB,CAC/F,CACD,GAAG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,CAAC;AAEF,wDAAwD;AACxD,eAAO,MAAM,sBAAsB,GAAI,YAAY,sBAAsB,KAAG,SAgB3E,CAAC;AAEF,8EAA8E;AAC9E,eAAO,MAAM,mBAAmB,GAC/B,cAAa,KAAK,CAAC,sBAAsB,CAAQ,KAC/C,cAID,CAAC;AAEH,0FAA0F;AAC1F,MAAM,MAAM,uBAAuB,GAAG,OAAO,CAC5C,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,UAAU,GAAG,YAAY,GAAG,mBAAmB,GAAG,iBAAiB,CAAC,CAC/F,GAAG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,uBAAuB,GAAI,YAAY,uBAAuB,KAAG,aAa5E,CAAC"}
@@ -22,26 +22,29 @@ export const create_test_actor = (overrides) => ({
22
22
  updated_by: null,
23
23
  ...overrides,
24
24
  });
25
- /** Create a test `Permit` with sensible defaults. */
26
- export const create_test_permit = (overrides) => ({
27
- id: 'permit-test',
28
- actor_id: 'actor-test',
29
- role: 'admin',
30
- scope_id: null,
31
- created_at: '2024-01-01T00:00:00Z',
32
- expires_at: null,
33
- revoked_at: null,
34
- revoked_by: null,
35
- revoked_reason: null,
36
- granted_by: null,
37
- source_offer_id: null,
38
- ...overrides,
39
- });
40
- /** Create a test `RequestContext` with permits from partial overrides. */
41
- export const create_test_context = (permits = [{}]) => ({
25
+ /** Create a test `RoleGrant` with sensible defaults. */
26
+ export const create_test_role_grant = (overrides) => {
27
+ const base = {
28
+ id: 'role-grant-test',
29
+ actor_id: 'actor-test',
30
+ role: 'admin',
31
+ scope_kind: null,
32
+ scope_id: null,
33
+ created_at: '2024-01-01T00:00:00Z',
34
+ expires_at: null,
35
+ revoked_at: null,
36
+ revoked_by: null,
37
+ revoked_reason: null,
38
+ granted_by: null,
39
+ source_offer_id: null,
40
+ };
41
+ return overrides ? { ...base, ...overrides } : base;
42
+ };
43
+ /** Create a test `RequestContext` with role_grants from partial overrides. */
44
+ export const create_test_context = (role_grants = [{}]) => ({
42
45
  account: create_test_account(),
43
46
  actor: create_test_actor(),
44
- permits: permits.map((p) => create_test_permit(p)),
47
+ role_grants: role_grants.map((p) => create_test_role_grant(p)),
45
48
  });
46
49
  /** Create a test `AuditLogEvent` with sensible defaults. */
47
50
  export const create_test_audit_event = (overrides) => ({
@@ -1 +1 @@
1
- {"version":3,"file":"integration.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/integration.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAsB7B,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAC;AAErD,OAAO,EAA6C,KAAK,eAAe,EAAC,MAAM,iBAAiB,CAAC;AACjG,OAAO,EAIN,KAAK,SAAS,EACd,MAAM,SAAS,CAAC;AAOjB,OAAO,EAKN,KAAK,uBAAuB,EAC5B,MAAM,kBAAkB,CAAC;AAqB1B;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC9C,4CAA4C;IAC5C,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,wDAAwD;IACxD,kBAAkB,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IAChE,iDAAiD;IACjD,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B;;;OAGG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAChC;;;;;;;;;;;;;;;;OAgBG;IACH,aAAa,EAAE,uBAAuB,CAAC;CACvC;AAsBD;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,mCAAmC,GAC/C,SAAS,8BAA8B,KACrC,IAg8CF,CAAC"}
1
+ {"version":3,"file":"integration.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/integration.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAsB7B,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAC;AAErD,OAAO,EAA6C,KAAK,eAAe,EAAC,MAAM,iBAAiB,CAAC;AACjG,OAAO,EAIN,KAAK,SAAS,EACd,MAAM,SAAS,CAAC;AAOjB,OAAO,EAKN,KAAK,uBAAuB,EAC5B,MAAM,kBAAkB,CAAC;AAsB1B;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC9C,4CAA4C;IAC5C,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,wDAAwD;IACxD,kBAAkB,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IAChE,iDAAiD;IACjD,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B;;;OAGG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAChC;;;;;;;;;;;;;;;;OAgBG;IACH,aAAa,EAAE,uBAAuB,CAAC;CACvC;AAsBD;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,mCAAmC,GAC/C,SAAS,8BAA8B,KACrC,IA87CF,CAAC"}