@fuzdev/fuz_app 0.92.0 → 0.94.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 (203) hide show
  1. package/README.md +2 -2
  2. package/dist/actions/action_codegen.d.ts +18 -18
  3. package/dist/actions/action_codegen.js +30 -30
  4. package/dist/actions/action_event.js +1 -1
  5. package/dist/actions/action_event_helpers.d.ts +1 -1
  6. package/dist/actions/action_event_types.d.ts +1 -1
  7. package/dist/actions/action_rpc.d.ts +2 -2
  8. package/dist/actions/broadcast_api.d.ts +1 -1
  9. package/dist/actions/broadcast_api.js +1 -1
  10. package/dist/actions/perform_action.d.ts +2 -2
  11. package/dist/actions/register_action_ws.d.ts +2 -2
  12. package/dist/actions/register_action_ws.js +2 -2
  13. package/dist/actions/register_ws_endpoint.js +1 -1
  14. package/dist/actions/request_tracker.svelte.d.ts +1 -1
  15. package/dist/actions/request_tracker.svelte.js +1 -1
  16. package/dist/actions/rpc_client.d.ts +1 -1
  17. package/dist/actions/socket.svelte.d.ts +2 -2
  18. package/dist/actions/transports_ws.js +1 -1
  19. package/dist/actions/transports_ws_auth_guard.d.ts +1 -1
  20. package/dist/actions/transports_ws_backend.d.ts +1 -1
  21. package/dist/actions/transports_ws_backend.js +2 -2
  22. package/dist/auth/account_action_specs.js +1 -1
  23. package/dist/auth/account_schema.d.ts +1 -1
  24. package/dist/auth/account_schema.js +1 -1
  25. package/dist/auth/actor_lookup_action_specs.js +1 -1
  26. package/dist/auth/actor_lookup_queries.d.ts +1 -1
  27. package/dist/auth/actor_search_action_specs.js +1 -1
  28. package/dist/auth/actor_search_queries.d.ts +1 -1
  29. package/dist/auth/admin_action_specs.js +1 -1
  30. package/dist/auth/api_token.js +1 -1
  31. package/dist/auth/api_token_queries.d.ts +1 -1
  32. package/dist/auth/app_settings_schema.d.ts +1 -1
  33. package/dist/auth/app_settings_schema.js +1 -1
  34. package/dist/auth/audit_emitter.d.ts +2 -2
  35. package/dist/auth/audit_log_routes.d.ts +1 -1
  36. package/dist/auth/audit_log_schema.d.ts +1 -1
  37. package/dist/auth/audit_log_schema.js +2 -2
  38. package/dist/auth/bearer_auth.d.ts +1 -1
  39. package/dist/auth/bootstrap_account.d.ts +1 -1
  40. package/dist/auth/bootstrap_route_schema.js +1 -1
  41. package/dist/auth/bootstrap_routes.d.ts +1 -1
  42. package/dist/auth/bootstrap_routes.js +1 -1
  43. package/dist/auth/cell_action_specs.js +2 -2
  44. package/dist/auth/cell_audit_action_specs.js +1 -1
  45. package/dist/auth/cell_audit_metadata.js +1 -1
  46. package/dist/auth/cell_field_action_specs.js +1 -1
  47. package/dist/auth/cell_field_audit_metadata.js +1 -1
  48. package/dist/auth/cell_grant_action_specs.js +1 -1
  49. package/dist/auth/cell_grant_audit_metadata.js +1 -1
  50. package/dist/auth/cell_item_action_specs.d.ts +1 -1
  51. package/dist/auth/cell_item_action_specs.js +3 -3
  52. package/dist/auth/cell_item_audit_metadata.js +1 -1
  53. package/dist/auth/cell_relation_visibility.d.ts +1 -1
  54. package/dist/auth/cleanup.d.ts +1 -1
  55. package/dist/auth/daemon_token_middleware.d.ts +1 -1
  56. package/dist/auth/deps.d.ts +2 -2
  57. package/dist/auth/invite_schema.d.ts +1 -1
  58. package/dist/auth/invite_schema.js +1 -1
  59. package/dist/auth/request_context.d.ts +1 -1
  60. package/dist/auth/role_grant_offer_action_specs.js +1 -1
  61. package/dist/auth/role_grant_offer_notifications.d.ts +1 -1
  62. package/dist/auth/role_grant_offer_notifications.js +1 -1
  63. package/dist/auth/role_grant_offer_queries.d.ts +1 -1
  64. package/dist/auth/role_grant_offer_schema.d.ts +1 -1
  65. package/dist/auth/role_grant_offer_schema.js +1 -1
  66. package/dist/auth/role_grant_queries.d.ts +1 -1
  67. package/dist/auth/session_queries.d.ts +1 -1
  68. package/dist/auth/session_queries.js +1 -1
  69. package/dist/auth/signup_route_schema.js +1 -1
  70. package/dist/cli/args.d.ts +1 -1
  71. package/dist/cli/args.js +2 -2
  72. package/dist/cli/help.d.ts +1 -1
  73. package/dist/cli/help.js +1 -1
  74. package/dist/cli/logger.d.ts +1 -1
  75. package/dist/cli/logger.js +1 -1
  76. package/dist/db/CLAUDE.md +1 -1
  77. package/dist/db/cell_audit_queries.d.ts +1 -1
  78. package/dist/db/cell_field_queries.d.ts +1 -1
  79. package/dist/db/cell_grant_queries.d.ts +1 -1
  80. package/dist/db/cell_item_queries.d.ts +1 -1
  81. package/dist/db/cell_queries.d.ts +3 -3
  82. package/dist/db/cell_queries.js +1 -1
  83. package/dist/db/fact_disk_storage.d.ts +2 -2
  84. package/dist/db/fact_disk_storage.js +4 -4
  85. package/dist/db/fact_queries.d.ts +1 -1
  86. package/dist/db/fact_store.d.ts +3 -3
  87. package/dist/db/fact_store.js +2 -2
  88. package/dist/db/file_fact_url.d.ts +1 -1
  89. package/dist/db/file_fact_url.js +1 -1
  90. package/dist/db/migrate.js +1 -1
  91. package/dist/db/status.js +1 -1
  92. package/dist/http/auth_shape.js +2 -2
  93. package/dist/http/common_routes.d.ts +1 -1
  94. package/dist/http/db_routes.d.ts +1 -1
  95. package/dist/http/origin.js +1 -1
  96. package/dist/http/pending_effects.d.ts +1 -1
  97. package/dist/http/proxy.d.ts +1 -1
  98. package/dist/http/route_spec.d.ts +1 -1
  99. package/dist/rate_limiter.js +1 -1
  100. package/dist/realtime/sse.d.ts +1 -1
  101. package/dist/realtime/sse_auth_guard.d.ts +1 -1
  102. package/dist/runtime/deno.js +1 -1
  103. package/dist/server/app_backend.d.ts +1 -1
  104. package/dist/server/app_backend.js +1 -1
  105. package/dist/server/env.js +1 -1
  106. package/dist/server/fact_write.d.ts +2 -2
  107. package/dist/server/fact_write.js +1 -1
  108. package/dist/server/serve_fact_route.d.ts +1 -1
  109. package/dist/server/serve_fact_route.js +2 -2
  110. package/dist/server/startup.d.ts +1 -1
  111. package/dist/testing/CLAUDE.md +50 -5
  112. package/dist/testing/adversarial_input.js +1 -1
  113. package/dist/testing/app_server.d.ts +1 -1
  114. package/dist/testing/app_server.js +1 -1
  115. package/dist/testing/auth_apps.js +1 -1
  116. package/dist/testing/cross_backend/bench/bench_report.d.ts +1 -1
  117. package/dist/testing/cross_backend/bench/bench_report.js +2 -2
  118. package/dist/testing/cross_backend/bench/run_cross_impl_bench.d.ts +1 -1
  119. package/dist/testing/cross_backend/bench/run_cross_impl_bench.js +1 -1
  120. package/dist/testing/cross_backend/bootstrap_backend.d.ts +1 -1
  121. package/dist/testing/cross_backend/cell_relations.js +1 -1
  122. package/dist/testing/cross_backend/conformance_case.d.ts +4 -0
  123. package/dist/testing/cross_backend/conformance_case.d.ts.map +1 -1
  124. package/dist/testing/cross_backend/conformance_case.js +26 -0
  125. package/dist/testing/cross_backend/conformance_table.d.ts +21 -0
  126. package/dist/testing/cross_backend/conformance_table.d.ts.map +1 -1
  127. package/dist/testing/cross_backend/conformance_table.js +109 -7
  128. package/dist/testing/cross_backend/create_cross_backend_global_setup.d.ts +1 -1
  129. package/dist/testing/cross_backend/create_dual_spawn_global_setup.d.ts +64 -0
  130. package/dist/testing/cross_backend/create_dual_spawn_global_setup.d.ts.map +1 -0
  131. package/dist/testing/cross_backend/{create_schema_parity_global_setup.js → create_dual_spawn_global_setup.js} +1 -1
  132. package/dist/testing/cross_backend/default_backend_configs.d.ts +12 -0
  133. package/dist/testing/cross_backend/default_backend_configs.d.ts.map +1 -1
  134. package/dist/testing/cross_backend/default_backend_configs.js +12 -0
  135. package/dist/testing/cross_backend/default_spine_surface.d.ts +1 -1
  136. package/dist/testing/cross_backend/default_spine_surface.d.ts.map +1 -1
  137. package/dist/testing/cross_backend/default_spine_surface.js +9 -2
  138. package/dist/testing/cross_backend/fact_serving.js +1 -1
  139. package/dist/testing/cross_backend/login_security.d.ts +11 -0
  140. package/dist/testing/cross_backend/login_security.d.ts.map +1 -0
  141. package/dist/testing/cross_backend/login_security.js +130 -0
  142. package/dist/testing/cross_backend/rust_spine_stub_backend_config.d.ts +17 -0
  143. package/dist/testing/cross_backend/rust_spine_stub_backend_config.d.ts.map +1 -1
  144. package/dist/testing/cross_backend/rust_spine_stub_backend_config.js +7 -2
  145. package/dist/testing/cross_backend/setup.d.ts +1 -1
  146. package/dist/testing/cross_backend/setup.js +1 -1
  147. package/dist/testing/cross_backend/testing_reset_actions.js +2 -2
  148. package/dist/testing/cross_backend/testing_server_core.d.ts +1 -1
  149. package/dist/testing/cross_backend/testing_server_core.js +1 -1
  150. package/dist/testing/cross_backend/ts_spine_backend_config.d.ts +11 -0
  151. package/dist/testing/cross_backend/ts_spine_backend_config.d.ts.map +1 -1
  152. package/dist/testing/cross_backend/ts_spine_backend_config.js +23 -7
  153. package/dist/testing/cross_backend/ws_round_trip.js +1 -1
  154. package/dist/testing/db.js +4 -4
  155. package/dist/testing/middleware.js +1 -1
  156. package/dist/testing/role_grant_helpers.d.ts +1 -1
  157. package/dist/testing/rpc_helpers.d.ts +18 -1
  158. package/dist/testing/rpc_helpers.d.ts.map +1 -1
  159. package/dist/testing/rpc_helpers.js +24 -2
  160. package/dist/testing/schema_generators.d.ts +1 -1
  161. package/dist/testing/schema_generators.js +1 -1
  162. package/dist/testing/stubs.js +1 -1
  163. package/dist/testing/testing_rate_limiter.d.ts +1 -1
  164. package/dist/testing/testing_rate_limiter.js +1 -1
  165. package/dist/testing/transports/bootstrap.d.ts +1 -1
  166. package/dist/testing/transports/bootstrap.js +1 -1
  167. package/dist/testing/ws_round_trip.d.ts +2 -2
  168. package/dist/testing/ws_round_trip.js +2 -2
  169. package/dist/ui/AdminSurface.svelte +1 -1
  170. package/dist/ui/AppShell.svelte +1 -1
  171. package/dist/ui/BootstrapForm.svelte +1 -1
  172. package/dist/ui/CLAUDE.md +1 -1
  173. package/dist/ui/ConfirmButton.svelte +2 -2
  174. package/dist/ui/ConfirmButton.svelte.d.ts +1 -1
  175. package/dist/ui/LoginForm.svelte +1 -1
  176. package/dist/ui/MenuLink.svelte +1 -1
  177. package/dist/ui/MenuLink.svelte.d.ts +1 -1
  178. package/dist/ui/PopoverButton.svelte +1 -1
  179. package/dist/ui/PopoverButton.svelte.d.ts +1 -1
  180. package/dist/ui/SignupForm.svelte +1 -1
  181. package/dist/ui/account_sessions_state.svelte.js +1 -1
  182. package/dist/ui/admin_accounts_state.svelte.d.ts +1 -1
  183. package/dist/ui/admin_accounts_state.svelte.js +1 -1
  184. package/dist/ui/admin_invites_state.svelte.d.ts +1 -1
  185. package/dist/ui/admin_invites_state.svelte.js +1 -1
  186. package/dist/ui/admin_sessions_state.svelte.d.ts +1 -1
  187. package/dist/ui/app_settings_state.svelte.js +1 -1
  188. package/dist/ui/async_slot.svelte.d.ts +2 -2
  189. package/dist/ui/async_slot.svelte.js +2 -2
  190. package/dist/ui/audit_log_state.svelte.js +1 -1
  191. package/dist/ui/auth_state.svelte.d.ts +1 -1
  192. package/dist/ui/auth_state.svelte.js +3 -3
  193. package/dist/ui/format_scope.js +1 -1
  194. package/dist/ui/popover.svelte.d.ts +1 -1
  195. package/dist/ui/popover.svelte.js +2 -2
  196. package/dist/ui/position_helpers.js +1 -1
  197. package/dist/ui/role_grant_offers_state.svelte.js +1 -1
  198. package/dist/ui/sidebar_state.svelte.js +1 -1
  199. package/dist/ui/table_state.svelte.d.ts +1 -1
  200. package/dist/ui/table_state.svelte.js +2 -2
  201. package/package.json +3 -2
  202. package/dist/testing/cross_backend/create_schema_parity_global_setup.d.ts +0 -59
  203. package/dist/testing/cross_backend/create_schema_parity_global_setup.d.ts.map +0 -1
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * @module
8
8
  */
9
- import type { Logger } from '@fuzdev/fuz_util/log.js';
9
+ import type { Logger } from '@fuzdev/fuz_util/log.ts';
10
10
  import type { Db, DbType } from '../db/db.js';
11
11
  import { type RouteSpec } from './route_spec.js';
12
12
  /**
@@ -9,7 +9,7 @@
9
9
  *
10
10
  * @module
11
11
  */
12
- import { escape_regexp } from '@fuzdev/fuz_util/regexp.js';
12
+ import { escape_regexp } from '@fuzdev/fuz_util/regexp.ts';
13
13
  import { ERROR_FORBIDDEN_ORIGIN } from './error_schemas.js';
14
14
  /**
15
15
  * Parses FUZ_ALLOWED_ORIGINS env var into regex matchers for request source verification.
@@ -39,7 +39,7 @@
39
39
  *
40
40
  * @module
41
41
  */
42
- import type { Logger } from '@fuzdev/fuz_util/log.js';
42
+ import type { Logger } from '@fuzdev/fuz_util/log.ts';
43
43
  /**
44
44
  * Minimal structural context required by `emit_after_commit`. Both
45
45
  * `RouteContext` and `ActionContext` satisfy this — they each carry
@@ -8,7 +8,7 @@
8
8
  * @module
9
9
  */
10
10
  import type { Context, MiddlewareHandler } from 'hono';
11
- import type { Logger } from '@fuzdev/fuz_util/log.js';
11
+ import type { Logger } from '@fuzdev/fuz_util/log.ts';
12
12
  import type { MiddlewareSpec } from './middleware_spec.js';
13
13
  /**
14
14
  * Normalize an IP address for consistent matching and storage.
@@ -14,7 +14,7 @@
14
14
  */
15
15
  import type { Context, Hono, MiddlewareHandler } from 'hono';
16
16
  import type { z } from 'zod';
17
- import type { Logger } from '@fuzdev/fuz_util/log.js';
17
+ import type { Logger } from '@fuzdev/fuz_util/log.ts';
18
18
  import type { Db } from '../db/db.js';
19
19
  import { type RouteErrorSchemas, type RateLimitKey } from './error_schemas.js';
20
20
  import type { MiddlewareSpec } from './middleware_spec.js';
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * @module
8
8
  */
9
- import { LruMap } from '@fuzdev/fuz_util/lru_map.js';
9
+ import { LruMap } from '@fuzdev/fuz_util/lru_map.ts';
10
10
  import { ERROR_RATE_LIMIT_EXCEEDED } from './http/error_schemas.js';
11
11
  /**
12
12
  * Default tracked-key cap: bounds worst-case memory under key-enumeration
@@ -8,7 +8,7 @@
8
8
  */
9
9
  import type { Context } from 'hono';
10
10
  import { z } from 'zod';
11
- import type { Logger } from '@fuzdev/fuz_util/log.js';
11
+ import type { Logger } from '@fuzdev/fuz_util/log.ts';
12
12
  /**
13
13
  * Generic SSE stream controller interface.
14
14
  *
@@ -10,7 +10,7 @@
10
10
  *
11
11
  * @module
12
12
  */
13
- import type { Logger } from '@fuzdev/fuz_util/log.js';
13
+ import type { Logger } from '@fuzdev/fuz_util/log.ts';
14
14
  import { type AuditLogEvent } from '../auth/audit_log_schema.js';
15
15
  import { SubscriberRegistry, type SubscribeOptions } from './subscriber_registry.js';
16
16
  import type { SseStream, SseNotification, EventSpec } from './sse.js';
@@ -7,7 +7,7 @@
7
7
  *
8
8
  * @module
9
9
  */
10
- import { to_error_message } from '@fuzdev/fuz_util/error.js';
10
+ import { to_error_message } from '@fuzdev/fuz_util/error.ts';
11
11
  /**
12
12
  * Create a runtime backed by Deno APIs.
13
13
  *
@@ -10,7 +10,7 @@
10
10
  *
11
11
  * @module
12
12
  */
13
- import { Logger } from '@fuzdev/fuz_util/log.js';
13
+ import { Logger } from '@fuzdev/fuz_util/log.ts';
14
14
  import type { AppDeps } from '../auth/deps.js';
15
15
  import { type AuditEmitter } from '../auth/audit_emitter.js';
16
16
  import type { DbType, Db } from '../db/db.js';
@@ -10,7 +10,7 @@
10
10
  *
11
11
  * @module
12
12
  */
13
- import { Logger } from '@fuzdev/fuz_util/log.js';
13
+ import { Logger } from '@fuzdev/fuz_util/log.ts';
14
14
  import { create_audit_emitter } from '../auth/audit_emitter.js';
15
15
  import { run_migrations } from '../db/migrate.js';
16
16
  import { auth_migration_ns, reserved_migration_namespaces } from '../auth/migrations.js';
@@ -9,7 +9,7 @@
9
9
  * @module
10
10
  */
11
11
  import { z } from 'zod';
12
- import { to_error_message } from '@fuzdev/fuz_util/error.js';
12
+ import { to_error_message } from '@fuzdev/fuz_util/error.ts';
13
13
  import { create_validated_keyring } from '../auth/keyring.js';
14
14
  import { parse_allowed_origins } from '../http/origin.js';
15
15
  /**
@@ -10,8 +10,8 @@
10
10
  *
11
11
  * @module
12
12
  */
13
- import { type FactHash } from '@fuzdev/fuz_util/fact_hash.js';
14
- import type { FactStore } from '@fuzdev/fuz_util/fact_store.js';
13
+ import { type FactHash } from '@fuzdev/fuz_util/fact_hash.ts';
14
+ import type { FactStore } from '@fuzdev/fuz_util/fact_store.ts';
15
15
  export interface WriteFactOptions {
16
16
  content_type: string;
17
17
  }
@@ -13,7 +13,7 @@
13
13
  import { randomBytes } from 'node:crypto';
14
14
  import { writeFile, rename, mkdir, unlink } from 'node:fs/promises';
15
15
  import { join } from 'node:path';
16
- import { FACT_HASH_PREFIX, fact_hash_bytes } from '@fuzdev/fuz_util/fact_hash.js';
16
+ import { FACT_HASH_PREFIX, fact_hash_bytes } from '@fuzdev/fuz_util/fact_hash.ts';
17
17
  import { mint_file_fact_url } from '../db/file_fact_url.js';
18
18
  /**
19
19
  * Write `bytes` as a fact, choosing embedded (PG) vs external (disk +
@@ -72,7 +72,7 @@
72
72
  *
73
73
  * @module
74
74
  */
75
- import type { Logger } from '@fuzdev/fuz_util/log.js';
75
+ import type { Logger } from '@fuzdev/fuz_util/log.ts';
76
76
  import { type RouteSpec } from '../http/route_spec.js';
77
77
  import type { AppDeps } from '../auth/deps.js';
78
78
  export interface CreateServeFactRouteSpecOptions {
@@ -75,8 +75,8 @@
75
75
  import { createReadStream } from 'node:fs';
76
76
  import { Readable } from 'node:stream';
77
77
  import { join } from 'node:path';
78
- import { FactHashSchema } from '@fuzdev/fuz_util/fact_hash.js';
79
- import { Uuid } from '@fuzdev/fuz_util/id.js';
78
+ import { FactHashSchema } from '@fuzdev/fuz_util/fact_hash.ts';
79
+ import { Uuid } from '@fuzdev/fuz_util/id.ts';
80
80
  import { z } from 'zod';
81
81
  import { build_request_context, get_request_context, has_role, } from '../auth/request_context.js';
82
82
  import { ROLE_ADMIN } from '../auth/role_schema.js';
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * @module
7
7
  */
8
- import type { Logger } from '@fuzdev/fuz_util/log.js';
8
+ import type { Logger } from '@fuzdev/fuz_util/log.ts';
9
9
  import type { AppSurface } from '../http/surface.js';
10
10
  /**
11
11
  * Log a startup summary from an `AppSurface`.
@@ -13,7 +13,7 @@ testing-patterns. This file is a reference index for the helpers themselves.
13
13
 
14
14
  ## Production guard — always the first import
15
15
 
16
- Every runtime-reachable module here starts with `import './assert_dev_env.js';`
16
+ Every runtime-reachable module here starts with `import './assert_dev_env.ts';`
17
17
  — reads `DEV` from `esm-env` and throws if false, preventing production-bundle
18
18
  inclusion. Make this the first line in new modules. Enforced by
19
19
  `src/test/testing/assert_dev_env_coverage.test.ts`, which fails if any module
@@ -770,7 +770,8 @@ One-shot transport:
770
770
 
771
771
  - `RpcTestTransport = (url, init) => Promise<Response>` — duck type `Hono.request` already satisfies.
772
772
  - `http_transport(app)` — adapter for anything with a `request()` method.
773
- - `RpcCallResult` — discriminated `{ok: true, status, result}` / `{ok: false, status, error: {code, message, data?}}`.
773
+ - `RpcCallResult` — discriminated `{ok: true, status, headers, result}` / `{ok: false, status, headers, error: {code, message, data?}}`. `headers` is the lowercased-key response-header snapshot so callers can assert header-level properties (e.g. the conformance runner's no-fingerprint invariant).
774
+ - `headers_to_record(headers)` — snapshot a `Headers` into a lowercased-key `Record<string, string>` (multi-value collapses to the comma-joined form; `Set-Cookie` excluded). Used by `rpc_call` and the conformance table's REST branch to thread response headers through for assertions.
774
775
  - `RpcCallArgs` — `{app, path, method, params?, headers?, id?, verb?}`. `verb` defaults to `'POST'`; use `'GET'` for `side_effects: false` methods.
775
776
  - `rpc_call(args)` — merges `RPC_CALL_DEFAULT_HEADERS` (`host: 'localhost'`, `origin: 'http://localhost:5173'`, `Content-Type: 'application/json'`) under caller headers. Envelope-shape violations throw; JSON-RPC errors return `{ok: false, error}` so callers assert on `error.code` / `error.data.reason`.
776
777
  - `rpc_call_typed<T>(args, output_schema)` — parses the success `result` through the schema; throws on envelope failure, error response, or schema mismatch. Use `rpc_call` when the test needs to assert on error shapes.
@@ -822,7 +823,7 @@ points:
822
823
 
823
824
  - **`await_pending_effects: true`** is set by `create_test_app`. Fire-and-forget effects (audit logs, session touches, WS fan-out via `emit_after_commit`) resolve before the response returns, so tests can assert on side effects inline without manual flushing.
824
825
  - **Deep-path imports only.** Import from the canonical module (`testing/db.js`, `testing/rpc_helpers.js`, etc.); fuz_app's `dist/` ships no barrel.
825
- - **DI via small `*Deps` interfaces.** Stub factories accept the same narrow `*Deps` contracts production code uses — never `Pick<GodType, ...>`. New helpers needing env/fs/logger take `EnvDeps` / `FsReadDeps` / `Logger` from `runtime/deps.ts` or `@fuzdev/fuz_util/log.js`.
826
+ - **DI via small `*Deps` interfaces.** Stub factories accept the same narrow `*Deps` contracts production code uses — never `Pick<GodType, ...>`. New helpers needing env/fs/logger take `EnvDeps` / `FsReadDeps` / `Logger` from `runtime/deps.ts` or `@fuzdev/fuz_util/log.ts`.
826
827
  - **Keep the shared echo routes in sync with public surface.** When middleware or public API gains a new context variable, header, or field, update the echo in `middleware.ts` (`create_bearer_auth_test_app`, `create_test_middleware_stack_app`) alongside the assertions in `src/test/auth/*.test.ts`. Drift surfaces as a missed assertion, not a test failure.
827
828
 
828
829
  ## Cross-backend integration layer
@@ -966,7 +967,7 @@ wire-shape check passes green on even when behavior is wrong.
966
967
 
967
968
  - `conformance_case.ts` — `ConformanceCase` Zod schema:
968
969
  `{name, request: {method, params?, as, verb?}, expect: {status,
969
- error_reason?, fields?}, note?, xfail?}`. A case is **data** — `method`
970
+ error_reason?, fields?, headers?, equivalence_group?}, note?, xfail?}`. A case is **data** — `method`
970
971
  resolves its `input`/`output` from the live registry (RPC) or `RouteSpec`
971
972
  (the 6 REST auth routes), so the case never carries a schema. `as` is the
972
973
  closed `ConformancePrincipal` enum (`keeper` / `daemon` / `token` /
@@ -978,7 +979,24 @@ error_reason?, fields?}, note?, xfail?}`. A case is **data** — `method`
978
979
  `error_reason` is the imported
979
980
  `ERROR_*` constant (asserted against the RPC `error.data.reason` or the
980
981
  REST flat-body `error`; the bare `unauthenticated()` 401 carries no
981
- reason, so `status` pins that denial class).
982
+ reason, so `status` pins that denial class). `equivalence_group` is the
983
+ **negative-space** axis: every case tagged with the same group string must
984
+ produce a **byte-identical** normalized response (`{status, body}`),
985
+ asserted per impl after the case loop. It promotes a masked pair
986
+ (wrong-password ≡ account-not-found, found-but-unauthorized ≡ not-found)
987
+ from "same status + reason" to "wire-indistinguishable", so a prober
988
+ hitting either spine can't tell the members apart — the twin of the
989
+ positive `output`-schema parity the runner already enforces. The
990
+ per-case status/reason assertions stay the non-vacuous positive control
991
+ (a both-paths-identically-broken group still fails the per-case checks).
992
+ `headers` is the **header** negative-space axis: a string value pins a
993
+ header present-and-equal (case-insensitive name), `null` pins it absent.
994
+ Independent of it, the runner enforces an always-on **no-fingerprint**
995
+ invariant on _every_ response (`conformance_table.ts` `FINGERPRINT_HEADERS`
996
+ — `Server` / `X-Powered-By` / `WWW-Authenticate` must stay absent on both
997
+ spines, so a framework upgrade adding one can't become a silent
998
+ backend-fingerprinting oracle). Headers are deliberately kept out of the
999
+ `equivalence_group` `{status, body}` comparison (`Set-Cookie` / `Date` vary).
982
1000
  - `conformance_table.ts` — `describe_conformance_table_tests({cases,
983
1001
  setup_test, surface_source, capabilities, rpc_endpoints, session_options,
984
1002
  principals?, suite_name?})`. Same `{setup_test, surface_source,
@@ -1347,6 +1365,33 @@ The accepted-case 403s rely on `create_spine_route_specs` zeroing
1347
1365
  `signup_fail_floor_ms` (mirroring `login_fail_floor_ms: 0`) so they don't each
1348
1366
  pay the 250ms denial floor.
1349
1367
 
1368
+ ### Login rate-limit + trusted-proxy parity — `cross_backend/login_security.ts`
1369
+
1370
+ `describe_login_security_cross_tests({setup_test, login_path?})` — the imperative
1371
+ suite pinning **login rate limiting + `X-Forwarded-For` client-IP resolution**
1372
+ over real HTTP on both spines. Two cases:
1373
+
1374
+ - **per-IP limit fires** — `default_login_ip_rate_limit.max_attempts` (5, the
1375
+ shared cap on both impls) failed logins from one forwarded IP → 401, the next →
1376
+ `429` with the canonical `{error: "rate_limit_exceeded", retry_after}` body +
1377
+ `Retry-After: ceil(retry_after)` header (TS `rate_limit_exceeded_response` ↔
1378
+ Rust `route_response::rate_limit_exceeded`).
1379
+ - **XFF keying** — exhaust one forwarded IP to 429, then a _distinct_ forwarded IP
1380
+ → 401 (not 429), proving the limiter keys on the resolved `X-Forwarded-For` IP,
1381
+ not the loopback TCP peer (a backend ignoring XFF would 429 the fresh IP too).
1382
+
1383
+ **Cross-process only**, on a **dedicated dual-spawn project** (`cross_backend_security`
1384
+ via `global_setup_login_security.ts`) — the limiters can't be enabled on a backend
1385
+ the standard suites share (they fire many loopback logins a live limiter would
1386
+ 429), so the standard backends keep every limiter null. Determinism without a
1387
+ limiter reset: each case uses its own forwarded IP (a fresh bucket) plus its own
1388
+ non-existent username. Zero Rust code change — the stub's `FUZ_LOGIN_RATE_LIMIT_ENABLED`
1389
+ and `FUZ_TRUSTED_PROXIES` env-gates were already wired; the TS side env-gates the
1390
+ limiters in the binary, and `create_spine_route_specs` honors `ctx.ip_rate_limiter`.
1391
+ The in-process counterparts already exist (`describe_rate_limiting_tests` plus the
1392
+ proxy middleware tests), so there's no in-process leg. `npm run test:cross:security`.
1393
+ Cited property: `docs/security.md` §"Rate Limiting" + §"Trusted Proxy / Client IP".
1394
+
1350
1395
  ### Building a TS test-server binary — `testing_server_core.ts` + adapters
1351
1396
 
1352
1397
  The reusable shape for standing up a **spawnable TS** cross-process test
@@ -14,7 +14,7 @@ import './assert_dev_env.js';
14
14
  */
15
15
  import { test, assert, describe } from 'vitest';
16
16
  import { z } from 'zod';
17
- import { zod_unwrap_to_object, zod_extract_fields } from '@fuzdev/fuz_util/zod.js';
17
+ import { zod_unwrap_to_object, zod_extract_fields } from '@fuzdev/fuz_util/zod.ts';
18
18
  import { is_null_schema } from '../http/schema_helpers.js';
19
19
  import { filter_routes_with_input, filter_routes_with_params, filter_routes_with_query, } from '../http/surface_query.js';
20
20
  import { ValidationError, ERROR_INVALID_REQUEST_BODY, ERROR_INVALID_JSON_BODY, ERROR_INVALID_ROUTE_PARAMS, ERROR_INVALID_QUERY_PARAMS, } from '../http/error_schemas.js';
@@ -13,7 +13,7 @@ import './assert_dev_env.js';
13
13
  * @module
14
14
  */
15
15
  import type { Hono } from 'hono';
16
- import type { Uuid } from '@fuzdev/fuz_util/id.js';
16
+ import type { Uuid } from '@fuzdev/fuz_util/id.ts';
17
17
  import { type Keyring } from '../auth/keyring.js';
18
18
  import type { Db, DbType } from '../db/db.js';
19
19
  import type { PasswordHashDeps } from '../auth/password.js';
@@ -1,6 +1,6 @@
1
1
  import './assert_dev_env.js';
2
2
  import { z } from 'zod';
3
- import { Logger } from '@fuzdev/fuz_util/log.js';
3
+ import { Logger } from '@fuzdev/fuz_util/log.ts';
4
4
  import { DEFAULT_TEST_PASSWORD } from './test_credentials.js';
5
5
  import { ROLE_KEEPER } from '../auth/role_schema.js';
6
6
  import { create_validated_keyring } from '../auth/keyring.js';
@@ -8,7 +8,7 @@ import './assert_dev_env.js';
8
8
  * @module
9
9
  */
10
10
  import { Hono } from 'hono';
11
- import { Logger } from '@fuzdev/fuz_util/log.js';
11
+ import { Logger } from '@fuzdev/fuz_util/log.ts';
12
12
  import { apply_route_specs } from '../http/route_spec.js';
13
13
  import { is_public_auth } from '../http/auth_shape.js';
14
14
  import { fuz_auth_guard_resolver } from '../auth/auth_guard_resolver.js';
@@ -1,5 +1,5 @@
1
1
  import '../../assert_dev_env.js';
2
- import { type BenchmarkComparison } from '@fuzdev/fuz_util/benchmark_stats.js';
2
+ import { type BenchmarkComparison } from '@fuzdev/fuz_util/benchmark_stats.ts';
3
3
  import type { CrossImplBenchResult } from './run_cross_impl_bench.js';
4
4
  /**
5
5
  * Reporting adapters over a `CrossImplBenchResult` — all built on fuz_util's
@@ -1,6 +1,6 @@
1
1
  import '../../assert_dev_env.js';
2
- import { benchmark_format_markdown } from '@fuzdev/fuz_util/benchmark_format.js';
3
- import { benchmark_stats_compare, } from '@fuzdev/fuz_util/benchmark_stats.js';
2
+ import { benchmark_format_markdown } from '@fuzdev/fuz_util/benchmark_format.ts';
3
+ import { benchmark_stats_compare, } from '@fuzdev/fuz_util/benchmark_stats.ts';
4
4
  /**
5
5
  * Reporting adapters over a `CrossImplBenchResult` — all built on fuz_util's
6
6
  * formatters + Welch comparison. Markdown for human eyeballs, a per-scenario
@@ -1,5 +1,5 @@
1
1
  import '../../assert_dev_env.js';
2
- import type { BenchmarkConfig, BenchmarkResult } from '@fuzdev/fuz_util/benchmark_types.js';
2
+ import type { BenchmarkConfig, BenchmarkResult } from '@fuzdev/fuz_util/benchmark_types.ts';
3
3
  import type { BootstrappedBackendHandle } from '../setup.js';
4
4
  import type { BenchScenario } from './scenario.js';
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  import '../../assert_dev_env.js';
2
- import { Benchmark } from '@fuzdev/fuz_util/benchmark.js';
2
+ import { Benchmark } from '@fuzdev/fuz_util/benchmark.ts';
3
3
  /**
4
4
  * Network-tuned defaults — fuz_util's micro-benchmark defaults (warmup 10,
5
5
  * min 30, duration 1000ms) are sized for sub-microsecond functions. RPC round
@@ -6,7 +6,7 @@ import '../assert_dev_env.js';
6
6
  * consumer's vitest `globalSetup` reduces to a single await:
7
7
  *
8
8
  * ```ts
9
- * import {bootstrap_backend} from '@fuzdev/fuz_app/testing/cross_backend/bootstrap_backend.js';
9
+ * import {bootstrap_backend} from '@fuzdev/fuz_app/testing/cross_backend/bootstrap_backend.ts';
10
10
  *
11
11
  * export default async function ({provide}) {
12
12
  * const bootstrapped = await bootstrap_backend(deno_backend_config());
@@ -52,7 +52,7 @@ import '../assert_dev_env.js';
52
52
  * @module
53
53
  */
54
54
  import { describe, assert } from 'vitest';
55
- import { fractional_index_between } from '@fuzdev/fuz_util/fractional_index.js';
55
+ import { fractional_index_between } from '@fuzdev/fuz_util/fractional_index.ts';
56
56
  import { CellCreateOutput, CellUpdateOutput, CellCloneOutput, CellGetOutput, } from '../../auth/cell_action_specs.js';
57
57
  import { AuditLogListOutput } from '../../auth/admin_action_specs.js';
58
58
  import { CellGrantCreateOutput, CellGrantListOutput, CellGrantRevokeOutput, } from '../../auth/cell_grant_action_specs.js';
@@ -85,6 +85,8 @@ export declare const ConformanceCaseExpectation: z.ZodObject<{
85
85
  status: z.ZodNumber;
86
86
  error_reason: z.ZodOptional<z.ZodString>;
87
87
  fields: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
88
+ headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodString>>>;
89
+ equivalence_group: z.ZodOptional<z.ZodString>;
88
90
  }, z.core.$strict>;
89
91
  export type ConformanceCaseExpectation = z.infer<typeof ConformanceCaseExpectation>;
90
92
  /**
@@ -133,6 +135,8 @@ export declare const ConformanceCase: z.ZodObject<{
133
135
  status: z.ZodNumber;
134
136
  error_reason: z.ZodOptional<z.ZodString>;
135
137
  fields: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
138
+ headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodString>>>;
139
+ equivalence_group: z.ZodOptional<z.ZodString>;
136
140
  }, z.core.$strict>;
137
141
  note: z.ZodOptional<z.ZodString>;
138
142
  xfail: z.ZodOptional<z.ZodObject<{
@@ -1 +1 @@
1
- {"version":3,"file":"conformance_case.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/conformance_case.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;EAS/B,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAExE,6CAA6C;AAC7C,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;kBAgBjC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAE5E,8DAA8D;AAC9D,eAAO,MAAM,0BAA0B;;;;kBAqBrC,CAAC;AACH,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAEpF;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB;;;kBAK/B,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAExE;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAS1B,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC"}
1
+ {"version":3,"file":"conformance_case.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/conformance_case.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;EAS/B,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAExE,6CAA6C;AAC7C,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;kBAgBjC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAE5E,8DAA8D;AAC9D,eAAO,MAAM,0BAA0B;;;;;;kBAiDrC,CAAC;AACH,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAEpF;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB;;;kBAK/B,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAExE;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAS1B,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC"}
@@ -96,6 +96,32 @@ export const ConformanceCaseExpectation = z.strictObject({
96
96
  description: 'Specific field-value assertions on the success `result` (2xx) or the error ' +
97
97
  '`error.data` (non-2xx). Each key must deep-equal the corresponding response field.',
98
98
  }),
99
+ headers: z
100
+ .record(z.string(), z.string().nullable())
101
+ .optional()
102
+ .meta({
103
+ description: 'Per-header expectations on the response. Each key is a header name ' +
104
+ '(case-insensitive); a string value asserts the header is present and equals ' +
105
+ 'it exactly, `null` asserts the header is ABSENT. Independent of this, the ' +
106
+ 'runner enforces an unconditional no-fingerprint invariant on EVERY response ' +
107
+ '(`Server` / `X-Powered-By` / `WWW-Authenticate` must stay absent on both ' +
108
+ 'spines), so a case only needs `headers` to pin a header beyond that ' +
109
+ 'always-on floor.',
110
+ }),
111
+ equivalence_group: z
112
+ .string()
113
+ .optional()
114
+ .meta({
115
+ description: 'Tags this case as a member of an indistinguishability group. After all cases ' +
116
+ 'run, the runner asserts every member of a group produced a BYTE-IDENTICAL ' +
117
+ 'normalized response (`{status, body}`) — checked per impl. This promotes a ' +
118
+ 'masked pair (found-but-unauthorized ≡ not-found, wrong-password ≡ ' +
119
+ 'account-not-found) from "same status + reason" to "wire-indistinguishable", ' +
120
+ 'and holds BOTH impls to it: a prober hitting either spine cannot tell the ' +
121
+ 'members apart. A group needs >= 2 members; a member may still set `fields`. ' +
122
+ 'The negative-space twin of the positive `output`-schema parity the runner ' +
123
+ 'already asserts.',
124
+ }),
99
125
  });
100
126
  /**
101
127
  * Marks a case as a deferred-by-design gap. The runner routes it through
@@ -36,6 +36,27 @@ export interface ConformanceTableOptions {
36
36
  /** `describe` block label. Defaults to `'conformance table'`. */
37
37
  readonly suite_name?: string;
38
38
  }
39
+ /**
40
+ * Response headers that fingerprint the backend implementation or framework.
41
+ * Neither spine emits these; the runner asserts they stay absent on EVERY
42
+ * conformance response so a framework upgrade or consumer middleware that adds
43
+ * (say) `Server:` to one spine can't silently become a backend-identifying
44
+ * oracle. Lowercased — matched against the lowercased-key snapshot
45
+ * `headers_to_record` produces.
46
+ */
47
+ export declare const FINGERPRINT_HEADERS: ReadonlyArray<string>;
48
+ /**
49
+ * Assert a response carries none of the `FINGERPRINT_HEADERS`. Run on every
50
+ * case unconditionally — the always-on no-fingerprint floor.
51
+ */
52
+ export declare const assert_no_fingerprint_headers: (headers: Record<string, string>, label: string) => void;
53
+ /**
54
+ * Assert each declared header expectation: a string value must be present and
55
+ * equal (header name matched case-insensitively), `null` must be absent. The
56
+ * negative-space twin for headers — `expect.headers` pins a header beyond the
57
+ * always-on no-fingerprint floor.
58
+ */
59
+ export declare const assert_expected_headers: (headers: Record<string, string>, expected: Record<string, string | null>, label: string) => void;
39
60
  /**
40
61
  * Register a `describe` block running every `ConformanceCase` as a
41
62
  * vitest `test` (or `xfail_until` for deferred-by-design rows). Drives
@@ -1 +1 @@
1
- {"version":3,"file":"conformance_table.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/conformance_table.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAwB9B,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,uBAAuB,CAAC;AAE1D,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,8BAA8B,CAAC;AAMjE,OAAO,EAIN,KAAK,uBAAuB,EAC5B,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAC,KAAK,eAAe,EAA4B,MAAM,uBAAuB,CAAC;AACtF,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,mBAAmB,CAAC;AAC3D,OAAO,KAAK,EAAC,SAAS,EAAc,MAAM,YAAY,CAAC;AAGvD;;;;;GAKG;AACH,MAAM,WAAW,0BAA0B;IAC1C,iEAAiE;IACjE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,gEAAgE;IAChE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,sDAAsD;AACtD,MAAM,WAAW,uBAAuB;IACvC,8CAA8C;IAC9C,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IAC/C,+DAA+D;IAC/D,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC;IAC/B,oEAAoE;IACpE,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,0EAA0E;IAC1E,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;IAC3C,kEAAkE;IAClE,QAAQ,CAAC,aAAa,EAAE,uBAAuB,CAAC;IAChD,4EAA4E;IAC5E,QAAQ,CAAC,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACjD,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,CAAC,EAAE,0BAA0B,CAAC;IACjD,iEAAiE;IACjE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC7B;AAkOD;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,GAAI,SAAS,uBAAuB,KAAG,IAgBnF,CAAC"}
1
+ {"version":3,"file":"conformance_table.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/conformance_table.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AA8B9B,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,uBAAuB,CAAC;AAE1D,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,8BAA8B,CAAC;AAMjE,OAAO,EAKN,KAAK,uBAAuB,EAC5B,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAC,KAAK,eAAe,EAA4B,MAAM,uBAAuB,CAAC;AACtF,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,mBAAmB,CAAC;AAC3D,OAAO,KAAK,EAAC,SAAS,EAAc,MAAM,YAAY,CAAC;AAGvD;;;;;GAKG;AACH,MAAM,WAAW,0BAA0B;IAC1C,iEAAiE;IACjE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,gEAAgE;IAChE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,sDAAsD;AACtD,MAAM,WAAW,uBAAuB;IACvC,8CAA8C;IAC9C,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IAC/C,+DAA+D;IAC/D,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC;IAC/B,oEAAoE;IACpE,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,0EAA0E;IAC1E,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;IAC3C,kEAAkE;IAClE,QAAQ,CAAC,aAAa,EAAE,uBAAuB,CAAC;IAChD,4EAA4E;IAC5E,QAAQ,CAAC,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACjD,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,CAAC,EAAE,0BAA0B,CAAC;IACjD,iEAAiE;IACjE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC7B;AA+FD;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,EAAE,aAAa,CAAC,MAAM,CAIrD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,6BAA6B,GACzC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,OAAO,MAAM,KACX,IAQF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GACnC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,UAAU,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,EACvC,OAAO,MAAM,KACX,IAYF,CAAC;AAgKF;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,GAAI,SAAS,uBAAuB,KAAG,IAkEnF,CAAC"}