@fuzdev/fuz_app 0.89.0 → 0.91.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 (57) hide show
  1. package/dist/auth/CLAUDE.md +7 -0
  2. package/dist/auth/account_action_specs.d.ts +1 -1
  3. package/dist/auth/account_route_schema.d.ts +2 -2
  4. package/dist/auth/account_schema.d.ts +3 -3
  5. package/dist/auth/admin_action_specs.d.ts +8 -8
  6. package/dist/auth/all_cell_actions.d.ts +35 -0
  7. package/dist/auth/all_cell_actions.d.ts.map +1 -0
  8. package/dist/auth/all_cell_actions.js +32 -0
  9. package/dist/auth/audit_log_schema.d.ts +1 -1
  10. package/dist/auth/invite_schema.d.ts +2 -2
  11. package/dist/auth/signup_route_schema.d.ts +2 -2
  12. package/dist/auth/signup_route_schema.d.ts.map +1 -1
  13. package/dist/auth/signup_route_schema.js +2 -2
  14. package/dist/primitive_schemas.d.ts +27 -1
  15. package/dist/primitive_schemas.d.ts.map +1 -1
  16. package/dist/primitive_schemas.js +55 -2
  17. package/dist/server/env.d.ts +1 -1
  18. package/dist/server/env.d.ts.map +1 -1
  19. package/dist/server/env.js +15 -3
  20. package/dist/testing/CLAUDE.md +135 -10
  21. package/dist/testing/app_server.d.ts +16 -5
  22. package/dist/testing/app_server.d.ts.map +1 -1
  23. package/dist/testing/app_server.js +3 -1
  24. package/dist/testing/cross_backend/action_manifest.d.ts +113 -0
  25. package/dist/testing/cross_backend/action_manifest.d.ts.map +1 -0
  26. package/dist/testing/cross_backend/action_manifest.js +89 -0
  27. package/dist/testing/cross_backend/action_manifest_parity.d.ts +67 -0
  28. package/dist/testing/cross_backend/action_manifest_parity.d.ts.map +1 -0
  29. package/dist/testing/cross_backend/action_manifest_parity.js +88 -0
  30. package/dist/testing/cross_backend/capabilities.d.ts +47 -30
  31. package/dist/testing/cross_backend/capabilities.d.ts.map +1 -1
  32. package/dist/testing/cross_backend/capabilities.js +19 -4
  33. package/dist/testing/cross_backend/default_backend_configs.d.ts +31 -15
  34. package/dist/testing/cross_backend/default_backend_configs.d.ts.map +1 -1
  35. package/dist/testing/cross_backend/default_backend_configs.js +30 -14
  36. package/dist/testing/cross_backend/default_spine_surface.d.ts.map +1 -1
  37. package/dist/testing/cross_backend/default_spine_surface.js +6 -0
  38. package/dist/testing/cross_backend/full_spine_mount.d.ts +81 -0
  39. package/dist/testing/cross_backend/full_spine_mount.d.ts.map +1 -0
  40. package/dist/testing/cross_backend/full_spine_mount.js +49 -0
  41. package/dist/testing/cross_backend/identity_parity.d.ts +13 -0
  42. package/dist/testing/cross_backend/identity_parity.d.ts.map +1 -0
  43. package/dist/testing/cross_backend/identity_parity.js +465 -0
  44. package/dist/testing/cross_backend/method_coverage.d.ts +71 -0
  45. package/dist/testing/cross_backend/method_coverage.d.ts.map +1 -0
  46. package/dist/testing/cross_backend/method_coverage.js +89 -0
  47. package/dist/testing/cross_backend/setup.d.ts +21 -0
  48. package/dist/testing/cross_backend/setup.d.ts.map +1 -1
  49. package/dist/testing/cross_backend/setup.js +33 -1
  50. package/dist/testing/cross_backend/testing_backdoor.d.ts.map +1 -1
  51. package/dist/testing/cross_backend/testing_backdoor.js +9 -5
  52. package/dist/testing/cross_backend/testing_reset_actions.d.ts +76 -2
  53. package/dist/testing/cross_backend/testing_reset_actions.d.ts.map +1 -1
  54. package/dist/testing/cross_backend/testing_reset_actions.js +63 -2
  55. package/dist/testing/schema_generators.d.ts.map +1 -1
  56. package/dist/testing/schema_generators.js +7 -0
  57. package/package.json +2 -2
@@ -0,0 +1,88 @@
1
+ import '../assert_dev_env.js';
2
+ /** The auth axes compared as scalars (`'none' | 'optional' | 'required'`). */
3
+ const AUTH_SCALAR_FIELDS = ['account', 'actor'];
4
+ /** The auth axes compared as sorted string lists. */
5
+ const AUTH_LIST_FIELDS = ['roles', 'credential_types'];
6
+ /** Positional string-list equality (entries are pre-sorted by `build_action_manifest`). */
7
+ const string_lists_equal = (a, b) => a.length === b.length && a.every((v, i) => v === b[i]);
8
+ /**
9
+ * Structural diff between two manifests — empty array means parity holds.
10
+ *
11
+ * Order is deterministic: methods in sorted order, with each method's
12
+ * side-effect + auth-field sub-diffs grouped together.
13
+ */
14
+ export const diff_action_manifests = (a, b) => {
15
+ const diffs = [];
16
+ const a_by = new Map(a.methods.map((m) => [m.method, m]));
17
+ const b_by = new Map(b.methods.map((m) => [m.method, m]));
18
+ const all_methods = new Set([...a_by.keys(), ...b_by.keys()]);
19
+ for (const method of [...all_methods].sort()) {
20
+ const ea = a_by.get(method);
21
+ const eb = b_by.get(method);
22
+ if (!ea) {
23
+ diffs.push({ kind: 'method_only_in', where: 'b', method });
24
+ continue;
25
+ }
26
+ if (!eb) {
27
+ diffs.push({ kind: 'method_only_in', where: 'a', method });
28
+ continue;
29
+ }
30
+ if (ea.side_effects !== eb.side_effects) {
31
+ diffs.push({ kind: 'side_effects_differ', method, a: ea.side_effects, b: eb.side_effects });
32
+ }
33
+ for (const field of AUTH_SCALAR_FIELDS) {
34
+ if (ea[field] !== eb[field]) {
35
+ diffs.push({ kind: 'auth_field_differs', method, field, a: ea[field], b: eb[field] });
36
+ }
37
+ }
38
+ for (const field of AUTH_LIST_FIELDS) {
39
+ if (!string_lists_equal(ea[field], eb[field])) {
40
+ diffs.push({ kind: 'auth_field_differs', method, field, a: ea[field], b: eb[field] });
41
+ }
42
+ }
43
+ }
44
+ return diffs;
45
+ };
46
+ /**
47
+ * Render a diff list as a human-readable multi-line string. Empty diffs
48
+ * produce an empty string.
49
+ */
50
+ export const format_action_manifest_diffs = (diffs, labels = {}) => {
51
+ if (diffs.length === 0)
52
+ return '';
53
+ const label_a = labels.a ?? 'a';
54
+ const label_b = labels.b ?? 'b';
55
+ const where_label = (where) => (where === 'a' ? label_a : label_b);
56
+ const lines = [];
57
+ for (const d of diffs) {
58
+ switch (d.kind) {
59
+ case 'method_only_in':
60
+ lines.push(` method ${d.method} only in ${where_label(d.where)}`);
61
+ break;
62
+ case 'side_effects_differ':
63
+ lines.push(` ${d.method} side_effects differs: ${label_a}=${d.a}, ${label_b}=${d.b}`);
64
+ break;
65
+ case 'auth_field_differs':
66
+ lines.push(` ${d.method} auth.${d.field} differs: ${label_a}=${JSON.stringify(d.a)}, ${label_b}=${JSON.stringify(d.b)}`);
67
+ break;
68
+ default:
69
+ // Compile-time exhaustiveness — a new variant without a case here
70
+ // makes `d` non-never and fails type-check.
71
+ d;
72
+ break;
73
+ }
74
+ }
75
+ return lines.join('\n');
76
+ };
77
+ /**
78
+ * Throw if the two manifests disagree. The error message names the impls
79
+ * (via `labels`) and lists every diff, so the failure is self-diagnosing.
80
+ */
81
+ export const assert_action_manifests_equal = (a, b, labels = {}) => {
82
+ const diffs = diff_action_manifests(a, b);
83
+ if (diffs.length === 0)
84
+ return;
85
+ const label_a = labels.a ?? 'a';
86
+ const label_b = labels.b ?? 'b';
87
+ throw new Error(`Action-manifest parity failed: ${diffs.length} diff(s) between ${label_a} and ${label_b}\n${format_action_manifest_diffs(diffs, labels)}`);
88
+ };
@@ -1,40 +1,45 @@
1
1
  import '../assert_dev_env.js';
2
2
  /**
3
- * Optional behaviors a backend may support. Each flag's TSDoc names the
4
- * tests that gate on it; add a new flag here before referencing it from
5
- * a suite body, and document the gating tests inline.
3
+ * Backend wiring facts recorded for documentation — **not** gating flags.
4
+ *
5
+ * The companion to `BackendCapabilities`: where each capability flag has a
6
+ * `test_if(capabilities.X, ...)` reader that skips a suite the backend doesn't
7
+ * implement, nothing reads these. They record middleware / limiter wiring that
8
+ * differs between the TS and Rust families (a backend-shape record) but gates
9
+ * no cross test today. They live in their own type precisely so
10
+ * `BackendCapabilities` stops claiming gating power it doesn't have — fold a
11
+ * flag in here the moment it has no `test_if` reader, and promote it back the
12
+ * day a suite genuinely gates on it.
6
13
  */
7
- export interface BackendCapabilities {
14
+ export interface BackendShapeNotes {
8
15
  /**
9
- * Bearer token auth (`Authorization: Bearer <token>`) is wired through
10
- * the backend's middleware stack.
11
- *
12
- * **Declared for backend-shape documentation, not gating.** No suite reads
13
- * this flag — the bearer-token cases in `describe_standard_integration_tests`
14
- * / `describe_rate_limiting_tests` run unconditionally (every spine wires
15
- * bearer auth). Fold into a typed capability taxonomy if these gain real
16
- * gating readers.
16
+ * Bearer-token auth (`Authorization: Bearer <token>`) is wired through the
17
+ * backend's middleware stack. `true` on every spine — the bearer-token cases
18
+ * in `describe_standard_integration_tests` / `describe_rate_limiting_tests`
19
+ * run unconditionally.
17
20
  */
18
21
  readonly bearer_auth: boolean;
19
22
  /**
20
- * Trusted-proxy XFF parsing is wired (`X-Forwarded-For` etc.).
21
- *
22
- * **Declared for backend-shape documentation, not gating.** No suite reads
23
- * this flag (there is no cross-process proxy-resolution suite); it records
24
- * the proxy-default difference between the TS family (`false`) and the Rust
25
- * family (`true`). Fold into a typed capability taxonomy if it gains real
26
- * gating readers.
23
+ * Trusted-proxy XFF parsing (`X-Forwarded-For` etc.) is wired. Records the
24
+ * proxy-default difference between the TS family (`false` — the test binary
25
+ * leaves proxy parsing off) and the Rust family (`true` — the client-IP
26
+ * middleware is always wired; the env-gate only chooses XFF vs the TCP peer).
27
27
  */
28
28
  readonly trusted_proxy: boolean;
29
29
  /**
30
- * Per-account login rate limiting is wired.
31
- *
32
- * **Declared for backend-shape documentation, not gating.** No suite reads
33
- * this flag; the `describe_rate_limiting_tests` per-account cases are
34
- * in-process-only and don't cross a process boundary. Fold into a typed
35
- * capability taxonomy if it gains real gating readers.
30
+ * Per-account login rate limiting is wired. `false` for the TS family (the
31
+ * canonical path leaves the limiter null in test mode), `true` for the Rust
32
+ * family (env-gated bucket on `/login` + `/password`).
36
33
  */
37
34
  readonly login_rate_limit: boolean;
35
+ }
36
+ /**
37
+ * Optional behaviors a backend may support. Each flag's TSDoc names the
38
+ * tests that gate on it; add a new flag here before referencing it from
39
+ * a suite body, and document the gating tests inline. Wiring facts that gate
40
+ * nothing belong in `BackendShapeNotes`, not here.
41
+ */
42
+ export interface BackendCapabilities {
38
43
  /**
39
44
  * WebSocket transport is reachable end-to-end. Gates the cross-process
40
45
  * WS round-trip suite; the in-process `describe_ws_round_trip_tests`
@@ -73,10 +78,16 @@ export interface BackendCapabilities {
73
78
  * The account-lifecycle admin verbs (`account_delete` soft-delete,
74
79
  * `account_undelete` reactivation, `account_purge` keeper hard-delete)
75
80
  * are live-mounted on the backend's RPC path. Gates the dedicated
76
- * `describe_account_lifecycle_cross_tests` suite. Like cells, these
77
- * destructive/stateful verbs stay off the standard declared surface (the
78
- * generic round-trip can't drive them — they delete the subject), so
79
- * this flag opts a backend into the lifecycle parity coverage.
81
+ * `describe_account_lifecycle_cross_tests` suite.
82
+ *
83
+ * Unlike cells / fact-serving / ws / sse, these verbs **are** on the
84
+ * standard declared surface — they live in `create_admin_actions`, so
85
+ * `create_spine_surface_spec` carries them and the spec-derived round-trip
86
+ * + attack-surface suites already auto-enumerate their wire shape + auth.
87
+ * This flag gates the *behavioral* parity the generic round-trip can't
88
+ * provide: it can't drive verbs that delete their own subject (soft-delete →
89
+ * undelete round-trip, keeper-confirmed purge, the keeper-guard refusal), so
90
+ * the dedicated cross suite adds them.
80
91
  */
81
92
  readonly account_lifecycle: boolean;
82
93
  /**
@@ -136,13 +147,19 @@ export interface BackendCapabilities {
136
147
  * declare each flag explicitly per backend.
137
148
  */
138
149
  export declare const in_process_capabilities: BackendCapabilities;
150
+ /**
151
+ * Shape notes for the in-process Hono transport — every wiring fact present
152
+ * (the in-process app exercises the full middleware stack). Documentation
153
+ * only, like every `BackendShapeNotes` (nothing reads it).
154
+ */
155
+ export declare const in_process_shape_notes: BackendShapeNotes;
139
156
  /**
140
157
  * Conditional `test()` wrapper — registers a vitest case only when
141
158
  * `cond` is true; otherwise registers it as `.skip` so the run still
142
159
  * surfaces the gated coverage in the report.
143
160
  *
144
161
  * Thin wrapper around vitest's `test.skipIf(!cond)` with the argument
145
- * order flipped to match the more readable `test_if(capabilities.bearer_auth, ...)`
162
+ * order flipped to match the more readable `test_if(capabilities.ws, ...)`
146
163
  * call pattern.
147
164
  */
148
165
  export declare const test_if: (cond: boolean, name: string, fn: () => void | Promise<void>) => void;
@@ -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;AAgC9B;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IACnC;;;;;;;;;OASG;IACH,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B;;;;;;;;OAQG;IACH,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC;;;;;;;OAOG;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;IACxB;;;;;;;;OAQG;IACH,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC;;;;;;;;;;;;;;;;;OAiBG;IACH,QAAQ,CAAC,kCAAkC,EAAE,OAAO,CAAC;CACrD;AAED;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,EAAE,mBAapC,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
+ {"version":3,"file":"capabilities.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAwC9B;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,iBAAiB;IACjC;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC;;;;OAIG;IACH,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;CACnC;AAED;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;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;;;;;;;;;;;;;;OAcG;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;IACxB;;;;;;;;OAQG;IACH,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC;;;;;;;;;;;;;;;;;OAiBG;IACH,QAAQ,CAAC,kCAAkC,EAAE,OAAO,CAAC;CACrD;AAED;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,EAAE,mBAUpC,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,iBAInC,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"}
@@ -24,6 +24,14 @@ import '../assert_dev_env.js';
24
24
  * - `rust_spine_stub_capabilities` — fuz_app's Rust spine-stub preset, in
25
25
  * `rust_spine_stub_backend_config.ts` (delta off the rust family default).
26
26
  *
27
+ * **Gating flags vs shape notes.** `BackendCapabilities` holds only flags a
28
+ * suite actually gates on (each has a `test_if(capabilities.X, ...)` reader).
29
+ * Wiring facts that gate nothing — `bearer_auth` / `trusted_proxy` /
30
+ * `login_rate_limit` — live in the parallel `BackendShapeNotes` record
31
+ * (`in_process_shape_notes` here, `ts_default_shape_notes` /
32
+ * `rust_default_shape_notes` in `default_backend_configs.ts`) so the
33
+ * capability type never claims gating power it doesn't have.
34
+ *
27
35
  * @module
28
36
  */
29
37
  import { test } from 'vitest';
@@ -34,9 +42,6 @@ import { test } from 'vitest';
34
42
  * declare each flag explicitly per backend.
35
43
  */
36
44
  export const in_process_capabilities = Object.freeze({
37
- bearer_auth: true,
38
- trusted_proxy: true,
39
- login_rate_limit: true,
40
45
  ws: true,
41
46
  sse: true,
42
47
  cell_crud: true,
@@ -47,13 +52,23 @@ export const in_process_capabilities = Object.freeze({
47
52
  account_status: true,
48
53
  oversized_reject_closes_connection: true,
49
54
  });
55
+ /**
56
+ * Shape notes for the in-process Hono transport — every wiring fact present
57
+ * (the in-process app exercises the full middleware stack). Documentation
58
+ * only, like every `BackendShapeNotes` (nothing reads it).
59
+ */
60
+ export const in_process_shape_notes = Object.freeze({
61
+ bearer_auth: true,
62
+ trusted_proxy: true,
63
+ login_rate_limit: true,
64
+ });
50
65
  /**
51
66
  * Conditional `test()` wrapper — registers a vitest case only when
52
67
  * `cond` is true; otherwise registers it as `.skip` so the run still
53
68
  * surfaces the gated coverage in the report.
54
69
  *
55
70
  * Thin wrapper around vitest's `test.skipIf(!cond)` with the argument
56
- * order flipped to match the more readable `test_if(capabilities.bearer_auth, ...)`
71
+ * order flipped to match the more readable `test_if(capabilities.ws, ...)`
57
72
  * call pattern.
58
73
  */
59
74
  export const test_if = (cond, name, fn) => {
@@ -11,13 +11,15 @@ import '../assert_dev_env.js';
11
11
  *
12
12
  * Defaults baked in by family:
13
13
  *
14
- * - **TS** — `'memory://'` PGlite, 30s startup window, capabilities
15
- * without trusted_proxy/login_rate_limit. The TS canonical path
16
- * leaves these limiters null in test mode.
14
+ * - **TS** — `'memory://'` PGlite, 30s startup window. Its shape notes
15
+ * (`ts_default_shape_notes`) record `trusted_proxy: false` /
16
+ * `login_rate_limit: false` — the TS canonical path leaves those limiters
17
+ * null in test mode.
17
18
  * - **Rust** — caller-supplied real Postgres URL (PGlite isn't reachable
18
- * from `tokio-postgres`), 120s startup window (cargo first-build cost),
19
- * capabilities including trusted_proxy + login_rate_limit + the
20
- * `FUZ_TESTING_RESET_DB_ON_STARTUP=true` self-wipe gate.
19
+ * from `tokio-postgres`), 120s startup window (cargo first-build cost), the
20
+ * `FUZ_TESTING_RESET_DB_ON_STARTUP=true` self-wipe gate, and shape notes
21
+ * (`rust_default_shape_notes`) recording `trusted_proxy: true` +
22
+ * `login_rate_limit: true`.
21
23
  *
22
24
  * Both builders default `port_env_var` to `'PORT'`. Consumers whose
23
25
  * binary reads a different name (e.g. zzz's `ZZZ_PORT`) override.
@@ -31,22 +33,36 @@ import '../assert_dev_env.js';
31
33
  * @module
32
34
  */
33
35
  import type { BackendBootstrapConfig, BackendConfig } from './backend_config.js';
34
- import type { BackendCapabilities } from './capabilities.js';
36
+ import type { BackendCapabilities, BackendShapeNotes } from './capabilities.js';
35
37
  import { type TestBackendPaths } from './build_test_backend_paths.js';
36
38
  /**
37
- * Capabilities shared by TS-family backends — same canonical
38
- * implementation, same feature set. No trusted-proxy phase (the test
39
- * binary doesn't enable proxy parsing) and no per-account login rate
40
- * limit (the TS canonical path leaves the limiter null in test mode).
39
+ * Capabilities shared by TS-family backends — same canonical implementation,
40
+ * same feature set. The non-gating wiring facts (`bearer_auth` /
41
+ * `trusted_proxy` / `login_rate_limit`) live in `ts_default_shape_notes`.
41
42
  */
42
43
  export declare const ts_default_capabilities: BackendCapabilities;
43
44
  /**
44
- * Capabilities for the Rust family. Adds `trusted_proxy: true` (the
45
- * Rust spine's client-IP middleware is always wired; the env-gate just
46
- * controls whether XFF is consulted vs the TCP peer IP) and
47
- * `login_rate_limit: true` (env-gated bucket on `/login` + `/password`).
45
+ * Capabilities for the Rust family. The non-gating wiring facts live in
46
+ * `rust_default_shape_notes` (which records the family's `trusted_proxy` +
47
+ * `login_rate_limit` differences from the TS family).
48
48
  */
49
49
  export declare const rust_default_capabilities: BackendCapabilities;
50
+ /**
51
+ * Shape notes for TS-family backends — wiring facts, not gating flags.
52
+ * `trusted_proxy: false` (the test binary doesn't enable proxy parsing) and
53
+ * `login_rate_limit: false` (the TS canonical path leaves the limiter null in
54
+ * test mode); bearer auth is always wired. Documentation only — see
55
+ * `BackendShapeNotes`.
56
+ */
57
+ export declare const ts_default_shape_notes: BackendShapeNotes;
58
+ /**
59
+ * Shape notes for Rust-family backends — wiring facts, not gating flags. Adds
60
+ * `trusted_proxy: true` (the Rust spine's client-IP middleware is always wired;
61
+ * the env-gate only chooses XFF vs the TCP peer IP) and `login_rate_limit: true`
62
+ * (env-gated bucket on `/login` + `/password`). Documentation only — see
63
+ * `BackendShapeNotes`.
64
+ */
65
+ export declare const rust_default_shape_notes: BackendShapeNotes;
50
66
  export interface MakeDefaultTsBackendConfigOptions {
51
67
  /** Diagnostic label; also used as the tmpdir prefix when `paths` is omitted. */
52
68
  readonly name: string;
@@ -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,mBAoBpC,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,EAAE,mBAmBtC,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"}
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,KAAK,EAAC,sBAAsB,EAAE,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAC/E,OAAO,KAAK,EAAC,mBAAmB,EAAE,iBAAiB,EAAC,MAAM,mBAAmB,CAAC;AAC9E,OAAO,EAA2B,KAAK,gBAAgB,EAAC,MAAM,+BAA+B,CAAC;AAQ9F;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,EAAE,mBAiBpC,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,EAAE,mBAgBtC,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,EAAE,iBAInC,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,EAAE,iBAIrC,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"}
@@ -2,15 +2,11 @@ import '../assert_dev_env.js';
2
2
  import { build_test_backend_paths } from './build_test_backend_paths.js';
3
3
  import { default_test_bootstrap_token, default_test_cookie_keys, default_test_keeper_password, default_test_keeper_username, } from './default_secrets.js';
4
4
  /**
5
- * Capabilities shared by TS-family backends — same canonical
6
- * implementation, same feature set. No trusted-proxy phase (the test
7
- * binary doesn't enable proxy parsing) and no per-account login rate
8
- * limit (the TS canonical path leaves the limiter null in test mode).
5
+ * Capabilities shared by TS-family backends — same canonical implementation,
6
+ * same feature set. The non-gating wiring facts (`bearer_auth` /
7
+ * `trusted_proxy` / `login_rate_limit`) live in `ts_default_shape_notes`.
9
8
  */
10
9
  export const ts_default_capabilities = Object.freeze({
11
- bearer_auth: true,
12
- trusted_proxy: false,
13
- login_rate_limit: false,
14
10
  ws: true,
15
11
  sse: false,
16
12
  cell_crud: true,
@@ -29,15 +25,11 @@ export const ts_default_capabilities = Object.freeze({
29
25
  oversized_reject_closes_connection: true,
30
26
  });
31
27
  /**
32
- * Capabilities for the Rust family. Adds `trusted_proxy: true` (the
33
- * Rust spine's client-IP middleware is always wired; the env-gate just
34
- * controls whether XFF is consulted vs the TCP peer IP) and
35
- * `login_rate_limit: true` (env-gated bucket on `/login` + `/password`).
28
+ * Capabilities for the Rust family. The non-gating wiring facts live in
29
+ * `rust_default_shape_notes` (which records the family's `trusted_proxy` +
30
+ * `login_rate_limit` differences from the TS family).
36
31
  */
37
32
  export const rust_default_capabilities = Object.freeze({
38
- bearer_auth: true,
39
- trusted_proxy: true,
40
- login_rate_limit: true,
41
33
  ws: true,
42
34
  sse: false,
43
35
  cell_crud: true,
@@ -54,6 +46,30 @@ export const rust_default_capabilities = Object.freeze({
54
46
  // and the pipelined request is never reached.
55
47
  oversized_reject_closes_connection: true,
56
48
  });
49
+ /**
50
+ * Shape notes for TS-family backends — wiring facts, not gating flags.
51
+ * `trusted_proxy: false` (the test binary doesn't enable proxy parsing) and
52
+ * `login_rate_limit: false` (the TS canonical path leaves the limiter null in
53
+ * test mode); bearer auth is always wired. Documentation only — see
54
+ * `BackendShapeNotes`.
55
+ */
56
+ export const ts_default_shape_notes = Object.freeze({
57
+ bearer_auth: true,
58
+ trusted_proxy: false,
59
+ login_rate_limit: false,
60
+ });
61
+ /**
62
+ * Shape notes for Rust-family backends — wiring facts, not gating flags. Adds
63
+ * `trusted_proxy: true` (the Rust spine's client-IP middleware is always wired;
64
+ * the env-gate only chooses XFF vs the TCP peer IP) and `login_rate_limit: true`
65
+ * (env-gated bucket on `/login` + `/password`). Documentation only — see
66
+ * `BackendShapeNotes`.
67
+ */
68
+ export const rust_default_shape_notes = Object.freeze({
69
+ bearer_auth: true,
70
+ trusted_proxy: true,
71
+ login_rate_limit: true,
72
+ });
57
73
  /** Bootstrap block built from the default secrets + supplied paths. */
58
74
  const build_default_bootstrap = (paths, overrides) => ({
59
75
  token_path: paths.bootstrap_token_path,
@@ -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;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,CAkB/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
+ {"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,CAwB/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"}
@@ -86,6 +86,12 @@ export const create_spine_route_specs = (ctx) => [
86
86
  session_options: spine_session_options,
87
87
  ip_rate_limiter: null,
88
88
  signup_account_rate_limiter: null,
89
+ // Disable the denial floor so the identity-parity suite's accepted
90
+ // cases (valid username/email, no invite → 403 no-matching-invite)
91
+ // don't each pay the 250ms timing floor. Mirrors `login_fail_floor_ms: 0`
92
+ // above — the floor is a production timing-oracle defense, not
93
+ // behavior any cross test asserts.
94
+ signup_fail_floor_ms: 0,
89
95
  }),
90
96
  ]),
91
97
  ...(ctx.audit_sse
@@ -0,0 +1,81 @@
1
+ import '../assert_dev_env.js';
2
+ /**
3
+ * The **full** live RPC mount for fuz_app's own spine test binary — the
4
+ * complete action set `testing_spine_server.ts` exposes on a single RPC
5
+ * endpoint, in one place.
6
+ *
7
+ * Where `default_spine_surface.ts` defines the **declared** surface
8
+ * (`create_spine_surface_spec` / `spine_rpc_endpoints` — the
9
+ * `create_standard_rpc_actions` bundle the spec-derived suites
10
+ * auto-enumerate), this module defines its superset: the standard bundle
11
+ * **plus** the families the binary live-mounts but keeps off the declared
12
+ * surface —
13
+ *
14
+ * - the `_testing_*` daemon-token backdoors (`create_testing_actions`),
15
+ * - the full cell verb set (CRUD + grant + field + item + audit),
16
+ * - the opt-in `actor_lookup` / `actor_search` resolvers,
17
+ * - the `_testing_action_manifest` backdoor, appended last (it dumps the live
18
+ * method set for the cross-impl manifest-parity gate, so it must enumerate
19
+ * every method above it).
20
+ *
21
+ * Single-sourcing the mount here lets the binary, the in-process parity
22
+ * setup, and the `spine_method_coverage` reconciliation test all build the
23
+ * same list — so a method can never be mounted in one place and forgotten
24
+ * in another. The reconciliation test enumerates `build_full_spine_rpc_actions`
25
+ * with stub deps and asserts the live method set equals the tagged coverage
26
+ * manifest; see `src/test/cross_backend/spine_method_coverage.ts`.
27
+ *
28
+ * **`$lib`-free by contract** — like `default_spine_surface.ts`, this module
29
+ * is reached by the spawned TS binary under Gro's loader (which resolves
30
+ * `.js`→`.ts` but not the `$lib` alias), so every import is relative. Keep
31
+ * it that way.
32
+ *
33
+ * @module
34
+ */
35
+ import type { RpcAction } from '../../actions/action_rpc.js';
36
+ import type { AppDeps } from '../../auth/deps.js';
37
+ import type { DaemonTokenState } from '../../auth/daemon_token.js';
38
+ import type { NotificationSender } from '../../auth/role_grant_offer_notifications.js';
39
+ import type { RpcEndpointSpec } from '../../http/surface.js';
40
+ import type { AppServerContext } from '../../server/app_server_context.js';
41
+ /** Options for {@link build_full_spine_rpc_actions} / {@link full_spine_rpc_endpoints}. */
42
+ export interface FullSpineMountOptions {
43
+ /**
44
+ * Daemon-token runtime state threaded into `create_testing_actions` — the
45
+ * `_testing_reset` handler mutates `keeper_account_id` after re-seeding.
46
+ * Pass the same instance the daemon-token middleware reads. For the
47
+ * coverage test (method enumeration only, handlers never run) any stub
48
+ * state satisfies it.
49
+ */
50
+ readonly daemon_token_state: DaemonTokenState;
51
+ /**
52
+ * WS notification sender for the role-grant-offer fan-out. Pass the SAME
53
+ * `BackendWebsocketTransport` the WS endpoint registers connections against
54
+ * (the transport is the connection registry). Omitted for enumeration.
55
+ */
56
+ readonly notification_sender?: NotificationSender | null;
57
+ }
58
+ /**
59
+ * Build the complete live RPC action list the spine test binary mounts on
60
+ * its single endpoint: the declared `create_standard_rpc_actions` bundle plus
61
+ * the off-surface families (`_testing_*` backdoors, cells, actor resolvers).
62
+ *
63
+ * Mirrors the previous inline assembly in `testing_spine_server.ts` exactly —
64
+ * `session_options` is pinned to `spine_session_options` (the binary's cookie
65
+ * config) and `roles` to `spine_roles` (carrying `cell_editor`), so the only
66
+ * runtime-varying inputs are the daemon-token state + notification sender.
67
+ *
68
+ * @param deps - the backend `AppDeps` (stub deps suffice for method enumeration)
69
+ * @param options - daemon-token state + optional WS notification sender
70
+ * @returns every `RpcAction` the binary exposes, in mount order
71
+ */
72
+ export declare const build_full_spine_rpc_actions: (deps: AppDeps, options: FullSpineMountOptions) => Array<RpcAction>;
73
+ /**
74
+ * Factory-form full mount at {@link SPINE_RPC_PATH}, the shape
75
+ * `create_app_server`'s `rpc_endpoints` slot accepts. The spine binary wires
76
+ * this directly; the surface builder (`create_spine_surface_spec`) keeps using
77
+ * the narrower `spine_rpc_endpoints` so the declared surface stays the
78
+ * standard bundle only.
79
+ */
80
+ export declare const full_spine_rpc_endpoints: (ctx: AppServerContext, options: FullSpineMountOptions) => Array<RpcEndpointSpec>;
81
+ //# sourceMappingURL=full_spine_mount.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"full_spine_mount.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/full_spine_mount.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,6BAA6B,CAAC;AAC3D,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,oBAAoB,CAAC;AAChD,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,4BAA4B,CAAC;AACjE,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,8CAA8C,CAAC;AAKrF,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,oCAAoC,CAAC;AAOzE,2FAA2F;AAC3F,MAAM,WAAW,qBAAqB;IACrC;;;;;;OAMG;IACH,QAAQ,CAAC,kBAAkB,EAAE,gBAAgB,CAAC;IAC9C;;;;OAIG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;CACzD;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,4BAA4B,GACxC,MAAM,OAAO,EACb,SAAS,qBAAqB,KAC5B,KAAK,CAAC,SAAS,CAoBjB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,GACpC,KAAK,gBAAgB,EACrB,SAAS,qBAAqB,KAC5B,KAAK,CAAC,eAAe,CAEvB,CAAC"}
@@ -0,0 +1,49 @@
1
+ import '../assert_dev_env.js';
2
+ import { create_standard_rpc_actions } from '../../auth/standard_rpc_actions.js';
3
+ import { create_all_cell_actions } from '../../auth/all_cell_actions.js';
4
+ import { create_actor_lookup_actions } from '../../auth/actor_lookup_actions.js';
5
+ import { create_actor_search_actions } from '../../auth/actor_search_actions.js';
6
+ import { create_testing_action_manifest_action, create_testing_actions, } from './testing_reset_actions.js';
7
+ import { SPINE_RPC_PATH, spine_roles, spine_session_options } from './default_spine_surface.js';
8
+ /**
9
+ * Build the complete live RPC action list the spine test binary mounts on
10
+ * its single endpoint: the declared `create_standard_rpc_actions` bundle plus
11
+ * the off-surface families (`_testing_*` backdoors, cells, actor resolvers).
12
+ *
13
+ * Mirrors the previous inline assembly in `testing_spine_server.ts` exactly —
14
+ * `session_options` is pinned to `spine_session_options` (the binary's cookie
15
+ * config) and `roles` to `spine_roles` (carrying `cell_editor`), so the only
16
+ * runtime-varying inputs are the daemon-token state + notification sender.
17
+ *
18
+ * @param deps - the backend `AppDeps` (stub deps suffice for method enumeration)
19
+ * @param options - daemon-token state + optional WS notification sender
20
+ * @returns every `RpcAction` the binary exposes, in mount order
21
+ */
22
+ export const build_full_spine_rpc_actions = (deps, options) => {
23
+ const actions = [
24
+ ...create_standard_rpc_actions({ ...deps, notification_sender: options.notification_sender ?? null }, { roles: spine_roles }),
25
+ ...create_testing_actions(deps, {
26
+ session_options: spine_session_options,
27
+ daemon_token_state: options.daemon_token_state,
28
+ }),
29
+ ...create_all_cell_actions(deps, { roles: spine_roles }),
30
+ ...create_actor_lookup_actions(deps),
31
+ ...create_actor_search_actions(deps),
32
+ ];
33
+ // Append the `_testing_action_manifest` backdoor last — it closes over the
34
+ // complete `actions` list (plus its own spec) to dump the live method set
35
+ // for the cross-impl manifest-parity gate, so it must come after every
36
+ // method it enumerates.
37
+ actions.push(create_testing_action_manifest_action(actions));
38
+ return actions;
39
+ };
40
+ /**
41
+ * Factory-form full mount at {@link SPINE_RPC_PATH}, the shape
42
+ * `create_app_server`'s `rpc_endpoints` slot accepts. The spine binary wires
43
+ * this directly; the surface builder (`create_spine_surface_spec`) keeps using
44
+ * the narrower `spine_rpc_endpoints` so the declared surface stays the
45
+ * standard bundle only.
46
+ */
47
+ export const full_spine_rpc_endpoints = (ctx, options) => [
48
+ { path: SPINE_RPC_PATH, actions: build_full_spine_rpc_actions(ctx.deps, options) },
49
+ ];
@@ -0,0 +1,13 @@
1
+ import '../assert_dev_env.js';
2
+ import type { SetupTest } from './setup.js';
3
+ /** Options for the identity-primitive parity suite. */
4
+ export interface IdentityParityCrossTestOptions {
5
+ /** Per-test fixture producer (in-process or cross-process). */
6
+ readonly setup_test: SetupTest;
7
+ /** REST login route path. Default `/api/account/login` (the spine convention). */
8
+ readonly login_path?: string;
9
+ /** REST signup route path. Default `/api/account/signup` (the spine convention). */
10
+ readonly signup_path?: string;
11
+ }
12
+ export declare const describe_identity_parity_cross_tests: (options: IdentityParityCrossTestOptions) => void;
13
+ //# sourceMappingURL=identity_parity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity_parity.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/identity_parity.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAqG9B,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,YAAY,CAAC;AAkB1C,uDAAuD;AACvD,MAAM,WAAW,8BAA8B;IAC9C,+DAA+D;IAC/D,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC;IAC/B,kFAAkF;IAClF,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,oFAAoF;IACpF,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC9B;AA0JD,eAAO,MAAM,oCAAoC,GAChD,SAAS,8BAA8B,KACrC,IA2TF,CAAC"}