@fuzdev/fuz_app 0.64.0 → 0.66.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 (223) hide show
  1. package/dist/actions/CLAUDE.md +510 -946
  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/actions/broadcast_api.d.ts +1 -1
  6. package/dist/actions/broadcast_api.js +1 -1
  7. package/dist/actions/cancel.d.ts +2 -2
  8. package/dist/actions/cancel.js +3 -3
  9. package/dist/actions/connection_closer.d.ts +1 -4
  10. package/dist/actions/connection_closer.d.ts.map +1 -1
  11. package/dist/actions/connection_closer.js +1 -4
  12. package/dist/actions/register_action_ws.d.ts +2 -2
  13. package/dist/actions/register_ws_endpoint.d.ts +1 -1
  14. package/dist/actions/transports_ws_auth_guard.d.ts +1 -2
  15. package/dist/actions/transports_ws_auth_guard.d.ts.map +1 -1
  16. package/dist/actions/transports_ws_auth_guard.js +1 -2
  17. package/dist/auth/CLAUDE.md +570 -1871
  18. package/dist/auth/account_schema.d.ts +1 -1
  19. package/dist/auth/account_schema.d.ts.map +1 -1
  20. package/dist/auth/api_token_queries.js +1 -1
  21. package/dist/auth/audit_log_ddl.d.ts +1 -1
  22. package/dist/auth/audit_log_ddl.d.ts.map +1 -1
  23. package/dist/auth/audit_log_ddl.js +1 -1
  24. package/dist/auth/audit_log_schema.js +2 -2
  25. package/dist/auth/bootstrap_account.d.ts.map +1 -1
  26. package/dist/auth/bootstrap_account.js +1 -5
  27. package/dist/auth/bootstrap_routes.d.ts +7 -1
  28. package/dist/auth/bootstrap_routes.d.ts.map +1 -1
  29. package/dist/auth/bootstrap_routes.js +15 -11
  30. package/dist/auth/daemon_token_middleware.d.ts +15 -5
  31. package/dist/auth/daemon_token_middleware.d.ts.map +1 -1
  32. package/dist/auth/daemon_token_middleware.js +24 -15
  33. package/dist/auth/invite_queries.d.ts +17 -7
  34. package/dist/auth/invite_queries.d.ts.map +1 -1
  35. package/dist/auth/invite_queries.js +19 -8
  36. package/dist/auth/keyring.d.ts +6 -6
  37. package/dist/auth/keyring.js +8 -8
  38. package/dist/auth/role_grant_offer_actions.d.ts.map +1 -1
  39. package/dist/auth/role_grant_offer_actions.js +4 -2
  40. package/dist/auth/signup_routes.d.ts +47 -1
  41. package/dist/auth/signup_routes.d.ts.map +1 -1
  42. package/dist/auth/signup_routes.js +103 -52
  43. package/dist/db/create_db.d.ts.map +1 -1
  44. package/dist/db/create_db.js +13 -0
  45. package/dist/dev/setup.d.ts +2 -2
  46. package/dist/dev/setup.js +3 -3
  47. package/dist/env/resolve.d.ts +44 -7
  48. package/dist/env/resolve.d.ts.map +1 -1
  49. package/dist/env/resolve.js +94 -27
  50. package/dist/http/CLAUDE.md +243 -522
  51. package/dist/http/error_schemas.d.ts +0 -4
  52. package/dist/http/error_schemas.d.ts.map +1 -1
  53. package/dist/http/error_schemas.js +0 -4
  54. package/dist/http/ip_canonical.d.ts +5 -4
  55. package/dist/http/ip_canonical.d.ts.map +1 -1
  56. package/dist/http/ip_canonical.js +8 -4
  57. package/dist/http/jsonrpc.d.ts +23 -7
  58. package/dist/http/jsonrpc.d.ts.map +1 -1
  59. package/dist/http/jsonrpc.js +19 -3
  60. package/dist/http/origin.d.ts +1 -1
  61. package/dist/http/origin.js +1 -1
  62. package/dist/http/surface.d.ts +9 -2
  63. package/dist/http/surface.d.ts.map +1 -1
  64. package/dist/runtime/mock.d.ts +1 -1
  65. package/dist/runtime/mock.js +2 -2
  66. package/dist/server/app_server.d.ts +41 -10
  67. package/dist/server/app_server.d.ts.map +1 -1
  68. package/dist/server/app_server.js +10 -4
  69. package/dist/server/env.d.ts +7 -7
  70. package/dist/server/env.d.ts.map +1 -1
  71. package/dist/server/env.js +14 -14
  72. package/dist/server/static.d.ts +4 -4
  73. package/dist/server/static.js +7 -7
  74. package/dist/testing/CLAUDE.md +740 -418
  75. package/dist/testing/admin_integration.d.ts +18 -23
  76. package/dist/testing/admin_integration.d.ts.map +1 -1
  77. package/dist/testing/admin_integration.js +230 -216
  78. package/dist/testing/app_server.d.ts +141 -39
  79. package/dist/testing/app_server.d.ts.map +1 -1
  80. package/dist/testing/app_server.js +157 -44
  81. package/dist/testing/audit_completeness.d.ts +25 -22
  82. package/dist/testing/audit_completeness.d.ts.map +1 -1
  83. package/dist/testing/audit_completeness.js +198 -159
  84. package/dist/testing/bootstrap_success.d.ts +28 -0
  85. package/dist/testing/bootstrap_success.d.ts.map +1 -0
  86. package/dist/testing/bootstrap_success.js +144 -0
  87. package/dist/testing/cross_backend/backend_config.d.ts +113 -0
  88. package/dist/testing/cross_backend/backend_config.d.ts.map +1 -0
  89. package/dist/testing/cross_backend/backend_config.js +1 -0
  90. package/dist/testing/cross_backend/bench/bench_report.d.ts +46 -0
  91. package/dist/testing/cross_backend/bench/bench_report.d.ts.map +1 -0
  92. package/dist/testing/cross_backend/bench/bench_report.js +83 -0
  93. package/dist/testing/cross_backend/bench/run_cross_impl_bench.d.ts +44 -0
  94. package/dist/testing/cross_backend/bench/run_cross_impl_bench.d.ts.map +1 -0
  95. package/dist/testing/cross_backend/bench/run_cross_impl_bench.js +38 -0
  96. package/dist/testing/cross_backend/bench/scenario.d.ts +57 -0
  97. package/dist/testing/cross_backend/bench/scenario.d.ts.map +1 -0
  98. package/dist/testing/cross_backend/bench/scenario.js +28 -0
  99. package/dist/testing/cross_backend/bootstrap_backend.d.ts +41 -0
  100. package/dist/testing/cross_backend/bootstrap_backend.d.ts.map +1 -0
  101. package/dist/testing/cross_backend/bootstrap_backend.js +34 -0
  102. package/dist/testing/cross_backend/build_test_backend_paths.d.ts +24 -0
  103. package/dist/testing/cross_backend/build_test_backend_paths.d.ts.map +1 -0
  104. package/dist/testing/cross_backend/build_test_backend_paths.js +33 -0
  105. package/dist/testing/cross_backend/capabilities.d.ts +65 -0
  106. package/dist/testing/cross_backend/capabilities.d.ts.map +1 -0
  107. package/dist/testing/cross_backend/capabilities.js +47 -0
  108. package/dist/testing/cross_backend/default_backend_configs.d.ts +122 -0
  109. package/dist/testing/cross_backend/default_backend_configs.d.ts.map +1 -0
  110. package/dist/testing/cross_backend/default_backend_configs.js +111 -0
  111. package/dist/testing/cross_backend/default_secrets.d.ts +40 -0
  112. package/dist/testing/cross_backend/default_secrets.d.ts.map +1 -0
  113. package/dist/testing/cross_backend/default_secrets.js +39 -0
  114. package/dist/testing/cross_backend/default_spine_surface.d.ts +64 -0
  115. package/dist/testing/cross_backend/default_spine_surface.d.ts.map +1 -0
  116. package/dist/testing/cross_backend/default_spine_surface.js +121 -0
  117. package/dist/testing/cross_backend/setup.d.ts +451 -0
  118. package/dist/testing/cross_backend/setup.d.ts.map +1 -0
  119. package/dist/testing/cross_backend/setup.js +581 -0
  120. package/dist/testing/cross_backend/spawn_backend.d.ts +58 -0
  121. package/dist/testing/cross_backend/spawn_backend.d.ts.map +1 -0
  122. package/dist/testing/cross_backend/spawn_backend.js +229 -0
  123. package/dist/testing/cross_backend/spine_stub_backend_config.d.ts +66 -0
  124. package/dist/testing/cross_backend/spine_stub_backend_config.d.ts.map +1 -0
  125. package/dist/testing/cross_backend/spine_stub_backend_config.js +49 -0
  126. package/dist/testing/cross_backend/sse_round_trip.d.ts +37 -0
  127. package/dist/testing/cross_backend/sse_round_trip.d.ts.map +1 -0
  128. package/dist/testing/cross_backend/sse_round_trip.js +137 -0
  129. package/dist/testing/cross_backend/standard.d.ts +96 -0
  130. package/dist/testing/cross_backend/standard.d.ts.map +1 -0
  131. package/dist/testing/cross_backend/standard.js +49 -0
  132. package/dist/testing/cross_backend/testing_reset_actions.d.ts +171 -0
  133. package/dist/testing/cross_backend/testing_reset_actions.d.ts.map +1 -0
  134. package/dist/testing/cross_backend/testing_reset_actions.js +213 -0
  135. package/dist/testing/cross_backend/testing_server_bun.d.ts +5 -0
  136. package/dist/testing/cross_backend/testing_server_bun.d.ts.map +1 -0
  137. package/dist/testing/cross_backend/testing_server_bun.js +59 -0
  138. package/dist/testing/cross_backend/testing_server_core.d.ts +140 -0
  139. package/dist/testing/cross_backend/testing_server_core.d.ts.map +1 -0
  140. package/dist/testing/cross_backend/testing_server_core.js +68 -0
  141. package/dist/testing/cross_backend/testing_server_deno.d.ts +5 -0
  142. package/dist/testing/cross_backend/testing_server_deno.d.ts.map +1 -0
  143. package/dist/testing/cross_backend/testing_server_deno.js +37 -0
  144. package/dist/testing/cross_backend/testing_server_node.d.ts +5 -0
  145. package/dist/testing/cross_backend/testing_server_node.d.ts.map +1 -0
  146. package/dist/testing/cross_backend/testing_server_node.js +50 -0
  147. package/dist/testing/cross_backend/ts_spine_backend_config.d.ts +72 -0
  148. package/dist/testing/cross_backend/ts_spine_backend_config.d.ts.map +1 -0
  149. package/dist/testing/cross_backend/ts_spine_backend_config.js +112 -0
  150. package/dist/testing/cross_backend/ws_round_trip.d.ts +35 -0
  151. package/dist/testing/cross_backend/ws_round_trip.d.ts.map +1 -0
  152. package/dist/testing/cross_backend/ws_round_trip.js +113 -0
  153. package/dist/testing/data_exposure.d.ts +11 -14
  154. package/dist/testing/data_exposure.d.ts.map +1 -1
  155. package/dist/testing/data_exposure.js +123 -146
  156. package/dist/testing/db_entities.d.ts +22 -1
  157. package/dist/testing/db_entities.d.ts.map +1 -1
  158. package/dist/testing/db_entities.js +24 -1
  159. package/dist/testing/integration.d.ts +56 -21
  160. package/dist/testing/integration.d.ts.map +1 -1
  161. package/dist/testing/integration.js +294 -319
  162. package/dist/testing/integration_helpers.d.ts +16 -6
  163. package/dist/testing/integration_helpers.d.ts.map +1 -1
  164. package/dist/testing/integration_helpers.js +7 -7
  165. package/dist/testing/mock_fs.d.ts.map +1 -1
  166. package/dist/testing/mock_fs.js +0 -2
  167. package/dist/testing/rate_limiting.d.ts.map +1 -1
  168. package/dist/testing/rate_limiting.js +9 -0
  169. package/dist/testing/role_grant_helpers.d.ts +31 -0
  170. package/dist/testing/role_grant_helpers.d.ts.map +1 -0
  171. package/dist/testing/role_grant_helpers.js +46 -0
  172. package/dist/testing/round_trip.d.ts +20 -16
  173. package/dist/testing/round_trip.d.ts.map +1 -1
  174. package/dist/testing/round_trip.js +61 -86
  175. package/dist/testing/rpc_helpers.d.ts +10 -4
  176. package/dist/testing/rpc_helpers.d.ts.map +1 -1
  177. package/dist/testing/rpc_helpers.js +1 -1
  178. package/dist/testing/rpc_round_trip.d.ts +24 -21
  179. package/dist/testing/rpc_round_trip.d.ts.map +1 -1
  180. package/dist/testing/rpc_round_trip.js +87 -104
  181. package/dist/testing/schema_introspect.d.ts +106 -0
  182. package/dist/testing/schema_introspect.d.ts.map +1 -0
  183. package/dist/testing/schema_introspect.js +123 -0
  184. package/dist/testing/schema_parity.d.ts +144 -0
  185. package/dist/testing/schema_parity.d.ts.map +1 -0
  186. package/dist/testing/schema_parity.js +233 -0
  187. package/dist/testing/sse_round_trip.d.ts.map +1 -1
  188. package/dist/testing/sse_round_trip.js +1 -68
  189. package/dist/testing/standard.d.ts +56 -25
  190. package/dist/testing/standard.d.ts.map +1 -1
  191. package/dist/testing/standard.js +62 -5
  192. package/dist/testing/stubs.d.ts +21 -6
  193. package/dist/testing/stubs.d.ts.map +1 -1
  194. package/dist/testing/stubs.js +33 -23
  195. package/dist/testing/testing_rate_limiter.d.ts +59 -0
  196. package/dist/testing/testing_rate_limiter.d.ts.map +1 -0
  197. package/dist/testing/testing_rate_limiter.js +74 -0
  198. package/dist/testing/transports/bootstrap.d.ts +52 -0
  199. package/dist/testing/transports/bootstrap.d.ts.map +1 -0
  200. package/dist/testing/transports/bootstrap.js +70 -0
  201. package/dist/testing/transports/fetch_transport.d.ts +81 -0
  202. package/dist/testing/transports/fetch_transport.d.ts.map +1 -0
  203. package/dist/testing/transports/fetch_transport.js +74 -0
  204. package/dist/testing/transports/sse_frame_reader.d.ts +41 -0
  205. package/dist/testing/transports/sse_frame_reader.d.ts.map +1 -0
  206. package/dist/testing/transports/sse_frame_reader.js +84 -0
  207. package/dist/testing/transports/sse_transport.d.ts +54 -0
  208. package/dist/testing/transports/sse_transport.d.ts.map +1 -0
  209. package/dist/testing/transports/sse_transport.js +51 -0
  210. package/dist/testing/transports/ws_client.d.ts +108 -0
  211. package/dist/testing/transports/ws_client.d.ts.map +1 -0
  212. package/dist/testing/transports/ws_client.js +56 -0
  213. package/dist/testing/transports/ws_transport.d.ts +43 -0
  214. package/dist/testing/transports/ws_transport.d.ts.map +1 -0
  215. package/dist/testing/transports/ws_transport.js +169 -0
  216. package/dist/testing/ws_round_trip.d.ts +21 -103
  217. package/dist/testing/ws_round_trip.d.ts.map +1 -1
  218. package/dist/testing/ws_round_trip.js +42 -40
  219. package/dist/ui/CLAUDE.md +5 -3
  220. package/dist/ui/MenuLink.svelte +16 -16
  221. package/dist/ui/MenuLink.svelte.d.ts +13 -4
  222. package/dist/ui/MenuLink.svelte.d.ts.map +1 -1
  223. package/package.json +10 -4
@@ -0,0 +1,233 @@
1
+ import './assert_dev_env.js';
2
+ /**
3
+ * Structural diff between two snapshots — empty array means parity holds.
4
+ *
5
+ * Order of diffs is deterministic: schema_version first, then tables in
6
+ * sorted order (with column/index/constraint sub-diffs grouped per table),
7
+ * then sequences. Consumers can rely on this for stable diff output.
8
+ */
9
+ export const diff_schema_snapshots = (a, b) => {
10
+ const diffs = [];
11
+ diff_schema_version(a.schema_version, b.schema_version, diffs);
12
+ const all_tables = new Set([...Object.keys(a.tables), ...Object.keys(b.tables)]);
13
+ for (const table of [...all_tables].sort()) {
14
+ const ta = a.tables[table];
15
+ const tb = b.tables[table];
16
+ if (!ta) {
17
+ diffs.push({ kind: 'table_only_in', where: 'b', table });
18
+ continue;
19
+ }
20
+ if (!tb) {
21
+ diffs.push({ kind: 'table_only_in', where: 'a', table });
22
+ continue;
23
+ }
24
+ diff_table(table, ta, tb, diffs);
25
+ }
26
+ const all_sequences = new Set([...Object.keys(a.sequences), ...Object.keys(b.sequences)]);
27
+ for (const sequence of [...all_sequences].sort()) {
28
+ const sa = a.sequences[sequence];
29
+ const sb = b.sequences[sequence];
30
+ if (!sa) {
31
+ diffs.push({ kind: 'sequence_only_in', where: 'b', sequence });
32
+ continue;
33
+ }
34
+ if (!sb) {
35
+ diffs.push({ kind: 'sequence_only_in', where: 'a', sequence });
36
+ continue;
37
+ }
38
+ diff_sequence(sequence, sa, sb, diffs);
39
+ }
40
+ return diffs;
41
+ };
42
+ const diff_schema_version = (a, b, out) => {
43
+ const key = (r) => `${r.namespace}\x00${r.name}`;
44
+ const a_by_key = new Map(a.map((r) => [key(r), r]));
45
+ const b_by_key = new Map(b.map((r) => [key(r), r]));
46
+ const keys = new Set([...a_by_key.keys(), ...b_by_key.keys()]);
47
+ for (const k of [...keys].sort()) {
48
+ const row_a = a_by_key.get(k);
49
+ const row_b = b_by_key.get(k);
50
+ if (!row_a) {
51
+ out.push({ kind: 'schema_version_only_in', where: 'b', row: row_b });
52
+ continue;
53
+ }
54
+ if (!row_b) {
55
+ out.push({ kind: 'schema_version_only_in', where: 'a', row: row_a });
56
+ continue;
57
+ }
58
+ if (row_a.sequence !== row_b.sequence) {
59
+ out.push({
60
+ kind: 'schema_version_sequence_differs',
61
+ namespace: row_a.namespace,
62
+ name: row_a.name,
63
+ a: row_a.sequence,
64
+ b: row_b.sequence,
65
+ });
66
+ }
67
+ }
68
+ };
69
+ const COLUMN_FIELDS = [
70
+ 'data_type',
71
+ 'udt_name',
72
+ 'is_nullable',
73
+ 'column_default',
74
+ 'is_identity',
75
+ ];
76
+ const diff_table = (table, a, b, out) => {
77
+ const all_columns = new Set([...Object.keys(a.columns), ...Object.keys(b.columns)]);
78
+ for (const column of [...all_columns].sort()) {
79
+ const ca = a.columns[column];
80
+ const cb = b.columns[column];
81
+ if (!ca) {
82
+ out.push({ kind: 'column_only_in', where: 'b', table, column });
83
+ continue;
84
+ }
85
+ if (!cb) {
86
+ out.push({ kind: 'column_only_in', where: 'a', table, column });
87
+ continue;
88
+ }
89
+ for (const field of COLUMN_FIELDS) {
90
+ if (ca[field] !== cb[field]) {
91
+ out.push({
92
+ kind: 'column_field_differs',
93
+ table,
94
+ column,
95
+ field,
96
+ a: ca[field],
97
+ b: cb[field],
98
+ });
99
+ }
100
+ }
101
+ }
102
+ const a_indexes = new Map(a.indexes.map((i) => [i.name, i.definition]));
103
+ const b_indexes = new Map(b.indexes.map((i) => [i.name, i.definition]));
104
+ const all_indexes = new Set([...a_indexes.keys(), ...b_indexes.keys()]);
105
+ for (const index of [...all_indexes].sort()) {
106
+ const def_a = a_indexes.get(index);
107
+ const def_b = b_indexes.get(index);
108
+ if (def_a === undefined) {
109
+ out.push({ kind: 'index_only_in', where: 'b', table, index });
110
+ continue;
111
+ }
112
+ if (def_b === undefined) {
113
+ out.push({ kind: 'index_only_in', where: 'a', table, index });
114
+ continue;
115
+ }
116
+ if (def_a !== def_b) {
117
+ out.push({ kind: 'index_definition_differs', table, index, a: def_a, b: def_b });
118
+ }
119
+ }
120
+ const a_constraints = new Map(a.constraints.map((c) => [c.name, c]));
121
+ const b_constraints = new Map(b.constraints.map((c) => [c.name, c]));
122
+ const all_constraints = new Set([...a_constraints.keys(), ...b_constraints.keys()]);
123
+ for (const constraint of [...all_constraints].sort()) {
124
+ const ca = a_constraints.get(constraint);
125
+ const cb = b_constraints.get(constraint);
126
+ if (!ca) {
127
+ out.push({ kind: 'constraint_only_in', where: 'b', table, constraint });
128
+ continue;
129
+ }
130
+ if (!cb) {
131
+ out.push({ kind: 'constraint_only_in', where: 'a', table, constraint });
132
+ continue;
133
+ }
134
+ if (ca.type !== cb.type || ca.definition !== cb.definition) {
135
+ out.push({
136
+ kind: 'constraint_differs',
137
+ table,
138
+ constraint,
139
+ a: { type: ca.type, definition: ca.definition },
140
+ b: { type: cb.type, definition: cb.definition },
141
+ });
142
+ }
143
+ }
144
+ };
145
+ const diff_sequence = (sequence, a, b, out) => {
146
+ if (a.data_type !== b.data_type) {
147
+ out.push({
148
+ kind: 'sequence_data_type_differs',
149
+ sequence,
150
+ a: a.data_type,
151
+ b: b.data_type,
152
+ });
153
+ }
154
+ };
155
+ /**
156
+ * Render a diff list as a human-readable multi-line string. Empty diffs
157
+ * produce an empty string.
158
+ */
159
+ export const format_schema_diffs = (diffs, labels = {}) => {
160
+ if (diffs.length === 0)
161
+ return '';
162
+ const label_a = labels.a ?? 'a';
163
+ const label_b = labels.b ?? 'b';
164
+ const where_label = (where) => (where === 'a' ? label_a : label_b);
165
+ const lines = [];
166
+ for (const d of diffs) {
167
+ switch (d.kind) {
168
+ case 'schema_version_only_in':
169
+ lines.push(` schema_version row only in ${where_label(d.where)}: ${d.row.namespace}/${d.row.name} (sequence ${d.row.sequence})`);
170
+ break;
171
+ case 'schema_version_sequence_differs':
172
+ lines.push(` schema_version sequence differs for ${d.namespace}/${d.name}: ${label_a}=${d.a}, ${label_b}=${d.b}`);
173
+ break;
174
+ case 'table_only_in':
175
+ lines.push(` table ${d.table} only in ${where_label(d.where)}`);
176
+ break;
177
+ case 'column_only_in':
178
+ lines.push(` ${d.table}.${d.column} only in ${where_label(d.where)}`);
179
+ break;
180
+ case 'column_field_differs':
181
+ lines.push(` ${d.table}.${d.column} ${d.field} differs: ${label_a}=${JSON.stringify(d.a)}, ${label_b}=${JSON.stringify(d.b)}`);
182
+ break;
183
+ case 'index_only_in':
184
+ lines.push(` index ${d.index} on ${d.table} only in ${where_label(d.where)}`);
185
+ break;
186
+ case 'index_definition_differs':
187
+ lines.push(` index ${d.index} on ${d.table} differs:\n ${label_a}: ${d.a}\n ${label_b}: ${d.b}`);
188
+ break;
189
+ case 'constraint_only_in':
190
+ lines.push(` constraint ${d.constraint} on ${d.table} only in ${where_label(d.where)}`);
191
+ break;
192
+ case 'constraint_differs':
193
+ lines.push(` constraint ${d.constraint} on ${d.table} differs:\n ${label_a}: ${d.a.type} ${d.a.definition}\n ${label_b}: ${d.b.type} ${d.b.definition}`);
194
+ break;
195
+ case 'sequence_only_in':
196
+ lines.push(` sequence ${d.sequence} only in ${where_label(d.where)}`);
197
+ break;
198
+ case 'sequence_data_type_differs':
199
+ lines.push(` sequence ${d.sequence} data_type differs: ${label_a}=${d.a}, ${label_b}=${d.b}`);
200
+ break;
201
+ default:
202
+ // Compile-time exhaustiveness — a new SchemaDiff variant without a
203
+ // case here makes `d` non-never and fails type-check.
204
+ d;
205
+ break;
206
+ }
207
+ }
208
+ return lines.join('\n');
209
+ };
210
+ /**
211
+ * Throw if the two snapshots disagree. The error message names the impls
212
+ * (via `labels`) and lists every diff, so the failure is self-diagnosing.
213
+ *
214
+ * Consumers wire this after bootstrapping each impl against an isolated DB:
215
+ *
216
+ * ```ts
217
+ * await drop_recreate_db('zzz_test');
218
+ * await spawn_backend(deno_config);
219
+ * const snapshot_deno = await query_schema_snapshot(db, {});
220
+ * await drop_recreate_db('zzz_test');
221
+ * await spawn_backend(rust_config);
222
+ * const snapshot_rust = await query_schema_snapshot(db, {});
223
+ * assert_schema_snapshots_equal(snapshot_deno, snapshot_rust, {a: 'deno', b: 'rust'});
224
+ * ```
225
+ */
226
+ export const assert_schema_snapshots_equal = (a, b, labels = {}) => {
227
+ const diffs = diff_schema_snapshots(a, b);
228
+ if (diffs.length === 0)
229
+ return;
230
+ const label_a = labels.a ?? 'a';
231
+ const label_b = labels.b ?? 'b';
232
+ throw new Error(`Schema parity failed: ${diffs.length} diff(s) between ${label_a} and ${label_b}\n${format_schema_diffs(diffs, labels)}`);
233
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"sse_round_trip.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/sse_round_trip.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAmB7B,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAwB,KAAK,SAAS,EAAuB,MAAM,oBAAoB,CAAC;AAE/F,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,6BAA6B,CAAC;AAG/D,OAAO,EAEN,KAAK,eAAe,EACpB,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAwB,KAAK,SAAS,EAAC,MAAM,SAAS,CAAC;AAE9D,OAAO,EAIN,KAAK,uBAAuB,EAC5B,MAAM,kBAAkB,CAAC;AAM1B,gDAAgD;AAChD,MAAM,WAAW,gBAAgB;IAChC,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,OAAO,EAAE,CAAC,GAAG,EAAE;QAAC,QAAQ,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,WAAW,CAAA;KAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E;;;OAGG;IACH,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAC/B;;;;OAIG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,8CAA8C;AAC9C,MAAM,WAAW,mBAAmB;IACnC,4CAA4C;IAC5C,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,qDAAqD;IACrD,kBAAkB,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IAChE,iDAAiD;IACjD,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,qEAAqE;IACrE,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAChC;;;;;OAKG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAChD;;;;;;;;;;;;OAYG;IACH,aAAa,EAAE,uBAAuB,CAAC;IACvC,8BAA8B;IAC9B,MAAM,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC;CAChC;AAyHD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,wBAAwB,GAAI,SAAS,mBAAmB,KAAG,IAgIvE,CAAC"}
1
+ {"version":3,"file":"sse_round_trip.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/sse_round_trip.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAmB7B,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAwB,KAAK,SAAS,EAAuB,MAAM,oBAAoB,CAAC;AAE/F,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,6BAA6B,CAAC;AAG/D,OAAO,EAEN,KAAK,eAAe,EACpB,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAwB,KAAK,SAAS,EAAC,MAAM,SAAS,CAAC;AAE9D,OAAO,EAIN,KAAK,uBAAuB,EAC5B,MAAM,kBAAkB,CAAC;AAO1B,gDAAgD;AAChD,MAAM,WAAW,gBAAgB;IAChC,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,OAAO,EAAE,CAAC,GAAG,EAAE;QAAC,QAAQ,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,WAAW,CAAA;KAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E;;;OAGG;IACH,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAC/B;;;;OAIG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,8CAA8C;AAC9C,MAAM,WAAW,mBAAmB;IACnC,4CAA4C;IAC5C,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,qDAAqD;IACrD,kBAAkB,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IAChE,iDAAiD;IACjD,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,qEAAqE;IACrE,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAChC;;;;;OAKG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAChD;;;;;;;;;;;;OAYG;IACH,aAAa,EAAE,uBAAuB,CAAC;IACvC,8BAA8B;IAC9B,MAAM,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC;CAChC;AA+CD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,wBAAwB,GAAI,SAAS,mBAAmB,KAAG,IAgIvE,CAAC"}
@@ -24,74 +24,7 @@ import { rpc_call, require_rpc_endpoint_path, resolve_rpc_endpoints_for_setup, }
24
24
  import { run_migrations } from '../db/migrate.js';
25
25
  import { auth_migration_ns } from '../auth/migrations.js';
26
26
  import { account_session_revoke_all_action_spec } from '../auth/account_action_specs.js';
27
- /**
28
- * Read one complete SSE frame (up to `\n\n`) from a stream reader.
29
- *
30
- * Returns the frame without the trailing `\n\n`. Throws on premature close.
31
- * Preserves any bytes past the terminator in the shared buffer for the next call.
32
- */
33
- const create_sse_frame_reader = (reader) => {
34
- const decoder = new TextDecoder();
35
- let buffer = '';
36
- let closed = false;
37
- const pump_once = async (timeout_ms) => {
38
- // Race the read against a timeout — vitest will otherwise hang on a misbehaving stream.
39
- const timeout = new Promise((resolve) => {
40
- setTimeout(() => resolve({ done: true, value: undefined, timed_out: true }), timeout_ms);
41
- });
42
- const result = (await Promise.race([reader.read(), timeout]));
43
- if ('timed_out' in result) {
44
- throw new Error(`SSE read timed out after ${timeout_ms}ms`);
45
- }
46
- if (result.done) {
47
- closed = true;
48
- return false;
49
- }
50
- buffer += decoder.decode(result.value, { stream: true });
51
- return true;
52
- };
53
- return {
54
- read_frame: async (timeout_ms = 2000) => {
55
- // SSE frames end with a blank line — the canonical terminator is `\n\n`.
56
- while (true) {
57
- const idx = buffer.indexOf('\n\n');
58
- if (idx >= 0) {
59
- const frame = buffer.slice(0, idx);
60
- buffer = buffer.slice(idx + 2);
61
- return frame;
62
- }
63
- const cont = await pump_once(timeout_ms);
64
- if (!cont)
65
- throw new Error('SSE stream ended before a frame was received');
66
- }
67
- },
68
- wait_for_close: async (timeout_ms) => {
69
- // Drain until the server closes the stream (pump_once returns false) or timeout expires.
70
- const deadline = Date.now() + timeout_ms;
71
- for (;;) {
72
- if (closed)
73
- return true;
74
- const remaining = deadline - Date.now();
75
- if (remaining <= 0)
76
- return false;
77
- try {
78
- await pump_once(Math.min(remaining, timeout_ms));
79
- }
80
- catch {
81
- return false;
82
- }
83
- }
84
- },
85
- cancel: async () => {
86
- try {
87
- await reader.cancel();
88
- }
89
- catch {
90
- // already closed
91
- }
92
- },
93
- };
94
- };
27
+ import { create_sse_frame_reader } from './transports/sse_frame_reader.js';
95
28
  /**
96
29
  * Validate a decoded SSE `data:` frame as a JSON-RPC-style `{method, params}` payload.
97
30
  */
@@ -2,59 +2,90 @@ import './assert_dev_env.js';
2
2
  /**
3
3
  * Combined standard test suite helper.
4
4
  *
5
- * Convenience wrapper that runs both `describe_standard_integration_tests`
6
- * and `describe_standard_admin_integration_tests` in a single call.
7
- * Existing per-suite calls keep working — this is purely additive.
5
+ * Bundles every DB-backed suite carrying the standard option shape, each
6
+ * gated on its relevant config — silent-skip when the gate isn't met
7
+ * (same precedent as `describe_standard_admin_integration_tests` skipping
8
+ * when `roles` isn't provided). Consumers wire the standard surface in
9
+ * one call instead of seven; forgetting a suite no longer silently loses
10
+ * coverage.
11
+ *
12
+ * Attack surface suites stay separate — their option shape is
13
+ * `{build, snapshot_path, expected_public_routes, ...}` rather than
14
+ * `{setup_test, surface_source, capabilities}`. A peer bundler lives
15
+ * for that side if/when needed.
8
16
  *
9
17
  * @module
10
18
  */
11
19
  import type { SessionOptions } from '../auth/session_cookie.js';
12
- import type { AppServerContext, AppServerOptions } from '../server/app_server.js';
13
- import type { RouteSpec } from '../http/route_spec.js';
14
20
  import type { RoleSchemaResult } from '../auth/role_schema.js';
15
- import type { DbFactory } from './db.js';
21
+ import type { AppServerContext, BootstrapServerOptions } from '../server/app_server.js';
22
+ import type { RouteSpec } from '../http/route_spec.js';
16
23
  import type { RpcEndpointsSuiteOption } from './rpc_helpers.js';
24
+ import type { BackendCapabilities } from './cross_backend/capabilities.js';
25
+ import type { SetupTest } from './cross_backend/setup.js';
26
+ import type { AppSurfaceSpec } from '../http/surface.js';
27
+ import type { SuiteAppOptions } from './app_server.js';
17
28
  /**
18
29
  * Configuration for `describe_standard_tests`.
19
30
  */
20
31
  export interface StandardTestOptions {
21
- /** Session config for cookie-based auth. */
22
- session_options: SessionOptions<string>;
23
- /** Route spec factory — same one used in production. */
24
- create_route_specs: (ctx: AppServerContext) => Array<RouteSpec>;
25
- /** Optional overrides for `AppServerOptions`. */
26
- app_options?: Partial<Omit<AppServerOptions, 'backend' | 'session_options' | 'create_route_specs'>>;
32
+ /** Per-test fixture-producing function. */
33
+ setup_test: SetupTest;
27
34
  /**
28
- * Database factories to run tests against. Default: pglite only.
35
+ * App surface. Constructed in TS by the consumer; same shape for
36
+ * in-process and cross-process tests.
29
37
  */
30
- db_factories?: Array<DbFactory>;
38
+ surface_source: AppSurfaceSpec;
39
+ /** Backend capability declarations. */
40
+ capabilities: BackendCapabilities;
41
+ /** Session config — needed for cookie_name + factory-form rpc_endpoints resolution. */
42
+ session_options: SessionOptions<string>;
31
43
  /**
32
- * Role schema result from `create_role_schema()`.
33
- * When provided, admin integration tests are included.
44
+ * Route spec factory same one used in production. Required by
45
+ * `describe_rate_limiting_tests`, which builds a fresh `TestApp` per test
46
+ * (bypasses the shared `setup_test` fixture) so it can pass tight
47
+ * per-test rate-limiter overrides.
34
48
  */
35
- roles?: RoleSchemaResult;
49
+ create_route_specs: (ctx: AppServerContext) => Array<RouteSpec>;
36
50
  /**
37
51
  * RPC endpoint specs — required. The standard integration tests drive
38
52
  * `account_verify`, `account_session_*`, `account_token_*` through the
39
53
  * RPC surface (and admin tests, when wired, drive role_grant grant/revoke
40
54
  * through it too).
41
- *
42
- * Accepts either an array (eager) or a factory
43
- * `(ctx: AppServerContext) => Array<RpcEndpointSpec>`. Round-tripped
44
- * to both sub-suites unchanged — see their docstrings for the full
45
- * factory-form contract.
46
55
  */
47
56
  rpc_endpoints: RpcEndpointsSuiteOption;
57
+ /**
58
+ * Role schema result from `create_role_schema()`.
59
+ * When provided, admin integration + audit completeness suites are included.
60
+ */
61
+ roles?: RoleSchemaResult;
62
+ /**
63
+ * Bootstrap config — when set to `mode: 'live'`, the bootstrap success
64
+ * suite runs against `create_test_app_for_bootstrap`. Other modes
65
+ * (`'disabled'` / `'surface_only'` / omission) silent-skip the suite.
66
+ */
67
+ bootstrap?: BootstrapServerOptions;
68
+ /** Optional overrides forwarded to `describe_rate_limiting_tests`. */
69
+ rate_limiting_app_options?: SuiteAppOptions;
48
70
  /**
49
71
  * Path prefix where admin routes are mounted.
50
72
  * Default `'/api/admin'`.
51
73
  */
52
74
  admin_prefix?: string;
75
+ /**
76
+ * Forwarded to `describe_standard_integration_tests` — overrides the
77
+ * default error-coverage threshold on the scoped REST surface. Set to
78
+ * `0` to skip the assertion entirely.
79
+ */
80
+ error_coverage_min?: number;
81
+ /** Override the bootstrap-success suite's synthetic token. */
82
+ bootstrap_token?: string;
53
83
  }
54
84
  /**
55
- * Run both standard integration and admin integration test suites.
56
- *
57
- * Admin tests are only included when `roles` is provided.
85
+ * Run the full standard test bundle integration, admin (when `roles`
86
+ * provided), audit completeness (when `roles` provided), bootstrap
87
+ * success (when `bootstrap.mode === 'live'`), round trip, RPC round
88
+ * trip, data exposure, rate limiting.
58
89
  */
59
90
  export declare const describe_standard_tests: (options: StandardTestOptions) => void;
60
91
  //# sourceMappingURL=standard.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"standard.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/standard.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAE7B;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAC,gBAAgB,EAAE,gBAAgB,EAAC,MAAM,yBAAyB,CAAC;AAChF,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,SAAS,CAAC;AAGvC,OAAO,KAAK,EAAC,uBAAuB,EAAC,MAAM,kBAAkB,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,mBAAmB;IACnC,4CAA4C;IAC5C,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,wDAAwD;IACxD,kBAAkB,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IAChE,iDAAiD;IACjD,WAAW,CAAC,EAAE,OAAO,CACpB,IAAI,CAAC,gBAAgB,EAAE,SAAS,GAAG,iBAAiB,GAAG,oBAAoB,CAAC,CAC5E,CAAC;IACF;;OAEG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAChC;;;OAGG;IACH,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB;;;;;;;;;;OAUG;IACH,aAAa,EAAE,uBAAuB,CAAC;IACvC;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,GAAI,SAAS,mBAAmB,KAAG,IAStE,CAAC"}
1
+ {"version":3,"file":"standard.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/standard.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAE7B;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAC,gBAAgB,EAAE,sBAAsB,EAAC,MAAM,yBAAyB,CAAC;AACtF,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAC;AASrD,OAAO,KAAK,EAAC,uBAAuB,EAAC,MAAM,kBAAkB,CAAC;AAC9D,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,iCAAiC,CAAC;AACzE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,0BAA0B,CAAC;AACxD,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,iBAAiB,CAAC;AAErD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IACnC,2CAA2C;IAC3C,UAAU,EAAE,SAAS,CAAC;IACtB;;;OAGG;IACH,cAAc,EAAE,cAAc,CAAC;IAC/B,uCAAuC;IACvC,YAAY,EAAE,mBAAmB,CAAC;IAClC,uFAAuF;IACvF,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC;;;;;OAKG;IACH,kBAAkB,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IAChE;;;;;OAKG;IACH,aAAa,EAAE,uBAAuB,CAAC;IACvC;;;OAGG;IACH,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB;;;;OAIG;IACH,SAAS,CAAC,EAAE,sBAAsB,CAAC;IACnC,sEAAsE;IACtE,yBAAyB,CAAC,EAAE,eAAe,CAAC;IAC5C;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,8DAA8D;IAC9D,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GAAI,SAAS,mBAAmB,KAAG,IA2DtE,CAAC"}
@@ -1,18 +1,75 @@
1
1
  import './assert_dev_env.js';
2
2
  import { describe_standard_integration_tests } from './integration.js';
3
3
  import { describe_standard_admin_integration_tests } from './admin_integration.js';
4
+ import { describe_round_trip_validation } from './round_trip.js';
5
+ import { describe_data_exposure_tests } from './data_exposure.js';
6
+ import { describe_rpc_round_trip_tests } from './rpc_round_trip.js';
7
+ import { describe_audit_completeness_tests } from './audit_completeness.js';
8
+ import { describe_rate_limiting_tests } from './rate_limiting.js';
9
+ import { describe_bootstrap_success_tests } from './bootstrap_success.js';
4
10
  /**
5
- * Run both standard integration and admin integration test suites.
6
- *
7
- * Admin tests are only included when `roles` is provided.
11
+ * Run the full standard test bundle integration, admin (when `roles`
12
+ * provided), audit completeness (when `roles` provided), bootstrap
13
+ * success (when `bootstrap.mode === 'live'`), round trip, RPC round
14
+ * trip, data exposure, rate limiting.
8
15
  */
9
16
  export const describe_standard_tests = (options) => {
10
- describe_standard_integration_tests(options);
17
+ describe_standard_integration_tests({
18
+ setup_test: options.setup_test,
19
+ surface_source: options.surface_source,
20
+ capabilities: options.capabilities,
21
+ session_options: options.session_options,
22
+ rpc_endpoints: options.rpc_endpoints,
23
+ error_coverage_min: options.error_coverage_min,
24
+ });
25
+ describe_round_trip_validation({
26
+ setup_test: options.setup_test,
27
+ surface_source: options.surface_source,
28
+ capabilities: options.capabilities,
29
+ });
30
+ describe_rpc_round_trip_tests({
31
+ setup_test: options.setup_test,
32
+ surface_source: options.surface_source,
33
+ capabilities: options.capabilities,
34
+ session_options: options.session_options,
35
+ rpc_endpoints: options.rpc_endpoints,
36
+ });
37
+ describe_data_exposure_tests({
38
+ setup_test: options.setup_test,
39
+ surface_source: options.surface_source,
40
+ capabilities: options.capabilities,
41
+ });
42
+ describe_rate_limiting_tests({
43
+ session_options: options.session_options,
44
+ create_route_specs: options.create_route_specs,
45
+ rpc_endpoints: options.rpc_endpoints,
46
+ app_options: options.rate_limiting_app_options,
47
+ });
11
48
  if (options.roles) {
12
49
  describe_standard_admin_integration_tests({
13
- ...options,
50
+ setup_test: options.setup_test,
51
+ surface_source: options.surface_source,
52
+ capabilities: options.capabilities,
53
+ session_options: options.session_options,
14
54
  roles: options.roles,
15
55
  rpc_endpoints: options.rpc_endpoints,
56
+ admin_prefix: options.admin_prefix,
57
+ });
58
+ describe_audit_completeness_tests({
59
+ setup_test: options.setup_test,
60
+ surface_source: options.surface_source,
61
+ capabilities: options.capabilities,
62
+ session_options: options.session_options,
63
+ rpc_endpoints: options.rpc_endpoints,
64
+ });
65
+ }
66
+ if (options.bootstrap?.mode === 'live') {
67
+ describe_bootstrap_success_tests({
68
+ session_options: options.session_options,
69
+ create_route_specs: options.create_route_specs,
70
+ rpc_endpoints: options.rpc_endpoints,
71
+ bootstrap: options.bootstrap,
72
+ bootstrap_token: options.bootstrap_token,
16
73
  });
17
74
  }
18
75
  };
@@ -4,7 +4,7 @@ import type { SessionOptions } from '../auth/session_cookie.js';
4
4
  import type { MiddlewareSpec } from '../http/middleware_spec.js';
5
5
  import type { AppDeps } from '../auth/deps.js';
6
6
  import type { AuditEmitter } from '../auth/audit_emitter.js';
7
- import type { AppServerContext } from '../server/app_server.js';
7
+ import type { AppServerContext, BootstrapServerOptions } from '../server/app_server.js';
8
8
  import { Db } from '../db/db.js';
9
9
  import { type RouteSpec } from '../http/route_spec.js';
10
10
  import { type AppSurfaceSpec, type RpcEndpointSpec } from '../http/surface.js';
@@ -127,13 +127,28 @@ export interface CreateTestAppSurfaceSpecOptions {
127
127
  * only, never mounts.
128
128
  */
129
129
  ws_endpoints?: ReadonlyArray<WsEndpointSpec> | ((ctx: AppServerContext) => ReadonlyArray<WsEndpointSpec>);
130
- /** Transform middleware array (e.g., tx's `extend_middleware_for_tx_binary`). */
130
+ /** Transform middleware array (e.g., zap's `extend_middleware_for_zap_binary`). */
131
131
  transform_middleware?: (specs: Array<MiddlewareSpec>) => Array<MiddlewareSpec>;
132
- /** Bootstrap route prefix (default: `'/api/account'`). */
133
- bootstrap_route_prefix?: string;
132
+ /**
133
+ * Bootstrap config — symmetric with `AppServerOptions.bootstrap`. Discriminated
134
+ * by `mode`: `'disabled'` skips the route (same as omission), `'surface_only'`
135
+ * mounts the route shape, `'live'` accepts a `token_path` for production
136
+ * symmetry (surface assembly only uses it for shape symmetry; the value is a
137
+ * live-execution concern handled by `create_test_app` → `create_app_server`).
138
+ *
139
+ * Surface assembly only reads `route_prefix` (default `'/api/account'`).
140
+ */
141
+ bootstrap?: BootstrapServerOptions;
134
142
  }
135
143
  /**
136
- * Create an `AppSurfaceSpec` for attack surface testing.
144
+ * Create an `AppSurfaceSpec` for the standard testing suites.
145
+ *
146
+ * Used by both in-process and cross-process tests as the schema source —
147
+ * the cross-process-ness lives in the transport + per-test fixture, not
148
+ * here. The on-disk `*_attack_surface.json` snapshot is observability
149
+ * (gen-time drift detection via `assert_surface_matches_snapshot`); the
150
+ * suites consume the spec object this function returns, not the JSON
151
+ * file.
137
152
  *
138
153
  * Mirrors `create_app_server`'s route assembly: consumer routes +
139
154
  * factory-managed bootstrap routes + surface generation. If
@@ -141,7 +156,7 @@ export interface CreateTestAppSurfaceSpecOptions {
141
156
  * to stay in sync (single source of truth for all consumers).
142
157
  *
143
158
  * @param options - surface spec options
144
- * @returns the surface spec for snapshot and adversarial testing
159
+ * @returns the surface spec for the standard suites
145
160
  */
146
161
  export declare const create_test_app_surface_spec: (options: CreateTestAppSurfaceSpecOptions) => AppSurfaceSpec;
147
162
  //# sourceMappingURL=stubs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"stubs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/stubs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"stubs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/stubs.ts"],"names":[],"mappings":"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"}