@fuzdev/fuz_app 0.82.0 → 0.84.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.
- package/dist/auth/account_queries.d.ts.map +1 -1
- package/dist/auth/account_queries.js +19 -9
- package/dist/auth/migrations.d.ts +21 -18
- package/dist/auth/migrations.d.ts.map +1 -1
- package/dist/auth/migrations.js +22 -19
- package/dist/db/CLAUDE.md +6 -0
- package/dist/db/schema_ready.d.ts +83 -0
- package/dist/db/schema_ready.d.ts.map +1 -0
- package/dist/db/schema_ready.js +103 -0
- package/dist/http/CLAUDE.md +3 -2
- package/dist/http/common_routes.d.ts +49 -0
- package/dist/http/common_routes.d.ts.map +1 -1
- package/dist/http/common_routes.js +92 -0
- package/dist/testing/CLAUDE.md +35 -6
- package/dist/testing/cross_backend/backend_config.d.ts +2 -2
- package/dist/testing/cross_backend/capabilities.d.ts +10 -0
- package/dist/testing/cross_backend/capabilities.d.ts.map +1 -1
- package/dist/testing/cross_backend/capabilities.js +1 -0
- package/dist/testing/cross_backend/default_backend_configs.d.ts.map +1 -1
- package/dist/testing/cross_backend/default_backend_configs.js +6 -0
- package/dist/testing/cross_backend/default_spine_surface.d.ts +48 -0
- package/dist/testing/cross_backend/default_spine_surface.d.ts.map +1 -1
- package/dist/testing/cross_backend/default_spine_surface.js +24 -24
- package/dist/testing/cross_backend/expected_schema.json +113 -0
- package/dist/testing/cross_backend/ready.d.ts +14 -0
- package/dist/testing/cross_backend/ready.d.ts.map +1 -0
- package/dist/testing/cross_backend/ready.js +50 -0
- package/dist/testing/cross_backend/rust_spine_stub_backend_config.d.ts +39 -0
- package/dist/testing/cross_backend/rust_spine_stub_backend_config.d.ts.map +1 -0
- package/dist/testing/cross_backend/rust_spine_stub_backend_config.js +103 -0
- package/dist/testing/cross_backend/ts_spine_backend_config.d.ts +1 -1
- package/dist/testing/cross_backend/ts_spine_backend_config.d.ts.map +1 -1
- package/dist/testing/cross_backend/ts_spine_backend_config.js +6 -2
- package/dist/testing/schema_ready_fixture.d.ts +46 -0
- package/dist/testing/schema_ready_fixture.d.ts.map +1 -0
- package/dist/testing/schema_ready_fixture.js +48 -0
- package/package.json +22 -15
- package/dist/testing/cross_backend/spine_stub_backend_config.d.ts +0 -66
- package/dist/testing/cross_backend/spine_stub_backend_config.d.ts.map +0 -1
- package/dist/testing/cross_backend/spine_stub_backend_config.js +0 -53
package/dist/testing/CLAUDE.md
CHANGED
|
@@ -853,7 +853,8 @@ source of truth for wire-shape conformance.
|
|
|
853
853
|
|
|
854
854
|
- `testing/cross_backend/capabilities.ts` — `BackendCapabilities` vocabulary
|
|
855
855
|
(`bearer_auth` / `trusted_proxy` / `login_rate_limit` / `ws` / `sse` /
|
|
856
|
-
`cell_crud` / `cell_relations` / `account_lifecycle` / `fact_serving`
|
|
856
|
+
`cell_crud` / `cell_relations` / `account_lifecycle` / `fact_serving` /
|
|
857
|
+
`ready`),
|
|
857
858
|
`test_if(cond, name, fn)`
|
|
858
859
|
for capability-gated cases, and `in_process_capabilities` preset. `cell_crud`
|
|
859
860
|
gates the CRUD parity suite, `cell_relations` the relation / ACL / audit
|
|
@@ -866,7 +867,10 @@ source of truth for wire-shape conformance.
|
|
|
866
867
|
gates `describe_fact_serving_cross_tests` (the cell-scoped per-reference +
|
|
867
868
|
admin-only bare-hash fact-serving parity suite); like cells it stays off the
|
|
868
869
|
declared surface and is `true` on every spine that mounts the serve routes +
|
|
869
|
-
the `_testing_put_fact` seeder.
|
|
870
|
+
the `_testing_put_fact` seeder. `ready` gates `describe_ready_cross_tests`
|
|
871
|
+
(anonymous `GET /ready` → `200 {ready: true}` on a clean spine bootstrap);
|
|
872
|
+
like cells/sse the `/ready` deploy gate stays off the declared surface, `true`
|
|
873
|
+
on every spine that live-mounts it over the shared `expected_schema.json`.
|
|
870
874
|
|
|
871
875
|
### `cross_backend/standard.ts` — `describe_standard_cross_process_tests`
|
|
872
876
|
|
|
@@ -1071,8 +1075,8 @@ in-process legs (plain `gro test`) are `src/test/auth/cell_crud_parity.db.test.t
|
|
|
1071
1075
|
- `testing/cross_backend/backend_config.ts` — `BackendConfig` +
|
|
1072
1076
|
`BackendBootstrapConfig` interfaces. Consumer factories
|
|
1073
1077
|
(`deno_backend_config()`, `rust_backend_config()`,
|
|
1074
|
-
`
|
|
1075
|
-
`
|
|
1078
|
+
`rust_spine_stub_backend_config()`) produce these; fuz_app ships
|
|
1079
|
+
`rust_spine_stub_backend_config()` as a convenience preset for the non-domain
|
|
1076
1080
|
third spine consumer, but otherwise backend-specific paths and env are a
|
|
1077
1081
|
consumer concern.
|
|
1078
1082
|
- `testing/cross_backend/spawn_backend.ts` — `spawn_backend(config) => BackendHandle`.
|
|
@@ -1180,6 +1184,31 @@ in-process `auth/origin_parity.db.test.ts` + the cross-process
|
|
|
1180
1184
|
Rust spine returned a plain-text body — now converged to the canonical TS
|
|
1181
1185
|
`{error: "forbidden_origin"}` via `fuz_http::forbidden_origin_response()`.
|
|
1182
1186
|
|
|
1187
|
+
### Readiness probe parity — `cross_backend/ready.ts`
|
|
1188
|
+
|
|
1189
|
+
`describe_ready_cross_tests({setup_test, capabilities, ready_path?})` — the
|
|
1190
|
+
imperative `/ready` deploy-gate suite: an anonymous, cookie-jar-free,
|
|
1191
|
+
no-Origin `GET /ready` → `200 {ready: true}` on a clean spine bootstrap (the
|
|
1192
|
+
deploy-poll shape a gate like zap uses). The `/ready` mechanism + its
|
|
1193
|
+
drift → `503` path are per-impl unit tests already (TS `db/schema_ready.ts`,
|
|
1194
|
+
Rust `fuz_db::schema_ready` / `fuz_http::ready`); this is the cross-impl
|
|
1195
|
+
success-path gate. Gated on `capabilities.ready`. Imperative (not a
|
|
1196
|
+
`conformance_table` row) because `/ready` is a public flat-REST route, not a
|
|
1197
|
+
JSON-RPC envelope, and the probe needs `fresh_transport({origin: null})` —
|
|
1198
|
+
the same reasons the sibling `cross_backend/origin.ts` suite is imperative.
|
|
1199
|
+
`$lib`-free; runs both legs (`cross_backend/ready_parity.db.test.ts` +
|
|
1200
|
+
`cross_backend/ready.cross.test.ts`).
|
|
1201
|
+
|
|
1202
|
+
Both backends read the **same** committed
|
|
1203
|
+
`testing/cross_backend/expected_schema.json` (column-presence is engine-portable,
|
|
1204
|
+
so one fixture is the cross-impl contract): the TS spine via
|
|
1205
|
+
`create_spine_ready_route_spec` (an `import.meta.url` URL off `default_spine_surface.ts`),
|
|
1206
|
+
the Rust `testing_spine_stub` via the absolute path `rust_spine_stub_backend_config`
|
|
1207
|
+
passes through `FUZ_RUST_SPINE_STUB_EXPECTED_SCHEMA_PATH`. The fixture covers the full
|
|
1208
|
+
spine bootstrap (auth + cell + cell_history + fact) and is regenerated +
|
|
1209
|
+
drift-guarded by `src/test/cross_backend/spine_expected_schema.db.test.ts`
|
|
1210
|
+
(`UPDATE_SCHEMA_READY=1`, then `gro format`).
|
|
1211
|
+
|
|
1183
1212
|
### Building a TS test-server binary — `testing_server_core.ts` + adapters
|
|
1184
1213
|
|
|
1185
1214
|
The reusable shape for standing up a **spawnable TS** cross-process test
|
|
@@ -1191,7 +1220,7 @@ re-roll the serve / daemon-info / WS-attach / drain boilerplate:
|
|
|
1191
1220
|
- `testing/cross_backend/testing_server_deno.ts` — `create_deno_testing_adapter()` (`Deno.serve` + `hono/deno`; `Deno` declared locally so it typechecks under the Node toolchain). Spawn the entry with `--sloppy-imports` (Deno doesn't do `.js`→`.ts`; Gro's loader does, so the Node path needs no flag).
|
|
1192
1221
|
- `testing/cross_backend/testing_server_bun.ts` — `create_bun_testing_adapter()` (`Bun.serve` + `hono/bun`'s module-level `upgradeWebSocket` + `websocket`; `Bun.serve` declared locally so it typechecks under the Node toolchain). **No extra deps** (`hono/bun` ships with `hono`; `Bun.serve` is built in, unlike Node's `@hono/node-server` + `@hono/node-ws`), and Bun resolves `.js`→`.ts` natively (no flag, unlike Deno). Reuses `create_node_runtime` (Bun implements the `node:fs`/`node:process` surface). WS is module-level + stateless (like Deno) — the `websocket` handler is threaded into `serve`, where `Bun.serve` wants it, so no post-serve attach.
|
|
1193
1222
|
- `testing/cross_backend/default_spine_surface.ts` — the canonical no-domain spine surface (account/admin/audit/signup + bootstrap): `spine_session_options`, `spine_roles`, `create_spine_route_specs`, `spine_rpc_endpoints`, `create_spine_surface_spec`. `$lib`-free (it's reached by the spawned binary under Gro's loader, which doesn't resolve `$lib`), so keep it on relative imports. Shared by the spine_stub cross test, the TS cross tests, and the binary.
|
|
1194
|
-
- `testing/cross_backend/ts_spine_backend_config.ts` — `ts_spine_node_backend_config()` / `ts_spine_deno_backend_config()` / `ts_spine_bun_backend_config()` presets (in-memory PGlite, no external infra), the TS analog of `
|
|
1223
|
+
- `testing/cross_backend/ts_spine_backend_config.ts` — `ts_spine_node_backend_config()` / `ts_spine_deno_backend_config()` / `ts_spine_bun_backend_config()` presets (in-memory PGlite, no external infra), the TS analog of `rust_spine_stub_backend_config()`.
|
|
1195
1224
|
|
|
1196
1225
|
fuz_app's own binary wiring (`src/test/cross_backend/testing_spine_server{,_node,_deno,_bun}.ts`) is the worked example: ~one `build_app` over `create_app_backend` + `create_app_server` + `_testing_reset` + a WS mount, reusing `default_spine_surface`. The `_node`/`_deno`/`_bun` entries differ only in which adapter they wire — `build_spine_app` is runtime-agnostic.
|
|
1197
1226
|
|
|
@@ -1234,7 +1263,7 @@ no stats engine reinvented. fuz_app ships the primitive; consumers wire
|
|
|
1234
1263
|
scenarios + the run (zzz's `npm run benchmark:cross-impl` was the first).
|
|
1235
1264
|
fuz_app also ships its **own** `npm run benchmark:cross-impl`
|
|
1236
1265
|
(`src/benchmarks/cross_impl.bench.ts`) on the back of its TS spine binary —
|
|
1237
|
-
ts-node + ts-deno + ts-bun (+ the Rust `spine_stub` when `
|
|
1266
|
+
ts-node + ts-deno + ts-bun (+ the Rust `spine_stub` when `FUZ_TESTING_RUST_SPINE_STUB_BIN`
|
|
1238
1267
|
is set). The three TS runtimes are apples-to-apples with each other (same
|
|
1239
1268
|
PGlite driver); TS-vs-Rust carries the PGlite-vs-Postgres DB-layer caveat
|
|
1240
1269
|
(documented in the run). The artifact (`*.latest.json`) is gitignored.
|
|
@@ -6,10 +6,10 @@ import '../assert_dev_env.js';
|
|
|
6
6
|
* env vars, bootstrap credentials, daemon-token discovery path, declared
|
|
7
7
|
* capabilities. Consumer projects ship per-backend factories
|
|
8
8
|
* (`deno_backend_config()`, `rust_backend_config()`,
|
|
9
|
-
* `
|
|
9
|
+
* `rust_spine_stub_backend_config()`) that produce this shape; `spawn_backend`
|
|
10
10
|
* consumes it.
|
|
11
11
|
*
|
|
12
|
-
* fuz_app ships `
|
|
12
|
+
* fuz_app ships `rust_spine_stub_backend_config()` as a convenience preset
|
|
13
13
|
* (operational dep on `testing_spine_stub` — path-based discovery, no
|
|
14
14
|
* `package.json` coupling to the stub's source package). Otherwise backend-specific
|
|
15
15
|
* knowledge (binary paths, port choices, env vars) is a consumer
|
|
@@ -76,6 +76,16 @@ export interface BackendCapabilities {
|
|
|
76
76
|
* the serve routes stay off the standard declared surface.
|
|
77
77
|
*/
|
|
78
78
|
readonly fact_serving: boolean;
|
|
79
|
+
/**
|
|
80
|
+
* The `/ready` readiness deploy gate (`GET /ready`) is live-mounted on the
|
|
81
|
+
* backend — the public column-presence schema-drift probe over the committed
|
|
82
|
+
* `expected_schema.json`. Gates `describe_ready_cross_tests` (anonymous
|
|
83
|
+
* `GET /ready` → `200 {ready: true}` on a clean spine bootstrap). Like
|
|
84
|
+
* ws/sse/cells, the route stays off the standard declared surface
|
|
85
|
+
* (`create_spine_surface_spec`); this flag opts a backend into the dedicated
|
|
86
|
+
* readiness parity coverage. The drift → `503` path stays per-impl unit tests.
|
|
87
|
+
*/
|
|
88
|
+
readonly ready: boolean;
|
|
79
89
|
}
|
|
80
90
|
/**
|
|
81
91
|
* Capability declarations for the in-process Hono transport. Every flag
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capabilities.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAmB9B;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IACnC;;;;OAIG;IACH,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC;;;OAGG;IACH,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;IACnC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB;;;;;OAKG;IACH,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB;;;;;;;OAOG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC;;;;;;;;OAQG;IACH,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC;;;;;;;;OAQG;IACH,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"capabilities.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAmB9B;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IACnC;;;;OAIG;IACH,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC;;;OAGG;IACH,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;IACnC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB;;;;;OAKG;IACH,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB;;;;;;;OAOG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC;;;;;;;;OAQG;IACH,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC;;;;;;;;OAQG;IACH,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B;;;;;;;;OAQG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACxB;AAED;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,EAAE,mBAWpC,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,OAAO,GAAI,MAAM,OAAO,EAAE,MAAM,MAAM,EAAE,IAAI,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAG,IAMrF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"default_backend_configs.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/default_backend_configs.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,KAAK,EAAC,sBAAsB,EAAE,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAC/E,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAA2B,KAAK,gBAAgB,EAAC,MAAM,+BAA+B,CAAC;AAQ9F;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,EAAE,
|
|
1
|
+
{"version":3,"file":"default_backend_configs.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/default_backend_configs.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,KAAK,EAAC,sBAAsB,EAAE,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAC/E,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAA2B,KAAK,gBAAgB,EAAC,MAAM,+BAA+B,CAAC;AAQ9F;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,EAAE,mBAapC,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,EAAE,mBAatC,CAAC;AAeH,MAAM,WAAW,iCAAiC;IACjD,gFAAgF;IAChF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,sCAAsC;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4DAA4D;IAC5D,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC9C,oDAAoD;IACpD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,iEAAiE;IACjE,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACtD,6CAA6C;IAC7C,QAAQ,CAAC,YAAY,CAAC,EAAE,mBAAmB,CAAC;IAC5C,wEAAwE;IACxE,QAAQ,CAAC,KAAK,CAAC,EAAE,gBAAgB,CAAC;IAClC,sEAAsE;IACtE,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC,CAAC;IAC/D;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B;;;;;;OAMG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,GAC1C,MAAM,iCAAiC,KACrC,aAoCF,CAAC;AAEF,MAAM,WAAW,mCAAmC;IACnD,gFAAgF;IAChF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,sCAAsC;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4DAA4D;IAC5D,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC9C;;;;OAIG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,iEAAiE;IACjE,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACtD,+CAA+C;IAC/C,QAAQ,CAAC,YAAY,CAAC,EAAE,mBAAmB,CAAC;IAC5C,wEAAwE;IACxE,QAAQ,CAAC,KAAK,CAAC,EAAE,gBAAgB,CAAC;IAClC,sEAAsE;IACtE,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC,CAAC;IAC/D;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,GAC5C,MAAM,mCAAmC,KACvC,aA4CF,CAAC"}
|
|
@@ -17,6 +17,9 @@ export const ts_default_capabilities = Object.freeze({
|
|
|
17
17
|
cell_relations: true,
|
|
18
18
|
account_lifecycle: true,
|
|
19
19
|
fact_serving: true,
|
|
20
|
+
// Off by default like `sse` — a generic TS consumer backend may not mount
|
|
21
|
+
// `/ready`. fuz_app's own spine configs (`ts_spine_*`) opt in.
|
|
22
|
+
ready: false,
|
|
20
23
|
});
|
|
21
24
|
/**
|
|
22
25
|
* Capabilities for the Rust family. Adds `trusted_proxy: true` (the
|
|
@@ -34,6 +37,9 @@ export const rust_default_capabilities = Object.freeze({
|
|
|
34
37
|
cell_relations: true,
|
|
35
38
|
account_lifecycle: true,
|
|
36
39
|
fact_serving: true,
|
|
40
|
+
// Off by default like `sse`; the spine-stub preset opts in (it mounts
|
|
41
|
+
// `/ready` over the env-supplied fixture path).
|
|
42
|
+
ready: false,
|
|
37
43
|
});
|
|
38
44
|
/** Bootstrap block built from the default secrets + supplied paths. */
|
|
39
45
|
const build_default_bootstrap = (paths, overrides) => ({
|
|
@@ -1,4 +1,29 @@
|
|
|
1
1
|
import '../assert_dev_env.js';
|
|
2
|
+
/**
|
|
3
|
+
* Canonical no-domain spine surface — the standard fuz_app
|
|
4
|
+
* auth/account/admin/audit surface with no consumer domain layer on top.
|
|
5
|
+
*
|
|
6
|
+
* This is the single source of truth for "the standard spine surface",
|
|
7
|
+
* shared by:
|
|
8
|
+
*
|
|
9
|
+
* - the Rust `testing_spine_stub` cross-process self-tests (which build the
|
|
10
|
+
* `AppSurfaceSpec` via `create_spine_surface_spec` and drive the binary's
|
|
11
|
+
* wire shape),
|
|
12
|
+
* - the TS `testing_spine_server` cross-process binary (which feeds
|
|
13
|
+
* `create_spine_route_specs` + `spine_rpc_endpoints` into a live
|
|
14
|
+
* `create_app_server`), and
|
|
15
|
+
* - the `cross_backend_ts_*` self-test projects.
|
|
16
|
+
*
|
|
17
|
+
* **`$lib`-free by contract.** This module and everything it imports use
|
|
18
|
+
* relative specifiers (no `$lib` SvelteKit alias) so the spawned TS test
|
|
19
|
+
* binary — run under Gro's loader, which resolves `.js`→`.ts` and package
|
|
20
|
+
* imports but **not** the `$lib` alias — can import it transitively. Keep
|
|
21
|
+
* it that way: a `$lib` import anywhere in this graph breaks the binary
|
|
22
|
+
* spawn while still typechecking under vitest.
|
|
23
|
+
*
|
|
24
|
+
* @module
|
|
25
|
+
*/
|
|
26
|
+
import type { Logger } from '@fuzdev/fuz_util/log.js';
|
|
2
27
|
import type { NotificationSender } from '../../auth/role_grant_offer_notifications.js';
|
|
3
28
|
import { type RoleSchemaResult } from '../../auth/role_schema.js';
|
|
4
29
|
import { type SessionOptions } from '../../auth/session_cookie.js';
|
|
@@ -84,6 +109,29 @@ export declare const spine_rpc_endpoints: (ctx: AppServerContext, options?: Spin
|
|
|
84
109
|
* the stream at `SPINE_SSE_PATH`.
|
|
85
110
|
*/
|
|
86
111
|
export declare const create_spine_route_specs: (ctx: AppServerContext) => Array<RouteSpec>;
|
|
112
|
+
/**
|
|
113
|
+
* Committed expected-schema fixture for the spine `/ready` deploy gate — the
|
|
114
|
+
* column map a fresh full spine bootstrap (auth + cell + cell_history + fact)
|
|
115
|
+
* produces. Resolved relative to this module so the spawned TS binary (which
|
|
116
|
+
* imports this source under its loader) reads it off disk via `node:fs`.
|
|
117
|
+
* Regenerated + guarded by `src/test/cross_backend/spine_expected_schema.db.test.ts`.
|
|
118
|
+
*
|
|
119
|
+
* The Rust `testing_spine_stub` reads the **same** committed file (its absolute
|
|
120
|
+
* path passed via env by `rust_spine_stub_backend_config`) — column-presence is
|
|
121
|
+
* engine-portable, so one fixture is the cross-impl contract.
|
|
122
|
+
*/
|
|
123
|
+
export declare const SPINE_EXPECTED_SCHEMA_URL: URL;
|
|
124
|
+
/**
|
|
125
|
+
* The spine's `/ready` route spec — the column-presence schema-drift deploy
|
|
126
|
+
* gate, reading {@link SPINE_EXPECTED_SCHEMA_URL}. Mounted **live** by the TS
|
|
127
|
+
* spine binary (in `build_spine_app`) and the in-process readiness parity leg,
|
|
128
|
+
* but kept **off** the declared surface (`create_spine_surface_spec`) like the
|
|
129
|
+
* fact-serving / ws / sse behaviors — `describe_ready_cross_tests` (gated on
|
|
130
|
+
* `capabilities.ready`) is its explicit coverage, not the generic round-trip.
|
|
131
|
+
*
|
|
132
|
+
* @param log - optional logger for server-side drift diagnostics
|
|
133
|
+
*/
|
|
134
|
+
export declare const create_spine_ready_route_spec: (log?: Logger) => RouteSpec;
|
|
87
135
|
/**
|
|
88
136
|
* The `AppSurfaceSpec` for the standard spine surface — the wire-shape
|
|
89
137
|
* source the cross-process round-trip + RPC-round-trip suites validate
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"default_spine_surface.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/default_spine_surface.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"default_spine_surface.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/default_spine_surface.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAIpD,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,8CAA8C,CAAC;AACrF,OAAO,EAAqB,KAAK,gBAAgB,EAAC,MAAM,2BAA2B,CAAC;AACpF,OAAO,EAAwB,KAAK,cAAc,EAAC,MAAM,8BAA8B,CAAC;AAIxF,OAAO,EAAqB,KAAK,SAAS,EAAC,MAAM,0BAA0B,CAAC;AAC5E,OAAO,KAAK,EAAC,cAAc,EAAE,eAAe,EAAC,MAAM,uBAAuB,CAAC;AAC3E,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,oCAAoC,CAAC;AAGzE;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,cAAc,CAAC,MAAM,CAAwC,CAAC;AAElG;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,gBAAgB,CAAC;AAEpD;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,EAAE,gBAExB,CAAC;AAEH,iEAAiE;AACjE,eAAO,MAAM,cAAc,aAAa,CAAC;AAEzC;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,4BAA4B,CAAC;AAExD,+CAA+C;AAC/C,MAAM,WAAW,wBAAwB;IACxC;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;CACzD;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,mBAAmB,GAC/B,KAAK,gBAAgB,EACrB,UAAU,wBAAwB,KAChC,KAAK,CAAC,eAAe,CAQvB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,wBAAwB,GAAI,KAAK,gBAAgB,KAAG,KAAK,CAAC,SAAS,CAiB/E,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,yBAAyB,EAAE,GAAwD,CAAC;AAEjG;;;;;;;;;GASG;AACH,eAAO,MAAM,6BAA6B,GAAI,MAAM,MAAM,KAAG,SAC6B,CAAC;AAE3F;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,QAAO,cAM1C,CAAC"}
|
|
@@ -1,34 +1,11 @@
|
|
|
1
1
|
import '../assert_dev_env.js';
|
|
2
|
-
/**
|
|
3
|
-
* Canonical no-domain spine surface — the standard fuz_app
|
|
4
|
-
* auth/account/admin/audit surface with no consumer domain layer on top.
|
|
5
|
-
*
|
|
6
|
-
* This is the single source of truth for "the standard spine surface",
|
|
7
|
-
* shared by:
|
|
8
|
-
*
|
|
9
|
-
* - the Rust `testing_spine_stub` cross-process self-tests (which build the
|
|
10
|
-
* `AppSurfaceSpec` via `create_spine_surface_spec` and drive the binary's
|
|
11
|
-
* wire shape),
|
|
12
|
-
* - the TS `testing_spine_server` cross-process binary (which feeds
|
|
13
|
-
* `create_spine_route_specs` + `spine_rpc_endpoints` into a live
|
|
14
|
-
* `create_app_server`), and
|
|
15
|
-
* - the `cross_backend_ts_*` self-test projects.
|
|
16
|
-
*
|
|
17
|
-
* **`$lib`-free by contract.** This module and everything it imports use
|
|
18
|
-
* relative specifiers (no `$lib` SvelteKit alias) so the spawned TS test
|
|
19
|
-
* binary — run under Gro's loader, which resolves `.js`→`.ts` and package
|
|
20
|
-
* imports but **not** the `$lib` alias — can import it transitively. Keep
|
|
21
|
-
* it that way: a `$lib` import anywhere in this graph breaks the binary
|
|
22
|
-
* spawn while still typechecking under vitest.
|
|
23
|
-
*
|
|
24
|
-
* @module
|
|
25
|
-
*/
|
|
26
2
|
import { create_account_route_specs } from '../../auth/account_routes.js';
|
|
27
3
|
import { create_audit_log_route_specs } from '../../auth/audit_log_routes.js';
|
|
28
4
|
import { create_role_schema } from '../../auth/role_schema.js';
|
|
29
5
|
import { create_session_config } from '../../auth/session_cookie.js';
|
|
30
6
|
import { create_signup_route_specs } from '../../auth/signup_routes.js';
|
|
31
7
|
import { create_standard_rpc_actions } from '../../auth/standard_rpc_actions.js';
|
|
8
|
+
import { create_ready_route_spec, load_expected_schema } from '../../http/common_routes.js';
|
|
32
9
|
import { prefix_route_specs } from '../../http/route_spec.js';
|
|
33
10
|
import { create_test_app_surface_spec } from '../stubs.js';
|
|
34
11
|
/**
|
|
@@ -114,6 +91,29 @@ export const create_spine_route_specs = (ctx) => [
|
|
|
114
91
|
? prefix_route_specs('/api/admin', create_audit_log_route_specs({ stream: ctx.audit_sse }))
|
|
115
92
|
: []),
|
|
116
93
|
];
|
|
94
|
+
/**
|
|
95
|
+
* Committed expected-schema fixture for the spine `/ready` deploy gate — the
|
|
96
|
+
* column map a fresh full spine bootstrap (auth + cell + cell_history + fact)
|
|
97
|
+
* produces. Resolved relative to this module so the spawned TS binary (which
|
|
98
|
+
* imports this source under its loader) reads it off disk via `node:fs`.
|
|
99
|
+
* Regenerated + guarded by `src/test/cross_backend/spine_expected_schema.db.test.ts`.
|
|
100
|
+
*
|
|
101
|
+
* The Rust `testing_spine_stub` reads the **same** committed file (its absolute
|
|
102
|
+
* path passed via env by `rust_spine_stub_backend_config`) — column-presence is
|
|
103
|
+
* engine-portable, so one fixture is the cross-impl contract.
|
|
104
|
+
*/
|
|
105
|
+
export const SPINE_EXPECTED_SCHEMA_URL = new URL('./expected_schema.json', import.meta.url);
|
|
106
|
+
/**
|
|
107
|
+
* The spine's `/ready` route spec — the column-presence schema-drift deploy
|
|
108
|
+
* gate, reading {@link SPINE_EXPECTED_SCHEMA_URL}. Mounted **live** by the TS
|
|
109
|
+
* spine binary (in `build_spine_app`) and the in-process readiness parity leg,
|
|
110
|
+
* but kept **off** the declared surface (`create_spine_surface_spec`) like the
|
|
111
|
+
* fact-serving / ws / sse behaviors — `describe_ready_cross_tests` (gated on
|
|
112
|
+
* `capabilities.ready`) is its explicit coverage, not the generic round-trip.
|
|
113
|
+
*
|
|
114
|
+
* @param log - optional logger for server-side drift diagnostics
|
|
115
|
+
*/
|
|
116
|
+
export const create_spine_ready_route_spec = (log) => create_ready_route_spec({ expected: load_expected_schema(SPINE_EXPECTED_SCHEMA_URL), log });
|
|
117
117
|
/**
|
|
118
118
|
* The `AppSurfaceSpec` for the standard spine surface — the wire-shape
|
|
119
119
|
* source the cross-process round-trip + RPC-round-trip suites validate
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
{
|
|
2
|
+
"account": [
|
|
3
|
+
"created_at",
|
|
4
|
+
"created_by",
|
|
5
|
+
"deleted_at",
|
|
6
|
+
"deleted_by",
|
|
7
|
+
"email",
|
|
8
|
+
"email_verified",
|
|
9
|
+
"id",
|
|
10
|
+
"password_hash",
|
|
11
|
+
"updated_at",
|
|
12
|
+
"updated_by",
|
|
13
|
+
"username"
|
|
14
|
+
],
|
|
15
|
+
"actor": [
|
|
16
|
+
"account_id",
|
|
17
|
+
"created_at",
|
|
18
|
+
"deleted_at",
|
|
19
|
+
"deleted_by",
|
|
20
|
+
"id",
|
|
21
|
+
"name",
|
|
22
|
+
"updated_at",
|
|
23
|
+
"updated_by"
|
|
24
|
+
],
|
|
25
|
+
"api_token": [
|
|
26
|
+
"account_id",
|
|
27
|
+
"created_at",
|
|
28
|
+
"expires_at",
|
|
29
|
+
"id",
|
|
30
|
+
"last_used_at",
|
|
31
|
+
"last_used_ip",
|
|
32
|
+
"name",
|
|
33
|
+
"token_hash"
|
|
34
|
+
],
|
|
35
|
+
"app_settings": ["id", "open_signup", "updated_at", "updated_by"],
|
|
36
|
+
"audit_log": [
|
|
37
|
+
"account_id",
|
|
38
|
+
"actor_id",
|
|
39
|
+
"created_at",
|
|
40
|
+
"event_type",
|
|
41
|
+
"id",
|
|
42
|
+
"ip",
|
|
43
|
+
"metadata",
|
|
44
|
+
"outcome",
|
|
45
|
+
"seq",
|
|
46
|
+
"target_account_id",
|
|
47
|
+
"target_actor_id"
|
|
48
|
+
],
|
|
49
|
+
"auth_session": ["account_id", "created_at", "expires_at", "id", "last_seen_at"],
|
|
50
|
+
"bootstrap_lock": ["bootstrapped", "id"],
|
|
51
|
+
"cell": [
|
|
52
|
+
"created_at",
|
|
53
|
+
"created_by",
|
|
54
|
+
"data",
|
|
55
|
+
"deleted_at",
|
|
56
|
+
"id",
|
|
57
|
+
"path",
|
|
58
|
+
"refs",
|
|
59
|
+
"updated_at",
|
|
60
|
+
"updated_by",
|
|
61
|
+
"visibility"
|
|
62
|
+
],
|
|
63
|
+
"cell_field": ["created_at", "name", "source_id", "target_id"],
|
|
64
|
+
"cell_grant": [
|
|
65
|
+
"actor_id",
|
|
66
|
+
"cell_id",
|
|
67
|
+
"created_at",
|
|
68
|
+
"granted_by",
|
|
69
|
+
"id",
|
|
70
|
+
"level",
|
|
71
|
+
"role",
|
|
72
|
+
"scope_id"
|
|
73
|
+
],
|
|
74
|
+
"cell_history": ["action_id", "cell_id", "created_at", "fact_hash", "id"],
|
|
75
|
+
"cell_item": ["child_id", "created_at", "parent_id", "position"],
|
|
76
|
+
"fact": ["bytes", "content_type", "created_at", "external_url", "hash", "size"],
|
|
77
|
+
"fact_ref": ["source_hash", "target_hash"],
|
|
78
|
+
"invite": ["claimed_at", "claimed_by", "created_at", "created_by", "email", "id", "username"],
|
|
79
|
+
"memo": ["created_at", "fn_id", "input_hash", "output_hash"],
|
|
80
|
+
"role_grant": [
|
|
81
|
+
"actor_id",
|
|
82
|
+
"created_at",
|
|
83
|
+
"expires_at",
|
|
84
|
+
"granted_by",
|
|
85
|
+
"id",
|
|
86
|
+
"revoked_at",
|
|
87
|
+
"revoked_by",
|
|
88
|
+
"revoked_reason",
|
|
89
|
+
"role",
|
|
90
|
+
"scope_id",
|
|
91
|
+
"scope_kind",
|
|
92
|
+
"source_offer_id"
|
|
93
|
+
],
|
|
94
|
+
"role_grant_offer": [
|
|
95
|
+
"accepted_at",
|
|
96
|
+
"created_at",
|
|
97
|
+
"decline_reason",
|
|
98
|
+
"declined_at",
|
|
99
|
+
"expires_at",
|
|
100
|
+
"from_actor_id",
|
|
101
|
+
"id",
|
|
102
|
+
"message",
|
|
103
|
+
"resulting_role_grant_id",
|
|
104
|
+
"retracted_at",
|
|
105
|
+
"role",
|
|
106
|
+
"scope_id",
|
|
107
|
+
"scope_kind",
|
|
108
|
+
"superseded_at",
|
|
109
|
+
"to_account_id",
|
|
110
|
+
"to_actor_id"
|
|
111
|
+
],
|
|
112
|
+
"schema_version": ["applied_at", "name", "namespace", "sequence"]
|
|
113
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import '../assert_dev_env.js';
|
|
2
|
+
import { type BackendCapabilities } from './capabilities.js';
|
|
3
|
+
import type { SetupTest } from './setup.js';
|
|
4
|
+
/** Options for the readiness-probe parity suite. */
|
|
5
|
+
export interface ReadyCrossTestOptions {
|
|
6
|
+
/** Per-test fixture-producing function (fresh keeper + db per call). */
|
|
7
|
+
readonly setup_test: SetupTest;
|
|
8
|
+
/** Backend capability declarations — the suite gates on `capabilities.ready`. */
|
|
9
|
+
readonly capabilities: BackendCapabilities;
|
|
10
|
+
/** Readiness probe path. Default `/ready`. */
|
|
11
|
+
readonly ready_path?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare const describe_ready_cross_tests: (options: ReadyCrossTestOptions) => void;
|
|
14
|
+
//# sourceMappingURL=ready.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ready.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/ready.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAiC9B,OAAO,EAAU,KAAK,mBAAmB,EAAC,MAAM,mBAAmB,CAAC;AACpE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,YAAY,CAAC;AAE1C,oDAAoD;AACpD,MAAM,WAAW,qBAAqB;IACrC,wEAAwE;IACxE,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC;IAC/B,iFAAiF;IACjF,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;IAC3C,8CAA8C;IAC9C,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,eAAO,MAAM,0BAA0B,GAAI,SAAS,qBAAqB,KAAG,IAuB3E,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import '../assert_dev_env.js';
|
|
2
|
+
/**
|
|
3
|
+
* Cross-backend parity suite for the `/ready` schema-drift deploy gate.
|
|
4
|
+
*
|
|
5
|
+
* The `/ready` mechanism already ships on both twins (TS `create_ready_route_spec`
|
|
6
|
+
* / `db/schema_ready.ts`; Rust `fuz_http::ready` / `fuz_db::schema_ready`), each
|
|
7
|
+
* with its own drift → `503` unit tests. This suite is the missing automated
|
|
8
|
+
* cross-impl gate: an anonymous `GET /ready` returns `200 {ready: true}` over
|
|
9
|
+
* real HTTP on **both** spine test servers, proving the success path is wire-
|
|
10
|
+
* identical and that both backends read the same committed `expected_schema.json`
|
|
11
|
+
* (column-presence is engine-portable, so one fixture is the cross-impl contract).
|
|
12
|
+
*
|
|
13
|
+
* `/ready` is a plain public REST route — not an RPC method, not one of the six
|
|
14
|
+
* REST auth routes — and it's deliberately **off** the declared spine surface
|
|
15
|
+
* (`create_spine_surface_spec`), like ws/sse/cells/fact-serving. So it needs a
|
|
16
|
+
* bespoke imperative suite (à la `origin.cross.test.ts`), gated on
|
|
17
|
+
* `capabilities.ready`, rather than a `conformance_table` row or generic
|
|
18
|
+
* round-trip enumeration. The drift → `503` path stays per-impl unit tests.
|
|
19
|
+
*
|
|
20
|
+
* Runs both legs via the shared `{setup_test, capabilities}` protocol: the
|
|
21
|
+
* in-process leg (`cross_backend/ready_parity.db.test.ts`, plain `gro test`) and
|
|
22
|
+
* the cross-process leg (`cross_backend/ready.cross.test.ts`, the TS spine
|
|
23
|
+
* binaries + Rust `testing_spine_stub` over real HTTP).
|
|
24
|
+
*
|
|
25
|
+
* `$lib`-free by contract (relative specifiers only), like the sibling
|
|
26
|
+
* cross-backend suites.
|
|
27
|
+
*
|
|
28
|
+
* @module
|
|
29
|
+
*/
|
|
30
|
+
import { describe, assert } from 'vitest';
|
|
31
|
+
import { test_if } from './capabilities.js';
|
|
32
|
+
export const describe_ready_cross_tests = (options) => {
|
|
33
|
+
const { setup_test, capabilities } = options;
|
|
34
|
+
const ready_path = options.ready_path ?? '/ready';
|
|
35
|
+
describe('readiness probe parity', () => {
|
|
36
|
+
test_if(capabilities.ready, 'anonymous GET /ready → 200 {ready: true} on a clean spine bootstrap', async () => {
|
|
37
|
+
const fixture = await setup_test();
|
|
38
|
+
// Anonymous deploy-poll shape: cookie-jar-free, no Origin, no auth.
|
|
39
|
+
// `/ready` is public and outside `/api`, so neither the session /
|
|
40
|
+
// bearer middleware nor the RPC dispatcher sits in the path — exactly
|
|
41
|
+
// how a deploy gate (zap) polls it post-deploy. A freshly bootstrapped
|
|
42
|
+
// spine covers the committed expected column map, so the drift check
|
|
43
|
+
// passes.
|
|
44
|
+
const res = await fixture.fresh_transport({ origin: null })(ready_path, { method: 'GET' });
|
|
45
|
+
assert.strictEqual(res.status, 200, 'a clean spine bootstrap must report ready');
|
|
46
|
+
const body = (await res.json().catch(() => undefined));
|
|
47
|
+
assert.strictEqual(body?.ready, true);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import '../assert_dev_env.js';
|
|
2
|
+
import type { BackendConfig } from './backend_config.js';
|
|
3
|
+
/** Env var naming the prebuilt `testing_spine_stub` binary. Required when `binary_path` is omitted. */
|
|
4
|
+
export declare const RUST_SPINE_STUB_BIN_ENV = "FUZ_TESTING_RUST_SPINE_STUB_BIN";
|
|
5
|
+
/**
|
|
6
|
+
* Env var the stub reads for the absolute path of the committed
|
|
7
|
+
* `expected_schema.json` its `/ready` gate introspects against. Pointed at the
|
|
8
|
+
* **same** fixture the TS spine reads ({@link SPINE_EXPECTED_SCHEMA_URL}) —
|
|
9
|
+
* column-presence is engine-portable, so one file is the cross-impl contract.
|
|
10
|
+
*/
|
|
11
|
+
export declare const RUST_SPINE_STUB_EXPECTED_SCHEMA_PATH_ENV = "FUZ_RUST_SPINE_STUB_EXPECTED_SCHEMA_PATH";
|
|
12
|
+
/** Default listening port — slots beside zzz's 1175/1176; matches the binary's `DEFAULT_PORT`. */
|
|
13
|
+
export declare const RUST_SPINE_STUB_DEFAULT_PORT = 1177;
|
|
14
|
+
/** Default Postgres database — real PG (PGlite isn't reachable from `tokio-postgres`). */
|
|
15
|
+
export declare const RUST_SPINE_STUB_DEFAULT_DATABASE_URL = "postgres://localhost/fuz_app_test_rust_spine_stub";
|
|
16
|
+
export interface SpineStubBackendConfigOptions {
|
|
17
|
+
/** Listening port. Default `RUST_SPINE_STUB_DEFAULT_PORT`. */
|
|
18
|
+
readonly port?: number;
|
|
19
|
+
/** Postgres connection URL. Default `RUST_SPINE_STUB_DEFAULT_DATABASE_URL`. */
|
|
20
|
+
readonly database_url?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Prebuilt binary path. Overrides the `FUZ_TESTING_RUST_SPINE_STUB_BIN` env
|
|
23
|
+
* var. When neither is set the preset throws.
|
|
24
|
+
*/
|
|
25
|
+
readonly binary_path?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Build the `BackendConfig` for `testing_spine_stub`. Resolves the binary
|
|
29
|
+
* from `options.binary_path` or `FUZ_TESTING_RUST_SPINE_STUB_BIN`; throws when
|
|
30
|
+
* neither is set so a missing build surfaces as a clear error rather than
|
|
31
|
+
* a confusing spawn failure. Reconciles the binary's env contract: port
|
|
32
|
+
* via `--port` (and `FUZ_RUST_SPINE_STUB_PORT`), daemon-token dir via
|
|
33
|
+
* `FUZ_RUST_SPINE_STUB_DIR` (anchored to `paths.root` so the written
|
|
34
|
+
* `{dir}/run/daemon_token` matches the path `spawn_backend` reads).
|
|
35
|
+
*
|
|
36
|
+
* @throws Error when no binary path is available.
|
|
37
|
+
*/
|
|
38
|
+
export declare const rust_spine_stub_backend_config: (options?: SpineStubBackendConfigOptions) => BackendConfig;
|
|
39
|
+
//# sourceMappingURL=rust_spine_stub_backend_config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rust_spine_stub_backend_config.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/rust_spine_stub_backend_config.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAuC9B,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAQvD,uGAAuG;AACvG,eAAO,MAAM,uBAAuB,oCAAoC,CAAC;AAEzE;;;;;GAKG;AACH,eAAO,MAAM,wCAAwC,6CAA6C,CAAC;AAEnG,kGAAkG;AAClG,eAAO,MAAM,4BAA4B,OAAO,CAAC;AAEjD,0FAA0F;AAC1F,eAAO,MAAM,oCAAoC,sDACG,CAAC;AAErD,MAAM,WAAW,6BAA6B;IAC7C,8DAA8D;IAC9D,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,+EAA+E;IAC/E,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,8BAA8B,GAC1C,UAAS,6BAAkC,KACzC,aA6CF,CAAC"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import '../assert_dev_env.js';
|
|
2
|
+
/**
|
|
3
|
+
* Cross-process `BackendConfig` preset for the non-domain spine consumer,
|
|
4
|
+
* `testing_spine_stub` — a Rust binary that mounts only the spine surface
|
|
5
|
+
* (auth / account / admin / audit / role-grant offers) with no domain
|
|
6
|
+
* layer. fuz_app drives it from `src/test/cross_backend/*.cross.test.ts`
|
|
7
|
+
* to verify its TS spec against the Rust spine end-to-end with no domain
|
|
8
|
+
* implementation in the loop — drift becomes a fuz_app failure rather than
|
|
9
|
+
* a downstream consumer's failure with mixed signals.
|
|
10
|
+
*
|
|
11
|
+
* **Binary discovery — env-supplied, never hardcoded.** The binary lives
|
|
12
|
+
* in a sibling Rust workspace, not in fuz_app, so the preset never bakes a
|
|
13
|
+
* path in. `FUZ_TESTING_RUST_SPINE_STUB_BIN` (or the `binary_path` option) must
|
|
14
|
+
* point at a prebuilt binary; the preset throws a clear error when neither
|
|
15
|
+
* is set rather than guessing. Build once with
|
|
16
|
+
* `cargo build -p testing_spine_stub --release` and point the env var at
|
|
17
|
+
* the resulting `target/release/testing_spine_stub`; operators / CI cache
|
|
18
|
+
* the binary across runs for fast spawns.
|
|
19
|
+
*
|
|
20
|
+
* **Operator setup** — the target Postgres database must exist before the
|
|
21
|
+
* harness runs (the harness never issues `CREATE DATABASE`, to avoid
|
|
22
|
+
* forcing a `CREATEDB` grant on the test role):
|
|
23
|
+
*
|
|
24
|
+
* ```bash
|
|
25
|
+
* createdb fuz_app_test_rust_spine_stub 2>/dev/null || true
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* The binary self-wipes the auth-namespace schema on every boot
|
|
29
|
+
* (`FUZ_TESTING_RESET_DB_ON_STARTUP=true`, set by the Rust-family builder),
|
|
30
|
+
* so no manual `DROP TABLE` between sessions is needed; per-test reset is
|
|
31
|
+
* the orthogonal `_testing_reset` RPC action `default_cross_process_setup`
|
|
32
|
+
* fires.
|
|
33
|
+
*
|
|
34
|
+
* @module
|
|
35
|
+
*/
|
|
36
|
+
import { fileURLToPath } from 'node:url';
|
|
37
|
+
import { build_test_backend_paths } from './build_test_backend_paths.js';
|
|
38
|
+
import { SPINE_EXPECTED_SCHEMA_URL } from './default_spine_surface.js';
|
|
39
|
+
import { make_default_rust_backend_config, rust_default_capabilities, } from './default_backend_configs.js';
|
|
40
|
+
/** Env var naming the prebuilt `testing_spine_stub` binary. Required when `binary_path` is omitted. */
|
|
41
|
+
export const RUST_SPINE_STUB_BIN_ENV = 'FUZ_TESTING_RUST_SPINE_STUB_BIN';
|
|
42
|
+
/**
|
|
43
|
+
* Env var the stub reads for the absolute path of the committed
|
|
44
|
+
* `expected_schema.json` its `/ready` gate introspects against. Pointed at the
|
|
45
|
+
* **same** fixture the TS spine reads ({@link SPINE_EXPECTED_SCHEMA_URL}) —
|
|
46
|
+
* column-presence is engine-portable, so one file is the cross-impl contract.
|
|
47
|
+
*/
|
|
48
|
+
export const RUST_SPINE_STUB_EXPECTED_SCHEMA_PATH_ENV = 'FUZ_RUST_SPINE_STUB_EXPECTED_SCHEMA_PATH';
|
|
49
|
+
/** Default listening port — slots beside zzz's 1175/1176; matches the binary's `DEFAULT_PORT`. */
|
|
50
|
+
export const RUST_SPINE_STUB_DEFAULT_PORT = 1177;
|
|
51
|
+
/** Default Postgres database — real PG (PGlite isn't reachable from `tokio-postgres`). */
|
|
52
|
+
export const RUST_SPINE_STUB_DEFAULT_DATABASE_URL = 'postgres://localhost/fuz_app_test_rust_spine_stub';
|
|
53
|
+
/**
|
|
54
|
+
* Build the `BackendConfig` for `testing_spine_stub`. Resolves the binary
|
|
55
|
+
* from `options.binary_path` or `FUZ_TESTING_RUST_SPINE_STUB_BIN`; throws when
|
|
56
|
+
* neither is set so a missing build surfaces as a clear error rather than
|
|
57
|
+
* a confusing spawn failure. Reconciles the binary's env contract: port
|
|
58
|
+
* via `--port` (and `FUZ_RUST_SPINE_STUB_PORT`), daemon-token dir via
|
|
59
|
+
* `FUZ_RUST_SPINE_STUB_DIR` (anchored to `paths.root` so the written
|
|
60
|
+
* `{dir}/run/daemon_token` matches the path `spawn_backend` reads).
|
|
61
|
+
*
|
|
62
|
+
* @throws Error when no binary path is available.
|
|
63
|
+
*/
|
|
64
|
+
export const rust_spine_stub_backend_config = (options = {}) => {
|
|
65
|
+
const { port = RUST_SPINE_STUB_DEFAULT_PORT, database_url = RUST_SPINE_STUB_DEFAULT_DATABASE_URL, binary_path = process.env[RUST_SPINE_STUB_BIN_ENV], } = options;
|
|
66
|
+
if (!binary_path) {
|
|
67
|
+
throw new Error(`rust_spine_stub_backend_config: no binary path — set ${RUST_SPINE_STUB_BIN_ENV} to a prebuilt ` +
|
|
68
|
+
'`testing_spine_stub` binary (build it with `cargo build -p testing_spine_stub --release`) ' +
|
|
69
|
+
'or pass `binary_path`.');
|
|
70
|
+
}
|
|
71
|
+
const name = 'spine_stub';
|
|
72
|
+
const paths = build_test_backend_paths(name);
|
|
73
|
+
return make_default_rust_backend_config({
|
|
74
|
+
name,
|
|
75
|
+
port,
|
|
76
|
+
// `--port` is the binary's authoritative port input; the
|
|
77
|
+
// `FUZ_RUST_SPINE_STUB_PORT` env the builder also sets (via `port_env_var`)
|
|
78
|
+
// is the lower-precedence fallback — both carry the same value.
|
|
79
|
+
start_command: [binary_path, '--port', String(port)],
|
|
80
|
+
database_url,
|
|
81
|
+
// The stub serves `GET /api/admin/audit/stream` (the spine
|
|
82
|
+
// `fuz_realtime::SseRegistry` + audit listener), so it advertises `sse`
|
|
83
|
+
// like the TS spines — the cross-process SSE suite's three cases run. It
|
|
84
|
+
// also live-mounts `/ready` over the env-supplied fixture path, so it
|
|
85
|
+
// advertises `ready` for `describe_ready_cross_tests`.
|
|
86
|
+
capabilities: { ...rust_default_capabilities, sse: true, ready: true },
|
|
87
|
+
port_env_var: 'FUZ_RUST_SPINE_STUB_PORT',
|
|
88
|
+
rust_log: 'info,testing_spine_stub=info',
|
|
89
|
+
paths,
|
|
90
|
+
extra_env: {
|
|
91
|
+
// The binary writes its daemon-token JSON to
|
|
92
|
+
// `{FUZ_RUST_SPINE_STUB_DIR}/run/daemon_token`; anchoring the dir to
|
|
93
|
+
// `paths.root` makes that equal `paths.daemon_token_path`, which
|
|
94
|
+
// `spawn_backend` reads after the health probe.
|
|
95
|
+
FUZ_RUST_SPINE_STUB_DIR: paths.root,
|
|
96
|
+
// Absolute path to the committed spine `expected_schema.json` — the
|
|
97
|
+
// stub's `/ready` gate introspects the live DB against it. The SAME
|
|
98
|
+
// file the TS spine reads, so the two backends share one cross-impl
|
|
99
|
+
// contract.
|
|
100
|
+
[RUST_SPINE_STUB_EXPECTED_SCHEMA_PATH_ENV]: fileURLToPath(SPINE_EXPECTED_SCHEMA_URL),
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
};
|
|
@@ -3,7 +3,7 @@ import '../assert_dev_env.js';
|
|
|
3
3
|
* Cross-process `BackendConfig` presets for fuz_app's domain-free **TS**
|
|
4
4
|
* spine test binary (`src/test/cross_backend/testing_spine_server_{node,deno,bun}.ts`).
|
|
5
5
|
*
|
|
6
|
-
* The TS analog of `
|
|
6
|
+
* The TS analog of `rust_spine_stub_backend_config` (which spawns the Rust spine):
|
|
7
7
|
* these spawn fuz_app's own TS impl over real HTTP with no domain layer, so
|
|
8
8
|
* the `cross_backend_ts_node` / `cross_backend_ts_deno` / `cross_backend_ts_bun`
|
|
9
9
|
* self-test projects verify fuz_app's wire path in its own repo across all
|