@fuzdev/fuz_app 0.146.1 → 0.148.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 (313) hide show
  1. package/dist/actions/CLAUDE.md +6 -4
  2. package/dist/actions/action_codegen.d.ts +15 -1
  3. package/dist/actions/action_codegen.d.ts.map +1 -1
  4. package/dist/actions/action_codegen.js +23 -2
  5. package/dist/actions/perform_action.js +1 -1
  6. package/dist/auth/CLAUDE.md +1 -1
  7. package/dist/auth/bootstrap_account.d.ts +2 -1
  8. package/dist/auth/bootstrap_account.d.ts.map +1 -1
  9. package/dist/auth/bootstrap_account.js +17 -6
  10. package/dist/auth/cell_action_specs.d.ts +3 -1
  11. package/dist/auth/cell_action_specs.d.ts.map +1 -1
  12. package/dist/auth/cell_action_specs.js +5 -5
  13. package/dist/auth/cell_actions.d.ts.map +1 -1
  14. package/dist/auth/cell_actions.js +2 -3
  15. package/dist/auth/cell_data_schema.d.ts +1 -1
  16. package/dist/auth/cell_data_schema.js +1 -1
  17. package/dist/auth/cell_field_action_specs.d.ts +4 -3
  18. package/dist/auth/cell_field_action_specs.d.ts.map +1 -1
  19. package/dist/auth/cell_field_action_specs.js +5 -6
  20. package/dist/auth/cell_field_actions.d.ts.map +1 -1
  21. package/dist/auth/cell_field_actions.js +8 -1
  22. package/dist/auth/cell_item_action_specs.d.ts +4 -2
  23. package/dist/auth/cell_item_action_specs.d.ts.map +1 -1
  24. package/dist/auth/cell_item_action_specs.js +5 -5
  25. package/dist/auth/cell_item_actions.d.ts.map +1 -1
  26. package/dist/auth/cell_item_actions.js +8 -1
  27. package/dist/auth/keyring.d.ts +35 -38
  28. package/dist/auth/keyring.d.ts.map +1 -1
  29. package/dist/auth/keyring.js +43 -50
  30. package/dist/auth/password_argon2.d.ts.map +1 -1
  31. package/dist/auth/password_argon2.js +11 -8
  32. package/dist/auth/role_grant_offer_action_specs.d.ts +2 -0
  33. package/dist/auth/role_grant_offer_action_specs.d.ts.map +1 -1
  34. package/dist/auth/role_grant_offer_action_specs.js +3 -1
  35. package/dist/auth/session_cookie.d.ts.map +1 -1
  36. package/dist/auth/session_cookie.js +5 -2
  37. package/dist/db/CLAUDE.md +18 -16
  38. package/dist/db/cell_queries.d.ts +3 -2
  39. package/dist/db/cell_queries.d.ts.map +1 -1
  40. package/dist/db/cell_queries.js +3 -2
  41. package/dist/db/fact_disk_storage.d.ts +15 -15
  42. package/dist/db/fact_disk_storage.d.ts.map +1 -1
  43. package/dist/db/fact_disk_storage.js +22 -28
  44. package/dist/db/fact_queries.d.ts +2 -3
  45. package/dist/db/fact_queries.d.ts.map +1 -1
  46. package/dist/db/fact_queries.js +2 -3
  47. package/dist/db/fact_store.d.ts +20 -18
  48. package/dist/db/fact_store.d.ts.map +1 -1
  49. package/dist/db/fact_store.js +30 -44
  50. package/dist/db/file_fact_url.d.ts +19 -4
  51. package/dist/db/file_fact_url.d.ts.map +1 -1
  52. package/dist/db/file_fact_url.js +19 -4
  53. package/dist/primitive_schemas.d.ts +1 -1
  54. package/dist/primitive_schemas.d.ts.map +1 -1
  55. package/dist/primitive_schemas.js +2 -1
  56. package/dist/schema_meta.d.ts +20 -0
  57. package/dist/schema_meta.d.ts.map +1 -1
  58. package/dist/schema_meta.js +7 -1
  59. package/dist/server/env.d.ts.map +1 -1
  60. package/dist/server/env.js +2 -2
  61. package/dist/server/serve_fact_route.d.ts +9 -5
  62. package/dist/server/serve_fact_route.d.ts.map +1 -1
  63. package/dist/server/serve_fact_route.js +15 -7
  64. package/dist/testing/CLAUDE.md +737 -114
  65. package/dist/testing/admin_integration.d.ts.map +1 -1
  66. package/dist/testing/admin_integration.js +73 -5
  67. package/dist/testing/adversarial_input.d.ts +0 -47
  68. package/dist/testing/adversarial_input.d.ts.map +1 -1
  69. package/dist/testing/adversarial_input.js +4 -340
  70. package/dist/testing/adversarial_input_cases.d.ts +64 -0
  71. package/dist/testing/adversarial_input_cases.d.ts.map +1 -0
  72. package/dist/testing/adversarial_input_cases.js +348 -0
  73. package/dist/testing/app_server.d.ts.map +1 -1
  74. package/dist/testing/app_server.js +2 -2
  75. package/dist/testing/audit_completeness.d.ts.map +1 -1
  76. package/dist/testing/audit_completeness.js +24 -20
  77. package/dist/testing/audit_drift_guard.d.ts +27 -1
  78. package/dist/testing/audit_drift_guard.d.ts.map +1 -1
  79. package/dist/testing/audit_drift_guard.js +50 -0
  80. package/dist/testing/cross_backend/account_lifecycle.d.ts.map +1 -1
  81. package/dist/testing/cross_backend/account_lifecycle.js +29 -12
  82. package/dist/testing/cross_backend/actor_lookup.d.ts.map +1 -1
  83. package/dist/testing/cross_backend/actor_lookup.js +7 -25
  84. package/dist/testing/cross_backend/app_settings.d.ts.map +1 -1
  85. package/dist/testing/cross_backend/app_settings.js +4 -6
  86. package/dist/testing/cross_backend/audit_cross_helpers.d.ts +51 -0
  87. package/dist/testing/cross_backend/audit_cross_helpers.d.ts.map +1 -0
  88. package/dist/testing/cross_backend/audit_cross_helpers.js +78 -0
  89. package/dist/testing/cross_backend/backend_config.d.ts +2 -1
  90. package/dist/testing/cross_backend/backend_config.d.ts.map +1 -1
  91. package/dist/testing/cross_backend/body_size.d.ts +6 -0
  92. package/dist/testing/cross_backend/body_size.d.ts.map +1 -1
  93. package/dist/testing/cross_backend/body_size.js +26 -44
  94. package/dist/testing/cross_backend/body_size_smuggling.d.ts +5 -0
  95. package/dist/testing/cross_backend/body_size_smuggling.d.ts.map +1 -1
  96. package/dist/testing/cross_backend/body_size_smuggling.js +7 -14
  97. package/dist/testing/cross_backend/bootstrap_backend.d.ts +11 -1
  98. package/dist/testing/cross_backend/bootstrap_backend.d.ts.map +1 -1
  99. package/dist/testing/cross_backend/bootstrap_backend.js +2 -1
  100. package/dist/testing/cross_backend/build_test_backend_paths.d.ts +3 -1
  101. package/dist/testing/cross_backend/build_test_backend_paths.d.ts.map +1 -1
  102. package/dist/testing/cross_backend/capabilities.d.ts +55 -59
  103. package/dist/testing/cross_backend/capabilities.d.ts.map +1 -1
  104. package/dist/testing/cross_backend/capabilities.js +20 -23
  105. package/dist/testing/cross_backend/cargo_binary.d.ts +70 -0
  106. package/dist/testing/cross_backend/cargo_binary.d.ts.map +1 -0
  107. package/dist/testing/cross_backend/cargo_binary.js +148 -0
  108. package/dist/testing/cross_backend/cell_crud.d.ts.map +1 -1
  109. package/dist/testing/cross_backend/cell_crud.js +57 -1
  110. package/dist/testing/cross_backend/cell_gated_create.d.ts +0 -60
  111. package/dist/testing/cross_backend/cell_gated_create.d.ts.map +1 -1
  112. package/dist/testing/cross_backend/cell_gated_create.js +9 -487
  113. package/dist/testing/cross_backend/cell_grant_role.d.ts +14 -2
  114. package/dist/testing/cross_backend/cell_grant_role.d.ts.map +1 -1
  115. package/dist/testing/cross_backend/cell_grant_role.js +22 -12
  116. package/dist/testing/cross_backend/cell_moderate.d.ts +66 -0
  117. package/dist/testing/cross_backend/cell_moderate.d.ts.map +1 -0
  118. package/dist/testing/cross_backend/cell_moderate.js +511 -0
  119. package/dist/testing/cross_backend/cell_ref_admission.d.ts.map +1 -1
  120. package/dist/testing/cross_backend/cell_ref_admission.js +1 -1
  121. package/dist/testing/cross_backend/cell_relations.d.ts.map +1 -1
  122. package/dist/testing/cross_backend/cell_relations.js +40 -19
  123. package/dist/testing/cross_backend/conformance_case.d.ts +43 -4
  124. package/dist/testing/cross_backend/conformance_case.d.ts.map +1 -1
  125. package/dist/testing/cross_backend/conformance_case.js +29 -1
  126. package/dist/testing/cross_backend/conformance_rpc_auth.d.ts +93 -0
  127. package/dist/testing/cross_backend/conformance_rpc_auth.d.ts.map +1 -0
  128. package/dist/testing/cross_backend/conformance_rpc_auth.js +125 -0
  129. package/dist/testing/cross_backend/conformance_table.d.ts +144 -4
  130. package/dist/testing/cross_backend/conformance_table.d.ts.map +1 -1
  131. package/dist/testing/cross_backend/conformance_table.js +297 -65
  132. package/dist/testing/cross_backend/cookie_attributes.d.ts.map +1 -1
  133. package/dist/testing/cross_backend/cookie_attributes.js +3 -2
  134. package/dist/testing/cross_backend/create_cross_backend_global_setup.d.ts +38 -5
  135. package/dist/testing/cross_backend/create_cross_backend_global_setup.d.ts.map +1 -1
  136. package/dist/testing/cross_backend/create_cross_backend_global_setup.js +24 -3
  137. package/dist/testing/cross_backend/create_dual_spawn_global_setup.d.ts +5 -5
  138. package/dist/testing/cross_backend/create_dual_spawn_global_setup.d.ts.map +1 -1
  139. package/dist/testing/cross_backend/credential_deadline.d.ts +10 -6
  140. package/dist/testing/cross_backend/credential_deadline.d.ts.map +1 -1
  141. package/dist/testing/cross_backend/credential_deadline.js +32 -31
  142. package/dist/testing/cross_backend/credential_header_robustness.d.ts.map +1 -1
  143. package/dist/testing/cross_backend/credential_header_robustness.js +4 -6
  144. package/dist/testing/cross_backend/{cell_cross_helpers.d.ts → cross_rpc.d.ts} +12 -2
  145. package/dist/testing/cross_backend/cross_rpc.d.ts.map +1 -0
  146. package/dist/testing/cross_backend/{cell_cross_helpers.js → cross_rpc.js} +31 -7
  147. package/dist/testing/cross_backend/default_backend_configs.d.ts +56 -61
  148. package/dist/testing/cross_backend/default_backend_configs.d.ts.map +1 -1
  149. package/dist/testing/cross_backend/default_backend_configs.js +97 -91
  150. package/dist/testing/cross_backend/default_spine_surface.d.ts.map +1 -1
  151. package/dist/testing/cross_backend/default_spine_surface.js +2 -2
  152. package/dist/testing/cross_backend/differential.d.ts +126 -0
  153. package/dist/testing/cross_backend/differential.d.ts.map +1 -0
  154. package/dist/testing/cross_backend/differential.js +201 -0
  155. package/dist/testing/cross_backend/differential_normalize.d.ts +150 -0
  156. package/dist/testing/cross_backend/differential_normalize.d.ts.map +1 -0
  157. package/dist/testing/cross_backend/differential_normalize.js +153 -0
  158. package/dist/testing/cross_backend/fact_serving.d.ts +5 -0
  159. package/dist/testing/cross_backend/fact_serving.d.ts.map +1 -1
  160. package/dist/testing/cross_backend/fact_serving.js +41 -7
  161. package/dist/testing/cross_backend/full_spine_mount.d.ts +15 -0
  162. package/dist/testing/cross_backend/full_spine_mount.d.ts.map +1 -1
  163. package/dist/testing/cross_backend/full_spine_mount.js +55 -1
  164. package/dist/testing/cross_backend/identity_parity.d.ts.map +1 -1
  165. package/dist/testing/cross_backend/identity_parity.js +6 -5
  166. package/dist/testing/cross_backend/in_process_setup.d.ts +12 -2
  167. package/dist/testing/cross_backend/in_process_setup.d.ts.map +1 -1
  168. package/dist/testing/cross_backend/in_process_setup.js +10 -7
  169. package/dist/testing/cross_backend/login_security.d.ts.map +1 -1
  170. package/dist/testing/cross_backend/login_security.js +13 -18
  171. package/dist/testing/cross_backend/origin.js +1 -1
  172. package/dist/testing/cross_backend/origin_conformance.js +1 -1
  173. package/dist/testing/cross_backend/origin_scope.d.ts +6 -0
  174. package/dist/testing/cross_backend/origin_scope.d.ts.map +1 -1
  175. package/dist/testing/cross_backend/origin_scope.js +13 -12
  176. package/dist/testing/cross_backend/peer_ping_ws.d.ts +2 -5
  177. package/dist/testing/cross_backend/peer_ping_ws.d.ts.map +1 -1
  178. package/dist/testing/cross_backend/peer_ping_ws.js +14 -24
  179. package/dist/testing/cross_backend/postgres_database.d.ts +85 -0
  180. package/dist/testing/cross_backend/postgres_database.d.ts.map +1 -0
  181. package/dist/testing/cross_backend/postgres_database.js +140 -0
  182. package/dist/testing/cross_backend/provided_context.d.ts +28 -0
  183. package/dist/testing/cross_backend/provided_context.d.ts.map +1 -0
  184. package/dist/testing/cross_backend/provided_context.js +35 -0
  185. package/dist/testing/cross_backend/query_shape.d.ts.map +1 -1
  186. package/dist/testing/cross_backend/query_shape.js +10 -12
  187. package/dist/testing/cross_backend/ready.js +2 -2
  188. package/dist/testing/cross_backend/revocation_drivers.d.ts +4 -3
  189. package/dist/testing/cross_backend/revocation_drivers.d.ts.map +1 -1
  190. package/dist/testing/cross_backend/revocation_drivers.js +1 -1
  191. package/dist/testing/cross_backend/role_grant_cross_helpers.d.ts +3 -2
  192. package/dist/testing/cross_backend/role_grant_cross_helpers.d.ts.map +1 -1
  193. package/dist/testing/cross_backend/role_grant_offer_lifecycle.d.ts +13 -0
  194. package/dist/testing/cross_backend/role_grant_offer_lifecycle.d.ts.map +1 -0
  195. package/dist/testing/cross_backend/role_grant_offer_lifecycle.js +203 -0
  196. package/dist/testing/cross_backend/role_grant_offer_notification_ws.d.ts +2 -5
  197. package/dist/testing/cross_backend/role_grant_offer_notification_ws.d.ts.map +1 -1
  198. package/dist/testing/cross_backend/role_grant_offer_notification_ws.js +203 -111
  199. package/dist/testing/cross_backend/role_grant_participation.d.ts +13 -0
  200. package/dist/testing/cross_backend/role_grant_participation.d.ts.map +1 -1
  201. package/dist/testing/cross_backend/role_grant_participation.js +32 -21
  202. package/dist/testing/cross_backend/role_grant_role_grammar.d.ts.map +1 -1
  203. package/dist/testing/cross_backend/role_grant_role_grammar.js +6 -9
  204. package/dist/testing/cross_backend/rpc_adversarial.d.ts +38 -0
  205. package/dist/testing/cross_backend/rpc_adversarial.d.ts.map +1 -0
  206. package/dist/testing/cross_backend/rpc_adversarial.js +292 -0
  207. package/dist/testing/cross_backend/rpc_success_fixtures.d.ts +24 -0
  208. package/dist/testing/cross_backend/rpc_success_fixtures.d.ts.map +1 -0
  209. package/dist/testing/cross_backend/rpc_success_fixtures.js +124 -0
  210. package/dist/testing/cross_backend/rust_spine_consumer_surface.d.ts +101 -0
  211. package/dist/testing/cross_backend/rust_spine_consumer_surface.d.ts.map +1 -0
  212. package/dist/testing/cross_backend/rust_spine_consumer_surface.js +113 -0
  213. package/dist/testing/cross_backend/rust_spine_stub_backend_config.d.ts +10 -0
  214. package/dist/testing/cross_backend/rust_spine_stub_backend_config.d.ts.map +1 -1
  215. package/dist/testing/cross_backend/rust_spine_stub_backend_config.js +27 -18
  216. package/dist/testing/cross_backend/session_cap.d.ts +9 -8
  217. package/dist/testing/cross_backend/session_cap.d.ts.map +1 -1
  218. package/dist/testing/cross_backend/session_cap.js +9 -4
  219. package/dist/testing/cross_backend/session_cookie_codec.d.ts +19 -0
  220. package/dist/testing/cross_backend/session_cookie_codec.d.ts.map +1 -0
  221. package/dist/testing/cross_backend/session_cookie_codec.js +128 -0
  222. package/dist/testing/cross_backend/setup.d.ts +56 -54
  223. package/dist/testing/cross_backend/setup.d.ts.map +1 -1
  224. package/dist/testing/cross_backend/setup.js +29 -29
  225. package/dist/testing/cross_backend/simple_request.d.ts.map +1 -1
  226. package/dist/testing/cross_backend/simple_request.js +4 -4
  227. package/dist/testing/cross_backend/spawn_backend.d.ts +59 -10
  228. package/dist/testing/cross_backend/spawn_backend.d.ts.map +1 -1
  229. package/dist/testing/cross_backend/spawn_backend.js +219 -60
  230. package/dist/testing/cross_backend/spine_suites.d.ts +231 -0
  231. package/dist/testing/cross_backend/spine_suites.d.ts.map +1 -0
  232. package/dist/testing/cross_backend/spine_suites.js +626 -0
  233. package/dist/testing/cross_backend/spine_surface_constants.d.ts +29 -0
  234. package/dist/testing/cross_backend/spine_surface_constants.d.ts.map +1 -1
  235. package/dist/testing/cross_backend/spine_surface_constants.js +29 -0
  236. package/dist/testing/cross_backend/sse_round_trip.d.ts.map +1 -1
  237. package/dist/testing/cross_backend/sse_round_trip.js +3 -4
  238. package/dist/testing/cross_backend/standard.d.ts +18 -1
  239. package/dist/testing/cross_backend/standard.d.ts.map +1 -1
  240. package/dist/testing/cross_backend/standard.js +2 -0
  241. package/dist/testing/cross_backend/test_cell_gated_create_authorize.d.ts +24 -0
  242. package/dist/testing/cross_backend/test_cell_gated_create_authorize.d.ts.map +1 -1
  243. package/dist/testing/cross_backend/test_cell_gated_create_authorize.js +15 -0
  244. package/dist/testing/cross_backend/testing_backdoor.d.ts +2 -8
  245. package/dist/testing/cross_backend/testing_backdoor.d.ts.map +1 -1
  246. package/dist/testing/cross_backend/testing_backdoor.js +7 -10
  247. package/dist/testing/cross_backend/testing_reset_actions.d.ts +10 -5
  248. package/dist/testing/cross_backend/testing_reset_actions.d.ts.map +1 -1
  249. package/dist/testing/cross_backend/testing_reset_actions.js +21 -12
  250. package/dist/testing/cross_backend/testing_server_bun.js +1 -1
  251. package/dist/testing/cross_backend/token_lifetime.js +1 -1
  252. package/dist/testing/cross_backend/token_scope_surface.d.ts.map +1 -1
  253. package/dist/testing/cross_backend/token_scope_surface.js +9 -13
  254. package/dist/testing/cross_backend/transport_composition.d.ts +26 -2
  255. package/dist/testing/cross_backend/transport_composition.d.ts.map +1 -1
  256. package/dist/testing/cross_backend/transport_composition.js +81 -51
  257. package/dist/testing/cross_backend/ts_spine_backend_config.d.ts +8 -0
  258. package/dist/testing/cross_backend/ts_spine_backend_config.d.ts.map +1 -1
  259. package/dist/testing/cross_backend/ts_spine_backend_config.js +17 -10
  260. package/dist/testing/cross_backend/ws_action_rate_limit.d.ts +2 -5
  261. package/dist/testing/cross_backend/ws_action_rate_limit.d.ts.map +1 -1
  262. package/dist/testing/cross_backend/ws_action_rate_limit.js +8 -14
  263. package/dist/testing/cross_backend/ws_connection_cap.d.ts +4 -9
  264. package/dist/testing/cross_backend/ws_connection_cap.d.ts.map +1 -1
  265. package/dist/testing/cross_backend/ws_connection_cap.js +11 -12
  266. package/dist/testing/cross_backend/ws_endpoint.d.ts +52 -0
  267. package/dist/testing/cross_backend/ws_endpoint.d.ts.map +1 -0
  268. package/dist/testing/cross_backend/ws_endpoint.js +54 -0
  269. package/dist/testing/cross_backend/ws_inbound_dispatch.d.ts +2 -5
  270. package/dist/testing/cross_backend/ws_inbound_dispatch.d.ts.map +1 -1
  271. package/dist/testing/cross_backend/ws_inbound_dispatch.js +9 -15
  272. package/dist/testing/cross_backend/ws_outbound_overflow.d.ts +2 -7
  273. package/dist/testing/cross_backend/ws_outbound_overflow.d.ts.map +1 -1
  274. package/dist/testing/cross_backend/ws_outbound_overflow.js +5 -9
  275. package/dist/testing/cross_backend/ws_role_gated.d.ts +4 -5
  276. package/dist/testing/cross_backend/ws_role_gated.d.ts.map +1 -1
  277. package/dist/testing/cross_backend/ws_role_gated.js +12 -21
  278. package/dist/testing/cross_backend/ws_round_trip.d.ts +12 -9
  279. package/dist/testing/cross_backend/ws_round_trip.d.ts.map +1 -1
  280. package/dist/testing/cross_backend/ws_round_trip.js +29 -34
  281. package/dist/testing/db_entities.d.ts +16 -3
  282. package/dist/testing/db_entities.d.ts.map +1 -1
  283. package/dist/testing/db_entities.js +28 -5
  284. package/dist/testing/integration_helpers.d.ts +61 -2
  285. package/dist/testing/integration_helpers.d.ts.map +1 -1
  286. package/dist/testing/integration_helpers.js +75 -18
  287. package/dist/testing/round_trip.d.ts +17 -0
  288. package/dist/testing/round_trip.d.ts.map +1 -1
  289. package/dist/testing/round_trip.js +67 -24
  290. package/dist/testing/rpc_attack_surface.d.ts.map +1 -1
  291. package/dist/testing/rpc_attack_surface.js +13 -138
  292. package/dist/testing/rpc_envelope_cases.d.ts +111 -0
  293. package/dist/testing/rpc_envelope_cases.d.ts.map +1 -0
  294. package/dist/testing/rpc_envelope_cases.js +240 -0
  295. package/dist/testing/rpc_helpers.d.ts +31 -0
  296. package/dist/testing/rpc_helpers.d.ts.map +1 -1
  297. package/dist/testing/rpc_helpers.js +35 -14
  298. package/dist/testing/rpc_round_trip.d.ts +62 -6
  299. package/dist/testing/rpc_round_trip.d.ts.map +1 -1
  300. package/dist/testing/rpc_round_trip.js +151 -39
  301. package/dist/testing/schema_generators.d.ts.map +1 -1
  302. package/dist/testing/schema_generators.js +22 -2
  303. package/dist/testing/standard.d.ts +26 -0
  304. package/dist/testing/standard.d.ts.map +1 -1
  305. package/dist/testing/standard.js +4 -1
  306. package/dist/testing/transports/raw_http.d.ts +21 -0
  307. package/dist/testing/transports/raw_http.d.ts.map +1 -1
  308. package/dist/testing/transports/raw_http.js +30 -0
  309. package/package.json +10 -8
  310. package/dist/testing/cross_backend/actor_search.d.ts +0 -6
  311. package/dist/testing/cross_backend/actor_search.d.ts.map +0 -1
  312. package/dist/testing/cross_backend/actor_search.js +0 -90
  313. package/dist/testing/cross_backend/cell_cross_helpers.d.ts.map +0 -1
@@ -0,0 +1,28 @@
1
+ import '../assert_dev_env.js';
2
+ import { type ReconstructedBootstrappedBackendHandle, type SerializableBootstrappedBackendHandle } from './setup.js';
3
+ declare module 'vitest' {
4
+ interface ProvidedContext {
5
+ /** The single-backend project's handle (`create_cross_backend_global_setup`). */
6
+ backend_handle: SerializableBootstrappedBackendHandle;
7
+ /** A dual-spawn project's first handle (`create_dual_spawn_global_setup`'s default keys). */
8
+ parity_handle_a: SerializableBootstrappedBackendHandle;
9
+ /** A dual-spawn project's second handle. */
10
+ parity_handle_b: SerializableBootstrappedBackendHandle;
11
+ }
12
+ }
13
+ /**
14
+ * The backend the project's `globalSetup` spawned, rebuilt from the provided
15
+ * `backend_handle`. Call at a test file's top level.
16
+ */
17
+ export declare const inject_backend_handle: () => ReconstructedBootstrappedBackendHandle;
18
+ /** The two backends a dual-spawn project's `globalSetup` spawned, under the default keys. */
19
+ export interface InjectedParityHandles {
20
+ readonly a: ReconstructedBootstrappedBackendHandle;
21
+ readonly b: ReconstructedBootstrappedBackendHandle;
22
+ }
23
+ /**
24
+ * The two backends a dual-spawn project provides as `parity_handle_a` /
25
+ * `parity_handle_b`, rebuilt. Call at a test file's top level.
26
+ */
27
+ export declare const inject_parity_handles: () => InjectedParityHandles;
28
+ //# sourceMappingURL=provided_context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provided_context.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/provided_context.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAwB9B,OAAO,EAEN,KAAK,sCAAsC,EAC3C,KAAK,qCAAqC,EAC1C,MAAM,YAAY,CAAC;AAEpB,OAAO,QAAQ,QAAQ,CAAC;IACvB,UAAiB,eAAe;QAC/B,iFAAiF;QACjF,cAAc,EAAE,qCAAqC,CAAC;QACtD,6FAA6F;QAC7F,eAAe,EAAE,qCAAqC,CAAC;QACvD,4CAA4C;QAC5C,eAAe,EAAE,qCAAqC,CAAC;KACvD;CACD;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAAO,sCACiB,CAAC;AAE3D,6FAA6F;AAC7F,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,CAAC,EAAE,sCAAsC,CAAC;IACnD,QAAQ,CAAC,CAAC,EAAE,sCAAsC,CAAC;CACnD;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAAO,qBAGvC,CAAC"}
@@ -0,0 +1,35 @@
1
+ import '../assert_dev_env.js';
2
+ /**
3
+ * The vitest `ProvidedContext` keys the cross-backend global setups provide,
4
+ * and the helpers a `*.cross.test.ts` file reads them with.
5
+ *
6
+ * `create_cross_backend_global_setup` provides one backend's handle as
7
+ * `backend_handle`; `create_dual_spawn_global_setup` provides two, as
8
+ * `parity_handle_a` / `parity_handle_b` by default. This module augments
9
+ * vitest's `ProvidedContext` with those keys, so a test file that imports
10
+ * `inject_backend_handle` (or `inject_parity_handles`) gets the typed `inject`
11
+ * with no augmentation of its own. A project providing other keys — a dual
12
+ * spawn under its own `provide_keys`, a probe result — augments
13
+ * `ProvidedContext` for those in its own module, beside this one.
14
+ *
15
+ * vitest refuses a value that isn't serializable, so the handles cross as
16
+ * `SerializableBootstrappedBackendHandle`; the helpers rebuild a usable handle
17
+ * with `reconstruct_bootstrapped_handle`.
18
+ *
19
+ * @module
20
+ */
21
+ import { inject } from 'vitest';
22
+ import { reconstruct_bootstrapped_handle } from './setup.js';
23
+ /**
24
+ * The backend the project's `globalSetup` spawned, rebuilt from the provided
25
+ * `backend_handle`. Call at a test file's top level.
26
+ */
27
+ export const inject_backend_handle = () => reconstruct_bootstrapped_handle(inject('backend_handle'));
28
+ /**
29
+ * The two backends a dual-spawn project provides as `parity_handle_a` /
30
+ * `parity_handle_b`, rebuilt. Call at a test file's top level.
31
+ */
32
+ export const inject_parity_handles = () => ({
33
+ a: reconstruct_bootstrapped_handle(inject('parity_handle_a')),
34
+ b: reconstruct_bootstrapped_handle(inject('parity_handle_b'))
35
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"query_shape.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/query_shape.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAwC9B,OAAO,KAAK,EAAE,uCAAuC,EAAE,MAAM,YAAY,CAAC;AAG1E;;;;;GAKG;AACH,MAAM,MAAM,0BAA0B,GAAG,uCAAuC,CAAC;AAQjF,eAAO,MAAM,gCAAgC,GAAI,SAAS,0BAA0B,KAAG,IAkJtF,CAAC"}
1
+ {"version":3,"file":"query_shape.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/query_shape.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAwC9B,OAAO,KAAK,EAAE,uCAAuC,EAAE,MAAM,YAAY,CAAC;AAG1E;;;;;GAKG;AACH,MAAM,MAAM,0BAA0B,GAAG,uCAAuC,CAAC;AAKjF,eAAO,MAAM,gCAAgC,GAAI,SAAS,0BAA0B,KAAG,IAqJtF,CAAC"}
@@ -19,7 +19,7 @@ import '../assert_dev_env.js';
19
19
  * first-wins; a duplicated `method` must dispatch the first one on every
20
20
  * backend (a last-wins reader dispatches a different method per backend on
21
21
  * the same request).
22
- * - **`GET /api/facts/:hash`** (gated on `capabilities.fact_serving`) —
22
+ * - **`GET /api/facts/:hash`** (gated on `capabilities.fact_serving_admin_hash`) —
23
23
  * strict query schema: unknown keys and a malformed `acting` are 400
24
24
  * `invalid_query_params` even for an anonymous caller (query precedes the
25
25
  * 401 guard), while a duplicated `acting` takes the first occurrence.
@@ -35,9 +35,7 @@ import { describe, test, assert } from 'vitest';
35
35
  import { account_verify_action_spec } from '../../auth/account_action_specs.js';
36
36
  import { ERROR_INVALID_QUERY_PARAMS } from '../../http/error_schemas.js';
37
37
  import { test_if } from './capabilities.js';
38
- import { SPINE_RPC_PATH } from './spine_surface_constants.js';
39
- /** The status route every spine serves (bundled into the account family). */
40
- const STATUS_PATH = '/api/account/status';
38
+ import { SPINE_ACCOUNT_STATUS_PATH, SPINE_RPC_PATH } from './spine_surface_constants.js';
41
39
  /** A well-formed blake3 hash that references no stored fact. */
42
40
  const MISSING_HASH = `blake3:${'a'.repeat(64)}`;
43
41
  export const describe_query_shape_cross_tests = (options) => {
@@ -51,7 +49,7 @@ export const describe_query_shape_cross_tests = (options) => {
51
49
  // persona; last-wins would fall through to `actor: null`, and a
52
50
  // derived-serde extractor would 400 before the handler ran.
53
51
  const nil = '00000000-0000-0000-0000-000000000000';
54
- const res = await fixture.transport(`${STATUS_PATH}?acting=${fixture.actor.id}&acting=${nil}`, { method: 'GET', headers: fixture.create_session_headers() });
52
+ const res = await fixture.transport(`${SPINE_ACCOUNT_STATUS_PATH}?acting=${fixture.actor.id}&acting=${nil}`, { method: 'GET', headers: fixture.create_session_headers() });
55
53
  assert.strictEqual(res.status, 200);
56
54
  const body = (await res.json());
57
55
  assert.strictEqual(body.actor?.id, fixture.actor.id, 'first acting occurrence must win');
@@ -60,7 +58,7 @@ export const describe_query_shape_cross_tests = (options) => {
60
58
  const fixture = await setup_test();
61
59
  // The keeper has one actor: an omitted selector resolves it, while a
62
60
  // malformed one answers account-only.
63
- const omitted = await fixture.transport(STATUS_PATH, {
61
+ const omitted = await fixture.transport(SPINE_ACCOUNT_STATUS_PATH, {
64
62
  method: 'GET',
65
63
  headers: fixture.create_session_headers()
66
64
  });
@@ -68,7 +66,7 @@ export const describe_query_shape_cross_tests = (options) => {
68
66
  const omitted_body = (await omitted.json());
69
67
  assert.strictEqual(omitted_body.actor?.id, fixture.actor.id);
70
68
  for (const raw of ['not-a-uuid', '', `"${fixture.actor.id}"`]) {
71
- const res = await fixture.transport(`${STATUS_PATH}?acting=${encodeURIComponent(raw)}`, {
69
+ const res = await fixture.transport(`${SPINE_ACCOUNT_STATUS_PATH}?acting=${encodeURIComponent(raw)}`, {
72
70
  method: 'GET',
73
71
  headers: fixture.create_session_headers()
74
72
  });
@@ -83,14 +81,14 @@ export const describe_query_shape_cross_tests = (options) => {
83
81
  // The status route has no query schema — an anonymous prober with a
84
82
  // junk query must hear the same 401 as a clean one (a pre-handler
85
83
  // query reject here is a backend fingerprint).
86
- const dup = await anon(`${STATUS_PATH}?acting=a&acting=b`, { method: 'GET' });
84
+ const dup = await anon(`${SPINE_ACCOUNT_STATUS_PATH}?acting=a&acting=b`, { method: 'GET' });
87
85
  assert.strictEqual(dup.status, 401);
88
- const unknown = await anon(`${STATUS_PATH}?foo=1&bar=2`, { method: 'GET' });
86
+ const unknown = await anon(`${SPINE_ACCOUNT_STATUS_PATH}?foo=1&bar=2`, { method: 'GET' });
89
87
  assert.strictEqual(unknown.status, 401);
90
88
  });
91
89
  test_if(capabilities.account_status, 'status: unknown query keys are ignored for an authed caller (no strict schema)', async () => {
92
90
  const fixture = await setup_test();
93
- const res = await fixture.transport(`${STATUS_PATH}?foo=1`, {
91
+ const res = await fixture.transport(`${SPINE_ACCOUNT_STATUS_PATH}?foo=1`, {
94
92
  method: 'GET',
95
93
  headers: fixture.create_session_headers()
96
94
  });
@@ -107,7 +105,7 @@ export const describe_query_shape_cross_tests = (options) => {
107
105
  assert.strictEqual(body.id, 7, 'first id occurrence must win');
108
106
  assert.ok(body.result !== undefined, 'first method occurrence must dispatch');
109
107
  });
110
- test_if(capabilities.fact_serving, 'bare-hash facts: unknown query key → 400 invalid_query_params, even anonymous', async () => {
108
+ test_if(capabilities.fact_serving_admin_hash, 'bare-hash facts: unknown query key → 400 invalid_query_params, even anonymous', async () => {
111
109
  const fixture = await setup_test();
112
110
  // Authed admin (the keeper): the strict query schema refuses the
113
111
  // unknown key before the handler can 404 the missing fact.
@@ -126,7 +124,7 @@ export const describe_query_shape_cross_tests = (options) => {
126
124
  const anon_clean = await anon(`/api/facts/${MISSING_HASH}`, { method: 'GET' });
127
125
  assert.strictEqual(anon_clean.status, 401);
128
126
  });
129
- test_if(capabilities.fact_serving, 'bare-hash facts: duplicated acting takes the first occurrence; malformed acting → 400', async () => {
127
+ test_if(capabilities.fact_serving_admin_hash, 'bare-hash facts: duplicated acting takes the first occurrence; malformed acting → 400', async () => {
130
128
  const fixture = await setup_test();
131
129
  // First occurrence is the keeper's real actor; the second is
132
130
  // garbage. First-wins passes the query phase and reaches the
@@ -13,13 +13,13 @@ import '../assert_dev_env.js';
13
13
  * `/ready` is a plain public REST route — not an RPC method, not one of the six
14
14
  * REST auth routes — and it's deliberately **off** the declared spine surface
15
15
  * (`create_spine_surface_spec`), like ws/sse/cells/fact-serving. So it needs a
16
- * bespoke imperative suite (à la `origin.cross.test.ts`), gated on
16
+ * bespoke imperative suite (à la `describe_origin_cross_tests`), gated on
17
17
  * `capabilities.ready`, rather than a `conformance_table` row or generic
18
18
  * round-trip enumeration. The drift → `503` path stays per-impl unit tests.
19
19
  *
20
20
  * Runs both legs via the shared `{setup_test, capabilities}` protocol: the
21
21
  * in-process leg (`cross_backend/ready_parity.db.test.ts`, plain `gro test`) and
22
- * the cross-process leg (`cross_backend/ready.cross.test.ts`, the TS spine
22
+ * the cross-process leg (`cross_backend/spine_suites.cross.test.ts`, the TS spine
23
23
  * binaries + Rust `testing_spine_stub` over real HTTP).
24
24
  *
25
25
  * @module
@@ -1,6 +1,7 @@
1
1
  import '../assert_dev_env.js';
2
2
  import type { BackendCapabilities } from './capabilities.js';
3
- import type { TestAccountFixture, TestFixture } from './setup.js';
3
+ import type { TestAccount } from '../app_server.js';
4
+ import type { TestFixture } from './setup.js';
4
5
  /**
5
6
  * POST a JSON body to a REST route on `account`'s session, asserting `200`.
6
7
  *
@@ -9,7 +10,7 @@ import type { TestAccountFixture, TestFixture } from './setup.js';
9
10
  * @param path - the REST route path
10
11
  * @param body - the JSON request body
11
12
  */
12
- export declare const cross_post_as: (fixture: TestFixture, account: TestAccountFixture, path: string, body: unknown) => Promise<void>;
13
+ export declare const cross_post_as: (fixture: TestFixture, account: TestAccount, path: string, body: unknown) => Promise<void>;
13
14
  /**
14
15
  * Revoke every API token of `account_id` over the keeper's admin session
15
16
  * (`admin_token_revoke_all`), asserting success.
@@ -45,7 +46,7 @@ export interface AccountRevocation {
45
46
  * `target` must have been created with `DEFAULT_TEST_PASSWORD`, which the
46
47
  * password-change row presents.
47
48
  */
48
- readonly revoke: (fixture: TestFixture, target: TestAccountFixture) => Promise<void>;
49
+ readonly revoke: (fixture: TestFixture, target: TestAccount) => Promise<void>;
49
50
  }
50
51
  /** Configuration for `create_account_revocations`. */
51
52
  export interface AccountRevocationsOptions {
@@ -1 +1 @@
1
- {"version":3,"file":"revocation_drivers.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/revocation_drivers.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AA4B9B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAElE;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,GACzB,SAAS,WAAW,EACpB,SAAS,kBAAkB,EAC3B,MAAM,MAAM,EACZ,MAAM,OAAO,KACX,OAAO,CAAC,IAAI,CAOd,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,4BAA4B,GACxC,SAAS,WAAW,EACpB,UAAU,MAAM,EAChB,YAAY,MAAM,KAChB,OAAO,CAAC,IAAI,CASd,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,GAC/B,SAAS,WAAW,EACpB,UAAU,MAAM,EAChB,YAAY,MAAM,KAChB,OAAO,CAAC,IAAI,CASd,CAAC;AAEF,2EAA2E;AAC3E,MAAM,WAAW,iBAAiB;IACjC,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4FAA4F;IAC5F,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,kBAAkB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACrF;AAED,sDAAsD;AACtD,MAAM,WAAW,yBAAyB;IACzC,8EAA8E;IAC9E,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;IAC3C,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,8BAA8B;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,uCAAuC;IACvC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,0BAA0B,GACtC,SAAS,yBAAyB,KAChC,aAAa,CAAC,iBAAiB,CAiCjC,CAAC"}
1
+ {"version":3,"file":"revocation_drivers.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/revocation_drivers.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AA4B9B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,GACzB,SAAS,WAAW,EACpB,SAAS,WAAW,EACpB,MAAM,MAAM,EACZ,MAAM,OAAO,KACX,OAAO,CAAC,IAAI,CAOd,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,4BAA4B,GACxC,SAAS,WAAW,EACpB,UAAU,MAAM,EAChB,YAAY,MAAM,KAChB,OAAO,CAAC,IAAI,CASd,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,GAC/B,SAAS,WAAW,EACpB,UAAU,MAAM,EAChB,YAAY,MAAM,KAChB,OAAO,CAAC,IAAI,CASd,CAAC;AAEF,2EAA2E;AAC3E,MAAM,WAAW,iBAAiB;IACjC,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4FAA4F;IAC5F,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9E;AAED,sDAAsD;AACtD,MAAM,WAAW,yBAAyB;IACzC,8EAA8E;IAC9E,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;IAC3C,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,8BAA8B;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,uCAAuC;IACvC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,0BAA0B,GACtC,SAAS,yBAAyB,KAChC,aAAa,CAAC,iBAAiB,CAiCjC,CAAC"}
@@ -20,7 +20,7 @@ import '../assert_dev_env.js';
20
20
  import { assert } from 'vitest';
21
21
  import { account_purge_action_spec, admin_token_revoke_all_action_spec } from '../../auth/admin_action_specs.js';
22
22
  import { DEFAULT_TEST_PASSWORD } from '../test_credentials.js';
23
- import { cross_rpc_call } from './cell_cross_helpers.js';
23
+ import { cross_rpc_call } from './cross_rpc.js';
24
24
  /**
25
25
  * POST a JSON body to a REST route on `account`'s session, asserting `200`.
26
26
  *
@@ -1,5 +1,6 @@
1
1
  import '../assert_dev_env.js';
2
- import type { TestAccountFixture, TestFixture } from './setup.js';
2
+ import type { TestAccount } from '../app_server.js';
3
+ import type { TestFixture } from './setup.js';
3
4
  /** Options for the role-grant fixtures. */
4
5
  export interface RoleGrantFixtureOptions {
5
6
  /** The role to offer. Default `ROLE_ADMIN`, the one builtin admin-grantable role. */
@@ -31,5 +32,5 @@ export declare const create_pending_role_grant_offer: (fixture: TestFixture, to_
31
32
  * @param options - the role and the RPC path
32
33
  * @returns the active grant's id
33
34
  */
34
- export declare const create_active_role_grant: (fixture: TestFixture, recipient: TestAccountFixture, options?: RoleGrantFixtureOptions) => Promise<string>;
35
+ export declare const create_active_role_grant: (fixture: TestFixture, recipient: TestAccount, options?: RoleGrantFixtureOptions) => Promise<string>;
35
36
  //# sourceMappingURL=role_grant_cross_helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"role_grant_cross_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/role_grant_cross_helpers.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAoB9B,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAElE,2CAA2C;AAC3C,MAAM,WAAW,uBAAuB;IACvC,qFAAqF;IACrF,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,4DAA4D;IAC5D,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,+BAA+B,GAC3C,SAAS,WAAW,EACpB,eAAe,MAAM,EACrB,kBAAiB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAoC,EAC1E,UAAS,uBAA4B,KACnC,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAWxB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,wBAAwB,GACpC,SAAS,WAAW,EACpB,WAAW,kBAAkB,EAC7B,UAAS,uBAA4B,KACnC,OAAO,CAAC,MAAM,CAgBhB,CAAC"}
1
+ {"version":3,"file":"role_grant_cross_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/role_grant_cross_helpers.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAoB9B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,2CAA2C;AAC3C,MAAM,WAAW,uBAAuB;IACvC,qFAAqF;IACrF,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,4DAA4D;IAC5D,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,+BAA+B,GAC3C,SAAS,WAAW,EACpB,eAAe,MAAM,EACrB,kBAAiB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAoC,EAC1E,UAAS,uBAA4B,KACnC,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAWxB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,wBAAwB,GACpC,SAAS,WAAW,EACpB,WAAW,WAAW,EACtB,UAAS,uBAA4B,KACnC,OAAO,CAAC,MAAM,CAgBhB,CAAC"}
@@ -0,0 +1,13 @@
1
+ import '../assert_dev_env.js';
2
+ import type { RpcPathCrossSuiteOptions } from './setup.js';
3
+ /** Options for `describe_role_grant_offer_lifecycle_cross_tests`. */
4
+ export interface RoleGrantOfferLifecycleCrossTestOptions extends RpcPathCrossSuiteOptions {
5
+ /**
6
+ * The role offered — one the backend's registry holds with the `admin`
7
+ * grant path. Default `SPINE_PARTICIPANT_ROLE`, the spine's own; a backend
8
+ * with only the builtin roles passes `ROLE_ADMIN`.
9
+ */
10
+ readonly role?: string;
11
+ }
12
+ export declare const describe_role_grant_offer_lifecycle_cross_tests: (options: RoleGrantOfferLifecycleCrossTestOptions) => void;
13
+ //# sourceMappingURL=role_grant_offer_lifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"role_grant_offer_lifecycle.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/role_grant_offer_lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAmD9B,OAAO,KAAK,EAAE,wBAAwB,EAAe,MAAM,YAAY,CAAC;AAMxE,qEAAqE;AACrE,MAAM,WAAW,uCAAwC,SAAQ,wBAAwB;IACxF;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,eAAO,MAAM,+CAA+C,GAC3D,SAAS,uCAAuC,KAC9C,IAyRF,CAAC"}
@@ -0,0 +1,203 @@
1
+ import '../assert_dev_env.js';
2
+ /**
3
+ * Cross-backend parity suite for the **role-grant-offer decline and retract
4
+ * refusals** — the error paths beneath the happy-path WS notification suite
5
+ * (`describe_role_grant_offer_notification_ws_tests`), which is the only other
6
+ * cross-process caller of these two verbs.
7
+ *
8
+ * What both spines must agree on, per the handlers
9
+ * (`auth/role_grant_offer_actions.ts` and the queries behind them):
10
+ *
11
+ * - **not yours → 404** `role_grant_offer_not_found`. Decline is scoped to the
12
+ * recipient account and retract to the grantor actor, so an offer the caller
13
+ * is not party to answers the same `not_found` as an id that names no offer
14
+ * (`docs/security.md` §"404-over-403 is the general mask"), and the offer is
15
+ * left pending. The scope check comes before the terminal check, so a
16
+ * stranger learns nothing of an offer's state either.
17
+ * - **already decided → 400** `invalid_request` with reason
18
+ * `role_grant_offer_terminal` — a decline or retract after an accept, a
19
+ * second decline, a second retract, and either one after the other.
20
+ * - **one audit row per success, none per refusal.** A decline writes
21
+ * `role_grant_offer_decline` attributed to the recipient and targeting the
22
+ * grantor, a retract `role_grant_offer_retract` attributed to the grantor
23
+ * and targeting the recipient, each with its event's metadata; the refusals
24
+ * above write nothing. Read through `list_audit_events`, which drains first
25
+ * and parses each row's metadata against its event's schema.
26
+ *
27
+ * Multi-step (each case needs an offer in a given state), so this is an
28
+ * imperative suite; the single-request rows — decline and retract of an id
29
+ * that names no offer — live in the conformance security slate. The verbs are
30
+ * on every spine's standard RPC surface, so the suite is ungated. The keeper
31
+ * is the grantor, so the fixture's keeper must hold `ROLE_ADMIN`
32
+ * (`extra_keeper_roles`), and it offers an admin-grantable role — the
33
+ * `role` option, `SPINE_PARTICIPANT_ROLE` by default; `ROLE_ADMIN` serves a
34
+ * backend with only the builtin roles.
35
+ *
36
+ * @module
37
+ */
38
+ import { assert, describe, test } from 'vitest';
39
+ import { rpc_call } from '../rpc_helpers.js';
40
+ import { ERROR_ROLE_GRANT_OFFER_NOT_FOUND, ERROR_ROLE_GRANT_OFFER_TERMINAL } from '../../auth/role_grant_offer_action_specs.js';
41
+ import { JSONRPC_INVALID_REQUEST } from '../../http/jsonrpc.js';
42
+ import { JSONRPC_ERROR_CODES } from '../../http/jsonrpc_errors.js';
43
+ import { assert_audit_metadata_fields, list_audit_events } from './audit_cross_helpers.js';
44
+ import { create_pending_role_grant_offer } from './role_grant_cross_helpers.js';
45
+ import { SPINE_PARTICIPANT_ROLE, SPINE_RPC_PATH } from './spine_surface_constants.js';
46
+ /** A well-formed UUID that names no offer. */
47
+ const NIL_UUID = '00000000-0000-0000-0000-000000000000';
48
+ export const describe_role_grant_offer_lifecycle_cross_tests = (options) => {
49
+ const { setup_test } = options;
50
+ const rpc_path = options.rpc_path ?? SPINE_RPC_PATH;
51
+ const role = options.role ?? SPINE_PARTICIPANT_ROLE;
52
+ const rpc = (fixture, method, params, headers) => rpc_call({ app: fixture.fresh_transport(), path: rpc_path, method, params, headers });
53
+ /** A pending `role` offer from the keeper to `recipient`. */
54
+ const create_offer = (fixture, recipient) => create_pending_role_grant_offer(fixture, recipient.account.id, undefined, {
55
+ role,
56
+ rpc_path
57
+ });
58
+ const decline = (fixture, offer_id, headers, reason) => rpc(fixture, 'role_grant_offer_decline', reason === undefined ? { offer_id } : { offer_id, reason }, headers);
59
+ const retract = (fixture, offer_id, headers) => rpc(fixture, 'role_grant_offer_retract', { offer_id }, headers);
60
+ const accept = (fixture, offer_id, headers) => rpc(fixture, 'role_grant_offer_accept', { offer_id }, headers);
61
+ const assert_ok = (res, label) => {
62
+ assert.ok(res.ok, `${label} must succeed: ${JSON.stringify(res)}`);
63
+ };
64
+ /** The masked refusal, returned as `{status, error}` for an identity comparison. */
65
+ const assert_not_found = (res, label) => {
66
+ assert.ok(!res.ok, `${label} must be refused: ${JSON.stringify(res)}`);
67
+ assert.strictEqual(res.status, 404, label);
68
+ assert.strictEqual(res.error.code, JSONRPC_ERROR_CODES.not_found, label);
69
+ assert.deepStrictEqual(res.error.data, { reason: ERROR_ROLE_GRANT_OFFER_NOT_FOUND }, label);
70
+ return { status: res.status, error: res.error };
71
+ };
72
+ const assert_terminal = (res, label) => {
73
+ assert.ok(!res.ok, `${label} must be refused: ${JSON.stringify(res)}`);
74
+ assert.strictEqual(res.status, 400, label);
75
+ assert.strictEqual(res.error.code, JSONRPC_INVALID_REQUEST, label);
76
+ assert.deepStrictEqual(res.error.data, { reason: ERROR_ROLE_GRANT_OFFER_TERMINAL }, label);
77
+ };
78
+ /** Whether `offer_id` is still in the recipient's pending inbox. */
79
+ const is_pending = async (fixture, recipient, offer_id) => {
80
+ const listed = await rpc(fixture, 'role_grant_offer_list', {}, recipient.create_session_headers());
81
+ if (!listed.ok)
82
+ assert.fail(`role_grant_offer_list failed: ${JSON.stringify(listed)}`);
83
+ const { offers } = listed.result;
84
+ return offers.some((offer) => offer.id === offer_id);
85
+ };
86
+ describe('role_grant_offer decline + retract refusals', () => {
87
+ test('a decline by anyone but the recipient → 404, identical to a missing offer; the offer stays pending', async () => {
88
+ const fixture = await setup_test();
89
+ const recipient = await fixture.create_account({ username: 'lifecycle_decline_to' });
90
+ const stranger = await fixture.create_account({ username: 'lifecycle_decline_by' });
91
+ const offer = await create_offer(fixture, recipient);
92
+ const missing = assert_not_found(await decline(fixture, NIL_UUID, stranger.create_session_headers()), 'a decline of a missing offer');
93
+ const by_stranger = assert_not_found(await decline(fixture, offer.id, stranger.create_session_headers()), 'a stranger declining');
94
+ assert.deepStrictEqual(by_stranger, missing, 'a stranger declining a real offer must hear what a missing offer answers');
95
+ // the grantor is a party to the offer, but not its recipient
96
+ assert_not_found(await decline(fixture, offer.id, fixture.create_session_headers()), 'the grantor declining its own offer');
97
+ assert.ok(await is_pending(fixture, recipient, offer.id), 'the refusals leave it pending');
98
+ assert_ok(await decline(fixture, offer.id, recipient.create_session_headers()), 'decline');
99
+ });
100
+ test('a retract by anyone but the grantor → 404, identical to a missing offer; the offer stays pending', async () => {
101
+ const fixture = await setup_test();
102
+ const recipient = await fixture.create_account({ username: 'lifecycle_retract_to' });
103
+ const stranger = await fixture.create_account({ username: 'lifecycle_retract_by' });
104
+ const offer = await create_offer(fixture, recipient);
105
+ const missing = assert_not_found(await retract(fixture, NIL_UUID, stranger.create_session_headers()), 'a retract of a missing offer');
106
+ const by_stranger = assert_not_found(await retract(fixture, offer.id, stranger.create_session_headers()), 'a stranger retracting');
107
+ assert.deepStrictEqual(by_stranger, missing, 'a stranger retracting a real offer must hear what a missing offer answers');
108
+ assert_not_found(await retract(fixture, offer.id, recipient.create_session_headers()), 'the recipient retracting');
109
+ assert.ok(await is_pending(fixture, recipient, offer.id), 'the refusals leave it pending');
110
+ assert_ok(await retract(fixture, offer.id, fixture.create_session_headers()), 'retract');
111
+ });
112
+ test('a decline or retract after accept → 400 role_grant_offer_terminal; a stranger still gets 404', async () => {
113
+ const fixture = await setup_test();
114
+ const recipient = await fixture.create_account({ username: 'lifecycle_accepted' });
115
+ const stranger = await fixture.create_account({ username: 'lifecycle_after_accept' });
116
+ const offer = await create_offer(fixture, recipient);
117
+ assert_ok(await accept(fixture, offer.id, recipient.create_session_headers()), 'accept');
118
+ assert_terminal(await decline(fixture, offer.id, recipient.create_session_headers()), 'a decline after accept');
119
+ assert_terminal(await retract(fixture, offer.id, fixture.create_session_headers()), 'a retract after accept');
120
+ // the scope check runs before the terminal check, so a non-party
121
+ // learns nothing of the offer's state
122
+ assert_not_found(await decline(fixture, offer.id, stranger.create_session_headers()), 'a stranger declining an accepted offer');
123
+ assert_not_found(await retract(fixture, offer.id, stranger.create_session_headers()), 'a stranger retracting an accepted offer');
124
+ });
125
+ test('a second decline, a second retract, and either after the other → 400 role_grant_offer_terminal', async () => {
126
+ const fixture = await setup_test();
127
+ const recipient = await fixture.create_account({ username: 'lifecycle_twice' });
128
+ const recipient_headers = recipient.create_session_headers();
129
+ const grantor_headers = fixture.create_session_headers();
130
+ const declined = await create_offer(fixture, recipient);
131
+ assert_ok(await decline(fixture, declined.id, recipient_headers), 'the first decline');
132
+ assert_terminal(await decline(fixture, declined.id, recipient_headers), 'a second decline');
133
+ assert_terminal(await retract(fixture, declined.id, grantor_headers), 'a retract after decline');
134
+ const retracted = await create_offer(fixture, recipient);
135
+ assert_ok(await retract(fixture, retracted.id, grantor_headers), 'the first retract');
136
+ assert_terminal(await retract(fixture, retracted.id, grantor_headers), 'a second retract');
137
+ assert_terminal(await decline(fixture, retracted.id, recipient_headers), 'a decline after retract');
138
+ });
139
+ test('a decline and a retract each write one audit row; their refusals write none', async () => {
140
+ const fixture = await setup_test();
141
+ const recipient = await fixture.create_account({ username: 'lifecycle_audited' });
142
+ const stranger = await fixture.create_account({ username: 'lifecycle_unaudited' });
143
+ const recipient_headers = recipient.create_session_headers();
144
+ const grantor_headers = fixture.create_session_headers();
145
+ const with_reason = await create_offer(fixture, recipient);
146
+ assert_ok(await decline(fixture, with_reason.id, recipient_headers, 'not now'), 'decline');
147
+ const without_reason = await create_offer(fixture, recipient);
148
+ assert_ok(await decline(fixture, without_reason.id, recipient_headers), 'decline');
149
+ const retracted = await create_offer(fixture, recipient);
150
+ assert_ok(await retract(fixture, retracted.id, grantor_headers), 'retract');
151
+ const read = async () => ({
152
+ declines: await list_audit_events(fixture, { event_type: 'role_grant_offer_decline' }, rpc_path),
153
+ retracts: await list_audit_events(fixture, { event_type: 'role_grant_offer_retract' }, rpc_path)
154
+ });
155
+ const before = await read();
156
+ const decline_row = (offer_id) => {
157
+ const rows = before.declines.filter((e) => e.metadata?.offer_id === offer_id);
158
+ assert.strictEqual(rows.length, 1, `one role_grant_offer_decline row for ${offer_id}`);
159
+ return rows[0];
160
+ };
161
+ for (const [offer_id, reason] of [
162
+ [with_reason.id, 'not now'],
163
+ [without_reason.id, undefined]
164
+ ]) {
165
+ const row = decline_row(offer_id);
166
+ assert.strictEqual(row.outcome, 'success');
167
+ // a decline is the recipient's act, addressed to the grantor
168
+ assert.strictEqual(row.account_id, recipient.account.id);
169
+ assert.strictEqual(row.actor_id, recipient.actor.id);
170
+ assert.strictEqual(row.target_account_id, fixture.account.id);
171
+ assert.strictEqual(row.target_actor_id, fixture.actor.id);
172
+ // a decline without a reason records none — absent, not null
173
+ assert_audit_metadata_fields(fixture, row.metadata, reason === undefined
174
+ ? { offer_id, role, scope_id: null }
175
+ : { offer_id, role, scope_id: null, reason }, reason === undefined ? ['reason'] : []);
176
+ }
177
+ assert.strictEqual(before.retracts.length, 1, 'one role_grant_offer_retract row');
178
+ const retract_row = before.retracts[0];
179
+ assert.strictEqual(retract_row.outcome, 'success');
180
+ // a retract is the grantor's act, addressed to the recipient; the
181
+ // offer named no actor, so no target actor
182
+ assert.strictEqual(retract_row.account_id, fixture.account.id);
183
+ assert.strictEqual(retract_row.actor_id, fixture.actor.id);
184
+ assert.strictEqual(retract_row.target_account_id, recipient.account.id);
185
+ assert.strictEqual(retract_row.target_actor_id, null);
186
+ assert_audit_metadata_fields(fixture, retract_row.metadata, {
187
+ offer_id: retracted.id,
188
+ role,
189
+ scope_id: null
190
+ });
191
+ // every refusal: not a party, then already decided
192
+ const pending = await create_offer(fixture, recipient);
193
+ assert_not_found(await decline(fixture, pending.id, stranger.create_session_headers()), 'a stranger declining');
194
+ assert_not_found(await retract(fixture, pending.id, stranger.create_session_headers()), 'a stranger retracting');
195
+ assert_terminal(await decline(fixture, with_reason.id, recipient_headers), 'a re-decline');
196
+ assert_terminal(await retract(fixture, retracted.id, grantor_headers), 'a re-retract');
197
+ assert_terminal(await decline(fixture, retracted.id, recipient_headers), 'a decline after retract');
198
+ const after = await read();
199
+ assert.strictEqual(after.declines.length, before.declines.length, 'no decline row added');
200
+ assert.strictEqual(after.retracts.length, before.retracts.length, 'no retract row added');
201
+ });
202
+ });
203
+ };
@@ -1,16 +1,13 @@
1
1
  import '../assert_dev_env.js';
2
2
  import { type BackendCapabilities } from './capabilities.js';
3
3
  import type { SetupTest } from './setup.js';
4
+ import { type WsEndpointTarget } from './ws_endpoint.js';
4
5
  /** Configuration for `describe_role_grant_offer_notification_ws_tests`. */
5
- export interface RoleGrantOfferNotificationWsTestOptions {
6
+ export interface RoleGrantOfferNotificationWsTestOptions extends WsEndpointTarget {
6
7
  /** Per-test fixture producer (`default_cross_process_setup(handle, ...)`). */
7
8
  readonly setup_test: SetupTest;
8
9
  /** Backend capability flags; every case gates on `capabilities.ws`. */
9
10
  readonly capabilities: BackendCapabilities;
10
- /** Base URL the backend is reachable at (e.g. `http://localhost:1178`). */
11
- readonly base_url: string;
12
- /** WebSocket endpoint path on the backend (e.g. `/api/ws`). */
13
- readonly ws_path: string;
14
11
  /**
15
12
  * The roles `ws_path` gates its upgrade on (its `required_roles`), or
16
13
  * omitted / `[]` for an ungated endpoint. Declare them for a backend whose
@@ -1 +1 @@
1
- {"version":3,"file":"role_grant_offer_notification_ws.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/role_grant_offer_notification_ws.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AA4E9B,OAAO,EAAE,KAAK,mBAAmB,EAAW,MAAM,mBAAmB,CAAC;AAKtE,OAAO,KAAK,EAAE,SAAS,EAAe,MAAM,YAAY,CAAC;AAKzD,2EAA2E;AAC3E,MAAM,WAAW,uCAAuC;IACvD,8EAA8E;IAC9E,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC;IAC/B,uEAAuE;IACvE,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;IAC3C,2EAA2E;IAC3E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;;;;OAMG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACnD;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,+CAA+C,GAC3D,SAAS,uCAAuC,KAC9C,IA6VF,CAAC"}
1
+ {"version":3,"file":"role_grant_offer_notification_ws.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/role_grant_offer_notification_ws.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAkF9B,OAAO,EAAE,KAAK,mBAAmB,EAAW,MAAM,mBAAmB,CAAC;AAKtE,OAAO,KAAK,EAAE,SAAS,EAAe,MAAM,YAAY,CAAC;AAEzD,OAAO,EAAmB,KAAK,gBAAgB,EAAyB,MAAM,kBAAkB,CAAC;AAKjG,2EAA2E;AAC3E,MAAM,WAAW,uCAAwC,SAAQ,gBAAgB;IAChF,8EAA8E;IAC9E,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC;IAC/B,uEAAuE;IACvE,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;IAC3C;;;;;;OAMG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACnD;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,+CAA+C,GAC3D,SAAS,uCAAuC,KAC9C,IAgbF,CAAC"}