@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.
Files changed (114) hide show
  1. package/dist/actions/CLAUDE.md +46 -20
  2. package/dist/actions/action_dispatcher.d.ts +1 -1
  3. package/dist/actions/action_dispatcher.d.ts.map +1 -1
  4. package/dist/actions/action_dispatcher.js +22 -16
  5. package/dist/actions/action_event.d.ts +18 -2
  6. package/dist/actions/action_event.d.ts.map +1 -1
  7. package/dist/actions/action_event.js +63 -19
  8. package/dist/actions/action_event_types.d.ts +22 -0
  9. package/dist/actions/action_event_types.d.ts.map +1 -1
  10. package/dist/actions/action_event_types.js +19 -0
  11. package/dist/actions/compile_action_registry.d.ts +4 -2
  12. package/dist/actions/compile_action_registry.d.ts.map +1 -1
  13. package/dist/actions/compile_action_registry.js +8 -3
  14. package/dist/actions/frontend_rpc_client.d.ts +6 -0
  15. package/dist/actions/frontend_rpc_client.d.ts.map +1 -1
  16. package/dist/actions/frontend_rpc_client.js +2 -1
  17. package/dist/actions/heartbeat.d.ts +8 -4
  18. package/dist/actions/heartbeat.d.ts.map +1 -1
  19. package/dist/actions/heartbeat.js +8 -4
  20. package/dist/actions/peer_ping.d.ts.map +1 -1
  21. package/dist/actions/peer_ping.js +3 -1
  22. package/dist/actions/perform_action.d.ts +1 -1
  23. package/dist/actions/perform_action.d.ts.map +1 -1
  24. package/dist/actions/perform_action.js +6 -4
  25. package/dist/actions/register_action_ws.d.ts +13 -0
  26. package/dist/actions/register_action_ws.d.ts.map +1 -1
  27. package/dist/actions/register_action_ws.js +23 -2
  28. package/dist/actions/rpc_client.d.ts +1 -1
  29. package/dist/actions/rpc_client.d.ts.map +1 -1
  30. package/dist/actions/rpc_client.js +2 -1
  31. package/dist/actions/socket.svelte.d.ts +53 -10
  32. package/dist/actions/socket.svelte.d.ts.map +1 -1
  33. package/dist/actions/socket.svelte.js +84 -23
  34. package/dist/actions/transports.d.ts +24 -0
  35. package/dist/actions/transports.d.ts.map +1 -1
  36. package/dist/actions/transports.js +30 -0
  37. package/dist/actions/transports_http.d.ts +11 -4
  38. package/dist/actions/transports_http.d.ts.map +1 -1
  39. package/dist/actions/transports_http.js +63 -18
  40. package/dist/actions/transports_ws.d.ts +28 -3
  41. package/dist/actions/transports_ws.d.ts.map +1 -1
  42. package/dist/actions/transports_ws.js +33 -4
  43. package/dist/actions/ws_endpoint_spec.d.ts +7 -0
  44. package/dist/actions/ws_endpoint_spec.d.ts.map +1 -1
  45. package/dist/auth/CLAUDE.md +6 -1
  46. package/dist/auth/audit_log_route_schema.d.ts.map +1 -1
  47. package/dist/auth/audit_log_route_schema.js +12 -1
  48. package/dist/auth/role_grant_offer_action_specs.d.ts +2 -1
  49. package/dist/auth/role_grant_offer_action_specs.d.ts.map +1 -1
  50. package/dist/auth/role_grant_offer_action_specs.js +2 -1
  51. package/dist/db/fact_disk_storage.js +1 -1
  52. package/dist/http/CLAUDE.md +10 -6
  53. package/dist/http/auth_shape.d.ts +19 -6
  54. package/dist/http/auth_shape.d.ts.map +1 -1
  55. package/dist/http/auth_shape.js +19 -6
  56. package/dist/http/jsonrpc_helpers.d.ts +0 -5
  57. package/dist/http/jsonrpc_helpers.d.ts.map +1 -1
  58. package/dist/http/jsonrpc_helpers.js +0 -13
  59. package/dist/http/schema_helpers.d.ts +56 -0
  60. package/dist/http/schema_helpers.d.ts.map +1 -1
  61. package/dist/http/schema_helpers.js +91 -0
  62. package/dist/http/surface_query.d.ts +29 -4
  63. package/dist/http/surface_query.d.ts.map +1 -1
  64. package/dist/http/surface_query.js +30 -5
  65. package/dist/realtime/sse_auth_guard.d.ts +9 -3
  66. package/dist/realtime/sse_auth_guard.d.ts.map +1 -1
  67. package/dist/realtime/sse_auth_guard.js +9 -3
  68. package/dist/server/app_server.d.ts.map +1 -1
  69. package/dist/server/app_server.js +1 -0
  70. package/dist/testing/CLAUDE.md +18 -13
  71. package/dist/testing/attack_surface.d.ts +5 -2
  72. package/dist/testing/attack_surface.d.ts.map +1 -1
  73. package/dist/testing/attack_surface.js +45 -17
  74. package/dist/testing/auth_apps.d.ts +25 -0
  75. package/dist/testing/auth_apps.d.ts.map +1 -1
  76. package/dist/testing/auth_apps.js +34 -5
  77. package/dist/testing/cross_backend/peer_ping_ws.d.ts.map +1 -1
  78. package/dist/testing/cross_backend/peer_ping_ws.js +18 -0
  79. package/dist/testing/cross_backend/testing_reset_actions.d.ts.map +1 -1
  80. package/dist/testing/cross_backend/testing_reset_actions.js +3 -2
  81. package/dist/testing/cross_backend/token_scope_surface.d.ts.map +1 -1
  82. package/dist/testing/cross_backend/token_scope_surface.js +36 -7
  83. package/dist/testing/cross_backend/ws_round_trip.d.ts +11 -3
  84. package/dist/testing/cross_backend/ws_round_trip.d.ts.map +1 -1
  85. package/dist/testing/cross_backend/ws_round_trip.js +74 -12
  86. package/dist/testing/surface_invariants.d.ts +7 -1
  87. package/dist/testing/surface_invariants.d.ts.map +1 -1
  88. package/dist/testing/surface_invariants.js +11 -5
  89. package/dist/testing/transports/ws_client.d.ts +6 -0
  90. package/dist/testing/transports/ws_client.d.ts.map +1 -1
  91. package/dist/testing/transports/ws_transport.d.ts.map +1 -1
  92. package/dist/testing/transports/ws_transport.js +6 -1
  93. package/dist/testing/ws_round_trip.d.ts.map +1 -1
  94. package/dist/testing/ws_round_trip.js +5 -0
  95. package/dist/ui/AdminAccounts.svelte +6 -4
  96. package/dist/ui/AdminAccounts.svelte.d.ts.map +1 -1
  97. package/dist/ui/AdminInvites.svelte +3 -3
  98. package/dist/ui/AdminInvites.svelte.d.ts.map +1 -1
  99. package/dist/ui/AdminOverview.svelte +10 -10
  100. package/dist/ui/AdminOverview.svelte.d.ts.map +1 -1
  101. package/dist/ui/AdminRoleGrantHistory.svelte +7 -7
  102. package/dist/ui/AdminRoleGrantHistory.svelte.d.ts.map +1 -1
  103. package/dist/ui/AdminSettings.svelte +1 -1
  104. package/dist/ui/RoleGrantOfferInbox.svelte +4 -1
  105. package/dist/ui/RoleGrantOfferInbox.svelte.d.ts.map +1 -1
  106. package/dist/ui/SurfaceExplorer.svelte +33 -17
  107. package/dist/ui/SurfaceExplorer.svelte.d.ts.map +1 -1
  108. package/dist/ui/form_state.svelte.d.ts +9 -4
  109. package/dist/ui/form_state.svelte.d.ts.map +1 -1
  110. package/dist/ui/form_state.svelte.js +28 -8
  111. package/package.json +10 -10
  112. package/dist/actions/request_tracker.svelte.d.ts +0 -77
  113. package/dist/actions/request_tracker.svelte.d.ts.map +0 -1
  114. 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
- * A fourth case (gated on `rpc_path`) covers server-initiated close: an
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. Up to four cases over a
54
- * real upgrade: authed `heartbeat` round-trip, anonymous-upgrade refusal,
55
- * disallowed-origin refusal, and — when `rpc_path` is supplied —
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 fixture = await setup_test();
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 role/keeper route has 403 in `error_schemas`.
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":"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"}
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 role/keeper route has 403 in `error_schemas`.
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 keeper_routes = filter_keeper_routes(surface);
39
- for (const route of [...role_routes, ...keeper_routes]) {
40
- assert.ok(route.error_schemas && '403' in route.error_schemas, `${format_route_key(route)} requires role/keeper but missing 403 error schema`);
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,CA8IvF,CAAC"}
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
- socket.on('close', () => {
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
- >{admin_accounts.account_count} account{admin_accounts.account_count === 1 ? '' : 's'}</span
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) && !row.pending_offers.some((o) => o.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":"AAkMA,QAAA,MAAM,aAAa,2DAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
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
- >{admin_invites.unclaimed_count} unclaimed / {admin_invites.invite_count} total</span
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":"AAqJA,QAAA,MAAM,YAAY,2DAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
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
- >{format_relative_time(most_recent.created_at)}</span
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
- >{format_relative_time(event.created_at)}</span
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
- >{format_relative_time(event.created_at)}</span
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"> log out </span>
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":"AAyUA,QAAA,MAAM,aAAa,2DAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
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
- >{row.username ?? truncate_uuid(row.actor_id ?? row.account_id ?? '?')}</span
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
- >{row.target_username ??
83
- truncate_uuid(row.target_actor_id ?? row.target_account_id ?? '?')}</span
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":"AAmGA,QAAA,MAAM,qBAAqB,2DAAwC,CAAC;AACpE,KAAK,qBAAqB,GAAG,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACtE,eAAe,qBAAqB,CAAC"}
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"}
@@ -33,7 +33,7 @@
33
33
  label="log out"
34
34
  >
35
35
  {#snippet popover_button_content()}
36
- <span class="p_md"> log out </span>
36
+ <span class="p_md">log out</span>
37
37
  {/snippet}
38
38
  </ConfirmButton>
39
39
  </section>
@@ -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 || role_grant_offers.accept.error || role_grant_offers.decline.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;AA+FH,QAAA,MAAM,mBAAmB,sDAAwC,CAAC;AAClE,KAAK,mBAAmB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAClE,eAAe,mBAAmB,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}<span class="chip color_a"
105
- >{summary.authenticated} authenticated</span
106
- >{/if}
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}{@const warnings = surface.diagnostics.filter(
124
+ {#if surface.diagnostics.length}
125
+ {@const warnings = surface.diagnostics.filter(
115
126
  (d: AppSurfaceDiagnostic) => d.level === 'warning'
116
- )}{#if warnings.length}<span class="chip color_e"
117
- >{warnings.length} warning{warnings.length === 1 ? '' : 's'}</span
118
- >{/if}{/if}
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
- >{mw.error_schemas ? Object.keys(mw.error_schemas).join(', ') : '-'}</td
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
- >{Object.keys(
298
+ <code>
299
+ {Object.keys(
285
300
  (event.params_schema as any).properties ?? event.params_schema
286
- ).join(', ')}</code
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><span class={d.level === 'warning' ? 'chip color_e' : 'chip'}>{d.level}</span></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;AAU3F,KAAK,gBAAgB,GAAI;IAAE,OAAO,EAAE,UAAU,CAAA;CAAE,CAAC;AAgclD,QAAA,MAAM,eAAe,sDAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,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 advancing
9
- * between focusable elements.
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 advancing between
52
- * focusable elements and tracks field touched state via delegated `focusout`.
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AASrD,qBAAa,SAAS;;IAKrB;;OAEG;IACH,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED;;;;;;;;OAQG;IACH,IAAI,IAAI,UAAU,CAAC,eAAe,CAAC;IAuCnC;;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"}
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"}