@fuzdev/fuz_app 0.140.0 → 0.142.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 (311) hide show
  1. package/dist/actions/CLAUDE.md +72 -22
  2. package/dist/actions/action_rpc.d.ts +5 -1
  3. package/dist/actions/action_rpc.d.ts.map +1 -1
  4. package/dist/actions/action_rpc.js +9 -1
  5. package/dist/actions/connection_closer.d.ts +44 -4
  6. package/dist/actions/connection_closer.d.ts.map +1 -1
  7. package/dist/actions/connection_closer.js +33 -3
  8. package/dist/actions/perform_action.d.ts +10 -0
  9. package/dist/actions/perform_action.d.ts.map +1 -1
  10. package/dist/actions/perform_action.js +23 -9
  11. package/dist/actions/register_action_ws.d.ts +42 -6
  12. package/dist/actions/register_action_ws.d.ts.map +1 -1
  13. package/dist/actions/register_action_ws.js +87 -19
  14. package/dist/actions/register_ws_endpoint.d.ts +15 -6
  15. package/dist/actions/register_ws_endpoint.d.ts.map +1 -1
  16. package/dist/actions/register_ws_endpoint.js +10 -4
  17. package/dist/actions/socket.svelte.d.ts +19 -4
  18. package/dist/actions/socket.svelte.d.ts.map +1 -1
  19. package/dist/actions/socket.svelte.js +31 -4
  20. package/dist/actions/transports.d.ts +30 -1
  21. package/dist/actions/transports.d.ts.map +1 -1
  22. package/dist/actions/transports.js +30 -1
  23. package/dist/actions/transports_ws_auth_guard.d.ts +13 -6
  24. package/dist/actions/transports_ws_auth_guard.d.ts.map +1 -1
  25. package/dist/actions/transports_ws_auth_guard.js +24 -10
  26. package/dist/actions/transports_ws_backend.d.ts +51 -5
  27. package/dist/actions/transports_ws_backend.d.ts.map +1 -1
  28. package/dist/actions/transports_ws_backend.js +62 -9
  29. package/dist/actions/ws_endpoint_spec.d.ts +11 -10
  30. package/dist/actions/ws_endpoint_spec.d.ts.map +1 -1
  31. package/dist/auth/CLAUDE.md +44 -22
  32. package/dist/auth/account_actions.d.ts.map +1 -1
  33. package/dist/auth/account_actions.js +12 -1
  34. package/dist/auth/account_route_schema.d.ts +1 -0
  35. package/dist/auth/account_route_schema.d.ts.map +1 -1
  36. package/dist/auth/account_route_schema.js +12 -0
  37. package/dist/auth/account_routes.d.ts +7 -2
  38. package/dist/auth/account_routes.d.ts.map +1 -1
  39. package/dist/auth/account_routes.js +240 -187
  40. package/dist/auth/admin_action_specs.d.ts +6 -1
  41. package/dist/auth/admin_action_specs.d.ts.map +1 -1
  42. package/dist/auth/admin_action_specs.js +6 -1
  43. package/dist/auth/admin_actions.d.ts.map +1 -1
  44. package/dist/auth/admin_actions.js +14 -2
  45. package/dist/auth/api_token.d.ts +20 -0
  46. package/dist/auth/api_token.d.ts.map +1 -1
  47. package/dist/auth/api_token.js +21 -1
  48. package/dist/auth/api_token_queries.d.ts +22 -4
  49. package/dist/auth/api_token_queries.d.ts.map +1 -1
  50. package/dist/auth/api_token_queries.js +11 -6
  51. package/dist/auth/audit_log_routes.d.ts +10 -0
  52. package/dist/auth/audit_log_routes.d.ts.map +1 -1
  53. package/dist/auth/audit_log_routes.js +20 -0
  54. package/dist/auth/audit_log_schema.d.ts +30 -5
  55. package/dist/auth/audit_log_schema.d.ts.map +1 -1
  56. package/dist/auth/audit_log_schema.js +30 -0
  57. package/dist/auth/bearer_auth.d.ts +4 -2
  58. package/dist/auth/bearer_auth.d.ts.map +1 -1
  59. package/dist/auth/bearer_auth.js +19 -8
  60. package/dist/auth/bootstrap_route_schema.d.ts +1 -0
  61. package/dist/auth/bootstrap_route_schema.d.ts.map +1 -1
  62. package/dist/auth/bootstrap_route_schema.js +1 -0
  63. package/dist/auth/bootstrap_routes.d.ts.map +1 -1
  64. package/dist/auth/bootstrap_routes.js +85 -76
  65. package/dist/auth/cell_action_specs.d.ts +7 -3
  66. package/dist/auth/cell_action_specs.d.ts.map +1 -1
  67. package/dist/auth/cell_action_specs.js +9 -5
  68. package/dist/auth/cell_actions.d.ts +3 -3
  69. package/dist/auth/cell_actions.d.ts.map +1 -1
  70. package/dist/auth/cell_actions.js +67 -38
  71. package/dist/auth/cell_authorize.d.ts +69 -8
  72. package/dist/auth/cell_authorize.d.ts.map +1 -1
  73. package/dist/auth/cell_authorize.js +89 -9
  74. package/dist/auth/cell_field_action_specs.d.ts +5 -4
  75. package/dist/auth/cell_field_action_specs.d.ts.map +1 -1
  76. package/dist/auth/cell_field_action_specs.js +7 -7
  77. package/dist/auth/cell_field_actions.d.ts +7 -5
  78. package/dist/auth/cell_field_actions.d.ts.map +1 -1
  79. package/dist/auth/cell_field_actions.js +24 -22
  80. package/dist/auth/cell_grant_action_specs.d.ts +6 -0
  81. package/dist/auth/cell_grant_action_specs.d.ts.map +1 -1
  82. package/dist/auth/cell_grant_action_specs.js +6 -0
  83. package/dist/auth/cell_grant_actions.d.ts +3 -1
  84. package/dist/auth/cell_grant_actions.d.ts.map +1 -1
  85. package/dist/auth/cell_grant_actions.js +16 -2
  86. package/dist/auth/cell_item_action_specs.d.ts +5 -4
  87. package/dist/auth/cell_item_action_specs.d.ts.map +1 -1
  88. package/dist/auth/cell_item_action_specs.js +7 -7
  89. package/dist/auth/cell_item_actions.d.ts +6 -5
  90. package/dist/auth/cell_item_actions.d.ts.map +1 -1
  91. package/dist/auth/cell_item_actions.js +23 -22
  92. package/dist/auth/cell_relation_list_limit.d.ts +20 -0
  93. package/dist/auth/cell_relation_list_limit.d.ts.map +1 -0
  94. package/dist/auth/cell_relation_list_limit.js +27 -0
  95. package/dist/auth/cell_relation_visibility.d.ts +4 -3
  96. package/dist/auth/cell_relation_visibility.d.ts.map +1 -1
  97. package/dist/auth/cell_relation_visibility.js +6 -5
  98. package/dist/auth/cell_steward.d.ts +45 -0
  99. package/dist/auth/cell_steward.d.ts.map +1 -0
  100. package/dist/auth/cell_steward.js +53 -0
  101. package/dist/auth/cleanup.d.ts +9 -9
  102. package/dist/auth/cleanup.js +9 -9
  103. package/dist/auth/credential_deadline.d.ts +95 -0
  104. package/dist/auth/credential_deadline.d.ts.map +1 -0
  105. package/dist/auth/credential_deadline.js +139 -0
  106. package/dist/auth/daemon_token_middleware.d.ts.map +1 -1
  107. package/dist/auth/daemon_token_middleware.js +4 -1
  108. package/dist/auth/middleware.d.ts +90 -12
  109. package/dist/auth/middleware.d.ts.map +1 -1
  110. package/dist/auth/middleware.js +115 -16
  111. package/dist/auth/request_context.d.ts +8 -2
  112. package/dist/auth/request_context.d.ts.map +1 -1
  113. package/dist/auth/request_context.js +20 -4
  114. package/dist/auth/resolved_auth.d.ts +13 -2
  115. package/dist/auth/resolved_auth.d.ts.map +1 -1
  116. package/dist/auth/resolved_auth.js +5 -4
  117. package/dist/auth/role_grant_offer_action_specs.d.ts +5 -0
  118. package/dist/auth/role_grant_offer_action_specs.d.ts.map +1 -1
  119. package/dist/auth/role_grant_offer_action_specs.js +6 -1
  120. package/dist/auth/role_grant_offer_actions.d.ts.map +1 -1
  121. package/dist/auth/role_grant_offer_actions.js +23 -16
  122. package/dist/auth/role_grant_offer_queries.d.ts +8 -6
  123. package/dist/auth/role_grant_offer_queries.d.ts.map +1 -1
  124. package/dist/auth/role_grant_offer_queries.js +16 -8
  125. package/dist/auth/session_cookie.d.ts +4 -0
  126. package/dist/auth/session_cookie.d.ts.map +1 -1
  127. package/dist/auth/session_cookie.js +3 -2
  128. package/dist/auth/session_middleware.d.ts +1 -1
  129. package/dist/auth/session_middleware.d.ts.map +1 -1
  130. package/dist/auth/session_middleware.js +4 -1
  131. package/dist/auth/session_queries.d.ts +19 -2
  132. package/dist/auth/session_queries.d.ts.map +1 -1
  133. package/dist/auth/session_queries.js +8 -2
  134. package/dist/auth/signup_route_schema.d.ts.map +1 -1
  135. package/dist/auth/signup_route_schema.js +1 -0
  136. package/dist/auth/signup_routes.d.ts +4 -3
  137. package/dist/auth/signup_routes.d.ts.map +1 -1
  138. package/dist/auth/signup_routes.js +157 -134
  139. package/dist/auth/token_scope.d.ts +7 -1
  140. package/dist/auth/token_scope.d.ts.map +1 -1
  141. package/dist/auth/token_scope.js +8 -2
  142. package/dist/db/CLAUDE.md +32 -19
  143. package/dist/db/cell_ddl.d.ts +1 -2
  144. package/dist/db/cell_ddl.d.ts.map +1 -1
  145. package/dist/db/cell_ddl.js +1 -2
  146. package/dist/db/cell_field_queries.d.ts +20 -18
  147. package/dist/db/cell_field_queries.d.ts.map +1 -1
  148. package/dist/db/cell_field_queries.js +28 -22
  149. package/dist/db/cell_item_queries.d.ts +20 -14
  150. package/dist/db/cell_item_queries.d.ts.map +1 -1
  151. package/dist/db/cell_item_queries.js +28 -18
  152. package/dist/db/cell_moderation.d.ts +67 -0
  153. package/dist/db/cell_moderation.d.ts.map +1 -0
  154. package/dist/db/cell_moderation.js +66 -0
  155. package/dist/db/cell_queries.d.ts +44 -14
  156. package/dist/db/cell_queries.d.ts.map +1 -1
  157. package/dist/db/cell_queries.js +68 -45
  158. package/dist/db/cell_view_sql.d.ts +102 -0
  159. package/dist/db/cell_view_sql.d.ts.map +1 -0
  160. package/dist/db/cell_view_sql.js +112 -0
  161. package/dist/db/db_pg.d.ts +1 -1
  162. package/dist/db/db_pg.js +1 -1
  163. package/dist/hono_context.d.ts +23 -0
  164. package/dist/hono_context.d.ts.map +1 -1
  165. package/dist/hono_context.js +19 -0
  166. package/dist/http/CLAUDE.md +41 -15
  167. package/dist/http/auth_shape.d.ts +5 -2
  168. package/dist/http/auth_shape.d.ts.map +1 -1
  169. package/dist/http/auth_shape.js +5 -2
  170. package/dist/http/ip_canonical.d.ts +30 -3
  171. package/dist/http/ip_canonical.d.ts.map +1 -1
  172. package/dist/http/ip_canonical.js +50 -3
  173. package/dist/http/middleware_spec.d.ts +16 -0
  174. package/dist/http/middleware_spec.d.ts.map +1 -1
  175. package/dist/http/origin.d.ts +113 -18
  176. package/dist/http/origin.d.ts.map +1 -1
  177. package/dist/http/origin.js +247 -127
  178. package/dist/http/route_spec.d.ts +21 -0
  179. package/dist/http/route_spec.d.ts.map +1 -1
  180. package/dist/http/schema_helpers.d.ts +22 -0
  181. package/dist/http/schema_helpers.d.ts.map +1 -1
  182. package/dist/http/schema_helpers.js +24 -0
  183. package/dist/http/surface.d.ts +6 -1
  184. package/dist/http/surface.d.ts.map +1 -1
  185. package/dist/http/surface.js +12 -5
  186. package/dist/primitive_schemas.d.ts +10 -1
  187. package/dist/primitive_schemas.d.ts.map +1 -1
  188. package/dist/primitive_schemas.js +11 -2
  189. package/dist/rate_limiter.d.ts +179 -12
  190. package/dist/rate_limiter.d.ts.map +1 -1
  191. package/dist/rate_limiter.js +352 -42
  192. package/dist/realtime/sse_auth_guard.d.ts +22 -6
  193. package/dist/realtime/sse_auth_guard.d.ts.map +1 -1
  194. package/dist/realtime/sse_auth_guard.js +31 -12
  195. package/dist/realtime/subscriber_registry.d.ts +10 -1
  196. package/dist/realtime/subscriber_registry.d.ts.map +1 -1
  197. package/dist/realtime/subscriber_registry.js +10 -1
  198. package/dist/server/app_server.d.ts +20 -7
  199. package/dist/server/app_server.d.ts.map +1 -1
  200. package/dist/server/app_server.js +8 -3
  201. package/dist/server/env.d.ts +2 -1
  202. package/dist/server/env.d.ts.map +1 -1
  203. package/dist/server/env.js +7 -17
  204. package/dist/server/serve_fact_route.d.ts +8 -4
  205. package/dist/server/serve_fact_route.d.ts.map +1 -1
  206. package/dist/server/serve_fact_route.js +16 -6
  207. package/dist/testing/CLAUDE.md +164 -25
  208. package/dist/testing/adversarial_headers.d.ts.map +1 -1
  209. package/dist/testing/adversarial_headers.js +13 -6
  210. package/dist/testing/connection_closer_helpers.d.ts +6 -1
  211. package/dist/testing/connection_closer_helpers.d.ts.map +1 -1
  212. package/dist/testing/connection_closer_helpers.js +4 -0
  213. package/dist/testing/cross_backend/account_lifecycle.d.ts.map +1 -1
  214. package/dist/testing/cross_backend/account_lifecycle.js +37 -2
  215. package/dist/testing/cross_backend/body_size.d.ts.map +1 -1
  216. package/dist/testing/cross_backend/body_size.js +14 -65
  217. package/dist/testing/cross_backend/capabilities.d.ts +26 -2
  218. package/dist/testing/cross_backend/capabilities.d.ts.map +1 -1
  219. package/dist/testing/cross_backend/capabilities.js +9 -3
  220. package/dist/testing/cross_backend/cell_gated_create.d.ts +38 -0
  221. package/dist/testing/cross_backend/cell_gated_create.d.ts.map +1 -1
  222. package/dist/testing/cross_backend/cell_gated_create.js +401 -5
  223. package/dist/testing/cross_backend/cell_relations.d.ts.map +1 -1
  224. package/dist/testing/cross_backend/cell_relations.js +145 -2
  225. package/dist/testing/cross_backend/conformance_case.d.ts +11 -3
  226. package/dist/testing/cross_backend/conformance_case.d.ts.map +1 -1
  227. package/dist/testing/cross_backend/conformance_case.js +6 -0
  228. package/dist/testing/cross_backend/conformance_table.d.ts.map +1 -1
  229. package/dist/testing/cross_backend/conformance_table.js +20 -19
  230. package/dist/testing/cross_backend/credential_deadline.d.ts +25 -0
  231. package/dist/testing/cross_backend/credential_deadline.d.ts.map +1 -0
  232. package/dist/testing/cross_backend/credential_deadline.js +185 -0
  233. package/dist/testing/cross_backend/default_backend_configs.d.ts.map +1 -1
  234. package/dist/testing/cross_backend/default_backend_configs.js +13 -2
  235. package/dist/testing/cross_backend/expected_schema.json +0 -1
  236. package/dist/testing/cross_backend/full_spine_mount.d.ts +3 -0
  237. package/dist/testing/cross_backend/full_spine_mount.d.ts.map +1 -1
  238. package/dist/testing/cross_backend/full_spine_mount.js +7 -1
  239. package/dist/testing/cross_backend/login_security.d.ts +16 -0
  240. package/dist/testing/cross_backend/login_security.d.ts.map +1 -1
  241. package/dist/testing/cross_backend/login_security.js +154 -0
  242. package/dist/testing/cross_backend/narrowed_api_token.d.ts +23 -0
  243. package/dist/testing/cross_backend/narrowed_api_token.d.ts.map +1 -0
  244. package/dist/testing/cross_backend/narrowed_api_token.js +40 -0
  245. package/dist/testing/cross_backend/origin.d.ts.map +1 -1
  246. package/dist/testing/cross_backend/origin.js +6 -26
  247. package/dist/testing/cross_backend/origin_conformance.d.ts +152 -0
  248. package/dist/testing/cross_backend/origin_conformance.d.ts.map +1 -0
  249. package/dist/testing/cross_backend/origin_conformance.js +136 -0
  250. package/dist/testing/cross_backend/origin_conformance.json +1679 -0
  251. package/dist/testing/cross_backend/origin_scope.d.ts +16 -0
  252. package/dist/testing/cross_backend/origin_scope.d.ts.map +1 -0
  253. package/dist/testing/cross_backend/origin_scope.js +140 -0
  254. package/dist/testing/cross_backend/query_shape.d.ts.map +1 -1
  255. package/dist/testing/cross_backend/query_shape.js +24 -2
  256. package/dist/testing/cross_backend/role_grant_cross_helpers.d.ts +35 -0
  257. package/dist/testing/cross_backend/role_grant_cross_helpers.d.ts.map +1 -0
  258. package/dist/testing/cross_backend/role_grant_cross_helpers.js +64 -0
  259. package/dist/testing/cross_backend/role_grant_offer_notification_ws.d.ts +8 -0
  260. package/dist/testing/cross_backend/role_grant_offer_notification_ws.d.ts.map +1 -1
  261. package/dist/testing/cross_backend/role_grant_offer_notification_ws.js +44 -33
  262. package/dist/testing/cross_backend/role_grant_participation.d.ts.map +1 -1
  263. package/dist/testing/cross_backend/role_grant_participation.js +64 -0
  264. package/dist/testing/cross_backend/rust_spine_stub_backend_config.d.ts.map +1 -1
  265. package/dist/testing/cross_backend/rust_spine_stub_backend_config.js +6 -4
  266. package/dist/testing/cross_backend/spine_surface_constants.d.ts +20 -1
  267. package/dist/testing/cross_backend/spine_surface_constants.d.ts.map +1 -1
  268. package/dist/testing/cross_backend/spine_surface_constants.js +23 -1
  269. package/dist/testing/cross_backend/testing_backdoor.d.ts.map +1 -1
  270. package/dist/testing/cross_backend/testing_backdoor.js +20 -7
  271. package/dist/testing/cross_backend/testing_reset_actions.d.ts +180 -5
  272. package/dist/testing/cross_backend/testing_reset_actions.d.ts.map +1 -1
  273. package/dist/testing/cross_backend/testing_reset_actions.js +154 -5
  274. package/dist/testing/cross_backend/token_scope_surface.d.ts.map +1 -1
  275. package/dist/testing/cross_backend/token_scope_surface.js +25 -21
  276. package/dist/testing/cross_backend/transport_composition.d.ts +60 -0
  277. package/dist/testing/cross_backend/transport_composition.d.ts.map +1 -0
  278. package/dist/testing/cross_backend/transport_composition.js +364 -0
  279. package/dist/testing/cross_backend/ts_spine_backend_config.d.ts.map +1 -1
  280. package/dist/testing/cross_backend/ts_spine_backend_config.js +21 -6
  281. package/dist/testing/cross_backend/ws_action_rate_limit.d.ts.map +1 -1
  282. package/dist/testing/cross_backend/ws_action_rate_limit.js +21 -1
  283. package/dist/testing/cross_backend/ws_role_gated.d.ts +38 -0
  284. package/dist/testing/cross_backend/ws_role_gated.d.ts.map +1 -0
  285. package/dist/testing/cross_backend/ws_role_gated.js +142 -0
  286. package/dist/testing/entities.d.ts +23 -0
  287. package/dist/testing/entities.d.ts.map +1 -1
  288. package/dist/testing/entities.js +37 -0
  289. package/dist/testing/integration.d.ts.map +1 -1
  290. package/dist/testing/integration.js +3 -1
  291. package/dist/testing/middleware.d.ts +10 -0
  292. package/dist/testing/middleware.d.ts.map +1 -1
  293. package/dist/testing/middleware.js +31 -7
  294. package/dist/testing/schema_introspect.js +1 -1
  295. package/dist/testing/schema_parity.d.ts +4 -3
  296. package/dist/testing/schema_parity.d.ts.map +1 -1
  297. package/dist/testing/schema_parity.js +4 -3
  298. package/dist/testing/schema_ready_fixture.d.ts +2 -4
  299. package/dist/testing/schema_ready_fixture.d.ts.map +1 -1
  300. package/dist/testing/schema_ready_fixture.js +2 -4
  301. package/dist/testing/stubs.d.ts +16 -3
  302. package/dist/testing/stubs.d.ts.map +1 -1
  303. package/dist/testing/stubs.js +20 -7
  304. package/dist/testing/surface_invariants.js +2 -2
  305. package/dist/ui/auth_state.svelte.d.ts +10 -0
  306. package/dist/ui/auth_state.svelte.d.ts.map +1 -1
  307. package/dist/ui/auth_state.svelte.js +22 -4
  308. package/package.json +1 -1
  309. package/dist/db/cell_history_ddl.d.ts +0 -38
  310. package/dist/db/cell_history_ddl.d.ts.map +0 -1
  311. package/dist/db/cell_history_ddl.js +0 -61
@@ -9,8 +9,8 @@ import '../assert_dev_env.js';
9
9
  * `Content-Length` over the cap is refused on the header, *before* auth,
10
10
  * origin, or dispatch run (middleware step 4). Each impl unit-tests this in
11
11
  * isolation; this suite pins the cross-impl agreement on the status + body
12
- * shape, on the exact `>` cap boundary (not an off-by-one divergence), and on
13
- * the cap answering ahead of the origin check and of auth. The cases:
12
+ * shape, and on the exact `>` cap boundary (not an off-by-one divergence). The
13
+ * cases:
14
14
  *
15
15
  * - **over-limit POST (cap + 1 byte) → 413** `payload_too_large`, refused
16
16
  * before any handler runs (the limit fires ahead of origin verification + the
@@ -25,11 +25,10 @@ import '../assert_dev_env.js';
25
25
  * - **under-limit POST (small) → 200** — a small, well-formed authenticated
26
26
  * `account_verify` envelope sails through to a successful handler response,
27
27
  * the positive control that the route works for normal traffic.
28
- * - **over-limit POST with a disallowed `Origin` → 413**, not the origin
29
- * check's 403, and **over-limit POST with no credentials → 413**, not 401:
30
- * the cap answers a declared length ahead of both. The control — the same
31
- * disallowed `Origin` on an under-limit body → 403 `forbidden_origin` —
32
- * shows the origin check still runs.
28
+ * - The cap answering a declared length ahead of the origin check and auth —
29
+ * over-cap with a disallowed `Origin` and no credential → 413 — is pinned per
30
+ * transport by the front-door table (`transport_composition.ts`), beside the
31
+ * under-cap 403 that shows the origin check still runs.
33
32
  * - **over-limit chunked POST (no `Content-Length`), authenticated → 413** —
34
33
  * a body with no declared length is refused by the bytes that arrive.
35
34
  *
@@ -83,7 +82,7 @@ import '../assert_dev_env.js';
83
82
  */
84
83
  import { describe, test, assert } from 'vitest';
85
84
  import { account_verify_action_spec } from '../../auth/account_action_specs.js';
86
- import { ERROR_FORBIDDEN_ORIGIN, ERROR_PAYLOAD_TOO_LARGE } from '../../http/error_schemas.js';
85
+ import { ERROR_PAYLOAD_TOO_LARGE } from '../../http/error_schemas.js';
87
86
  import { raw_http_exchange, raw_http_parse_response } from '../transports/raw_http.js';
88
87
  import { SPINE_RPC_PATH } from './spine_surface_constants.js';
89
88
  /**
@@ -111,8 +110,6 @@ const sized_envelope = (id, target_bytes) => {
111
110
  };
112
111
  /** A small, well-formed nullary `account_verify` body — well under the cap. */
113
112
  const small_envelope = (id) => JSON.stringify({ jsonrpc: '2.0', method: account_verify_action_spec.method, id });
114
- /** An `Origin` no backend's allowlist admits. */
115
- const DISALLOWED_ORIGIN = 'http://evil.com';
116
113
  /** Chunk size of the streamed over-cap body. */
117
114
  const STREAM_CHUNK_BYTES = 64 * 1024;
118
115
  /**
@@ -191,19 +188,15 @@ export const describe_body_size_cross_tests = (options) => {
191
188
  body
192
189
  });
193
190
  /**
194
- * POST with a declared `Content-Length` one byte over the cap. Over a
195
- * socket only the head is sent; in-process, the whole body.
196
- *
197
- * `headers` carries the credential and any `Origin`, which defaults to the
198
- * backend's own. `anonymous` picks the cookie-jar-free transport in-process;
199
- * a raw head carries only what `headers` names either way.
191
+ * POST as the keeper, with the backend's own `Origin` and a declared
192
+ * `Content-Length` one byte over the cap. Over a socket only the head is
193
+ * sent; in-process, the whole body.
200
194
  */
201
- const post_over_limit_declared = async (fixture, request) => {
202
- const { id, headers, anonymous } = request;
195
+ const post_over_limit_declared = async (fixture, id) => {
196
+ const headers = fixture.create_session_headers();
203
197
  const content_length = BODY_LIMIT_DEFAULT_BYTES + 1;
204
198
  if (base_url === null) {
205
- const transport = anonymous ? fixture.fresh_transport() : fixture.transport;
206
- return to_sized_response(await transport(rpc_path, {
199
+ return to_sized_response(await fixture.transport(rpc_path, {
207
200
  method: 'POST',
208
201
  headers: { ...headers, 'content-type': 'application/json' },
209
202
  body: sized_envelope(id, content_length)
@@ -258,11 +251,7 @@ export const describe_body_size_cross_tests = (options) => {
258
251
  // Keeper session cookie + the default allowed Origin, so neither auth
259
252
  // nor origin is the cause — only the size. One byte over the cap: both
260
253
  // impls reject on a strict `>`.
261
- const res = await post_over_limit_declared(fixture, {
262
- id: 'over-limit',
263
- headers: fixture.create_session_headers(),
264
- anonymous: false
265
- });
254
+ const res = await post_over_limit_declared(fixture, 'over-limit');
266
255
  assert_payload_too_large(res, 'a body one byte over the cap must be rejected with 413');
267
256
  });
268
257
  test('at-limit POST (exactly the cap) → not size-rejected', async () => {
@@ -281,46 +270,6 @@ export const describe_body_size_cross_tests = (options) => {
281
270
  const res = await post(fixture, small_envelope('under-limit'));
282
271
  assert.strictEqual(res.status, 200, 'an under-limit authenticated request must pass');
283
272
  });
284
- test('over-limit POST with a disallowed Origin → 413, not 403', async () => {
285
- const fixture = await setup_test();
286
- // Keeper session + a rogue Origin: the origin check would answer 403,
287
- // and the cap, which reads only the declared length, answers first.
288
- const res = await post_over_limit_declared(fixture, {
289
- id: 'over-limit-evil-origin',
290
- headers: { ...fixture.create_session_headers(), origin: DISALLOWED_ORIGIN },
291
- anonymous: false
292
- });
293
- assert_payload_too_large(res, 'a declared length over the cap must answer 413 ahead of the origin check');
294
- });
295
- test('under-limit POST with a disallowed Origin → 403 forbidden_origin', async () => {
296
- const fixture = await setup_test();
297
- // The control for the case above: the same request minus the size is
298
- // refused by the origin check, so the 413 there is the cap answering
299
- // first, not the origin check being absent.
300
- const res = await fixture.transport(rpc_path, {
301
- method: 'POST',
302
- headers: {
303
- ...fixture.create_session_headers(),
304
- origin: DISALLOWED_ORIGIN,
305
- 'content-type': 'application/json'
306
- },
307
- body: small_envelope('under-limit-evil-origin')
308
- });
309
- assert.strictEqual(res.status, 403, 'a disallowed Origin on an under-limit body is refused');
310
- const body = (await res.json().catch(() => undefined));
311
- assert.strictEqual(body?.error, ERROR_FORBIDDEN_ORIGIN);
312
- });
313
- test('over-limit POST with no credentials → 413, not 401', async () => {
314
- const fixture = await setup_test();
315
- // No cookie, no token: the dispatcher would answer 401, and the cap
316
- // answers first.
317
- const res = await post_over_limit_declared(fixture, {
318
- id: 'over-limit-anonymous',
319
- headers: {},
320
- anonymous: true
321
- });
322
- assert_payload_too_large(res, 'a declared length over the cap must answer 413 ahead of auth');
323
- });
324
273
  test('over-limit chunked POST (no Content-Length), authenticated → 413', async () => {
325
274
  const fixture = await setup_test();
326
275
  // Keeper session + the default allowed Origin, so nothing but the size
@@ -208,6 +208,30 @@ export interface BackendCapabilities {
208
208
  * mount it.
209
209
  */
210
210
  readonly cell_gated_create: boolean;
211
+ /**
212
+ * The backend mounts a second, role-gated WebSocket endpoint at
213
+ * `SPINE_ROLE_GATED_WS_PATH`, gated on `SPINE_ROLE_GATED_WS_ROLES`, beside
214
+ * its ungated `ws_path`. Gates `describe_ws_role_gated_cross_tests`: a
215
+ * revoked global grant of a listed role closes the account's gated socket
216
+ * with `WS_CLOSE_PERMISSION_REVOKED`, its ungated socket stays open and
217
+ * still receives the account's pushes, a re-upgrade is refused at the gate,
218
+ * and a scoped revoke closes nothing. `true` only on the reference spine binaries that
219
+ * mount that endpoint (the TS spine binary + the Rust `testing_spine_stub`).
220
+ */
221
+ readonly ws_role_gated: boolean;
222
+ /**
223
+ * A refused WebSocket upgrade carries its refusal body — the flat
224
+ * `{error, ...}` the same refusal answers over plain HTTP. Not a gate: it
225
+ * forks how `describe_transport_composition_cross_tests` reads its WS rows.
226
+ * `true`, an empty refusal body fails the case; `false`, an empty body is
227
+ * allowed (the case pins the status alone) and a non-empty one is still
228
+ * asserted.
229
+ *
230
+ * `false` on Node: `@hono/node-ws` writes a refused upgrade to the raw
231
+ * socket with `Content-Length: 0`, dropping the response body. `true` on
232
+ * Deno, Bun, and the Rust spine, which send the response as built.
233
+ */
234
+ readonly ws_refusal_body: boolean;
211
235
  }
212
236
  /**
213
237
  * Capability declarations for the in-process Hono transport. Nearly every
@@ -218,8 +242,8 @@ export interface BackendCapabilities {
218
242
  * `create_ws_transport`, so the in-process driver never runs it — the
219
243
  * transport itself supports server-initiated requests),
220
244
  * `ws_handshake_pipelining` (raw bytes on a real socket),
221
- * `ws_account_actions` (a real socket's reply-then-close ordering), and
222
- * `cell_gated_create`. Cross-process consumers declare each flag explicitly
245
+ * `ws_account_actions` (a real socket's reply-then-close ordering),
246
+ * `cell_gated_create`, and `ws_role_gated`. Cross-process consumers declare each flag explicitly
223
247
  * per backend.
224
248
  */
225
249
  export declare const in_process_capabilities: BackendCapabilities;
@@ -1 +1 @@
1
- {"version":3,"file":"capabilities.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AA2C9B;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,iBAAiB;IACjC;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC;;;;OAIG;IACH,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;CACnC;AAED;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IACnC;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB;;;;;OAKG;IACH,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB;;;;;;;OAOG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC;;;;;;;;OAQG;IACH,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B;;;;;;;;OAQG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB;;;;;;;;OAQG;IACH,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC;;;;;;;;;;;;;;;;;;OAkBG;IACH,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B;;;;;;;;;;;;;;;;OAgBG;IACH,QAAQ,CAAC,uBAAuB,EAAE,OAAO,CAAC;IAC1C;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAC;IACrC;;;;;;;;;;;;;;;;OAgBG;IACH,QAAQ,CAAC,wBAAwB,EAAE,OAAO,CAAC;IAC3C;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;CACpC;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,uBAAuB,EAAE,mBAqBpC,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,iBAInC,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,OAAO,GAAI,MAAM,OAAO,EAAE,MAAM,MAAM,EAAE,IAAI,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAG,IAMrF,CAAC"}
1
+ {"version":3,"file":"capabilities.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AA2C9B;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,iBAAiB;IACjC;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC;;;;OAIG;IACH,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;CACnC;AAED;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IACnC;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB;;;;;OAKG;IACH,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB;;;;;;;OAOG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC;;;;;;;;OAQG;IACH,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B;;;;;;;;OAQG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB;;;;;;;;OAQG;IACH,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC;;;;;;;;;;;;;;;;;;OAkBG;IACH,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B;;;;;;;;;;;;;;;;OAgBG;IACH,QAAQ,CAAC,uBAAuB,EAAE,OAAO,CAAC;IAC1C;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAC;IACrC;;;;;;;;;;;;;;;;OAgBG;IACH,QAAQ,CAAC,wBAAwB,EAAE,OAAO,CAAC;IAC3C;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC;;;;;;;;;OASG;IACH,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;CAClC;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,uBAAuB,EAAE,mBA2BpC,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,iBAInC,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,OAAO,GAAI,MAAM,OAAO,EAAE,MAAM,MAAM,EAAE,IAAI,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAG,IAMrF,CAAC"}
@@ -47,8 +47,8 @@ import { test } from 'vitest';
47
47
  * `create_ws_transport`, so the in-process driver never runs it — the
48
48
  * transport itself supports server-initiated requests),
49
49
  * `ws_handshake_pipelining` (raw bytes on a real socket),
50
- * `ws_account_actions` (a real socket's reply-then-close ordering), and
51
- * `cell_gated_create`. Cross-process consumers declare each flag explicitly
50
+ * `ws_account_actions` (a real socket's reply-then-close ordering),
51
+ * `cell_gated_create`, and `ws_role_gated`. Cross-process consumers declare each flag explicitly
52
52
  * per backend.
53
53
  */
54
54
  export const in_process_capabilities = Object.freeze({
@@ -71,7 +71,13 @@ export const in_process_capabilities = Object.freeze({
71
71
  ws_self_revocation_reply: true,
72
72
  // Cross-process-only: the test `CellCreateAuthorize` policy is mounted on the
73
73
  // spine binaries' full mount + the Rust stub, not the in-process default app.
74
- cell_gated_create: false
74
+ cell_gated_create: false,
75
+ // Cross-process-only: the gated endpoint is a spine-binary mount, and the
76
+ // case reads a real socket's close.
77
+ ws_role_gated: false,
78
+ // Read only by the front-door table's WS rows, which skip in-process (no
79
+ // socket to upgrade); Hono's own refusals carry their bodies.
80
+ ws_refusal_body: true
75
81
  });
76
82
  /**
77
83
  * Shape notes for the in-process Hono transport — every wiring fact present
@@ -19,6 +19,44 @@ export declare const describe_cell_gated_create_cross_tests: (options: RpcPathCa
19
19
  * contribution gets `cell_not_found`, never learns it exists.
20
20
  * - **reject** → `moderation: 'rejected'`, visibility stays private.
21
21
  *
22
+ * And that moderation gates reads — a cell's effective audience is its
23
+ * visibility or grants **and** its moderation admission (unmoderated or
24
+ * `approved`), so a pending or rejected contribution reaches no one past its
25
+ * author and admins:
26
+ *
27
+ * - **an author's self-flip to public admits nobody** — a pending post its
28
+ * author makes public stays 404 to anon and a fresh non-admin on `cell_get`,
29
+ * and out of their `cell_list`; the author and admin still read it.
30
+ * - **rejection holds a public post back** — pending → rejected → public, and
31
+ * approved → rejected (approval made it public, rejection leaves visibility
32
+ * alone), both 404 past the author; a grant made while the post was approved
33
+ * stops admitting once it is rejected, on `cell_get` and `shared_with: 'me'`.
34
+ * - **an approved post is live** — the control.
35
+ * - **relation reads follow** — a pending post in a public collection is
36
+ * omitted from anon `cell_item_list`, beside a live sibling that isn't; at
37
+ * the far end of all four relation lists, a pending post is hidden from
38
+ * anon even flipped public, and a rejected one from its grant holder.
39
+ * - **fact serving follows** — a pending post's fact is 404 to anon, even
40
+ * with the post flipped public (also gated on `capabilities.fact_serving`).
41
+ *
42
+ * And the steward arm — the owner of a **non-admin** root (a parentless
43
+ * non-`space` kind carrying the same policy, which the test authorizer leaves
44
+ * open) reads the pending posts under it and moderates them:
45
+ *
46
+ * - **the queue** — `cell_list({root_id, moderation: 'pending'})` and
47
+ * `cell_get` (with `can_edit` / `can_grant` false) → 200; a stranger 404s.
48
+ * - **moderation** — the root owner approves → 200; the author 403, a
49
+ * stranger 404.
50
+ * - **the arm stops there** — the root owner's `cell_clone` of the pending
51
+ * post and a contribution under it are both 404.
52
+ * - **fact serving** — the root owner fetches a pending post's fact → 200,
53
+ * anon 404 (also gated on `capabilities.fact_serving`).
54
+ *
55
+ * And that `cell_grant_create` refuses a pending contribution — **403**
56
+ * `cell_grant_unapproved` for its author and an admin, actor- and role-shaped,
57
+ * while a non-manager keeps the **404** mask; the same grant lands once the
58
+ * post is approved.
59
+ *
22
60
  * Gated on `capabilities.cell_gated_create` — a `pending` contribution only
23
61
  * exists when the directory authorizer is mounted (reference spine binaries).
24
62
  */
@@ -1 +1 @@
1
- {"version":3,"file":"cell_gated_create.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/cell_gated_create.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAuD9B,OAAO,KAAK,EAAE,uCAAuC,EAAE,MAAM,YAAY,CAAC;AAkB1E,eAAO,MAAM,sCAAsC,GAClD,SAAS,uCAAuC,KAC9C,IAwPF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,kCAAkC,GAC9C,SAAS,uCAAuC,KAC9C,IAyKF,CAAC"}
1
+ {"version":3,"file":"cell_gated_create.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/cell_gated_create.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAoE9B,OAAO,KAAK,EAAE,uCAAuC,EAAE,MAAM,YAAY,CAAC;AAqB1E,eAAO,MAAM,sCAAsC,GAClD,SAAS,uCAAuC,KAC9C,IAuTF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,eAAO,MAAM,kCAAkC,GAC9C,SAAS,uCAAuC,KAC9C,IA25BF,CAAC"}