@fuzdev/fuz_app 0.68.0 → 0.69.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/perform_action.d.ts.map +1 -1
- package/dist/actions/perform_action.js +10 -3
- package/dist/auth/admin_action_specs.d.ts +2 -3
- package/dist/auth/admin_action_specs.d.ts.map +1 -1
- package/dist/auth/admin_action_specs.js +2 -3
- package/dist/auth/admin_actions.d.ts +4 -14
- package/dist/auth/admin_actions.d.ts.map +1 -1
- package/dist/auth/admin_actions.js +28 -36
- package/dist/auth/signup_routes.d.ts +0 -3
- package/dist/auth/signup_routes.d.ts.map +1 -1
- package/dist/auth/signup_routes.js +9 -3
- package/dist/auth/standard_rpc_actions.d.ts +5 -5
- package/dist/auth/standard_rpc_actions.js +4 -4
- package/dist/server/app_server.d.ts +1 -7
- package/dist/server/app_server.d.ts.map +1 -1
- package/dist/server/app_server.js +1 -5
- package/dist/testing/CLAUDE.md +85 -2
- package/dist/testing/app_server.d.ts +34 -0
- package/dist/testing/app_server.d.ts.map +1 -1
- package/dist/testing/app_server.js +31 -6
- package/dist/testing/cross_backend/account_lifecycle.d.ts.map +1 -1
- package/dist/testing/cross_backend/account_lifecycle.js +69 -1
- package/dist/testing/cross_backend/actor_lookup.d.ts +10 -0
- package/dist/testing/cross_backend/actor_lookup.d.ts.map +1 -0
- package/dist/testing/cross_backend/actor_lookup.js +83 -0
- package/dist/testing/cross_backend/actor_search.d.ts +6 -0
- package/dist/testing/cross_backend/actor_search.d.ts.map +1 -0
- package/dist/testing/cross_backend/actor_search.js +92 -0
- package/dist/testing/cross_backend/app_settings.d.ts +6 -0
- package/dist/testing/cross_backend/app_settings.d.ts.map +1 -0
- package/dist/testing/cross_backend/app_settings.js +95 -0
- package/dist/testing/cross_backend/backend_config.d.ts +1 -1
- package/dist/testing/cross_backend/capabilities.d.ts +0 -9
- package/dist/testing/cross_backend/capabilities.d.ts.map +1 -1
- package/dist/testing/cross_backend/capabilities.js +0 -1
- package/dist/testing/cross_backend/cell_grant_role.d.ts +8 -0
- package/dist/testing/cross_backend/cell_grant_role.d.ts.map +1 -0
- package/dist/testing/cross_backend/cell_grant_role.js +102 -0
- package/dist/testing/cross_backend/conformance_case.d.ts +144 -0
- package/dist/testing/cross_backend/conformance_case.d.ts.map +1 -0
- package/dist/testing/cross_backend/conformance_case.js +132 -0
- package/dist/testing/cross_backend/conformance_table.d.ts +46 -0
- package/dist/testing/cross_backend/conformance_table.d.ts.map +1 -0
- package/dist/testing/cross_backend/conformance_table.js +199 -0
- package/dist/testing/cross_backend/default_backend_configs.d.ts.map +1 -1
- package/dist/testing/cross_backend/default_backend_configs.js +0 -2
- package/dist/testing/cross_backend/default_spine_surface.d.ts +17 -9
- package/dist/testing/cross_backend/default_spine_surface.d.ts.map +1 -1
- package/dist/testing/cross_backend/default_spine_surface.js +20 -12
- package/dist/testing/cross_backend/origin.d.ts +10 -0
- package/dist/testing/cross_backend/origin.d.ts.map +1 -0
- package/dist/testing/cross_backend/origin.js +73 -0
- package/dist/testing/cross_backend/setup.d.ts +22 -40
- package/dist/testing/cross_backend/setup.d.ts.map +1 -1
- package/dist/testing/cross_backend/setup.js +34 -5
- package/dist/testing/cross_backend/testing_reset_actions.d.ts +90 -2
- package/dist/testing/cross_backend/testing_reset_actions.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_reset_actions.js +91 -3
- package/dist/testing/cross_backend/xfail.d.ts +15 -0
- package/dist/testing/cross_backend/xfail.d.ts.map +1 -0
- package/dist/testing/cross_backend/xfail.js +37 -0
- package/dist/testing/integration.d.ts +2 -3
- package/dist/testing/integration.d.ts.map +1 -1
- package/dist/testing/integration.js +20 -85
- package/dist/testing/rate_limiting.d.ts +1 -1
- package/dist/testing/rpc_helpers.d.ts +3 -3
- package/dist/testing/sse_round_trip.d.ts +1 -1
- package/dist/testing/stubs.d.ts.map +1 -1
- package/dist/testing/stubs.js +0 -1
- package/dist/ui/AdminAccounts.svelte +74 -83
- package/dist/ui/AdminAccounts.svelte.d.ts.map +1 -1
- package/dist/ui/AdminSessions.svelte +21 -23
- package/dist/ui/AdminSessions.svelte.d.ts.map +1 -1
- package/dist/ui/CLAUDE.md +17 -26
- package/dist/ui/OpenSignupToggle.svelte +2 -5
- package/dist/ui/OpenSignupToggle.svelte.d.ts.map +1 -1
- package/dist/ui/account_sessions_state.svelte.d.ts +9 -10
- package/dist/ui/account_sessions_state.svelte.d.ts.map +1 -1
- package/dist/ui/account_sessions_state.svelte.js +7 -17
- package/dist/ui/admin_accounts_state.svelte.d.ts +12 -19
- package/dist/ui/admin_accounts_state.svelte.d.ts.map +1 -1
- package/dist/ui/admin_accounts_state.svelte.js +10 -24
- package/dist/ui/admin_invites_state.svelte.d.ts +8 -11
- package/dist/ui/admin_invites_state.svelte.d.ts.map +1 -1
- package/dist/ui/admin_invites_state.svelte.js +7 -16
- package/dist/ui/admin_sessions_state.svelte.d.ts +6 -10
- package/dist/ui/admin_sessions_state.svelte.d.ts.map +1 -1
- package/dist/ui/admin_sessions_state.svelte.js +4 -14
- package/dist/ui/app_settings_state.svelte.d.ts +8 -12
- package/dist/ui/app_settings_state.svelte.d.ts.map +1 -1
- package/dist/ui/app_settings_state.svelte.js +6 -16
- package/dist/ui/audit_log_state.svelte.d.ts +9 -8
- package/dist/ui/audit_log_state.svelte.d.ts.map +1 -1
- package/dist/ui/audit_log_state.svelte.js +8 -20
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xfail.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/xfail.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAyB9B;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,WAAW,GACvB,aAAa,MAAM,EACnB,QAAQ,MAAM,EACd,MAAM,MAAM,EACZ,IAAI,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAC5B,IAEF,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import '../assert_dev_env.js';
|
|
2
|
+
/**
|
|
3
|
+
* `xfail_until` — mark a deferred-by-design gap as an expected failure.
|
|
4
|
+
*
|
|
5
|
+
* A thin wrapper over vitest's `test.fails` that bakes a tracking id +
|
|
6
|
+
* reason into the test label. Two properties make it the right tool for
|
|
7
|
+
* declared gaps (distinct from in-scope gaps, which fail loud as a normal
|
|
8
|
+
* red `test`):
|
|
9
|
+
*
|
|
10
|
+
* - **Visible** — the case shows in the report as a distinct expected
|
|
11
|
+
* failure, not a silent `.skip`, so a deferred gap never disappears from
|
|
12
|
+
* view.
|
|
13
|
+
* - **Self-cleaning** — `test.fails` turns **red** the moment the body
|
|
14
|
+
* stops throwing (i.e. the impl starts passing), forcing whoever closed
|
|
15
|
+
* the gap to delete the marker. A `.skip` would rot silently; this can't.
|
|
16
|
+
*
|
|
17
|
+
* Sibling to `test_if` in `capabilities.ts`. No taxonomy — a one-line
|
|
18
|
+
* marker with a tracking id and a reason, nothing more.
|
|
19
|
+
*
|
|
20
|
+
* @module
|
|
21
|
+
*/
|
|
22
|
+
import { test } from 'vitest';
|
|
23
|
+
/**
|
|
24
|
+
* Register `fn` as an expected-failure test. Passes while `fn` throws /
|
|
25
|
+
* rejects; **fails** once `fn` succeeds (signalling the gap closed and the
|
|
26
|
+
* marker should be removed).
|
|
27
|
+
*
|
|
28
|
+
* @param tracking_id - descriptive id of the tracked gap (e.g.
|
|
29
|
+
* `'audit-log-sse-rust-spine'`) — a feature/behavior name, not a
|
|
30
|
+
* process/milestone label.
|
|
31
|
+
* @param reason - why the case is deferred-by-design.
|
|
32
|
+
* @param name - the assertion / test label.
|
|
33
|
+
* @param fn - the test body (expected to throw/reject until the gap closes).
|
|
34
|
+
*/
|
|
35
|
+
export const xfail_until = (tracking_id, reason, name, fn) => {
|
|
36
|
+
test.fails(`${name} [xfail_until ${tracking_id}: ${reason}]`, fn);
|
|
37
|
+
};
|
|
@@ -25,13 +25,12 @@ export interface StandardIntegrationTestOptions {
|
|
|
25
25
|
* not the source the test runtime reads from.
|
|
26
26
|
*/
|
|
27
27
|
surface_source: AppSurfaceSpec;
|
|
28
|
-
/** Backend capability declarations
|
|
28
|
+
/** Backend capability declarations for capability-gated cases. */
|
|
29
29
|
capabilities: BackendCapabilities;
|
|
30
30
|
/**
|
|
31
31
|
* Session config — needed to resolve factory-form `rpc_endpoints`
|
|
32
32
|
* against a stub `AppServerContext` at setup time and to read
|
|
33
|
-
* `cookie_name` for manual cookie composition in the
|
|
34
|
-
* cases.
|
|
33
|
+
* `cookie_name` for manual cookie composition in the session cases.
|
|
35
34
|
*/
|
|
36
35
|
session_options: SessionOptions<string>;
|
|
37
36
|
/**
|
|
@@ -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;
|
|
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;AAM9D,OAAO,EAKN,KAAK,uBAAuB,EAC5B,MAAM,kBAAkB,CAAC;AAiB1B,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAC,KAAK,mBAAmB,EAAC,MAAM,iCAAiC,CAAC;AACzE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,0BAA0B,CAAC;AAGxD;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC9C;;;;OAIG;IACH,UAAU,EAAE,SAAS,CAAC;IACtB;;;;;;;;;OASG;IACH,cAAc,EAAE,cAAc,CAAC;IAC/B,kEAAkE;IAClE,YAAY,EAAE,mBAAmB,CAAC;IAClC;;;;OAIG;IACH,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC;;;;;;;;;;;;OAYG;IACH,aAAa,EAAE,uBAAuB,CAAC;IACvC;;;;;;;OAOG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,eAAO,MAAM,mCAAmC,GAC/C,SAAS,8BAA8B,KACrC,IAyzCF,CAAC"}
|
|
@@ -17,14 +17,13 @@ import './assert_dev_env.js';
|
|
|
17
17
|
* @module
|
|
18
18
|
*/
|
|
19
19
|
import { describe, test, assert, afterAll } from 'vitest';
|
|
20
|
-
import { find_auth_route, assert_response_matches_spec,
|
|
20
|
+
import { find_auth_route, assert_response_matches_spec, assert_no_error_info_leakage, } from './integration_helpers.js';
|
|
21
21
|
import { find_rpc_action, rpc_call_for_spec, require_rpc_endpoint_path, resolve_rpc_endpoints_for_setup, } from './rpc_helpers.js';
|
|
22
22
|
import { ErrorCoverageCollector, assert_error_coverage, DEFAULT_INTEGRATION_ERROR_COVERAGE, } from './error_coverage.js';
|
|
23
|
-
import { ApiError, ERROR_FORBIDDEN_ORIGIN } from '../http/error_schemas.js';
|
|
24
23
|
import { is_public_auth } from '../http/auth_shape.js';
|
|
25
24
|
import { account_verify_action_spec, account_session_list_action_spec, account_session_revoke_action_spec, account_session_revoke_all_action_spec, account_token_create_action_spec, account_token_list_action_spec, account_token_revoke_action_spec, } from '../auth/account_action_specs.js';
|
|
26
25
|
import { invite_create_action_spec } from '../auth/admin_action_specs.js';
|
|
27
|
-
import {
|
|
26
|
+
import {} from './cross_backend/capabilities.js';
|
|
28
27
|
import { DEFAULT_TEST_PASSWORD } from './app_server.js';
|
|
29
28
|
/**
|
|
30
29
|
* Standard integration test suite for fuz_app auth routes.
|
|
@@ -323,19 +322,12 @@ export const describe_standard_integration_tests = (options) => {
|
|
|
323
322
|
});
|
|
324
323
|
assert.strictEqual(res.status, 401);
|
|
325
324
|
});
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
path: rpc_path,
|
|
333
|
-
spec: account_verify_action_spec,
|
|
334
|
-
params: undefined,
|
|
335
|
-
headers: { cookie: `${cookie_name}=${expired_cookie}` },
|
|
336
|
-
});
|
|
337
|
-
assert.strictEqual(res.status, 401);
|
|
338
|
-
});
|
|
325
|
+
// Expired-session rejection promoted to the cross-backend conformance
|
|
326
|
+
// table (the `expired_session` principal, `conformance_expiry_cases.ts`) —
|
|
327
|
+
// it exercises the authoritative server-side DB-row expiry gate over
|
|
328
|
+
// real auth resolution on every spine, not the cookie-payload gate a
|
|
329
|
+
// backdated-payload forge hit here. The payload gate stays covered by
|
|
330
|
+
// `parse_session`'s own unit tests.
|
|
339
331
|
});
|
|
340
332
|
// --- 4. Session revocation ---
|
|
341
333
|
describe('session revocation', () => {
|
|
@@ -486,29 +478,11 @@ export const describe_standard_integration_tests = (options) => {
|
|
|
486
478
|
});
|
|
487
479
|
// --- 5. Origin verification ---
|
|
488
480
|
describe('origin verification', () => {
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
const res = await fixture.transport(rpc_path, {
|
|
495
|
-
method: 'POST',
|
|
496
|
-
headers: {
|
|
497
|
-
host: 'localhost',
|
|
498
|
-
origin: 'http://evil.com',
|
|
499
|
-
'content-type': 'application/json',
|
|
500
|
-
cookie: `${cookie_name}=${fixture.backend_internals.session_cookie}`,
|
|
501
|
-
},
|
|
502
|
-
body: JSON.stringify({
|
|
503
|
-
jsonrpc: '2.0',
|
|
504
|
-
method: account_verify_action_spec.method,
|
|
505
|
-
id: 'evil-origin',
|
|
506
|
-
}),
|
|
507
|
-
});
|
|
508
|
-
assert.strictEqual(res.status, 403);
|
|
509
|
-
const body = ApiError.parse(await res.json());
|
|
510
|
-
assert.strictEqual(body.error, ERROR_FORBIDDEN_ORIGIN);
|
|
511
|
-
});
|
|
481
|
+
// Disallowed-Origin → 403 and absent-Origin → pass promoted to the
|
|
482
|
+
// dedicated cross-backend origin parity suite (`cross_backend/origin.ts`,
|
|
483
|
+
// both legs) — it drives raw transport calls against each spine's real
|
|
484
|
+
// origin middleware. This positive control stays here as a basic
|
|
485
|
+
// happy-path check in the consumer integration bundle.
|
|
512
486
|
test('valid origin is accepted', async () => {
|
|
513
487
|
const fixture = await options.setup_test();
|
|
514
488
|
const res = await rpc_call_for_spec({
|
|
@@ -520,21 +494,6 @@ export const describe_standard_integration_tests = (options) => {
|
|
|
520
494
|
});
|
|
521
495
|
assert.strictEqual(res.status, 200);
|
|
522
496
|
});
|
|
523
|
-
test_if(options.capabilities.in_process_only, 'no origin header is allowed (direct access)', async () => {
|
|
524
|
-
const fixture = await options.setup_test();
|
|
525
|
-
assert(fixture.in_process);
|
|
526
|
-
// Probe the "no Origin / no Referer" path; `suppress_default_origin`
|
|
527
|
-
// skips the default `origin` header.
|
|
528
|
-
const res = await rpc_call_for_spec({
|
|
529
|
-
app: { request: fixture.transport },
|
|
530
|
-
path: rpc_path,
|
|
531
|
-
spec: account_verify_action_spec,
|
|
532
|
-
params: undefined,
|
|
533
|
-
headers: { cookie: `${cookie_name}=${fixture.backend_internals.session_cookie}` },
|
|
534
|
-
suppress_default_origin: true,
|
|
535
|
-
});
|
|
536
|
-
assert.notStrictEqual(res.status, 403);
|
|
537
|
-
});
|
|
538
497
|
});
|
|
539
498
|
// --- 6. Bearer auth ---
|
|
540
499
|
describe('bearer auth', () => {
|
|
@@ -938,37 +897,13 @@ export const describe_standard_integration_tests = (options) => {
|
|
|
938
897
|
});
|
|
939
898
|
});
|
|
940
899
|
// --- 11. Expired credential rejection ---
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
path: rpc_path,
|
|
949
|
-
spec: account_verify_action_spec,
|
|
950
|
-
params: undefined,
|
|
951
|
-
headers: { cookie: `${cookie_name}=${expired_cookie}` },
|
|
952
|
-
});
|
|
953
|
-
assert.strictEqual(res.status, 401, 'Expired session cookie should be rejected');
|
|
954
|
-
});
|
|
955
|
-
test_if(options.capabilities.in_process_only, 'expired session cookie returns 401 on mutation route', async () => {
|
|
956
|
-
const fixture = await options.setup_test();
|
|
957
|
-
assert(fixture.in_process);
|
|
958
|
-
const logout_route = find_auth_route(route_specs, '/logout', 'POST');
|
|
959
|
-
assert.ok(logout_route, 'Expected POST /logout route — ensure create_route_specs includes account routes');
|
|
960
|
-
const expired_cookie = await create_expired_test_cookie(fixture.keyring, options.session_options);
|
|
961
|
-
const res = await fixture.transport(logout_route.path, {
|
|
962
|
-
method: 'POST',
|
|
963
|
-
headers: {
|
|
964
|
-
host: 'localhost',
|
|
965
|
-
cookie: `${cookie_name}=${expired_cookie}`,
|
|
966
|
-
},
|
|
967
|
-
});
|
|
968
|
-
assert.strictEqual(res.status, 401, 'Expired session cookie should be rejected on POST');
|
|
969
|
-
error_collector.record(route_specs, 'POST', logout_route.path, 401);
|
|
970
|
-
});
|
|
971
|
-
});
|
|
900
|
+
// Expired-credential rejection (read + mutation paths) promoted to the
|
|
901
|
+
// cross-backend conformance table (`conformance_expiry_cases.ts`, the
|
|
902
|
+
// `expired_session` principal) — it asserts the authoritative
|
|
903
|
+
// server-side DB-row expiry gate over real auth resolution on every
|
|
904
|
+
// spine. The two near-identical in-process skips this replaced (both an
|
|
905
|
+
// `account_verify` read) collapse into the single read row there; the
|
|
906
|
+
// `/logout` mutation path is the second row.
|
|
972
907
|
// --- 12. Bearer token browser context on mutation routes ---
|
|
973
908
|
describe('bearer token browser context silently discarded on mutations', () => {
|
|
974
909
|
test('bearer token with Origin header discarded on POST logout', async () => {
|
|
@@ -32,7 +32,7 @@ export interface RateLimitingTestOptions {
|
|
|
32
32
|
* Accepts either an array (eager) or a factory
|
|
33
33
|
* `(ctx: AppServerContext) => Array<RpcEndpointSpec>` — the factory form
|
|
34
34
|
* is required when action handlers must close over the per-test
|
|
35
|
-
* `ctx.
|
|
35
|
+
* `ctx.deps`. The factory must return the same
|
|
36
36
|
* endpoint `path` regardless of ctx — it is invoked once at setup with
|
|
37
37
|
* a stub ctx for path lookup and again per-test by `create_app_server`
|
|
38
38
|
* for live dispatch.
|
|
@@ -10,9 +10,9 @@ import type { SessionOptions } from '../auth/session_cookie.js';
|
|
|
10
10
|
* Union accepted by the suite-level `rpc_endpoints` option — eager array or
|
|
11
11
|
* a factory that takes an `AppServerContext` and returns endpoint specs. The
|
|
12
12
|
* factory form is required when action handlers must close over the
|
|
13
|
-
* per-test `ctx.
|
|
14
|
-
* `create_standard_rpc_actions(ctx.deps
|
|
15
|
-
*
|
|
13
|
+
* per-test `ctx.deps` (e.g. the canonical
|
|
14
|
+
* `create_standard_rpc_actions(ctx.deps)` pattern). `create_app_server`
|
|
15
|
+
* resolves either shape natively; test helpers
|
|
16
16
|
* forward the raw value to the top-level `rpc_endpoints` slot on
|
|
17
17
|
* `CreateTestAppOptions` for live dispatch.
|
|
18
18
|
*/
|
|
@@ -57,7 +57,7 @@ export interface SseRouteTestOptions {
|
|
|
57
57
|
* Accepts either an array (eager) or a factory
|
|
58
58
|
* `(ctx: AppServerContext) => Array<RpcEndpointSpec>` — the factory form
|
|
59
59
|
* is required when action handlers must close over the per-test
|
|
60
|
-
* `ctx.
|
|
60
|
+
* `ctx.deps`. The factory must return the same
|
|
61
61
|
* endpoint `path` regardless of ctx — it is invoked once at setup with
|
|
62
62
|
* a stub ctx for path lookup and again per-test by `create_app_server`
|
|
63
63
|
* for live dispatch.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stubs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/stubs.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAa7B,OAAO,KAAK,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAE3B,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,4BAA4B,CAAC;AAE/D,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,0BAA0B,CAAC;AAE3D,OAAO,KAAK,EAAC,gBAAgB,EAAE,sBAAsB,EAAC,MAAM,yBAAyB,CAAC;AACtF,OAAO,EAAC,EAAE,EAAC,MAAM,aAAa,CAAC;AAC/B,OAAO,EAAqB,KAAK,SAAS,EAAC,MAAM,uBAAuB,CAAC;AAGzE,OAAO,EAEN,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,gCAAgC,CAAC;AACnE,OAAO,KAAK,EAAC,SAAS,EAAkB,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAA8B,KAAK,WAAW,EAAC,MAAM,+BAA+B,CAAC;AAI5F;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,oBAAoB,GAAI,CAAC,GAAG,GAAG,EAAE,OAAO,MAAM,KAAG,CAqBtD,CAAC;AAET;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,GAAI,CAAC,GAAG,GAAG,EAAE,QAAQ,MAAM,EAAE,YAAY,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,CAOxF,CAAC;AAET,iEAAiE;AACjE,eAAO,MAAM,IAAI,EAAE,GAAkC,CAAC;AAEtD;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,QAAO,EAI/B,CAAC;AAEJ,gDAAgD;AAChD,eAAO,MAAM,YAAY,QAAO,QAAgC,CAAC;AAEjE,2CAA2C;AAC3C,eAAO,MAAM,OAAO,GAAU,IAAI,GAAG,EAAE,MAAM,GAAG,KAAG,OAAO,CAAC,IAAI,CAAW,CAAC;AAI3E;;;;;;;;;;GAUG;AACH,eAAO,MAAM,yBAAyB,QAAO,YAM3C,CAAC;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB,QAAO,WAUxC,CAAC;AAEF,2EAA2E;AAC3E,eAAO,MAAM,aAAa,EAAE,OAS3B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,QAAO,OAStC,CAAC;AAEH,2FAA2F;AAC3F,eAAO,MAAM,0BAA0B,GAAI,UAAU;IACpD,iDAAiD;IACjD,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAC/B,KAAG,KAAK,CAAC,cAAc,CAqBvB,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,8BAA8B,GAC1C,iBAAiB,cAAc,CAAC,MAAM,CAAC,KACrC,
|
|
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
|
@@ -201,7 +201,6 @@ export const create_stub_app_server_context = (session_options) => {
|
|
|
201
201
|
signup_account_rate_limiter: null,
|
|
202
202
|
action_ip_rate_limiter: null,
|
|
203
203
|
action_account_rate_limiter: null,
|
|
204
|
-
app_settings: { open_signup: false, updated_at: null, updated_by: null },
|
|
205
204
|
audit_sse: null,
|
|
206
205
|
};
|
|
207
206
|
};
|
|
@@ -50,21 +50,18 @@
|
|
|
50
50
|
</p>
|
|
51
51
|
{/if}
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
<
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
here.
|
|
66
|
-
</p>
|
|
67
|
-
{/if}
|
|
53
|
+
<label class="row gap_xs font_size_sm">
|
|
54
|
+
<input
|
|
55
|
+
type="checkbox"
|
|
56
|
+
checked={admin_accounts.show_deleted}
|
|
57
|
+
onchange={(e) => admin_accounts.set_show_deleted(e.currentTarget.checked)}
|
|
58
|
+
/>
|
|
59
|
+
show deleted
|
|
60
|
+
</label>
|
|
61
|
+
<p class="text_50 font_size_sm">
|
|
62
|
+
“delete” is a reversible soft-delete (tombstone) — enable “show deleted” to reactivate an
|
|
63
|
+
account. Permanent hard-delete (purge) is keeper/CLI-only and intentionally not available here.
|
|
64
|
+
</p>
|
|
68
65
|
|
|
69
66
|
{#if admin_accounts.list.loading}
|
|
70
67
|
<p class="text_50">loading accounts...</p>
|
|
@@ -111,7 +108,7 @@
|
|
|
111
108
|
expires {format_relative_time(role_grant.expires_at)}
|
|
112
109
|
</span>
|
|
113
110
|
{/if}
|
|
114
|
-
{#if
|
|
111
|
+
{#if row.actor}
|
|
115
112
|
{@const actor_id = row.actor.id}
|
|
116
113
|
{@const revoke_error = admin_accounts.revoke.error(role_grant.id)}
|
|
117
114
|
<ConfirmButton
|
|
@@ -129,6 +126,7 @@
|
|
|
129
126
|
{/each}
|
|
130
127
|
{#each row.pending_offers as offer (offer.id)}
|
|
131
128
|
{@const offer_scope = scope_label(offer.scope_id, offer.role)}
|
|
129
|
+
{@const retract_error = admin_accounts.retract.error(offer.id)}
|
|
132
130
|
<div class="row">
|
|
133
131
|
<span
|
|
134
132
|
class="chip"
|
|
@@ -141,18 +139,15 @@
|
|
|
141
139
|
{offer_scope}
|
|
142
140
|
</span>
|
|
143
141
|
{/if}
|
|
144
|
-
|
|
145
|
-
{
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
{#if retract_error}
|
|
154
|
-
<span class="color_c_50 font_size_sm">{retract_error}</span>
|
|
155
|
-
{/if}
|
|
142
|
+
<ConfirmButton
|
|
143
|
+
onconfirm={() => admin_accounts.submit_retract(offer.id)}
|
|
144
|
+
title="retract offer"
|
|
145
|
+
class="sm"
|
|
146
|
+
label="retract"
|
|
147
|
+
pending={admin_accounts.retract.loading(offer.id)}
|
|
148
|
+
/>
|
|
149
|
+
{#if retract_error}
|
|
150
|
+
<span class="color_c_50 font_size_sm">{retract_error}</span>
|
|
156
151
|
{/if}
|
|
157
152
|
</div>
|
|
158
153
|
{/each}
|
|
@@ -160,70 +155,66 @@
|
|
|
160
155
|
<span class="text_50">none</span>
|
|
161
156
|
{/if}
|
|
162
157
|
{:else if column.key === 'actor'}
|
|
163
|
-
{#
|
|
164
|
-
{
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
{#if !row.role_grants.some((p) => p.role === role) && !row.pending_offers.some((o) => o.role === role)}
|
|
168
|
-
<ConfirmButton
|
|
169
|
-
onconfirm={() => admin_accounts.submit_grant(row.account.id, role)}
|
|
170
|
-
title="offer {role}"
|
|
171
|
-
class="sm"
|
|
172
|
-
label={`+ ${role}`}
|
|
173
|
-
pending={admin_accounts.grant.loading(key)}
|
|
174
|
-
>
|
|
175
|
-
{#snippet popover_content(_popover, do_confirm)}
|
|
176
|
-
<button type="button" class="color_b bg_100" onclick={() => do_confirm()}>
|
|
177
|
-
<span class="py_sm">offer '{role}' to @{row.account.username}</span>
|
|
178
|
-
</button>
|
|
179
|
-
{/snippet}
|
|
180
|
-
</ConfirmButton>
|
|
181
|
-
{#if grant_error}
|
|
182
|
-
<span class="color_c_50 font_size_sm">{grant_error}</span>
|
|
183
|
-
{/if}
|
|
184
|
-
{/if}
|
|
185
|
-
{/each}
|
|
186
|
-
{/if}
|
|
187
|
-
{:else if column.key === 'pending_offers'}
|
|
188
|
-
{#if admin_accounts.has_rpc}
|
|
189
|
-
{#if row.account.deleted_at}
|
|
190
|
-
{@const undelete_error = admin_accounts.undelete.error(row.account.id)}
|
|
191
|
-
<span
|
|
192
|
-
class="chip font_size_sm color_c"
|
|
193
|
-
title={format_datetime_local(row.account.deleted_at)}
|
|
194
|
-
>
|
|
195
|
-
deleted {format_relative_time(row.account.deleted_at)}
|
|
196
|
-
</span>
|
|
197
|
-
<button
|
|
198
|
-
type="button"
|
|
199
|
-
class="sm"
|
|
200
|
-
disabled={admin_accounts.undelete.loading(row.account.id)}
|
|
201
|
-
onclick={() => admin_accounts.submit_undelete(row.account.id)}
|
|
202
|
-
>
|
|
203
|
-
reactivate
|
|
204
|
-
</button>
|
|
205
|
-
{#if undelete_error}
|
|
206
|
-
<span class="color_c_50 font_size_sm">{undelete_error}</span>
|
|
207
|
-
{/if}
|
|
208
|
-
{:else}
|
|
209
|
-
{@const delete_error = admin_accounts.soft_delete.error(row.account.id)}
|
|
158
|
+
{#each admin_accounts.grantable_roles as role (role)}
|
|
159
|
+
{@const key = grant_key(row.account.id, role)}
|
|
160
|
+
{@const grant_error = admin_accounts.grant.error(key)}
|
|
161
|
+
{#if !row.role_grants.some((p) => p.role === role) && !row.pending_offers.some((o) => o.role === role)}
|
|
210
162
|
<ConfirmButton
|
|
211
|
-
onconfirm={() => admin_accounts.
|
|
212
|
-
title="
|
|
163
|
+
onconfirm={() => admin_accounts.submit_grant(row.account.id, role)}
|
|
164
|
+
title="offer {role}"
|
|
213
165
|
class="sm"
|
|
214
|
-
label=
|
|
215
|
-
pending={admin_accounts.
|
|
166
|
+
label={`+ ${role}`}
|
|
167
|
+
pending={admin_accounts.grant.loading(key)}
|
|
216
168
|
>
|
|
217
169
|
{#snippet popover_content(_popover, do_confirm)}
|
|
218
|
-
<button type="button" class="
|
|
219
|
-
<span class="py_sm">
|
|
170
|
+
<button type="button" class="color_b bg_100" onclick={() => do_confirm()}>
|
|
171
|
+
<span class="py_sm">offer '{role}' to @{row.account.username}</span>
|
|
220
172
|
</button>
|
|
221
173
|
{/snippet}
|
|
222
174
|
</ConfirmButton>
|
|
223
|
-
{#if
|
|
224
|
-
<span class="color_c_50 font_size_sm">{
|
|
175
|
+
{#if grant_error}
|
|
176
|
+
<span class="color_c_50 font_size_sm">{grant_error}</span>
|
|
225
177
|
{/if}
|
|
226
178
|
{/if}
|
|
179
|
+
{/each}
|
|
180
|
+
{:else if column.key === 'pending_offers'}
|
|
181
|
+
{#if row.account.deleted_at}
|
|
182
|
+
{@const undelete_error = admin_accounts.undelete.error(row.account.id)}
|
|
183
|
+
<span
|
|
184
|
+
class="chip font_size_sm color_c"
|
|
185
|
+
title={format_datetime_local(row.account.deleted_at)}
|
|
186
|
+
>
|
|
187
|
+
deleted {format_relative_time(row.account.deleted_at)}
|
|
188
|
+
</span>
|
|
189
|
+
<button
|
|
190
|
+
type="button"
|
|
191
|
+
class="sm"
|
|
192
|
+
disabled={admin_accounts.undelete.loading(row.account.id)}
|
|
193
|
+
onclick={() => admin_accounts.submit_undelete(row.account.id)}
|
|
194
|
+
>
|
|
195
|
+
reactivate
|
|
196
|
+
</button>
|
|
197
|
+
{#if undelete_error}
|
|
198
|
+
<span class="color_c_50 font_size_sm">{undelete_error}</span>
|
|
199
|
+
{/if}
|
|
200
|
+
{:else}
|
|
201
|
+
{@const delete_error = admin_accounts.soft_delete.error(row.account.id)}
|
|
202
|
+
<ConfirmButton
|
|
203
|
+
onconfirm={() => admin_accounts.submit_delete(row.account.id)}
|
|
204
|
+
title="soft-delete @{row.account.username}"
|
|
205
|
+
class="sm"
|
|
206
|
+
label="delete"
|
|
207
|
+
pending={admin_accounts.soft_delete.loading(row.account.id)}
|
|
208
|
+
>
|
|
209
|
+
{#snippet popover_content(_popover, do_confirm)}
|
|
210
|
+
<button type="button" class="color_c bg_100" onclick={() => do_confirm()}>
|
|
211
|
+
<span class="py_sm">soft-delete @{row.account.username} (reversible)</span>
|
|
212
|
+
</button>
|
|
213
|
+
{/snippet}
|
|
214
|
+
</ConfirmButton>
|
|
215
|
+
{#if delete_error}
|
|
216
|
+
<span class="color_c_50 font_size_sm">{delete_error}</span>
|
|
217
|
+
{/if}
|
|
227
218
|
{/if}
|
|
228
219
|
{/if}
|
|
229
220
|
{/snippet}
|
|
@@ -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":"AAkMA,QAAA,MAAM,aAAa,2DAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
|
|
@@ -62,29 +62,27 @@
|
|
|
62
62
|
{format_relative_time(row.expires_at)}
|
|
63
63
|
</span>
|
|
64
64
|
{:else if column.key === 'account_id'}
|
|
65
|
-
{
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
{
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
{
|
|
86
|
-
<span class="color_c_50 font_size_sm">{revoke_tokens_error}</span>
|
|
87
|
-
{/if}
|
|
65
|
+
{@const revoke_sessions_error = admin_sessions.revoke_sessions.error(row.account_id)}
|
|
66
|
+
{@const revoke_tokens_error = admin_sessions.revoke_tokens.error(row.account_id)}
|
|
67
|
+
<ConfirmButton
|
|
68
|
+
onconfirm={() => admin_sessions.submit_revoke_sessions(row.account_id)}
|
|
69
|
+
title="revoke all sessions for {row.username}"
|
|
70
|
+
class="sm"
|
|
71
|
+
label="revoke sessions"
|
|
72
|
+
pending={admin_sessions.revoke_sessions.loading(row.account_id)}
|
|
73
|
+
/>
|
|
74
|
+
{#if revoke_sessions_error}
|
|
75
|
+
<span class="color_c_50 font_size_sm">{revoke_sessions_error}</span>
|
|
76
|
+
{/if}
|
|
77
|
+
<ConfirmButton
|
|
78
|
+
onconfirm={() => admin_sessions.submit_revoke_tokens(row.account_id)}
|
|
79
|
+
title="revoke all tokens for {row.username}"
|
|
80
|
+
class="sm"
|
|
81
|
+
label="revoke tokens"
|
|
82
|
+
pending={admin_sessions.revoke_tokens.loading(row.account_id)}
|
|
83
|
+
/>
|
|
84
|
+
{#if revoke_tokens_error}
|
|
85
|
+
<span class="color_c_50 font_size_sm">{revoke_tokens_error}</span>
|
|
88
86
|
{/if}
|
|
89
87
|
{:else if column.format}
|
|
90
88
|
{column.format(row[column.key], row)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdminSessions.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/ui/AdminSessions.svelte"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AdminSessions.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/ui/AdminSessions.svelte"],"names":[],"mappings":"AAkGA,UAAU,kCAAkC,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,OAAO,GAAG,EAAE,EAAE,QAAQ,GAAG,MAAM;IACpM,KAAK,OAAO,EAAE,OAAO,QAAQ,EAAE,2BAA2B,CAAC,KAAK,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC;IACjK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,KAAK,CAAA;KAAC,GAAG,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IACtG,YAAY,CAAC,EAAE,QAAQ,CAAC;CAC3B;AAKD,QAAA,MAAM,aAAa;;kBAA+E,CAAC;AACjF,KAAK,aAAa,GAAG,YAAY,CAAC,OAAO,aAAa,CAAC,CAAC;AAC1D,eAAe,aAAa,CAAC"}
|
package/dist/ui/CLAUDE.md
CHANGED
|
@@ -18,16 +18,17 @@ file is a reference, not a tutorial.
|
|
|
18
18
|
|
|
19
19
|
## Key patterns
|
|
20
20
|
|
|
21
|
-
### RPC adapter contexts
|
|
21
|
+
### RPC adapter contexts (required, no fallback)
|
|
22
22
|
|
|
23
23
|
Five narrow RPC adapter contexts — `admin_accounts_rpc_context`,
|
|
24
24
|
`admin_invites_rpc_context`, `audit_log_rpc_context`,
|
|
25
25
|
`app_settings_rpc_context`, `account_sessions_rpc_context` — carry a
|
|
26
|
-
reactive `() => Rpc
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
here.) The standard consumer
|
|
26
|
+
reactive `() => Rpc` accessor. None declares a fallback, so `get()` throws
|
|
27
|
+
when a component mounts without a provisioner above it — the adapter is
|
|
28
|
+
required, and a missing wire fails loudly at mount rather than degrading
|
|
29
|
+
silently. (`role_grant_offers_state_context` carries a `RoleGrantOffersState`
|
|
30
|
+
directly, not an RPC accessor, and isn't counted here.) The standard consumer
|
|
31
|
+
shape:
|
|
31
32
|
|
|
32
33
|
```ts
|
|
33
34
|
const get_rpc = admin_accounts_rpc_context.get();
|
|
@@ -45,14 +46,6 @@ The provisioner calls `context.set(() => rpc)` once at the admin route
|
|
|
45
46
|
shell. Every admin component plus `OpenSignupToggle.svelte` consumes the
|
|
46
47
|
context — RPC adapters are never threaded through props.
|
|
47
48
|
|
|
48
|
-
### `has_rpc` gates fetch and mutations
|
|
49
|
-
|
|
50
|
-
Every state class backed by a narrow RPC interface exposes a `has_rpc`
|
|
51
|
-
getter. When `false`, `fetch()`, mutations, and `subscribe` no-op and
|
|
52
|
-
set `error` to `'rpc adapter not wired'`. `AdminSessionsState`'s listing
|
|
53
|
-
plus mutations all run through the shared `AdminAccountsRpc`, so
|
|
54
|
-
`has_rpc` gates the whole surface.
|
|
55
|
-
|
|
56
49
|
### `$state.raw` Map keyed by id + `$derived` views
|
|
57
50
|
|
|
58
51
|
`RoleGrantOffersState` maintains a single `Map<string, RoleGrantOfferJson>` in
|
|
@@ -159,7 +152,7 @@ destructive actions.
|
|
|
159
152
|
`/api/surface` (REST) and delegates to `SurfaceExplorer`.
|
|
160
153
|
- `OpenSignupToggle.svelte` — single checkbox bound to
|
|
161
154
|
`AppSettingsState.settings.open_signup`. Consumes
|
|
162
|
-
`app_settings_rpc_context
|
|
155
|
+
`app_settings_rpc_context`.
|
|
163
156
|
- `SurfaceExplorer.svelte` — reads-only `AppSurface` renderer. Props:
|
|
164
157
|
`surface: AppSurface`. Filter routes by auth type; expand a row to
|
|
165
158
|
dump `params`/`query`/`input`/`output`/`errors` schemas as JSON.
|
|
@@ -317,8 +310,7 @@ the `submit_*` prefix where the verb collides with a slot name.
|
|
|
317
310
|
(`list_sessions` wraps `admin_session_list`) and the two revoke-all
|
|
318
311
|
mutations. Slots: `list` (AsyncSlot), `revoke_sessions` /
|
|
319
312
|
`revoke_tokens` (`KeyedAsyncSlot<Uuid, void>` keyed by
|
|
320
|
-
`account_id`). `
|
|
321
|
-
Methods: `fetch`, `submit_revoke_sessions`, `submit_revoke_tokens`.
|
|
313
|
+
`account_id`). Methods: `fetch`, `submit_revoke_sessions`, `submit_revoke_tokens`.
|
|
322
314
|
- `app_settings_state.svelte.ts` — `AppSettingsState` +
|
|
323
315
|
`app_settings_rpc_context` + narrow `AppSettingsRpc` (`get`,
|
|
324
316
|
`update`). Slots: `list`, `update`. Field: `settings`. Single
|
|
@@ -337,23 +329,22 @@ the `submit_*` prefix where the verb collides with a slot name.
|
|
|
337
329
|
|
|
338
330
|
## RPC adapter contexts
|
|
339
331
|
|
|
340
|
-
All five RPC-carrying contexts
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
provisioner pattern.
|
|
332
|
+
All five RPC-carrying contexts are required (no fallback) — `get()` throws
|
|
333
|
+
when unprovisioned; consumers wire a typed RPC client to each narrow
|
|
334
|
+
interface. See "Key patterns" above for the provisioner pattern.
|
|
344
335
|
|
|
345
336
|
- `auth_state_context` — carries `AuthState` directly (not an RPC
|
|
346
337
|
accessor). Used by every auth form, `AdminOverview`,
|
|
347
338
|
`AdminSettings`, `AccountSessions`, `LogoutButton`.
|
|
348
|
-
- `admin_accounts_rpc_context` — `() => AdminAccountsRpc
|
|
339
|
+
- `admin_accounts_rpc_context` — `() => AdminAccountsRpc`.
|
|
349
340
|
Consumed by `AdminAccounts`, `AdminSessions`, `AdminOverview`.
|
|
350
|
-
- `admin_invites_rpc_context` — `() => AdminInvitesRpc
|
|
341
|
+
- `admin_invites_rpc_context` — `() => AdminInvitesRpc`.
|
|
351
342
|
Consumed by `AdminInvites`, `AdminOverview`.
|
|
352
|
-
- `audit_log_rpc_context` — `() => AuditLogRpc
|
|
343
|
+
- `audit_log_rpc_context` — `() => AuditLogRpc`. Consumed by
|
|
353
344
|
`AdminAuditLog`, `AdminRoleGrantHistory`, `AdminOverview`.
|
|
354
|
-
- `app_settings_rpc_context` — `() => AppSettingsRpc
|
|
345
|
+
- `app_settings_rpc_context` — `() => AppSettingsRpc`.
|
|
355
346
|
Consumed by `OpenSignupToggle`, `AdminOverview`.
|
|
356
|
-
- `account_sessions_rpc_context` — `() => AccountSessionsRpc
|
|
347
|
+
- `account_sessions_rpc_context` — `() => AccountSessionsRpc`.
|
|
357
348
|
Consumed by `AccountSessions`.
|
|
358
349
|
- `role_grant_offers_state_context` — carries `RoleGrantOffersState`
|
|
359
350
|
directly. Consumed by `RoleGrantOfferInbox`, `RoleGrantOfferForm`,
|