@fuzdev/fuz_app 0.112.0 → 0.114.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 +46 -20
- package/dist/actions/action_dispatcher.d.ts +1 -1
- package/dist/actions/action_dispatcher.d.ts.map +1 -1
- package/dist/actions/action_dispatcher.js +22 -16
- package/dist/actions/action_event.d.ts +18 -2
- package/dist/actions/action_event.d.ts.map +1 -1
- package/dist/actions/action_event.js +63 -19
- package/dist/actions/action_event_types.d.ts +22 -0
- package/dist/actions/action_event_types.d.ts.map +1 -1
- package/dist/actions/action_event_types.js +19 -0
- package/dist/actions/compile_action_registry.d.ts +4 -2
- package/dist/actions/compile_action_registry.d.ts.map +1 -1
- package/dist/actions/compile_action_registry.js +8 -3
- package/dist/actions/frontend_rpc_client.d.ts +6 -0
- package/dist/actions/frontend_rpc_client.d.ts.map +1 -1
- package/dist/actions/frontend_rpc_client.js +2 -1
- package/dist/actions/heartbeat.d.ts +8 -4
- package/dist/actions/heartbeat.d.ts.map +1 -1
- package/dist/actions/heartbeat.js +8 -4
- package/dist/actions/peer_ping.d.ts.map +1 -1
- package/dist/actions/peer_ping.js +3 -1
- package/dist/actions/perform_action.d.ts +1 -1
- package/dist/actions/perform_action.d.ts.map +1 -1
- package/dist/actions/perform_action.js +6 -4
- package/dist/actions/register_action_ws.d.ts +13 -0
- package/dist/actions/register_action_ws.d.ts.map +1 -1
- package/dist/actions/register_action_ws.js +23 -2
- package/dist/actions/rpc_client.d.ts +1 -1
- package/dist/actions/rpc_client.d.ts.map +1 -1
- package/dist/actions/rpc_client.js +2 -1
- package/dist/actions/socket.svelte.d.ts +53 -10
- package/dist/actions/socket.svelte.d.ts.map +1 -1
- package/dist/actions/socket.svelte.js +84 -23
- package/dist/actions/transports.d.ts +24 -0
- package/dist/actions/transports.d.ts.map +1 -1
- package/dist/actions/transports.js +30 -0
- package/dist/actions/transports_http.d.ts +11 -4
- package/dist/actions/transports_http.d.ts.map +1 -1
- package/dist/actions/transports_http.js +63 -18
- package/dist/actions/transports_ws.d.ts +28 -3
- package/dist/actions/transports_ws.d.ts.map +1 -1
- package/dist/actions/transports_ws.js +33 -4
- package/dist/actions/ws_endpoint_spec.d.ts +7 -0
- package/dist/actions/ws_endpoint_spec.d.ts.map +1 -1
- package/dist/auth/CLAUDE.md +6 -1
- package/dist/auth/audit_log_route_schema.d.ts.map +1 -1
- package/dist/auth/audit_log_route_schema.js +12 -1
- package/dist/auth/role_grant_offer_action_specs.d.ts +2 -1
- package/dist/auth/role_grant_offer_action_specs.d.ts.map +1 -1
- package/dist/auth/role_grant_offer_action_specs.js +2 -1
- package/dist/db/fact_disk_storage.js +1 -1
- package/dist/http/CLAUDE.md +10 -6
- package/dist/http/auth_shape.d.ts +19 -6
- package/dist/http/auth_shape.d.ts.map +1 -1
- package/dist/http/auth_shape.js +19 -6
- package/dist/http/jsonrpc_helpers.d.ts +0 -5
- package/dist/http/jsonrpc_helpers.d.ts.map +1 -1
- package/dist/http/jsonrpc_helpers.js +0 -13
- package/dist/http/schema_helpers.d.ts +56 -0
- package/dist/http/schema_helpers.d.ts.map +1 -1
- package/dist/http/schema_helpers.js +91 -0
- package/dist/http/surface_query.d.ts +29 -4
- package/dist/http/surface_query.d.ts.map +1 -1
- package/dist/http/surface_query.js +30 -5
- package/dist/realtime/sse_auth_guard.d.ts +9 -3
- package/dist/realtime/sse_auth_guard.d.ts.map +1 -1
- package/dist/realtime/sse_auth_guard.js +9 -3
- package/dist/server/app_server.d.ts.map +1 -1
- package/dist/server/app_server.js +1 -0
- package/dist/testing/CLAUDE.md +18 -13
- package/dist/testing/attack_surface.d.ts +5 -2
- package/dist/testing/attack_surface.d.ts.map +1 -1
- package/dist/testing/attack_surface.js +45 -17
- package/dist/testing/auth_apps.d.ts +25 -0
- package/dist/testing/auth_apps.d.ts.map +1 -1
- package/dist/testing/auth_apps.js +34 -5
- package/dist/testing/cross_backend/peer_ping_ws.d.ts.map +1 -1
- package/dist/testing/cross_backend/peer_ping_ws.js +18 -0
- package/dist/testing/cross_backend/testing_reset_actions.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_reset_actions.js +3 -2
- package/dist/testing/cross_backend/token_scope_surface.d.ts.map +1 -1
- package/dist/testing/cross_backend/token_scope_surface.js +36 -7
- package/dist/testing/cross_backend/ws_round_trip.d.ts +11 -3
- package/dist/testing/cross_backend/ws_round_trip.d.ts.map +1 -1
- package/dist/testing/cross_backend/ws_round_trip.js +74 -12
- package/dist/testing/surface_invariants.d.ts +7 -1
- package/dist/testing/surface_invariants.d.ts.map +1 -1
- package/dist/testing/surface_invariants.js +11 -5
- package/dist/testing/transports/ws_client.d.ts +6 -0
- package/dist/testing/transports/ws_client.d.ts.map +1 -1
- package/dist/testing/transports/ws_transport.d.ts.map +1 -1
- package/dist/testing/transports/ws_transport.js +6 -1
- package/dist/testing/ws_round_trip.d.ts.map +1 -1
- package/dist/testing/ws_round_trip.js +5 -0
- package/dist/ui/AdminAccounts.svelte +6 -4
- package/dist/ui/AdminAccounts.svelte.d.ts.map +1 -1
- package/dist/ui/AdminInvites.svelte +3 -3
- package/dist/ui/AdminInvites.svelte.d.ts.map +1 -1
- package/dist/ui/AdminOverview.svelte +10 -10
- package/dist/ui/AdminOverview.svelte.d.ts.map +1 -1
- package/dist/ui/AdminRoleGrantHistory.svelte +7 -7
- package/dist/ui/AdminRoleGrantHistory.svelte.d.ts.map +1 -1
- package/dist/ui/AdminSettings.svelte +1 -1
- package/dist/ui/RoleGrantOfferInbox.svelte +4 -1
- package/dist/ui/RoleGrantOfferInbox.svelte.d.ts.map +1 -1
- package/dist/ui/SurfaceExplorer.svelte +33 -17
- package/dist/ui/SurfaceExplorer.svelte.d.ts.map +1 -1
- package/dist/ui/form_state.svelte.d.ts +9 -4
- package/dist/ui/form_state.svelte.d.ts.map +1 -1
- package/dist/ui/form_state.svelte.js +28 -8
- package/package.json +10 -10
- package/dist/actions/request_tracker.svelte.d.ts +0 -77
- package/dist/actions/request_tracker.svelte.d.ts.map +0 -1
- package/dist/actions/request_tracker.svelte.js +0 -169
|
@@ -24,7 +24,13 @@ import '../assert_dev_env.js';
|
|
|
24
24
|
* upgrade time (not per message), so the negative cases assert the upgrade
|
|
25
25
|
* itself rejects rather than a per-message error frame.
|
|
26
26
|
*
|
|
27
|
-
*
|
|
27
|
+
* Two spine-parity cases follow: `heartbeat` answers the parameterless shapes
|
|
28
|
+
* (absent, `{}`) and refuses a declared param with `invalid_params`, and a
|
|
29
|
+
* message over the backend's cap (`max_message_bytes`, default
|
|
30
|
+
* `DEFAULT_WS_MAX_MESSAGE_BYTES`) closes the socket with
|
|
31
|
+
* `WS_CLOSE_MESSAGE_TOO_BIG`.
|
|
32
|
+
*
|
|
33
|
+
* A final case (gated on `rpc_path`) covers server-initiated close: an
|
|
28
34
|
* authenticated socket is dropped when the account's sessions are revoked
|
|
29
35
|
* mid-connection. Per-message dispatch never re-checks credential validity,
|
|
30
36
|
* so the live socket survives on the audit-fed `create_ws_auth_guard` seam —
|
|
@@ -43,29 +49,31 @@ import '../assert_dev_env.js';
|
|
|
43
49
|
import { assert, describe } from 'vitest';
|
|
44
50
|
import { assert_rejects } from '@fuzdev/fuz_util/testing.ts';
|
|
45
51
|
import { heartbeat_action_spec } from '../../actions/heartbeat.js';
|
|
52
|
+
import { DEFAULT_WS_MAX_MESSAGE_BYTES, WS_CLOSE_MESSAGE_TOO_BIG } from '../../actions/transports.js';
|
|
46
53
|
import { account_session_revoke_all_action_spec } from '../../auth/account_action_specs.js';
|
|
54
|
+
import { JSONRPC_ERROR_CODES } from '../../http/jsonrpc_errors.js';
|
|
55
|
+
import { is_response_for } from '../transports/ws_client.js';
|
|
47
56
|
import { create_ws_transport } from '../transports/ws_transport.js';
|
|
48
57
|
import { create_rpc_post_init } from '../rpc_helpers.js';
|
|
49
58
|
import { test_if } from './capabilities.js';
|
|
50
59
|
/** Origin guaranteed to fail the `http://localhost:*` allowlist the test backends run with. */
|
|
51
60
|
const DISALLOWED_ORIGIN = 'http://disallowed.example';
|
|
52
61
|
/**
|
|
53
|
-
* Register the cross-process WS round-trip suite
|
|
54
|
-
*
|
|
55
|
-
*
|
|
62
|
+
* Register the cross-process WS round-trip suite over a real upgrade: authed
|
|
63
|
+
* `heartbeat` round-trip, `heartbeat`'s parameterless-shape contract, an
|
|
64
|
+
* oversized message closing with `WS_CLOSE_MESSAGE_TOO_BIG`, anonymous-upgrade
|
|
65
|
+
* refusal, disallowed-origin refusal, and — when `rpc_path` is supplied —
|
|
56
66
|
* session-revocation closing the live socket.
|
|
57
67
|
*/
|
|
58
68
|
export const describe_cross_process_ws_tests = (options) => {
|
|
59
|
-
const { setup_test, capabilities, base_url, ws_path, origin, rpc_path } = options;
|
|
69
|
+
const { setup_test, capabilities, base_url, ws_path, origin, rpc_path, max_message_bytes = DEFAULT_WS_MAX_MESSAGE_BYTES } = options;
|
|
70
|
+
const open_authed = async () => {
|
|
71
|
+
const fixture = await setup_test();
|
|
72
|
+
return create_ws_transport({ base_url, ws_path, cookies: fixture.transport.cookies(), origin });
|
|
73
|
+
};
|
|
60
74
|
describe('cross-process websocket', () => {
|
|
61
75
|
test_if(capabilities.ws, 'authenticated upgrade round-trips heartbeat', async () => {
|
|
62
|
-
const
|
|
63
|
-
const client = await create_ws_transport({
|
|
64
|
-
base_url,
|
|
65
|
-
ws_path,
|
|
66
|
-
cookies: fixture.transport.cookies(),
|
|
67
|
-
origin
|
|
68
|
-
});
|
|
76
|
+
const client = await open_authed();
|
|
69
77
|
try {
|
|
70
78
|
const result = await client.request(1, heartbeat_action_spec.method, {});
|
|
71
79
|
assert.deepStrictEqual(result, {}, 'heartbeat returns an empty result over the wire');
|
|
@@ -74,6 +82,60 @@ export const describe_cross_process_ws_tests = (options) => {
|
|
|
74
82
|
await client.close();
|
|
75
83
|
}
|
|
76
84
|
});
|
|
85
|
+
// `heartbeat` is parameterless on both spines (`z.void()` /
|
|
86
|
+
// `require_void_params`): the empty shapes are the no-arg call, and a
|
|
87
|
+
// declared param is `invalid_params`, not ignored.
|
|
88
|
+
test_if(capabilities.ws, 'heartbeat admits only the parameterless shapes', async () => {
|
|
89
|
+
const client = await open_authed();
|
|
90
|
+
try {
|
|
91
|
+
const cases = [
|
|
92
|
+
[1, {}, true],
|
|
93
|
+
[2, { params: {} }, true],
|
|
94
|
+
[3, { params: { stray: 1 } }, false]
|
|
95
|
+
];
|
|
96
|
+
for (const [id, params, ok] of cases) {
|
|
97
|
+
await client.send({
|
|
98
|
+
jsonrpc: '2.0',
|
|
99
|
+
id,
|
|
100
|
+
method: heartbeat_action_spec.method,
|
|
101
|
+
...params
|
|
102
|
+
});
|
|
103
|
+
const frame = await client.wait_for(is_response_for(id));
|
|
104
|
+
const label = JSON.stringify(params);
|
|
105
|
+
if (ok) {
|
|
106
|
+
assert.ok('result' in frame, `${label}: ${JSON.stringify(frame)}`);
|
|
107
|
+
assert.deepStrictEqual(frame.result, {}, label);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
assert.ok('error' in frame, `${label}: ${JSON.stringify(frame)}`);
|
|
111
|
+
assert.strictEqual(frame.error.code, JSONRPC_ERROR_CODES.invalid_params, label);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
finally {
|
|
116
|
+
await client.close();
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
// Both spines cap an inbound message (`DEFAULT_WS_MAX_MESSAGE_BYTES` by
|
|
120
|
+
// default) and close the socket on a larger one rather than replying.
|
|
121
|
+
test_if(capabilities.ws, 'an oversized message closes the socket with WS_CLOSE_MESSAGE_TOO_BIG', async () => {
|
|
122
|
+
const client = await open_authed();
|
|
123
|
+
try {
|
|
124
|
+
await client.send({
|
|
125
|
+
jsonrpc: '2.0',
|
|
126
|
+
id: 1,
|
|
127
|
+
method: heartbeat_action_spec.method,
|
|
128
|
+
params: { pad: 'x'.repeat(max_message_bytes) }
|
|
129
|
+
});
|
|
130
|
+
const closed = await client.wait_for_close(5000);
|
|
131
|
+
assert.ok(closed, 'socket did not close within 5s of an oversized message');
|
|
132
|
+
assert.strictEqual(client.close_code, WS_CLOSE_MESSAGE_TOO_BIG);
|
|
133
|
+
}
|
|
134
|
+
finally {
|
|
135
|
+
// the server may reset the connection under the unread tail
|
|
136
|
+
await client.close().catch(() => { });
|
|
137
|
+
}
|
|
138
|
+
});
|
|
77
139
|
// Per-connection auth fires at upgrade time (`require_auth`), so an
|
|
78
140
|
// anonymous socket never opens — the upgrade is refused outright.
|
|
79
141
|
test_if(capabilities.ws, 'anonymous upgrade is refused', async () => {
|
|
@@ -5,7 +5,13 @@ import type { AppSurface } from '../http/surface.js';
|
|
|
5
5
|
*/
|
|
6
6
|
export declare const assert_protected_routes_declare_401: (surface: AppSurface) => void;
|
|
7
7
|
/**
|
|
8
|
-
* Every
|
|
8
|
+
* Every route with an authority gate that can answer 403 declares one — a
|
|
9
|
+
* role gate, or a credential-channel gate of any kind (keeper included).
|
|
10
|
+
*
|
|
11
|
+
* The credential half is not just the keeper routes: the session-only gates
|
|
12
|
+
* point the same axis the other way and refuse with the same status, so a
|
|
13
|
+
* route carrying one and no 403 schema would have its denial body go
|
|
14
|
+
* unvalidated by the DEV-only error-schema check.
|
|
9
15
|
*/
|
|
10
16
|
export declare const assert_role_routes_declare_403: (surface: AppSurface) => void;
|
|
11
17
|
/**
|
|
@@ -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,EAAE,UAAU,EAAwB,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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"}
|
|
@@ -18,7 +18,7 @@ import './assert_dev_env.js';
|
|
|
18
18
|
*/
|
|
19
19
|
import { assert } from 'vitest';
|
|
20
20
|
import { middleware_applies } from '../http/schema_helpers.js';
|
|
21
|
-
import { filter_protected_routes, filter_role_routes, filter_keeper_routes, filter_routes_with_input, filter_routes_with_params, filter_routes_with_query, filter_public_routes, format_route_key } from '../http/surface_query.js';
|
|
21
|
+
import { filter_protected_routes, filter_role_routes, filter_keeper_routes, filter_credential_gated_routes, filter_routes_with_input, filter_routes_with_params, filter_routes_with_query, filter_public_routes, format_route_key } from '../http/surface_query.js';
|
|
22
22
|
import { PROTOCOL_ACTION_METHODS } from '../actions/action_codegen.js';
|
|
23
23
|
// --- Structural invariants ---
|
|
24
24
|
/**
|
|
@@ -31,13 +31,19 @@ export const assert_protected_routes_declare_401 = (surface) => {
|
|
|
31
31
|
}
|
|
32
32
|
};
|
|
33
33
|
/**
|
|
34
|
-
* Every
|
|
34
|
+
* Every route with an authority gate that can answer 403 declares one — a
|
|
35
|
+
* role gate, or a credential-channel gate of any kind (keeper included).
|
|
36
|
+
*
|
|
37
|
+
* The credential half is not just the keeper routes: the session-only gates
|
|
38
|
+
* point the same axis the other way and refuse with the same status, so a
|
|
39
|
+
* route carrying one and no 403 schema would have its denial body go
|
|
40
|
+
* unvalidated by the DEV-only error-schema check.
|
|
35
41
|
*/
|
|
36
42
|
export const assert_role_routes_declare_403 = (surface) => {
|
|
37
43
|
const role_routes = filter_role_routes(surface);
|
|
38
|
-
const
|
|
39
|
-
for (const route of [...role_routes, ...
|
|
40
|
-
assert.ok(route.error_schemas && '403' in route.error_schemas, `${format_route_key(route)}
|
|
44
|
+
const credential_gated_routes = filter_credential_gated_routes(surface);
|
|
45
|
+
for (const route of [...role_routes, ...credential_gated_routes]) {
|
|
46
|
+
assert.ok(route.error_schemas && '403' in route.error_schemas, `${format_route_key(route)} has a role or credential gate but missing 403 error schema`);
|
|
41
47
|
}
|
|
42
48
|
};
|
|
43
49
|
/**
|
|
@@ -124,6 +124,12 @@ export interface WsClient {
|
|
|
124
124
|
* in `testing/sse_round_trip.ts`.
|
|
125
125
|
*/
|
|
126
126
|
wait_for_close: (timeout_ms?: number) => Promise<boolean>;
|
|
127
|
+
/**
|
|
128
|
+
* The close code of the connection once it has closed — the server's
|
|
129
|
+
* (e.g. `WS_CLOSE_MESSAGE_TOO_BIG`), the test's own, or `1006` when the
|
|
130
|
+
* connection dropped without a close frame. `null` while open.
|
|
131
|
+
*/
|
|
132
|
+
readonly close_code: number | null;
|
|
127
133
|
/** Every message the server has sent, in arrival order. */
|
|
128
134
|
readonly messages: ReadonlyArray<unknown>;
|
|
129
135
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ws_client.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/transports/ws_client.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ws_client.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/transports/ws_client.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ws_transport.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/transports/ws_transport.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAuB9B,OAAO,EAMN,KAAK,QAAQ,EACb,KAAK,kBAAkB,EAEvB,MAAM,gBAAgB,CAAC;AAGxB,sDAAsD;AACtD,MAAM,WAAW,kBAAkB;IAClC,gHAAgH;IAChH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,8DAA8D;IAC9D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACxC;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC;;;;;;;OAOG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,kBAAkB,CAAC;CACzC;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,mBAAmB,GAAU,SAAS,kBAAkB,KAAG,OAAO,CAAC,QAAQ,
|
|
1
|
+
{"version":3,"file":"ws_transport.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/transports/ws_transport.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAuB9B,OAAO,EAMN,KAAK,QAAQ,EACb,KAAK,kBAAkB,EAEvB,MAAM,gBAAgB,CAAC;AAGxB,sDAAsD;AACtD,MAAM,WAAW,kBAAkB;IAClC,gHAAgH;IAChH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,8DAA8D;IAC9D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACxC;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC;;;;;;;OAOG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,kBAAkB,CAAC;CACzC;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,mBAAmB,GAAU,SAAS,kBAAkB,KAAG,OAAO,CAAC,QAAQ,CAmJvF,CAAC"}
|
|
@@ -69,7 +69,9 @@ export const create_ws_transport = async (options) => {
|
|
|
69
69
|
socket.send(JSON.stringify(message));
|
|
70
70
|
});
|
|
71
71
|
});
|
|
72
|
-
|
|
72
|
+
let close_code = null;
|
|
73
|
+
socket.on('close', (code) => {
|
|
74
|
+
close_code = code;
|
|
73
75
|
for (const resolve of close_resolvers)
|
|
74
76
|
resolve();
|
|
75
77
|
close_resolvers = [];
|
|
@@ -140,6 +142,9 @@ export const create_ws_transport = async (options) => {
|
|
|
140
142
|
get messages() {
|
|
141
143
|
return received;
|
|
142
144
|
},
|
|
145
|
+
get close_code() {
|
|
146
|
+
return close_code;
|
|
147
|
+
},
|
|
143
148
|
send: send_impl,
|
|
144
149
|
async request(id, method, params, timeout_ms) {
|
|
145
150
|
await send_impl(create_jsonrpc_request(method, params, id));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ws_round_trip.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/ws_round_trip.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ws_round_trip.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/ws_round_trip.ts"],"names":[],"mappings":"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"}
|
|
@@ -223,6 +223,7 @@ export const create_ws_test_harness = (options) => {
|
|
|
223
223
|
// test closed the socket.
|
|
224
224
|
const close_waiters = [];
|
|
225
225
|
let is_closed = false;
|
|
226
|
+
let close_code = null;
|
|
226
227
|
// Captured in `ws.close` below; `client.close(...)` returns it so
|
|
227
228
|
// tests can await async `on_socket_close` cleanup.
|
|
228
229
|
let close_pending = null;
|
|
@@ -240,6 +241,7 @@ export const create_ws_test_harness = (options) => {
|
|
|
240
241
|
if (is_closed)
|
|
241
242
|
return;
|
|
242
243
|
is_closed = true;
|
|
244
|
+
close_code = code ?? 1000;
|
|
243
245
|
for (const resolve of close_waiters.splice(0))
|
|
244
246
|
resolve();
|
|
245
247
|
const close_event = new Event('close');
|
|
@@ -326,6 +328,9 @@ export const create_ws_test_harness = (options) => {
|
|
|
326
328
|
if (close_pending)
|
|
327
329
|
await close_pending;
|
|
328
330
|
},
|
|
331
|
+
get close_code() {
|
|
332
|
+
return close_code;
|
|
333
|
+
},
|
|
329
334
|
wait_for: wait_for_impl,
|
|
330
335
|
wait_for_close: (timeout_ms = WS_CLIENT_DEFAULT_TIMEOUT_MS) => {
|
|
331
336
|
if (is_closed)
|
|
@@ -44,9 +44,9 @@
|
|
|
44
44
|
<h1>accounts</h1>
|
|
45
45
|
{#if admin_accounts.account_count > 0}
|
|
46
46
|
<p>
|
|
47
|
-
<span class="chip color_a"
|
|
48
|
-
|
|
49
|
-
>
|
|
47
|
+
<span class="chip color_a">
|
|
48
|
+
{admin_accounts.account_count} account{admin_accounts.account_count === 1 ? '' : 's'}
|
|
49
|
+
</span>
|
|
50
50
|
</p>
|
|
51
51
|
{/if}
|
|
52
52
|
|
|
@@ -158,7 +158,9 @@
|
|
|
158
158
|
{#each admin_accounts.grantable_roles as role (role)}
|
|
159
159
|
{@const key = grant_key(row.account.id, role)}
|
|
160
160
|
{@const grant_error = admin_accounts.grant.error(key)}
|
|
161
|
-
{#if !row.role_grants.some((p) => p.role === role) &&
|
|
161
|
+
{#if !row.role_grants.some((p) => p.role === role) &&
|
|
162
|
+
!row.pending_offers.some((o) => o.role === role)
|
|
163
|
+
}
|
|
162
164
|
<ConfirmButton
|
|
163
165
|
onconfirm={() => admin_accounts.submit_grant(row.account.id, role)}
|
|
164
166
|
title="offer {role}"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdminAccounts.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/ui/AdminAccounts.svelte"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AdminAccounts.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/ui/AdminAccounts.svelte"],"names":[],"mappings":"AAqMA,QAAA,MAAM,aAAa,2DAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
|
|
@@ -59,9 +59,9 @@
|
|
|
59
59
|
</section>
|
|
60
60
|
{#if admin_invites.invite_count > 0}
|
|
61
61
|
<p>
|
|
62
|
-
<span class="chip color_a"
|
|
63
|
-
|
|
64
|
-
>
|
|
62
|
+
<span class="chip color_a">
|
|
63
|
+
{admin_invites.unclaimed_count} unclaimed / {admin_invites.invite_count} total
|
|
64
|
+
</span>
|
|
65
65
|
</p>
|
|
66
66
|
{/if}
|
|
67
67
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdminInvites.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/ui/AdminInvites.svelte"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AdminInvites.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/ui/AdminInvites.svelte"],"names":[],"mappings":"AAuJA,QAAA,MAAM,YAAY,2DAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
|
|
@@ -146,9 +146,9 @@
|
|
|
146
146
|
<div class="baseline-row gap_xs font_size_sm mt_sm">
|
|
147
147
|
<span class="text_50">newest session:</span>
|
|
148
148
|
<strong>{most_recent.username}</strong>
|
|
149
|
-
<span class="text_50" title={format_datetime_local(most_recent.created_at)}
|
|
150
|
-
|
|
151
|
-
>
|
|
149
|
+
<span class="text_50" title={format_datetime_local(most_recent.created_at)}>
|
|
150
|
+
{format_relative_time(most_recent.created_at)}
|
|
151
|
+
</span>
|
|
152
152
|
</div>
|
|
153
153
|
{/if}
|
|
154
154
|
{/if}
|
|
@@ -214,9 +214,9 @@
|
|
|
214
214
|
<ul class="compact-list">
|
|
215
215
|
{#each recent_events as event (event.id)}
|
|
216
216
|
<li>
|
|
217
|
-
<span class="text_50 font_size_sm" title={format_datetime_local(event.created_at)}
|
|
218
|
-
|
|
219
|
-
>
|
|
217
|
+
<span class="text_50 font_size_sm" title={format_datetime_local(event.created_at)}>
|
|
218
|
+
{format_relative_time(event.created_at)}
|
|
219
|
+
</span>
|
|
220
220
|
<code class="font_size_sm">{event.event_type}</code>
|
|
221
221
|
{#if event.outcome === 'failure'}
|
|
222
222
|
<span class="chip font_size_sm color_c">fail</span>
|
|
@@ -251,9 +251,9 @@
|
|
|
251
251
|
<ul class="compact-list">
|
|
252
252
|
{#each role_grant_changes.slice(0, 4) as event (event.id)}
|
|
253
253
|
<li class="font_size_sm">
|
|
254
|
-
<span class="text_50" title={format_datetime_local(event.created_at)}
|
|
255
|
-
|
|
256
|
-
>
|
|
254
|
+
<span class="text_50" title={format_datetime_local(event.created_at)}>
|
|
255
|
+
{format_relative_time(event.created_at)}
|
|
256
|
+
</span>
|
|
257
257
|
<code>{event.event_type === 'role_grant_create' ? 'grant' : 'revoke'}</code>
|
|
258
258
|
{#if event.metadata?.role}
|
|
259
259
|
<span class="chip font_size_sm">{event.metadata.role}</span>
|
|
@@ -309,7 +309,7 @@
|
|
|
309
309
|
label="log out"
|
|
310
310
|
>
|
|
311
311
|
{#snippet popover_button_content()}
|
|
312
|
-
<span class="p_md">
|
|
312
|
+
<span class="p_md">log out</span>
|
|
313
313
|
{/snippet}
|
|
314
314
|
</ConfirmButton>
|
|
315
315
|
</div>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdminOverview.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/ui/AdminOverview.svelte"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AdminOverview.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/ui/AdminOverview.svelte"],"names":[],"mappings":"AA+UA,QAAA,MAAM,aAAa,2DAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
|
|
@@ -74,14 +74,14 @@
|
|
|
74
74
|
{:else if column.key === 'username'}
|
|
75
75
|
<!-- Prefer actor-grain id in the truncated fallback; account is
|
|
76
76
|
the second fallback for events with no actor binding. -->
|
|
77
|
-
<span class="text_50"
|
|
78
|
-
|
|
79
|
-
>
|
|
77
|
+
<span class="text_50">
|
|
78
|
+
{row.username ?? truncate_uuid(row.actor_id ?? row.account_id ?? '?')}
|
|
79
|
+
</span>
|
|
80
80
|
{:else if column.key === 'target_username'}
|
|
81
|
-
<span class="text_50"
|
|
82
|
-
|
|
83
|
-
truncate_uuid(row.target_actor_id ?? row.target_account_id ?? '?')}
|
|
84
|
-
>
|
|
81
|
+
<span class="text_50">
|
|
82
|
+
{row.target_username ??
|
|
83
|
+
truncate_uuid(row.target_actor_id ?? row.target_account_id ?? '?')}
|
|
84
|
+
</span>
|
|
85
85
|
{:else if column.key === 'created_at'}
|
|
86
86
|
<span title={format_datetime_local(row.created_at)}>
|
|
87
87
|
{format_relative_time(row.created_at)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdminRoleGrantHistory.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/ui/AdminRoleGrantHistory.svelte"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AdminRoleGrantHistory.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/ui/AdminRoleGrantHistory.svelte"],"names":[],"mappings":"AAuGA,QAAA,MAAM,qBAAqB,2DAAwC,CAAC;AACpE,KAAK,qBAAqB,GAAG,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACtE,eAAe,qBAAqB,CAAC"}
|
|
@@ -48,7 +48,10 @@
|
|
|
48
48
|
<section class="role-grant-offer-inbox">
|
|
49
49
|
<h2>pending offers</h2>
|
|
50
50
|
|
|
51
|
-
{#if role_grant_offers.list.error ||
|
|
51
|
+
{#if role_grant_offers.list.error ||
|
|
52
|
+
role_grant_offers.accept.error ||
|
|
53
|
+
role_grant_offers.decline.error
|
|
54
|
+
}
|
|
52
55
|
<p class="color_c_50">
|
|
53
56
|
{role_grant_offers.list.error ??
|
|
54
57
|
role_grant_offers.accept.error ??
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RoleGrantOfferInbox.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/ui/RoleGrantOfferInbox.svelte"],"names":[],"mappings":"AAmBA,OAAO,EAA6C,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAE/F,KAAK,gBAAgB,GAAI;IACxB,uEAAuE;IACvE,YAAY,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,CAAC;IACjD;;;;OAIG;IACH,YAAY,CAAC,EAAE,WAAW,CAAC;IAC3B,+DAA+D;IAC/D,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACvC,CAAC;
|
|
1
|
+
{"version":3,"file":"RoleGrantOfferInbox.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/ui/RoleGrantOfferInbox.svelte"],"names":[],"mappings":"AAmBA,OAAO,EAA6C,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAE/F,KAAK,gBAAgB,GAAI;IACxB,uEAAuE;IACvE,YAAY,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,CAAC;IACjD;;;;OAIG;IACH,YAAY,CAAC,EAAE,WAAW,CAAC;IAC3B,+DAA+D;IAC/D,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACvC,CAAC;AAiGH,QAAA,MAAM,mBAAmB,sDAAwC,CAAC;AAClE,KAAK,mBAAmB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAClE,eAAe,mBAAmB,CAAC"}
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import type { AppSurface, AppSurfaceRoute, AppSurfaceDiagnostic } from '../http/surface.js';
|
|
14
14
|
import { surface_auth_summary, format_route_key } from '../http/surface_query.js';
|
|
15
15
|
import {
|
|
16
|
+
is_credential_gated_auth,
|
|
16
17
|
is_keeper_auth,
|
|
17
18
|
is_plain_authenticated_auth,
|
|
18
19
|
is_public_auth,
|
|
@@ -22,7 +23,7 @@
|
|
|
22
23
|
|
|
23
24
|
const { surface }: { surface: AppSurface } = $props();
|
|
24
25
|
|
|
25
|
-
const auth_types = ['all', 'none', 'authenticated', 'role', 'keeper'] as const;
|
|
26
|
+
const auth_types = ['all', 'none', 'authenticated', 'role', 'credential', 'keeper'] as const;
|
|
26
27
|
|
|
27
28
|
let auth_filter: (typeof auth_types)[number] = $state.raw('all');
|
|
28
29
|
let expanded_route: string | null = $state.raw(null);
|
|
@@ -49,6 +50,8 @@
|
|
|
49
50
|
return is_plain_authenticated_auth(auth);
|
|
50
51
|
case 'role':
|
|
51
52
|
return is_role_auth(auth);
|
|
53
|
+
case 'credential':
|
|
54
|
+
return is_credential_gated_auth(auth) && !is_keeper_auth(auth);
|
|
52
55
|
case 'keeper':
|
|
53
56
|
return is_keeper_auth(auth);
|
|
54
57
|
}
|
|
@@ -90,32 +93,44 @@
|
|
|
90
93
|
if (is_public_auth(auth)) return 'chip color_b';
|
|
91
94
|
if (is_keeper_auth(auth)) return 'chip color_c';
|
|
92
95
|
if (is_role_auth(auth)) return 'chip color_d';
|
|
96
|
+
if (is_credential_gated_auth(auth)) return 'chip color_e';
|
|
93
97
|
if (is_plain_authenticated_auth(auth)) return 'chip color_a';
|
|
94
98
|
return 'chip';
|
|
95
99
|
};
|
|
96
100
|
|
|
97
101
|
const role_count = $derived(Array.from(summary.role.values()).reduce((sum, n) => sum + n, 0));
|
|
102
|
+
const credential_count = $derived(
|
|
103
|
+
Array.from(summary.credential.values()).reduce((sum, n) => sum + n, 0)
|
|
104
|
+
);
|
|
98
105
|
</script>
|
|
99
106
|
|
|
100
107
|
<section>
|
|
101
108
|
<div class="row" style:gap="var(--space_md)" style:flex-wrap="wrap" style:align-items="center">
|
|
102
109
|
<span class="chip">{surface.routes.length} routes</span>
|
|
103
110
|
{#if summary.none > 0}<span class="chip color_b">{summary.none} public</span>{/if}
|
|
104
|
-
{#if summary.authenticated > 0}
|
|
105
|
-
|
|
106
|
-
|
|
111
|
+
{#if summary.authenticated > 0}
|
|
112
|
+
<span class="chip color_a">{summary.authenticated} authenticated</span>
|
|
113
|
+
{/if}
|
|
107
114
|
{#if role_count > 0}<span class="chip color_d">{role_count} role</span>{/if}
|
|
115
|
+
{#if credential_count > 0}
|
|
116
|
+
<span class="chip color_e">{credential_count} credential-gated</span>
|
|
117
|
+
{/if}
|
|
108
118
|
{#if summary.keeper > 0}<span class="chip color_c">{summary.keeper} keeper</span>{/if}
|
|
109
119
|
<span class="chip">{surface.middleware.length} middleware</span>
|
|
110
120
|
{#if rpc_method_count > 0}<span class="chip">{rpc_method_count} rpc methods</span>{/if}
|
|
111
121
|
{#if ws_method_count > 0}<span class="chip">{ws_method_count} ws methods</span>{/if}
|
|
112
122
|
{#if surface.env.length}<span class="chip">{surface.env.length} env</span>{/if}
|
|
113
123
|
{#if surface.events.length}<span class="chip">{surface.events.length} events</span>{/if}
|
|
114
|
-
{#if surface.diagnostics.length}
|
|
124
|
+
{#if surface.diagnostics.length}
|
|
125
|
+
{@const warnings = surface.diagnostics.filter(
|
|
115
126
|
(d: AppSurfaceDiagnostic) => d.level === 'warning'
|
|
116
|
-
)}
|
|
117
|
-
|
|
118
|
-
>
|
|
127
|
+
)}
|
|
128
|
+
{#if warnings.length}
|
|
129
|
+
<span class="chip color_e">
|
|
130
|
+
{warnings.length} warning{warnings.length === 1 ? '' : 's'}
|
|
131
|
+
</span>
|
|
132
|
+
{/if}
|
|
133
|
+
{/if}
|
|
119
134
|
</div>
|
|
120
135
|
|
|
121
136
|
<h3>routes</h3>
|
|
@@ -221,9 +236,9 @@
|
|
|
221
236
|
<tr>
|
|
222
237
|
<td><code>{mw.name}</code></td>
|
|
223
238
|
<td><code>{mw.path}</code></td>
|
|
224
|
-
<td class="text_50"
|
|
225
|
-
|
|
226
|
-
>
|
|
239
|
+
<td class="text_50">
|
|
240
|
+
{mw.error_schemas ? Object.keys(mw.error_schemas).join(', ') : '-'}
|
|
241
|
+
</td>
|
|
227
242
|
</tr>
|
|
228
243
|
{/each}
|
|
229
244
|
</tbody>
|
|
@@ -280,11 +295,11 @@
|
|
|
280
295
|
<td>
|
|
281
296
|
<!-- TODO fix the `as any` cast -->
|
|
282
297
|
{#if event.params_schema}
|
|
283
|
-
<code
|
|
284
|
-
|
|
298
|
+
<code>
|
|
299
|
+
{Object.keys(
|
|
285
300
|
(event.params_schema as any).properties ?? event.params_schema
|
|
286
|
-
).join(', ')}
|
|
287
|
-
>
|
|
301
|
+
).join(', ')}
|
|
302
|
+
</code>
|
|
288
303
|
{:else}
|
|
289
304
|
<span class="text_50">none</span>
|
|
290
305
|
{/if}
|
|
@@ -457,8 +472,9 @@
|
|
|
457
472
|
<tbody>
|
|
458
473
|
{#each surface.diagnostics as d, i (i)}
|
|
459
474
|
<tr>
|
|
460
|
-
<td
|
|
461
|
-
|
|
475
|
+
<td>
|
|
476
|
+
<span class={d.level === 'warning' ? 'chip color_e' : 'chip'}>{d.level}</span>
|
|
477
|
+
</td>
|
|
462
478
|
<td><code>{d.category}</code></td>
|
|
463
479
|
<td>{d.message}</td>
|
|
464
480
|
<td class="text_50">{d.source ?? '-'}</td>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SurfaceExplorer.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/ui/SurfaceExplorer.svelte"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,UAAU,EAAyC,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"SurfaceExplorer.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/ui/SurfaceExplorer.svelte"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,UAAU,EAAyC,MAAM,oBAAoB,CAAC;AAW3F,KAAK,gBAAgB,GAAI;IAAE,OAAO,EAAE,UAAU,CAAA;CAAE,CAAC;AAwdlD,QAAA,MAAM,eAAe,sDAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
|
|
@@ -5,8 +5,12 @@
|
|
|
5
5
|
* `attempted` state (set on submit attempt). Errors show after a field is blurred or
|
|
6
6
|
* after a submit attempt, avoiding premature validation while the user is still typing.
|
|
7
7
|
*
|
|
8
|
-
* The `FormState.form` attachment also handles Enter key
|
|
9
|
-
*
|
|
8
|
+
* The `FormState.form` attachment also handles the Enter key: in an input
|
|
9
|
+
* followed by another input it moves focus to that input (past any button
|
|
10
|
+
* between), and in the last input it submits the form (`requestSubmit`) —
|
|
11
|
+
* so Enter in a login form's password field logs in, even when the form's
|
|
12
|
+
* button is `type="button"`, as `PendingButton` is. Hidden inputs don't count, and an Enter that commits
|
|
13
|
+
* IME composition is left alone.
|
|
10
14
|
*
|
|
11
15
|
* All trackable inputs must have a `name` attribute — an error is thrown in dev
|
|
12
16
|
* if an input without `name` loses focus.
|
|
@@ -48,8 +52,9 @@ export declare class FormState {
|
|
|
48
52
|
*/
|
|
49
53
|
get attempted(): boolean;
|
|
50
54
|
/**
|
|
51
|
-
* Creates a form attachment that handles Enter key
|
|
52
|
-
*
|
|
55
|
+
* Creates a form attachment that handles the Enter key (advance focus to
|
|
56
|
+
* the next input, or submit from the last one) and tracks field touched
|
|
57
|
+
* state via delegated `focusout`.
|
|
53
58
|
*
|
|
54
59
|
* Fields are identified by their `name` attribute.
|
|
55
60
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form_state.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/ui/form_state.svelte.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"form_state.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/ui/form_state.svelte.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAUrD,qBAAa,SAAS;;IAKrB;;OAEG;IACH,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED;;;;;;;;;OASG;IACH,IAAI,IAAI,UAAU,CAAC,eAAe,CAAC;IAmDnC;;OAEG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAIlC;;;OAGG;IACH,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAI5B;;;;OAIG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI1B;;OAEG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAiB1B;;;;OAIG;IACH,OAAO,IAAI,IAAI;IAIf;;;;OAIG;IACH,KAAK,IAAI,IAAI;CAIb"}
|