@fuzdev/fuz_app 0.54.0 → 0.56.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (348) hide show
  1. package/dist/actions/CLAUDE.md +214 -103
  2. package/dist/actions/action_bridge.d.ts +8 -5
  3. package/dist/actions/action_bridge.d.ts.map +1 -1
  4. package/dist/actions/action_bridge.js +1 -11
  5. package/dist/actions/action_codegen.d.ts +32 -0
  6. package/dist/actions/action_codegen.d.ts.map +1 -1
  7. package/dist/actions/action_codegen.js +35 -15
  8. package/dist/actions/action_registry.d.ts.map +1 -1
  9. package/dist/actions/action_registry.js +5 -2
  10. package/dist/actions/action_rpc.d.ts +141 -22
  11. package/dist/actions/action_rpc.d.ts.map +1 -1
  12. package/dist/actions/action_rpc.js +106 -187
  13. package/dist/actions/action_spec.d.ts +55 -16
  14. package/dist/actions/action_spec.d.ts.map +1 -1
  15. package/dist/actions/action_spec.js +16 -11
  16. package/dist/actions/action_types.d.ts +28 -60
  17. package/dist/actions/action_types.d.ts.map +1 -1
  18. package/dist/actions/action_types.js +13 -5
  19. package/dist/actions/broadcast_api.d.ts +2 -2
  20. package/dist/actions/broadcast_api.js +2 -2
  21. package/dist/actions/compile_action_registry.d.ts +50 -0
  22. package/dist/actions/compile_action_registry.d.ts.map +1 -0
  23. package/dist/actions/compile_action_registry.js +69 -0
  24. package/dist/actions/heartbeat.d.ts +8 -4
  25. package/dist/actions/heartbeat.d.ts.map +1 -1
  26. package/dist/actions/heartbeat.js +5 -4
  27. package/dist/actions/perform_action.d.ts +145 -0
  28. package/dist/actions/perform_action.d.ts.map +1 -0
  29. package/dist/actions/perform_action.js +258 -0
  30. package/dist/actions/register_action_ws.d.ts +46 -40
  31. package/dist/actions/register_action_ws.d.ts.map +1 -1
  32. package/dist/actions/register_action_ws.js +101 -159
  33. package/dist/actions/register_ws_endpoint.d.ts +15 -10
  34. package/dist/actions/register_ws_endpoint.d.ts.map +1 -1
  35. package/dist/actions/register_ws_endpoint.js +54 -7
  36. package/dist/actions/transports.d.ts.map +1 -1
  37. package/dist/actions/transports.js +0 -4
  38. package/dist/actions/transports_ws_auth_guard.d.ts +1 -1
  39. package/dist/actions/transports_ws_auth_guard.js +1 -1
  40. package/dist/actions/transports_ws_backend.d.ts +1 -1
  41. package/dist/actions/transports_ws_backend.js +1 -1
  42. package/dist/auth/CLAUDE.md +794 -410
  43. package/dist/auth/account_action_specs.d.ts +28 -7
  44. package/dist/auth/account_action_specs.d.ts.map +1 -1
  45. package/dist/auth/account_action_specs.js +7 -7
  46. package/dist/auth/account_actions.d.ts +7 -13
  47. package/dist/auth/account_actions.d.ts.map +1 -1
  48. package/dist/auth/account_actions.js +26 -35
  49. package/dist/auth/account_queries.d.ts +52 -16
  50. package/dist/auth/account_queries.d.ts.map +1 -1
  51. package/dist/auth/account_queries.js +87 -38
  52. package/dist/auth/account_routes.d.ts +9 -11
  53. package/dist/auth/account_routes.d.ts.map +1 -1
  54. package/dist/auth/account_routes.js +118 -46
  55. package/dist/auth/account_schema.d.ts +46 -35
  56. package/dist/auth/account_schema.d.ts.map +1 -1
  57. package/dist/auth/account_schema.js +21 -28
  58. package/dist/auth/admin_action_specs.d.ts +100 -32
  59. package/dist/auth/admin_action_specs.d.ts.map +1 -1
  60. package/dist/auth/admin_action_specs.js +64 -33
  61. package/dist/auth/admin_actions.d.ts +13 -19
  62. package/dist/auth/admin_actions.d.ts.map +1 -1
  63. package/dist/auth/admin_actions.js +37 -41
  64. package/dist/auth/audit_emitter.d.ts +160 -0
  65. package/dist/auth/audit_emitter.d.ts.map +1 -0
  66. package/dist/auth/audit_emitter.js +83 -0
  67. package/dist/auth/audit_log_queries.d.ts +17 -48
  68. package/dist/auth/audit_log_queries.d.ts.map +1 -1
  69. package/dist/auth/audit_log_queries.js +20 -56
  70. package/dist/auth/audit_log_routes.d.ts +1 -1
  71. package/dist/auth/audit_log_routes.d.ts.map +1 -1
  72. package/dist/auth/audit_log_routes.js +7 -3
  73. package/dist/auth/audit_log_schema.d.ts +92 -32
  74. package/dist/auth/audit_log_schema.d.ts.map +1 -1
  75. package/dist/auth/audit_log_schema.js +75 -46
  76. package/dist/auth/auth_guard_resolver.d.ts +44 -0
  77. package/dist/auth/auth_guard_resolver.d.ts.map +1 -0
  78. package/dist/auth/auth_guard_resolver.js +56 -0
  79. package/dist/auth/bearer_auth.d.ts +9 -7
  80. package/dist/auth/bearer_auth.d.ts.map +1 -1
  81. package/dist/auth/bearer_auth.js +13 -21
  82. package/dist/auth/bootstrap_account.d.ts +7 -7
  83. package/dist/auth/bootstrap_account.d.ts.map +1 -1
  84. package/dist/auth/bootstrap_account.js +7 -7
  85. package/dist/auth/bootstrap_routes.d.ts.map +1 -1
  86. package/dist/auth/bootstrap_routes.js +11 -10
  87. package/dist/auth/cleanup.d.ts +20 -26
  88. package/dist/auth/cleanup.d.ts.map +1 -1
  89. package/dist/auth/cleanup.js +33 -42
  90. package/dist/auth/credential_type_schema.d.ts +115 -0
  91. package/dist/auth/credential_type_schema.d.ts.map +1 -0
  92. package/dist/auth/credential_type_schema.js +127 -0
  93. package/dist/auth/daemon_token_middleware.d.ts +23 -11
  94. package/dist/auth/daemon_token_middleware.d.ts.map +1 -1
  95. package/dist/auth/daemon_token_middleware.js +28 -22
  96. package/dist/auth/ddl.d.ts +2 -2
  97. package/dist/auth/ddl.d.ts.map +1 -1
  98. package/dist/auth/ddl.js +6 -6
  99. package/dist/auth/deps.d.ts +7 -18
  100. package/dist/auth/deps.d.ts.map +1 -1
  101. package/dist/auth/grant_path_schema.d.ts +117 -0
  102. package/dist/auth/grant_path_schema.d.ts.map +1 -0
  103. package/dist/auth/grant_path_schema.js +137 -0
  104. package/dist/auth/invite_queries.d.ts +12 -1
  105. package/dist/auth/invite_queries.d.ts.map +1 -1
  106. package/dist/auth/invite_queries.js +12 -1
  107. package/dist/auth/invite_schema.d.ts +1 -1
  108. package/dist/auth/invite_schema.d.ts.map +1 -1
  109. package/dist/auth/invite_schema.js +1 -1
  110. package/dist/auth/middleware.d.ts.map +1 -1
  111. package/dist/auth/middleware.js +9 -4
  112. package/dist/auth/migrations.d.ts +37 -14
  113. package/dist/auth/migrations.d.ts.map +1 -1
  114. package/dist/auth/migrations.js +79 -32
  115. package/dist/auth/request_context.d.ts +331 -61
  116. package/dist/auth/request_context.d.ts.map +1 -1
  117. package/dist/auth/request_context.js +378 -95
  118. package/dist/auth/{permit_offer_action_specs.d.ts → role_grant_offer_action_specs.d.ts} +163 -94
  119. package/dist/auth/role_grant_offer_action_specs.d.ts.map +1 -0
  120. package/dist/auth/role_grant_offer_action_specs.js +262 -0
  121. package/dist/auth/role_grant_offer_actions.d.ts +104 -0
  122. package/dist/auth/role_grant_offer_actions.d.ts.map +1 -0
  123. package/dist/auth/role_grant_offer_actions.js +473 -0
  124. package/dist/auth/{permit_offer_notifications.d.ts → role_grant_offer_notifications.d.ts} +90 -70
  125. package/dist/auth/role_grant_offer_notifications.d.ts.map +1 -0
  126. package/dist/auth/role_grant_offer_notifications.js +182 -0
  127. package/dist/auth/role_grant_offer_queries.d.ts +242 -0
  128. package/dist/auth/role_grant_offer_queries.d.ts.map +1 -0
  129. package/dist/auth/role_grant_offer_queries.js +533 -0
  130. package/dist/auth/role_grant_offer_schema.d.ts +150 -0
  131. package/dist/auth/role_grant_offer_schema.d.ts.map +1 -0
  132. package/dist/auth/{permit_offer_schema.js → role_grant_offer_schema.js} +60 -36
  133. package/dist/auth/role_grant_queries.d.ts +231 -0
  134. package/dist/auth/role_grant_queries.d.ts.map +1 -0
  135. package/dist/auth/role_grant_queries.js +320 -0
  136. package/dist/auth/role_schema.d.ts +150 -40
  137. package/dist/auth/role_schema.d.ts.map +1 -1
  138. package/dist/auth/role_schema.js +144 -45
  139. package/dist/auth/scope_kind_schema.d.ts +96 -0
  140. package/dist/auth/scope_kind_schema.d.ts.map +1 -0
  141. package/dist/auth/scope_kind_schema.js +94 -0
  142. package/dist/auth/self_service_role_action_specs.d.ts +6 -1
  143. package/dist/auth/self_service_role_action_specs.d.ts.map +1 -1
  144. package/dist/auth/self_service_role_action_specs.js +3 -1
  145. package/dist/auth/self_service_role_actions.d.ts +34 -27
  146. package/dist/auth/self_service_role_actions.d.ts.map +1 -1
  147. package/dist/auth/self_service_role_actions.js +68 -48
  148. package/dist/auth/session_cookie.d.ts +43 -6
  149. package/dist/auth/session_cookie.d.ts.map +1 -1
  150. package/dist/auth/session_cookie.js +31 -5
  151. package/dist/auth/session_middleware.d.ts +37 -3
  152. package/dist/auth/session_middleware.d.ts.map +1 -1
  153. package/dist/auth/session_middleware.js +33 -7
  154. package/dist/auth/signup_routes.d.ts.map +1 -1
  155. package/dist/auth/signup_routes.js +48 -19
  156. package/dist/auth/standard_action_specs.d.ts +2 -2
  157. package/dist/auth/standard_action_specs.js +4 -4
  158. package/dist/auth/standard_rpc_actions.d.ts +23 -19
  159. package/dist/auth/standard_rpc_actions.d.ts.map +1 -1
  160. package/dist/auth/standard_rpc_actions.js +12 -12
  161. package/dist/db/migrate.d.ts +12 -8
  162. package/dist/db/migrate.d.ts.map +1 -1
  163. package/dist/db/migrate.js +10 -7
  164. package/dist/dev/setup.d.ts +2 -2
  165. package/dist/dev/setup.d.ts.map +1 -1
  166. package/dist/dev/setup.js +9 -7
  167. package/dist/env/load.d.ts +1 -1
  168. package/dist/env/load.js +1 -1
  169. package/dist/hono_context.d.ts +64 -5
  170. package/dist/hono_context.d.ts.map +1 -1
  171. package/dist/hono_context.js +38 -2
  172. package/dist/http/CLAUDE.md +264 -87
  173. package/dist/http/auth_shape.d.ts +191 -0
  174. package/dist/http/auth_shape.d.ts.map +1 -0
  175. package/dist/http/auth_shape.js +237 -0
  176. package/dist/http/common_routes.js +3 -3
  177. package/dist/http/db_routes.d.ts +4 -0
  178. package/dist/http/db_routes.d.ts.map +1 -1
  179. package/dist/http/db_routes.js +44 -7
  180. package/dist/http/error_schemas.d.ts +132 -19
  181. package/dist/http/error_schemas.d.ts.map +1 -1
  182. package/dist/http/error_schemas.js +132 -40
  183. package/dist/http/jsonrpc_errors.d.ts +27 -2
  184. package/dist/http/jsonrpc_errors.d.ts.map +1 -1
  185. package/dist/http/jsonrpc_errors.js +26 -2
  186. package/dist/http/pending_effects.d.ts +71 -18
  187. package/dist/http/pending_effects.d.ts.map +1 -1
  188. package/dist/http/pending_effects.js +87 -18
  189. package/dist/http/proxy.d.ts +52 -5
  190. package/dist/http/proxy.d.ts.map +1 -1
  191. package/dist/http/proxy.js +92 -14
  192. package/dist/http/route_spec.d.ts +113 -41
  193. package/dist/http/route_spec.d.ts.map +1 -1
  194. package/dist/http/route_spec.js +130 -52
  195. package/dist/http/schema_helpers.d.ts +3 -2
  196. package/dist/http/schema_helpers.d.ts.map +1 -1
  197. package/dist/http/schema_helpers.js +9 -2
  198. package/dist/http/surface.d.ts +2 -1
  199. package/dist/http/surface.d.ts.map +1 -1
  200. package/dist/http/surface.js +1 -2
  201. package/dist/http/surface_query.d.ts +39 -35
  202. package/dist/http/surface_query.d.ts.map +1 -1
  203. package/dist/http/surface_query.js +79 -36
  204. package/dist/primitive_schemas.d.ts +39 -0
  205. package/dist/primitive_schemas.d.ts.map +1 -0
  206. package/dist/primitive_schemas.js +40 -0
  207. package/dist/realtime/sse_auth_guard.d.ts +5 -5
  208. package/dist/realtime/sse_auth_guard.js +9 -9
  209. package/dist/runtime/mock.d.ts +1 -1
  210. package/dist/runtime/mock.js +1 -1
  211. package/dist/server/app_backend.d.ts +14 -11
  212. package/dist/server/app_backend.d.ts.map +1 -1
  213. package/dist/server/app_backend.js +12 -8
  214. package/dist/server/app_server.d.ts +7 -7
  215. package/dist/server/app_server.d.ts.map +1 -1
  216. package/dist/server/app_server.js +36 -31
  217. package/dist/server/validate_nginx.d.ts +1 -1
  218. package/dist/server/validate_nginx.js +1 -1
  219. package/dist/testing/CLAUDE.md +73 -55
  220. package/dist/testing/admin_integration.d.ts +5 -6
  221. package/dist/testing/admin_integration.d.ts.map +1 -1
  222. package/dist/testing/admin_integration.js +100 -96
  223. package/dist/testing/adversarial_headers.js +1 -1
  224. package/dist/testing/app_server.d.ts +11 -14
  225. package/dist/testing/app_server.d.ts.map +1 -1
  226. package/dist/testing/app_server.js +18 -17
  227. package/dist/testing/assertions.d.ts.map +1 -1
  228. package/dist/testing/assertions.js +2 -1
  229. package/dist/testing/attack_surface.d.ts.map +1 -1
  230. package/dist/testing/attack_surface.js +15 -9
  231. package/dist/testing/audit_completeness.d.ts +2 -2
  232. package/dist/testing/audit_completeness.d.ts.map +1 -1
  233. package/dist/testing/audit_completeness.js +53 -39
  234. package/dist/testing/auth_apps.d.ts +5 -4
  235. package/dist/testing/auth_apps.d.ts.map +1 -1
  236. package/dist/testing/auth_apps.js +28 -22
  237. package/dist/testing/data_exposure.d.ts.map +1 -1
  238. package/dist/testing/data_exposure.js +5 -5
  239. package/dist/testing/db.d.ts +1 -1
  240. package/dist/testing/db.d.ts.map +1 -1
  241. package/dist/testing/db.js +4 -4
  242. package/dist/testing/db_entities.d.ts +22 -0
  243. package/dist/testing/db_entities.d.ts.map +1 -0
  244. package/dist/testing/db_entities.js +28 -0
  245. package/dist/testing/entities.d.ts +10 -8
  246. package/dist/testing/entities.d.ts.map +1 -1
  247. package/dist/testing/entities.js +22 -18
  248. package/dist/testing/integration.d.ts.map +1 -1
  249. package/dist/testing/integration.js +13 -14
  250. package/dist/testing/integration_helpers.d.ts +8 -6
  251. package/dist/testing/integration_helpers.d.ts.map +1 -1
  252. package/dist/testing/integration_helpers.js +29 -23
  253. package/dist/testing/middleware.d.ts +15 -11
  254. package/dist/testing/middleware.d.ts.map +1 -1
  255. package/dist/testing/middleware.js +75 -32
  256. package/dist/testing/rpc_attack_surface.d.ts.map +1 -1
  257. package/dist/testing/rpc_attack_surface.js +40 -24
  258. package/dist/testing/rpc_helpers.d.ts.map +1 -1
  259. package/dist/testing/rpc_helpers.js +3 -1
  260. package/dist/testing/rpc_round_trip.d.ts +1 -1
  261. package/dist/testing/rpc_round_trip.d.ts.map +1 -1
  262. package/dist/testing/rpc_round_trip.js +14 -13
  263. package/dist/testing/sse_round_trip.d.ts +3 -4
  264. package/dist/testing/sse_round_trip.d.ts.map +1 -1
  265. package/dist/testing/sse_round_trip.js +7 -11
  266. package/dist/testing/standard.d.ts +1 -1
  267. package/dist/testing/stubs.d.ts +25 -0
  268. package/dist/testing/stubs.d.ts.map +1 -1
  269. package/dist/testing/stubs.js +43 -2
  270. package/dist/testing/surface_invariants.d.ts +2 -2
  271. package/dist/testing/ws_round_trip.d.ts +12 -13
  272. package/dist/testing/ws_round_trip.d.ts.map +1 -1
  273. package/dist/testing/ws_round_trip.js +24 -12
  274. package/dist/ui/AdminAccounts.svelte +23 -20
  275. package/dist/ui/AdminOverview.svelte +15 -13
  276. package/dist/ui/AdminOverview.svelte.d.ts.map +1 -1
  277. package/dist/ui/{AdminPermitHistory.svelte → AdminRoleGrantHistory.svelte} +12 -12
  278. package/dist/ui/AdminRoleGrantHistory.svelte.d.ts +4 -0
  279. package/dist/ui/AdminRoleGrantHistory.svelte.d.ts.map +1 -0
  280. package/dist/ui/BootstrapForm.svelte +1 -1
  281. package/dist/ui/CLAUDE.md +65 -59
  282. package/dist/ui/{PermitOfferForm.svelte → RoleGrantOfferForm.svelte} +37 -22
  283. package/dist/ui/RoleGrantOfferForm.svelte.d.ts +20 -0
  284. package/dist/ui/RoleGrantOfferForm.svelte.d.ts.map +1 -0
  285. package/dist/ui/{PermitOfferHistory.svelte → RoleGrantOfferHistory.svelte} +12 -12
  286. package/dist/ui/{PermitOfferHistory.svelte.d.ts → RoleGrantOfferHistory.svelte.d.ts} +4 -4
  287. package/dist/ui/RoleGrantOfferHistory.svelte.d.ts.map +1 -0
  288. package/dist/ui/{PermitOfferInbox.svelte → RoleGrantOfferInbox.svelte} +14 -14
  289. package/dist/ui/{PermitOfferInbox.svelte.d.ts → RoleGrantOfferInbox.svelte.d.ts} +4 -4
  290. package/dist/ui/RoleGrantOfferInbox.svelte.d.ts.map +1 -0
  291. package/dist/ui/SignupForm.svelte +1 -1
  292. package/dist/ui/SurfaceExplorer.svelte +35 -15
  293. package/dist/ui/SurfaceExplorer.svelte.d.ts.map +1 -1
  294. package/dist/ui/account_sessions_state.svelte.d.ts +2 -3
  295. package/dist/ui/account_sessions_state.svelte.d.ts.map +1 -1
  296. package/dist/ui/account_sessions_state.svelte.js +2 -3
  297. package/dist/ui/admin_accounts_state.svelte.d.ts +25 -18
  298. package/dist/ui/admin_accounts_state.svelte.d.ts.map +1 -1
  299. package/dist/ui/admin_accounts_state.svelte.js +28 -17
  300. package/dist/ui/admin_rpc_adapters.d.ts +20 -20
  301. package/dist/ui/admin_rpc_adapters.d.ts.map +1 -1
  302. package/dist/ui/admin_rpc_adapters.js +17 -17
  303. package/dist/ui/admin_sessions_state.svelte.d.ts +2 -2
  304. package/dist/ui/admin_sessions_state.svelte.js +2 -2
  305. package/dist/ui/audit_log_state.svelte.d.ts +7 -7
  306. package/dist/ui/audit_log_state.svelte.d.ts.map +1 -1
  307. package/dist/ui/audit_log_state.svelte.js +6 -6
  308. package/dist/ui/auth_state.svelte.d.ts +3 -3
  309. package/dist/ui/auth_state.svelte.d.ts.map +1 -1
  310. package/dist/ui/auth_state.svelte.js +6 -6
  311. package/dist/ui/format_scope.d.ts +2 -2
  312. package/dist/ui/format_scope.js +2 -2
  313. package/dist/ui/{permit_offers_state.svelte.d.ts → role_grant_offers_state.svelte.d.ts} +39 -31
  314. package/dist/ui/role_grant_offers_state.svelte.d.ts.map +1 -0
  315. package/dist/ui/{permit_offers_state.svelte.js → role_grant_offers_state.svelte.js} +25 -19
  316. package/dist/ui/ui_format.js +2 -2
  317. package/package.json +3 -3
  318. package/dist/auth/permit_offer_action_specs.d.ts.map +0 -1
  319. package/dist/auth/permit_offer_action_specs.js +0 -227
  320. package/dist/auth/permit_offer_actions.d.ts +0 -110
  321. package/dist/auth/permit_offer_actions.d.ts.map +0 -1
  322. package/dist/auth/permit_offer_actions.js +0 -452
  323. package/dist/auth/permit_offer_notifications.d.ts.map +0 -1
  324. package/dist/auth/permit_offer_notifications.js +0 -182
  325. package/dist/auth/permit_offer_queries.d.ts +0 -183
  326. package/dist/auth/permit_offer_queries.d.ts.map +0 -1
  327. package/dist/auth/permit_offer_queries.js +0 -408
  328. package/dist/auth/permit_offer_schema.d.ts +0 -103
  329. package/dist/auth/permit_offer_schema.d.ts.map +0 -1
  330. package/dist/auth/permit_queries.d.ts +0 -210
  331. package/dist/auth/permit_queries.d.ts.map +0 -1
  332. package/dist/auth/permit_queries.js +0 -294
  333. package/dist/auth/require_keeper.d.ts +0 -20
  334. package/dist/auth/require_keeper.d.ts.map +0 -1
  335. package/dist/auth/require_keeper.js +0 -35
  336. package/dist/auth/route_guards.d.ts +0 -21
  337. package/dist/auth/route_guards.d.ts.map +0 -1
  338. package/dist/auth/route_guards.js +0 -32
  339. package/dist/auth/session_lifecycle.d.ts +0 -37
  340. package/dist/auth/session_lifecycle.d.ts.map +0 -1
  341. package/dist/auth/session_lifecycle.js +0 -29
  342. package/dist/ui/AdminPermitHistory.svelte.d.ts +0 -4
  343. package/dist/ui/AdminPermitHistory.svelte.d.ts.map +0 -1
  344. package/dist/ui/PermitOfferForm.svelte.d.ts +0 -14
  345. package/dist/ui/PermitOfferForm.svelte.d.ts.map +0 -1
  346. package/dist/ui/PermitOfferHistory.svelte.d.ts.map +0 -1
  347. package/dist/ui/PermitOfferInbox.svelte.d.ts.map +0 -1
  348. package/dist/ui/permit_offers_state.svelte.d.ts.map +0 -1
@@ -0,0 +1,262 @@
1
+ /**
2
+ * Role grant offer RPC action specs — declarative contract for the
3
+ * consentful-role-grants surface (offer lifecycle + admin revoke).
4
+ *
5
+ * Import this module for the specs, Input/Output schemas, `ERROR_ROLE_GRANT_OFFER_*`
6
+ * reason constants, and the `all_role_grant_offer_action_specs` registry.
7
+ * Handlers live in `auth/role_grant_offer_actions.ts`.
8
+ *
9
+ * Authorization enforcement: offer-lifecycle specs declare account+actor
10
+ * required (no roles) and rely on `query_*` IDOR guards or in-handler
11
+ * policy checks (e.g. `role_grant_offer_list`/`_history` elevate to admin only
12
+ * when inspecting another account — an input-dependent check that can't be
13
+ * expressed at the spec level). `role_grant_revoke` adds `roles: ['admin']` —
14
+ * the RPC dispatcher's per-spec post-authorization auth gate
15
+ * (`check_action_auth_post_authorization`) rejects non-admin callers before
16
+ * the handler runs even though the endpoint hosts non-admin methods
17
+ * alongside.
18
+ *
19
+ * @module
20
+ */
21
+ import { z } from 'zod';
22
+ import { Uuid } from '@fuzdev/fuz_util/id.js';
23
+ import { ERROR_ROLE_GRANT_NOT_FOUND, ERROR_ROLE_NOT_WEB_GRANTABLE } from '../http/error_schemas.js';
24
+ import { RoleName } from './role_schema.js';
25
+ import { ROLE_GRANT_OFFER_MESSAGE_LENGTH_MAX, RoleGrantOfferJson, } from './role_grant_offer_schema.js';
26
+ import { ROLE_GRANT_REVOKED_REASON_LENGTH_MAX } from './account_schema.js';
27
+ import { ActingActor } from '../http/auth_shape.js';
28
+ /** Error reason — caller tried to offer themselves a role_grant. */
29
+ export const ERROR_ROLE_GRANT_OFFER_SELF_TARGET = 'role_grant_offer_self_target';
30
+ /** Error reason — offer is declined, retracted, or superseded. */
31
+ export const ERROR_ROLE_GRANT_OFFER_TERMINAL = 'role_grant_offer_terminal';
32
+ /** Error reason — offer's `expires_at` has passed. */
33
+ export const ERROR_ROLE_GRANT_OFFER_EXPIRED = 'role_grant_offer_expired';
34
+ /** Error reason — offer does not exist or belongs to a different recipient (404-over-403 IDOR mask). */
35
+ export const ERROR_ROLE_GRANT_OFFER_NOT_FOUND = 'role_grant_offer_not_found';
36
+ /** Error reason — the offered role does not include `'admin'` in its `RoleSpec.grant_paths` (nobody may offer it via this surface). */
37
+ export const ERROR_ROLE_GRANT_OFFER_ROLE_NOT_GRANTABLE = 'role_grant_offer_role_not_grantable';
38
+ /** Error reason — caller is not authorized to offer this role (default policy: caller lacks the role; consumer `authorize` callback may add further policy). */
39
+ export const ERROR_ROLE_GRANT_OFFER_NOT_AUTHORIZED = 'role_grant_offer_not_authorized';
40
+ /** Error reason — actor-targeted offer was accepted by an actor other than `to_actor_id`. */
41
+ export const ERROR_ROLE_GRANT_OFFER_ACTOR_MISMATCH = 'role_grant_offer_actor_mismatch';
42
+ /** Error reason — `role_grant_offer_create` was called with a `to_actor_id` that does not belong to `to_account_id`. */
43
+ export const ERROR_ROLE_GRANT_OFFER_ACTOR_ACCOUNT_MISMATCH = 'role_grant_offer_actor_account_mismatch';
44
+ // -- Input/output schemas ---------------------------------------------------
45
+ /**
46
+ * Input for `role_grant_offer_create`.
47
+ *
48
+ * `to_actor_id` (optional) narrows the offer to a specific actor on the
49
+ * recipient account. When supplied, `role_grant_offer_accept` will only admit
50
+ * the named actor — wrong-actor accepts reject with
51
+ * `role_grant_offer_actor_mismatch`. The audit envelope's `target_actor_id` is
52
+ * stamped from this column on the create / supersede / expire / retract
53
+ * events. Omit (or pass null) for the account-grain default — any actor
54
+ * on `to_account_id` may accept.
55
+ */
56
+ export const RoleGrantOfferCreateInput = z.strictObject({
57
+ to_account_id: Uuid.meta({ description: 'Account id of the recipient.' }),
58
+ to_actor_id: Uuid.nullish().meta({
59
+ description: 'Optional actor-grain target on the recipient account. When set, only this actor may accept and the audit envelope carries it on offer-shape events. Must belong to `to_account_id`.',
60
+ }),
61
+ role: RoleName.meta({ description: 'Role being offered.' }),
62
+ scope_kind: z.string().nullish().meta({
63
+ description: 'Machine-readable kind tag for `scope_id` — paired-null with `scope_id` (both null for global, both non-null for scoped). Required iff `scope_id` is set.',
64
+ }),
65
+ scope_id: Uuid.nullish().meta({
66
+ description: 'Scope id for resource-scoped grants (e.g. classroom id). `null` for global.',
67
+ }),
68
+ message: z
69
+ .string()
70
+ .max(ROLE_GRANT_OFFER_MESSAGE_LENGTH_MAX)
71
+ .nullish()
72
+ .meta({ description: 'Optional free-form note from the grantor.' }),
73
+ acting: ActingActor,
74
+ });
75
+ /** Input for `role_grant_offer_accept`. */
76
+ export const RoleGrantOfferAcceptInput = z.strictObject({
77
+ offer_id: Uuid.meta({ description: 'The offer to accept.' }),
78
+ acting: ActingActor,
79
+ });
80
+ /** Input for `role_grant_offer_decline`. */
81
+ export const RoleGrantOfferDeclineInput = z.strictObject({
82
+ offer_id: Uuid.meta({ description: 'The offer to decline.' }),
83
+ reason: z
84
+ .string()
85
+ .max(ROLE_GRANT_OFFER_MESSAGE_LENGTH_MAX)
86
+ .nullish()
87
+ .meta({ description: 'Optional free-form reason given on decline.' }),
88
+ acting: ActingActor,
89
+ });
90
+ /** Input for `role_grant_offer_retract`. */
91
+ export const RoleGrantOfferRetractInput = z.strictObject({
92
+ offer_id: Uuid.meta({ description: 'The offer to retract.' }),
93
+ acting: ActingActor,
94
+ });
95
+ /** Input for `role_grant_offer_list`. `account_id` is admin-only (inspect another account's inbox). */
96
+ export const RoleGrantOfferListInput = z.strictObject({
97
+ account_id: Uuid.nullish().meta({
98
+ description: 'Admin-only — list offers for another account. Defaults to the caller.',
99
+ }),
100
+ acting: ActingActor,
101
+ });
102
+ /**
103
+ * Input for `role_grant_revoke`. Admin-only mutation that revokes an active
104
+ * role_grant on a target actor. `actor_id` is the natural key — role_grants are
105
+ * actor-scoped, and the admin UI reads `row.actor.id` straight from the
106
+ * listing. Deriving `actor_id` from `account_id` would collapse under
107
+ * multi-actor accounts.
108
+ */
109
+ export const RoleGrantRevokeInput = z.strictObject({
110
+ actor_id: Uuid.meta({ description: 'Actor whose role_grant to revoke.' }),
111
+ role_grant_id: Uuid.meta({ description: 'The role_grant to revoke.' }),
112
+ reason: z.string().max(ROLE_GRANT_REVOKED_REASON_LENGTH_MAX).nullish().meta({
113
+ description: 'Optional free-form reason; stamped on `role_grant.revoked_reason` and surfaced on the revokee WS notification.',
114
+ }),
115
+ acting: ActingActor,
116
+ });
117
+ /**
118
+ * Input for `role_grant_offer_history`. Returns every offer involving the account
119
+ * in either direction (recipient or grantor), including terminal rows, newest
120
+ * first. `account_id` is admin-only.
121
+ */
122
+ export const RoleGrantOfferHistoryInput = z.strictObject({
123
+ account_id: Uuid.nullish().meta({
124
+ description: 'Admin-only — history for another account. Defaults to the caller.',
125
+ }),
126
+ limit: z.number().int().min(1).max(500).nullish().meta({
127
+ description: 'Max rows to return (default 100).',
128
+ }),
129
+ offset: z.number().int().min(0).nullish().meta({
130
+ description: 'Pagination offset (default 0).',
131
+ }),
132
+ acting: ActingActor,
133
+ });
134
+ /** Output for `role_grant_offer_create`. */
135
+ export const RoleGrantOfferCreateOutput = z.strictObject({
136
+ offer: RoleGrantOfferJson,
137
+ });
138
+ /** Output for `role_grant_offer_accept`. */
139
+ export const RoleGrantOfferAcceptOutput = z.strictObject({
140
+ role_grant_id: Uuid,
141
+ offer: RoleGrantOfferJson,
142
+ superseded_offer_ids: z.array(Uuid),
143
+ });
144
+ /** Output for `role_grant_offer_decline` / `role_grant_offer_retract`. */
145
+ export const RoleGrantOfferOkOutput = z.strictObject({ ok: z.literal(true) });
146
+ /** Output for `role_grant_offer_list`. */
147
+ export const RoleGrantOfferListOutput = z.strictObject({ offers: z.array(RoleGrantOfferJson) });
148
+ /** Output for `role_grant_offer_history`. */
149
+ export const RoleGrantOfferHistoryOutput = z.strictObject({ offers: z.array(RoleGrantOfferJson) });
150
+ /** Output for `role_grant_revoke`. */
151
+ export const RoleGrantRevokeOutput = z.strictObject({
152
+ ok: z.literal(true),
153
+ revoked: z.literal(true),
154
+ });
155
+ // -- Action specs -----------------------------------------------------------
156
+ export const role_grant_offer_create_action_spec = {
157
+ method: 'role_grant_offer_create',
158
+ kind: 'request_response',
159
+ initiator: 'frontend',
160
+ auth: { account: 'required', actor: 'required' },
161
+ side_effects: true,
162
+ input: RoleGrantOfferCreateInput,
163
+ output: RoleGrantOfferCreateOutput,
164
+ async: true,
165
+ description: "Offer a role_grant to another account. Grantor must hold the offered role (or pass a consumer authorize callback); role's `grant_paths` must include `'admin'`.",
166
+ error_reasons: [
167
+ ERROR_ROLE_GRANT_OFFER_SELF_TARGET,
168
+ ERROR_ROLE_GRANT_OFFER_ROLE_NOT_GRANTABLE,
169
+ ERROR_ROLE_GRANT_OFFER_NOT_AUTHORIZED,
170
+ ERROR_ROLE_GRANT_OFFER_ACTOR_ACCOUNT_MISMATCH,
171
+ ],
172
+ };
173
+ export const role_grant_offer_accept_action_spec = {
174
+ method: 'role_grant_offer_accept',
175
+ kind: 'request_response',
176
+ initiator: 'frontend',
177
+ auth: { account: 'required', actor: 'required' },
178
+ side_effects: true,
179
+ input: RoleGrantOfferAcceptInput,
180
+ output: RoleGrantOfferAcceptOutput,
181
+ async: true,
182
+ description: 'Accept an offer. Atomically marks the offer accepted, inserts the role_grant, and supersedes sibling pending offers for the same (account, role, scope).',
183
+ error_reasons: [
184
+ ERROR_ROLE_GRANT_OFFER_NOT_FOUND,
185
+ ERROR_ROLE_GRANT_OFFER_TERMINAL,
186
+ ERROR_ROLE_GRANT_OFFER_EXPIRED,
187
+ ERROR_ROLE_GRANT_OFFER_ACTOR_MISMATCH,
188
+ ],
189
+ };
190
+ export const role_grant_offer_decline_action_spec = {
191
+ method: 'role_grant_offer_decline',
192
+ kind: 'request_response',
193
+ initiator: 'frontend',
194
+ auth: { account: 'required', actor: 'required' },
195
+ side_effects: true,
196
+ input: RoleGrantOfferDeclineInput,
197
+ output: RoleGrantOfferOkOutput,
198
+ async: true,
199
+ description: 'Decline an offer. Recipient-only.',
200
+ error_reasons: [ERROR_ROLE_GRANT_OFFER_NOT_FOUND, ERROR_ROLE_GRANT_OFFER_TERMINAL],
201
+ };
202
+ export const role_grant_offer_retract_action_spec = {
203
+ method: 'role_grant_offer_retract',
204
+ kind: 'request_response',
205
+ initiator: 'frontend',
206
+ auth: { account: 'required', actor: 'required' },
207
+ side_effects: true,
208
+ input: RoleGrantOfferRetractInput,
209
+ output: RoleGrantOfferOkOutput,
210
+ async: true,
211
+ description: 'Retract an offer. Grantor-only, pre-decision.',
212
+ error_reasons: [ERROR_ROLE_GRANT_OFFER_NOT_FOUND, ERROR_ROLE_GRANT_OFFER_TERMINAL],
213
+ };
214
+ export const role_grant_offer_list_action_spec = {
215
+ method: 'role_grant_offer_list',
216
+ kind: 'request_response',
217
+ initiator: 'frontend',
218
+ auth: { account: 'required', actor: 'required' },
219
+ side_effects: false,
220
+ input: RoleGrantOfferListInput,
221
+ output: RoleGrantOfferListOutput,
222
+ async: true,
223
+ description: 'List pending, non-expired offers for the caller. Admins may pass `account_id` to inspect another account.',
224
+ };
225
+ export const role_grant_offer_history_action_spec = {
226
+ method: 'role_grant_offer_history',
227
+ kind: 'request_response',
228
+ initiator: 'frontend',
229
+ auth: { account: 'required', actor: 'required' },
230
+ side_effects: false,
231
+ input: RoleGrantOfferHistoryInput,
232
+ output: RoleGrantOfferHistoryOutput,
233
+ async: true,
234
+ description: 'List every offer involving the caller (either direction), including terminal rows, newest first. Admins may pass `account_id` to inspect another account.',
235
+ };
236
+ export const role_grant_revoke_action_spec = {
237
+ method: 'role_grant_revoke',
238
+ kind: 'request_response',
239
+ initiator: 'frontend',
240
+ auth: { account: 'required', actor: 'required', roles: ['admin'] },
241
+ side_effects: true,
242
+ input: RoleGrantRevokeInput,
243
+ output: RoleGrantRevokeOutput,
244
+ async: true,
245
+ description: 'Revoke an active role_grant on a target actor. Admin-only. Supersedes any pending offers for the same (account, role, scope). Fires role_grant_revoke + role_grant_offer_supersede notifications.',
246
+ error_reasons: [ERROR_ROLE_GRANT_NOT_FOUND, ERROR_ROLE_NOT_WEB_GRANTABLE],
247
+ rate_limit: 'account',
248
+ };
249
+ /**
250
+ * All role-grant-offer action specs — a codegen-ready registry. Consumers spread
251
+ * this into their own action-spec array to include offer lifecycle + revoke
252
+ * methods in a typed client surface.
253
+ */
254
+ export const all_role_grant_offer_action_specs = [
255
+ role_grant_offer_create_action_spec,
256
+ role_grant_offer_accept_action_spec,
257
+ role_grant_offer_decline_action_spec,
258
+ role_grant_offer_retract_action_spec,
259
+ role_grant_offer_list_action_spec,
260
+ role_grant_offer_history_action_spec,
261
+ role_grant_revoke_action_spec,
262
+ ];
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Role grant offer RPC action handlers — the consentful-role-grants action surface.
3
+ *
4
+ * Seven actions: six offer-lifecycle methods (create / accept / decline /
5
+ * retract / list / history) plus `role_grant_revoke` (admin-only). All mount
6
+ * on a consumer's JSON-RPC endpoint via `create_rpc_endpoint`. The action
7
+ * specs themselves live in `auth/role_grant_offer_action_specs.ts`. Mutations
8
+ * declare `side_effects: true` so the RPC dispatcher wraps the handler in
9
+ * a DB transaction; `role_grant_offer_list` and `role_grant_offer_history` declare
10
+ * `side_effects: false` so they are addressable via GET.
11
+ *
12
+ * Authorization:
13
+ * - `role_grant_offer_create` — the grantor must hold an active role_grant for the
14
+ * role being offered, and that role's `grant_paths` must include `'admin'`.
15
+ * Consumers needing a richer policy (e.g., "teacher may offer student in
16
+ * *their* classroom") pass an `authorize` callback that overrides the default.
17
+ * - `role_grant_offer_accept` / `role_grant_offer_decline` — keyed to the caller's
18
+ * account; `query_*` helpers enforce the IDOR guard.
19
+ * - `role_grant_offer_retract` — keyed to the caller's actor.
20
+ * - `role_grant_offer_list` / `role_grant_offer_history` — self by default;
21
+ * `{account_id}` is admin-only.
22
+ * - `role_grant_revoke` — spec-level `auth: {role: 'admin'}`; the RPC
23
+ * dispatcher rejects non-admin callers before the handler runs.
24
+ * The admin-grant-path gate prevents revoking keeper / daemon-scoped
25
+ * roles via this surface. Keys on `actor_id` to survive multi-actor accounts.
26
+ *
27
+ * Audit events are emitted in-transaction by the query layer (atomic with
28
+ * the role_grant write on accept/revoke) or by the handler via the bound
29
+ * `deps.audit.emit_role_grant_target` helper for single-event lifecycle
30
+ * transitions. `audit.notify` (SSE/WS broadcast) fires post-commit in both
31
+ * paths.
32
+ *
33
+ * WS notifications fan out post-commit via `emit_after_commit` when a
34
+ * `notification_sender` is wired: offer lifecycle transitions notify the
35
+ * counterparty, `role_grant_revoke` notifies the revokee plus each superseded
36
+ * pending offer's grantor.
37
+ *
38
+ * @module
39
+ */
40
+ import { type ActionContext, type RpcAction } from '../actions/action_rpc.js';
41
+ import { type RoleSchemaResult } from './role_schema.js';
42
+ import { type RequestContext } from './request_context.js';
43
+ import type { RouteFactoryDeps } from './deps.js';
44
+ import { type NotificationSender } from './role_grant_offer_notifications.js';
45
+ /**
46
+ * Authorization callback for `role_grant_offer_create`. Returns `true` to allow,
47
+ * `false` to reject (handler converts to `forbidden`).
48
+ *
49
+ * Provided with the fully-resolved request context and the parsed input
50
+ * (pre-TTL, pre-normalization). Consumers override the default to implement
51
+ * policies like "teacher may offer classroom_student only in classrooms they
52
+ * teach".
53
+ */
54
+ export type RoleGrantOfferCreateAuthorize = (auth: RequestContext, input: {
55
+ to_account_id: string;
56
+ role: string;
57
+ scope_id: string | null;
58
+ }, deps: Pick<RouteFactoryDeps, 'log'>, ctx: ActionContext) => boolean | Promise<boolean>;
59
+ /** Options for `create_role_grant_offer_actions`. */
60
+ export interface RoleGrantOfferActionOptions {
61
+ /**
62
+ * Role schema result from `create_role_schema()`. Defaults to builtin roles only.
63
+ * Drives the grantability gate: a role is offerable / revocable through
64
+ * this surface only when its `RoleSpec.grant_paths` includes `'admin'`
65
+ * (the `GRANT_PATH_ADMIN` constant).
66
+ */
67
+ roles?: RoleSchemaResult;
68
+ /** TTL applied to newly-created offers. Defaults to `ROLE_GRANT_OFFER_DEFAULT_TTL_MS`. */
69
+ default_ttl_ms?: number;
70
+ /**
71
+ * Custom authorization for `role_grant_offer_create`. The default requires the
72
+ * caller to hold an active role_grant for the offered role *and* the role's
73
+ * `RoleSpec.grant_paths` to include `'admin'`. Consumers with richer
74
+ * policies (scope-aware, chained roles) override this.
75
+ */
76
+ authorize?: RoleGrantOfferCreateAuthorize;
77
+ }
78
+ /**
79
+ * Authorization callback that admits any admin and otherwise falls back to
80
+ * the symmetric default (caller must hold the offered role globally).
81
+ *
82
+ * The admin-grant-path filter in `create_handler` runs **before** the
83
+ * `authorize` callback, so this never sees roles whose `grant_paths`
84
+ * omits `'admin'`. Drop into
85
+ * `create_role_grant_offer_actions({authorize: authorize_admin_or_holder})`
86
+ * (or any factory that forwards `authorize`, e.g. `create_standard_rpc_actions`)
87
+ * for the common "admins offer anything; users offer what they hold"
88
+ * pattern. Scope-aware policies (e.g. classroom_teacher offering
89
+ * classroom_student in their own scope) wrap this and short-circuit `true`
90
+ * before delegating.
91
+ */
92
+ export declare const authorize_admin_or_holder: RoleGrantOfferCreateAuthorize;
93
+ /**
94
+ * Create the seven role-grant-offer RPC actions (six offer-lifecycle methods
95
+ * plus `role_grant_revoke`).
96
+ *
97
+ * @param deps - `RouteFactoryDeps` (`log`, `audit`, …) plus optional `notification_sender` for WS fan-out — when absent, WS fan-out is silently skipped (DB-only side effects still happen). Consumers wiring `BackendWebsocketTransport` assign its instance directly (the transport's `send_to_account` signature accepts the broader `JsonrpcMessageFromServerToClient`, which is contravariantly compatible)
98
+ * @param options - role schema, default TTL, authorization override
99
+ * @returns the `RpcAction` array to spread into a `create_rpc_endpoint` call
100
+ */
101
+ export declare const create_role_grant_offer_actions: (deps: Pick<RouteFactoryDeps, "log" | "audit"> & {
102
+ notification_sender?: NotificationSender | null;
103
+ }, options?: RoleGrantOfferActionOptions) => Array<RpcAction>;
104
+ //# sourceMappingURL=role_grant_offer_actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"role_grant_offer_actions.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/role_grant_offer_actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,EAGN,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAIN,KAAK,gBAAgB,EACrB,MAAM,kBAAkB,CAAC;AA0B1B,OAAO,EAA4C,KAAK,cAAc,EAAC,MAAM,sBAAsB,CAAC;AACpG,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,WAAW,CAAC;AAEhD,OAAO,EAON,KAAK,kBAAkB,EACvB,MAAM,qCAAqC,CAAC;AAiC7C;;;;;;;;GAQG;AACH,MAAM,MAAM,6BAA6B,GAAG,CAC3C,IAAI,EAAE,cAAc,EACpB,KAAK,EAAE;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAAC,EACrE,IAAI,EAAE,IAAI,CAAC,gBAAgB,EAAE,KAAK,CAAC,EACnC,GAAG,EAAE,aAAa,KACd,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAEhC,qDAAqD;AACrD,MAAM,WAAW,2BAA2B;IAC3C;;;;;OAKG;IACH,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,0FAA0F;IAC1F,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,6BAA6B,CAAC;CAC1C;AA6BD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,yBAAyB,EAAE,6BAavC,CAAC;AAIF;;;;;;;GAOG;AACH,eAAO,MAAM,+BAA+B,GAC3C,MAAM,IAAI,CAAC,gBAAgB,EAAE,KAAK,GAAG,OAAO,CAAC,GAAG;IAC/C,mBAAmB,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;CAChD,EACD,UAAS,2BAAgC,KACvC,KAAK,CAAC,SAAS,CAidjB,CAAC"}