@fuzdev/fuz_app 0.63.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 +124 -11
- 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/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 +79 -15
- package/dist/auth/account_action_specs.d.ts +1 -1
- 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 +31 -1
- 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 +55 -8
- package/dist/auth/account_schema.d.ts +3 -3
- 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/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_schema.d.ts +5 -3
- package/dist/auth/audit_log_schema.d.ts.map +1 -1
- package/dist/auth/audit_log_schema.js +5 -3
- package/dist/auth/bootstrap_routes.d.ts +1 -1
- package/dist/auth/invite_schema.d.ts +2 -2
- 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/http/CLAUDE.md +26 -10
- 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 +64 -28
- 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 +3 -5
- 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/SurfaceExplorer.svelte +161 -2
- package/dist/ui/SurfaceExplorer.svelte.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import './assert_dev_env.js';
|
|
2
|
+
import { type AuditEmitter, type CreateAuditEmitterOptions } from '../auth/audit_emitter.js';
|
|
3
|
+
import type { AuditLogInput } from '../auth/audit_log_schema.js';
|
|
4
|
+
import type { AuditFactory } from '../server/app_backend.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 declare const install_audit_drift_guard: () => void;
|
|
25
|
+
/**
|
|
26
|
+
* Marker pushed into a shared sequence array by an emit-recording
|
|
27
|
+
* `audit_factory`. Pair with `RecordedClose` from
|
|
28
|
+
* `connection_closer_helpers.ts` to test close-vs-emit ordering at
|
|
29
|
+
* handler call sites — see `create_emit_ordering_audit_factory` below.
|
|
30
|
+
*/
|
|
31
|
+
export interface AuditEmitMarker {
|
|
32
|
+
kind: 'emit';
|
|
33
|
+
at: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Pair returned by {@link create_recording_audit_emitter} — the
|
|
37
|
+
* `AuditEmitter` to inject as `deps.audit`, plus the shared `calls`
|
|
38
|
+
* array that records every captured emission. Both fields are live —
|
|
39
|
+
* callers read `calls` after exercising the handler to assert on the
|
|
40
|
+
* audit metadata shape.
|
|
41
|
+
*/
|
|
42
|
+
export interface RecordingAuditEmitter {
|
|
43
|
+
emitter: AuditEmitter;
|
|
44
|
+
calls: Array<AuditLogInput>;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Build a no-op `AuditEmitter` that records every `emit`, `emit_pool`, and
|
|
48
|
+
* `emit_role_grant_target` call into `calls` as an `AuditLogInput`. Use to
|
|
49
|
+
* capture audit metadata shapes in unit tests (e.g. password change failure
|
|
50
|
+
* outcome, role-grant create denial) without standing up the full PGlite +
|
|
51
|
+
* `query_audit_log` pipeline.
|
|
52
|
+
*
|
|
53
|
+
* **Capture scope — all four production fan-out shapes.**
|
|
54
|
+
* `emit_role_grant_target` mirrors `create_audit_emitter`'s lift logic in
|
|
55
|
+
* place — `actor_id` / `account_id` / `ip` are populated from `auth` + `ctx`
|
|
56
|
+
* and the `event_type` / `outcome` / `target_*_id` / `metadata` fields
|
|
57
|
+
* forward from the input envelope. Tests asserting on role-grant-shape
|
|
58
|
+
* emissions read out of the same homogeneous `calls` array.
|
|
59
|
+
* `notify` is a no-op; `on_event_chain` is an empty array.
|
|
60
|
+
*
|
|
61
|
+
* `emit` AND `emit_pool` both append to `calls` so cleanup-sweep tests
|
|
62
|
+
* (which use `emit_pool` exclusively — see `auth/cleanup.ts`) can also
|
|
63
|
+
* read assertions off the same array.
|
|
64
|
+
*
|
|
65
|
+
* Pass `calls_ref` to write into a caller-owned array (callers that
|
|
66
|
+
* declared `const events: Array<AuditLogInput> = []` and want to keep
|
|
67
|
+
* the reference). Omit to let the helper allocate a fresh array and
|
|
68
|
+
* return it on the `calls` field of the result.
|
|
69
|
+
*
|
|
70
|
+
* The returned emitter is deliberately NOT frozen — slots stay mutable
|
|
71
|
+
* so a test can override one when it needs bespoke shape (e.g. an
|
|
72
|
+
* `emit_pool` that throws on the first call). The production
|
|
73
|
+
* `create_audit_emitter` freeze invariant exists to catch the
|
|
74
|
+
* `patch_audit_emit_capture` hot-patch footgun against the
|
|
75
|
+
* closure-captured `emit`; the recording emitter has no inner closure,
|
|
76
|
+
* so the freeze isn't load-bearing here.
|
|
77
|
+
*/
|
|
78
|
+
export declare const create_recording_audit_emitter: (calls_ref?: Array<AuditLogInput>) => RecordingAuditEmitter;
|
|
79
|
+
/**
|
|
80
|
+
* Build an `audit_factory` that produces a real `create_audit_emitter`
|
|
81
|
+
* with its `emit` decorated to push a `{kind: 'emit', at: seq.value++}`
|
|
82
|
+
* marker into a shared sequence + events array. Used by the close-vs-emit
|
|
83
|
+
* ordering test to compose against a shared sequence counter (typically
|
|
84
|
+
* `create_recording_closer(seq_ref)` capturing eager-close calls).
|
|
85
|
+
*
|
|
86
|
+
* Pass the returned factory through `create_test_app({audit_factory: …})`
|
|
87
|
+
* — the test backend invokes it with its constructed `{db, log}` and
|
|
88
|
+
* lands the decorated emitter on `backend.deps.audit`. Production
|
|
89
|
+
* handlers dereference `deps.audit.emit` at call time, so the decorator
|
|
90
|
+
* sees every subsequent handler invocation. The underlying `emit` still
|
|
91
|
+
* runs — the decorator records the call, it does not suppress side
|
|
92
|
+
* effects.
|
|
93
|
+
*
|
|
94
|
+
* **Scope — both `emit` and `emit_role_grant_target`.** The decorator
|
|
95
|
+
* is captured by `emit_role_grant_target`'s closure inside
|
|
96
|
+
* `create_audit_emitter` (and re-exposed as the outer `emit` slot), so
|
|
97
|
+
* role-grant-shape emissions land in `events_ref` alongside bare `emit`
|
|
98
|
+
* calls. `emit_pool` and `notify` are not decorated — they take
|
|
99
|
+
* `AuditLogInput` / `AuditLogEvent` directly without going through
|
|
100
|
+
* `emit`, so handler-side `emit_pool` writes (today only
|
|
101
|
+
* `auth/cleanup.ts`) skip capture. Close-firing handlers all reach for
|
|
102
|
+
* `emit` or `emit_role_grant_target`, so the ordering test sees them
|
|
103
|
+
* regardless of which entry point a future refactor picks.
|
|
104
|
+
*
|
|
105
|
+
* Optionally accept `extra_options` to thread `on_audit_event` /
|
|
106
|
+
* `audit_log_config` into the inner emitter — useful when a test wants
|
|
107
|
+
* both ordering capture and a real SSE/WS guard wired into the same
|
|
108
|
+
* emitter chain.
|
|
109
|
+
*/
|
|
110
|
+
export declare const create_emit_ordering_audit_factory: <E extends {
|
|
111
|
+
kind: string;
|
|
112
|
+
at: number;
|
|
113
|
+
}>(seq_ref: {
|
|
114
|
+
value: number;
|
|
115
|
+
}, events_ref: Array<AuditEmitMarker | E>, extra_options?: Omit<CreateAuditEmitterOptions, "db" | "log" | "emit_decorator">) => AuditFactory;
|
|
116
|
+
//# sourceMappingURL=audit_drift_guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit_drift_guard.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/audit_drift_guard.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAU7B,OAAO,EAEN,KAAK,YAAY,EACjB,KAAK,yBAAyB,EAC9B,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,6BAA6B,CAAC;AAC/D,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,0BAA0B,CAAC;AAE3D;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,yBAAyB,QAAO,IAiB5C,CAAC;AAEF;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACX;AAED;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACrC,OAAO,EAAE,YAAY,CAAC;IACtB,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,8BAA8B,GAC1C,YAAY,KAAK,CAAC,aAAa,CAAC,KAC9B,qBA0BF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,kCAAkC,GAAI,CAAC,SAAS;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAC,EACtF,SAAS;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,EACxB,YAAY,KAAK,CAAC,eAAe,GAAG,CAAC,CAAC,EACtC,gBAAgB,IAAI,CAAC,yBAAyB,EAAE,IAAI,GAAG,KAAK,GAAG,gBAAgB,CAAC,KAC9E,YAWF,CAAC"}
|
|
@@ -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
|
};
|