@fuzdev/fuz_app 0.63.0 → 0.65.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 (181) hide show
  1. package/dist/actions/CLAUDE.md +525 -827
  2. package/dist/actions/broadcast_api.d.ts +1 -1
  3. package/dist/actions/broadcast_api.js +1 -1
  4. package/dist/actions/cancel.d.ts +2 -2
  5. package/dist/actions/cancel.js +3 -3
  6. package/dist/actions/connection_closer.d.ts +65 -0
  7. package/dist/actions/connection_closer.d.ts.map +1 -0
  8. package/dist/actions/connection_closer.js +38 -0
  9. package/dist/actions/register_action_ws.d.ts +2 -2
  10. package/dist/actions/register_action_ws.d.ts.map +1 -1
  11. package/dist/actions/register_action_ws.js +23 -2
  12. package/dist/actions/register_ws_endpoint.d.ts +12 -10
  13. package/dist/actions/register_ws_endpoint.d.ts.map +1 -1
  14. package/dist/actions/register_ws_endpoint.js +5 -5
  15. package/dist/actions/transports_ws_auth_guard.d.ts +25 -10
  16. package/dist/actions/transports_ws_auth_guard.d.ts.map +1 -1
  17. package/dist/actions/transports_ws_auth_guard.js +24 -9
  18. package/dist/actions/ws_endpoint_spec.d.ts +119 -0
  19. package/dist/actions/ws_endpoint_spec.d.ts.map +1 -0
  20. package/dist/actions/ws_endpoint_spec.js +13 -0
  21. package/dist/auth/CLAUDE.md +592 -1808
  22. package/dist/auth/account_action_specs.d.ts +1 -1
  23. package/dist/auth/account_actions.d.ts +13 -0
  24. package/dist/auth/account_actions.d.ts.map +1 -1
  25. package/dist/auth/account_actions.js +31 -1
  26. package/dist/auth/account_routes.d.ts +12 -2
  27. package/dist/auth/account_routes.d.ts.map +1 -1
  28. package/dist/auth/account_routes.js +55 -8
  29. package/dist/auth/account_schema.d.ts +4 -4
  30. package/dist/auth/account_schema.d.ts.map +1 -1
  31. package/dist/auth/admin_action_specs.d.ts +8 -8
  32. package/dist/auth/admin_actions.d.ts +11 -0
  33. package/dist/auth/admin_actions.d.ts.map +1 -1
  34. package/dist/auth/admin_actions.js +25 -0
  35. package/dist/auth/api_token_queries.js +1 -1
  36. package/dist/auth/audit_emitter.d.ts +56 -12
  37. package/dist/auth/audit_emitter.d.ts.map +1 -1
  38. package/dist/auth/audit_emitter.js +38 -12
  39. package/dist/auth/audit_log_ddl.d.ts +1 -1
  40. package/dist/auth/audit_log_ddl.d.ts.map +1 -1
  41. package/dist/auth/audit_log_ddl.js +1 -1
  42. package/dist/auth/audit_log_schema.d.ts +5 -3
  43. package/dist/auth/audit_log_schema.d.ts.map +1 -1
  44. package/dist/auth/audit_log_schema.js +5 -3
  45. package/dist/auth/bootstrap_account.d.ts.map +1 -1
  46. package/dist/auth/bootstrap_account.js +1 -5
  47. package/dist/auth/bootstrap_routes.d.ts +8 -2
  48. package/dist/auth/bootstrap_routes.d.ts.map +1 -1
  49. package/dist/auth/bootstrap_routes.js +15 -11
  50. package/dist/auth/invite_schema.d.ts +2 -2
  51. package/dist/auth/keyring.d.ts +6 -6
  52. package/dist/auth/keyring.js +8 -8
  53. package/dist/auth/role_grant_offer_actions.d.ts.map +1 -1
  54. package/dist/auth/role_grant_offer_actions.js +4 -2
  55. package/dist/auth/signup_routes.d.ts +1 -1
  56. package/dist/auth/standard_rpc_actions.d.ts +1 -0
  57. package/dist/auth/standard_rpc_actions.d.ts.map +1 -1
  58. package/dist/auth/standard_rpc_actions.js +1 -0
  59. package/dist/db/create_db.d.ts.map +1 -1
  60. package/dist/db/create_db.js +13 -0
  61. package/dist/dev/setup.d.ts +2 -2
  62. package/dist/dev/setup.js +3 -3
  63. package/dist/http/CLAUDE.md +225 -483
  64. package/dist/http/error_schemas.d.ts +0 -4
  65. package/dist/http/error_schemas.d.ts.map +1 -1
  66. package/dist/http/error_schemas.js +0 -4
  67. package/dist/http/ip_canonical.d.ts +100 -0
  68. package/dist/http/ip_canonical.d.ts.map +1 -0
  69. package/dist/http/ip_canonical.js +195 -0
  70. package/dist/http/origin.d.ts +14 -6
  71. package/dist/http/origin.d.ts.map +1 -1
  72. package/dist/http/origin.js +14 -32
  73. package/dist/http/pending_effects.d.ts +1 -1
  74. package/dist/http/pending_effects.js +1 -1
  75. package/dist/http/proxy.d.ts +13 -5
  76. package/dist/http/proxy.d.ts.map +1 -1
  77. package/dist/http/proxy.js +15 -23
  78. package/dist/http/surface.d.ts +50 -0
  79. package/dist/http/surface.d.ts.map +1 -1
  80. package/dist/http/surface.js +27 -1
  81. package/dist/primitive_schemas.d.ts +20 -4
  82. package/dist/primitive_schemas.d.ts.map +1 -1
  83. package/dist/primitive_schemas.js +25 -4
  84. package/dist/realtime/sse_auth_guard.d.ts +16 -4
  85. package/dist/realtime/sse_auth_guard.d.ts.map +1 -1
  86. package/dist/realtime/sse_auth_guard.js +15 -3
  87. package/dist/runtime/mock.js +1 -1
  88. package/dist/server/app_backend.d.ts +66 -19
  89. package/dist/server/app_backend.d.ts.map +1 -1
  90. package/dist/server/app_backend.js +57 -34
  91. package/dist/server/app_server.d.ts +101 -10
  92. package/dist/server/app_server.d.ts.map +1 -1
  93. package/dist/server/app_server.js +105 -6
  94. package/dist/server/env.d.ts +7 -7
  95. package/dist/server/env.d.ts.map +1 -1
  96. package/dist/server/env.js +14 -14
  97. package/dist/server/startup.d.ts.map +1 -1
  98. package/dist/server/startup.js +12 -0
  99. package/dist/server/static.d.ts +4 -4
  100. package/dist/server/static.js +7 -7
  101. package/dist/testing/CLAUDE.md +269 -59
  102. package/dist/testing/admin_integration.d.ts +18 -23
  103. package/dist/testing/admin_integration.d.ts.map +1 -1
  104. package/dist/testing/admin_integration.js +159 -202
  105. package/dist/testing/adversarial_headers.d.ts +6 -0
  106. package/dist/testing/adversarial_headers.d.ts.map +1 -1
  107. package/dist/testing/adversarial_headers.js +13 -5
  108. package/dist/testing/app_server.d.ts +148 -60
  109. package/dist/testing/app_server.d.ts.map +1 -1
  110. package/dist/testing/app_server.js +143 -54
  111. package/dist/testing/attack_surface.d.ts +8 -7
  112. package/dist/testing/attack_surface.d.ts.map +1 -1
  113. package/dist/testing/attack_surface.js +12 -8
  114. package/dist/testing/audit_completeness.d.ts +23 -22
  115. package/dist/testing/audit_completeness.d.ts.map +1 -1
  116. package/dist/testing/audit_completeness.js +199 -158
  117. package/dist/testing/audit_drift_guard.d.ts +116 -0
  118. package/dist/testing/audit_drift_guard.d.ts.map +1 -0
  119. package/dist/testing/audit_drift_guard.js +134 -0
  120. package/dist/testing/bootstrap_success.d.ts +28 -0
  121. package/dist/testing/bootstrap_success.d.ts.map +1 -0
  122. package/dist/testing/bootstrap_success.js +144 -0
  123. package/dist/testing/connection_closer_helpers.d.ts +44 -0
  124. package/dist/testing/connection_closer_helpers.d.ts.map +1 -0
  125. package/dist/testing/connection_closer_helpers.js +48 -0
  126. package/dist/testing/cross_backend/capabilities.d.ts +64 -0
  127. package/dist/testing/cross_backend/capabilities.d.ts.map +1 -0
  128. package/dist/testing/cross_backend/capabilities.js +47 -0
  129. package/dist/testing/cross_backend/setup.d.ts +215 -0
  130. package/dist/testing/cross_backend/setup.d.ts.map +1 -0
  131. package/dist/testing/cross_backend/setup.js +101 -0
  132. package/dist/testing/data_exposure.d.ts +14 -15
  133. package/dist/testing/data_exposure.d.ts.map +1 -1
  134. package/dist/testing/data_exposure.js +127 -146
  135. package/dist/testing/db_entities.d.ts +11 -1
  136. package/dist/testing/db_entities.d.ts.map +1 -1
  137. package/dist/testing/db_entities.js +13 -1
  138. package/dist/testing/integration.d.ts +35 -21
  139. package/dist/testing/integration.d.ts.map +1 -1
  140. package/dist/testing/integration.js +231 -293
  141. package/dist/testing/integration_helpers.d.ts +16 -6
  142. package/dist/testing/integration_helpers.d.ts.map +1 -1
  143. package/dist/testing/integration_helpers.js +7 -7
  144. package/dist/testing/mock_fs.d.ts.map +1 -1
  145. package/dist/testing/mock_fs.js +0 -2
  146. package/dist/testing/rate_limiting.d.ts.map +1 -1
  147. package/dist/testing/rate_limiting.js +13 -4
  148. package/dist/testing/role_grant_helpers.d.ts +31 -0
  149. package/dist/testing/role_grant_helpers.d.ts.map +1 -0
  150. package/dist/testing/role_grant_helpers.js +46 -0
  151. package/dist/testing/round_trip.d.ts +21 -16
  152. package/dist/testing/round_trip.d.ts.map +1 -1
  153. package/dist/testing/round_trip.js +65 -86
  154. package/dist/testing/rpc_helpers.d.ts +2 -1
  155. package/dist/testing/rpc_helpers.d.ts.map +1 -1
  156. package/dist/testing/rpc_round_trip.d.ts +24 -21
  157. package/dist/testing/rpc_round_trip.d.ts.map +1 -1
  158. package/dist/testing/rpc_round_trip.js +91 -106
  159. package/dist/testing/schema_introspect.d.ts +106 -0
  160. package/dist/testing/schema_introspect.d.ts.map +1 -0
  161. package/dist/testing/schema_introspect.js +123 -0
  162. package/dist/testing/schema_parity.d.ts +144 -0
  163. package/dist/testing/schema_parity.d.ts.map +1 -0
  164. package/dist/testing/schema_parity.js +233 -0
  165. package/dist/testing/sse_round_trip.d.ts.map +1 -1
  166. package/dist/testing/sse_round_trip.js +12 -6
  167. package/dist/testing/standard.d.ts +57 -25
  168. package/dist/testing/standard.d.ts.map +1 -1
  169. package/dist/testing/standard.js +62 -5
  170. package/dist/testing/stubs.d.ts +22 -3
  171. package/dist/testing/stubs.d.ts.map +1 -1
  172. package/dist/testing/stubs.js +28 -21
  173. package/dist/testing/surface_invariants.d.ts +66 -1
  174. package/dist/testing/surface_invariants.d.ts.map +1 -1
  175. package/dist/testing/surface_invariants.js +103 -1
  176. package/dist/testing/transports/surface_source.d.ts +51 -0
  177. package/dist/testing/transports/surface_source.d.ts.map +1 -0
  178. package/dist/testing/transports/surface_source.js +19 -0
  179. package/dist/ui/SurfaceExplorer.svelte +161 -2
  180. package/dist/ui/SurfaceExplorer.svelte.d.ts.map +1 -1
  181. package/package.json +4 -4
@@ -96,6 +96,52 @@ export interface ErrorSchemaAuditEntry {
96
96
  * @returns audit entries for every route x status combination
97
97
  */
98
98
  export declare const audit_error_schema_tightness: (surface: AppSurface) => Array<ErrorSchemaAuditEntry>;
99
+ /**
100
+ * Every RPC method on every endpoint has a non-empty `description`.
101
+ *
102
+ * Parallel of `assert_descriptions_present` over `surface.rpc_endpoints`.
103
+ * Empty descriptions on RPC methods leak through `library.json` codegen and
104
+ * consumer-facing docs without the route-level check catching them.
105
+ */
106
+ export declare const assert_rpc_method_descriptions_present: (surface: AppSurface) => void;
107
+ /**
108
+ * Every WS method on every endpoint has a non-empty `description`.
109
+ *
110
+ * Parallel of `assert_descriptions_present` over `surface.ws_endpoints`.
111
+ * Same rationale as `assert_rpc_method_descriptions_present` — codegen +
112
+ * surface explorer consume the description, blank values surface as `''`.
113
+ */
114
+ export declare const assert_ws_method_descriptions_present: (surface: AppSurface) => void;
115
+ /**
116
+ * Every WS endpoint's `methods` includes every protocol action method
117
+ * (`heartbeat`, `cancel`).
118
+ *
119
+ * Consumers register WS endpoints by spreading `protocol_actions` from
120
+ * `actions/protocol.ts` before their own actions:
121
+ *
122
+ * ```ts
123
+ * ws_endpoints: [{path: '/api/ws', actions: [...protocol_actions, ...consumer_actions], ...}]
124
+ * ```
125
+ *
126
+ * Forgetting the spread compiles cleanly but breaks at runtime: client-side
127
+ * heartbeats and `cancel` notifications get `method_not_found` from the
128
+ * dispatcher, so disconnect detection silently regresses and per-request
129
+ * cancel never aborts the matching handler. Catch the mistake at the
130
+ * surface layer rather than at runtime.
131
+ */
132
+ export declare const assert_ws_endpoints_include_protocol_actions: (surface: AppSurface) => void;
133
+ /**
134
+ * WS methods follow the kind ⇔ auth biconditional emitted by surface
135
+ * generation: `kind === 'remote_notification' ⟺ auth === null`.
136
+ *
137
+ * `generate_app_surface` produces this shape directly from the action
138
+ * spec union (notifications carry `auth: null` per `ActionSpecUnion`;
139
+ * `request_response` carries a `RouteAuth`). The assertion guards against
140
+ * drift if a future surface emitter, transform, or test fixture violates
141
+ * it — and gives consumers a clear failure message when a hand-built
142
+ * surface mocks the shape incorrectly.
143
+ */
144
+ export declare const assert_ws_notifications_have_null_auth: (surface: AppSurface) => void;
99
145
  /**
100
146
  * Configuration for security policy invariants.
101
147
  *
@@ -146,7 +192,9 @@ export declare const assert_no_unexpected_public_mutations: (surface: AppSurface
146
192
  *
147
193
  * Note: RPC endpoints (`create_rpc_endpoint`) use `input: z.null()` on their
148
194
  * route specs — the dispatcher handles body/query parsing internally. Real input
149
- * schemas live in `rpc_endpoints` surface, not on routes.
195
+ * schemas live in `rpc_endpoints` surface, not on routes; see
196
+ * `assert_rpc_ws_surface_invariants` for the parallel checks over RPC/WS
197
+ * method shapes.
150
198
  */
151
199
  export declare const assert_mutation_routes_use_post: (surface: AppSurface) => void;
152
200
  /**
@@ -223,6 +271,23 @@ export declare const assert_error_schema_tightness: (surface: AppSurface, option
223
271
  * the offending route and the missing/inconsistent field.
224
272
  */
225
273
  export declare const assert_surface_invariants: (surface: AppSurface) => void;
274
+ /**
275
+ * Run all RPC / WS structural invariants. Options-free — applies
276
+ * universally to the `surface.rpc_endpoints` and `surface.ws_endpoints`
277
+ * slots produced by `generate_app_surface`.
278
+ *
279
+ * Parallel of `assert_surface_invariants` for the non-REST surfaces.
280
+ * Within-endpoint duplicate method names and the auth-shape biconditional
281
+ * are already enforced at startup by `compile_action_registry` (see
282
+ * `actions/CLAUDE.md` §Registry compile) — these assertions cover only
283
+ * the contract-surface concerns that a runtime registration check
284
+ * cannot: empty descriptions, missing protocol-action spread on WS
285
+ * endpoints, and kind ⇔ auth drift on WS methods.
286
+ *
287
+ * @throws AssertionError on the first invariant violation; the message
288
+ * names the offending endpoint, method, and field.
289
+ */
290
+ export declare const assert_rpc_ws_surface_invariants: (surface: AppSurface) => void;
226
291
  /**
227
292
  * Run security policy invariants. Configurable with sensible defaults.
228
293
  *
@@ -1 +1 @@
1
- {"version":3,"file":"surface_invariants.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/surface_invariants.ts"],"names":[],"mappings":"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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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"}
@@ -19,6 +19,7 @@ import './assert_dev_env.js';
19
19
  import { assert } from 'vitest';
20
20
  import { middleware_applies } from '../http/schema_helpers.js';
21
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';
22
+ import { PROTOCOL_ACTION_METHODS } from '../actions/action_codegen.js';
22
23
  // --- Structural invariants ---
23
24
  /**
24
25
  * Every protected route has 401 in `error_schemas`.
@@ -374,6 +375,83 @@ export const audit_error_schema_tightness = (surface) => {
374
375
  }
375
376
  return entries;
376
377
  };
378
+ // --- RPC / WS structural invariants ---
379
+ /**
380
+ * Every RPC method on every endpoint has a non-empty `description`.
381
+ *
382
+ * Parallel of `assert_descriptions_present` over `surface.rpc_endpoints`.
383
+ * Empty descriptions on RPC methods leak through `library.json` codegen and
384
+ * consumer-facing docs without the route-level check catching them.
385
+ */
386
+ export const assert_rpc_method_descriptions_present = (surface) => {
387
+ for (const ep of surface.rpc_endpoints) {
388
+ for (const method of ep.methods) {
389
+ assert.ok(method.description.length > 0, `RPC method '${method.name}' on endpoint '${ep.path}' has empty description`);
390
+ }
391
+ }
392
+ };
393
+ /**
394
+ * Every WS method on every endpoint has a non-empty `description`.
395
+ *
396
+ * Parallel of `assert_descriptions_present` over `surface.ws_endpoints`.
397
+ * Same rationale as `assert_rpc_method_descriptions_present` — codegen +
398
+ * surface explorer consume the description, blank values surface as `''`.
399
+ */
400
+ export const assert_ws_method_descriptions_present = (surface) => {
401
+ for (const ep of surface.ws_endpoints) {
402
+ for (const method of ep.methods) {
403
+ assert.ok(method.description.length > 0, `WS method '${method.name}' on endpoint '${ep.path}' has empty description`);
404
+ }
405
+ }
406
+ };
407
+ /**
408
+ * Every WS endpoint's `methods` includes every protocol action method
409
+ * (`heartbeat`, `cancel`).
410
+ *
411
+ * Consumers register WS endpoints by spreading `protocol_actions` from
412
+ * `actions/protocol.ts` before their own actions:
413
+ *
414
+ * ```ts
415
+ * ws_endpoints: [{path: '/api/ws', actions: [...protocol_actions, ...consumer_actions], ...}]
416
+ * ```
417
+ *
418
+ * Forgetting the spread compiles cleanly but breaks at runtime: client-side
419
+ * heartbeats and `cancel` notifications get `method_not_found` from the
420
+ * dispatcher, so disconnect detection silently regresses and per-request
421
+ * cancel never aborts the matching handler. Catch the mistake at the
422
+ * surface layer rather than at runtime.
423
+ */
424
+ export const assert_ws_endpoints_include_protocol_actions = (surface) => {
425
+ for (const ep of surface.ws_endpoints) {
426
+ const method_names = new Set(ep.methods.map((m) => m.name));
427
+ for (const expected of PROTOCOL_ACTION_METHODS) {
428
+ assert.ok(method_names.has(expected), `WS endpoint '${ep.path}' is missing protocol action method '${expected}' — ` +
429
+ `spread \`protocol_actions\` from 'actions/protocol.js' into \`actions\``);
430
+ }
431
+ }
432
+ };
433
+ /**
434
+ * WS methods follow the kind ⇔ auth biconditional emitted by surface
435
+ * generation: `kind === 'remote_notification' ⟺ auth === null`.
436
+ *
437
+ * `generate_app_surface` produces this shape directly from the action
438
+ * spec union (notifications carry `auth: null` per `ActionSpecUnion`;
439
+ * `request_response` carries a `RouteAuth`). The assertion guards against
440
+ * drift if a future surface emitter, transform, or test fixture violates
441
+ * it — and gives consumers a clear failure message when a hand-built
442
+ * surface mocks the shape incorrectly.
443
+ */
444
+ export const assert_ws_notifications_have_null_auth = (surface) => {
445
+ for (const ep of surface.ws_endpoints) {
446
+ for (const method of ep.methods) {
447
+ const is_notification = method.kind === 'remote_notification';
448
+ const has_null_auth = method.auth === null;
449
+ assert.ok(is_notification === has_null_auth, `WS method '${method.name}' on endpoint '${ep.path}' violates kind ⇔ auth: ` +
450
+ `kind='${method.kind}', auth=${has_null_auth ? 'null' : 'non-null'} ` +
451
+ `(notifications must have auth: null; request_response must have a RouteAuth)`);
452
+ }
453
+ }
454
+ };
377
455
  /** Default patterns for sensitive REST routes that should be rate-limited. */
378
456
  const DEFAULT_SENSITIVE_PATTERNS = [
379
457
  /\/login$/,
@@ -424,7 +502,9 @@ export const assert_no_unexpected_public_mutations = (surface, allowlist = []) =
424
502
  *
425
503
  * Note: RPC endpoints (`create_rpc_endpoint`) use `input: z.null()` on their
426
504
  * route specs — the dispatcher handles body/query parsing internally. Real input
427
- * schemas live in `rpc_endpoints` surface, not on routes.
505
+ * schemas live in `rpc_endpoints` surface, not on routes; see
506
+ * `assert_rpc_ws_surface_invariants` for the parallel checks over RPC/WS
507
+ * method shapes.
428
508
  */
429
509
  export const assert_mutation_routes_use_post = (surface) => {
430
510
  const input_routes = filter_routes_with_input(surface);
@@ -546,6 +626,28 @@ export const assert_surface_invariants = (surface) => {
546
626
  assert_error_code_status_consistency(surface);
547
627
  assert_404_schemas_use_specific_errors(surface);
548
628
  };
629
+ /**
630
+ * Run all RPC / WS structural invariants. Options-free — applies
631
+ * universally to the `surface.rpc_endpoints` and `surface.ws_endpoints`
632
+ * slots produced by `generate_app_surface`.
633
+ *
634
+ * Parallel of `assert_surface_invariants` for the non-REST surfaces.
635
+ * Within-endpoint duplicate method names and the auth-shape biconditional
636
+ * are already enforced at startup by `compile_action_registry` (see
637
+ * `actions/CLAUDE.md` §Registry compile) — these assertions cover only
638
+ * the contract-surface concerns that a runtime registration check
639
+ * cannot: empty descriptions, missing protocol-action spread on WS
640
+ * endpoints, and kind ⇔ auth drift on WS methods.
641
+ *
642
+ * @throws AssertionError on the first invariant violation; the message
643
+ * names the offending endpoint, method, and field.
644
+ */
645
+ export const assert_rpc_ws_surface_invariants = (surface) => {
646
+ assert_rpc_method_descriptions_present(surface);
647
+ assert_ws_method_descriptions_present(surface);
648
+ assert_ws_endpoints_include_protocol_actions(surface);
649
+ assert_ws_notifications_have_null_auth(surface);
650
+ };
549
651
  /**
550
652
  * Run security policy invariants. Configurable with sensible defaults.
551
653
  *
@@ -0,0 +1,51 @@
1
+ import '../assert_dev_env.js';
2
+ /**
3
+ * Discriminated source for the `AppSurface` a suite asserts against.
4
+ *
5
+ * In-process callers pass `{kind: 'inline', spec}` — the full
6
+ * `AppSurfaceSpec` with route closures intact. Cross-process callers
7
+ * pass `{kind: 'snapshot', path}` — a committed JSON file containing
8
+ * only the JSON-serializable `AppSurface` shape.
9
+ *
10
+ * Backs the suite parameter that previously was `build: () => AppSurfaceSpec`.
11
+ *
12
+ * @module
13
+ */
14
+ import type { AppSurface, AppSurfaceSpec } from '../../http/surface.js';
15
+ /**
16
+ * Where a suite reads the `AppSurface` from for its assertions.
17
+ *
18
+ * Two variants. The `inline` variant carries the full `AppSurfaceSpec`
19
+ * (with route closures) — the only variant in-process suites can use
20
+ * for route-iteration tests, since route closures aren't JSON-serializable.
21
+ * The `snapshot` variant carries a path to a committed JSON file containing
22
+ * the `AppSurface` shape only — cross-process consumers use this to assert
23
+ * against a backend that doesn't share TS handler closures.
24
+ *
25
+ * No `'fetched'` (live `/api/surface` endpoint) variant: a dead union
26
+ * case is dead weight and a code-shaped invitation to add a debug
27
+ * endpoint the design explicitly rejected; committed snapshot is the
28
+ * contract.
29
+ */
30
+ export type SurfaceSource = {
31
+ readonly kind: 'inline';
32
+ readonly spec: AppSurfaceSpec;
33
+ } | {
34
+ readonly kind: 'snapshot';
35
+ readonly path: string;
36
+ };
37
+ /**
38
+ * Resolve a `SurfaceSource` to the underlying surface shape.
39
+ *
40
+ * The `inline` variant returns the full `AppSurfaceSpec` (route closures
41
+ * available). The `snapshot` variant returns the serialized `AppSurface`
42
+ * shape only. Asymmetric on purpose — suites that need `route_specs`
43
+ * (with closures) must use the `inline` variant; suites working on the
44
+ * `AppSurface` shape work with either.
45
+ *
46
+ * @throws Error when called with `{kind: 'snapshot'}` — the snapshot
47
+ * variant lands alongside the cross-process transport plumbing.
48
+ * No in-process caller exercises this branch today.
49
+ */
50
+ export declare const resolve_surface_source: (src: SurfaceSource) => Promise<AppSurface | AppSurfaceSpec>;
51
+ //# sourceMappingURL=surface_source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surface_source.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/transports/surface_source.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAC,UAAU,EAAE,cAAc,EAAC,MAAM,uBAAuB,CAAC;AAEtE;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,aAAa,GACtB;IAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAA;CAAC,GACxD;IAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAC,CAAC;AAEtD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,sBAAsB,GAClC,KAAK,aAAa,KAChB,OAAO,CAAC,UAAU,GAAG,cAAc,CAKrC,CAAC"}
@@ -0,0 +1,19 @@
1
+ import '../assert_dev_env.js';
2
+ /**
3
+ * Resolve a `SurfaceSource` to the underlying surface shape.
4
+ *
5
+ * The `inline` variant returns the full `AppSurfaceSpec` (route closures
6
+ * available). The `snapshot` variant returns the serialized `AppSurface`
7
+ * shape only. Asymmetric on purpose — suites that need `route_specs`
8
+ * (with closures) must use the `inline` variant; suites working on the
9
+ * `AppSurface` shape work with either.
10
+ *
11
+ * @throws Error when called with `{kind: 'snapshot'}` — the snapshot
12
+ * variant lands alongside the cross-process transport plumbing.
13
+ * No in-process caller exercises this branch today.
14
+ */
15
+ export const resolve_surface_source = async (src) => {
16
+ if (src.kind === 'inline')
17
+ return src.spec;
18
+ throw new Error(`surface_source.kind === 'snapshot' is not yet implemented; lands with cross-process transport plumbing (path=${src.path})`);
19
+ };
@@ -17,6 +17,7 @@
17
17
  is_plain_authenticated_auth,
18
18
  is_public_auth,
19
19
  is_role_auth,
20
+ type RouteAuth,
20
21
  } from '../http/auth_shape.js';
21
22
 
22
23
  const {surface}: {surface: AppSurface} = $props();
@@ -28,6 +29,13 @@
28
29
 
29
30
  const summary = $derived(surface_auth_summary(surface));
30
31
 
32
+ const rpc_method_count = $derived(
33
+ surface.rpc_endpoints.reduce((sum, ep) => sum + ep.methods.length, 0),
34
+ );
35
+ const ws_method_count = $derived(
36
+ surface.ws_endpoints.reduce((sum, ep) => sum + ep.methods.length, 0),
37
+ );
38
+
31
39
  const auth_matches_filter = (
32
40
  auth: AppSurfaceRoute['auth'],
33
41
  filter: (typeof auth_types)[number],
@@ -51,6 +59,8 @@
51
59
  );
52
60
 
53
61
  let expanded_event: string | null = $state.raw(null);
62
+ let expanded_rpc_method: string | null = $state.raw(null);
63
+ let expanded_ws_method: string | null = $state.raw(null);
54
64
 
55
65
  const toggle_route = (key: string): void => {
56
66
  expanded_route = expanded_route === key ? null : key;
@@ -60,7 +70,15 @@
60
70
  expanded_event = expanded_event === method ? null : method;
61
71
  };
62
72
 
63
- const format_auth = (auth: AppSurfaceRoute['auth']): string => {
73
+ const toggle_rpc_method = (key: string): void => {
74
+ expanded_rpc_method = expanded_rpc_method === key ? null : key;
75
+ };
76
+
77
+ const toggle_ws_method = (key: string): void => {
78
+ expanded_ws_method = expanded_ws_method === key ? null : key;
79
+ };
80
+
81
+ const format_auth = (auth: RouteAuth): string => {
64
82
  if (is_public_auth(auth)) return 'none';
65
83
  if (is_keeper_auth(auth)) return 'keeper';
66
84
  if (is_role_auth(auth)) return `role:${auth.roles!.join('|')}`;
@@ -68,7 +86,7 @@
68
86
  return 'other';
69
87
  };
70
88
 
71
- const auth_chip_class = (auth: AppSurfaceRoute['auth']): string => {
89
+ const auth_chip_class = (auth: RouteAuth): string => {
72
90
  if (is_public_auth(auth)) return 'chip color_b';
73
91
  if (is_keeper_auth(auth)) return 'chip color_c';
74
92
  if (is_role_auth(auth)) return 'chip color_d';
@@ -89,6 +107,8 @@
89
107
  {#if role_count > 0}<span class="chip color_d">{role_count} role</span>{/if}
90
108
  {#if summary.keeper > 0}<span class="chip color_c">{summary.keeper} keeper</span>{/if}
91
109
  <span class="chip">{surface.middleware.length} middleware</span>
110
+ {#if rpc_method_count > 0}<span class="chip">{rpc_method_count} rpc methods</span>{/if}
111
+ {#if ws_method_count > 0}<span class="chip">{ws_method_count} ws methods</span>{/if}
92
112
  {#if surface.env.length}<span class="chip">{surface.env.length} env</span>{/if}
93
113
  {#if surface.events.length}<span class="chip">{surface.events.length} events</span>{/if}
94
114
  {#if surface.diagnostics.length}{@const warnings = surface.diagnostics.filter(
@@ -283,6 +303,145 @@
283
303
  </div>
284
304
  {/if}
285
305
 
306
+ {#if surface.rpc_endpoints.length}
307
+ <h3>rpc endpoints</h3>
308
+ {#each surface.rpc_endpoints as endpoint (endpoint.path)}
309
+ <div class="row" style:gap="var(--space_sm)" style:align-items="center">
310
+ <code>{endpoint.path}</code>
311
+ <span class="chip">{endpoint.methods.length} methods</span>
312
+ </div>
313
+ {#if endpoint.methods.length === 0}
314
+ <p class="text_50">no methods</p>
315
+ {:else}
316
+ <div style:overflow-x="auto">
317
+ <table>
318
+ <thead>
319
+ <tr>
320
+ <th>method</th>
321
+ <th>auth</th>
322
+ <th>side effects</th>
323
+ <th>rate limit</th>
324
+ <th>description</th>
325
+ </tr>
326
+ </thead>
327
+ <tbody>
328
+ {#each endpoint.methods as method (method.name)}
329
+ {@const key = `${endpoint.path}|${method.name}`}
330
+ <tr onclick={() => toggle_rpc_method(key)} style:cursor="pointer">
331
+ <td><code>{method.name}</code></td>
332
+ <td>
333
+ <span class={auth_chip_class(method.auth)}>{format_auth(method.auth)}</span>
334
+ </td>
335
+ <td>{method.side_effects ? 'yes' : 'no'}</td>
336
+ <td class="text_50">{method.rate_limit_key ?? '-'}</td>
337
+ <td class="text_50">{method.description}</td>
338
+ </tr>
339
+ {#if expanded_rpc_method === key}
340
+ <tr transition:slide>
341
+ <td colspan="5">
342
+ <div class="column" style:gap="var(--space_sm)">
343
+ <div>
344
+ <strong>input</strong>
345
+ {#if method.input_schema}
346
+ <pre>{JSON.stringify(method.input_schema, null, 2)}</pre>
347
+ {:else}
348
+ <span class="text_50">none (z.void)</span>
349
+ {/if}
350
+ </div>
351
+ <div>
352
+ <strong>output</strong>
353
+ <pre>{JSON.stringify(method.output_schema, null, 2)}</pre>
354
+ </div>
355
+ </div>
356
+ </td>
357
+ </tr>
358
+ {/if}
359
+ {/each}
360
+ </tbody>
361
+ </table>
362
+ </div>
363
+ {/if}
364
+ {/each}
365
+ {/if}
366
+
367
+ {#if surface.ws_endpoints.length}
368
+ <h3>websocket endpoints</h3>
369
+ {#each surface.ws_endpoints as endpoint (endpoint.path)}
370
+ <div
371
+ class="row"
372
+ style:gap="var(--space_sm)"
373
+ style:align-items="center"
374
+ style:flex-wrap="wrap"
375
+ >
376
+ <code>{endpoint.path}</code>
377
+ <span class="chip">{endpoint.methods.length} methods</span>
378
+ {#each endpoint.required_roles as role (role)}
379
+ <span class="chip color_d">role:{role}</span>
380
+ {/each}
381
+ {#each endpoint.allowed_origins as origin (origin)}
382
+ <span class="chip color_b"><code>{origin}</code></span>
383
+ {/each}
384
+ </div>
385
+ {#if endpoint.methods.length === 0}
386
+ <p class="text_50">no methods</p>
387
+ {:else}
388
+ <div style:overflow-x="auto">
389
+ <table>
390
+ <thead>
391
+ <tr>
392
+ <th>method</th>
393
+ <th>kind</th>
394
+ <th>auth</th>
395
+ <th>side effects</th>
396
+ <th>rate limit</th>
397
+ <th>description</th>
398
+ </tr>
399
+ </thead>
400
+ <tbody>
401
+ {#each endpoint.methods as method (method.name)}
402
+ {@const key = `${endpoint.path}|${method.name}`}
403
+ <tr onclick={() => toggle_ws_method(key)} style:cursor="pointer">
404
+ <td><code>{method.name}</code></td>
405
+ <td><span class="chip">{method.kind}</span></td>
406
+ <td>
407
+ {#if method.auth}
408
+ <span class={auth_chip_class(method.auth)}>{format_auth(method.auth)}</span>
409
+ {:else}
410
+ <span class="text_50">—</span>
411
+ {/if}
412
+ </td>
413
+ <td>{method.side_effects ? 'yes' : 'no'}</td>
414
+ <td class="text_50">{method.rate_limit_key ?? '-'}</td>
415
+ <td class="text_50">{method.description}</td>
416
+ </tr>
417
+ {#if expanded_ws_method === key}
418
+ <tr transition:slide>
419
+ <td colspan="6">
420
+ <div class="column" style:gap="var(--space_sm)">
421
+ <div>
422
+ <strong>input</strong>
423
+ {#if method.input_schema}
424
+ <pre>{JSON.stringify(method.input_schema, null, 2)}</pre>
425
+ {:else}
426
+ <span class="text_50">none (z.void)</span>
427
+ {/if}
428
+ </div>
429
+ <div>
430
+ <strong>output</strong>
431
+ <pre>{JSON.stringify(method.output_schema, null, 2)}</pre>
432
+ </div>
433
+ </div>
434
+ </td>
435
+ </tr>
436
+ {/if}
437
+ {/each}
438
+ </tbody>
439
+ </table>
440
+ </div>
441
+ {/if}
442
+ {/each}
443
+ {/if}
444
+
286
445
  {#if surface.diagnostics.length}
287
446
  <h3>diagnostics</h3>
288
447
  <div style:overflow-x="auto">
@@ -1 +1 @@
1
- {"version":3,"file":"SurfaceExplorer.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/ui/SurfaceExplorer.svelte"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAC,UAAU,EAAwC,MAAM,oBAAoB,CAAC;AASzF,KAAK,gBAAgB,GAAI;IAAC,OAAO,EAAE,UAAU,CAAA;CAAC,CAAC;AAuShD,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,EAAC,UAAU,EAAwC,MAAM,oBAAoB,CAAC;AAUzF,KAAK,gBAAgB,GAAI;IAAC,OAAO,EAAE,UAAU,CAAA;CAAC,CAAC;AAgchD,QAAA,MAAM,eAAe,sDAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fuzdev/fuz_app",
3
- "version": "0.63.0",
3
+ "version": "0.65.0",
4
4
  "description": "fullstack app library",
5
5
  "glyph": "🗝",
6
6
  "logo": "logo.svg",
@@ -46,11 +46,11 @@
46
46
  "@fuzdev/fuz_code": "^0.45.1",
47
47
  "@fuzdev/fuz_css": "^0.59.0",
48
48
  "@fuzdev/fuz_ui": "^0.192.0",
49
- "@fuzdev/fuz_util": "^0.59.0",
49
+ "@fuzdev/fuz_util": "^0.60.1",
50
50
  "@fuzdev/gro": "^0.199.0",
51
51
  "@jridgewell/trace-mapping": "^0.3.31",
52
52
  "@node-rs/argon2": "^2.0.2",
53
- "@ryanatkn/eslint-config": "^0.11.0",
53
+ "@ryanatkn/eslint-config": "^0.12.1",
54
54
  "@sveltejs/acorn-typescript": "^1.0.9",
55
55
  "@sveltejs/adapter-static": "^3.0.10",
56
56
  "@sveltejs/kit": "^2.55.0",
@@ -62,7 +62,7 @@
62
62
  "eslint": "^9.39.4",
63
63
  "eslint-plugin-svelte": "^3.15.1",
64
64
  "esm-env": "^1.2.2",
65
- "hono": "^4.12.7",
65
+ "hono": "^4.12.21",
66
66
  "jsdom": "^28.1.0",
67
67
  "magic-string": "^0.30.21",
68
68
  "pg": "^8.20.0",