@fuzdev/fuz_app 0.83.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/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 +7 -3
- 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
|
@@ -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
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ts_spine_backend_config.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/ts_spine_backend_config.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAOvD,8GAA8G;AAC9G,eAAO,MAAM,gBAAgB,6BAA6B,CAAC;AAE3D;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"ts_spine_backend_config.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/ts_spine_backend_config.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAOvD,8GAA8G;AAC9G,eAAO,MAAM,gBAAgB,6BAA6B,CAAC;AAE3D;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,4BAA4B,CAAC;AAS3D,6FAA6F;AAC7F,eAAO,MAAM,0BAA0B,OAAO,CAAC;AAE/C,iDAAiD;AACjD,eAAO,MAAM,0BAA0B,OAAO,CAAC;AAE/C,gDAAgD;AAChD,eAAO,MAAM,yBAAyB,OAAO,CAAC;AAE9C,yDAAyD;AACzD,eAAO,MAAM,mBAAmB,wDAAwD,CAAC;AAEzF,yDAAyD;AACzD,eAAO,MAAM,mBAAmB,wDAAwD,CAAC;AAEzF,wDAAwD;AACxD,eAAO,MAAM,kBAAkB,uDAAuD,CAAC;AAEvF,MAAM,WAAW,2BAA2B;IAC3C,mFAAmF;IACnF,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,8DAA8D;IAC9D,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED;;;GAGG;AACH,eAAO,MAAM,4BAA4B,GACxC,UAAS,2BAAgC,KACvC,aAgBF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,GACvC,UAAS,2BAAgC,KACvC,aAgBF,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,4BAA4B,GACxC,UAAS,2BAAgC,KACvC,aA6BF,CAAC"}
|
|
@@ -11,8 +11,12 @@ export const TS_SPINE_DIR_ENV = 'FUZ_TESTING_TS_SPINE_DIR';
|
|
|
11
11
|
* the stream, so the shared `ts_default_capabilities` stays `sse: false`.
|
|
12
12
|
*/
|
|
13
13
|
export const TS_SPINE_SSE_PATH = '/api/admin/audit/stream';
|
|
14
|
-
/**
|
|
15
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Capabilities for the TS spine binary — `ts_default_capabilities` plus `sse`
|
|
16
|
+
* (the binary wires `audit_log_sse`) and `ready` (the binary live-mounts the
|
|
17
|
+
* `/ready` deploy gate in `build_spine_app`).
|
|
18
|
+
*/
|
|
19
|
+
const ts_spine_capabilities = Object.freeze({ ...ts_default_capabilities, sse: true, ready: true });
|
|
16
20
|
/** Default port for the Node TS spine binary — slots beside the Rust `spine_stub` (1177). */
|
|
17
21
|
export const TS_SPINE_NODE_DEFAULT_PORT = 1178;
|
|
18
22
|
/** Default port for the Deno TS spine binary. */
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import './assert_dev_env.js';
|
|
2
|
+
import type { Db } from '../db/db.js';
|
|
3
|
+
import { type ExpectedSchema } from '../db/schema_ready.js';
|
|
4
|
+
/** Options for `sync_expected_schema_fixture`. */
|
|
5
|
+
export interface SyncExpectedSchemaFixtureOptions {
|
|
6
|
+
/** A bootstrapped DB — the consumer has run its full migration chain on it. */
|
|
7
|
+
db: Db;
|
|
8
|
+
/** Committed fixture location — an `import.meta.url`-relative URL or a path. */
|
|
9
|
+
fixture_url: URL | string;
|
|
10
|
+
/**
|
|
11
|
+
* When true, overwrite the fixture with the live column map instead of just
|
|
12
|
+
* reading it. Drive from an env flag (e.g. `UPDATE_SCHEMA_READY === '1'`).
|
|
13
|
+
*/
|
|
14
|
+
update?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/** The live column map and the committed fixture, for a `deepEqual` assertion. */
|
|
17
|
+
export interface SyncExpectedSchemaFixtureResult {
|
|
18
|
+
/** Columns introspected from the live, freshly-bootstrapped DB. */
|
|
19
|
+
live: Record<string, Array<string>>;
|
|
20
|
+
/** The committed fixture (re-read after writing when `update`). */
|
|
21
|
+
committed: ExpectedSchema;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Introspect the live (bootstrapped) DB's columns, write them to the committed
|
|
25
|
+
* fixture when `update`, then read the committed fixture back. The caller
|
|
26
|
+
* asserts `deepEqual(live, committed)`:
|
|
27
|
+
*
|
|
28
|
+
* ```ts
|
|
29
|
+
* const {live, committed} = await sync_expected_schema_fixture({
|
|
30
|
+
* db,
|
|
31
|
+
* fixture_url: new URL('../../lib/server/expected_schema.json', import.meta.url),
|
|
32
|
+
* update: process.env.UPDATE_SCHEMA_READY === '1',
|
|
33
|
+
* });
|
|
34
|
+
* assert.deepEqual(live, committed);
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* When `update` writes the fixture it emits raw `JSON.stringify` (one array
|
|
38
|
+
* element per line); Prettier collapses short arrays inline, so run `gro format`
|
|
39
|
+
* after `UPDATE_SCHEMA_READY=1` before committing or the format check will flag
|
|
40
|
+
* the regenerated file. (The content is identical either way — the regen test
|
|
41
|
+
* compares values, not formatting.)
|
|
42
|
+
*
|
|
43
|
+
* @returns the live column map and the committed map (post-write when `update`)
|
|
44
|
+
*/
|
|
45
|
+
export declare const sync_expected_schema_fixture: (options: SyncExpectedSchemaFixtureOptions) => Promise<SyncExpectedSchemaFixtureResult>;
|
|
46
|
+
//# sourceMappingURL=schema_ready_fixture.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema_ready_fixture.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/schema_ready_fixture.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAmB7B,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,aAAa,CAAC;AACpC,OAAO,EAAuB,KAAK,cAAc,EAAC,MAAM,uBAAuB,CAAC;AAEhF,kDAAkD;AAClD,MAAM,WAAW,gCAAgC;IAChD,+EAA+E;IAC/E,EAAE,EAAE,EAAE,CAAC;IACP,gFAAgF;IAChF,WAAW,EAAE,GAAG,GAAG,MAAM,CAAC;IAC1B;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,kFAAkF;AAClF,MAAM,WAAW,+BAA+B;IAC/C,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACpC,mEAAmE;IACnE,SAAS,EAAE,cAAc,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,4BAA4B,GACxC,SAAS,gCAAgC,KACvC,OAAO,CAAC,+BAA+B,CAQzC,CAAC"}
|