@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
@@ -32,11 +32,22 @@ export const create_audit_log_route_shape = (required_role = DEFAULT_AUDIT_STREA
32
32
  account: 'required',
33
33
  actor: 'required',
34
34
  roles: [required_role],
35
+ // The stream is a session channel. A bearer that opens one cannot be
36
+ // closed when it is revoked: `token_revoke` closes WS sockets keyed by
37
+ // token, and SSE subscribers are not keyed that way, so a revoked
38
+ // token would keep receiving audit rows for the life of the
39
+ // connection. Gating the channel is what makes
40
+ // `realtime/sse_auth_guard.ts`'s omission of `token_revoke` correct
41
+ // rather than merely asserted.
42
+ credential_types: ['session'],
35
43
  // Rule 3 — a narrowed token holds no audit feed. Same reasoning as the
36
44
  // WS upgrade: this is a long-lived server→client stream whose contents
37
45
  // are decided by the account's role, not by any per-message scope
38
46
  // check, so there is no point after open at which a narrowing could
39
- // apply.
47
+ // apply. Unreachable behind the credential gate above on the default
48
+ // mount, and kept deliberately: it is the rule-3 declaration the
49
+ // surface census matches on, and it still governs a consumer that
50
+ // widens the channel gate.
40
51
  required_scope: 'surface:audit_stream'
41
52
  },
42
53
  description: 'Subscribe to realtime audit log events',
@@ -11,7 +11,8 @@
11
11
  * required (no roles) and rely on `query_*` IDOR guards or in-handler
12
12
  * policy checks (e.g. `role_grant_offer_list`/`_history` elevate to admin only
13
13
  * when inspecting another account — an input-dependent check that can't be
14
- * expressed at the spec level). `role_grant_revoke` adds `roles: ['admin']` —
14
+ * expressed at the spec level). `role_grant_revoke` and `role_grant_assign` add
15
+ * `roles: ['admin']` —
15
16
  * the RPC dispatcher's per-spec post-authorization auth gate
16
17
  * (`check_action_auth_post_authorization`) rejects non-admin callers before
17
18
  * the handler runs even though the endpoint hosts non-admin methods
@@ -1 +1 @@
1
- {"version":3,"file":"role_grant_offer_action_specs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/role_grant_offer_action_specs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"role_grant_offer_action_specs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/role_grant_offer_action_specs.ts"],"names":[],"mappings":"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"}
@@ -11,7 +11,8 @@
11
11
  * required (no roles) and rely on `query_*` IDOR guards or in-handler
12
12
  * policy checks (e.g. `role_grant_offer_list`/`_history` elevate to admin only
13
13
  * when inspecting another account — an input-dependent check that can't be
14
- * expressed at the spec level). `role_grant_revoke` adds `roles: ['admin']` —
14
+ * expressed at the spec level). `role_grant_revoke` and `role_grant_assign` add
15
+ * `roles: ['admin']` —
15
16
  * the RPC dispatcher's per-spec post-authorization auth gate
16
17
  * (`check_action_auth_post_authorization`) rejects non-admin callers before
17
18
  * the handler runs even though the endpoint hosts non-admin methods
@@ -29,7 +29,7 @@
29
29
  */
30
30
  import { createHash } from 'node:crypto';
31
31
  import { join } from 'node:path';
32
- import { Blake3Hasher } from '@fuzdev/blake3_wasm';
32
+ import { Blake3Hasher } from '@fuzdev/blake3-wasm';
33
33
  import { to_error_message } from '@fuzdev/fuz_util/error.ts';
34
34
  import { blake3_ready } from '@fuzdev/fuz_util/hash_blake3.ts';
35
35
  import { to_hex } from '@fuzdev/fuz_util/hex.ts';
@@ -17,7 +17,7 @@ effects, see ../../../docs/architecture.md.
17
17
  - `http/route_spec.ts` — `RouteSpec` + `apply_route_specs`, validation pipeline, transactions.
18
18
  - `http/auth_shape.ts` — canonical `RouteAuth` Zod schema + cross-axis invariants + predicates.
19
19
  - `http/error_schemas.ts` — `ERROR_*` constants, standard error shapes, `derive_error_schemas`.
20
- - `http/schema_helpers.ts` — shared Zod introspection (null/strict/surface/merge/middleware-applies).
20
+ - `http/schema_helpers.ts` — shared Zod introspection (null/void/strict/surface/merge/middleware-applies) + `to_void_params` / `to_input_params` / `safe_parse_dropping_unknown_keys`.
21
21
  - `http/middleware_spec.ts` — `MiddlewareSpec` interface.
22
22
  - `http/surface.ts` — `AppSurface`, `AppSurfaceSpec`, `generate_app_surface`, diagnostics.
23
23
  - `http/surface_query.ts` — pure filters/groupings over `AppSurface`.
@@ -220,7 +220,7 @@ confirmation.
220
220
  — extracted to break a circular dependency between `http/route_spec.ts`
221
221
  (input validation) and `http/surface.ts` (surface generation).
222
222
 
223
- **Import `is_null_schema`, `is_strict_object_schema`, `schema_to_surface`,
223
+ **Import `is_null_schema`, `is_void_schema`, `to_void_params`, `to_input_params`, `is_strict_object_schema`, `schema_to_surface`,
224
224
  `middleware_applies`, and `merge_error_schemas` from `http/schema_helpers.ts`,
225
225
  not from `http/surface.ts`.** The helpers were moved; `http/surface.ts`
226
226
  only imports and re-uses them for generation logic.
@@ -228,6 +228,10 @@ only imports and re-uses them for generation logic.
228
228
  Key helpers:
229
229
 
230
230
  - `is_null_schema(schema)` — `instanceof z.ZodNull` (not parse-null, to avoid false positives from `z.nullable(z.string())`)
231
+ - `is_void_schema(schema)` — `instanceof z.ZodVoid`; a `z.void()` input declares a parameterless RPC method
232
+ - `to_void_params(raw_params)` — reads absent, `null`, and `{}` params of a `z.void()` input as the no-arg call (`undefined`), passing any other shape through for `z.void()` to refuse — the twin of the Rust spine's `require_void_params`
233
+ - `to_input_params(input, raw_params)` — the one params normalizer every receiving end runs before `input.safeParse`: `to_void_params` for a `z.void()` input, else absent/`null` → `{}`; used by both the server dispatch core (`perform_action`) and the peer receive path (`ActionDispatcher`)
234
+ - `safe_parse_dropping_unknown_keys(schema, value)` — the forward-compatible read of a remote-authored payload: when every issue is an unrecognized key, strips those keys from a copy and reparses; any other issue still fails. Used for response `result`s (`ActionEvent`) and peer replies (`peer/ping`); matches serde's ignore-unknown-fields default on the Rust spine
231
235
  - `is_strict_object_schema(schema)` — detects `z.strictObject()` by checking `schema.def.catchall instanceof z.ZodNever`
232
236
  - `schema_to_surface(schema)` — Zod → JSON Schema, with `$schema` and `default` keys stripped recursively (defaults may be non-deterministic; `$schema` is snapshot noise)
233
237
  - `middleware_applies(mw_path, route_path)` — Hono pattern matching: `'*'`, exact, `'/api/*'` prefix (handles `prefix.slice(0, -1)` so `/api/*` also matches the bare `/api`)
@@ -264,11 +268,11 @@ the source specs, for tests that need to iterate over raw specs.
264
268
  No side effects, no state — filters and groupings over `AppSurface`:
265
269
 
266
270
  - `filter_protected_routes` / `filter_public_routes`
267
- - `filter_role_routes` / `filter_authenticated_routes` / `filter_keeper_routes` / `filter_routes_for_role(role)`
271
+ - `filter_role_routes` / `filter_authenticated_routes` / `filter_keeper_routes` / `filter_credential_gated_routes` (any `auth.credential_types` gate — superset of keeper) / `filter_routes_for_role(role)`
268
272
  - `filter_routes_by_prefix(prefix)` / `filter_routes_with_input` / `filter_routes_with_params` / `filter_routes_with_query` / `filter_mutation_routes` / `filter_rate_limited_routes`
269
- - `routes_by_auth_type(surface)` — `Map<RouteAuthCategory, Array<AppSurfaceRoute>>` where `RouteAuthCategory = 'none' | 'authenticated' | 'optional' | 'keeper' | 'role:<name>' | 'other'`. Multi-role specs appear under each role bucket
273
+ - `routes_by_auth_type(surface)` — `Map<RouteAuthCategory, Array<AppSurfaceRoute>>` where `RouteAuthCategory = 'none' | 'authenticated' | 'optional' | 'keeper' | 'role:<name>' | 'credential:<type>' | 'other'`. Multi-role / multi-channel specs appear under each bucket. Keeper is tested before the role bucket and the general credential bucket after it — keeper is an authority _level_ and names the route, a session gate is a _channel_ restriction over the authority the route already declares (so the audit SSE stream buckets as `role:admin`)
270
274
  - `format_route_key(route)` → `'METHOD /path'`
271
- - `surface_auth_summary(surface)` — counts per auth type, roles broken out by name
275
+ - `surface_auth_summary(surface)` — counts per auth type, roles and credential channels broken out by name; buckets exactly as `routes_by_auth_type`
272
276
 
273
277
  The per-route auth predicates these filters compose over (`is_public_auth`,
274
278
  `is_role_auth`, `is_credential_gated_auth`, `is_keeper_auth`,
@@ -401,7 +405,7 @@ to a JSON-RPC code.
401
405
  - Envelope schemas in `http/jsonrpc.ts`: `JsonrpcRequest`, `JsonrpcNotification`, `JsonrpcResponse`, `JsonrpcErrorResponse`, `JsonrpcResponseOrError`, `JsonrpcMessage`, `JsonrpcMessageFromClientToServer`, `JsonrpcMessageFromServerToClient`. Also `JsonrpcRequestId`, `JsonrpcMethod`, `JsonrpcProgressToken`, `JsonrpcMcpMeta`, `JsonrpcRequestParamsMeta`
402
406
  - Builders in `http/jsonrpc_helpers.ts`: `create_jsonrpc_request`, `create_jsonrpc_notification`, `create_jsonrpc_response`, `create_jsonrpc_error_response`, `create_jsonrpc_error_response_from_thrown` (preserves code/message/data on `ThrownJsonrpcError`; plain `Error` → `internal_error` with `{stack}` in DEV)
403
407
  - Type guards: `is_jsonrpc_request_id` (rejects NaN/Infinity), `is_jsonrpc_object`, `is_jsonrpc_message`, `is_jsonrpc_request` / `_notification` / `_response` / `_error_response`
404
- - Converters: `to_jsonrpc_message_id`, `to_jsonrpc_params` (normalizes primitives to `{value}`), `to_jsonrpc_result` (null/undefined → `{}`, primitives → `{value}`)
408
+ - Converters: `to_jsonrpc_message_id`, `to_jsonrpc_params` (normalizes primitives to `{value}`)
405
409
 
406
410
  Handlers can `throw jsonrpc_errors.*` — `apply_route_specs`' error-catch
407
411
  layer converts to `{error: JsonrpcErrorObject}` at the correct HTTP status.
@@ -189,16 +189,29 @@ export declare const is_role_auth: (auth: RouteAuth) => boolean;
189
189
  /** True iff the route declares any credential-type gate (`auth.credential_types?.length`). */
190
190
  export declare const is_credential_gated_auth: (auth: RouteAuth) => boolean;
191
191
  /**
192
- * True iff the route is the keeper bucket — credential gate restricted
193
- * to `daemon_token`. Keeper is the only credential gate today; if more
194
- * land, this filter widens. Knows the `'daemon_token'` literal directly
195
- * (the keeper composition is fuz_app's only registered credential gate).
192
+ * True iff the route is the keeper bucket — a credential gate admitting
193
+ * `daemon_token`. Knows the literal directly, because keeper is a named
194
+ * authority level rather than one channel among many: it is the ceiling
195
+ * sessions and api tokens cannot reach.
196
+ *
197
+ * Narrower than `is_credential_gated_auth`, which is true of every channel
198
+ * gate — including the session-only gates pointing the other way (the
199
+ * credential-minting actions, `POST /logout` / `POST /password`, the audit
200
+ * SSE stream). Reach for the general predicate when the question is "does a
201
+ * channel gate answer here"; reach for this one only when the question is
202
+ * about keeper specifically.
196
203
  */
197
204
  export declare const is_keeper_auth: (auth: RouteAuth) => boolean;
198
205
  /**
199
206
  * True iff the route is plain authenticated — `account === 'required'`
200
- * with no role gate and no credential gate. Account-grain authenticated
201
- * routes (logout, password change, account self-service) fall here.
207
+ * with no role gate and no credential gate: any credential the auth
208
+ * middleware resolved gets in.
209
+ *
210
+ * A channel gate takes a route out of this bucket, which is why the
211
+ * account-grain routes one might expect here are not — `POST /logout`,
212
+ * `POST /password`, and the `account_*` credential-lifecycle actions all
213
+ * declare `credential_types: ['session']` and answer to
214
+ * `is_credential_gated_auth` instead.
202
215
  */
203
216
  export declare const is_plain_authenticated_auth: (auth: RouteAuth) => boolean;
204
217
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"auth_shape.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/auth_shape.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,WAAW,6DAGtB,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEtD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,OAAO,KAAG,MAAM,GAAG,SAGtD,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,aAAa;;;;EAA2C,CAAC;AACtE,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAE1D;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;IAMpB;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;;kBAyCF,CAAC;AACJ,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC;AAUlD;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,MAAM,SAAS,KAAG,OACA,CAAC;AAElD;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,GAAI,MAAM,SAAS,KAAG,OAAgC,CAAC;AAE/E;;;;GAIG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,SAAS,KAAG,OAAkC,CAAC;AAEnF,wEAAwE;AACxE,eAAO,MAAM,YAAY,GAAI,MAAM,SAAS,KAAG,OAA+B,CAAC;AAE/E,8FAA8F;AAC9F,eAAO,MAAM,wBAAwB,GAAI,MAAM,SAAS,KAAG,OAC3B,CAAC;AAEjC;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,MAAM,SAAS,KAAG,OACQ,CAAC;AAE1D;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,GAAI,MAAM,SAAS,KAAG,OACwB,CAAC;AAYvF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,4BAA4B,GAAI,QAAQ,CAAC,CAAC,OAAO,KAAG,OAIhE,CAAC;AAEF;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC3B,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,sCAAsC,GAClD,MAAM,SAAS,EACf,OAAO,WAAW,EAClB,SAAS,MAAM,KACb,IAmBF,CAAC"}
1
+ {"version":3,"file":"auth_shape.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/auth_shape.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,WAAW,6DAGtB,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEtD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,OAAO,KAAG,MAAM,GAAG,SAGtD,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,aAAa;;;;EAA2C,CAAC;AACtE,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAE1D;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;IAMpB;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;;kBAyCF,CAAC;AACJ,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC;AAUlD;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,MAAM,SAAS,KAAG,OACA,CAAC;AAElD;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,GAAI,MAAM,SAAS,KAAG,OAAgC,CAAC;AAE/E;;;;GAIG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,SAAS,KAAG,OAAkC,CAAC;AAEnF,wEAAwE;AACxE,eAAO,MAAM,YAAY,GAAI,MAAM,SAAS,KAAG,OAA+B,CAAC;AAE/E,8FAA8F;AAC9F,eAAO,MAAM,wBAAwB,GAAI,MAAM,SAAS,KAAG,OAC3B,CAAC;AAEjC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,cAAc,GAAI,MAAM,SAAS,KAAG,OACQ,CAAC;AAE1D;;;;;;;;;;GAUG;AACH,eAAO,MAAM,2BAA2B,GAAI,MAAM,SAAS,KAAG,OACwB,CAAC;AAYvF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,4BAA4B,GAAI,QAAQ,CAAC,CAAC,OAAO,KAAG,OAIhE,CAAC;AAEF;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC3B,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,sCAAsC,GAClD,MAAM,SAAS,EACf,OAAO,WAAW,EAClB,SAAS,MAAM,KACb,IAmBF,CAAC"}
@@ -224,16 +224,29 @@ export const is_role_auth = (auth) => !!auth.roles?.length;
224
224
  /** True iff the route declares any credential-type gate (`auth.credential_types?.length`). */
225
225
  export const is_credential_gated_auth = (auth) => !!auth.credential_types?.length;
226
226
  /**
227
- * True iff the route is the keeper bucket — credential gate restricted
228
- * to `daemon_token`. Keeper is the only credential gate today; if more
229
- * land, this filter widens. Knows the `'daemon_token'` literal directly
230
- * (the keeper composition is fuz_app's only registered credential gate).
227
+ * True iff the route is the keeper bucket — a credential gate admitting
228
+ * `daemon_token`. Knows the literal directly, because keeper is a named
229
+ * authority level rather than one channel among many: it is the ceiling
230
+ * sessions and api tokens cannot reach.
231
+ *
232
+ * Narrower than `is_credential_gated_auth`, which is true of every channel
233
+ * gate — including the session-only gates pointing the other way (the
234
+ * credential-minting actions, `POST /logout` / `POST /password`, the audit
235
+ * SSE stream). Reach for the general predicate when the question is "does a
236
+ * channel gate answer here"; reach for this one only when the question is
237
+ * about keeper specifically.
231
238
  */
232
239
  export const is_keeper_auth = (auth) => auth.credential_types?.includes('daemon_token') ?? false;
233
240
  /**
234
241
  * True iff the route is plain authenticated — `account === 'required'`
235
- * with no role gate and no credential gate. Account-grain authenticated
236
- * routes (logout, password change, account self-service) fall here.
242
+ * with no role gate and no credential gate: any credential the auth
243
+ * middleware resolved gets in.
244
+ *
245
+ * A channel gate takes a route out of this bucket, which is why the
246
+ * account-grain routes one might expect here are not — `POST /logout`,
247
+ * `POST /password`, and the `account_*` credential-lifecycle actions all
248
+ * declare `credential_types: ['session']` and answer to
249
+ * `is_credential_gated_auth` instead.
237
250
  */
238
251
  export const is_plain_authenticated_auth = (auth) => auth.account === 'required' && !is_role_auth(auth) && !is_credential_gated_auth(auth);
239
252
  // --- Registry-time invariant 2 enforcement ---
@@ -61,9 +61,4 @@ export declare const to_jsonrpc_envelope_id: (frame: unknown) => JsonrpcRequestI
61
61
  * Returns `undefined` for null/undefined, wraps primitives in `{value}`.
62
62
  */
63
63
  export declare const to_jsonrpc_params: (input: unknown) => Record<string, any> | undefined;
64
- /**
65
- * Normalizes output to JSON-RPC result format.
66
- * Returns empty object for null/undefined, wraps primitives in `{value}`.
67
- */
68
- export declare const to_jsonrpc_result: (output: unknown) => Record<string, any>;
69
64
  //# sourceMappingURL=jsonrpc_helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"jsonrpc_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/jsonrpc_helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,EACN,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,yBAAyB,EAC9B,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,cAAc,EAEnB,eAAe,EACf,MAAM,cAAc,CAAC;AAKtB,0CAA0C;AAC1C,eAAO,MAAM,sBAAsB,GAClC,QAAQ,aAAa,EACrB,QAAQ,oBAAoB,GAAG,SAAS,EACxC,IAAI,gBAAgB,KAClB,cAUF,CAAC;AAEF,mDAAmD;AACnD,eAAO,MAAM,uBAAuB,GACnC,IAAI,gBAAgB,EACpB,QAAQ,aAAa,KACnB,eAID,CAAC;AAEH,6EAA6E;AAC7E,eAAO,MAAM,2BAA2B,GACvC,QAAQ,aAAa,EACrB,QAAQ,yBAAyB,GAAG,SAAS,KAC3C,mBASF,CAAC;AAEF,iDAAiD;AACjD,eAAO,MAAM,6BAA6B,GACzC,IAAI,oBAAoB,CAAC,IAAI,CAAC,EAC9B,OAAO,oBAAoB,CAAC,OAAO,CAAC,KAClC,oBAID,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,yCAAyC,GACrD,IAAI,gBAAgB,GAAG,IAAI,EAC3B,OAAO,OAAO,KACZ,oBAyBF,CAAC;AAIF,kFAAkF;AAClF,eAAO,MAAM,qBAAqB,GAAI,IAAI,OAAO,KAAG,EAAE,IAAI,gBAGzD,CAAC;AAEF,qEAAqE;AACrE,eAAO,MAAM,iBAAiB,GAC7B,SAAS,OAAO,KACd,OAAO,IAAI;IAAE,OAAO,EAAE,OAAO,eAAe,CAAA;CAIF,CAAC;AAE9C,sEAAsE;AACtE,eAAO,MAAM,kBAAkB,GAC9B,SAAS,OAAO,KACd,OAAO,IAAI,cAAc,GAAG,KAAK,CAAC,cAAc,CAGrB,CAAC;AAE/B,iEAAiE;AACjE,eAAO,MAAM,kBAAkB,GAAI,SAAS,OAAO,KAAG,OAAO,IAAI,cACI,CAAC;AAEtE,wEAAwE;AACxE,eAAO,MAAM,uBAAuB,GAAI,SAAS,OAAO,KAAG,OAAO,IAAI,mBACE,CAAC;AAEzE,0EAA0E;AAC1E,eAAO,MAAM,mBAAmB,GAAI,SAAS,OAAO,KAAG,OAAO,IAAI,eACG,CAAC;AAEtE,uEAAuE;AACvE,eAAO,MAAM,yBAAyB,GAAI,SAAS,OAAO,KAAG,OAAO,IAAI,oBACJ,CAAC;AAIrE;;;GAGG;AACH,eAAO,MAAM,qBAAqB,GAAI,eAAe,OAAO,KAAG,gBAAgB,GAAG,IAOjF,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,sBAAsB,GAAI,OAAO,OAAO,KAAG,gBAAgB,GAAG,IACX,CAAC;AAEjE;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAAI,OAAO,OAAO,KAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAQxE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAAI,QAAQ,OAAO,KAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAQrE,CAAC"}
1
+ {"version":3,"file":"jsonrpc_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/jsonrpc_helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,EACN,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,yBAAyB,EAC9B,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,cAAc,EAEnB,eAAe,EACf,MAAM,cAAc,CAAC;AAKtB,0CAA0C;AAC1C,eAAO,MAAM,sBAAsB,GAClC,QAAQ,aAAa,EACrB,QAAQ,oBAAoB,GAAG,SAAS,EACxC,IAAI,gBAAgB,KAClB,cAUF,CAAC;AAEF,mDAAmD;AACnD,eAAO,MAAM,uBAAuB,GACnC,IAAI,gBAAgB,EACpB,QAAQ,aAAa,KACnB,eAID,CAAC;AAEH,6EAA6E;AAC7E,eAAO,MAAM,2BAA2B,GACvC,QAAQ,aAAa,EACrB,QAAQ,yBAAyB,GAAG,SAAS,KAC3C,mBASF,CAAC;AAEF,iDAAiD;AACjD,eAAO,MAAM,6BAA6B,GACzC,IAAI,oBAAoB,CAAC,IAAI,CAAC,EAC9B,OAAO,oBAAoB,CAAC,OAAO,CAAC,KAClC,oBAID,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,yCAAyC,GACrD,IAAI,gBAAgB,GAAG,IAAI,EAC3B,OAAO,OAAO,KACZ,oBAyBF,CAAC;AAIF,kFAAkF;AAClF,eAAO,MAAM,qBAAqB,GAAI,IAAI,OAAO,KAAG,EAAE,IAAI,gBAGzD,CAAC;AAEF,qEAAqE;AACrE,eAAO,MAAM,iBAAiB,GAC7B,SAAS,OAAO,KACd,OAAO,IAAI;IAAE,OAAO,EAAE,OAAO,eAAe,CAAA;CAIF,CAAC;AAE9C,sEAAsE;AACtE,eAAO,MAAM,kBAAkB,GAC9B,SAAS,OAAO,KACd,OAAO,IAAI,cAAc,GAAG,KAAK,CAAC,cAAc,CAGrB,CAAC;AAE/B,iEAAiE;AACjE,eAAO,MAAM,kBAAkB,GAAI,SAAS,OAAO,KAAG,OAAO,IAAI,cACI,CAAC;AAEtE,wEAAwE;AACxE,eAAO,MAAM,uBAAuB,GAAI,SAAS,OAAO,KAAG,OAAO,IAAI,mBACE,CAAC;AAEzE,0EAA0E;AAC1E,eAAO,MAAM,mBAAmB,GAAI,SAAS,OAAO,KAAG,OAAO,IAAI,eACG,CAAC;AAEtE,uEAAuE;AACvE,eAAO,MAAM,yBAAyB,GAAI,SAAS,OAAO,KAAG,OAAO,IAAI,oBACJ,CAAC;AAIrE;;;GAGG;AACH,eAAO,MAAM,qBAAqB,GAAI,eAAe,OAAO,KAAG,gBAAgB,GAAG,IAOjF,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,sBAAsB,GAAI,OAAO,OAAO,KAAG,gBAAgB,GAAG,IACX,CAAC;AAEjE;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAAI,OAAO,OAAO,KAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAQxE,CAAC"}
@@ -136,16 +136,3 @@ export const to_jsonrpc_params = (input) => {
136
136
  }
137
137
  return { value: input };
138
138
  };
139
- /**
140
- * Normalizes output to JSON-RPC result format.
141
- * Returns empty object for null/undefined, wraps primitives in `{value}`.
142
- */
143
- export const to_jsonrpc_result = (output) => {
144
- if (output === null || output === undefined) {
145
- return {};
146
- }
147
- if (typeof output === 'object' && !Array.isArray(output)) {
148
- return output;
149
- }
150
- return { value: output };
151
- };
@@ -27,6 +27,62 @@ export declare const is_null_schema: (schema: z.ZodType) => boolean;
27
27
  * and the dispatcher maps absent params to `undefined` for these specs.
28
28
  */
29
29
  export declare const is_void_schema: (schema: z.ZodType) => boolean;
30
+ /**
31
+ * Normalize the raw `params` of a `z.void()` input: an absent `params`, an
32
+ * empty object, and the `null` a GET `?params=null` parses to are all the
33
+ * no-arg call (`undefined`); anything else passes through for `z.void()` to
34
+ * refuse.
35
+ *
36
+ * JSON-RPC 2.0 lets a parameterless call omit `params`, and an empty by-name
37
+ * structure carries no parameters, so refusing `{}` would only break clients
38
+ * that send it for a parameterless call. Arrays — `[]` included — are not
39
+ * normalized: RPC params are by-name only. The Rust spine's
40
+ * `require_void_params` accepts the same shapes. Receiving ends reach it
41
+ * through `to_input_params`.
42
+ *
43
+ * @param raw_params - the request's `params` as parsed off the wire
44
+ * @returns `undefined` for an empty shape, else `raw_params` unchanged
45
+ */
46
+ export declare const to_void_params: (raw_params: unknown) => unknown;
47
+ /**
48
+ * Normalize the raw `params` of an RPC call for `input` to validate: for a
49
+ * `z.void()` input, `to_void_params`; for any other input, an absent or
50
+ * `null` `params` reads as `{}`, so an all-optional object input accepts a
51
+ * call that omits them. Every receiving end — the server dispatch
52
+ * (`perform_action`) and a peer receiving a request or notification
53
+ * (`ActionDispatcher`) — reads params through this, so a peer is never
54
+ * stricter than the server.
55
+ *
56
+ * @param input - the action's input schema
57
+ * @param raw_params - the call's `params` as parsed off the wire
58
+ * @returns the value to run `input.safeParse` on
59
+ */
60
+ export declare const to_input_params: (input: z.ZodType, raw_params: unknown) => unknown;
61
+ /**
62
+ * `schema.safeParse(value)`, except that keys the schema doesn't declare are
63
+ * dropped rather than refused — the forward-compatible read of a payload a
64
+ * remote authored.
65
+ *
66
+ * Output schemas are strict so the server's DEV output validation catches a
67
+ * handler leaking fields it shouldn't. The receiving side, though, is often
68
+ * older than the remote it talks to — a deploy lands before open tabs reload
69
+ * — and a remote that adds a field is making a compatible change. So when
70
+ * every issue is an unrecognized key, those keys are stripped from a copy of
71
+ * `value` and it's parsed again; any other issue (a wrong type, a missing
72
+ * field, `null` where a value is required) still fails. `value` itself is
73
+ * never mutated. This matches serde's default on the Rust spine, which
74
+ * ignores unknown fields. Keys nested in a `z.union` branch surface as a
75
+ * union issue and aren't stripped; a `z.discriminatedUnion` reports its
76
+ * matched branch's issues directly, so those are.
77
+ *
78
+ * Used for a response's `result` (`ActionEvent`) and for a peer's reply to a
79
+ * server-initiated request (`peer/ping`).
80
+ *
81
+ * @param schema - the declared shape
82
+ * @param value - the remote-authored payload
83
+ * @returns the parse result, with undeclared keys dropped on success
84
+ */
85
+ export declare const safe_parse_dropping_unknown_keys: <T extends z.ZodType>(schema: T, value: unknown) => z.ZodSafeParseResult<z.output<T>>;
30
86
  /**
31
87
  * Check if a schema is a strict object (`z.strictObject()`).
32
88
  *
@@ -1 +1 @@
1
- {"version":3,"file":"schema_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/schema_helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAEN,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,MAAM,oBAAoB,CAAC;AAE5B;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,GAAI,QAAQ,CAAC,CAAC,OAAO,KAAG,OAAsC,CAAC;AAE1F;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,GAAI,QAAQ,CAAC,CAAC,OAAO,KAAG,OAAsC,CAAC;AAE1F;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GAAI,QAAQ,CAAC,CAAC,OAAO,KAAG,OACe,CAAC;AAE5E;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,QAAQ,CAAC,CAAC,OAAO,KAAG,OAQrD,CAAC;AAoBF;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,GAAI,SAAS,MAAM,EAAE,YAAY,MAAM,KAAG,OAQxE,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB,GAC/B,MAAM;IACL,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC;IACrB,KAAK,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC;IACpB,UAAU,CAAC,EAAE,YAAY,CAAC;IAC1B,MAAM,CAAC,EAAE,iBAAiB,CAAC;CAC3B,EACD,oBAAoB,iBAAiB,GAAG,IAAI,KAC1C,iBAAiB,GAAG,IAUtB,CAAC"}
1
+ {"version":3,"file":"schema_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/schema_helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAEN,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,MAAM,oBAAoB,CAAC;AAE5B;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,GAAI,QAAQ,CAAC,CAAC,OAAO,KAAG,OAAsC,CAAC;AAE1F;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,GAAI,QAAQ,CAAC,CAAC,OAAO,KAAG,OAAsC,CAAC;AAE1F;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,cAAc,GAAI,YAAY,OAAO,KAAG,OAUpD,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,eAAe,GAAI,OAAO,CAAC,CAAC,OAAO,EAAE,YAAY,OAAO,KAAG,OACA,CAAC;AAEzE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,gCAAgC,GAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EACnE,QAAQ,CAAC,EACT,OAAO,OAAO,KACZ,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAclC,CAAC;AAWF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GAAI,QAAQ,CAAC,CAAC,OAAO,KAAG,OACe,CAAC;AAE5E;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,QAAQ,CAAC,CAAC,OAAO,KAAG,OAQrD,CAAC;AAoBF;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,GAAI,SAAS,MAAM,EAAE,YAAY,MAAM,KAAG,OAQxE,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB,GAC/B,MAAM;IACL,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC;IACrB,KAAK,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC;IACpB,UAAU,CAAC,EAAE,YAAY,CAAC;IAC1B,MAAM,CAAC,EAAE,iBAAiB,CAAC;CAC3B,EACD,oBAAoB,iBAAiB,GAAG,IAAI,KAC1C,iBAAiB,GAAG,IAUtB,CAAC"}
@@ -26,6 +26,97 @@ export const is_null_schema = (schema) => schema instanceof z.ZodNull;
26
26
  * and the dispatcher maps absent params to `undefined` for these specs.
27
27
  */
28
28
  export const is_void_schema = (schema) => schema instanceof z.ZodVoid;
29
+ /**
30
+ * Normalize the raw `params` of a `z.void()` input: an absent `params`, an
31
+ * empty object, and the `null` a GET `?params=null` parses to are all the
32
+ * no-arg call (`undefined`); anything else passes through for `z.void()` to
33
+ * refuse.
34
+ *
35
+ * JSON-RPC 2.0 lets a parameterless call omit `params`, and an empty by-name
36
+ * structure carries no parameters, so refusing `{}` would only break clients
37
+ * that send it for a parameterless call. Arrays — `[]` included — are not
38
+ * normalized: RPC params are by-name only. The Rust spine's
39
+ * `require_void_params` accepts the same shapes. Receiving ends reach it
40
+ * through `to_input_params`.
41
+ *
42
+ * @param raw_params - the request's `params` as parsed off the wire
43
+ * @returns `undefined` for an empty shape, else `raw_params` unchanged
44
+ */
45
+ export const to_void_params = (raw_params) => {
46
+ if (raw_params === undefined || raw_params === null)
47
+ return undefined;
48
+ if (typeof raw_params === 'object' &&
49
+ !Array.isArray(raw_params) &&
50
+ Object.keys(raw_params).length === 0) {
51
+ return undefined;
52
+ }
53
+ return raw_params;
54
+ };
55
+ /**
56
+ * Normalize the raw `params` of an RPC call for `input` to validate: for a
57
+ * `z.void()` input, `to_void_params`; for any other input, an absent or
58
+ * `null` `params` reads as `{}`, so an all-optional object input accepts a
59
+ * call that omits them. Every receiving end — the server dispatch
60
+ * (`perform_action`) and a peer receiving a request or notification
61
+ * (`ActionDispatcher`) — reads params through this, so a peer is never
62
+ * stricter than the server.
63
+ *
64
+ * @param input - the action's input schema
65
+ * @param raw_params - the call's `params` as parsed off the wire
66
+ * @returns the value to run `input.safeParse` on
67
+ */
68
+ export const to_input_params = (input, raw_params) => is_void_schema(input) ? to_void_params(raw_params) : (raw_params ?? {});
69
+ /**
70
+ * `schema.safeParse(value)`, except that keys the schema doesn't declare are
71
+ * dropped rather than refused — the forward-compatible read of a payload a
72
+ * remote authored.
73
+ *
74
+ * Output schemas are strict so the server's DEV output validation catches a
75
+ * handler leaking fields it shouldn't. The receiving side, though, is often
76
+ * older than the remote it talks to — a deploy lands before open tabs reload
77
+ * — and a remote that adds a field is making a compatible change. So when
78
+ * every issue is an unrecognized key, those keys are stripped from a copy of
79
+ * `value` and it's parsed again; any other issue (a wrong type, a missing
80
+ * field, `null` where a value is required) still fails. `value` itself is
81
+ * never mutated. This matches serde's default on the Rust spine, which
82
+ * ignores unknown fields. Keys nested in a `z.union` branch surface as a
83
+ * union issue and aren't stripped; a `z.discriminatedUnion` reports its
84
+ * matched branch's issues directly, so those are.
85
+ *
86
+ * Used for a response's `result` (`ActionEvent`) and for a peer's reply to a
87
+ * server-initiated request (`peer/ping`).
88
+ *
89
+ * @param schema - the declared shape
90
+ * @param value - the remote-authored payload
91
+ * @returns the parse result, with undeclared keys dropped on success
92
+ */
93
+ export const safe_parse_dropping_unknown_keys = (schema, value) => {
94
+ const parsed = schema.safeParse(value);
95
+ if (parsed.success)
96
+ return parsed;
97
+ const { issues } = parsed.error;
98
+ if (!issues.every((issue) => issue.code === 'unrecognized_keys'))
99
+ return parsed;
100
+ const stripped = structuredClone(value);
101
+ for (const issue of issues) {
102
+ const target = get_at_path(stripped, issue.path);
103
+ if (typeof target !== 'object' || target === null)
104
+ return parsed;
105
+ for (const key of issue.keys) {
106
+ Reflect.deleteProperty(target, key);
107
+ }
108
+ }
109
+ return schema.safeParse(stripped);
110
+ };
111
+ const get_at_path = (value, path) => {
112
+ let current = value;
113
+ for (const segment of path) {
114
+ if (typeof current !== 'object' || current === null)
115
+ return undefined;
116
+ current = current[segment];
117
+ }
118
+ return current;
119
+ };
29
120
  /**
30
121
  * Check if a schema is a strict object (`z.strictObject()`).
31
122
  *
@@ -27,6 +27,17 @@ export declare const filter_role_routes: (surface: AppSurface) => Array<AppSurfa
27
27
  export declare const filter_authenticated_routes: (surface: AppSurface) => Array<AppSurfaceRoute>;
28
28
  /** Filter routes that require keeper credentials (`daemon_token`). */
29
29
  export declare const filter_keeper_routes: (surface: AppSurface) => Array<AppSurfaceRoute>;
30
+ /**
31
+ * Filter routes gated to a credential channel (any non-empty
32
+ * `auth.credential_types`), whichever channel that is.
33
+ *
34
+ * Superset of `filter_keeper_routes`: keeper is the `daemon_token` gate, and
35
+ * the same axis points the other way on the session-only routes (the
36
+ * credential-minting actions, `POST /logout` / `POST /password`, the audit
37
+ * SSE stream). Adversarial runners need the whole bucket, since every route
38
+ * in it answers `credential_type_required` to a channel it does not admit.
39
+ */
40
+ export declare const filter_credential_gated_routes: (surface: AppSurface) => Array<AppSurfaceRoute>;
30
41
  /** Filter routes whose `auth.roles` includes the named role. */
31
42
  export declare const filter_routes_for_role: (surface: AppSurface, role: string) => Array<AppSurfaceRoute>;
32
43
  /**
@@ -38,11 +49,22 @@ export declare const filter_routes_for_role: (surface: AppSurface, role: string)
38
49
  * - `'role:<name>'` for each role declared on `auth.roles` (multi-role specs
39
50
  * are emitted multiple times; callers that need single-bucket grouping
40
51
  * should pre-collapse)
52
+ * - `'credential:<type>'` for each channel a role-less route's
53
+ * `credential_types` admits — the session-only gates (`POST /logout`,
54
+ * `POST /password`, the `account_*` credential-lifecycle actions), plus any
55
+ * channel a consumer registers
41
56
  * - `'authenticated'` for `account === 'required'` without role / credential gate
42
57
  * - `'optional'` when either axis is `'optional'` and no other bucket fits
43
58
  * - `'other'` as a last-resort bucket for shapes that don't match above
59
+ *
60
+ * Keeper is tested before the role bucket and the general credential bucket
61
+ * after it, which is not an inconsistency: keeper is an authority *level* — a
62
+ * ceiling no session or api token reaches — so it names the route, while a
63
+ * session gate is a *channel* restriction layered over whatever authority the
64
+ * route already declares. So the audit SSE stream, gated to the session
65
+ * channel and to the admin role, buckets as `role:admin`.
44
66
  */
45
- export type RouteAuthCategory = 'none' | 'authenticated' | 'optional' | 'keeper' | `role:${string}` | 'other';
67
+ export type RouteAuthCategory = 'none' | 'authenticated' | 'optional' | 'keeper' | `role:${string}` | `credential:${string}` | 'other';
46
68
  /**
47
69
  * Group routes by auth category (see `RouteAuthCategory`). Multi-role specs
48
70
  * appear under each of their role buckets.
@@ -65,16 +87,19 @@ export declare const format_route_key: (route: AppSurfaceRoute) => string;
65
87
  /**
66
88
  * Summarize route auth distribution across the surface.
67
89
  *
68
- * Categorical view over the flat auth record. Multi-role specs
69
- * contribute one count per role they admit.
90
+ * Categorical view over the flat auth record, bucketing exactly as
91
+ * `routes_by_auth_type`. Multi-role and multi-channel specs contribute one
92
+ * count per role / channel they admit.
70
93
  *
71
- * @returns counts by auth category, with role counts broken out by role name
94
+ * @returns counts by auth category, with role and channel counts broken out
95
+ * by name
72
96
  */
73
97
  export declare const surface_auth_summary: (surface: AppSurface) => {
74
98
  none: number;
75
99
  authenticated: number;
76
100
  optional: number;
77
101
  role: Map<string, number>;
102
+ credential: Map<string, number>;
78
103
  keeper: number;
79
104
  other: number;
80
105
  };
@@ -1 +1 @@
1
- {"version":3,"file":"surface_query.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/surface_query.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAQhE,6DAA6D;AAC7D,eAAO,MAAM,uBAAuB,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC7B,CAAC;AAEvD,2EAA2E;AAC3E,eAAO,MAAM,oBAAoB,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC3B,CAAC;AAEtD,0EAA0E;AAC1E,eAAO,MAAM,kBAAkB,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC3B,CAAC;AAEpD;;;GAGG;AACH,eAAO,MAAM,2BAA2B,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CACrB,CAAC;AAEnE,sEAAsE;AACtE,eAAO,MAAM,oBAAoB,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC3B,CAAC;AAEtD,gEAAgE;AAChE,eAAO,MAAM,sBAAsB,GAAI,SAAS,UAAU,EAAE,MAAM,MAAM,KAAG,KAAK,CAAC,eAAe,CAC5B,CAAC;AAErE;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,iBAAiB,GAC5B,MAAM,GAAG,eAAe,GAAG,UAAU,GAAG,QAAQ,GAAG,QAAQ,MAAM,EAAE,GAAG,OAAO,CAAC;AAE/E;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAAI,SAAS,UAAU,KAAG,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,eAAe,CAAC,CAmC3F,CAAC;AAEF,qDAAqD;AACrD,eAAO,MAAM,uBAAuB,GACnC,SAAS,UAAU,EACnB,QAAQ,MAAM,KACZ,KAAK,CAAC,eAAe,CAA4D,CAAC;AAErF,uDAAuD;AACvD,eAAO,MAAM,wBAAwB,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC9B,CAAC;AAEvD,wDAAwD;AACxD,eAAO,MAAM,yBAAyB,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC9B,CAAC;AAExD,uDAAuD;AACvD,eAAO,MAAM,wBAAwB,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC9B,CAAC;AAEvD,mEAAmE;AACnE,eAAO,MAAM,sBAAsB,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CACtC,CAAC;AAE7C,gDAAgD;AAChD,eAAO,MAAM,0BAA0B,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC9B,CAAC;AAEzD,iEAAiE;AACjE,eAAO,MAAM,gBAAgB,GAAI,OAAO,eAAe,KAAG,MAAyC,CAAC;AAEpG;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,GAChC,SAAS,UAAU,KACjB;IACF,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CAqCd,CAAC"}
1
+ {"version":3,"file":"surface_query.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/surface_query.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAShE,6DAA6D;AAC7D,eAAO,MAAM,uBAAuB,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC7B,CAAC;AAEvD,2EAA2E;AAC3E,eAAO,MAAM,oBAAoB,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC3B,CAAC;AAEtD,0EAA0E;AAC1E,eAAO,MAAM,kBAAkB,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC3B,CAAC;AAEpD;;;GAGG;AACH,eAAO,MAAM,2BAA2B,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CACrB,CAAC;AAEnE,sEAAsE;AACtE,eAAO,MAAM,oBAAoB,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC3B,CAAC;AAEtD;;;;;;;;;GASG;AACH,eAAO,MAAM,8BAA8B,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC3B,CAAC;AAEhE,gEAAgE;AAChE,eAAO,MAAM,sBAAsB,GAAI,SAAS,UAAU,EAAE,MAAM,MAAM,KAAG,KAAK,CAAC,eAAe,CAC5B,CAAC;AAErE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,MAAM,iBAAiB,GAC1B,MAAM,GACN,eAAe,GACf,UAAU,GACV,QAAQ,GACR,QAAQ,MAAM,EAAE,GAChB,cAAc,MAAM,EAAE,GACtB,OAAO,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAAI,SAAS,UAAU,KAAG,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,eAAe,CAAC,CAwC3F,CAAC;AAEF,qDAAqD;AACrD,eAAO,MAAM,uBAAuB,GACnC,SAAS,UAAU,EACnB,QAAQ,MAAM,KACZ,KAAK,CAAC,eAAe,CAA4D,CAAC;AAErF,uDAAuD;AACvD,eAAO,MAAM,wBAAwB,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC9B,CAAC;AAEvD,wDAAwD;AACxD,eAAO,MAAM,yBAAyB,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC9B,CAAC;AAExD,uDAAuD;AACvD,eAAO,MAAM,wBAAwB,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC9B,CAAC;AAEvD,mEAAmE;AACnE,eAAO,MAAM,sBAAsB,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CACtC,CAAC;AAE7C,gDAAgD;AAChD,eAAO,MAAM,0BAA0B,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC9B,CAAC;AAEzD,iEAAiE;AACjE,eAAO,MAAM,gBAAgB,GAAI,OAAO,eAAe,KAAG,MAAyC,CAAC;AAEpG;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,GAChC,SAAS,UAAU,KACjB;IACF,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1B,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CA4Cd,CAAC"}
@@ -13,7 +13,7 @@
13
13
  *
14
14
  * @module
15
15
  */
16
- import { is_keeper_auth, is_plain_authenticated_auth, is_public_auth, is_role_auth } from './auth_shape.js';
16
+ import { is_credential_gated_auth, is_keeper_auth, is_plain_authenticated_auth, is_public_auth, is_role_auth } from './auth_shape.js';
17
17
  /** Filter routes that require any form of authentication. */
18
18
  export const filter_protected_routes = (surface) => surface.routes.filter((r) => !is_public_auth(r.auth));
19
19
  /** Filter routes that are publicly accessible (no auth surface at all). */
@@ -27,6 +27,17 @@ export const filter_role_routes = (surface) => surface.routes.filter((r) => is_r
27
27
  export const filter_authenticated_routes = (surface) => surface.routes.filter((r) => is_plain_authenticated_auth(r.auth));
28
28
  /** Filter routes that require keeper credentials (`daemon_token`). */
29
29
  export const filter_keeper_routes = (surface) => surface.routes.filter((r) => is_keeper_auth(r.auth));
30
+ /**
31
+ * Filter routes gated to a credential channel (any non-empty
32
+ * `auth.credential_types`), whichever channel that is.
33
+ *
34
+ * Superset of `filter_keeper_routes`: keeper is the `daemon_token` gate, and
35
+ * the same axis points the other way on the session-only routes (the
36
+ * credential-minting actions, `POST /logout` / `POST /password`, the audit
37
+ * SSE stream). Adversarial runners need the whole bucket, since every route
38
+ * in it answers `credential_type_required` to a channel it does not admit.
39
+ */
40
+ export const filter_credential_gated_routes = (surface) => surface.routes.filter((r) => is_credential_gated_auth(r.auth));
30
41
  /** Filter routes whose `auth.roles` includes the named role. */
31
42
  export const filter_routes_for_role = (surface, role) => surface.routes.filter((r) => r.auth.roles?.includes(role) ?? false);
32
43
  /**
@@ -58,6 +69,11 @@ export const routes_by_auth_type = (surface) => {
58
69
  push(`role:${role}`, r);
59
70
  continue;
60
71
  }
72
+ if (is_credential_gated_auth(auth)) {
73
+ for (const credential_type of auth.credential_types)
74
+ push(`credential:${credential_type}`, r);
75
+ continue;
76
+ }
61
77
  if (is_plain_authenticated_auth(auth)) {
62
78
  push('authenticated', r);
63
79
  continue;
@@ -87,16 +103,19 @@ export const format_route_key = (route) => `${route.method} ${route.path}`;
87
103
  /**
88
104
  * Summarize route auth distribution across the surface.
89
105
  *
90
- * Categorical view over the flat auth record. Multi-role specs
91
- * contribute one count per role they admit.
106
+ * Categorical view over the flat auth record, bucketing exactly as
107
+ * `routes_by_auth_type`. Multi-role and multi-channel specs contribute one
108
+ * count per role / channel they admit.
92
109
  *
93
- * @returns counts by auth category, with role counts broken out by role name
110
+ * @returns counts by auth category, with role and channel counts broken out
111
+ * by name
94
112
  */
95
113
  export const surface_auth_summary = (surface) => {
96
114
  let none = 0;
97
115
  let authenticated = 0;
98
116
  let optional = 0;
99
117
  const role = new Map();
118
+ const credential = new Map();
100
119
  let keeper = 0;
101
120
  let other = 0;
102
121
  for (const r of surface.routes) {
@@ -115,6 +134,12 @@ export const surface_auth_summary = (surface) => {
115
134
  }
116
135
  continue;
117
136
  }
137
+ if (is_credential_gated_auth(auth)) {
138
+ for (const credential_type of auth.credential_types) {
139
+ credential.set(credential_type, (credential.get(credential_type) ?? 0) + 1);
140
+ }
141
+ continue;
142
+ }
118
143
  if (is_plain_authenticated_auth(auth)) {
119
144
  authenticated++;
120
145
  continue;
@@ -125,5 +150,5 @@ export const surface_auth_summary = (surface) => {
125
150
  }
126
151
  other++;
127
152
  }
128
- return { none, authenticated, optional, role, keeper, other };
153
+ return { none, authenticated, optional, role, credential, keeper, other };
129
154
  };
@@ -31,9 +31,15 @@ export declare const AUDIT_LOG_CHANNEL = "audit_log";
31
31
  * `session_revoke` closes only the stream tied to the specific revoked session
32
32
  * (matched by the blake3 session hash in `event.metadata.session_id`) — closing
33
33
  * all of a user's streams for a single-session revoke would be over-aggressive.
34
- * The single `token_revoke` the WS half handles is omitted: an SSE stream is
35
- * opened under a cookie session, never an API token, so no stream is keyed by a
36
- * single token id.
34
+ * The single `token_revoke` the WS half handles is omitted, and what makes that
35
+ * correct is a gate rather than an assumption: the audit route declares
36
+ * `credential_types: ['session']` (`auth/audit_log_route_schema.ts`), so a
37
+ * bearer is refused at the channel and no stream is ever keyed by a single
38
+ * token id. **A consumer that widens that gate must key its subscribers by
39
+ * api-token id and add `token_revoke` here** — otherwise a revoked token keeps
40
+ * receiving audit rows for the life of the connection. The Rust twin enforces
41
+ * the same pairing structurally, via the `RevocationScope` column on
42
+ * `AUDIT_EVENT_SPECS`.
37
43
  */
38
44
  export declare const disconnect_event_types: ReadonlySet<string>;
39
45
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"sse_auth_guard.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/realtime/sse_auth_guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,EAGN,KAAK,aAAa,EAClB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACrF,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAEtE,2DAA2D;AAC3D,eAAO,MAAM,iBAAiB,cAAc,CAAC;AAE7C;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,sBAAsB,EAAE,WAAW,CAAC,MAAM,CAOrD,CAAC;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,qBAAqB,GAAI,CAAC,EACtC,UAAU,kBAAkB,CAAC,CAAC,CAAC,EAC/B,eAAe,MAAM,GAAG,IAAI,EAC5B,KAAK,MAAM,KACT,CAAC,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CA6CjC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC3B,8FAA8F;IAC9F,SAAS,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB,KAAK,MAAM,IAAI,CAAC;IAC1F,kFAAkF;IAClF,GAAG,EAAE,MAAM,CAAC;IACZ,yJAAyJ;IACzJ,cAAc,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC/C,yEAAyE;IACzE,QAAQ,EAAE,kBAAkB,CAAC,eAAe,CAAC,CAAC;CAC9C;AAED;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,EAAE,KAAK,CAAC,SAAS,CAOlD,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,2BAA2B,KAAK,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,eAAO,MAAM,oBAAoB,GAAI,SAAS;IAC7C,mEAAmE;IACnE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,KAAG,WAgBH,CAAC"}
1
+ {"version":3,"file":"sse_auth_guard.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/realtime/sse_auth_guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,EAGN,KAAK,aAAa,EAClB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACrF,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAEtE,2DAA2D;AAC3D,eAAO,MAAM,iBAAiB,cAAc,CAAC;AAE7C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,sBAAsB,EAAE,WAAW,CAAC,MAAM,CAOrD,CAAC;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,qBAAqB,GAAI,CAAC,EACtC,UAAU,kBAAkB,CAAC,CAAC,CAAC,EAC/B,eAAe,MAAM,GAAG,IAAI,EAC5B,KAAK,MAAM,KACT,CAAC,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CA6CjC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC3B,8FAA8F;IAC9F,SAAS,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB,KAAK,MAAM,IAAI,CAAC;IAC1F,kFAAkF;IAClF,GAAG,EAAE,MAAM,CAAC;IACZ,yJAAyJ;IACzJ,cAAc,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC/C,yEAAyE;IACzE,QAAQ,EAAE,kBAAkB,CAAC,eAAe,CAAC,CAAC;CAC9C;AAED;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,EAAE,KAAK,CAAC,SAAS,CAOlD,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,2BAA2B,KAAK,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,eAAO,MAAM,oBAAoB,GAAI,SAAS;IAC7C,mEAAmE;IACnE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,KAAG,WAgBH,CAAC"}