@fuzdev/fuz_app 0.62.0 → 0.64.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/actions/CLAUDE.md +139 -24
- package/dist/actions/action_rpc.d.ts +10 -0
- package/dist/actions/action_rpc.d.ts.map +1 -1
- package/dist/actions/action_rpc.js +1 -1
- package/dist/actions/action_spec.d.ts +1 -1
- package/dist/actions/action_spec.js +1 -1
- package/dist/actions/connection_closer.d.ts +68 -0
- package/dist/actions/connection_closer.d.ts.map +1 -0
- package/dist/actions/connection_closer.js +41 -0
- package/dist/actions/perform_action.d.ts.map +1 -1
- package/dist/actions/perform_action.js +1 -0
- package/dist/actions/register_action_ws.d.ts.map +1 -1
- package/dist/actions/register_action_ws.js +23 -2
- package/dist/actions/register_ws_endpoint.d.ts +11 -9
- package/dist/actions/register_ws_endpoint.d.ts.map +1 -1
- package/dist/actions/register_ws_endpoint.js +5 -5
- package/dist/actions/transports_ws_auth_guard.d.ts +24 -8
- package/dist/actions/transports_ws_auth_guard.d.ts.map +1 -1
- package/dist/actions/transports_ws_auth_guard.js +23 -7
- package/dist/actions/ws_endpoint_spec.d.ts +119 -0
- package/dist/actions/ws_endpoint_spec.d.ts.map +1 -0
- package/dist/actions/ws_endpoint_spec.js +13 -0
- package/dist/auth/CLAUDE.md +124 -39
- package/dist/auth/account_action_specs.d.ts +7 -1
- package/dist/auth/account_action_specs.d.ts.map +1 -1
- package/dist/auth/account_action_specs.js +11 -4
- package/dist/auth/account_actions.d.ts +13 -0
- package/dist/auth/account_actions.d.ts.map +1 -1
- package/dist/auth/account_actions.js +40 -5
- package/dist/auth/account_routes.d.ts +12 -2
- package/dist/auth/account_routes.d.ts.map +1 -1
- package/dist/auth/account_routes.js +63 -12
- package/dist/auth/account_schema.d.ts +5 -5
- package/dist/auth/account_schema.js +2 -2
- package/dist/auth/actor_lookup_actions.d.ts +1 -1
- package/dist/auth/actor_lookup_actions.js +1 -1
- package/dist/auth/actor_lookup_queries.d.ts +1 -1
- package/dist/auth/actor_lookup_queries.js +1 -1
- package/dist/auth/actor_search_action_specs.d.ts +1 -1
- package/dist/auth/actor_search_action_specs.js +1 -1
- package/dist/auth/actor_search_actions.d.ts +1 -1
- package/dist/auth/actor_search_actions.js +1 -1
- package/dist/auth/actor_search_queries.d.ts +1 -1
- package/dist/auth/actor_search_queries.js +1 -1
- package/dist/auth/admin_action_specs.d.ts +8 -8
- package/dist/auth/admin_actions.d.ts +11 -0
- package/dist/auth/admin_actions.d.ts.map +1 -1
- package/dist/auth/admin_actions.js +25 -0
- package/dist/auth/all_action_spec_registries.d.ts +2 -2
- package/dist/auth/all_action_spec_registries.js +2 -2
- package/dist/auth/audit_emitter.d.ts +56 -12
- package/dist/auth/audit_emitter.d.ts.map +1 -1
- package/dist/auth/audit_emitter.js +38 -12
- package/dist/auth/audit_log_routes.d.ts +1 -1
- package/dist/auth/audit_log_routes.js +1 -1
- package/dist/auth/audit_log_schema.d.ts +30 -3
- package/dist/auth/audit_log_schema.d.ts.map +1 -1
- package/dist/auth/audit_log_schema.js +21 -3
- package/dist/auth/bootstrap_routes.d.ts +1 -1
- package/dist/auth/invite_schema.d.ts +2 -2
- package/dist/auth/request_context.d.ts +1 -1
- package/dist/auth/signup_routes.d.ts +1 -1
- package/dist/auth/standard_rpc_actions.d.ts +1 -0
- package/dist/auth/standard_rpc_actions.d.ts.map +1 -1
- package/dist/auth/standard_rpc_actions.js +1 -0
- package/dist/env/update_env_variable.js +1 -1
- package/dist/http/CLAUDE.md +42 -26
- package/dist/http/ip_canonical.d.ts +99 -0
- package/dist/http/ip_canonical.d.ts.map +1 -0
- package/dist/http/ip_canonical.js +191 -0
- package/dist/http/origin.d.ts +13 -5
- package/dist/http/origin.d.ts.map +1 -1
- package/dist/http/origin.js +13 -31
- package/dist/http/pending_effects.d.ts +1 -1
- package/dist/http/pending_effects.js +1 -1
- package/dist/http/proxy.d.ts +13 -5
- package/dist/http/proxy.d.ts.map +1 -1
- package/dist/http/proxy.js +15 -23
- package/dist/http/surface.d.ts +50 -0
- package/dist/http/surface.d.ts.map +1 -1
- package/dist/http/surface.js +27 -1
- package/dist/primitive_schemas.d.ts +20 -4
- package/dist/primitive_schemas.d.ts.map +1 -1
- package/dist/primitive_schemas.js +25 -4
- package/dist/realtime/sse_auth_guard.d.ts +16 -4
- package/dist/realtime/sse_auth_guard.d.ts.map +1 -1
- package/dist/realtime/sse_auth_guard.js +15 -3
- package/dist/server/app_backend.d.ts +66 -19
- package/dist/server/app_backend.d.ts.map +1 -1
- package/dist/server/app_backend.js +57 -34
- package/dist/server/app_server.d.ts +60 -0
- package/dist/server/app_server.d.ts.map +1 -1
- package/dist/server/app_server.js +95 -2
- package/dist/server/startup.d.ts.map +1 -1
- package/dist/server/startup.js +12 -0
- package/dist/testing/CLAUDE.md +91 -71
- package/dist/testing/admin_integration.d.ts.map +1 -1
- package/dist/testing/admin_integration.js +4 -5
- package/dist/testing/adversarial_headers.d.ts +6 -0
- package/dist/testing/adversarial_headers.d.ts.map +1 -1
- package/dist/testing/adversarial_headers.js +13 -5
- package/dist/testing/app_server.d.ts +33 -32
- package/dist/testing/app_server.d.ts.map +1 -1
- package/dist/testing/app_server.js +4 -13
- package/dist/testing/attack_surface.d.ts +8 -7
- package/dist/testing/attack_surface.d.ts.map +1 -1
- package/dist/testing/attack_surface.js +12 -8
- package/dist/testing/audit_completeness.d.ts.map +1 -1
- package/dist/testing/audit_completeness.js +20 -6
- package/dist/testing/audit_drift_guard.d.ts +116 -0
- package/dist/testing/audit_drift_guard.d.ts.map +1 -0
- package/dist/testing/audit_drift_guard.js +134 -0
- package/dist/testing/connection_closer_helpers.d.ts +44 -0
- package/dist/testing/connection_closer_helpers.d.ts.map +1 -0
- package/dist/testing/connection_closer_helpers.js +48 -0
- package/dist/testing/integration.d.ts.map +1 -1
- package/dist/testing/integration.js +7 -9
- package/dist/testing/rate_limiting.js +4 -4
- package/dist/testing/rpc_helpers.d.ts +2 -1
- package/dist/testing/rpc_helpers.d.ts.map +1 -1
- package/dist/testing/rpc_round_trip.d.ts.map +1 -1
- package/dist/testing/rpc_round_trip.js +6 -8
- package/dist/testing/sse_round_trip.d.ts.map +1 -1
- package/dist/testing/sse_round_trip.js +12 -6
- package/dist/testing/stubs.d.ts +11 -0
- package/dist/testing/stubs.d.ts.map +1 -1
- package/dist/testing/stubs.js +4 -0
- package/dist/testing/surface_invariants.d.ts +66 -1
- package/dist/testing/surface_invariants.d.ts.map +1 -1
- package/dist/testing/surface_invariants.js +103 -1
- package/dist/ui/CLAUDE.md +13 -18
- package/dist/ui/SurfaceExplorer.svelte +161 -2
- package/dist/ui/SurfaceExplorer.svelte.d.ts.map +1 -1
- package/dist/ui/keyed_async_slot.svelte.d.ts +1 -1
- package/dist/ui/keyed_async_slot.svelte.js +1 -1
- package/package.json +1 -1
|
@@ -1,12 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* WebSocket auth guard — bridges audit events to `BackendWebsocketTransport`.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* **Why this exists.** `register_action_ws` captures `account_id` and
|
|
5
|
+
* `credential_type` at upgrade time and reuses them for every message.
|
|
6
|
+
* `perform_action`'s per-message authorization phase reloads role_grants
|
|
7
|
+
* from the DB, but session and token VALIDITY are not re-queried — that
|
|
8
|
+
* trade-off keeps chatty WS connections fast. The cost: nothing in the
|
|
9
|
+
* dispatch path notices when a session is revoked or a token is rotated.
|
|
10
|
+
* This guard is the enforcement mechanism — it listens on the audit
|
|
11
|
+
* chain and closes affected sockets when revocation events fire, so
|
|
12
|
+
* revocation actually takes effect on existing connections. Without it,
|
|
13
|
+
* `session_revoke` / `token_revoke` are no-ops for open WS connections.
|
|
7
14
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
15
|
+
* Mirror of `realtime/sse_auth_guard.ts` for the backend WebSocket
|
|
16
|
+
* transport. Dispatches audit events to the right `close_sockets_for_*`
|
|
17
|
+
* method so consumers do not re-implement the switch themselves.
|
|
18
|
+
*
|
|
19
|
+
* For standard WS endpoints mounted via `AppServerOptions.ws_endpoints`,
|
|
20
|
+
* `create_app_server` composes the guard automatically per
|
|
21
|
+
* `WsEndpointSpec.auth_guard`. For custom wiring, append the handler
|
|
22
|
+
* inside the consumer's `audit_factory` body (or via
|
|
23
|
+
* `audit.on_event_chain.push(...)` post-assembly).
|
|
10
24
|
*
|
|
11
25
|
* @module
|
|
12
26
|
*/
|
|
@@ -14,7 +28,7 @@ import type { Logger } from '@fuzdev/fuz_util/log.js';
|
|
|
14
28
|
import type { AuditLogEvent } from '../auth/audit_log_schema.js';
|
|
15
29
|
import type { BackendWebsocketTransport } from './transports_ws_backend.js';
|
|
16
30
|
/**
|
|
17
|
-
* Audit-event callback shape — the function `
|
|
31
|
+
* Audit-event callback shape — the function `CreateAuditEmitterOptions.on_audit_event`
|
|
18
32
|
* accepts and that the helpers in this module return.
|
|
19
33
|
*
|
|
20
34
|
* Exported so consumers composing multiple handlers (typically
|
|
@@ -46,8 +60,10 @@ export declare const ws_disconnect_event_types: ReadonlySet<string>;
|
|
|
46
60
|
* user close another user's socket by guessing a session hash or token id.
|
|
47
61
|
*
|
|
48
62
|
* @param log - logger for disconnect events (info level on non-zero closures)
|
|
49
|
-
* @returns an `on_audit_event` callback suitable for `
|
|
50
|
-
*
|
|
63
|
+
* @returns an `on_audit_event` callback suitable for `create_audit_emitter`'s
|
|
64
|
+
* `on_audit_event` slot, or for appending onto
|
|
65
|
+
* `audit.on_event_chain` post-assembly. The returned callback mutates
|
|
66
|
+
* `transport` (closing matching sockets via
|
|
51
67
|
* `close_sockets_for_session` / `_token` / `_account`) on every relevant event.
|
|
52
68
|
*/
|
|
53
69
|
export declare const create_ws_auth_guard: (transport: BackendWebsocketTransport, log: Logger) => AuditEventHandler;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transports_ws_auth_guard.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/transports_ws_auth_guard.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"transports_ws_auth_guard.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/transports_ws_auth_guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAEpD,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,6BAA6B,CAAC;AAC/D,OAAO,KAAK,EAAC,yBAAyB,EAAC,MAAM,4BAA4B,CAAC;AAE1E;;;;;;;;GAQG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;AAE/D;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,yBAAyB,EAAE,WAAW,CAAC,MAAM,CAMxD,CAAC;AAEH;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB,GAChC,WAAW,yBAAyB,EACpC,KAAK,MAAM,KACT,iBA6CF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,uBAAuB,GACnC,WAAW,yBAAyB,EACpC,KAAK,MAAM,KACT,iBAaF,CAAC"}
|
|
@@ -1,12 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* WebSocket auth guard — bridges audit events to `BackendWebsocketTransport`.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* **Why this exists.** `register_action_ws` captures `account_id` and
|
|
5
|
+
* `credential_type` at upgrade time and reuses them for every message.
|
|
6
|
+
* `perform_action`'s per-message authorization phase reloads role_grants
|
|
7
|
+
* from the DB, but session and token VALIDITY are not re-queried — that
|
|
8
|
+
* trade-off keeps chatty WS connections fast. The cost: nothing in the
|
|
9
|
+
* dispatch path notices when a session is revoked or a token is rotated.
|
|
10
|
+
* This guard is the enforcement mechanism — it listens on the audit
|
|
11
|
+
* chain and closes affected sockets when revocation events fire, so
|
|
12
|
+
* revocation actually takes effect on existing connections. Without it,
|
|
13
|
+
* `session_revoke` / `token_revoke` are no-ops for open WS connections.
|
|
7
14
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
15
|
+
* Mirror of `realtime/sse_auth_guard.ts` for the backend WebSocket
|
|
16
|
+
* transport. Dispatches audit events to the right `close_sockets_for_*`
|
|
17
|
+
* method so consumers do not re-implement the switch themselves.
|
|
18
|
+
*
|
|
19
|
+
* For standard WS endpoints mounted via `AppServerOptions.ws_endpoints`,
|
|
20
|
+
* `create_app_server` composes the guard automatically per
|
|
21
|
+
* `WsEndpointSpec.auth_guard`. For custom wiring, append the handler
|
|
22
|
+
* inside the consumer's `audit_factory` body (or via
|
|
23
|
+
* `audit.on_event_chain.push(...)` post-assembly).
|
|
10
24
|
*
|
|
11
25
|
* @module
|
|
12
26
|
*/
|
|
@@ -39,8 +53,10 @@ export const ws_disconnect_event_types = new Set([
|
|
|
39
53
|
* user close another user's socket by guessing a session hash or token id.
|
|
40
54
|
*
|
|
41
55
|
* @param log - logger for disconnect events (info level on non-zero closures)
|
|
42
|
-
* @returns an `on_audit_event` callback suitable for `
|
|
43
|
-
*
|
|
56
|
+
* @returns an `on_audit_event` callback suitable for `create_audit_emitter`'s
|
|
57
|
+
* `on_audit_event` slot, or for appending onto
|
|
58
|
+
* `audit.on_event_chain` post-assembly. The returned callback mutates
|
|
59
|
+
* `transport` (closing matching sockets via
|
|
44
60
|
* `close_sockets_for_session` / `_token` / `_account`) on every relevant event.
|
|
45
61
|
*/
|
|
46
62
|
export const create_ws_auth_guard = (transport, log) => {
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `WsEndpointSpec` — the canonical WebSocket endpoint declaration consumed
|
|
3
|
+
* by `create_app_server`'s `ws_endpoints` option (mirror of `RpcEndpointSpec`
|
|
4
|
+
* for HTTP RPC).
|
|
5
|
+
*
|
|
6
|
+
* Lives in its own module so both `server/app_server.ts` (which mounts
|
|
7
|
+
* endpoints from these specs) and `http/surface.ts` (which threads the
|
|
8
|
+
* resolved spec list into surface generation) can import it without a
|
|
9
|
+
* cycle between the two.
|
|
10
|
+
*
|
|
11
|
+
* @module
|
|
12
|
+
*/
|
|
13
|
+
import type { Action } from './action_types.js';
|
|
14
|
+
import type { RoleName } from '../auth/role_schema.js';
|
|
15
|
+
import type { BackendWebsocketTransport } from './transports_ws_backend.js';
|
|
16
|
+
import type { ServerHeartbeatOptions, SocketCloseContext, SocketOpenContext } from './register_action_ws.js';
|
|
17
|
+
import type { AuditEventHandler } from './transports_ws_auth_guard.js';
|
|
18
|
+
/**
|
|
19
|
+
* Declarative description of a WebSocket endpoint to be auto-mounted by
|
|
20
|
+
* `create_app_server`.
|
|
21
|
+
*
|
|
22
|
+
* Single source of truth for mount + surface — the same array drives
|
|
23
|
+
* `register_ws_endpoint`-style upgrade wiring AND the `surface.ws_endpoints`
|
|
24
|
+
* slot emitted into `AppSurface`, so consumers cannot drift their declared
|
|
25
|
+
* actions from what dispatch actually serves.
|
|
26
|
+
*/
|
|
27
|
+
export interface WsEndpointSpec {
|
|
28
|
+
/** Hono mount path (e.g. `/api/ws`). */
|
|
29
|
+
path: string;
|
|
30
|
+
/**
|
|
31
|
+
* Origin allowlist regexes — typically parsed via `parse_allowed_origins`.
|
|
32
|
+
* Passed straight to `verify_request_source` on upgrade.
|
|
33
|
+
*/
|
|
34
|
+
allowed_origins: ReadonlyArray<RegExp>;
|
|
35
|
+
/**
|
|
36
|
+
* The actions registered on this endpoint. Spread `protocol_actions`
|
|
37
|
+
* from `actions/protocol.ts` first to complete the
|
|
38
|
+
* disconnect-detection + per-request cancel pairing with the frontend
|
|
39
|
+
* client.
|
|
40
|
+
*/
|
|
41
|
+
actions: ReadonlyArray<Action>;
|
|
42
|
+
/**
|
|
43
|
+
* Roles permitted to upgrade — any-of disjunction. Omit (or pass `[]`)
|
|
44
|
+
* to skip the upgrade-time role gate; per-action `auth` on each spec
|
|
45
|
+
* still applies at dispatch time via `perform_action`. Pass
|
|
46
|
+
* `[ROLE_ADMIN]` for a zap-style admin-only WS endpoint.
|
|
47
|
+
*/
|
|
48
|
+
required_roles?: ReadonlyArray<RoleName>;
|
|
49
|
+
/**
|
|
50
|
+
* Existing transport to register connections with. Auto-created when
|
|
51
|
+
* omitted. Either way the mounted transport is reachable on
|
|
52
|
+
* `AppServer.ws_endpoints[path]` for broadcast / fan-out.
|
|
53
|
+
*/
|
|
54
|
+
transport?: BackendWebsocketTransport;
|
|
55
|
+
/**
|
|
56
|
+
* Server-side heartbeat policy. Default-on (60s receive-silence
|
|
57
|
+
* timeout). Set `false` only when an upstream stack (TCP keepalive,
|
|
58
|
+
* Cloudflare idle timeout) already owns disconnect detection.
|
|
59
|
+
*/
|
|
60
|
+
heartbeat?: boolean | ServerHeartbeatOptions;
|
|
61
|
+
/** Optional per-message delay for testing loading states. */
|
|
62
|
+
artificial_delay?: number;
|
|
63
|
+
/**
|
|
64
|
+
* Called once per socket after `transport.add_connection` but before
|
|
65
|
+
* the first message dispatches. See
|
|
66
|
+
* `RegisterActionWsOptions.on_socket_open`.
|
|
67
|
+
*/
|
|
68
|
+
on_socket_open?: (ctx: SocketOpenContext) => void | Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Called once per socket on close, before `transport.remove_connection`.
|
|
71
|
+
* See `RegisterActionWsOptions.on_socket_close`.
|
|
72
|
+
*/
|
|
73
|
+
on_socket_close?: (ctx: SocketCloseContext) => void | Promise<void>;
|
|
74
|
+
/**
|
|
75
|
+
* Default `true` — auto-composes `create_ws_auth_guard` +
|
|
76
|
+
* `create_ws_logout_closer` against this endpoint's transport and
|
|
77
|
+
* appends them to `deps.audit.on_event_chain`. Wiring is deduped by
|
|
78
|
+
* transport **reference identity** (`WeakSet<BackendWebsocketTransport>`),
|
|
79
|
+
* so two `WsEndpointSpec`s sharing the exact same instance get a
|
|
80
|
+
* single pair of listeners.
|
|
81
|
+
*
|
|
82
|
+
* **Shared-transport OR-semantics.** When multiple `WsEndpointSpec`s
|
|
83
|
+
* share one transport, the guard is wired iff **any** of those specs
|
|
84
|
+
* has `auth_guard !== false`. To opt out for a shared transport,
|
|
85
|
+
* every sibling spec must pass `auth_guard: false`. The default is
|
|
86
|
+
* "fail safe" — easier to enable than disable, and predictable
|
|
87
|
+
* regardless of spec order.
|
|
88
|
+
*
|
|
89
|
+
* Reference-identity dedupe means **wrapped or proxied transports
|
|
90
|
+
* dedupe as separate entries** — a consumer threading every
|
|
91
|
+
* transport through a tracing / DI / metrics shim will get a fresh
|
|
92
|
+
* pair of listeners per shimmed reference, even when the underlying
|
|
93
|
+
* transport is the same. If you wrap or proxy, set `auth_guard:
|
|
94
|
+
* false` on the duplicate `WsEndpointSpec`s and compose
|
|
95
|
+
* `create_ws_auth_guard` / `create_ws_logout_closer` against the
|
|
96
|
+
* underlying transport once.
|
|
97
|
+
*
|
|
98
|
+
* Set `false` when a consumer needs to compose their own callback
|
|
99
|
+
* from scratch — or to opt out of the auto-wiring entirely.
|
|
100
|
+
*
|
|
101
|
+
* NOTE: does NOT close sockets on `role_grant_revoke` — that omission
|
|
102
|
+
* is deliberate (per-connection role tracking is out of scope). A user
|
|
103
|
+
* whose admin role is revoked keeps their socket open; the next message
|
|
104
|
+
* gets `forbidden` from the per-message authorization phase. Consumers
|
|
105
|
+
* wanting role-revoke disconnection use `extra_audit_handlers`.
|
|
106
|
+
*/
|
|
107
|
+
auth_guard?: boolean;
|
|
108
|
+
/**
|
|
109
|
+
* Extra audit-event handlers appended to `deps.audit.on_event_chain`
|
|
110
|
+
* AFTER the standard `auth_guard` wiring (when enabled). By the time
|
|
111
|
+
* these run, the standard guards may have already closed sockets. Use
|
|
112
|
+
* for role-revoke disconnection, custom analytics, etc.
|
|
113
|
+
*
|
|
114
|
+
* Never deduped — consumer-owned; pass the same handler twice and it
|
|
115
|
+
* fires twice.
|
|
116
|
+
*/
|
|
117
|
+
extra_audit_handlers?: ReadonlyArray<AuditEventHandler>;
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=ws_endpoint_spec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ws_endpoint_spec.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/ws_endpoint_spec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,mBAAmB,CAAC;AAC9C,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,EAAC,yBAAyB,EAAC,MAAM,4BAA4B,CAAC;AAC1E,OAAO,KAAK,EACX,sBAAsB,EACtB,kBAAkB,EAClB,iBAAiB,EACjB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,+BAA+B,CAAC;AAErE;;;;;;;;GAQG;AACH,MAAM,WAAW,cAAc;IAC9B,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,eAAe,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACvC;;;;;OAKG;IACH,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC/B;;;;;OAKG;IACH,cAAc,CAAC,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IACzC;;;;OAIG;IACH,SAAS,CAAC,EAAE,yBAAyB,CAAC;IACtC;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG,sBAAsB,CAAC;IAC7C,6DAA6D;IAC7D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,GAAG,EAAE,iBAAiB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClE;;;OAGG;IACH,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,kBAAkB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;;;OAQG;IACH,oBAAoB,CAAC,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAC;CACxD"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `WsEndpointSpec` — the canonical WebSocket endpoint declaration consumed
|
|
3
|
+
* by `create_app_server`'s `ws_endpoints` option (mirror of `RpcEndpointSpec`
|
|
4
|
+
* for HTTP RPC).
|
|
5
|
+
*
|
|
6
|
+
* Lives in its own module so both `server/app_server.ts` (which mounts
|
|
7
|
+
* endpoints from these specs) and `http/surface.ts` (which threads the
|
|
8
|
+
* resolved spec list into surface generation) can import it without a
|
|
9
|
+
* cycle between the two.
|
|
10
|
+
*
|
|
11
|
+
* @module
|
|
12
|
+
*/
|
|
13
|
+
export {};
|
package/dist/auth/CLAUDE.md
CHANGED
|
@@ -2,16 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
> Auth domain: identity, crypto primitives, schema + DDL, queries, middleware, routes, RPC actions, cleanup.
|
|
4
4
|
|
|
5
|
-
Grouped below by theme. For design rationale and threat
|
|
6
|
-
|
|
5
|
+
Grouped below by theme. For design rationale and threat model, see
|
|
6
|
+
../../../docs/identity.md and ../../../docs/security.md. For the
|
|
7
7
|
subsystem's place in server assembly and middleware ordering, see
|
|
8
|
-
|
|
8
|
+
../../../docs/architecture.md and the root ../../../CLAUDE.md. For
|
|
9
|
+
the workspace-wide DI vocabulary (capabilities / options / runtime
|
|
10
|
+
state), see Skill(fuz-stack) dependency-injection.
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
`
|
|
12
|
-
(
|
|
13
|
-
inline, never in `deps`. All `query_*` functions take
|
|
14
|
-
as their first arg.
|
|
12
|
+
Auth-specific instances: stateless capabilities in `AppDeps` /
|
|
13
|
+
`RouteFactoryDeps`; static config in `*Options`; runtime state
|
|
14
|
+
(`DaemonTokenState`, mutable `AppSettings` ref, `BootstrapStatus`) is
|
|
15
|
+
inline, never in `deps`. All `query_*` functions take
|
|
16
|
+
`deps: QueryDeps = {db}` as their first arg.
|
|
15
17
|
|
|
16
18
|
## Crypto primitives
|
|
17
19
|
|
|
@@ -373,10 +375,11 @@ Zod enum; `AuditOutcome` is `'success' | 'failure'`.
|
|
|
373
375
|
- **Consumer extensibility**: `create_audit_log_config({extra_events})`
|
|
374
376
|
builds an `AuditLogConfig` merging builtins with consumer event-type
|
|
375
377
|
strings keyed to a Zod schema (validates metadata) or `null` (registers
|
|
376
|
-
without validation). Pass the result
|
|
377
|
-
—
|
|
378
|
-
|
|
379
|
-
`
|
|
378
|
+
without validation). Pass the result into the consumer's `audit_factory`
|
|
379
|
+
body — typically `({db, log}) => create_audit_emitter({db, log,
|
|
380
|
+
audit_log_config, on_audit_event})` — so it gets captured inside the
|
|
381
|
+
bound `AppDeps.audit` emitter; every call to `audit.emit` validates
|
|
382
|
+
against it (defaults to `builtin_audit_log_config` when absent). `query_audit_log` still accepts
|
|
380
383
|
the trailing `config` positional arg for in-transaction emit sites that
|
|
381
384
|
hold a transaction-scoped DB only. Builtin collisions and
|
|
382
385
|
`AuditEventTypeName` format failures throw at construction. The DB
|
|
@@ -754,7 +757,9 @@ run'` if the seed somehow missed (defensive — migrations always seed).
|
|
|
754
757
|
- `query_audit_log_list_role_grant_history` (filters to `role_grant_create` / `role_grant_revoke`).
|
|
755
758
|
- `query_audit_log_cleanup_before`.
|
|
756
759
|
- **Audit fan-out runs through `AppDeps.audit`** (the bound emitter built
|
|
757
|
-
by `
|
|
760
|
+
by the consumer's `audit_factory` callback on `CreateAppBackendOptions`,
|
|
761
|
+
typically a one-liner over `create_audit_emitter` — see
|
|
762
|
+
§`audit_emitter.ts`).
|
|
758
763
|
`audit.emit(ctx, input)` writes via the captured pool, so audit entries
|
|
759
764
|
persist even when the request transaction rolls back. The emitter
|
|
760
765
|
closes over `on_audit_event` + `audit_log_config` so handlers can never
|
|
@@ -765,7 +770,11 @@ run'` if the seed somehow missed (defensive — migrations always seed).
|
|
|
765
770
|
### `audit_emitter.ts`
|
|
766
771
|
|
|
767
772
|
`AuditEmitter` is the bound capability that lives on `AppDeps.audit`,
|
|
768
|
-
built once
|
|
773
|
+
built once by the consumer's `audit_factory` callback on
|
|
774
|
+
`CreateAppBackendOptions`. `create_app_backend` invokes the callback
|
|
775
|
+
with its constructed `{db, log}` after migrations run; the canonical
|
|
776
|
+
body is `({db, log}) => create_audit_emitter({db, log, on_audit_event,
|
|
777
|
+
audit_log_config})`.
|
|
769
778
|
|
|
770
779
|
Four methods:
|
|
771
780
|
|
|
@@ -789,7 +798,7 @@ Per-call `ctx` shape:
|
|
|
789
798
|
- `emit` requires `{pending_effects: Array<Promise<void>>}` — the eager
|
|
790
799
|
queue only. Both `RouteContext` and `ActionContext` satisfy this
|
|
791
800
|
structurally; `audit.emit` pushes its in-flight pool-write promise
|
|
792
|
-
onto the eager queue. See
|
|
801
|
+
onto the eager queue. See `http/CLAUDE.md` §Pending Effects for
|
|
793
802
|
the eager / deferred split.
|
|
794
803
|
- `emit_role_grant_target` adds `client_ip: string` (also on `ActionContext`;
|
|
795
804
|
REST handlers pass `{pending_effects, client_ip: get_client_ip(c)}`).
|
|
@@ -919,7 +928,7 @@ consciously violate the contract.
|
|
|
919
928
|
|
|
920
929
|
## Middleware
|
|
921
930
|
|
|
922
|
-
See the root
|
|
931
|
+
See the root ../../../CLAUDE.md §Middleware Ordering for the canonical
|
|
923
932
|
assembly order. Two-phase identity:
|
|
924
933
|
|
|
925
934
|
- **Authentication** runs in middleware (session / bearer / daemon
|
|
@@ -974,7 +983,7 @@ assembly order. Two-phase identity:
|
|
|
974
983
|
actor row was deleted between credential validation and the
|
|
975
984
|
follow-up read). The named per-error shape `AuthorizationFailureBody`
|
|
976
985
|
is still exported for callers that want to bind the failure body
|
|
977
|
-
by type. See the root
|
|
986
|
+
by type. See the root ../../../CLAUDE.md §Cleanest architecture
|
|
978
987
|
takes priority for the rationale.
|
|
979
988
|
|
|
980
989
|
Session parsing is separate from auth enforcement — login / bootstrap
|
|
@@ -1141,6 +1150,8 @@ Session-based auth route specs. Factory: `create_account_route_specs(deps, optio
|
|
|
1141
1150
|
- `POST /logout` — revokes session by hash, clears cookie.
|
|
1142
1151
|
- **`POST /password`** — `current_password: PasswordProvided` +
|
|
1143
1152
|
`new_password: Password`. Per-IP + per-account rate limited.
|
|
1153
|
+
Declares `credential_types: ['session']` (see
|
|
1154
|
+
`docs/security.md` §Credential-channel gating).
|
|
1144
1155
|
**Revokes all sessions + all API tokens** (force re-auth everywhere);
|
|
1145
1156
|
clears cookie.
|
|
1146
1157
|
- **`GET /verify`** — empty-body session-validity probe for nginx
|
|
@@ -1212,7 +1223,7 @@ gets `require_auth` when `account === 'required'` or `actor === 'required'`;
|
|
|
1212
1223
|
`post_authorization` gets `require_credential_types(types)` when
|
|
1213
1224
|
`credential_types?.length` and `require_role(roles)` when `roles?.length`.
|
|
1214
1225
|
Injected into `apply_route_specs` so the generic HTTP framework stays
|
|
1215
|
-
auth-agnostic (see
|
|
1226
|
+
auth-agnostic (see `http/CLAUDE.md` §Validation pipeline for where it plugs in).
|
|
1216
1227
|
|
|
1217
1228
|
### `audit_log_routes.ts`
|
|
1218
1229
|
|
|
@@ -1232,7 +1243,7 @@ module produces is now just the optional SSE stream:
|
|
|
1232
1243
|
## RPC actions (SAES)
|
|
1233
1244
|
|
|
1234
1245
|
Three action surfaces that mount on a consumer's JSON-RPC endpoint via
|
|
1235
|
-
`create_rpc_endpoint` (see
|
|
1246
|
+
`create_rpc_endpoint` (see `actions/CLAUDE.md` §Single JSON-RPC 2.0 endpoint).
|
|
1236
1247
|
Each surface is split across two files:
|
|
1237
1248
|
|
|
1238
1249
|
- `*_action_specs.ts` — Input/Output Zod schemas (paired with `z.infer` type
|
|
@@ -1327,6 +1338,19 @@ Closure state:
|
|
|
1327
1338
|
When absent, those two specs are still present in `all_admin_action_specs`
|
|
1328
1339
|
(surface-wise) but the handlers are not wired — RPC dispatch returns
|
|
1329
1340
|
`method_not_found`.
|
|
1341
|
+
- `options.connection_closer?: ConnectionCloser | null` — when set,
|
|
1342
|
+
`admin_session_revoke_all` and `admin_token_revoke_all` handlers
|
|
1343
|
+
eagerly close the target account's live WS sockets via
|
|
1344
|
+
`close_sockets_for_account(input.account_id)` BEFORE emitting the
|
|
1345
|
+
audit event. Failure outcomes (404 account-not-found) skip the
|
|
1346
|
+
eager close. Listener-based close
|
|
1347
|
+
(`transports_ws_auth_guard` on `audit.on_event_chain`) stays as a
|
|
1348
|
+
fail-safe; primitives are idempotent. Symmetric with the
|
|
1349
|
+
self-service surface (see `AccountActionOptions.connection_closer`
|
|
1350
|
+
below). `BackendWebsocketTransport` satisfies the interface
|
|
1351
|
+
structurally. Mirrors `zzz_server`'s parity pass — fuz_app widens
|
|
1352
|
+
to admin-side too (Rust port's catch-up tracked in
|
|
1353
|
+
`~/dev/zzz/TODO_RUST_SERVER_DETAILS.md`).
|
|
1330
1354
|
|
|
1331
1355
|
`all_admin_action_specs: Array<RequestResponseActionSpec>` — codegen-ready
|
|
1332
1356
|
registry of all eleven specs (always includes the two app-settings specs).
|
|
@@ -1413,16 +1437,16 @@ Error reason constants (exported as `as const` literals):
|
|
|
1413
1437
|
- `ERROR_ROLE_GRANT_OFFER_ACTOR_MISMATCH` (`'role_grant_offer_actor_mismatch'` —
|
|
1414
1438
|
actor-targeted offer was accepted by an actor other than `to_actor_id`)
|
|
1415
1439
|
|
|
1416
|
-
Plus re-uses from
|
|
1440
|
+
Plus re-uses from `http/error_schemas.ts`: `ERROR_ROLE_GRANT_NOT_FOUND`,
|
|
1417
1441
|
`ERROR_ROLE_NOT_WEB_GRANTABLE`, `ERROR_INSUFFICIENT_PERMISSIONS`,
|
|
1418
1442
|
`ERROR_ACCOUNT_NOT_FOUND`.
|
|
1419
1443
|
|
|
1420
1444
|
Each spec declares the reason codes its handler may surface (see
|
|
1421
|
-
|
|
1445
|
+
`actions/CLAUDE.md` §Action specs for the field semantics). Only
|
|
1422
1446
|
domain reasons returned via `error.data.reason` are listed; standard
|
|
1423
1447
|
transport errors (validation, auth, rate-limit) stay implicit. Drift
|
|
1424
1448
|
between declared reasons and handler throws is caught by
|
|
1425
|
-
|
|
1449
|
+
../../test/auth/role_grant_offer_actions.error_reasons.test.ts.
|
|
1426
1450
|
|
|
1427
1451
|
Failure-outcome audit events emitted (success and failure rows both carry
|
|
1428
1452
|
`ip: ctx.client_ip` — uniform with the admin and self-service surfaces):
|
|
@@ -1442,8 +1466,8 @@ Failure-outcome audit events emitted (success and failure rows both carry
|
|
|
1442
1466
|
role_grant).
|
|
1443
1467
|
|
|
1444
1468
|
WS notifications (post-commit via `emit_after_commit` from
|
|
1445
|
-
|
|
1446
|
-
can't starve others; see
|
|
1469
|
+
`http/pending_effects.js` — swallows exceptions so one failed send
|
|
1470
|
+
can't starve others; see `http/CLAUDE.md` §Pending Effects):
|
|
1447
1471
|
|
|
1448
1472
|
- Create → `role_grant_offer_received` to recipient.
|
|
1449
1473
|
- Retract → `role_grant_offer_retracted` to recipient.
|
|
@@ -1490,6 +1514,8 @@ surface drop down to the per-domain factories directly.
|
|
|
1490
1514
|
Option routing: `roles` is shared between admin and role-grant-offer;
|
|
1491
1515
|
`app_settings` flows to admin only; `default_ttl_ms` and `authorize`
|
|
1492
1516
|
flow to role-grant-offer only; `max_tokens` flows to account only;
|
|
1517
|
+
`connection_closer` is shared between admin and account (handler-side
|
|
1518
|
+
eager WS close on revoke; role-grant-offer ignores);
|
|
1493
1519
|
`notification_sender` is wired through to role-grant-offer (admin +
|
|
1494
1520
|
account ignore it).
|
|
1495
1521
|
|
|
@@ -1506,7 +1532,7 @@ Pair this with `create_app_server`'s `rpc_endpoints` factory form
|
|
|
1506
1532
|
(`(ctx) => Array<RpcEndpointSpec>`) so the combined action list gets
|
|
1507
1533
|
`ctx.deps` + `ctx.app_settings` — `create_app_server` auto-mounts the
|
|
1508
1534
|
endpoint via `create_rpc_endpoint`, so consumers don't need to mount it
|
|
1509
|
-
again in `create_route_specs`. See
|
|
1535
|
+
again in `create_route_specs`. See ../../../docs/usage.md §Server
|
|
1510
1536
|
Assembly.
|
|
1511
1537
|
|
|
1512
1538
|
Pre-bundle consumers spread `create_admin_actions` and
|
|
@@ -1519,20 +1545,43 @@ consumer wiring the admin surface without account actions will hit
|
|
|
1519
1545
|
`method not found` on first admin-suite run.
|
|
1520
1546
|
|
|
1521
1547
|
Frontend mirror: `all_standard_action_specs` (in
|
|
1522
|
-
|
|
1548
|
+
`auth/standard_action_specs.ts`) bundles `all_admin_action_specs +
|
|
1523
1549
|
all_role_grant_offer_action_specs + all_account_action_specs` into one
|
|
1524
1550
|
`ReadonlyArray<RequestResponseActionSpec>` for typed-client codegen
|
|
1525
1551
|
and `create_frontend_rpc_client({specs})` wiring. Self-service role
|
|
1526
1552
|
specs are not included (opt-in, app-specific `eligible_roles`) —
|
|
1527
1553
|
spread `all_self_service_role_action_specs` separately when needed.
|
|
1528
1554
|
|
|
1555
|
+
To expose the standard surface over WebSocket as well as HTTP RPC,
|
|
1556
|
+
spread `protocol_actions` and `create_standard_rpc_actions(ctx.deps,
|
|
1557
|
+
opts)` into `create_app_server`'s `ws_endpoints` factory alongside the
|
|
1558
|
+
matching `rpc_endpoints` entry:
|
|
1559
|
+
|
|
1560
|
+
```ts
|
|
1561
|
+
ws_endpoints: (ctx) => [{
|
|
1562
|
+
path: '/api/ws',
|
|
1563
|
+
allowed_origins,
|
|
1564
|
+
actions: [
|
|
1565
|
+
...protocol_actions,
|
|
1566
|
+
...create_standard_rpc_actions(ctx.deps, opts),
|
|
1567
|
+
...consumer_local_actions,
|
|
1568
|
+
],
|
|
1569
|
+
}],
|
|
1570
|
+
```
|
|
1571
|
+
|
|
1572
|
+
The same action factory powers both surfaces; per-message authorization
|
|
1573
|
+
and rate limiting fire identically across HTTP RPC and WS. With both
|
|
1574
|
+
endpoints mounted, a typed frontend client can route per-method via
|
|
1575
|
+
`transport_for_method` (e.g. `account_*` over WS for live revocation
|
|
1576
|
+
detection, admin reads over HTTP).
|
|
1577
|
+
|
|
1529
1578
|
### `all_action_spec_registries.ts` — walker-only registry-of-registries
|
|
1530
1579
|
|
|
1531
1580
|
`all_fuz_auth_action_spec_registries` — walker/codegen entry for every
|
|
1532
1581
|
fuz-auth action-spec bundle (`admin`, `role_grant_offer`, `account`,
|
|
1533
1582
|
`self_service_role`, `actor_lookup`, `actor_search`). Not a mounting
|
|
1534
1583
|
surface; protocol specs are excluded. Iterated by registry-wide
|
|
1535
|
-
invariant tests in
|
|
1584
|
+
invariant tests in ../../test/auth/.
|
|
1536
1585
|
|
|
1537
1586
|
### `account_action_specs.ts` + `account_actions.ts` — seven self-service RPC actions
|
|
1538
1587
|
|
|
@@ -1553,6 +1602,18 @@ operations are account-scoped via `query_session_revoke_for_account` /
|
|
|
1553
1602
|
or token id returns `revoked: false` rather than revealing whether the id
|
|
1554
1603
|
exists.
|
|
1555
1604
|
|
|
1605
|
+
**Credential-channel gating** — `account_token_create`,
|
|
1606
|
+
`account_token_revoke`, `account_session_revoke`, and
|
|
1607
|
+
`account_session_revoke_all` declare `credential_types: ['session']`
|
|
1608
|
+
on their `auth` axis (same gate as REST `POST /password`).
|
|
1609
|
+
`account_session_revoke` is gated alongside `_revoke_all` because a
|
|
1610
|
+
leaked bearer can otherwise compose `account_session_list` + N×revoke
|
|
1611
|
+
to reach the same lockout. Admin token/session revoke specs in
|
|
1612
|
+
`admin_action_specs.ts` deliberately stay unrestricted (admin
|
|
1613
|
+
scripting from CLI/bearer is legitimate operator workflow). For the
|
|
1614
|
+
threat model, the trust-bar rationale, and the defense-in-depth audit
|
|
1615
|
+
metadata see `docs/security.md` §Credential-channel gating.
|
|
1616
|
+
|
|
1556
1617
|
| Spec | Side effects | Rate limit | Input | Output |
|
|
1557
1618
|
| ---------------------------------------- | ------------ | ----------- | -------------- | ----------------------- |
|
|
1558
1619
|
| `account_verify_action_spec` | false | | `z.void()` | `SessionAccountJson` |
|
|
@@ -1577,11 +1638,31 @@ vector, so rate caps are symmetry-only and skipped.
|
|
|
1577
1638
|
Audit events emitted (via `deps.audit.emit` with `ip: ctx.client_ip`):
|
|
1578
1639
|
`session_revoke`, `session_revoke_all`, `token_create`, `token_revoke`. The
|
|
1579
1640
|
IP is the resolved trusted-proxy value from `ActionContext.client_ip`,
|
|
1580
|
-
matching the REST handler convention.
|
|
1641
|
+
matching the REST handler convention. Every gated event additionally
|
|
1642
|
+
records `credential_type` (read from `ActionContext.credential_type`)
|
|
1643
|
+
in metadata — defense in depth so forensics survive if the
|
|
1644
|
+
`credential_types: ['session']` spec gate is ever loosened or bypassed.
|
|
1645
|
+
The REST `password_change` audit row mirrors the same field on all
|
|
1646
|
+
three outcomes (success, wrong-password, concurrent-change).
|
|
1581
1647
|
|
|
1582
1648
|
Deps: `Pick<RouteFactoryDeps, 'log' | 'audit'>`.
|
|
1583
|
-
Options: `{max_tokens?: number | null
|
|
1584
|
-
from `account_routes.ts`;
|
|
1649
|
+
Options: `{max_tokens?: number | null, connection_closer?: ConnectionCloser | null}`.
|
|
1650
|
+
`max_tokens` defaults to `DEFAULT_MAX_TOKENS` from `account_routes.ts`;
|
|
1651
|
+
`null` disables the cap. `connection_closer` (from
|
|
1652
|
+
`actions/connection_closer.ts`) wires handler-side eager WS socket
|
|
1653
|
+
closure: `account_session_revoke` calls `close_sockets_for_session(input.session_id)`,
|
|
1654
|
+
`_session_revoke_all` calls `close_sockets_for_account(account.id)`,
|
|
1655
|
+
`account_token_revoke` calls `close_sockets_for_token(input.token_id)` —
|
|
1656
|
+
each fires synchronously BEFORE the audit emit so revocation lands even
|
|
1657
|
+
when the audit INSERT fails. Listener-based close
|
|
1658
|
+
(`transports_ws_auth_guard` on `audit.on_event_chain`) stays as a
|
|
1659
|
+
fail-safe; close primitives are idempotent. Failure outcomes
|
|
1660
|
+
(`revoked: false`) skip the eager close — mirrors the listener's
|
|
1661
|
+
`outcome === 'failure'` guard so attacker-guessable ids can't be used to
|
|
1662
|
+
target arbitrary sockets. `BackendWebsocketTransport` satisfies
|
|
1663
|
+
`ConnectionCloser` structurally — consumers pass the WS transport
|
|
1664
|
+
instance directly. Mirrors `zzz_server::handlers/account.rs` (landed
|
|
1665
|
+
2026-05-16).
|
|
1585
1666
|
|
|
1586
1667
|
`all_account_action_specs: Array<RequestResponseActionSpec>` — codegen-ready
|
|
1587
1668
|
registry of all seven specs.
|
|
@@ -1698,7 +1779,7 @@ One static `request_response` action — `actor_search({query, scope_ids?, limit
|
|
|
1698
1779
|
powers person-target pickers. Sibling to `actor_lookup`: that resolves a
|
|
1699
1780
|
batch of known ids to labels; this resolves a partial name to candidate
|
|
1700
1781
|
actors. Reuses `ActorLookupEntryJson` from
|
|
1701
|
-
|
|
1782
|
+
`auth/actor_lookup_action_specs.ts` so the labels arc on the consumer side
|
|
1702
1783
|
stays uniform. Default limit `ACTOR_SEARCH_LIMIT_DEFAULT = 20`, hard cap
|
|
1703
1784
|
`ACTOR_SEARCH_LIMIT_MAX = 50`. Query string capped at
|
|
1704
1785
|
`ACTOR_SEARCH_QUERY_LENGTH_MAX = 50`.
|
|
@@ -1789,15 +1870,19 @@ resulting role_grant.
|
|
|
1789
1870
|
- `db: Db` — pool-level instance (middleware uses this; route handlers
|
|
1790
1871
|
get a transaction-scoped `Db` via `RouteContext`).
|
|
1791
1872
|
- `log: Logger`.
|
|
1792
|
-
- `audit: AuditEmitter` — bound emitter built once
|
|
1793
|
-
|
|
1873
|
+
- `audit: AuditEmitter` — bound emitter built once by the consumer's
|
|
1874
|
+
`audit_factory` callback on `CreateAppBackendOptions`. The factory
|
|
1875
|
+
runs after `create_db` resolves and migrations apply;
|
|
1876
|
+
`create_app_backend` invokes it with `{db, log}` and lands the
|
|
1877
|
+
returned emitter on `deps.audit`. The canonical body is one line
|
|
1878
|
+
over `create_audit_emitter` (closes over the pool, the
|
|
1794
1879
|
`on_audit_event` subscriber chain, and the optional
|
|
1795
|
-
`AuditLogConfig`
|
|
1880
|
+
`AuditLogConfig`); consumers wrap or replace it for tests. Handlers
|
|
1881
|
+
reach `audit.emit(ctx, input)` /
|
|
1796
1882
|
`audit.emit_role_grant_target(ctx, auth, input)` and never see the
|
|
1797
|
-
pool.
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
via `audit.on_event_chain.push(...)` at server assembly).
|
|
1883
|
+
pool. The slot is the single seam for SSE/WS fan-out — additional
|
|
1884
|
+
listeners append via `audit.on_event_chain.push(...)` at server
|
|
1885
|
+
assembly.
|
|
1801
1886
|
- **`RouteFactoryDeps = Omit<AppDeps, 'db'>`** — for route factories. Route
|
|
1802
1887
|
handlers receive DB access via `RouteContext`, so factories don't capture
|
|
1803
1888
|
a pool-level `Db`.
|
|
@@ -1805,5 +1890,5 @@ resulting role_grant.
|
|
|
1805
1890
|
Action factories take `Pick<RouteFactoryDeps, 'log' | 'audit'>` directly
|
|
1806
1891
|
(role-grant-offer adds `notification_sender?` inline).
|
|
1807
1892
|
|
|
1808
|
-
See root
|
|
1893
|
+
See root ../../../CLAUDE.md §AppDeps Vocabulary for the
|
|
1809
1894
|
capability / options / runtime-state split across the whole project.
|
|
@@ -98,7 +98,7 @@ export declare const account_verify_action_spec: {
|
|
|
98
98
|
input: z.ZodVoid;
|
|
99
99
|
output: z.ZodObject<{
|
|
100
100
|
id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
|
|
101
|
-
username: z.ZodString
|
|
101
|
+
username: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
102
102
|
email: z.ZodNullable<z.ZodEmail>;
|
|
103
103
|
email_verified: z.ZodBoolean;
|
|
104
104
|
created_at: z.ZodString;
|
|
@@ -135,6 +135,7 @@ export declare const account_session_revoke_action_spec: {
|
|
|
135
135
|
auth: {
|
|
136
136
|
account: "required";
|
|
137
137
|
actor: "none";
|
|
138
|
+
credential_types: string[];
|
|
138
139
|
};
|
|
139
140
|
side_effects: true;
|
|
140
141
|
input: z.ZodObject<{
|
|
@@ -154,6 +155,7 @@ export declare const account_session_revoke_all_action_spec: {
|
|
|
154
155
|
auth: {
|
|
155
156
|
account: "required";
|
|
156
157
|
actor: "none";
|
|
158
|
+
credential_types: string[];
|
|
157
159
|
};
|
|
158
160
|
side_effects: true;
|
|
159
161
|
input: z.ZodVoid;
|
|
@@ -165,6 +167,8 @@ export declare const account_session_revoke_all_action_spec: {
|
|
|
165
167
|
description: string;
|
|
166
168
|
};
|
|
167
169
|
/**
|
|
170
|
+
* `credential_types: ['session']` — see `docs/security.md` §Credential-channel gating.
|
|
171
|
+
*
|
|
168
172
|
* `rate_limit: 'account'` bounds the burn rate of API-token creates. The
|
|
169
173
|
* outstanding-token count is already capped by `max_tokens` (via
|
|
170
174
|
* `query_api_token_enforce_limit`), but the per-account *rate* of churn
|
|
@@ -179,6 +183,7 @@ export declare const account_token_create_action_spec: {
|
|
|
179
183
|
auth: {
|
|
180
184
|
account: "required";
|
|
181
185
|
actor: "none";
|
|
186
|
+
credential_types: string[];
|
|
182
187
|
};
|
|
183
188
|
side_effects: true;
|
|
184
189
|
input: z.ZodPrefault<z.ZodObject<{
|
|
@@ -225,6 +230,7 @@ export declare const account_token_revoke_action_spec: {
|
|
|
225
230
|
auth: {
|
|
226
231
|
account: "required";
|
|
227
232
|
actor: "none";
|
|
233
|
+
credential_types: string[];
|
|
228
234
|
};
|
|
229
235
|
side_effects: true;
|
|
230
236
|
input: z.ZodObject<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account_action_specs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/account_action_specs.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAGtB,OAAO,KAAK,EAAC,yBAAyB,EAAC,MAAM,2BAA2B,CAAC;AAMzE,6EAA6E;AAC7E,eAAO,MAAM,WAAW,WAAW,CAAC;AACpC,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEtD,uDAAuD;AACvD,eAAO,MAAM,gBAAgB,WAAW,CAAC;AACzC,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEhE,yCAAyC;AACzC,eAAO,MAAM,iBAAiB;;;;;;;;kBAE5B,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAElE,2EAA2E;AAC3E,eAAO,MAAM,kBAAkB;;kBAE7B,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEpE,iFAAiF;AACjF,eAAO,MAAM,mBAAmB;;;kBAG9B,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEtE,6DAA6D;AAC7D,eAAO,MAAM,qBAAqB,WAAW,CAAC;AAC9C,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAE1E,+CAA+C;AAC/C,eAAO,MAAM,sBAAsB;;;kBAGjC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAE5E,wCAAwC;AACxC,eAAO,MAAM,gBAAgB;;mBAOf,CAAC;AACf,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEhE,2EAA2E;AAC3E,eAAO,MAAM,iBAAiB;;;;;kBAK5B,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAElE,qDAAqD;AACrD,eAAO,MAAM,cAAc,WAAW,CAAC;AACvC,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAE5D,4DAA4D;AAC5D,eAAO,MAAM,eAAe;;;;;;;;;;kBAE1B,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAE9D,wCAAwC;AACxC,eAAO,MAAM,gBAAgB;;kBAE3B,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEhE,+EAA+E;AAC/E,eAAO,MAAM,iBAAiB;;;kBAG5B,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAIlE,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;CAUF,CAAC;AAEtC,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;;;CAUR,CAAC;
|
|
1
|
+
{"version":3,"file":"account_action_specs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/account_action_specs.ts"],"names":[],"mappings":"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"}
|