@fuzdev/fuz_app 0.65.0 → 0.67.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 (159) hide show
  1. package/dist/actions/CLAUDE.md +65 -86
  2. package/dist/actions/action_codegen.d.ts +1 -1
  3. package/dist/actions/action_codegen.js +1 -1
  4. package/dist/actions/action_event_data.d.ts +1 -1
  5. package/dist/auth/CLAUDE.md +83 -104
  6. package/dist/auth/audit_log_schema.js +2 -2
  7. package/dist/auth/daemon_token_middleware.d.ts +15 -5
  8. package/dist/auth/daemon_token_middleware.d.ts.map +1 -1
  9. package/dist/auth/daemon_token_middleware.js +24 -15
  10. package/dist/auth/invite_queries.d.ts +17 -7
  11. package/dist/auth/invite_queries.d.ts.map +1 -1
  12. package/dist/auth/invite_queries.js +19 -8
  13. package/dist/auth/signup_routes.d.ts +47 -1
  14. package/dist/auth/signup_routes.d.ts.map +1 -1
  15. package/dist/auth/signup_routes.js +103 -52
  16. package/dist/env/resolve.d.ts +44 -7
  17. package/dist/env/resolve.d.ts.map +1 -1
  18. package/dist/env/resolve.js +94 -27
  19. package/dist/http/CLAUDE.md +47 -52
  20. package/dist/http/jsonrpc.d.ts +23 -7
  21. package/dist/http/jsonrpc.d.ts.map +1 -1
  22. package/dist/http/jsonrpc.js +19 -3
  23. package/dist/http/surface.d.ts +9 -2
  24. package/dist/http/surface.d.ts.map +1 -1
  25. package/dist/runtime/mock.d.ts +1 -1
  26. package/dist/runtime/mock.js +1 -1
  27. package/dist/testing/CLAUDE.md +659 -511
  28. package/dist/testing/admin_integration.d.ts +5 -5
  29. package/dist/testing/admin_integration.d.ts.map +1 -1
  30. package/dist/testing/admin_integration.js +95 -39
  31. package/dist/testing/app_server.d.ts +16 -1
  32. package/dist/testing/app_server.d.ts.map +1 -1
  33. package/dist/testing/app_server.js +18 -3
  34. package/dist/testing/audit_completeness.d.ts +7 -5
  35. package/dist/testing/audit_completeness.d.ts.map +1 -1
  36. package/dist/testing/audit_completeness.js +5 -9
  37. package/dist/testing/bootstrap_success.js +2 -2
  38. package/dist/testing/cross_backend/backend_config.d.ts +113 -0
  39. package/dist/testing/cross_backend/backend_config.d.ts.map +1 -0
  40. package/dist/testing/cross_backend/backend_config.js +1 -0
  41. package/dist/testing/cross_backend/bench/bench_report.d.ts +46 -0
  42. package/dist/testing/cross_backend/bench/bench_report.d.ts.map +1 -0
  43. package/dist/testing/cross_backend/bench/bench_report.js +83 -0
  44. package/dist/testing/cross_backend/bench/run_cross_impl_bench.d.ts +44 -0
  45. package/dist/testing/cross_backend/bench/run_cross_impl_bench.d.ts.map +1 -0
  46. package/dist/testing/cross_backend/bench/run_cross_impl_bench.js +38 -0
  47. package/dist/testing/cross_backend/bench/scenario.d.ts +57 -0
  48. package/dist/testing/cross_backend/bench/scenario.d.ts.map +1 -0
  49. package/dist/testing/cross_backend/bench/scenario.js +28 -0
  50. package/dist/testing/cross_backend/bootstrap_backend.d.ts +41 -0
  51. package/dist/testing/cross_backend/bootstrap_backend.d.ts.map +1 -0
  52. package/dist/testing/cross_backend/bootstrap_backend.js +34 -0
  53. package/dist/testing/cross_backend/build_test_backend_paths.d.ts +24 -0
  54. package/dist/testing/cross_backend/build_test_backend_paths.d.ts.map +1 -0
  55. package/dist/testing/cross_backend/build_test_backend_paths.js +33 -0
  56. package/dist/testing/cross_backend/capabilities.d.ts +3 -2
  57. package/dist/testing/cross_backend/capabilities.d.ts.map +1 -1
  58. package/dist/testing/cross_backend/default_backend_configs.d.ts +122 -0
  59. package/dist/testing/cross_backend/default_backend_configs.d.ts.map +1 -0
  60. package/dist/testing/cross_backend/default_backend_configs.js +111 -0
  61. package/dist/testing/cross_backend/default_secrets.d.ts +40 -0
  62. package/dist/testing/cross_backend/default_secrets.d.ts.map +1 -0
  63. package/dist/testing/cross_backend/default_secrets.js +39 -0
  64. package/dist/testing/cross_backend/default_spine_surface.d.ts +64 -0
  65. package/dist/testing/cross_backend/default_spine_surface.d.ts.map +1 -0
  66. package/dist/testing/cross_backend/default_spine_surface.js +121 -0
  67. package/dist/testing/cross_backend/setup.d.ts +270 -34
  68. package/dist/testing/cross_backend/setup.d.ts.map +1 -1
  69. package/dist/testing/cross_backend/setup.js +495 -15
  70. package/dist/testing/cross_backend/spawn_backend.d.ts +58 -0
  71. package/dist/testing/cross_backend/spawn_backend.d.ts.map +1 -0
  72. package/dist/testing/cross_backend/spawn_backend.js +229 -0
  73. package/dist/testing/cross_backend/spine_stub_backend_config.d.ts +66 -0
  74. package/dist/testing/cross_backend/spine_stub_backend_config.d.ts.map +1 -0
  75. package/dist/testing/cross_backend/spine_stub_backend_config.js +49 -0
  76. package/dist/testing/cross_backend/sse_round_trip.d.ts +37 -0
  77. package/dist/testing/cross_backend/sse_round_trip.d.ts.map +1 -0
  78. package/dist/testing/cross_backend/sse_round_trip.js +137 -0
  79. package/dist/testing/cross_backend/standard.d.ts +96 -0
  80. package/dist/testing/cross_backend/standard.d.ts.map +1 -0
  81. package/dist/testing/cross_backend/standard.js +49 -0
  82. package/dist/testing/cross_backend/testing_reset_actions.d.ts +171 -0
  83. package/dist/testing/cross_backend/testing_reset_actions.d.ts.map +1 -0
  84. package/dist/testing/cross_backend/testing_reset_actions.js +213 -0
  85. package/dist/testing/cross_backend/testing_server_bun.d.ts +5 -0
  86. package/dist/testing/cross_backend/testing_server_bun.d.ts.map +1 -0
  87. package/dist/testing/cross_backend/testing_server_bun.js +59 -0
  88. package/dist/testing/cross_backend/testing_server_core.d.ts +140 -0
  89. package/dist/testing/cross_backend/testing_server_core.d.ts.map +1 -0
  90. package/dist/testing/cross_backend/testing_server_core.js +68 -0
  91. package/dist/testing/cross_backend/testing_server_deno.d.ts +5 -0
  92. package/dist/testing/cross_backend/testing_server_deno.d.ts.map +1 -0
  93. package/dist/testing/cross_backend/testing_server_deno.js +37 -0
  94. package/dist/testing/cross_backend/testing_server_node.d.ts +5 -0
  95. package/dist/testing/cross_backend/testing_server_node.d.ts.map +1 -0
  96. package/dist/testing/cross_backend/testing_server_node.js +50 -0
  97. package/dist/testing/cross_backend/ts_spine_backend_config.d.ts +72 -0
  98. package/dist/testing/cross_backend/ts_spine_backend_config.d.ts.map +1 -0
  99. package/dist/testing/cross_backend/ts_spine_backend_config.js +112 -0
  100. package/dist/testing/cross_backend/ws_round_trip.d.ts +35 -0
  101. package/dist/testing/cross_backend/ws_round_trip.d.ts.map +1 -0
  102. package/dist/testing/cross_backend/ws_round_trip.js +113 -0
  103. package/dist/testing/data_exposure.d.ts +4 -6
  104. package/dist/testing/data_exposure.d.ts.map +1 -1
  105. package/dist/testing/data_exposure.js +1 -5
  106. package/dist/testing/db_entities.d.ts +18 -7
  107. package/dist/testing/db_entities.d.ts.map +1 -1
  108. package/dist/testing/db_entities.js +18 -7
  109. package/dist/testing/integration.d.ts +27 -6
  110. package/dist/testing/integration.d.ts.map +1 -1
  111. package/dist/testing/integration.js +93 -58
  112. package/dist/testing/round_trip.d.ts +4 -5
  113. package/dist/testing/round_trip.d.ts.map +1 -1
  114. package/dist/testing/round_trip.js +1 -5
  115. package/dist/testing/rpc_helpers.d.ts +10 -4
  116. package/dist/testing/rpc_helpers.d.ts.map +1 -1
  117. package/dist/testing/rpc_helpers.js +1 -1
  118. package/dist/testing/rpc_round_trip.d.ts +5 -5
  119. package/dist/testing/rpc_round_trip.d.ts.map +1 -1
  120. package/dist/testing/rpc_round_trip.js +1 -5
  121. package/dist/testing/sse_round_trip.d.ts.map +1 -1
  122. package/dist/testing/sse_round_trip.js +1 -68
  123. package/dist/testing/standard.d.ts +4 -5
  124. package/dist/testing/standard.d.ts.map +1 -1
  125. package/dist/testing/stubs.d.ts +10 -3
  126. package/dist/testing/stubs.d.ts.map +1 -1
  127. package/dist/testing/stubs.js +9 -2
  128. package/dist/testing/testing_rate_limiter.d.ts +59 -0
  129. package/dist/testing/testing_rate_limiter.d.ts.map +1 -0
  130. package/dist/testing/testing_rate_limiter.js +74 -0
  131. package/dist/testing/transports/bootstrap.d.ts +52 -0
  132. package/dist/testing/transports/bootstrap.d.ts.map +1 -0
  133. package/dist/testing/transports/bootstrap.js +70 -0
  134. package/dist/testing/transports/fetch_transport.d.ts +81 -0
  135. package/dist/testing/transports/fetch_transport.d.ts.map +1 -0
  136. package/dist/testing/transports/fetch_transport.js +74 -0
  137. package/dist/testing/transports/sse_frame_reader.d.ts +41 -0
  138. package/dist/testing/transports/sse_frame_reader.d.ts.map +1 -0
  139. package/dist/testing/transports/sse_frame_reader.js +84 -0
  140. package/dist/testing/transports/sse_transport.d.ts +54 -0
  141. package/dist/testing/transports/sse_transport.d.ts.map +1 -0
  142. package/dist/testing/transports/sse_transport.js +51 -0
  143. package/dist/testing/transports/ws_client.d.ts +108 -0
  144. package/dist/testing/transports/ws_client.d.ts.map +1 -0
  145. package/dist/testing/transports/ws_client.js +56 -0
  146. package/dist/testing/transports/ws_transport.d.ts +43 -0
  147. package/dist/testing/transports/ws_transport.d.ts.map +1 -0
  148. package/dist/testing/transports/ws_transport.js +169 -0
  149. package/dist/testing/ws_round_trip.d.ts +21 -103
  150. package/dist/testing/ws_round_trip.d.ts.map +1 -1
  151. package/dist/testing/ws_round_trip.js +42 -40
  152. package/dist/ui/CLAUDE.md +5 -3
  153. package/dist/ui/MenuLink.svelte +16 -16
  154. package/dist/ui/MenuLink.svelte.d.ts +13 -4
  155. package/dist/ui/MenuLink.svelte.d.ts.map +1 -1
  156. package/package.json +20 -3
  157. package/dist/testing/transports/surface_source.d.ts +0 -51
  158. package/dist/testing/transports/surface_source.d.ts.map +0 -1
  159. package/dist/testing/transports/surface_source.js +0 -19
@@ -0,0 +1,49 @@
1
+ import '../assert_dev_env.js';
2
+ import { describe_standard_integration_tests } from '../integration.js';
3
+ import { describe_standard_admin_integration_tests } from '../admin_integration.js';
4
+ import { describe_round_trip_validation } from '../round_trip.js';
5
+ import { describe_rpc_round_trip_tests } from '../rpc_round_trip.js';
6
+ import { describe_data_exposure_tests } from '../data_exposure.js';
7
+ /**
8
+ * Run the cross-process standard test bundle — integration, admin (when
9
+ * `roles` provided), round trip, RPC round trip, data exposure. See the
10
+ * module doc for the suites omitted from this bundle and why.
11
+ */
12
+ export const describe_standard_cross_process_tests = (options) => {
13
+ describe_standard_integration_tests({
14
+ setup_test: options.setup_test,
15
+ surface_source: options.surface_source,
16
+ capabilities: options.capabilities,
17
+ session_options: options.session_options,
18
+ rpc_endpoints: options.rpc_endpoints,
19
+ error_coverage_min: options.error_coverage_min,
20
+ });
21
+ describe_round_trip_validation({
22
+ setup_test: options.setup_test,
23
+ surface_source: options.surface_source,
24
+ capabilities: options.capabilities,
25
+ });
26
+ describe_rpc_round_trip_tests({
27
+ setup_test: options.setup_test,
28
+ surface_source: options.surface_source,
29
+ capabilities: options.capabilities,
30
+ session_options: options.session_options,
31
+ rpc_endpoints: options.rpc_endpoints,
32
+ });
33
+ describe_data_exposure_tests({
34
+ setup_test: options.setup_test,
35
+ surface_source: options.surface_source,
36
+ capabilities: options.capabilities,
37
+ });
38
+ if (options.roles) {
39
+ describe_standard_admin_integration_tests({
40
+ setup_test: options.setup_test,
41
+ surface_source: options.surface_source,
42
+ capabilities: options.capabilities,
43
+ session_options: options.session_options,
44
+ roles: options.roles,
45
+ rpc_endpoints: options.rpc_endpoints,
46
+ admin_prefix: options.admin_prefix,
47
+ });
48
+ }
49
+ };
@@ -0,0 +1,171 @@
1
+ import '../assert_dev_env.js';
2
+ /**
3
+ * Test-binary RPC actions for cross-process integration tests.
4
+ *
5
+ * Single daemon-token-authed action: **`_testing_reset`** — full DB
6
+ * wipe + keeper re-seed + optional secondary-account seeding. The
7
+ * handler wipes every auth-namespace row (no keeper-preserve filter),
8
+ * flips `bootstrap_lock` back to its post-bootstrap shape, seeds a
9
+ * fresh keeper account inline (reusing `create_test_account_with_credentials`
10
+ * so cross-process matches in-process write semantics), seeds any
11
+ * caller-requested `extra_accounts` (also direct-inserted at this
12
+ * setup step), refreshes the daemon-token cache to point at the new
13
+ * keeper, and fires the consumer-supplied domain-state callback. The
14
+ * new keeper + secondary credentials return as the action output so
15
+ * the per-test fixture closes over them.
16
+ *
17
+ * The redesign converges in-process and cross-process keeper
18
+ * lifetimes: both modes now run against a freshly bootstrapped keeper
19
+ * per test. Mutation-cascade tests (password change, revoke-all,
20
+ * hardcoded-username signup uniqueness) and direct keeper-vs-admin
21
+ * probes work uniformly cross-process.
22
+ *
23
+ * **Keeper ≠ admin.** The `keeper` and `admin` roles are independent.
24
+ * Keeper authorizes daemon-token / bootstrap paths; admin authorizes
25
+ * the user-facing admin RPC surface. `_testing_reset` seeds the keeper
26
+ * account with `[ROLE_KEEPER, ROLE_ADMIN]` by default — matching the
27
+ * production `bootstrap_account` flow — plus any roles passed via
28
+ * `extra_keeper_roles`. Tests probing the keeper-vs-admin separation
29
+ * (a keeper-only account must 403 on admin RPCs) declare a secondary
30
+ * via `extra_accounts: [{username, roles: [ROLE_KEEPER]}]` so the
31
+ * account is seeded at this same bootstrap-equivalent step.
32
+ *
33
+ * **No free-form runtime bypass.** Earlier drafts considered a separate
34
+ * `_testing_seed_role_grant` action for arbitrary direct grants; that
35
+ * was rejected because a runtime bypass would let tests skip the
36
+ * production consent flow's side-effects (audit emit, WS fan-out) and
37
+ * silently mask bugs in those paths. The bypass that does exist —
38
+ * `extra_accounts` — is framed as bootstrap-time seeding, the same
39
+ * shape `bootstrap_account` itself uses to grant the initial
40
+ * `KEEPER` + `ADMIN` pair. Tests that want a role on a *post-bootstrap*
41
+ * account must route through `role_grant_offer_create` +
42
+ * `role_grant_offer_accept` (the production path); they observe the
43
+ * full event chain.
44
+ *
45
+ * Production safety: this module lives under `cross_backend/` and starts
46
+ * with `import '../assert_dev_env.js';` — production bundles either
47
+ * tree-shake the module out or throw at startup. The Rust mirror
48
+ * (`fuz_testing` crate) ships a parallel action; `cargo xtask
49
+ * check-release` blocks `fuz_testing` from entering production dep
50
+ * graphs.
51
+ *
52
+ * @module
53
+ */
54
+ import { z } from 'zod';
55
+ import { type RpcAction } from '../../actions/action_rpc.js';
56
+ import type { AppDeps } from '../../auth/deps.js';
57
+ import type { SessionOptions } from '../../auth/session_cookie.js';
58
+ import type { DaemonTokenState } from '../../auth/daemon_token.js';
59
+ /**
60
+ * The `_testing_reset` action spec.
61
+ *
62
+ * Input:
63
+ * - `extra_keeper_roles` — roles to grant the fresh keeper *in addition
64
+ * to* `[ROLE_KEEPER, ROLE_ADMIN]` (matching production bootstrap).
65
+ * - `extra_accounts` — additional accounts to seed at this same
66
+ * bootstrap-equivalent step. Each entry's `roles` are direct-granted
67
+ * (bypassing offer/accept) because the seed is *part of bootstrap*,
68
+ * not a post-bootstrap action. Use this for accounts whose required
69
+ * roles aren't admin-grantable via offer/accept (e.g. `ROLE_KEEPER`,
70
+ * whose `RoleSpec.grant_paths` is bootstrap-only). For
71
+ * admin-grantable roles, prefer `fixture.create_account({roles})`
72
+ * (offer/accept production path).
73
+ *
74
+ * Output: keeper credentials plus a parallel array of seeded
75
+ * `extra_accounts` (same order as input). The per-test fixture closes
76
+ * over the returned values; subsequent calls in the same test see the
77
+ * fresh keeper and any requested secondaries.
78
+ *
79
+ * `auth` gates on the daemon-token credential — the keeper holds it
80
+ * exclusively. The action is internally privileged (it runs direct
81
+ * DB writes the production wire never exposes); daemon-token auth is
82
+ * the structural fence.
83
+ */
84
+ export declare const testing_reset_action_spec: {
85
+ readonly method: "_testing_reset";
86
+ readonly kind: "request_response";
87
+ readonly initiator: "frontend";
88
+ readonly auth: {
89
+ readonly account: "required";
90
+ readonly actor: "none";
91
+ readonly credential_types: readonly ["daemon_token"];
92
+ };
93
+ readonly side_effects: true;
94
+ readonly input: z.ZodObject<{
95
+ extra_keeper_roles: z.ZodOptional<z.ZodArray<z.ZodString>>;
96
+ extra_accounts: z.ZodOptional<z.ZodArray<z.ZodObject<{
97
+ username: z.ZodString;
98
+ password_value: z.ZodOptional<z.ZodString>;
99
+ roles: z.ZodArray<z.ZodString>;
100
+ }, z.core.$strict>>>;
101
+ }, z.core.$strict>;
102
+ readonly output: z.ZodObject<{
103
+ account: z.ZodObject<{
104
+ id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
105
+ username: z.ZodString;
106
+ }, z.core.$strict>;
107
+ actor: z.ZodObject<{
108
+ id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
109
+ }, z.core.$strict>;
110
+ api_token: z.ZodString;
111
+ session_cookie: z.ZodString;
112
+ extra_accounts: z.ZodArray<z.ZodObject<{
113
+ account: z.ZodObject<{
114
+ id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
115
+ username: z.ZodString;
116
+ }, z.core.$strict>;
117
+ actor: z.ZodObject<{
118
+ id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
119
+ }, z.core.$strict>;
120
+ api_token: z.ZodString;
121
+ session_cookie: z.ZodString;
122
+ }, z.core.$strict>>;
123
+ }, z.core.$strict>;
124
+ readonly async: true;
125
+ readonly description: "Test-binary only — wipe auth tables, re-bootstrap a fresh keeper (+ optional extras), fire the domain-state reset.";
126
+ };
127
+ /** Options for `create_testing_actions`. */
128
+ export interface CreateTestingActionsOptions {
129
+ /**
130
+ * Session cookie options — the reset action uses these when signing
131
+ * the fresh keeper's (and any extra accounts') session cookies.
132
+ * Pass the same `SessionOptions` the live `create_app_server` call
133
+ * was wired with.
134
+ */
135
+ readonly session_options: SessionOptions<string>;
136
+ /**
137
+ * Daemon-token runtime state — the reset action mutates
138
+ * `state.keeper_account_id` to point at the freshly seeded keeper
139
+ * after the old row is wiped. Pass the same `DaemonTokenState`
140
+ * instance the daemon-token middleware reads.
141
+ */
142
+ readonly daemon_token_state: DaemonTokenState;
143
+ /**
144
+ * Consumer-supplied callback invoked after the auth-table reset.
145
+ * `testing_zzz_server` clears workspace registry + terminals + the
146
+ * scoped FS scratch dir here; `testing_spine_stub` has no domain
147
+ * layer and passes a no-op (or omits the option). Runs inside the
148
+ * same RPC dispatch as the auth-table writes, so a throw surfaces
149
+ * to the caller as a JSON-RPC error and the per-test fixture
150
+ * short-circuits.
151
+ */
152
+ readonly reset_state?: () => Promise<void> | void;
153
+ }
154
+ /**
155
+ * Build the testing RPC actions for a test binary's registry.
156
+ *
157
+ * Returns `_testing_reset` — the single privileged action test binaries
158
+ * register. The test binary calls this at server-assembly time and
159
+ * registers the result on its dispatcher.
160
+ *
161
+ * The reset action's table-wipe list mirrors
162
+ * `auth_integration_truncate_tables` from `testing/db.ts` — the
163
+ * canonical "auth tables a between-test reset must clear" set.
164
+ * `testing_reset_actions.coverage.test.ts` enforces the set-equality
165
+ * invariant so a future auth migration that adds a table to that list
166
+ * without updating this handler fails CI.
167
+ */
168
+ export declare const create_testing_actions: (deps: AppDeps, options: CreateTestingActionsOptions) => Array<RpcAction>;
169
+ /** Set of auth-namespace tables `_testing_reset` wipes. Mirrored by the coverage test. */
170
+ export declare const testing_reset_wiped_tables: string[];
171
+ //# sourceMappingURL=testing_reset_actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing_reset_actions.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/testing_reset_actions.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAGtB,OAAO,EAAa,KAAK,SAAS,EAAC,MAAM,6BAA6B,CAAC;AAEvE,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,oBAAoB,CAAC;AAChD,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,8BAA8B,CAAC;AACjE,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,4BAA4B,CAAC;AAajE;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwBQ,CAAC;AAE/C,4CAA4C;AAC5C,MAAM,WAAW,2BAA2B;IAC3C;;;;;OAKG;IACH,QAAQ,CAAC,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACjD;;;;;OAKG;IACH,QAAQ,CAAC,kBAAkB,EAAE,gBAAgB,CAAC;IAC9C;;;;;;;;OAQG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAClD;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,sBAAsB,GAClC,MAAM,OAAO,EACb,SAAS,2BAA2B,KAClC,KAAK,CAAC,SAAS,CA4FjB,CAAC;AAEF,0FAA0F;AAC1F,eAAO,MAAM,0BAA0B,UAAmC,CAAC"}
@@ -0,0 +1,213 @@
1
+ import '../assert_dev_env.js';
2
+ /**
3
+ * Test-binary RPC actions for cross-process integration tests.
4
+ *
5
+ * Single daemon-token-authed action: **`_testing_reset`** — full DB
6
+ * wipe + keeper re-seed + optional secondary-account seeding. The
7
+ * handler wipes every auth-namespace row (no keeper-preserve filter),
8
+ * flips `bootstrap_lock` back to its post-bootstrap shape, seeds a
9
+ * fresh keeper account inline (reusing `create_test_account_with_credentials`
10
+ * so cross-process matches in-process write semantics), seeds any
11
+ * caller-requested `extra_accounts` (also direct-inserted at this
12
+ * setup step), refreshes the daemon-token cache to point at the new
13
+ * keeper, and fires the consumer-supplied domain-state callback. The
14
+ * new keeper + secondary credentials return as the action output so
15
+ * the per-test fixture closes over them.
16
+ *
17
+ * The redesign converges in-process and cross-process keeper
18
+ * lifetimes: both modes now run against a freshly bootstrapped keeper
19
+ * per test. Mutation-cascade tests (password change, revoke-all,
20
+ * hardcoded-username signup uniqueness) and direct keeper-vs-admin
21
+ * probes work uniformly cross-process.
22
+ *
23
+ * **Keeper ≠ admin.** The `keeper` and `admin` roles are independent.
24
+ * Keeper authorizes daemon-token / bootstrap paths; admin authorizes
25
+ * the user-facing admin RPC surface. `_testing_reset` seeds the keeper
26
+ * account with `[ROLE_KEEPER, ROLE_ADMIN]` by default — matching the
27
+ * production `bootstrap_account` flow — plus any roles passed via
28
+ * `extra_keeper_roles`. Tests probing the keeper-vs-admin separation
29
+ * (a keeper-only account must 403 on admin RPCs) declare a secondary
30
+ * via `extra_accounts: [{username, roles: [ROLE_KEEPER]}]` so the
31
+ * account is seeded at this same bootstrap-equivalent step.
32
+ *
33
+ * **No free-form runtime bypass.** Earlier drafts considered a separate
34
+ * `_testing_seed_role_grant` action for arbitrary direct grants; that
35
+ * was rejected because a runtime bypass would let tests skip the
36
+ * production consent flow's side-effects (audit emit, WS fan-out) and
37
+ * silently mask bugs in those paths. The bypass that does exist —
38
+ * `extra_accounts` — is framed as bootstrap-time seeding, the same
39
+ * shape `bootstrap_account` itself uses to grant the initial
40
+ * `KEEPER` + `ADMIN` pair. Tests that want a role on a *post-bootstrap*
41
+ * account must route through `role_grant_offer_create` +
42
+ * `role_grant_offer_accept` (the production path); they observe the
43
+ * full event chain.
44
+ *
45
+ * Production safety: this module lives under `cross_backend/` and starts
46
+ * with `import '../assert_dev_env.js';` — production bundles either
47
+ * tree-shake the module out or throw at startup. The Rust mirror
48
+ * (`fuz_testing` crate) ships a parallel action; `cargo xtask
49
+ * check-release` blocks `fuz_testing` from entering production dep
50
+ * graphs.
51
+ *
52
+ * @module
53
+ */
54
+ import { z } from 'zod';
55
+ import { Uuid } from '@fuzdev/fuz_util/id.js';
56
+ import { rpc_action } from '../../actions/action_rpc.js';
57
+ import { ROLE_ADMIN, ROLE_KEEPER } from '../../auth/role_schema.js';
58
+ import { auth_integration_truncate_tables } from '../db.js';
59
+ import { create_test_account_with_credentials, DEFAULT_TEST_PASSWORD } from '../app_server.js';
60
+ /** Output shape for an individual seeded account (keeper or extra). */
61
+ const SeededAccountShape = z.strictObject({
62
+ account: z.strictObject({ id: Uuid, username: z.string() }),
63
+ actor: z.strictObject({ id: Uuid }),
64
+ api_token: z.string(),
65
+ session_cookie: z.string(),
66
+ });
67
+ /**
68
+ * The `_testing_reset` action spec.
69
+ *
70
+ * Input:
71
+ * - `extra_keeper_roles` — roles to grant the fresh keeper *in addition
72
+ * to* `[ROLE_KEEPER, ROLE_ADMIN]` (matching production bootstrap).
73
+ * - `extra_accounts` — additional accounts to seed at this same
74
+ * bootstrap-equivalent step. Each entry's `roles` are direct-granted
75
+ * (bypassing offer/accept) because the seed is *part of bootstrap*,
76
+ * not a post-bootstrap action. Use this for accounts whose required
77
+ * roles aren't admin-grantable via offer/accept (e.g. `ROLE_KEEPER`,
78
+ * whose `RoleSpec.grant_paths` is bootstrap-only). For
79
+ * admin-grantable roles, prefer `fixture.create_account({roles})`
80
+ * (offer/accept production path).
81
+ *
82
+ * Output: keeper credentials plus a parallel array of seeded
83
+ * `extra_accounts` (same order as input). The per-test fixture closes
84
+ * over the returned values; subsequent calls in the same test see the
85
+ * fresh keeper and any requested secondaries.
86
+ *
87
+ * `auth` gates on the daemon-token credential — the keeper holds it
88
+ * exclusively. The action is internally privileged (it runs direct
89
+ * DB writes the production wire never exposes); daemon-token auth is
90
+ * the structural fence.
91
+ */
92
+ export const testing_reset_action_spec = {
93
+ method: '_testing_reset',
94
+ kind: 'request_response',
95
+ initiator: 'frontend',
96
+ auth: { account: 'required', actor: 'none', credential_types: ['daemon_token'] },
97
+ side_effects: true,
98
+ input: z.strictObject({
99
+ extra_keeper_roles: z.array(z.string()).optional(),
100
+ extra_accounts: z
101
+ .array(z.strictObject({
102
+ username: z.string(),
103
+ password_value: z.string().optional(),
104
+ roles: z.array(z.string()),
105
+ }))
106
+ .optional(),
107
+ }),
108
+ output: SeededAccountShape.extend({
109
+ extra_accounts: z.array(SeededAccountShape),
110
+ }),
111
+ async: true,
112
+ description: 'Test-binary only — wipe auth tables, re-bootstrap a fresh keeper (+ optional extras), fire the domain-state reset.',
113
+ };
114
+ /**
115
+ * Build the testing RPC actions for a test binary's registry.
116
+ *
117
+ * Returns `_testing_reset` — the single privileged action test binaries
118
+ * register. The test binary calls this at server-assembly time and
119
+ * registers the result on its dispatcher.
120
+ *
121
+ * The reset action's table-wipe list mirrors
122
+ * `auth_integration_truncate_tables` from `testing/db.ts` — the
123
+ * canonical "auth tables a between-test reset must clear" set.
124
+ * `testing_reset_actions.coverage.test.ts` enforces the set-equality
125
+ * invariant so a future auth migration that adds a table to that list
126
+ * without updating this handler fails CI.
127
+ */
128
+ export const create_testing_actions = (deps, options) => {
129
+ const { session_options, daemon_token_state, reset_state } = options;
130
+ const log = deps.log;
131
+ return [
132
+ rpc_action(testing_reset_action_spec, async (input, ctx) => {
133
+ log.info('[_testing_reset] resetting auth state + re-seeding keeper');
134
+ // 1. Wipe every auth-namespace row. No keeper-preserve filter —
135
+ // the fresh-keeper-per-test contract means mutation-cascade
136
+ // tests (password change, revoke-all) and hardcoded-username
137
+ // signup-uniqueness tests can't leak between cases.
138
+ //
139
+ // `audit_log` has no FK to account so it wipes wholesale.
140
+ // `role_grant_offer` + `invite` likewise (callers don't carry
141
+ // state across resets). For account-FK tables we wipe rows
142
+ // referencing actor/account first to satisfy FK order.
143
+ await ctx.db.query('DELETE FROM audit_log');
144
+ await ctx.db.query('DELETE FROM role_grant_offer');
145
+ await ctx.db.query('DELETE FROM invite');
146
+ await ctx.db.query('DELETE FROM api_token');
147
+ await ctx.db.query('DELETE FROM auth_session');
148
+ await ctx.db.query('DELETE FROM role_grant');
149
+ await ctx.db.query('DELETE FROM actor');
150
+ await ctx.db.query('DELETE FROM account');
151
+ // 2. Reset singleton `app_settings` to production defaults
152
+ // (matches in-process `_build_test_backend` behavior in
153
+ // `app_server.ts`). Tests that flipped `open_signup` mid-run
154
+ // revert.
155
+ await ctx.db.query('UPDATE app_settings SET open_signup = false, updated_at = NULL, updated_by = NULL ' +
156
+ 'WHERE open_signup = true OR updated_at IS NOT NULL');
157
+ // 3. Flip `bootstrap_lock` to its post-bootstrap shape. Production
158
+ // `bootstrap_account` flips this to `true` on success; the
159
+ // in-process `bootstrap_test_keeper` mirrors the flip. We're
160
+ // about to seed the keeper here, so the final state needs to
161
+ // be `bootstrapped = true`. We don't need an intermediate flip
162
+ // to `false` — nothing reads it between our DELETEs and the
163
+ // UPDATE.
164
+ await ctx.db.query('UPDATE bootstrap_lock SET bootstrapped = true WHERE id = 1');
165
+ // 4. Seed the fresh keeper inline. Reuses the same primitive
166
+ // in-process tests use (`create_test_account_with_credentials`)
167
+ // so cross-process and in-process write semantics stay in
168
+ // parity — same hash, same account+actor+role_grants+
169
+ // api_token+session_cookie shape.
170
+ //
171
+ // Roles default to `[ROLE_KEEPER, ROLE_ADMIN]` to match
172
+ // production `bootstrap_account`. `extra_keeper_roles` adds
173
+ // on top.
174
+ const keeper = await create_test_account_with_credentials({
175
+ db: ctx.db,
176
+ keyring: deps.keyring,
177
+ session_options,
178
+ password: deps.password,
179
+ password_value: DEFAULT_TEST_PASSWORD,
180
+ roles: [ROLE_KEEPER, ROLE_ADMIN, ...(input.extra_keeper_roles ?? [])],
181
+ });
182
+ // 5. Seed any caller-requested extras. These are bootstrap-time
183
+ // secondaries — the bypass exists in the same cradle the
184
+ // keeper does, not as a free-form runtime action.
185
+ const extras = [];
186
+ for (const spec of input.extra_accounts ?? []) {
187
+ const seeded = await create_test_account_with_credentials({
188
+ db: ctx.db,
189
+ keyring: deps.keyring,
190
+ session_options,
191
+ password: deps.password,
192
+ username: spec.username,
193
+ password_value: spec.password_value ?? DEFAULT_TEST_PASSWORD,
194
+ roles: spec.roles,
195
+ });
196
+ extras.push(seeded);
197
+ }
198
+ // 6. Refresh the daemon-token cache so subsequent daemon-token
199
+ // requests resolve to the freshly seeded keeper. The
200
+ // middleware's lazy-refresh path only fires when the cached
201
+ // id is null; setting it directly here avoids one round-trip
202
+ // of stale-id-then-refresh on the next call.
203
+ daemon_token_state.keeper_account_id = keeper.account.id;
204
+ // 7. Fire domain-state reset (zzz workspaces/terminals/scratch,
205
+ // or no-op for spine_stub).
206
+ if (reset_state)
207
+ await reset_state();
208
+ return { ...keeper, extra_accounts: extras };
209
+ }),
210
+ ];
211
+ };
212
+ /** Set of auth-namespace tables `_testing_reset` wipes. Mirrored by the coverage test. */
213
+ export const testing_reset_wiped_tables = auth_integration_truncate_tables;
@@ -0,0 +1,5 @@
1
+ import '../assert_dev_env.js';
2
+ import type { TestingServerAdapter } from './testing_server_core.js';
3
+ /** Build the Bun {@link TestingServerAdapter}. */
4
+ export declare const create_bun_testing_adapter: () => TestingServerAdapter;
5
+ //# sourceMappingURL=testing_server_bun.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing_server_bun.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/testing_server_bun.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AA6B9B,OAAO,KAAK,EAAc,oBAAoB,EAAC,MAAM,0BAA0B,CAAC;AAehF,kDAAkD;AAClD,eAAO,MAAM,0BAA0B,QAAO,oBA+B5C,CAAC"}
@@ -0,0 +1,59 @@
1
+ import '../assert_dev_env.js';
2
+ /**
3
+ * Bun runtime adapter for spawnable cross-process test server binaries.
4
+ *
5
+ * Binds `Bun.serve` and `hono/bun`'s module-level `upgradeWebSocket` +
6
+ * `websocket` handler. The shared `testing_server_core.ts` owns the rest.
7
+ * Third sibling to `testing_server_node.ts` / `testing_server_deno.ts` —
8
+ * together the three isolate the JS-runtime axis (Node V8 / Deno V8 / Bun
9
+ * JSC) on identical TS surfaces, and the Rust spine binary covers the
10
+ * cross-language axis.
11
+ *
12
+ * Needs **no extra deps**: `hono/bun` ships with the `hono` peer dep and
13
+ * `Bun.serve` is built in (unlike Node, which pulls `@hono/node-server` +
14
+ * `@hono/node-ws`). `RuntimeDeps` reuse `create_node_runtime` — Bun
15
+ * implements the `node:fs` / `node:process` surface `RuntimeDeps` +
16
+ * `cli/daemon` touch.
17
+ *
18
+ * `Bun.serve` is declared locally (mirroring `testing_server_deno.ts`'s
19
+ * `Deno` declaration) so this module typechecks under fuz_app's Node-based
20
+ * config without `@types/bun`. It is only ever *run* under Bun.
21
+ *
22
+ * @module
23
+ */
24
+ import process from 'node:process';
25
+ import { getConnInfo, upgradeWebSocket, websocket } from 'hono/bun';
26
+ import { create_node_runtime } from '../../runtime/node.js';
27
+ /** Build the Bun {@link TestingServerAdapter}. */
28
+ export const create_bun_testing_adapter = () => ({
29
+ runtime_label: 'Bun',
30
+ runtime: create_node_runtime(),
31
+ get_connection_ip: (c) => getConnInfo(c).remote.address,
32
+ // Bun's WS upgrade is module-level and stateless (like Deno) — no
33
+ // post-serve attach. The `websocket` handler is threaded into `serve`
34
+ // below, where `Bun.serve` wants it.
35
+ prepare_websocket: () => ({ upgrade_websocket: upgradeWebSocket }),
36
+ serve: ({ fetch, port, hostname }) => {
37
+ const server = Bun.serve({
38
+ fetch: fetch,
39
+ port,
40
+ hostname,
41
+ // Harmless for HTTP-only binaries — Bun only invokes it for sockets
42
+ // upgraded via `upgradeWebSocket`.
43
+ websocket,
44
+ });
45
+ const handle = {
46
+ shutdown: async () => {
47
+ await server.stop();
48
+ },
49
+ native: server,
50
+ };
51
+ return handle;
52
+ },
53
+ pid: process.pid,
54
+ register_shutdown_signals: (handler) => {
55
+ process.on('SIGINT', () => void handler());
56
+ process.on('SIGTERM', () => void handler());
57
+ },
58
+ exit: (code) => process.exit(code),
59
+ });
@@ -0,0 +1,140 @@
1
+ import '../assert_dev_env.js';
2
+ /**
3
+ * Runtime-agnostic core for spawnable cross-process **test** server
4
+ * binaries.
5
+ *
6
+ * A test binary mounts a fuz_app-derived surface over a real HTTP socket so
7
+ * the `cross_backend/*` suites (and the cross-impl bench) can drive it the
8
+ * same way they drive the Rust spine. This module owns the runtime-neutral
9
+ * orchestration — stale-daemon check, daemon-info write, serve, post-serve
10
+ * WS attach, graceful drain shutdown — and delegates the runtime-boundary
11
+ * primitives (HTTP serve, WS upgrade construction, signals, pid, exit) to a
12
+ * {@link TestingServerAdapter}. The two shipped adapters are
13
+ * `testing_server_node.ts` (`@hono/node-server` + `@hono/node-ws`) and
14
+ * `testing_server_deno.ts` (`Deno.serve` + `hono/deno`).
15
+ *
16
+ * The app itself — routes, RPC, DB, `_testing_reset`, optional WS mount —
17
+ * is the caller's {@link StartTestingServerOptions.build_app} seam, so this
18
+ * core stays domain-free. fuz_app's own `testing_spine_server` passes a
19
+ * no-domain build; consumers (zzz, fuz_forge) pass their domain build.
20
+ *
21
+ * **NEVER ships in a release.** This module lives under `cross_backend/` and
22
+ * opens with `import '../assert_dev_env.js';`, which throws on
23
+ * production-bundle load. The runtime adapters reach for the optional
24
+ * `@hono/node-server` / `@hono/node-ws` peer deps; only test binaries import
25
+ * them.
26
+ *
27
+ * @module
28
+ */
29
+ import type { Context, Hono } from 'hono';
30
+ import type { UpgradeWebSocket } from 'hono/ws';
31
+ import { type Logger as LoggerType } from '@fuzdev/fuz_util/log.js';
32
+ import type { RuntimeDeps } from '../../runtime/deps.js';
33
+ /**
34
+ * Adapter-built handle to a bound HTTP server.
35
+ *
36
+ * `shutdown` stops accepting new connections and drains in-flight ones.
37
+ * `native` is an adapter-specific server reference — used by Node's
38
+ * `@hono/node-ws` `injectWebSocket(server)` post-serve hook; Deno leaves it
39
+ * unset.
40
+ */
41
+ export interface ServeHandle {
42
+ shutdown: () => Promise<void>;
43
+ /** Adapter-specific server ref for post-serve hooks. Type-erased at the seam. */
44
+ native?: unknown;
45
+ }
46
+ /**
47
+ * Result of an adapter's WS preparation step.
48
+ *
49
+ * `upgrade_websocket` is the Hono `UpgradeWebSocket` closure the caller's
50
+ * WS mount uses to register the endpoint. `attach_to_server` runs after
51
+ * `serve()` returns a {@link ServeHandle} — Node uses it for
52
+ * `injectWebSocket(server)`; Deno leaves it undefined.
53
+ */
54
+ export interface PreparedWebsocket {
55
+ upgrade_websocket: UpgradeWebSocket;
56
+ attach_to_server?: (handle: ServeHandle) => void;
57
+ }
58
+ /**
59
+ * Runtime adapter contract for the test-binary entry. Each adapter
60
+ * (`testing_server_node.ts`, `testing_server_deno.ts`) implements this and
61
+ * hands the shape to {@link start_testing_server}.
62
+ */
63
+ export interface TestingServerAdapter {
64
+ /** Human-readable runtime label for log output (e.g. `"Node"`, `"Deno"`). */
65
+ runtime_label: string;
66
+ /** `RuntimeDeps` capability bundle from `create_node_runtime` / `create_deno_runtime`. */
67
+ runtime: RuntimeDeps;
68
+ /** Extract the raw TCP connection IP from a Hono context. */
69
+ get_connection_ip: (c: Context) => string | undefined;
70
+ /** Build the WS upgrade closure after the caller's `build_app` returns the app. */
71
+ prepare_websocket: (app: Hono) => PreparedWebsocket;
72
+ /** Bind `app.fetch` to `port` on `hostname`; return a {@link ServeHandle}. */
73
+ serve: (options: {
74
+ fetch: Hono['fetch'];
75
+ port: number;
76
+ hostname: string;
77
+ }) => ServeHandle;
78
+ /** Current process pid (for `daemon.json`). */
79
+ pid: number;
80
+ /** Register SIGINT/SIGTERM listeners that invoke `handler` once each. */
81
+ register_shutdown_signals: (handler: () => Promise<void>) => void;
82
+ /** Forceful exit on graceful-shutdown completion or fatal error. */
83
+ exit: (code: number) => never;
84
+ }
85
+ /**
86
+ * The assembled app a {@link StartTestingServerOptions.build_app} seam
87
+ * returns.
88
+ *
89
+ * `mount_websocket` is invoked by the core after the app exists and the
90
+ * adapter prepared the WS upgrade closure — the closure mounts the WS
91
+ * endpoint(s) (e.g. via `register_ws_endpoint`) and wires any
92
+ * audit-revocation guards. Omit it for an HTTP-only binary.
93
+ */
94
+ export interface BuiltTestingApp {
95
+ /** The assembled Hono app (HTTP routes + RPC already mounted). */
96
+ app: Hono;
97
+ /** Tear down backend(s) + DB + any rotation on graceful shutdown. */
98
+ close: () => Promise<void>;
99
+ /** Mount WS endpoint(s) given the runtime-prepared upgrade closure. */
100
+ mount_websocket?: (upgrade_websocket: UpgradeWebSocket) => void;
101
+ }
102
+ /** Options for {@link start_testing_server}. */
103
+ export interface StartTestingServerOptions {
104
+ /** Runtime-boundary adapter (Node or Deno). */
105
+ adapter: TestingServerAdapter;
106
+ /**
107
+ * Daemon-info namespace — the `cli/daemon` key the `daemon.json` is
108
+ * written under (e.g. `'fuz_app_spine'`). The cross-process harness
109
+ * reads the daemon token from the rotation file, not this; `daemon.json`
110
+ * is for stale-process detection + parity with production daemon
111
+ * lifecycle.
112
+ */
113
+ daemon_name: string;
114
+ /** Bind host (e.g. `'localhost'`). */
115
+ host: string;
116
+ /** Bind port. */
117
+ port: number;
118
+ /** App version recorded in `daemon.json`. */
119
+ app_version?: string;
120
+ /**
121
+ * Build the app. Closes over the entry's runtime + connection-IP getter
122
+ * + password deps + resolved config — so this core never touches the
123
+ * domain. Returns the assembled app, a `close` teardown, and an optional
124
+ * `mount_websocket` hook.
125
+ */
126
+ build_app: () => Promise<BuiltTestingApp>;
127
+ /** Optional logger; defaults to a `[daemon_name]`-namespaced `Logger`. */
128
+ log?: LoggerType;
129
+ }
130
+ /**
131
+ * Boot a test-mode server using the supplied runtime adapter.
132
+ *
133
+ * Mirrors a production `start_server` at the surface level — stale-daemon
134
+ * check, daemon-info write, bind, graceful drain — but the app is the
135
+ * caller's no-domain (or domain) {@link StartTestingServerOptions.build_app}
136
+ * and the runtime boundary is the {@link TestingServerAdapter}. Refuses to
137
+ * bind an open host (the test binary must stay on loopback).
138
+ */
139
+ export declare const start_testing_server: (options: StartTestingServerOptions) => Promise<void>;
140
+ //# sourceMappingURL=testing_server_core.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing_server_core.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/testing_server_core.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAC,OAAO,EAAE,IAAI,EAAC,MAAM,MAAM,CAAC;AACxC,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAS,KAAK,MAAM,IAAI,UAAU,EAAC,MAAM,yBAAyB,CAAC;AAG1E,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,uBAAuB,CAAC;AAEvD;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC3B,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,iFAAiF;IACjF,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IACjC,iBAAiB,EAAE,gBAAgB,CAAC;IACpC,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,CAAC;CACjD;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACpC,6EAA6E;IAC7E,aAAa,EAAE,MAAM,CAAC;IACtB,0FAA0F;IAC1F,OAAO,EAAE,WAAW,CAAC;IACrB,6DAA6D;IAC7D,iBAAiB,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,MAAM,GAAG,SAAS,CAAC;IACtD,mFAAmF;IACnF,iBAAiB,EAAE,CAAC,GAAG,EAAE,IAAI,KAAK,iBAAiB,CAAC;IACpD,8EAA8E;IAC9E,KAAK,EAAE,CAAC,OAAO,EAAE;QAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAC,KAAK,WAAW,CAAC;IACxF,+CAA+C;IAC/C,GAAG,EAAE,MAAM,CAAC;IACZ,yEAAyE;IACzE,yBAAyB,EAAE,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;IAClE,oEAAoE;IACpE,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC;CAC9B;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,eAAe;IAC/B,kEAAkE;IAClE,GAAG,EAAE,IAAI,CAAC;IACV,qEAAqE;IACrE,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,uEAAuE;IACvE,eAAe,CAAC,EAAE,CAAC,iBAAiB,EAAE,gBAAgB,KAAK,IAAI,CAAC;CAChE;AAED,gDAAgD;AAChD,MAAM,WAAW,yBAAyB;IACzC,+CAA+C;IAC/C,OAAO,EAAE,oBAAoB,CAAC;IAC9B;;;;;;OAMG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,SAAS,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,CAAC;IAC1C,0EAA0E;IAC1E,GAAG,CAAC,EAAE,UAAU,CAAC;CACjB;AAKD;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,GAAU,SAAS,yBAAyB,KAAG,OAAO,CAAC,IAAI,CA4D3F,CAAC"}