@fuzdev/fuz_app 0.62.0 → 0.64.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/actions/CLAUDE.md +139 -24
- package/dist/actions/action_rpc.d.ts +10 -0
- package/dist/actions/action_rpc.d.ts.map +1 -1
- package/dist/actions/action_rpc.js +1 -1
- package/dist/actions/action_spec.d.ts +1 -1
- package/dist/actions/action_spec.js +1 -1
- package/dist/actions/connection_closer.d.ts +68 -0
- package/dist/actions/connection_closer.d.ts.map +1 -0
- package/dist/actions/connection_closer.js +41 -0
- package/dist/actions/perform_action.d.ts.map +1 -1
- package/dist/actions/perform_action.js +1 -0
- package/dist/actions/register_action_ws.d.ts.map +1 -1
- package/dist/actions/register_action_ws.js +23 -2
- package/dist/actions/register_ws_endpoint.d.ts +11 -9
- package/dist/actions/register_ws_endpoint.d.ts.map +1 -1
- package/dist/actions/register_ws_endpoint.js +5 -5
- package/dist/actions/transports_ws_auth_guard.d.ts +24 -8
- package/dist/actions/transports_ws_auth_guard.d.ts.map +1 -1
- package/dist/actions/transports_ws_auth_guard.js +23 -7
- package/dist/actions/ws_endpoint_spec.d.ts +119 -0
- package/dist/actions/ws_endpoint_spec.d.ts.map +1 -0
- package/dist/actions/ws_endpoint_spec.js +13 -0
- package/dist/auth/CLAUDE.md +124 -39
- package/dist/auth/account_action_specs.d.ts +7 -1
- package/dist/auth/account_action_specs.d.ts.map +1 -1
- package/dist/auth/account_action_specs.js +11 -4
- package/dist/auth/account_actions.d.ts +13 -0
- package/dist/auth/account_actions.d.ts.map +1 -1
- package/dist/auth/account_actions.js +40 -5
- package/dist/auth/account_routes.d.ts +12 -2
- package/dist/auth/account_routes.d.ts.map +1 -1
- package/dist/auth/account_routes.js +63 -12
- package/dist/auth/account_schema.d.ts +5 -5
- package/dist/auth/account_schema.js +2 -2
- package/dist/auth/actor_lookup_actions.d.ts +1 -1
- package/dist/auth/actor_lookup_actions.js +1 -1
- package/dist/auth/actor_lookup_queries.d.ts +1 -1
- package/dist/auth/actor_lookup_queries.js +1 -1
- package/dist/auth/actor_search_action_specs.d.ts +1 -1
- package/dist/auth/actor_search_action_specs.js +1 -1
- package/dist/auth/actor_search_actions.d.ts +1 -1
- package/dist/auth/actor_search_actions.js +1 -1
- package/dist/auth/actor_search_queries.d.ts +1 -1
- package/dist/auth/actor_search_queries.js +1 -1
- package/dist/auth/admin_action_specs.d.ts +8 -8
- package/dist/auth/admin_actions.d.ts +11 -0
- package/dist/auth/admin_actions.d.ts.map +1 -1
- package/dist/auth/admin_actions.js +25 -0
- package/dist/auth/all_action_spec_registries.d.ts +2 -2
- package/dist/auth/all_action_spec_registries.js +2 -2
- package/dist/auth/audit_emitter.d.ts +56 -12
- package/dist/auth/audit_emitter.d.ts.map +1 -1
- package/dist/auth/audit_emitter.js +38 -12
- package/dist/auth/audit_log_routes.d.ts +1 -1
- package/dist/auth/audit_log_routes.js +1 -1
- package/dist/auth/audit_log_schema.d.ts +30 -3
- package/dist/auth/audit_log_schema.d.ts.map +1 -1
- package/dist/auth/audit_log_schema.js +21 -3
- package/dist/auth/bootstrap_routes.d.ts +1 -1
- package/dist/auth/invite_schema.d.ts +2 -2
- package/dist/auth/request_context.d.ts +1 -1
- package/dist/auth/signup_routes.d.ts +1 -1
- package/dist/auth/standard_rpc_actions.d.ts +1 -0
- package/dist/auth/standard_rpc_actions.d.ts.map +1 -1
- package/dist/auth/standard_rpc_actions.js +1 -0
- package/dist/env/update_env_variable.js +1 -1
- package/dist/http/CLAUDE.md +42 -26
- package/dist/http/ip_canonical.d.ts +99 -0
- package/dist/http/ip_canonical.d.ts.map +1 -0
- package/dist/http/ip_canonical.js +191 -0
- package/dist/http/origin.d.ts +13 -5
- package/dist/http/origin.d.ts.map +1 -1
- package/dist/http/origin.js +13 -31
- package/dist/http/pending_effects.d.ts +1 -1
- package/dist/http/pending_effects.js +1 -1
- package/dist/http/proxy.d.ts +13 -5
- package/dist/http/proxy.d.ts.map +1 -1
- package/dist/http/proxy.js +15 -23
- package/dist/http/surface.d.ts +50 -0
- package/dist/http/surface.d.ts.map +1 -1
- package/dist/http/surface.js +27 -1
- package/dist/primitive_schemas.d.ts +20 -4
- package/dist/primitive_schemas.d.ts.map +1 -1
- package/dist/primitive_schemas.js +25 -4
- package/dist/realtime/sse_auth_guard.d.ts +16 -4
- package/dist/realtime/sse_auth_guard.d.ts.map +1 -1
- package/dist/realtime/sse_auth_guard.js +15 -3
- package/dist/server/app_backend.d.ts +66 -19
- package/dist/server/app_backend.d.ts.map +1 -1
- package/dist/server/app_backend.js +57 -34
- package/dist/server/app_server.d.ts +60 -0
- package/dist/server/app_server.d.ts.map +1 -1
- package/dist/server/app_server.js +95 -2
- package/dist/server/startup.d.ts.map +1 -1
- package/dist/server/startup.js +12 -0
- package/dist/testing/CLAUDE.md +91 -71
- package/dist/testing/admin_integration.d.ts.map +1 -1
- package/dist/testing/admin_integration.js +4 -5
- package/dist/testing/adversarial_headers.d.ts +6 -0
- package/dist/testing/adversarial_headers.d.ts.map +1 -1
- package/dist/testing/adversarial_headers.js +13 -5
- package/dist/testing/app_server.d.ts +33 -32
- package/dist/testing/app_server.d.ts.map +1 -1
- package/dist/testing/app_server.js +4 -13
- package/dist/testing/attack_surface.d.ts +8 -7
- package/dist/testing/attack_surface.d.ts.map +1 -1
- package/dist/testing/attack_surface.js +12 -8
- package/dist/testing/audit_completeness.d.ts.map +1 -1
- package/dist/testing/audit_completeness.js +20 -6
- package/dist/testing/audit_drift_guard.d.ts +116 -0
- package/dist/testing/audit_drift_guard.d.ts.map +1 -0
- package/dist/testing/audit_drift_guard.js +134 -0
- package/dist/testing/connection_closer_helpers.d.ts +44 -0
- package/dist/testing/connection_closer_helpers.d.ts.map +1 -0
- package/dist/testing/connection_closer_helpers.js +48 -0
- package/dist/testing/integration.d.ts.map +1 -1
- package/dist/testing/integration.js +7 -9
- package/dist/testing/rate_limiting.js +4 -4
- package/dist/testing/rpc_helpers.d.ts +2 -1
- package/dist/testing/rpc_helpers.d.ts.map +1 -1
- package/dist/testing/rpc_round_trip.d.ts.map +1 -1
- package/dist/testing/rpc_round_trip.js +6 -8
- package/dist/testing/sse_round_trip.d.ts.map +1 -1
- package/dist/testing/sse_round_trip.js +12 -6
- package/dist/testing/stubs.d.ts +11 -0
- package/dist/testing/stubs.d.ts.map +1 -1
- package/dist/testing/stubs.js +4 -0
- package/dist/testing/surface_invariants.d.ts +66 -1
- package/dist/testing/surface_invariants.d.ts.map +1 -1
- package/dist/testing/surface_invariants.js +103 -1
- package/dist/ui/CLAUDE.md +13 -18
- package/dist/ui/SurfaceExplorer.svelte +161 -2
- package/dist/ui/SurfaceExplorer.svelte.d.ts.map +1 -1
- package/dist/ui/keyed_async_slot.svelte.d.ts +1 -1
- package/dist/ui/keyed_async_slot.svelte.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import './assert_dev_env.js';
|
|
2
|
+
import { assert, beforeEach, afterEach } from 'vitest';
|
|
3
|
+
import { get_audit_metadata_validation_failures, get_audit_unknown_event_type_failures, reset_audit_metadata_validation_failures, reset_audit_unknown_event_type_failures, } from '../auth/audit_log_queries.js';
|
|
4
|
+
import { create_audit_emitter, } from '../auth/audit_emitter.js';
|
|
5
|
+
/**
|
|
6
|
+
* Register per-test `beforeEach` + `afterEach` hooks that catch any audit
|
|
7
|
+
* emission with a metadata shape that fails its `audit_metadata_schemas`
|
|
8
|
+
* entry, or an `event_type` not present in the active `AuditLogConfig`.
|
|
9
|
+
*
|
|
10
|
+
* The production validation in `query_audit_log` is fail-open — it bumps
|
|
11
|
+
* process-wide counters and proceeds, so a regression that emits an
|
|
12
|
+
* undeclared metadata field or a typo'd event-type lands a row that
|
|
13
|
+
* passes downstream queries but breaks forensics. Tests that exercise
|
|
14
|
+
* audit emits should fail loudly when this happens.
|
|
15
|
+
*
|
|
16
|
+
* Call at the top of every `describe` / `describe_db` block that fires
|
|
17
|
+
* audit writes through `deps.audit.emit`. Resets counters before each
|
|
18
|
+
* test and asserts zero on completion.
|
|
19
|
+
*
|
|
20
|
+
* Pair with `await_pending_effects: true` (the default for
|
|
21
|
+
* `create_test_app`) so fire-and-forget audit writes have completed by
|
|
22
|
+
* the time the after-each check observes counter state.
|
|
23
|
+
*/
|
|
24
|
+
export const install_audit_drift_guard = () => {
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
reset_audit_metadata_validation_failures();
|
|
27
|
+
reset_audit_unknown_event_type_failures();
|
|
28
|
+
});
|
|
29
|
+
afterEach(() => {
|
|
30
|
+
assert.strictEqual(get_audit_metadata_validation_failures(), 0, 'audit metadata failed schema validation — see audit_log_schema.audit_metadata_schemas');
|
|
31
|
+
assert.strictEqual(get_audit_unknown_event_type_failures(), 0, 'audit emitted an unknown event_type — see AUDIT_EVENT_TYPES');
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Build a no-op `AuditEmitter` that records every `emit`, `emit_pool`, and
|
|
36
|
+
* `emit_role_grant_target` call into `calls` as an `AuditLogInput`. Use to
|
|
37
|
+
* capture audit metadata shapes in unit tests (e.g. password change failure
|
|
38
|
+
* outcome, role-grant create denial) without standing up the full PGlite +
|
|
39
|
+
* `query_audit_log` pipeline.
|
|
40
|
+
*
|
|
41
|
+
* **Capture scope — all four production fan-out shapes.**
|
|
42
|
+
* `emit_role_grant_target` mirrors `create_audit_emitter`'s lift logic in
|
|
43
|
+
* place — `actor_id` / `account_id` / `ip` are populated from `auth` + `ctx`
|
|
44
|
+
* and the `event_type` / `outcome` / `target_*_id` / `metadata` fields
|
|
45
|
+
* forward from the input envelope. Tests asserting on role-grant-shape
|
|
46
|
+
* emissions read out of the same homogeneous `calls` array.
|
|
47
|
+
* `notify` is a no-op; `on_event_chain` is an empty array.
|
|
48
|
+
*
|
|
49
|
+
* `emit` AND `emit_pool` both append to `calls` so cleanup-sweep tests
|
|
50
|
+
* (which use `emit_pool` exclusively — see `auth/cleanup.ts`) can also
|
|
51
|
+
* read assertions off the same array.
|
|
52
|
+
*
|
|
53
|
+
* Pass `calls_ref` to write into a caller-owned array (callers that
|
|
54
|
+
* declared `const events: Array<AuditLogInput> = []` and want to keep
|
|
55
|
+
* the reference). Omit to let the helper allocate a fresh array and
|
|
56
|
+
* return it on the `calls` field of the result.
|
|
57
|
+
*
|
|
58
|
+
* The returned emitter is deliberately NOT frozen — slots stay mutable
|
|
59
|
+
* so a test can override one when it needs bespoke shape (e.g. an
|
|
60
|
+
* `emit_pool` that throws on the first call). The production
|
|
61
|
+
* `create_audit_emitter` freeze invariant exists to catch the
|
|
62
|
+
* `patch_audit_emit_capture` hot-patch footgun against the
|
|
63
|
+
* closure-captured `emit`; the recording emitter has no inner closure,
|
|
64
|
+
* so the freeze isn't load-bearing here.
|
|
65
|
+
*/
|
|
66
|
+
export const create_recording_audit_emitter = (calls_ref) => {
|
|
67
|
+
const calls = calls_ref ?? [];
|
|
68
|
+
const emitter = {
|
|
69
|
+
emit: (_ctx, input) => {
|
|
70
|
+
calls.push(input);
|
|
71
|
+
},
|
|
72
|
+
emit_role_grant_target: (ctx, auth, input) => {
|
|
73
|
+
calls.push({
|
|
74
|
+
event_type: input.event_type,
|
|
75
|
+
actor_id: auth.actor.id,
|
|
76
|
+
account_id: auth.account.id,
|
|
77
|
+
outcome: input.outcome,
|
|
78
|
+
target_account_id: input.target_account_id,
|
|
79
|
+
target_actor_id: input.target_actor_id,
|
|
80
|
+
ip: ctx.client_ip,
|
|
81
|
+
metadata: input.metadata,
|
|
82
|
+
});
|
|
83
|
+
},
|
|
84
|
+
emit_pool: (input) => {
|
|
85
|
+
calls.push(input);
|
|
86
|
+
return Promise.resolve();
|
|
87
|
+
},
|
|
88
|
+
notify: () => undefined,
|
|
89
|
+
on_event_chain: [],
|
|
90
|
+
};
|
|
91
|
+
return { emitter, calls };
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* Build an `audit_factory` that produces a real `create_audit_emitter`
|
|
95
|
+
* with its `emit` decorated to push a `{kind: 'emit', at: seq.value++}`
|
|
96
|
+
* marker into a shared sequence + events array. Used by the close-vs-emit
|
|
97
|
+
* ordering test to compose against a shared sequence counter (typically
|
|
98
|
+
* `create_recording_closer(seq_ref)` capturing eager-close calls).
|
|
99
|
+
*
|
|
100
|
+
* Pass the returned factory through `create_test_app({audit_factory: …})`
|
|
101
|
+
* — the test backend invokes it with its constructed `{db, log}` and
|
|
102
|
+
* lands the decorated emitter on `backend.deps.audit`. Production
|
|
103
|
+
* handlers dereference `deps.audit.emit` at call time, so the decorator
|
|
104
|
+
* sees every subsequent handler invocation. The underlying `emit` still
|
|
105
|
+
* runs — the decorator records the call, it does not suppress side
|
|
106
|
+
* effects.
|
|
107
|
+
*
|
|
108
|
+
* **Scope — both `emit` and `emit_role_grant_target`.** The decorator
|
|
109
|
+
* is captured by `emit_role_grant_target`'s closure inside
|
|
110
|
+
* `create_audit_emitter` (and re-exposed as the outer `emit` slot), so
|
|
111
|
+
* role-grant-shape emissions land in `events_ref` alongside bare `emit`
|
|
112
|
+
* calls. `emit_pool` and `notify` are not decorated — they take
|
|
113
|
+
* `AuditLogInput` / `AuditLogEvent` directly without going through
|
|
114
|
+
* `emit`, so handler-side `emit_pool` writes (today only
|
|
115
|
+
* `auth/cleanup.ts`) skip capture. Close-firing handlers all reach for
|
|
116
|
+
* `emit` or `emit_role_grant_target`, so the ordering test sees them
|
|
117
|
+
* regardless of which entry point a future refactor picks.
|
|
118
|
+
*
|
|
119
|
+
* Optionally accept `extra_options` to thread `on_audit_event` /
|
|
120
|
+
* `audit_log_config` into the inner emitter — useful when a test wants
|
|
121
|
+
* both ordering capture and a real SSE/WS guard wired into the same
|
|
122
|
+
* emitter chain.
|
|
123
|
+
*/
|
|
124
|
+
export const create_emit_ordering_audit_factory = (seq_ref, events_ref, extra_options) => {
|
|
125
|
+
return ({ db, log }) => create_audit_emitter({
|
|
126
|
+
...extra_options,
|
|
127
|
+
db,
|
|
128
|
+
log,
|
|
129
|
+
emit_decorator: (inner) => (ctx, input) => {
|
|
130
|
+
events_ref.push({ kind: 'emit', at: seq_ref.value++ });
|
|
131
|
+
inner(ctx, input);
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import './assert_dev_env.js';
|
|
2
|
+
import type { ConnectionCloser } from '../actions/connection_closer.js';
|
|
3
|
+
/**
|
|
4
|
+
* Record of a single `ConnectionCloser` method invocation. `at` is the
|
|
5
|
+
* value of a monotonically-increasing sequence counter at the time of
|
|
6
|
+
* the call — pair with `create_emit_ordering_audit_factory` to record both
|
|
7
|
+
* close + audit emit calls into the same sequence for ordering tests.
|
|
8
|
+
*/
|
|
9
|
+
export interface RecordedClose {
|
|
10
|
+
method: 'session' | 'token' | 'account';
|
|
11
|
+
id: string;
|
|
12
|
+
at: number;
|
|
13
|
+
}
|
|
14
|
+
export interface RecordingCloser {
|
|
15
|
+
closer: ConnectionCloser;
|
|
16
|
+
calls: Array<RecordedClose>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Build a `ConnectionCloser` that records every call into `calls` rather
|
|
20
|
+
* than touching real transports. Each method returns 1 ("one socket
|
|
21
|
+
* closed") regardless of whether a real socket exists — handlers
|
|
22
|
+
* typically ignore the return value.
|
|
23
|
+
*
|
|
24
|
+
* Pass `seq_ref` to share the sequence counter with a sibling
|
|
25
|
+
* `create_emit_ordering_audit_factory` so tests can pin close-vs-emit
|
|
26
|
+
* ordering at the handler call site. Without `seq_ref`, the closer
|
|
27
|
+
* uses a fresh internal counter — `at: N` values within a single test
|
|
28
|
+
* are meaningful, but cannot be compared against audit emit ordering.
|
|
29
|
+
*/
|
|
30
|
+
export declare const create_recording_closer: (seq_ref?: {
|
|
31
|
+
value: number;
|
|
32
|
+
}) => RecordingCloser;
|
|
33
|
+
/**
|
|
34
|
+
* Pin `{method, id}` on a single recorded close call without baking in
|
|
35
|
+
* the `at: N` sequence number. Use at every "did the closer fire?"
|
|
36
|
+
* assertion site; the sequence number is only meaningful for dedicated
|
|
37
|
+
* ordering tests (paired with `create_emit_ordering_audit_factory`).
|
|
38
|
+
*
|
|
39
|
+
* Throws via `assert.ok` if `call` is `undefined` — index a recorded
|
|
40
|
+
* `calls` array directly (`calls[0]`) and let this helper handle the
|
|
41
|
+
* missing-element case.
|
|
42
|
+
*/
|
|
43
|
+
export declare const assert_close_call: (call: RecordedClose | undefined, method: "session" | "token" | "account", id: string) => void;
|
|
44
|
+
//# sourceMappingURL=connection_closer_helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection_closer_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/connection_closer_helpers.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAI7B,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,iCAAiC,CAAC;AAEtE;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC7B,MAAM,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IACxC,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,eAAe;IAC/B,MAAM,EAAE,gBAAgB,CAAC;IACzB,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;CAC5B;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,uBAAuB,GAAI,UAAU;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,KAAG,eAkBnE,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,GAC7B,MAAM,aAAa,GAAG,SAAS,EAC/B,QAAQ,SAAS,GAAG,OAAO,GAAG,SAAS,EACvC,IAAI,MAAM,KACR,IAIF,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import './assert_dev_env.js';
|
|
2
|
+
import { assert } from 'vitest';
|
|
3
|
+
/**
|
|
4
|
+
* Build a `ConnectionCloser` that records every call into `calls` rather
|
|
5
|
+
* than touching real transports. Each method returns 1 ("one socket
|
|
6
|
+
* closed") regardless of whether a real socket exists — handlers
|
|
7
|
+
* typically ignore the return value.
|
|
8
|
+
*
|
|
9
|
+
* Pass `seq_ref` to share the sequence counter with a sibling
|
|
10
|
+
* `create_emit_ordering_audit_factory` so tests can pin close-vs-emit
|
|
11
|
+
* ordering at the handler call site. Without `seq_ref`, the closer
|
|
12
|
+
* uses a fresh internal counter — `at: N` values within a single test
|
|
13
|
+
* are meaningful, but cannot be compared against audit emit ordering.
|
|
14
|
+
*/
|
|
15
|
+
export const create_recording_closer = (seq_ref) => {
|
|
16
|
+
const calls = [];
|
|
17
|
+
const seq = seq_ref ?? { value: 0 };
|
|
18
|
+
const closer = {
|
|
19
|
+
close_sockets_for_session: (id) => {
|
|
20
|
+
calls.push({ method: 'session', id, at: seq.value++ });
|
|
21
|
+
return 1;
|
|
22
|
+
},
|
|
23
|
+
close_sockets_for_token: (id) => {
|
|
24
|
+
calls.push({ method: 'token', id, at: seq.value++ });
|
|
25
|
+
return 1;
|
|
26
|
+
},
|
|
27
|
+
close_sockets_for_account: (id) => {
|
|
28
|
+
calls.push({ method: 'account', id, at: seq.value++ });
|
|
29
|
+
return 1;
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
return { closer, calls };
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Pin `{method, id}` on a single recorded close call without baking in
|
|
36
|
+
* the `at: N` sequence number. Use at every "did the closer fire?"
|
|
37
|
+
* assertion site; the sequence number is only meaningful for dedicated
|
|
38
|
+
* ordering tests (paired with `create_emit_ordering_audit_factory`).
|
|
39
|
+
*
|
|
40
|
+
* Throws via `assert.ok` if `call` is `undefined` — index a recorded
|
|
41
|
+
* `calls` array directly (`calls[0]`) and let this helper handle the
|
|
42
|
+
* missing-element case.
|
|
43
|
+
*/
|
|
44
|
+
export const assert_close_call = (call, method, id) => {
|
|
45
|
+
assert.ok(call, 'expected a recorded close call');
|
|
46
|
+
assert.strictEqual(call.method, method);
|
|
47
|
+
assert.strictEqual(call.id, id);
|
|
48
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integration.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/integration.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAsB7B,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAC;AAErD,OAAO,EAA6C,KAAK,eAAe,EAAC,MAAM,iBAAiB,CAAC;AACjG,OAAO,EAIN,KAAK,SAAS,EACd,MAAM,SAAS,CAAC;AAOjB,OAAO,EAKN,KAAK,uBAAuB,EAC5B,MAAM,kBAAkB,CAAC;AAsB1B;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC9C,4CAA4C;IAC5C,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,wDAAwD;IACxD,kBAAkB,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IAChE,iDAAiD;IACjD,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B;;;OAGG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAChC;;;;;;;;;;;;;;;;OAgBG;IACH,aAAa,EAAE,uBAAuB,CAAC;CACvC;
|
|
1
|
+
{"version":3,"file":"integration.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/integration.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAsB7B,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAC;AAErD,OAAO,EAA6C,KAAK,eAAe,EAAC,MAAM,iBAAiB,CAAC;AACjG,OAAO,EAIN,KAAK,SAAS,EACd,MAAM,SAAS,CAAC;AAOjB,OAAO,EAKN,KAAK,uBAAuB,EAC5B,MAAM,kBAAkB,CAAC;AAsB1B;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC9C,4CAA4C;IAC5C,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,wDAAwD;IACxD,kBAAkB,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IAChE,iDAAiD;IACjD,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B;;;OAGG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAChC;;;;;;;;;;;;;;;;OAgBG;IACH,aAAa,EAAE,uBAAuB,CAAC;CACvC;AAoBD;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,mCAAmC,GAC/C,SAAS,8BAA8B,KACrC,IA87CF,CAAC"}
|
|
@@ -31,19 +31,17 @@ import { account_verify_action_spec, account_session_list_action_spec, account_s
|
|
|
31
31
|
import { invite_create_action_spec } from '../auth/admin_action_specs.js';
|
|
32
32
|
/**
|
|
33
33
|
* Build `CreateTestAppOptions` from standard options plus a database.
|
|
34
|
-
* Forwards `options.rpc_endpoints` to `
|
|
35
|
-
* `create_app_server` auto-mounts it per-test with
|
|
36
|
-
* `SuiteAppOptions` excludes `rpc_endpoints` so there's no way
|
|
37
|
-
* `options.app_options` to collide with the suite-level field.
|
|
34
|
+
* Forwards `options.rpc_endpoints` to the top-level `rpc_endpoints` slot on
|
|
35
|
+
* `CreateTestAppOptions` so `create_app_server` auto-mounts it per-test with
|
|
36
|
+
* the real ctx. `SuiteAppOptions` excludes `rpc_endpoints` so there's no way
|
|
37
|
+
* for `options.app_options` to collide with the suite-level field.
|
|
38
38
|
*/
|
|
39
39
|
const build_test_app_options = (options, db) => ({
|
|
40
40
|
session_options: options.session_options,
|
|
41
41
|
create_route_specs: options.create_route_specs,
|
|
42
42
|
db,
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
rpc_endpoints: options.rpc_endpoints,
|
|
46
|
-
},
|
|
43
|
+
rpc_endpoints: options.rpc_endpoints,
|
|
44
|
+
app_options: options.app_options,
|
|
47
45
|
});
|
|
48
46
|
/**
|
|
49
47
|
* Standard integration test suite for fuz_app auth routes.
|
|
@@ -66,7 +64,7 @@ export const describe_standard_integration_tests = (options) => {
|
|
|
66
64
|
// Hard-fail early so consumers see a clear setup error instead of a
|
|
67
65
|
// confusing test failure when `rpc_endpoints` is missing. Factory-form
|
|
68
66
|
// callers are resolved with a stub ctx purely to extract the endpoint
|
|
69
|
-
// path; real handlers run per-test via `
|
|
67
|
+
// path; real handlers run per-test via the top-level `rpc_endpoints` slot on `CreateTestAppOptions`.
|
|
70
68
|
const rpc_endpoints_for_setup = resolve_rpc_endpoints_for_setup(options.rpc_endpoints, options.session_options);
|
|
71
69
|
const rpc_path = require_rpc_endpoint_path(rpc_endpoints_for_setup);
|
|
72
70
|
const init_schema = async (db) => {
|
|
@@ -44,7 +44,7 @@ export const describe_rate_limiting_tests = (options) => {
|
|
|
44
44
|
// Hard-fail early so consumers see a clear setup error instead of a
|
|
45
45
|
// confusing test failure when `rpc_endpoints` is missing. Factory-form
|
|
46
46
|
// callers are resolved with a stub ctx purely to extract the endpoint
|
|
47
|
-
// path; real handlers run per-test via `
|
|
47
|
+
// path; real handlers run per-test via the top-level `rpc_endpoints` slot on `CreateTestAppOptions`.
|
|
48
48
|
const rpc_endpoints_for_setup = resolve_rpc_endpoints_for_setup(options.rpc_endpoints, options.session_options);
|
|
49
49
|
const rpc_path = require_rpc_endpoint_path(rpc_endpoints_for_setup);
|
|
50
50
|
const init_schema = async (db) => {
|
|
@@ -64,9 +64,9 @@ export const describe_rate_limiting_tests = (options) => {
|
|
|
64
64
|
session_options: options.session_options,
|
|
65
65
|
create_route_specs: options.create_route_specs,
|
|
66
66
|
db: get_db(),
|
|
67
|
+
rpc_endpoints: options.rpc_endpoints,
|
|
67
68
|
app_options: {
|
|
68
69
|
...options.app_options,
|
|
69
|
-
rpc_endpoints: options.rpc_endpoints,
|
|
70
70
|
ip_rate_limiter,
|
|
71
71
|
login_account_rate_limiter: null,
|
|
72
72
|
bearer_ip_rate_limiter: null,
|
|
@@ -117,9 +117,9 @@ export const describe_rate_limiting_tests = (options) => {
|
|
|
117
117
|
session_options: options.session_options,
|
|
118
118
|
create_route_specs: options.create_route_specs,
|
|
119
119
|
db: get_db(),
|
|
120
|
+
rpc_endpoints: options.rpc_endpoints,
|
|
120
121
|
app_options: {
|
|
121
122
|
...options.app_options,
|
|
122
|
-
rpc_endpoints: options.rpc_endpoints,
|
|
123
123
|
ip_rate_limiter: null,
|
|
124
124
|
login_account_rate_limiter,
|
|
125
125
|
bearer_ip_rate_limiter: null,
|
|
@@ -182,9 +182,9 @@ export const describe_rate_limiting_tests = (options) => {
|
|
|
182
182
|
session_options: options.session_options,
|
|
183
183
|
create_route_specs: options.create_route_specs,
|
|
184
184
|
db: get_db(),
|
|
185
|
+
rpc_endpoints: options.rpc_endpoints,
|
|
185
186
|
app_options: {
|
|
186
187
|
...options.app_options,
|
|
187
|
-
rpc_endpoints: options.rpc_endpoints,
|
|
188
188
|
ip_rate_limiter: null,
|
|
189
189
|
login_account_rate_limiter: null,
|
|
190
190
|
bearer_ip_rate_limiter,
|
|
@@ -13,7 +13,8 @@ import type { SessionOptions } from '../auth/session_cookie.js';
|
|
|
13
13
|
* per-test `ctx.app_settings` / `ctx.deps` (e.g. the canonical
|
|
14
14
|
* `create_standard_rpc_actions(ctx.deps, {app_settings: ctx.app_settings})`
|
|
15
15
|
* pattern). `create_app_server` resolves either shape natively; test helpers
|
|
16
|
-
* forward the raw value to `
|
|
16
|
+
* forward the raw value to the top-level `rpc_endpoints` slot on
|
|
17
|
+
* `CreateTestAppOptions` for live dispatch.
|
|
17
18
|
*/
|
|
18
19
|
export type RpcEndpointsSuiteOption = Array<RpcEndpointSpec> | ((ctx: AppServerContext) => Array<RpcEndpointSpec>);
|
|
19
20
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rpc_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/rpc_helpers.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAa7B,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,OAAO,EAIN,KAAK,gBAAgB,EACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAC,yBAAyB,EAAC,MAAM,2BAA2B,CAAC;AACzE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,0BAA0B,CAAC;AACxD,OAAO,KAAK,EAAC,qBAAqB,EAAE,mBAAmB,EAAE,eAAe,EAAC,MAAM,oBAAoB,CAAC;AACpG,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAG9D
|
|
1
|
+
{"version":3,"file":"rpc_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/rpc_helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rpc_round_trip.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/rpc_round_trip.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAe7B,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAE9D,OAAO,EAEN,KAAK,eAAe,EAGpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAwB,KAAK,SAAS,EAAC,MAAM,SAAS,CAAC;AAO9D,OAAO,EAMN,KAAK,uBAAuB,EAC5B,MAAM,kBAAkB,CAAC;AAE1B,mDAAmD;AACnD,MAAM,WAAW,uBAAuB;IACvC,4CAA4C;IAC5C,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,wDAAwD;IACxD,kBAAkB,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IAChE;;;;;;;;;;OAUG;IACH,aAAa,EAAE,uBAAuB,CAAC;IACvC,iDAAiD;IACjD,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,qEAAqE;IACrE,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAChC,qDAAqD;IACrD,YAAY,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC7B,6EAA6E;IAC7E,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACvD;AA2BD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,6BAA6B,GAAI,SAAS,uBAAuB,KAAG,
|
|
1
|
+
{"version":3,"file":"rpc_round_trip.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/rpc_round_trip.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAe7B,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAE9D,OAAO,EAEN,KAAK,eAAe,EAGpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAwB,KAAK,SAAS,EAAC,MAAM,SAAS,CAAC;AAO9D,OAAO,EAMN,KAAK,uBAAuB,EAC5B,MAAM,kBAAkB,CAAC;AAE1B,mDAAmD;AACnD,MAAM,WAAW,uBAAuB;IACvC,4CAA4C;IAC5C,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,wDAAwD;IACxD,kBAAkB,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IAChE;;;;;;;;;;OAUG;IACH,aAAa,EAAE,uBAAuB,CAAC;IACvC,iDAAiD;IACjD,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,qEAAqE;IACrE,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAChC,qDAAqD;IACrD,YAAY,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC7B,6EAA6E;IAC7E,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACvD;AA2BD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,6BAA6B,GAAI,SAAS,uBAAuB,KAAG,IA4IhF,CAAC"}
|
|
@@ -54,10 +54,10 @@ const pick_rpc_auth_headers = (method, test_app, authed_account, admin_account)
|
|
|
54
54
|
export const describe_rpc_round_trip_tests = (options) => {
|
|
55
55
|
const skip_set = new Set(options.skip_methods);
|
|
56
56
|
// Resolve factory-form endpoints once for setup-time iteration (method
|
|
57
|
-
// enumeration, surface lookup). Real handlers run per-test via
|
|
58
|
-
// `
|
|
59
|
-
// `.output` are ctx-independent, so
|
|
60
|
-
// what the live dispatcher serves.
|
|
57
|
+
// enumeration, surface lookup). Real handlers run per-test via the
|
|
58
|
+
// top-level `rpc_endpoints` slot on `CreateTestAppOptions` —
|
|
59
|
+
// `action.spec.method` / `.input` / `.output` are ctx-independent, so
|
|
60
|
+
// the stub-resolved specs match what the live dispatcher serves.
|
|
61
61
|
const rpc_endpoints_for_setup = resolve_rpc_endpoints_for_setup(options.rpc_endpoints, options.session_options);
|
|
62
62
|
const init_schema = async (db) => {
|
|
63
63
|
await run_migrations(db, [auth_migration_ns]);
|
|
@@ -76,10 +76,8 @@ export const describe_rpc_round_trip_tests = (options) => {
|
|
|
76
76
|
session_options: options.session_options,
|
|
77
77
|
create_route_specs: options.create_route_specs,
|
|
78
78
|
db,
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
rpc_endpoints: options.rpc_endpoints,
|
|
82
|
-
},
|
|
79
|
+
rpc_endpoints: options.rpc_endpoints,
|
|
80
|
+
app_options: options.app_options,
|
|
83
81
|
});
|
|
84
82
|
authed_account = await test_app.create_account({
|
|
85
83
|
username: 'rpc_round_trip_authed',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sse_round_trip.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/sse_round_trip.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAmB7B,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAwB,KAAK,SAAS,EAAuB,MAAM,oBAAoB,CAAC;AAE/F,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"sse_round_trip.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/sse_round_trip.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAmB7B,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAwB,KAAK,SAAS,EAAuB,MAAM,oBAAoB,CAAC;AAE/F,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,6BAA6B,CAAC;AAG/D,OAAO,EAEN,KAAK,eAAe,EACpB,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAwB,KAAK,SAAS,EAAC,MAAM,SAAS,CAAC;AAE9D,OAAO,EAIN,KAAK,uBAAuB,EAC5B,MAAM,kBAAkB,CAAC;AAM1B,gDAAgD;AAChD,MAAM,WAAW,gBAAgB;IAChC,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,OAAO,EAAE,CAAC,GAAG,EAAE;QAAC,QAAQ,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,WAAW,CAAA;KAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E;;;OAGG;IACH,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAC/B;;;;OAIG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,8CAA8C;AAC9C,MAAM,WAAW,mBAAmB;IACnC,4CAA4C;IAC5C,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,qDAAqD;IACrD,kBAAkB,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IAChE,iDAAiD;IACjD,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,qEAAqE;IACrE,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAChC;;;;;OAKG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAChD;;;;;;;;;;;;OAYG;IACH,aAAa,EAAE,uBAAuB,CAAC;IACvC,8BAA8B;IAC9B,MAAM,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC;CAChC;AAyHD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,wBAAwB,GAAI,SAAS,mBAAmB,KAAG,IAgIvE,CAAC"}
|
|
@@ -16,6 +16,7 @@ import './assert_dev_env.js';
|
|
|
16
16
|
import { describe, test, beforeAll, afterAll, assert } from 'vitest';
|
|
17
17
|
import { SSE_CONNECTED_COMMENT } from '../realtime/sse.js';
|
|
18
18
|
import { ROLE_ADMIN } from '../auth/role_schema.js';
|
|
19
|
+
import { create_audit_emitter } from '../auth/audit_emitter.js';
|
|
19
20
|
import { create_test_app, } from './app_server.js';
|
|
20
21
|
import { create_pglite_factory } from './db.js';
|
|
21
22
|
import { find_route_spec, pick_auth_headers } from './integration_helpers.js';
|
|
@@ -134,7 +135,7 @@ export const describe_sse_route_tests = (options) => {
|
|
|
134
135
|
// Hard-fail early so consumers see a clear setup error instead of a
|
|
135
136
|
// confusing test failure when `rpc_endpoints` is missing. Factory-form
|
|
136
137
|
// callers are resolved with a stub ctx purely to extract the endpoint
|
|
137
|
-
// path; real handlers run per-test via `
|
|
138
|
+
// path; real handlers run per-test via the top-level `rpc_endpoints` slot on `CreateTestAppOptions`.
|
|
138
139
|
const rpc_endpoints_for_setup = resolve_rpc_endpoints_for_setup(options.rpc_endpoints, options.session_options);
|
|
139
140
|
const rpc_path = require_rpc_endpoint_path(rpc_endpoints_for_setup);
|
|
140
141
|
const init_schema = async (db) => {
|
|
@@ -153,15 +154,20 @@ export const describe_sse_route_tests = (options) => {
|
|
|
153
154
|
let db;
|
|
154
155
|
beforeAll(async () => {
|
|
155
156
|
db = await factory.create();
|
|
157
|
+
// Forward the consumer's listener through an `audit_factory`
|
|
158
|
+
// body — the sugar was removed from `TestAppServerOptions`
|
|
159
|
+
// to match the production `CreateAppBackendOptions` shape.
|
|
160
|
+
const { on_audit_event } = options;
|
|
161
|
+
const audit_factory = on_audit_event
|
|
162
|
+
? (params) => create_audit_emitter({ ...params, on_audit_event })
|
|
163
|
+
: undefined;
|
|
156
164
|
test_app = await create_test_app({
|
|
157
165
|
session_options: options.session_options,
|
|
158
166
|
create_route_specs: options.create_route_specs,
|
|
159
167
|
db,
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
},
|
|
164
|
-
on_audit_event: options.on_audit_event,
|
|
168
|
+
rpc_endpoints: options.rpc_endpoints,
|
|
169
|
+
app_options: options.app_options,
|
|
170
|
+
audit_factory,
|
|
165
171
|
});
|
|
166
172
|
authed_account = await test_app.create_account({
|
|
167
173
|
username: 'sse_authed',
|
package/dist/testing/stubs.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ import type { AppServerContext } from '../server/app_server.js';
|
|
|
8
8
|
import { Db } from '../db/db.js';
|
|
9
9
|
import { type RouteSpec } from '../http/route_spec.js';
|
|
10
10
|
import { type AppSurfaceSpec, type RpcEndpointSpec } from '../http/surface.js';
|
|
11
|
+
import type { WsEndpointSpec } from '../actions/ws_endpoint_spec.js';
|
|
11
12
|
import type { EventSpec } from '../realtime/sse.js';
|
|
12
13
|
import { type AuditLogSse } from '../realtime/sse_auth_guard.js';
|
|
13
14
|
/**
|
|
@@ -116,6 +117,16 @@ export interface CreateTestAppSurfaceSpecOptions {
|
|
|
116
117
|
* the stub `AppServerContext` this helper already builds.
|
|
117
118
|
*/
|
|
118
119
|
rpc_endpoints?: Array<RpcEndpointSpec> | ((ctx: AppServerContext) => Array<RpcEndpointSpec>);
|
|
120
|
+
/**
|
|
121
|
+
* WebSocket endpoint specs for surface generation. Symmetric with
|
|
122
|
+
* `create_app_server`'s `ws_endpoints` option — pass the same value
|
|
123
|
+
* to both entry points so the attack surface tests see the same WS
|
|
124
|
+
* endpoints production auto-mounts. The factory runs once against
|
|
125
|
+
* the stub `AppServerContext` this helper already builds. No
|
|
126
|
+
* `upgradeWebSocket` needed — this helper produces an `AppSurfaceSpec`
|
|
127
|
+
* only, never mounts.
|
|
128
|
+
*/
|
|
129
|
+
ws_endpoints?: ReadonlyArray<WsEndpointSpec> | ((ctx: AppServerContext) => ReadonlyArray<WsEndpointSpec>);
|
|
119
130
|
/** Transform middleware array (e.g., tx's `extend_middleware_for_tx_binary`). */
|
|
120
131
|
transform_middleware?: (specs: Array<MiddlewareSpec>) => Array<MiddlewareSpec>;
|
|
121
132
|
/** Bootstrap route prefix (default: `'/api/account'`). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stubs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/stubs.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"stubs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/stubs.ts"],"names":[],"mappings":"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"}
|
package/dist/testing/stubs.js
CHANGED
|
@@ -237,6 +237,9 @@ export const create_test_app_surface_spec = (options) => {
|
|
|
237
237
|
actions: endpoint.actions,
|
|
238
238
|
log: ctx.deps.log,
|
|
239
239
|
})) ?? [];
|
|
240
|
+
// Resolve ws endpoints (mirrors create_app_server). Surface-only —
|
|
241
|
+
// no `register_ws_endpoint` call here, so no `upgradeWebSocket` needed.
|
|
242
|
+
const resolved_ws_endpoints = typeof options.ws_endpoints === 'function' ? options.ws_endpoints(ctx) : options.ws_endpoints;
|
|
240
243
|
const route_specs = [
|
|
241
244
|
...consumer_routes,
|
|
242
245
|
...rpc_route_specs,
|
|
@@ -252,5 +255,6 @@ export const create_test_app_surface_spec = (options) => {
|
|
|
252
255
|
env_schema: options.env_schema ?? BaseServerEnv,
|
|
253
256
|
event_specs: options.event_specs,
|
|
254
257
|
rpc_endpoints: resolved_rpc_endpoints,
|
|
258
|
+
ws_endpoints: resolved_ws_endpoints,
|
|
255
259
|
});
|
|
256
260
|
};
|
|
@@ -96,6 +96,52 @@ export interface ErrorSchemaAuditEntry {
|
|
|
96
96
|
* @returns audit entries for every route x status combination
|
|
97
97
|
*/
|
|
98
98
|
export declare const audit_error_schema_tightness: (surface: AppSurface) => Array<ErrorSchemaAuditEntry>;
|
|
99
|
+
/**
|
|
100
|
+
* Every RPC method on every endpoint has a non-empty `description`.
|
|
101
|
+
*
|
|
102
|
+
* Parallel of `assert_descriptions_present` over `surface.rpc_endpoints`.
|
|
103
|
+
* Empty descriptions on RPC methods leak through `library.json` codegen and
|
|
104
|
+
* consumer-facing docs without the route-level check catching them.
|
|
105
|
+
*/
|
|
106
|
+
export declare const assert_rpc_method_descriptions_present: (surface: AppSurface) => void;
|
|
107
|
+
/**
|
|
108
|
+
* Every WS method on every endpoint has a non-empty `description`.
|
|
109
|
+
*
|
|
110
|
+
* Parallel of `assert_descriptions_present` over `surface.ws_endpoints`.
|
|
111
|
+
* Same rationale as `assert_rpc_method_descriptions_present` — codegen +
|
|
112
|
+
* surface explorer consume the description, blank values surface as `''`.
|
|
113
|
+
*/
|
|
114
|
+
export declare const assert_ws_method_descriptions_present: (surface: AppSurface) => void;
|
|
115
|
+
/**
|
|
116
|
+
* Every WS endpoint's `methods` includes every protocol action method
|
|
117
|
+
* (`heartbeat`, `cancel`).
|
|
118
|
+
*
|
|
119
|
+
* Consumers register WS endpoints by spreading `protocol_actions` from
|
|
120
|
+
* `actions/protocol.ts` before their own actions:
|
|
121
|
+
*
|
|
122
|
+
* ```ts
|
|
123
|
+
* ws_endpoints: [{path: '/api/ws', actions: [...protocol_actions, ...consumer_actions], ...}]
|
|
124
|
+
* ```
|
|
125
|
+
*
|
|
126
|
+
* Forgetting the spread compiles cleanly but breaks at runtime: client-side
|
|
127
|
+
* heartbeats and `cancel` notifications get `method_not_found` from the
|
|
128
|
+
* dispatcher, so disconnect detection silently regresses and per-request
|
|
129
|
+
* cancel never aborts the matching handler. Catch the mistake at the
|
|
130
|
+
* surface layer rather than at runtime.
|
|
131
|
+
*/
|
|
132
|
+
export declare const assert_ws_endpoints_include_protocol_actions: (surface: AppSurface) => void;
|
|
133
|
+
/**
|
|
134
|
+
* WS methods follow the kind ⇔ auth biconditional emitted by surface
|
|
135
|
+
* generation: `kind === 'remote_notification' ⟺ auth === null`.
|
|
136
|
+
*
|
|
137
|
+
* `generate_app_surface` produces this shape directly from the action
|
|
138
|
+
* spec union (notifications carry `auth: null` per `ActionSpecUnion`;
|
|
139
|
+
* `request_response` carries a `RouteAuth`). The assertion guards against
|
|
140
|
+
* drift if a future surface emitter, transform, or test fixture violates
|
|
141
|
+
* it — and gives consumers a clear failure message when a hand-built
|
|
142
|
+
* surface mocks the shape incorrectly.
|
|
143
|
+
*/
|
|
144
|
+
export declare const assert_ws_notifications_have_null_auth: (surface: AppSurface) => void;
|
|
99
145
|
/**
|
|
100
146
|
* Configuration for security policy invariants.
|
|
101
147
|
*
|
|
@@ -146,7 +192,9 @@ export declare const assert_no_unexpected_public_mutations: (surface: AppSurface
|
|
|
146
192
|
*
|
|
147
193
|
* Note: RPC endpoints (`create_rpc_endpoint`) use `input: z.null()` on their
|
|
148
194
|
* route specs — the dispatcher handles body/query parsing internally. Real input
|
|
149
|
-
* schemas live in `rpc_endpoints` surface, not on routes
|
|
195
|
+
* schemas live in `rpc_endpoints` surface, not on routes; see
|
|
196
|
+
* `assert_rpc_ws_surface_invariants` for the parallel checks over RPC/WS
|
|
197
|
+
* method shapes.
|
|
150
198
|
*/
|
|
151
199
|
export declare const assert_mutation_routes_use_post: (surface: AppSurface) => void;
|
|
152
200
|
/**
|
|
@@ -223,6 +271,23 @@ export declare const assert_error_schema_tightness: (surface: AppSurface, option
|
|
|
223
271
|
* the offending route and the missing/inconsistent field.
|
|
224
272
|
*/
|
|
225
273
|
export declare const assert_surface_invariants: (surface: AppSurface) => void;
|
|
274
|
+
/**
|
|
275
|
+
* Run all RPC / WS structural invariants. Options-free — applies
|
|
276
|
+
* universally to the `surface.rpc_endpoints` and `surface.ws_endpoints`
|
|
277
|
+
* slots produced by `generate_app_surface`.
|
|
278
|
+
*
|
|
279
|
+
* Parallel of `assert_surface_invariants` for the non-REST surfaces.
|
|
280
|
+
* Within-endpoint duplicate method names and the auth-shape biconditional
|
|
281
|
+
* are already enforced at startup by `compile_action_registry` (see
|
|
282
|
+
* `actions/CLAUDE.md` §Registry compile) — these assertions cover only
|
|
283
|
+
* the contract-surface concerns that a runtime registration check
|
|
284
|
+
* cannot: empty descriptions, missing protocol-action spread on WS
|
|
285
|
+
* endpoints, and kind ⇔ auth drift on WS methods.
|
|
286
|
+
*
|
|
287
|
+
* @throws AssertionError on the first invariant violation; the message
|
|
288
|
+
* names the offending endpoint, method, and field.
|
|
289
|
+
*/
|
|
290
|
+
export declare const assert_rpc_ws_surface_invariants: (surface: AppSurface) => void;
|
|
226
291
|
/**
|
|
227
292
|
* Run security policy invariants. Configurable with sensible defaults.
|
|
228
293
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"surface_invariants.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/surface_invariants.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAuB7B,OAAO,KAAK,EAAC,UAAU,EAAuB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"surface_invariants.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/surface_invariants.ts"],"names":[],"mappings":"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"}
|