@fuzdev/fuz_app 0.86.0 → 0.87.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/testing/CLAUDE.md +6 -3
- package/dist/testing/cross_backend/account_lifecycle.d.ts +5 -5
- package/dist/testing/cross_backend/account_lifecycle.d.ts.map +1 -1
- package/dist/testing/cross_backend/account_lifecycle.js +1 -1
- package/dist/testing/cross_backend/actor_lookup.d.ts +5 -5
- package/dist/testing/cross_backend/actor_lookup.d.ts.map +1 -1
- package/dist/testing/cross_backend/actor_search.d.ts +3 -3
- package/dist/testing/cross_backend/actor_search.d.ts.map +1 -1
- package/dist/testing/cross_backend/app_settings.d.ts +3 -3
- package/dist/testing/cross_backend/app_settings.d.ts.map +1 -1
- package/dist/testing/cross_backend/body_size.d.ts +10 -0
- package/dist/testing/cross_backend/body_size.d.ts.map +1 -0
- package/dist/testing/cross_backend/body_size.js +137 -0
- package/dist/testing/cross_backend/body_size_smuggling.d.ts +10 -0
- package/dist/testing/cross_backend/body_size_smuggling.d.ts.map +1 -0
- package/dist/testing/cross_backend/body_size_smuggling.js +138 -0
- package/dist/testing/cross_backend/cell_cross_helpers.d.ts +0 -11
- package/dist/testing/cross_backend/cell_cross_helpers.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_crud.d.ts +2 -2
- package/dist/testing/cross_backend/cell_crud.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_crud.js +1 -1
- package/dist/testing/cross_backend/cell_grant_role.d.ts +2 -2
- package/dist/testing/cross_backend/cell_grant_role.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_grant_role.js +1 -1
- package/dist/testing/cross_backend/cell_relations.d.ts +2 -2
- package/dist/testing/cross_backend/cell_relations.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_relations.js +1 -1
- package/dist/testing/cross_backend/conformance_table.d.ts.map +1 -1
- package/dist/testing/cross_backend/conformance_table.js +8 -6
- package/dist/testing/cross_backend/fact_serving.d.ts +2 -3
- package/dist/testing/cross_backend/fact_serving.d.ts.map +1 -1
- package/dist/testing/cross_backend/origin.d.ts +5 -5
- package/dist/testing/cross_backend/origin.d.ts.map +1 -1
- package/dist/testing/cross_backend/ready.d.ts +2 -7
- package/dist/testing/cross_backend/ready.d.ts.map +1 -1
- package/dist/testing/cross_backend/setup.d.ts +28 -0
- package/dist/testing/cross_backend/setup.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_backdoor.d.ts +2 -2
- package/dist/testing/cross_backend/testing_backdoor.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/testing/CLAUDE.md
CHANGED
|
@@ -1043,9 +1043,12 @@ stays **off** `create_spine_surface_spec`, and these dedicated suites are the
|
|
|
1043
1043
|
cell validators (`describe_standard_cross_process_tests`' generic round-trip
|
|
1044
1044
|
never sees them). Both parse every success response against the verb's Zod
|
|
1045
1045
|
**output** schema, so a TS↔Rust envelope drift fails the suite — not just a
|
|
1046
|
-
payload-field drift. Call-site primitives (`
|
|
1047
|
-
`expect_output`
|
|
1048
|
-
`cross_backend/
|
|
1046
|
+
payload-field drift. Call-site primitives (`cross_rpc_call` / `error_reason` /
|
|
1047
|
+
`expect_output`) live in `cross_backend/cell_cross_helpers.ts`; the shared
|
|
1048
|
+
options shape is `RpcPathCrossSuiteOptions` from `cross_backend/setup.ts` (the
|
|
1049
|
+
neutral base every RPC-dispatched imperative cross suite aliases — origin,
|
|
1050
|
+
body-size, actor lookup/search, account lifecycle, app settings, testing
|
|
1051
|
+
backdoor, cell).
|
|
1049
1052
|
|
|
1050
1053
|
- **`describe_cell_crud_cross_tests`** (gates on `capabilities.cell_crud`) —
|
|
1051
1054
|
the create → get → update → delete → list lifecycle threading the id, plus
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import '../assert_dev_env.js';
|
|
2
|
-
import {
|
|
2
|
+
import type { RpcPathCrossSuiteOptions } from './setup.js';
|
|
3
3
|
/**
|
|
4
|
-
* Options for the account-lifecycle parity suite.
|
|
5
|
-
*
|
|
6
|
-
* `
|
|
4
|
+
* Options for the account-lifecycle parity suite. The standard
|
|
5
|
+
* RPC-dispatched cross-suite shape (`setup_test` / `capabilities` /
|
|
6
|
+
* `rpc_path`); aliases `RpcPathCrossSuiteOptions` rather than duplicating.
|
|
7
7
|
*/
|
|
8
|
-
export type AccountLifecycleCrossTestOptions =
|
|
8
|
+
export type AccountLifecycleCrossTestOptions = RpcPathCrossSuiteOptions;
|
|
9
9
|
export declare const describe_account_lifecycle_cross_tests: (options: AccountLifecycleCrossTestOptions) => void;
|
|
10
10
|
//# sourceMappingURL=account_lifecycle.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account_lifecycle.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/account_lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"account_lifecycle.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/account_lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAkC9B,OAAO,KAAK,EAAC,wBAAwB,EAAC,MAAM,YAAY,CAAC;AAGzD;;;;GAIG;AACH,MAAM,MAAM,gCAAgC,GAAG,wBAAwB,CAAC;AAExE,eAAO,MAAM,sCAAsC,GAClD,SAAS,gCAAgC,KACvC,IA+TF,CAAC"}
|
|
@@ -21,7 +21,7 @@ import { describe, assert } from 'vitest';
|
|
|
21
21
|
import { AccountDeleteOutput, AccountUndeleteOutput, AccountPurgeOutput, AdminAccountListOutput, AuditLogListOutput, ERROR_CANNOT_DELETE_KEEPER, } from '../../auth/admin_action_specs.js';
|
|
22
22
|
import { ERROR_ACCOUNT_NOT_FOUND, ERROR_AUTHENTICATION_REQUIRED } from '../../http/error_schemas.js';
|
|
23
23
|
import { test_if } from './capabilities.js';
|
|
24
|
-
import { cross_rpc_call, error_reason, expect_output
|
|
24
|
+
import { cross_rpc_call, error_reason, expect_output } from './cell_cross_helpers.js';
|
|
25
25
|
import { SPINE_RPC_PATH } from './default_spine_surface.js';
|
|
26
26
|
export const describe_account_lifecycle_cross_tests = (options) => {
|
|
27
27
|
const { setup_test, capabilities } = options;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import '../assert_dev_env.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { RpcPathCrossSuiteOptions } from './setup.js';
|
|
3
3
|
/**
|
|
4
|
-
* Options for the actor-lookup parity suite.
|
|
5
|
-
*
|
|
6
|
-
* `
|
|
4
|
+
* Options for the actor-lookup parity suite. The standard RPC-dispatched
|
|
5
|
+
* cross-suite shape (`setup_test` / `capabilities` / `rpc_path`); aliases
|
|
6
|
+
* the shared `RpcPathCrossSuiteOptions` rather than minting a duplicate.
|
|
7
7
|
*/
|
|
8
|
-
export type ActorLookupCrossTestOptions =
|
|
8
|
+
export type ActorLookupCrossTestOptions = RpcPathCrossSuiteOptions;
|
|
9
9
|
export declare const describe_actor_lookup_cross_tests: (options: ActorLookupCrossTestOptions) => void;
|
|
10
10
|
//# sourceMappingURL=actor_lookup.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actor_lookup.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/actor_lookup.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAqC9B,OAAO,KAAK,EAAC,
|
|
1
|
+
{"version":3,"file":"actor_lookup.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/actor_lookup.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAqC9B,OAAO,KAAK,EAAC,wBAAwB,EAAC,MAAM,YAAY,CAAC;AAGzD;;;;GAIG;AACH,MAAM,MAAM,2BAA2B,GAAG,wBAAwB,CAAC;AASnE,eAAO,MAAM,iCAAiC,GAAI,SAAS,2BAA2B,KAAG,IAkDxF,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import '../assert_dev_env.js';
|
|
2
|
-
import type {
|
|
3
|
-
/** Options for the actor-search parity suite (
|
|
4
|
-
export type ActorSearchCrossTestOptions =
|
|
2
|
+
import type { RpcPathCrossSuiteOptions } from './setup.js';
|
|
3
|
+
/** Options for the actor-search parity suite (the standard RPC-dispatched shape). */
|
|
4
|
+
export type ActorSearchCrossTestOptions = RpcPathCrossSuiteOptions;
|
|
5
5
|
export declare const describe_actor_search_cross_tests: (options: ActorSearchCrossTestOptions) => void;
|
|
6
6
|
//# sourceMappingURL=actor_search.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actor_search.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/actor_search.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AA2C9B,OAAO,KAAK,EAAC,
|
|
1
|
+
{"version":3,"file":"actor_search.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/actor_search.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AA2C9B,OAAO,KAAK,EAAC,wBAAwB,EAAC,MAAM,YAAY,CAAC;AAGzD,qFAAqF;AACrF,MAAM,MAAM,2BAA2B,GAAG,wBAAwB,CAAC;AASnE,eAAO,MAAM,iCAAiC,GAAI,SAAS,2BAA2B,KAAG,IAyDxF,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import '../assert_dev_env.js';
|
|
2
|
-
import type {
|
|
3
|
-
/** Options for the app-settings effect suite (
|
|
4
|
-
export type AppSettingsCrossTestOptions =
|
|
2
|
+
import type { RpcPathCrossSuiteOptions } from './setup.js';
|
|
3
|
+
/** Options for the app-settings effect suite (the standard RPC-dispatched shape). */
|
|
4
|
+
export type AppSettingsCrossTestOptions = RpcPathCrossSuiteOptions;
|
|
5
5
|
export declare const describe_app_settings_cross_tests: (options: AppSettingsCrossTestOptions) => void;
|
|
6
6
|
//# sourceMappingURL=app_settings.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app_settings.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/app_settings.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAsC9B,OAAO,KAAK,EAAC,
|
|
1
|
+
{"version":3,"file":"app_settings.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/app_settings.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAsC9B,OAAO,KAAK,EAAC,wBAAwB,EAAC,MAAM,YAAY,CAAC;AAGzD,qFAAqF;AACrF,MAAM,MAAM,2BAA2B,GAAG,wBAAwB,CAAC;AAiBnE,eAAO,MAAM,iCAAiC,GAAI,SAAS,2BAA2B,KAAG,IA8DxF,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import '../assert_dev_env.js';
|
|
2
|
+
import type { RpcPathCrossSuiteOptions } from './setup.js';
|
|
3
|
+
/**
|
|
4
|
+
* Options for the body-size parity suite — the standard RPC-dispatched
|
|
5
|
+
* cross-suite shape (`setup_test` / `capabilities` / `rpc_path`); aliases the
|
|
6
|
+
* shared `RpcPathCrossSuiteOptions` rather than minting a duplicate.
|
|
7
|
+
*/
|
|
8
|
+
export type BodySizeCrossTestOptions = RpcPathCrossSuiteOptions;
|
|
9
|
+
export declare const describe_body_size_cross_tests: (options: BodySizeCrossTestOptions) => void;
|
|
10
|
+
//# sourceMappingURL=body_size.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"body_size.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/body_size.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AA6D9B,OAAO,KAAK,EAAC,wBAAwB,EAAC,MAAM,YAAY,CAAC;AAGzD;;;;GAIG;AACH,MAAM,MAAM,wBAAwB,GAAG,wBAAwB,CAAC;AAmDhE,eAAO,MAAM,8BAA8B,GAAI,SAAS,wBAAwB,KAAG,IA0ClF,CAAC"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import '../assert_dev_env.js';
|
|
2
|
+
/**
|
|
3
|
+
* Cross-backend parity suite for the request body-size limit.
|
|
4
|
+
*
|
|
5
|
+
* `create_app_server` (TS) and the Rust spine both cap the request body at a
|
|
6
|
+
* 1 MiB default (`DEFAULT_MAX_BODY_SIZE` / `fuz_http`'s
|
|
7
|
+
* `DEFAULT_BODY_LIMIT_BYTES`) and reject oversized payloads with `413` and the
|
|
8
|
+
* canonical flat REST body `{error: 'payload_too_large'}` — *before* auth,
|
|
9
|
+
* origin, or dispatch run (middleware step 4). Each impl unit-tests this in
|
|
10
|
+
* isolation, but nothing fires an oversized POST over the wire, so the
|
|
11
|
+
* cross-impl agreement on the status + body shape (and on the exact `>` cap
|
|
12
|
+
* boundary, not an off-by-one divergence) was unpinned. Three cases:
|
|
13
|
+
*
|
|
14
|
+
* - **over-limit POST (cap + 1 byte) → 413** `payload_too_large`, refused
|
|
15
|
+
* before any handler runs (the limit fires ahead of origin verification + the
|
|
16
|
+
* dispatcher, so an over-cap body is rejected regardless of how well-formed it
|
|
17
|
+
* is). Exactly one byte over — both impls reject on a strict `>`, so this is
|
|
18
|
+
* the tight upper boundary, and staying just over keeps it clear of any
|
|
19
|
+
* larger framework-default limit that would answer with a different body.
|
|
20
|
+
* - **at-limit POST (exactly the cap) → not 413** — one byte under the
|
|
21
|
+
* rejection threshold passes the size gate and reaches the dispatcher (the
|
|
22
|
+
* downstream status is irrelevant; only "not size-rejected" is asserted). The
|
|
23
|
+
* boundary sibling of the case above.
|
|
24
|
+
* - **under-limit POST (small) → 200** — a small, well-formed authenticated
|
|
25
|
+
* `account_verify` envelope sails through to a successful handler response,
|
|
26
|
+
* the positive control that the route works for normal traffic.
|
|
27
|
+
*
|
|
28
|
+
* **Real-socket connection hazard (cross-process only).** When the server caps
|
|
29
|
+
* the body it answers 413 and closes the connection *before* the client
|
|
30
|
+
* finishes uploading — correct HTTP, since an unread request body can't share a
|
|
31
|
+
* keep-alive socket. The client's pool can then hand that now-dead socket to
|
|
32
|
+
* the very next request (observed as `other side closed`). So every request
|
|
33
|
+
* here goes through `fetch_retrying_once`: a request that inherits the poisoned
|
|
34
|
+
* socket retries onto a fresh connection, which both keeps the suite
|
|
35
|
+
* deterministic *and* evicts the dead socket so it can't strand a later cross
|
|
36
|
+
* suite in the same process. In-process (`app.request`) has no socket, so the
|
|
37
|
+
* hazard is cross-process-only and the retry never fires there.
|
|
38
|
+
*
|
|
39
|
+
* Like origin/payload rejection, this is middleware-level flat REST — not the
|
|
40
|
+
* JSON-RPC envelope the conformance-table runner expects — so it's an
|
|
41
|
+
* imperative suite, not a `conformance_table` row. Runs both legs via the
|
|
42
|
+
* shared `{setup_test, capabilities}` protocol: the in-process leg
|
|
43
|
+
* (`auth/body_size_parity.db.test.ts`, plain `gro test`) and the cross-process
|
|
44
|
+
* leg (`cross_backend/body_size.cross.test.ts`, the TS spine binaries + Rust
|
|
45
|
+
* `testing_spine_stub` over real HTTP). The body-size limit is on every spine,
|
|
46
|
+
* so the suite is ungated.
|
|
47
|
+
*
|
|
48
|
+
* Cited property: `docs/security.md` §"Body Size Limiting".
|
|
49
|
+
*
|
|
50
|
+
* `$lib`-free by contract (relative specifiers only), like the sibling
|
|
51
|
+
* cross-backend suites.
|
|
52
|
+
*
|
|
53
|
+
* @module
|
|
54
|
+
*/
|
|
55
|
+
import { describe, test, assert } from 'vitest';
|
|
56
|
+
import { account_verify_action_spec } from '../../auth/account_action_specs.js';
|
|
57
|
+
import { ERROR_PAYLOAD_TOO_LARGE } from '../../http/error_schemas.js';
|
|
58
|
+
import { SPINE_RPC_PATH } from './default_spine_surface.js';
|
|
59
|
+
/**
|
|
60
|
+
* The shared 1 MiB default both impls ship (`DEFAULT_MAX_BODY_SIZE` in TS,
|
|
61
|
+
* `DEFAULT_BODY_LIMIT_BYTES` in `fuz_http`). Kept as a local cross-impl
|
|
62
|
+
* contract value rather than imported from either impl — the boundary it
|
|
63
|
+
* pins is the shared default, and a change to either is a deliberate
|
|
64
|
+
* cross-impl decision that would revisit this suite regardless.
|
|
65
|
+
*/
|
|
66
|
+
const BODY_LIMIT_DEFAULT_BYTES = 1024 * 1024;
|
|
67
|
+
/**
|
|
68
|
+
* Build an `account_verify` JSON-RPC envelope whose serialized length is
|
|
69
|
+
* *exactly* `target_bytes`, by growing a `params.pad` string to fill. Every
|
|
70
|
+
* character is ASCII, so the string length equals the UTF-8 byte length equals
|
|
71
|
+
* the `Content-Length` the transport sends — which is what the body-size
|
|
72
|
+
* middleware measures. `account_verify` takes no params, but at/over the cap
|
|
73
|
+
* the size check fires before input validation, so the padded shape is never
|
|
74
|
+
* reached on the rejection path.
|
|
75
|
+
*/
|
|
76
|
+
const sized_envelope = (id, target_bytes) => {
|
|
77
|
+
const method = account_verify_action_spec.method;
|
|
78
|
+
const base = JSON.stringify({ jsonrpc: '2.0', method, id, params: { pad: '' } });
|
|
79
|
+
const pad = 'x'.repeat(Math.max(0, target_bytes - base.length));
|
|
80
|
+
return JSON.stringify({ jsonrpc: '2.0', method, id, params: { pad } });
|
|
81
|
+
};
|
|
82
|
+
/** A small, well-formed nullary `account_verify` body — well under the cap. */
|
|
83
|
+
const small_envelope = (id) => JSON.stringify({ jsonrpc: '2.0', method: account_verify_action_spec.method, id });
|
|
84
|
+
/**
|
|
85
|
+
* Issue a request, retrying once if the call *throws* (vs. returning a
|
|
86
|
+
* response). A request handed the keep-alive socket the server closed on an
|
|
87
|
+
* oversized-body rejection fails at the transport layer before any response;
|
|
88
|
+
* one retry opens a fresh connection (and drops the dead socket from the
|
|
89
|
+
* pool). Keyed on "threw at all" rather than a specific error code so it holds
|
|
90
|
+
* across the node / deno / bun cross runtimes, which surface different errors.
|
|
91
|
+
*/
|
|
92
|
+
const fetch_retrying_once = async (transport, path, init) => {
|
|
93
|
+
try {
|
|
94
|
+
return await transport(path, init);
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return await transport(path, init);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
export const describe_body_size_cross_tests = (options) => {
|
|
101
|
+
const { setup_test } = options;
|
|
102
|
+
const rpc_path = options.rpc_path ?? SPINE_RPC_PATH;
|
|
103
|
+
/** POST `body` to the RPC path as the keeper, retry-once on a dead socket. */
|
|
104
|
+
const post = (fixture, body) => fetch_retrying_once(fixture.transport, rpc_path, {
|
|
105
|
+
method: 'POST',
|
|
106
|
+
headers: { ...fixture.create_session_headers(), 'content-type': 'application/json' },
|
|
107
|
+
body,
|
|
108
|
+
});
|
|
109
|
+
describe('body-size limit parity', () => {
|
|
110
|
+
test('over-limit POST (cap + 1) → 413 payload_too_large (refused before dispatch)', async () => {
|
|
111
|
+
const fixture = await setup_test();
|
|
112
|
+
// Keeper session cookie + the transport's default allowed Origin, so
|
|
113
|
+
// neither auth nor origin is the cause — only the body size. One byte
|
|
114
|
+
// over the cap: both impls reject on a strict `>`.
|
|
115
|
+
const res = await post(fixture, sized_envelope('over-limit', BODY_LIMIT_DEFAULT_BYTES + 1));
|
|
116
|
+
assert.strictEqual(res.status, 413, 'a body one byte over the cap must be rejected with 413');
|
|
117
|
+
const body = (await res.json().catch(() => undefined));
|
|
118
|
+
assert.strictEqual(body?.error, ERROR_PAYLOAD_TOO_LARGE);
|
|
119
|
+
});
|
|
120
|
+
test('at-limit POST (exactly the cap) → not size-rejected', async () => {
|
|
121
|
+
const fixture = await setup_test();
|
|
122
|
+
// Exactly at the cap is one byte under the `>` threshold, so it clears
|
|
123
|
+
// the size gate and reaches the dispatcher. Whatever the dispatcher
|
|
124
|
+
// then returns, it must not be the 413 — that's the lower boundary.
|
|
125
|
+
const res = await post(fixture, sized_envelope('at-limit', BODY_LIMIT_DEFAULT_BYTES));
|
|
126
|
+
assert.notStrictEqual(res.status, 413, 'a body exactly at the cap must not be size-rejected');
|
|
127
|
+
});
|
|
128
|
+
test('under-limit POST (small) → 200', async () => {
|
|
129
|
+
const fixture = await setup_test();
|
|
130
|
+
// Small well-formed body: clears the cap and reaches the
|
|
131
|
+
// `account_verify` handler, the positive control that normal traffic
|
|
132
|
+
// passes (and the 413 above is size-gated, not a blanket rejection).
|
|
133
|
+
const res = await post(fixture, small_envelope('under-limit'));
|
|
134
|
+
assert.strictEqual(res.status, 200, 'an under-limit authenticated request must pass');
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import '../assert_dev_env.js';
|
|
2
|
+
/** Options for the smuggling probe — needs the raw URL, not a transport. */
|
|
3
|
+
export interface BodySizeSmugglingCrossTestOptions {
|
|
4
|
+
/** Base URL the spawned backend is reachable at (e.g. `http://localhost:1178`). */
|
|
5
|
+
readonly base_url: string;
|
|
6
|
+
/** RPC endpoint path to target. Default `/api/rpc`. */
|
|
7
|
+
readonly rpc_path?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare const describe_body_size_smuggling_cross_tests: (options: BodySizeSmugglingCrossTestOptions) => void;
|
|
10
|
+
//# sourceMappingURL=body_size_smuggling.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"body_size_smuggling.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/body_size_smuggling.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAkD9B,4EAA4E;AAC5E,MAAM,WAAW,iCAAiC;IACjD,mFAAmF;IACnF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,uDAAuD;IACvD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC3B;AAqDD,eAAO,MAAM,wCAAwC,GACpD,SAAS,iCAAiC,KACxC,IA4DF,CAAC"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import '../assert_dev_env.js';
|
|
2
|
+
/**
|
|
3
|
+
* Cross-backend request-smuggling probe for the body-size limit's connection
|
|
4
|
+
* handling — the security sibling of `body_size.ts`.
|
|
5
|
+
*
|
|
6
|
+
* When the server caps the request body it answers `413` on the
|
|
7
|
+
* `Content-Length` header and closes the connection *without reading the
|
|
8
|
+
* oversized body*. That close is load-bearing: HTTP/1.1 forbids reusing a
|
|
9
|
+
* keep-alive connection whose request body wasn't consumed, because the unread
|
|
10
|
+
* body bytes would otherwise be parsed as the start of the next request — a
|
|
11
|
+
* classic request-smuggling vector. This suite proves the mitigation holds end
|
|
12
|
+
* to end by **pipelining**: it opens a raw TCP socket and sends, in one write,
|
|
13
|
+
* an oversized `POST` immediately followed by a second `GET` request. A correct
|
|
14
|
+
* server rejects the POST with `413` and never processes the trailing GET (the
|
|
15
|
+
* connection closes with the GET bytes unconsumed); a vulnerable one would
|
|
16
|
+
* drain past the body and answer the smuggled GET too. The assertion is
|
|
17
|
+
* therefore "**at most one** HTTP response comes back" — a *second* response is
|
|
18
|
+
* the smuggle. It's `<= 1` rather than "exactly the 413" because the impls close
|
|
19
|
+
* differently at the TCP level (node-server graceful close delivers the 413
|
|
20
|
+
* first; hyper's RST can drop the in-flight 413 before the client reads it), so
|
|
21
|
+
* demanding a cleanly-read 413 would be flaky; the 413-ness itself is pinned
|
|
22
|
+
* reliably over `fetch` by `describe_body_size_cross_tests`. A **positive
|
|
23
|
+
* control** (two pipelined requests → >= 2 responses) proves a second response
|
|
24
|
+
* *would* be seen if the trailing request were processed — without it the
|
|
25
|
+
* `<= 1` assertion would be vacuous on a server that never reuses connections,
|
|
26
|
+
* and it also proves the response counter isn't undercounting.
|
|
27
|
+
*
|
|
28
|
+
* Raw-socket by necessity (the `FetchTransport` can't pipeline two requests on
|
|
29
|
+
* one connection), so — unlike `body_size.ts` — this is **cross-process only**
|
|
30
|
+
* (no in-process leg; there is no socket in-process) and ungated (the limit is
|
|
31
|
+
* on every spine). Robust by construction: it counts responses until the
|
|
32
|
+
* socket closes or a short read timeout, so a server that closes (the expected
|
|
33
|
+
* path) and one that merely holds the connection open without smuggling both
|
|
34
|
+
* read as one response; only an actual second response fails.
|
|
35
|
+
*
|
|
36
|
+
* Cited property: `docs/security.md` §"Body Size Limiting" (connection close on
|
|
37
|
+
* oversized reject).
|
|
38
|
+
*
|
|
39
|
+
* `$lib`-free by contract (relative + `node:` specifiers only).
|
|
40
|
+
*
|
|
41
|
+
* @module
|
|
42
|
+
*/
|
|
43
|
+
import { connect } from 'node:net';
|
|
44
|
+
import { describe, test, assert } from 'vitest';
|
|
45
|
+
import { SPINE_RPC_PATH } from './default_spine_surface.js';
|
|
46
|
+
/** The shared 1 MiB cap (see `body_size.ts` for why it's a local constant). */
|
|
47
|
+
const BODY_LIMIT_DEFAULT_BYTES = 1024 * 1024;
|
|
48
|
+
/**
|
|
49
|
+
* Open a raw TCP socket to `base_url`, write `request_bytes` once, and collect
|
|
50
|
+
* everything the server sends back until it closes the connection or
|
|
51
|
+
* `read_timeout_ms` elapses. Write errors are swallowed: the server closing
|
|
52
|
+
* mid-upload (the correct response to an oversized body) surfaces as
|
|
53
|
+
* `EPIPE`/`ECONNRESET` on our unfinished write, which is exactly the behavior
|
|
54
|
+
* under test — what matters is what we *read back*.
|
|
55
|
+
*/
|
|
56
|
+
const send_raw = (base_url, request_bytes, read_timeout_ms) => new Promise((resolve) => {
|
|
57
|
+
const url = new URL(base_url);
|
|
58
|
+
const port = Number(url.port) || (url.protocol === 'https:' ? 443 : 80);
|
|
59
|
+
const socket = connect({ host: url.hostname, port });
|
|
60
|
+
let received = '';
|
|
61
|
+
let settled = false;
|
|
62
|
+
const finish = () => {
|
|
63
|
+
if (settled)
|
|
64
|
+
return;
|
|
65
|
+
settled = true;
|
|
66
|
+
clearTimeout(timer);
|
|
67
|
+
socket.destroy();
|
|
68
|
+
resolve(received);
|
|
69
|
+
};
|
|
70
|
+
const timer = setTimeout(finish, read_timeout_ms);
|
|
71
|
+
socket.setEncoding('latin1');
|
|
72
|
+
socket.on('connect', () => socket.write(request_bytes));
|
|
73
|
+
socket.on('data', (chunk) => {
|
|
74
|
+
received += chunk;
|
|
75
|
+
});
|
|
76
|
+
socket.on('error', () => { }); // EPIPE/ECONNRESET on mid-write close is expected
|
|
77
|
+
socket.on('close', finish);
|
|
78
|
+
});
|
|
79
|
+
/**
|
|
80
|
+
* Count HTTP response status lines in a raw byte stream. Deliberately
|
|
81
|
+
* **unanchored** (no `^`/`m`): a second pipelined response is concatenated
|
|
82
|
+
* straight after the first response's body, which carries no trailing newline,
|
|
83
|
+
* so a line-anchored match would miss it — and missing a smuggled second
|
|
84
|
+
* response is a silent false negative. No response header or JSON error body
|
|
85
|
+
* contains the literal `HTTP/1.x NNN`, so an unanchored match counts exactly
|
|
86
|
+
* the status lines. The positive control below proves this counts 2 when the
|
|
87
|
+
* server genuinely returns 2.
|
|
88
|
+
*/
|
|
89
|
+
const count_responses = (raw) => (raw.match(/HTTP\/1\.[01] \d{3}/g) ?? []).length;
|
|
90
|
+
export const describe_body_size_smuggling_cross_tests = (options) => {
|
|
91
|
+
const { base_url } = options;
|
|
92
|
+
const rpc_path = options.rpc_path ?? SPINE_RPC_PATH;
|
|
93
|
+
const host = new URL(base_url).host;
|
|
94
|
+
describe('body-size limit — request-smuggling resistance', () => {
|
|
95
|
+
// Positive control: prove the server returns >1 response on a single
|
|
96
|
+
// connection. Without this the smuggling assertion below would be
|
|
97
|
+
// vacuously green on a server that simply never reuses connections — and
|
|
98
|
+
// it also validates `count_responses` actually counts a second response.
|
|
99
|
+
test('control: two pipelined requests → ≥2 responses (connection reuse is real)', async () => {
|
|
100
|
+
const two_requests = `GET ${rpc_path} HTTP/1.1\r\nHost: ${host}\r\n\r\n` +
|
|
101
|
+
`GET ${rpc_path} HTTP/1.1\r\nHost: ${host}\r\nConnection: close\r\n\r\n`;
|
|
102
|
+
const response = await send_raw(base_url, two_requests, 2000);
|
|
103
|
+
const n = count_responses(response);
|
|
104
|
+
assert.ok(n >= 2, `expected ≥2 responses on one keep-alive connection (got ${n}); without ` +
|
|
105
|
+
`connection reuse — or with an undercounting matcher — the smuggling ` +
|
|
106
|
+
`assertion below is not a real signal. Raw head: ${response.slice(0, 120)}`);
|
|
107
|
+
});
|
|
108
|
+
test('oversized POST + pipelined GET → smuggled request not processed', async () => {
|
|
109
|
+
const oversized_len = BODY_LIMIT_DEFAULT_BYTES + 1024;
|
|
110
|
+
// One write: an over-cap POST (rejected on Content-Length, body never
|
|
111
|
+
// read) immediately followed by a GET. If the server wrongly drained
|
|
112
|
+
// the unread body it would reach + answer this GET — a smuggle.
|
|
113
|
+
const payload = `POST ${rpc_path} HTTP/1.1\r\n` +
|
|
114
|
+
`Host: ${host}\r\n` +
|
|
115
|
+
`Content-Type: application/json\r\n` +
|
|
116
|
+
`Content-Length: ${oversized_len}\r\n` +
|
|
117
|
+
`\r\n` +
|
|
118
|
+
'x'.repeat(oversized_len) +
|
|
119
|
+
`GET ${rpc_path} HTTP/1.1\r\nHost: ${host}\r\n\r\n`;
|
|
120
|
+
const response = await send_raw(base_url, payload, 2000);
|
|
121
|
+
// The security property is "the pipelined GET is not processed", i.e.
|
|
122
|
+
// **at most one** response comes back (the 413, or none if the close
|
|
123
|
+
// raced the read). A *second* response is the smuggle. We assert `<= 1`
|
|
124
|
+
// rather than "exactly the 413" because the two impls close the
|
|
125
|
+
// connection differently at the TCP level — node-server closes
|
|
126
|
+
// gracefully (the 413 is delivered first), hyper sends an RST that can
|
|
127
|
+
// drop the in-flight 413 before the client reads it — and demanding a
|
|
128
|
+
// cleanly-read 413 here would be flaky. That the oversized body is
|
|
129
|
+
// rejected *with* a 413 is pinned reliably (over `fetch`) by
|
|
130
|
+
// `describe_body_size_cross_tests`; this test owns only the no-smuggle
|
|
131
|
+
// half. The control above proves a second response *would* be seen if
|
|
132
|
+
// the GET were processed, so `<= 1` is a real signal, not a vacuous one.
|
|
133
|
+
const n = count_responses(response);
|
|
134
|
+
assert.ok(n <= 1, `expected at most one response (the GET must not be smuggled in off the ` +
|
|
135
|
+
`unread body); a second response means it was. Saw ${n}. Raw head: ${response.slice(0, 120)}`);
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
};
|
|
@@ -1,17 +1,6 @@
|
|
|
1
1
|
import '../assert_dev_env.js';
|
|
2
2
|
import type { z } from 'zod';
|
|
3
3
|
import type { FetchTransport } from '../transports/fetch_transport.js';
|
|
4
|
-
import type { BackendCapabilities } from './capabilities.js';
|
|
5
|
-
import type { SetupTest } from './setup.js';
|
|
6
|
-
/** Shared options for the cell cross-backend parity suites. */
|
|
7
|
-
export interface CellCrossTestOptions {
|
|
8
|
-
/** Per-test fixture-producing function (fresh keeper + db per call). */
|
|
9
|
-
readonly setup_test: SetupTest;
|
|
10
|
-
/** Backend capability declarations — each suite gates on its own flag. */
|
|
11
|
-
readonly capabilities: BackendCapabilities;
|
|
12
|
-
/** RPC endpoint path the cell verbs are mounted on. Default `/api/rpc`. */
|
|
13
|
-
readonly rpc_path?: string;
|
|
14
|
-
}
|
|
15
4
|
/** Minimal JSON-RPC envelope shape the suites read off responses. */
|
|
16
5
|
export interface RpcResult {
|
|
17
6
|
readonly ok: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cell_cross_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/cell_cross_helpers.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAmB9B,OAAO,KAAK,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAG3B,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"cell_cross_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/cell_cross_helpers.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAmB9B,OAAO,KAAK,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAG3B,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,kCAAkC,CAAC;AAErE,qEAAqE;AACrE,MAAM,WAAW,SAAS;IACzB,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAC,CAAC;CAC5F;AAED;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAC1B,WAAW,cAAc,EACzB,MAAM,MAAM,EACZ,QAAQ,MAAM,EACd,QAAQ,OAAO,EACf,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAC7B,OAAO,CAAC,SAAS,CAMnB,CAAC;AAEF,gFAAgF;AAChF,eAAO,MAAM,YAAY,GAAI,GAAG,SAAS,KAAG,OAG/B,CAAC;AAEd;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAI,CAAC,EAAE,GAAG,SAAS,EAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAG,CAQrE,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import '../assert_dev_env.js';
|
|
2
|
-
import {
|
|
3
|
-
export declare const describe_cell_crud_cross_tests: (options:
|
|
2
|
+
import type { RpcPathCrossSuiteOptions } from './setup.js';
|
|
3
|
+
export declare const describe_cell_crud_cross_tests: (options: RpcPathCrossSuiteOptions) => void;
|
|
4
4
|
//# sourceMappingURL=cell_crud.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cell_crud.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/cell_crud.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"cell_crud.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/cell_crud.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAsD9B,OAAO,KAAK,EAAC,wBAAwB,EAAC,MAAM,YAAY,CAAC;AAGzD,eAAO,MAAM,8BAA8B,GAAI,SAAS,wBAAwB,KAAG,IAwSlF,CAAC"}
|
|
@@ -42,7 +42,7 @@ import '../assert_dev_env.js';
|
|
|
42
42
|
import { describe, assert } from 'vitest';
|
|
43
43
|
import { CellCreateOutput, CellDeleteOutput, CellGetOutput, CellListOutput, CellUpdateOutput, } from '../../auth/cell_action_specs.js';
|
|
44
44
|
import { test_if } from './capabilities.js';
|
|
45
|
-
import { cross_rpc_call, error_reason, expect_output
|
|
45
|
+
import { cross_rpc_call, error_reason, expect_output } from './cell_cross_helpers.js';
|
|
46
46
|
import { SPINE_RPC_PATH } from './default_spine_surface.js';
|
|
47
47
|
export const describe_cell_crud_cross_tests = (options) => {
|
|
48
48
|
const { setup_test, capabilities } = options;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import '../assert_dev_env.js';
|
|
2
|
-
import {
|
|
2
|
+
import type { RpcPathCrossSuiteOptions } from './setup.js';
|
|
3
3
|
/** App role the holder is seeded with; matches the spine's registered role. */
|
|
4
4
|
export declare const CELL_EDITOR_ROLE = "cell_editor";
|
|
5
5
|
/** Username the fixture seeds (via `extra_accounts`) holding `CELL_EDITOR_ROLE`. */
|
|
6
6
|
export declare const CELL_ROLE_HOLDER_USERNAME = "cell_role_holder";
|
|
7
|
-
export declare const describe_cell_grant_role_cross_tests: (options:
|
|
7
|
+
export declare const describe_cell_grant_role_cross_tests: (options: RpcPathCrossSuiteOptions) => void;
|
|
8
8
|
//# sourceMappingURL=cell_grant_role.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cell_grant_role.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/cell_grant_role.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"cell_grant_role.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/cell_grant_role.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AA8C9B,OAAO,KAAK,EAAC,wBAAwB,EAAC,MAAM,YAAY,CAAC;AAGzD,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,gBAAyB,CAAC;AAEvD,oFAAoF;AACpF,eAAO,MAAM,yBAAyB,qBAAqB,CAAC;AAK5D,eAAO,MAAM,oCAAoC,GAAI,SAAS,wBAAwB,KAAG,IAuIxF,CAAC"}
|
|
@@ -37,7 +37,7 @@ import { describe, assert } from 'vitest';
|
|
|
37
37
|
import { CellCreateOutput, CellGetOutput, CellUpdateOutput } from '../../auth/cell_action_specs.js';
|
|
38
38
|
import { CellGrantCreateOutput, ERROR_CELL_GRANT_UNKNOWN_ROLE, } from '../../auth/cell_grant_action_specs.js';
|
|
39
39
|
import { test_if } from './capabilities.js';
|
|
40
|
-
import { cross_rpc_call, error_reason, expect_output
|
|
40
|
+
import { cross_rpc_call, error_reason, expect_output } from './cell_cross_helpers.js';
|
|
41
41
|
import { SPINE_CELL_EDITOR_ROLE, SPINE_RPC_PATH } from './default_spine_surface.js';
|
|
42
42
|
/** App role the holder is seeded with; matches the spine's registered role. */
|
|
43
43
|
export const CELL_EDITOR_ROLE = SPINE_CELL_EDITOR_ROLE;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import '../assert_dev_env.js';
|
|
2
|
-
import {
|
|
3
|
-
export declare const describe_cell_relations_cross_tests: (options:
|
|
2
|
+
import type { RpcPathCrossSuiteOptions } from './setup.js';
|
|
3
|
+
export declare const describe_cell_relations_cross_tests: (options: RpcPathCrossSuiteOptions) => void;
|
|
4
4
|
//# sourceMappingURL=cell_relations.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cell_relations.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/cell_relations.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"cell_relations.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/cell_relations.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAqF9B,OAAO,KAAK,EAAC,wBAAwB,EAAC,MAAM,YAAY,CAAC;AAsFzD,eAAO,MAAM,mCAAmC,GAAI,SAAS,wBAAwB,KAAG,IAyvBvF,CAAC"}
|
|
@@ -60,7 +60,7 @@ import { CellFieldDeleteOutput, CellFieldListOutput, CellFieldSetOutput, } from
|
|
|
60
60
|
import { CellItemDeleteOutput, CellItemInsertOutput, CellItemListOutput, CellItemMoveOutput, } from '../../auth/cell_item_action_specs.js';
|
|
61
61
|
import { CellAuditListOutput } from '../../auth/cell_audit_action_specs.js';
|
|
62
62
|
import { test_if } from './capabilities.js';
|
|
63
|
-
import { cross_rpc_call, error_reason, expect_output
|
|
63
|
+
import { cross_rpc_call, error_reason, expect_output } from './cell_cross_helpers.js';
|
|
64
64
|
import { SPINE_RPC_PATH } from './default_spine_surface.js';
|
|
65
65
|
/** Create a cell over the wire and return its id (the parity gate parses the output). */
|
|
66
66
|
const create_cell = async (t, rpc_path, h, params) => expect_output(await cross_rpc_call(t, rpc_path, 'cell_create', params, h), CellCreateOutput).cell
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conformance_table.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/conformance_table.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAwB9B,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,uBAAuB,CAAC;AAE1D,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,8BAA8B,CAAC;AAMjE,OAAO,EAIN,KAAK,uBAAuB,EAC5B,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAC,KAAK,eAAe,EAA4B,MAAM,uBAAuB,CAAC;AACtF,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,mBAAmB,CAAC;AAC3D,OAAO,KAAK,EAAC,SAAS,EAAc,MAAM,YAAY,CAAC;AAGvD;;;;;GAKG;AACH,MAAM,WAAW,0BAA0B;IAC1C,iEAAiE;IACjE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,gEAAgE;IAChE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,sDAAsD;AACtD,MAAM,WAAW,uBAAuB;IACvC,8CAA8C;IAC9C,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IAC/C,+DAA+D;IAC/D,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC;IAC/B,oEAAoE;IACpE,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,0EAA0E;IAC1E,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;IAC3C,kEAAkE;IAClE,QAAQ,CAAC,aAAa,EAAE,uBAAuB,CAAC;IAChD,4EAA4E;IAC5E,QAAQ,CAAC,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACjD,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,CAAC,EAAE,0BAA0B,CAAC;IACjD,iEAAiE;IACjE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC7B;
|
|
1
|
+
{"version":3,"file":"conformance_table.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/conformance_table.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAwB9B,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,uBAAuB,CAAC;AAE1D,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,8BAA8B,CAAC;AAMjE,OAAO,EAIN,KAAK,uBAAuB,EAC5B,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAC,KAAK,eAAe,EAA4B,MAAM,uBAAuB,CAAC;AACtF,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,mBAAmB,CAAC;AAC3D,OAAO,KAAK,EAAC,SAAS,EAAc,MAAM,YAAY,CAAC;AAGvD;;;;;GAKG;AACH,MAAM,WAAW,0BAA0B;IAC1C,iEAAiE;IACjE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,gEAAgE;IAChE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,sDAAsD;AACtD,MAAM,WAAW,uBAAuB;IACvC,8CAA8C;IAC9C,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IAC/C,+DAA+D;IAC/D,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC;IAC/B,oEAAoE;IACpE,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,0EAA0E;IAC1E,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;IAC3C,kEAAkE;IAClE,QAAQ,CAAC,aAAa,EAAE,uBAAuB,CAAC;IAChD,4EAA4E;IAC5E,QAAQ,CAAC,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACjD,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,CAAC,EAAE,0BAA0B,CAAC;IACjD,iEAAiE;IACjE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC7B;AAkOD;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,GAAI,SAAS,uBAAuB,KAAG,IAgBnF,CAAC"}
|
|
@@ -133,13 +133,15 @@ const run_rpc_case = async (c, transport, headers, suppress_default_origin, reso
|
|
|
133
133
|
assert.ok(!res.ok, `${c.name}: expected error status ${c.expect.status} but got success`);
|
|
134
134
|
assert.strictEqual(res.status, c.expect.status, `${c.name}: error status`);
|
|
135
135
|
if (c.expect.error_reason !== undefined) {
|
|
136
|
+
// A row that *declares* a reason must carry it — present AND equal —
|
|
137
|
+
// mirroring the REST branch's unconditional `body.error` assertion. The
|
|
138
|
+
// earlier skip-if-absent form let a backend that dropped the reason pass
|
|
139
|
+
// a row declaring one, blessing a reason/forensic-parity divergence (the
|
|
140
|
+
// IDOR-mask / privilege reason is exactly the distinguishing bit). Rows
|
|
141
|
+
// whose denial genuinely has no reason (the bare `unauthenticated()` 401)
|
|
142
|
+
// simply omit `error_reason` and are pinned by `status` above.
|
|
136
143
|
const reason = res.error.data?.reason;
|
|
137
|
-
|
|
138
|
-
// 401 now); a denial that genuinely omits it falls back to the status
|
|
139
|
-
// assertion above to pin the denial class.
|
|
140
|
-
if (reason !== undefined) {
|
|
141
|
-
assert.strictEqual(reason, c.expect.error_reason, `${c.name}: error.data.reason`);
|
|
142
|
-
}
|
|
144
|
+
assert.strictEqual(reason, c.expect.error_reason, `${c.name}: error.data.reason`);
|
|
143
145
|
}
|
|
144
146
|
if (c.expect.fields)
|
|
145
147
|
assert_fields(res.error.data, c.expect.fields, c.name);
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import '../assert_dev_env.js';
|
|
2
|
-
import {
|
|
3
|
-
import type { SetupTest } from './setup.js';
|
|
2
|
+
import type { RpcPathCrossSuiteOptions, SetupTest } from './setup.js';
|
|
4
3
|
/**
|
|
5
4
|
* The fact suite adds one optional knob to the shared cell options: a setup
|
|
6
5
|
* variant whose keeper carries a **second actor**. Only the multi-actor case
|
|
7
6
|
* needs it; the rest of the suite runs single-actor, so wiring it is opt-in.
|
|
8
7
|
* Omit it and the multi-actor case silently skips.
|
|
9
8
|
*/
|
|
10
|
-
export interface FactServingCrossTestOptions extends
|
|
9
|
+
export interface FactServingCrossTestOptions extends RpcPathCrossSuiteOptions {
|
|
11
10
|
readonly setup_test_multi_actor?: SetupTest;
|
|
12
11
|
}
|
|
13
12
|
export declare const describe_fact_serving_cross_tests: (options: FactServingCrossTestOptions) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fact_serving.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/fact_serving.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"fact_serving.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/fact_serving.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAiD9B,OAAO,KAAK,EAAC,wBAAwB,EAAE,SAAS,EAAC,MAAM,YAAY,CAAC;AAEpE;;;;;GAKG;AACH,MAAM,WAAW,2BAA4B,SAAQ,wBAAwB;IAC5E,QAAQ,CAAC,sBAAsB,CAAC,EAAE,SAAS,CAAC;CAC5C;AA8BD,eAAO,MAAM,iCAAiC,GAAI,SAAS,2BAA2B,KAAG,IA8NxF,CAAC"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import '../assert_dev_env.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { RpcPathCrossSuiteOptions } from './setup.js';
|
|
3
3
|
/**
|
|
4
|
-
* Options for the origin parity suite.
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Options for the origin parity suite. The standard RPC-dispatched
|
|
5
|
+
* cross-suite shape (`setup_test` / `capabilities` / `rpc_path`); aliases
|
|
6
|
+
* the shared `RpcPathCrossSuiteOptions` rather than minting a duplicate.
|
|
7
7
|
*/
|
|
8
|
-
export type OriginCrossTestOptions =
|
|
8
|
+
export type OriginCrossTestOptions = RpcPathCrossSuiteOptions;
|
|
9
9
|
export declare const describe_origin_cross_tests: (options: OriginCrossTestOptions) => void;
|
|
10
10
|
//# sourceMappingURL=origin.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"origin.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/origin.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAkC9B,OAAO,KAAK,EAAC,
|
|
1
|
+
{"version":3,"file":"origin.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/origin.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAkC9B,OAAO,KAAK,EAAC,wBAAwB,EAAC,MAAM,YAAY,CAAC;AAGzD;;;;GAIG;AACH,MAAM,MAAM,sBAAsB,GAAG,wBAAwB,CAAC;AAM9D,eAAO,MAAM,2BAA2B,GAAI,SAAS,sBAAsB,KAAG,IAwC7E,CAAC"}
|
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import '../assert_dev_env.js';
|
|
2
|
-
import {
|
|
3
|
-
import type { SetupTest } from './setup.js';
|
|
2
|
+
import type { CrossSuiteOptions } from './setup.js';
|
|
4
3
|
/** 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;
|
|
4
|
+
export interface ReadyCrossTestOptions extends CrossSuiteOptions {
|
|
10
5
|
/** Readiness probe path. Default `/ready`. */
|
|
11
6
|
readonly ready_path?: string;
|
|
12
7
|
}
|
|
@@ -1 +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;
|
|
1
|
+
{"version":3,"file":"ready.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/ready.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAkC9B,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,YAAY,CAAC;AAElD,oDAAoD;AACpD,MAAM,WAAW,qBAAsB,SAAQ,iBAAiB;IAC/D,8CAA8C;IAC9C,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,eAAO,MAAM,0BAA0B,GAAI,SAAS,qBAAqB,KAAG,IAuB3E,CAAC"}
|
|
@@ -187,6 +187,34 @@ export type TestFixture = TestFixtureBase;
|
|
|
187
187
|
* a fresh per-test bundle on each call.
|
|
188
188
|
*/
|
|
189
189
|
export type SetupTest = () => Promise<TestFixture>;
|
|
190
|
+
/**
|
|
191
|
+
* Base options shared by every imperative cross-backend parity suite
|
|
192
|
+
* (`origin` / `ready` / `body_size` / `cell_*` / `actor_*` /
|
|
193
|
+
* `account_lifecycle` / `app_settings` / `testing_backdoor` / …). The
|
|
194
|
+
* `{setup_test, capabilities}` core is identical across them; each suite
|
|
195
|
+
* extends this with its own path field (`rpc_path` for RPC-dispatched
|
|
196
|
+
* suites via `RpcPathCrossSuiteOptions`, `ready_path` for the readiness
|
|
197
|
+
* probe, etc.). Lives here in the neutral fixture-types home rather than in
|
|
198
|
+
* any one domain helper, so a non-cell suite no longer reaches into the
|
|
199
|
+
* cell helpers for its option shape.
|
|
200
|
+
*/
|
|
201
|
+
export interface CrossSuiteOptions {
|
|
202
|
+
/** Per-test fixture-producing function (fresh keeper + db per call). */
|
|
203
|
+
readonly setup_test: SetupTest;
|
|
204
|
+
/** Backend capability declarations — each suite gates on its own flag. */
|
|
205
|
+
readonly capabilities: BackendCapabilities;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* `CrossSuiteOptions` plus the RPC endpoint path the suite dispatches
|
|
209
|
+
* against — the shape every JSON-RPC-driven imperative suite takes (cell
|
|
210
|
+
* verbs, origin, body-size, actor lookup/search, account lifecycle, app
|
|
211
|
+
* settings, testing backdoor). Suites alias this under a self-documenting
|
|
212
|
+
* per-suite name (e.g. `OriginCrossTestOptions = RpcPathCrossSuiteOptions`).
|
|
213
|
+
*/
|
|
214
|
+
export interface RpcPathCrossSuiteOptions extends CrossSuiteOptions {
|
|
215
|
+
/** RPC endpoint path the methods are mounted on. Default `/api/rpc`. */
|
|
216
|
+
readonly rpc_path?: string;
|
|
217
|
+
}
|
|
190
218
|
/**
|
|
191
219
|
* Options for `default_in_process_setup`. Extends `CreateTestAppOptions`
|
|
192
220
|
* with the same `extra_accounts` slot the cross-process variant accepts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/setup.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAuB9B,OAAO,EAAC,IAAI,EAAC,MAAM,wBAAwB,CAAC;AAE5C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,0BAA0B,CAAC;AACxD,OAAO,KAAK,EAAC,sBAAsB,EAAC,MAAM,4BAA4B,CAAC;AACvE,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,oCAAoC,CAAC;AACzE,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,8BAA8B,CAAC;AAKjE,OAAO,EAKN,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAGN,KAAK,uBAAuB,EAC5B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAA0B,KAAK,mBAAmB,EAAC,MAAM,mBAAmB,CAAC;AACpF,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAyB,KAAK,cAAc,EAAC,MAAM,kCAAkC,CAAC;AAC7F,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,oBAAoB,CAAC;AAEtD;;;;;GAKG;AACH,MAAM,WAAW,wBAAwB;IACxC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CAC/B;AAED;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,GAAG,WAAW,CAAC;AAE7C;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACtC;AAED,sEAAsE;AACtE,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,OAAO,EAAE;QAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAC,CAAC;IACjE,QAAQ,CAAC,KAAK,EAAE;QAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAA;KAAC,CAAC;IACpC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,sBAAsB,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5F,QAAQ,CAAC,qBAAqB,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3F;AAoCD;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,eAAe;IAC/B;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC;IACnC;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,QAAQ,CAAC,eAAe,EAAE,CAAC,OAAO,CAAC,EAAE;QAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAC,KAAK,cAAc,CAAC;IAC1F,+CAA+C;IAC/C,QAAQ,CAAC,OAAO,EAAE;QAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAC,CAAC;IACjE,8CAA8C;IAC9C,QAAQ,CAAC,KAAK,EAAE;QAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAA;KAAC,CAAC;IACpC,8DAA8D;IAC9D,QAAQ,CAAC,sBAAsB,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5F,4DAA4D;IAC5D,QAAQ,CAAC,qBAAqB,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3F,iEAAiE;IACjE,QAAQ,CAAC,2BAA2B,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjG;;;;;OAKG;IACH,QAAQ,CAAC,cAAc,EAAE,CAAC,OAAO,CAAC,EAAE,wBAAwB,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAC7F;;;;;OAKG;IACH,QAAQ,CAAC,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAC;IACvE;;;;;;;;OAQG;IACH,QAAQ,CAAC,YAAY,EAAE,aAAa,CAAC;QAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;IACjF;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,oBAAoB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CACrD;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,WAAW,GAAG,eAAe,CAAC;AAE1C;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/setup.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import '../assert_dev_env.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { RpcPathCrossSuiteOptions } from './setup.js';
|
|
3
3
|
/** Options for the testing-backdoor negative-credential suite. */
|
|
4
|
-
export type TestingBackdoorCrossTestOptions =
|
|
4
|
+
export type TestingBackdoorCrossTestOptions = RpcPathCrossSuiteOptions;
|
|
5
5
|
export declare const describe_testing_backdoor_cross_tests: (options: TestingBackdoorCrossTestOptions) => void;
|
|
6
6
|
//# sourceMappingURL=testing_backdoor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing_backdoor.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/testing_backdoor.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAyD9B,OAAO,KAAK,EAAC,
|
|
1
|
+
{"version":3,"file":"testing_backdoor.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/testing_backdoor.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAyD9B,OAAO,KAAK,EAAC,wBAAwB,EAAc,MAAM,YAAY,CAAC;AA+DtE,kEAAkE;AAClE,MAAM,MAAM,+BAA+B,GAAG,wBAAwB,CAAC;AAEvE,eAAO,MAAM,qCAAqC,GACjD,SAAS,+BAA+B,KACtC,IAiCF,CAAC"}
|