api #

fullstack app library

242 modules ยท 1458 declarations

Modules
#

AcceptOfferInput
#

auth/role_grant_offer_queries.ts view source

AcceptOfferInput

offer_id

type Uuid

to_account_id

Account of the accepting recipient โ€” IDOR guard against another account accepting the offer.

type Uuid

actor_id

Accepting actor โ€” the actor that will hold the resulting role_grant. Must belong to to_account_id; the query verifies and throws if not (defense-in-depth โ€” the action handler passes auth.actor.id which is session-bound, but the query enforces the invariant for all callers including tests and future direct consumers).

Required because under multi-actor an account may host many actors; the resulting role_grant must bind to the actor that actually accepted, not "an" actor on the account picked by query order.

type Uuid

ip

Optional IP to stamp on the audit events.

type string | null

AcceptOfferResult
#

auth/role_grant_offer_queries.ts view source

AcceptOfferResult

Result of query_accept_offer โ€” the role_grant produced (new or pre-existing on race), plus the (now-accepted) offer.

role_grant

offer

created

true if this call is the one that accepted the offer (new role_grant inserted); false on a race returning the already-created role_grant.

type boolean

superseded_offers

Sibling offers superseded by this accept โ€” empty on the race-loser path. Each entry carries its grantor's from_account_id so the caller can fan out role_grant_offer_supersede notifications without a second round-trip.

type Array<SupersededOffer>

audit_events

Audit events emitted in-transaction โ€” fed back through audit.notify by the caller, which fans out to audit.on_event_chain. Includes one role_grant_offer_supersede per superseded sibling.

type Array<AuditLogEvent>

Account
#

auth/account_schema.ts view source

Account

Account โ€” authentication identity. You log in as an account.

id

type Uuid

username

email

type Email | null

email_verified

type boolean

password_hash

type string

created_at

type string

created_by

type Uuid | null

updated_at

type string

updated_by

type Uuid | null

ACCOUNT_EMAIL_INDEX
#

auth/auth_ddl.ts view source

"\nCREATE UNIQUE INDEX IF NOT EXISTS idx_account_email ON account (LOWER(email)) WHERE email IS NOT NULL"

ACCOUNT_ID_KEY
#

hono_context.ts view source

"auth_account_id"

Hono context variable name for the authenticated account id.

Set by the auth middleware (session, bearer, or daemon token) on a valid credential. null for unauthenticated requests. The route-spec wrapper / RPC dispatcher's authorization phase reads this when resolving the acting actor; account-grain auth guards (require_auth) and account-grain handlers read it directly.

ACCOUNT_SCHEMA
#

auth/auth_ddl.ts view source

"\nCREATE TABLE IF NOT EXISTS account (\n id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n username TEXT UNIQUE NOT NULL,\n email TEXT,\n email_verified BOOLEAN NOT NULL DEFAULT false,\n password_hash TEXT NOT NULL,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n created_by UUID,\n updated_at TIMESTAMPTZ ...

Identity-table DDL โ€” CREATE TABLE, index, and seed statements for the core auth tables (account, actor, role_grant, auth_session, api_token, bootstrap_lock, invite, app_settings).

Consumed by auth/migrations.ts. Paired with auth/audit_log_ddl.ts (audit table) and auth/role_grant_offer_ddl.ts (offer table) โ€” DDL lives in *_ddl.ts, Zod schemas in *_schema.ts.

account_session_list_action_spec
#

auth/account_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "none"; }; side_effects: false; input: ZodVoid; output: ZodObject<{ sessions: ZodArray<ZodObject<{ id: ZodString; account_id: $ZodBranded<...>; created_at: ZodString; expires_at: ZodString; last_seen_at: ZodString;...

account_session_revoke_action_spec
#

auth/account_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "none"; credential_types: string[]; }; side_effects: true; input: ZodObject<{ session_id: ZodString; }, $strict>; output: ZodObject<...>; async: true; description: string; }

account_session_revoke_all_action_spec
#

auth/account_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "none"; credential_types: string[]; }; side_effects: true; input: ZodVoid; output: ZodObject<...>; async: true; description: string; }

account_sessions_rpc_context
#

ui/account_sessions_state.svelte.ts view source

{ get: () => () => AccountSessionsRpc | null; set: (value?: (() => AccountSessionsRpc | null) | undefined) => () => AccountSessionsRpc | null; }

Svelte context carrying the reactive AccountSessionsRpc accessor. Mirrors the admin-side RPC contexts. Unset context falls back to () => null so components render the usual "rpc adapter not wired" state.

account_token_create_action_spec
#

auth/account_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "none"; credential_types: string[]; }; side_effects: true; input: ZodPrefault<ZodObject<{ name: ZodDefault<ZodString>; }, $strict>>; output: ZodObject<...>; async: true; description: string; rate_limit: "account"; }

credential_types: ['session'] โ€” see docs/security.md ยงCredential-channel gating.

rate_limit: 'account' bounds the burn rate of API-token creates. The outstanding-token count is already capped by max_tokens (via query_api_token_enforce_limit), but the per-account *rate* of churn is not โ€” without this cap, a caller could rotate tokens in a tight loop to amplify token_create audit churn or attempt to provoke downstream rate-limit hot spots.

account_token_list_action_spec
#

auth/account_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "none"; }; side_effects: false; input: ZodVoid; output: ZodObject<{ tokens: ZodArray<ZodObject<{ id: ZodString; ... 5 more ...; created_at: ZodString; }, $strict>>; }, $strict>; async: true; description: string; }

account_token_revoke_action_spec
#

auth/account_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "none"; credential_types: string[]; }; side_effects: true; input: ZodObject<{ token_id: ZodString; }, $strict>; output: ZodObject<...>; async: true; description: string; }

ACCOUNT_USERNAME_CI_INDEX
#

account_verify_action_spec
#

auth/account_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "none"; }; side_effects: false; input: ZodVoid; output: ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; username: ZodPipe<...>; email: ZodNullable<...>; email_verified: ZodBoolean; created_at: ZodString; }, $s...

AccountActionOptions
#

auth/account_actions.ts view source

AccountActionOptions

max_tokens

Max API tokens per account. When set, account_token_create enforces the cap via query_api_token_enforce_limit inside the same transaction โ€” oldest tokens are evicted once the cap is exceeded. Default DEFAULT_MAX_TOKENS; pass null to disable the cap.

type number | null

connection_closer

Live-connection closer โ€” when set, account_session_revoke / _session_revoke_all / account_token_revoke handlers eagerly close affected WebSocket sockets BEFORE emitting the corresponding audit event. Closes the audit-failure-leaks-WS surface: the listener-based close (transports_ws_auth_guard) only fires after the audit INSERT succeeds, so a DB error would leave live sockets stale. BackendWebsocketTransport satisfies this interface structurally; consumers pass their transport instance directly. When absent, only the listener-based close runs. Mirrors zzz_server's handler-side close_sockets_for_* calls.

type ConnectionCloser | null

AccountRouteOptions
#

auth/account_routes.ts view source

AccountRouteOptions

Per-factory configuration for account route specs.

inheritance

login_account_rate_limiter

Rate limiter for login attempts, keyed by submitted username. Pass null to disable.

type RateLimiter | null

max_sessions

Max active sessions per account. Evicts oldest on login. Default 5, null disables.

type number | null

login_fail_floor_ms

Minimum wall-clock time (ms) for login 401 responses. Set to 0 or a negative number to disable (e.g., in tests). Default DEFAULT_LOGIN_FAIL_FLOOR_MS.

type number

login_fail_jitter_ms

Uniform jitter window (ยฑms) layered on the floor. Set to 0 to disable jitter while keeping the floor. Default DEFAULT_LOGIN_FAIL_JITTER_MS.

type number

connection_closer

Live-connection closer โ€” when set, the logout and password handlers eagerly close affected WebSocket sockets for the account BEFORE emitting the corresponding audit event. Mirrors the self-service action surface (see AccountActionOptions.connection_closer). When absent, only the listener-based close (transports_ws_auth_guard on audit.on_event_chain) runs.

type ConnectionCloser | null

AccountSessions
#

AccountSessionsRpc
#

ui/account_sessions_state.svelte.ts view source

AccountSessionsRpc

Narrow RPC surface consumed by AccountSessionsState. Consumers adapt their typed RPC client to this shape. Mirrors the other per-domain *Rpc interfaces (AdminAccountsRpc, AuditLogRpc, AdminInvitesRpc).

The three methods wrap the corresponding action specs on auth/account_actions.ts:

- list โ†’ account_session_list - revoke โ†’ account_session_revoke (IDOR-guarded by account_id server-side) - revoke_all โ†’ account_session_revoke_all

list

type () => Promise<{sessions: Array<AuthSessionJson>}>

revoke

type (params: {session_id: string}) => Promise<{ok: true; revoked: boolean}>

revoke_all

type () => Promise<{ok: true; count: number}>

AccountSessionsState
#

ui/account_sessions_state.svelte.ts view source

list

readonly

revoke

readonly

revoke_all

readonly

sessions

type Array<AuthSessionJson>

active_count

type number

readonly

constructor

type new (options?: AccountSessionsStateOptions | undefined): AccountSessionsState

options?
type AccountSessionsStateOptions | undefined
optional

fetch

type (): Promise<void>

returns Promise<void>

submit_revoke

type (id: string): Promise<void>

id
type string
returns Promise<void>

submit_revoke_all

type (): Promise<void>

returns Promise<void>

AccountSessionsStateOptions
#

ui/account_sessions_state.svelte.ts view source

AccountSessionsStateOptions

get_rpc

Reactive accessor for the RPC adapter; returns null when unwired. Matches the get_rpc pattern on the admin state classes.

type () => AccountSessionsRpc | null

AccountStatusInput
#

AccountStatusOptions
#

auth/account_routes.ts view source

AccountStatusOptions

Options for the account status route spec.

path

Override the default path (/api/account/status).

type string

bootstrap_status

Runtime bootstrap status โ€” when available, 401 responses include bootstrap_available.

type {available: boolean}

AccountStatusOutput
#

auth/account_routes.ts view source

ZodObject<{ account: ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; username: ZodPipe<ZodString, ZodTransform<string, string>>; email: ZodNullable<...>; email_verified: ZodBoolean; created_at: ZodString; }, $strict>; actor: ZodNullable<...>; role_grants: ZodArray<...>; }, $strict>

Output for GET /api/account/status on the authenticated path.

account is always populated for authenticated callers. actor and role_grants are populated when the caller's account has a unique actor or the request supplies ?acting=<actor_id>; on multi-actor accounts without an acting query, actor is null and role_grants is empty so the frontend can show a persona picker without a separate roundtrip.

AccountStatusUnauthenticatedError
#

auth/account_routes.ts view source

ZodObject<{ error: ZodLiteral<"authentication_required">; bootstrap_available: ZodOptional<ZodBoolean>; }, $loose>

Error body for GET /api/account/status on the unauthenticated path.

AccountVanishedError
#

ActingActor
#

http/auth_shape.ts view source

ZodOptional<$ZodBranded<ZodUUID, "Uuid", "out">>

acting field shared by every input that needs the caller's acting actor. Declaring acting: ActingActor on a route or action input signals to the dispatcher's authorization phase to resolve an actor against the authenticated account: it runs resolve_acting_actor, builds the actor-bound RequestContext, and loads role_grants before auth guards fire.

Resolution rules: omitted + 1 actor โ†’ use it; omitted + multiple actors โ†’ actor_required with the available list; supplied + on the account โ†’ use it; supplied + foreign actor โ†’ actor_not_on_account.

Account-grain routes โ€” input doesn't declare acting and auth doesn't require role_grants โ€” skip resolution entirely; their RequestContext.actor is null and the audit envelope's actor_id stays null.

Lives next to RouteAuth because the two are paired by registry-time invariant 2: auth.actor !== 'none' โŸบ input (or query, on REST GETs) declares acting?: ActingActor. Keeping the contract in one module removes the http/ โ†’ auth/ import that an earlier split forced.

ActingSlots
#

http/auth_shape.ts view source

ActingSlots

Slots where a spec may declare the acting?: ActingActor field โ€” input for both REST + actions; query for REST GETs that bi-locate acting on the query schema (actions have no query shape, so the field is omitted on action call sites).

input

type z.ZodType

query

type z.ZodType

Action
#

actions/action_types.ts view source

Action<TSpec>

A spec paired with its optional handler โ€” the composable unit passed to register_action_ws and create_rpc_client. The server uses both fields; the client reads only spec (the handler is ignored, harmless). Shared fuz_app primitives (e.g. heartbeat_action) export a complete tuple so consumers spread them into both sides' actions arrays without inventing per-repo ping plumbing.

Polymorphic on kind: request_response specs require a handler for dispatch; remote_notification specs may declare a stub handler for symmetry but are dispatcher-handled (e.g. cancel); local_call specs never reach a network dispatcher. The WS dispatcher only invokes handlers on request_response actions; everything else is registry-only.

generics

TSpec

constraint ActionSpecUnion

spec

type TSpec

handler

Server-side handler โ€” invoked by dispatchers on request_response actions. Ignored for client-only specs and dispatcher-handled notifications.

action_event_phase_by_kind
#

actions/action_event_types.ts view source

Record<"request_response" | "remote_notification" | "local_call", readonly ("send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute")[]>

action_event_phase_transitions
#

actions/action_event_types.ts view source

Record<"send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute", "send_request" | "receive_request" | ... 7 more ... | null>

action_event_step_transitions
#

action_method_enum_kinds_all
#

ActionActorContext
#

actions/action_rpc.ts view source

ActionActorContext

ActionContext narrowed to a resolved acting actor.

Used by handlers whose spec declares auth.actor === 'required' โ€” the dispatcher's authorization phase resolves an actor (per registry-time invariant 2 the input declares acting?: ActingActor), so ctx.auth.actor is non-null. Selected automatically by rpc_action's conditional return type for the actor-implying tier.

inheritance

extends:
  • Omit<ActionContext, 'auth'>

auth

ActionAuthContext
#

actions/action_rpc.ts view source

ActionAuthContext

ActionContext narrowed to a non-null RequestContext.

Used by handlers whose spec declares auth.account === 'required' (with auth.actor === 'none') โ€” the dispatcher's pre-validation 401 gate guarantees request_context is populated before the handler runs, but the actor slot stays null because no acting resolution happened. Selected automatically by rpc_action's conditional return type for the account-grain tier.

inheritance

extends:
  • Omit<ActionContext, 'auth'>

auth

ActionContext
#

actions/action_rpc.ts view source

ActionContext

Per-request context provided to action handlers across every transport (HTTP RPC, WebSocket, REST bridge). Built once per dispatched action by perform_action and threaded into the handler.

auth is RequestContext | null โ€” handlers for authenticated actions can narrow via the dispatcher's authorization-phase guarantee.

Single handler context shape across every transport. Consumers inject domain deps via factory closures the same way HTTP RPC factories do.

auth

The authenticated identity, or null for public routes.

type RequestContext | null

request_id

The JSON-RPC request ID from the envelope.

connection_id

Stable per-socket connection id on WebSocket transport; undefined on HTTP RPC. Consumers key per-connection domain state on this directly; HTTP handlers ignore it.

type Uuid

db

Transaction-scoped when spec.side_effects is true (the dispatcher wraps in db.transaction); pool-level otherwise. Handlers that need rollback-resilient writes call deps.audit.emit(ctx, input), which captures the pool inside its closure.

type Db

pending_effects

Eager fire-and-forget queue โ€” push the in-flight Promise<void> for pool writes already running (audit emits, session touch, api-token usage tracking). Drained via flush_pending_effects after the handler returns.

type Array<Promise<void>>

post_commit_effects

Deferred post-commit thunks โ€” do not push directly; reach for emit_after_commit(ctx, fn) from pending_effects.ts. The flush site invokes each thunk after the handler (and any wrapping db.transaction) returns.

type Array<() => void | Promise<void>>

client_ip

Resolved client IP from the trusted-proxy middleware โ€” 'unknown' if the middleware wasn't in the stack (e.g. WS dispatch) or couldn't resolve. Thread into deps.audit.emit as ip: ctx.client_ip for every user-initiated action so RPC audit rows match the REST convention. Pass null only for rows written outside a request (e.g. the role_grant_offer_expire cleanup sweep in auth/cleanup.ts).

type string

credential_type

Credential channel the request arrived on ('session' | 'api_token' | 'daemon_token'), or null for anonymous requests. Same value the dispatcher's credential_types gate consumed at step 4 โ€” exposed here so handlers can record it in audit metadata (defense in depth: the gate may be loosened or bypassed in a future refactor, but the audit row preserves what actually authenticated the request).

type CredentialType | null

log

Logger instance.

type Logger

notify

Send a request-scoped JSON-RPC notification to the originator.

On streaming transports (WebSocket) this routes to the originating connection only. On the HTTP RPC transport this is a no-op with a DEV-mode warn โ€” non-streaming transports have no channel for mid- request notifications. The streams field on an ActionSpec names the notification method this handler is expected to emit.

type (method: string, params: unknown) => void

signal

AbortSignal that fires when the originating request is cancelled (client disconnect on HTTP, socket close or per-request cancel notification on WebSocket). Streaming handlers should check this for early termination.

type AbortSignal

ActionEvent
#

actions/action_event.ts view source

Action event that manages the lifecycle of an action through its state machine.

generics

TMethod

constraint string
default string

TPhase

constraint ActionEventPhase

TStep

constraint ActionEventStep

environment

type ActionEventEnvironment

readonly

spec

method narrows to TMethod so consumers passing a typed TApi to create_rpc_client get event.spec.method typed as the union of their API's method names rather than plain string. The runtime value comes from lookup_action_spec(method) keyed off the Proxy get trap, so the narrowing matches the dispatched method.

type ActionSpecUnion & {method: TMethod}

readonly

constructor

type new <TMethod extends string = string, TPhase extends ActionEventPhase = "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute", TStep extends ActionEventStep = "initial" | ... 3 more ... | "failed">(environment: ActionEventEnvironment, spec: { ...; } | ... 1 more ... | { ...; }, data: ActionEventDataUnion<...>): ActionEvent<...>

environment
spec
type { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }
data
type ActionEventDataUnion<TMethod>

toJSON

type (): ActionEventDataUnion<TMethod>

returns ActionEventDataUnion<TMethod>

observe

Subscribe a listener fired on every data transition.

type (listener: ActionEventChangeObserver<TMethod>): () => void

listener

called with (new_data, old_data, event) after each mutation

type ActionEventChangeObserver<TMethod>
returns () => void

unsubscribe function

set_data

Replace the event's data and notify observers.

type (new_data: ActionEventDataUnion<TMethod>): void

new_data
type ActionEventDataUnion<TMethod>
returns void

parse

Parse input data according to the action's schema.

type (): this

returns this

this for chaining with handle_async / handle_sync

throws
  • Error - if called from a step other than `initial`

handle_async

Execute the handler for the current phase.

type (): Promise<void>

returns Promise<void>
throws
  • Error - if called from a step other than `parsed` (or `failed`,

handle_sync

Execute handler synchronously (only for sync local_call actions).

type (): void

returns void
throws
  • Error - if the spec is not a sync `local_call`, or if called

transition

Transition to a new phase.

type (phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"): void

phase

the next phase to transition into

type "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"
returns void
throws
  • Error - if called from a step other than `handled` (or

is_complete

type (): boolean

returns boolean

update_progress

type (progress: unknown): void

progress
type unknown
returns void

set_request

type (request: { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }): void

request
type { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }
returns void

set_response

type (response: { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; } | { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<...>); message: string; data?: unknown; }; }): void

response
type { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; } | { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<...>); message: string; data?: unknown; }; }
returns void

set_notification

type (notification: { [x: string]: unknown; jsonrpc: "2.0"; method: string; params?: { [x: string]: unknown; } | undefined; }): void

notification
type { [x: string]: unknown; jsonrpc: "2.0"; method: string; params?: { [x: string]: unknown; } | undefined; }
returns void

ActionEventChangeObserver
#

ActionEventData
#

actions/action_event_data.ts view source

ZodObject<{ kind: ZodEnum<{ request_response: "request_response"; remote_notification: "remote_notification"; local_call: "local_call"; }>; phase: ZodEnum<{ send_request: "send_request"; ... 7 more ...; execute: "execute"; }>; ... 9 more ...; notification: ZodNullable<...>; }, $strict>

ActionEventDataUnion
#

ActionEventEnvironment
#

actions/action_event_types.ts view source

ActionEventEnvironment

executor

readonly

lookup_action_handler

type ( method: string, phase: ActionEventPhase, ) => ((event: any) => any) | undefined

lookup_action_spec

type (method: string) => ActionSpecUnion | undefined

log

type Logger | null
readonly

ActionEventLocalCallData
#

ActionEventOptions
#

ActionEventPhase
#

actions/action_spec.ts view source

ZodEnum<{ send_request: "send_request"; receive_request: "receive_request"; send_response: "send_response"; receive_response: "receive_response"; send_error: "send_error"; receive_error: "receive_error"; send: "send"; receive: "receive"; execute: "execute"; }>

ActionEventRemoteNotificationData
#

ActionEventRequestResponseData
#

ActionEventStep
#

ActionExecutor
#

ActionHandler
#

actions/action_rpc.ts view source

ActionHandler<TInput, TOutput>

Handler function for an RPC action.

Receives validated input and an ActionContext with per-request deps. Returns the output value (serialized to JSON by the wrapper).

generics

TInput

default any

TOutput

default any

ActionInitiator
#

ActionKind
#

ActionMethodEnumKind
#

ActionPeer
#

actions/action_peer.ts view source

environment

type ActionEventEnvironment

readonly

transports

type Transports

readonly

default_send_options

type Omit<ActionPeerSendOptions, 'signal'>

constructor

type new (options: ActionPeerOptions): ActionPeer

options

send

Resolve a transport (per-call name โ†’ default name โ†’ registry default) and forward the message. Catches unexpected throws and converts them to JSON-RPC error responses โ€” this method never throws.

type (message: { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }, options?: ActionPeerSendOptions | undefined): Promise<...>

message
type { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }
options?
type ActionPeerSendOptions | undefined
optional
returns Promise<{ [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; } | { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<...>); message: string; data?: unknown; }; }>

the response envelope for requests, or null for successful notifications (JsonrpcErrorResponse if the notification's transport send failed)

send

type (message: { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }, options?: ActionPeerSendOptions | undefined): Promise<...>

message
type { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }
options?
type ActionPeerSendOptions | undefined
optional
returns Promise<{ [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; } | { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<...>); message: string; data?: unknown; }; }>

send

type (message: { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }, options?: ActionPeerSendOptions | undefined): Promise<...>

message
type { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }
options?
type ActionPeerSendOptions | undefined
optional
returns Promise<{ [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; } | { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<...>); message: string; data?: unknown; }; }>

receive

Dispatch an inbound JSON-RPC message โ€” request, notification, or malformed envelope. Never throws; unexpected failures become JSON-RPC error responses.

type (message: unknown): Promise<{ [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; } | { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | ... 4 more ... | (number & $brand<...>); message: string; data?: unknown; }; } | { ...; } | null>

message
type unknown
returns Promise<{ [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; } | { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<...>); message: string; data?: unknown; }; } | { ...; } | n...

response message for requests, null for notifications, or an invalid_request error for malformed input

ActionPeerOptions
#

ActionPeerSendOptions
#

actions/action_peer.ts view source

ActionPeerSendOptions

Per-call options for ActionPeer.send. Extends TransportSendOptions with transport_name for per-call transport selection. The peer-wide default for any field lives on ActionPeerOptions.default_send_options โ€” set queue: true there once for client-authoritative peers and override per-call for exceptions (e.g. high-frequency position sync where stale replays are wrong).

inheritance

transport_name

ActionRegistry
#

actions/action_registry.ts view source

specs

type Array<ActionSpecUnion>

readonly

constructor

type new (specs: ({ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; })[]): ActionRegistry

specs
type ({ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; ...

ActionRegistryCompileResult
#

actions/compile_action_registry.ts view source

ActionRegistryCompileResult

Result returned by compile_action_registry.

action_map

Method โ†’ RpcAction lookup for dispatch. Only request_response specs with a handler land here โ€” kind-polymorphic input arrays (the WebSocket dispatcher's actions: ReadonlyArray<Action>) pass remote_notification / handler-less specs through unchanged.

type Map<string, RpcAction>

ActionRouteOptions
#

actions/action_bridge.ts view source

ActionRouteOptions

Options for deriving a RouteSpec from an ActionSpec.

path

type string

handler

params

URL path parameter schema. Use z.strictObject() with string fields matching :param segments.

type z.ZodObject

query

URL query parameter schema. Use z.strictObject() with string fields.

type z.ZodObject

http_method

Override the default HTTP method (default: side_effects โ†’ POST, else GET).

auth

Override the route's auth shape โ€” defaults to the action spec's auth (the canonical four-axis shape from http/auth_shape.ts is shared verbatim between action specs and route specs, so no mapping is needed).

errors

Handler-specific error schemas (HTTP status code โ†’ Zod schema). Transport-specific โ€” not on ActionSpec.

ActionSideEffects
#

ActionSpec
#

actions/action_spec.ts view source

ZodObject<{ method: ZodString; kind: ZodEnum<{ request_response: "request_response"; remote_notification: "remote_notification"; local_call: "local_call"; }>; initiator: ZodEnum<...>; ... 8 more ...; rate_limit: ZodOptional<...>; }, $strict>

ActionSpecUnion
#

actions/action_spec.ts view source

ZodUnion<readonly [ZodObject<{ method: ZodString; initiator: ZodEnum<{ frontend: "frontend"; backend: "backend"; both: "both"; }>; side_effects: ZodBoolean; input: ZodCustom<ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>, ZodType<...>>; ... 7 more ...; async: ZodDefault<...>; }, $strict>, ZodObject<....

Actor
#

auth/account_schema.ts view source

Actor

Actor โ€” the entity that acts. Owns cells, holds role_grants, appears in audit trails.

id

type Uuid

account_id

type Uuid

name

type string

created_at

type string

updated_at

type string | null

updated_by

type Uuid | null

ACTOR_INDEX
#

actor_lookup_action_spec
#

auth/actor_lookup_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "none"; }; side_effects: false; input: ZodObject<{ ids: ZodArray<$ZodBranded<ZodUUID, "Uuid", "out">>; }, $strict>; output: ZodObject<...>; async: true; rate_limit: "account"; description: string; }

ACTOR_LOOKUP_IDS_MAX
#

ACTOR_NAME_LOWER_INDEX
#

auth/auth_ddl.ts view source

"\nCREATE INDEX IF NOT EXISTS idx_actor_name_lower ON actor (LOWER(name) text_pattern_ops)"

Functional index on LOWER(actor.name) supporting case-insensitive prefix search by actor_search (LOWER(name) LIKE LOWER(query) || '%'). text_pattern_ops keeps the LIKE-prefix pattern index-eligible โ€” without it the planner falls back to a sequential scan once the table grows.

ACTOR_SCHEMA
#

auth/auth_ddl.ts view source

"\nCREATE TABLE IF NOT EXISTS actor (\n id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n account_id UUID NOT NULL REFERENCES account(id) ON DELETE CASCADE,\n name TEXT NOT NULL,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n updated_at TIMESTAMPTZ,\n updated_by UUID REFERENCES actor(id) ON DELETE SET NULL\...

actor_search_action_spec
#

auth/actor_search_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "none"; }; side_effects: false; input: ZodObject<{ query: ZodString; scope_ids: ZodOptional<ZodArray<$ZodBranded<ZodUUID, "Uuid", "out">>>; limit: ZodOptional<...>; }, $strict>; ... 4 more ...; description: string; }

ACTOR_SEARCH_LIMIT_DEFAULT
#

ACTOR_SEARCH_LIMIT_MAX
#

ACTOR_SEARCH_QUERY_LENGTH_MAX
#

auth/actor_search_action_specs.ts view source

50

Hard cap on the query string length. Long inputs offer no extra search value once they exceed actor.name realistic lengths, and a low cap keeps the per-request work bounded for pathological inputs.

ActorActionHandler
#

ActorLookupActionDeps
#

ActorLookupEntryJson
#

auth/actor_lookup_action_specs.ts view source

ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; username: ZodString; display_name: ZodOptional<ZodString>; }, $strict>

One resolved actor row. display_name omitted when blank.

ActorLookupInput
#

ActorLookupOutput
#

ActorLookupRow
#

auth/actor_lookup_queries.ts view source

ActorLookupRow

Row shape returned to handlers โ€” wire mapping happens at the action layer.

id

type Uuid

username

type string

display_name

type string | null

ActorNotOnAccountError
#

ActorRequiredError
#

http/error_schemas.ts view source

ZodObject<{ error: ZodLiteral<"actor_required">; available: ZodArray<ZodObject<{ id: ZodString; name: ZodString; }, $loose>>; }, $loose>

Authorization-phase failure shapes. Surfaced when the dispatcher's apply_authorization_phase rejects a request before the handler runs โ€” the route is acting-aware (input declares acting?: ActingActor or auth requires role_grants), but actor resolution failed.

400: actor_required (with available[]) for unspecified-actor on a multi-actor account; actor_not_on_account for a supplied actor id that doesn't belong to the authenticated account.

500: no_actors_on_account for a signup-invariant violation (the actor list enumerated empty); account_vanished for a torn-read race (account/actor row deleted between credential validation and the dispatcher's follow-up read).

Used by derive_error_schemas when auth.actor !== 'none' so the merged error surface matches what the dispatcher actually emits.

ActorSearchActionDeps
#

ActorSearchInput
#

ActorSearchOutput
#

ActorSearchQueryInput
#

auth/actor_search_queries.ts view source

ActorSearchQueryInput

Inputs for query_actor_search.

query

Case-insensitive prefix string. Must be non-empty (action layer enforces min(1)).

type string

scope_ids

When non-empty, restrict to actors holding an active role_grant on one of these scope ids. When empty / omitted, no scope filter is applied โ€” the handler is responsible for the admin gate.

type ReadonlyArray<Uuid>

limit

Maximum rows to return. The handler clamps to ACTOR_SEARCH_LIMIT_MAX.

type number

ActorSummaryJson
#

auth/account_schema.ts view source

ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; name: ZodString; }, $strict>

Zod schema for the actor summary returned in admin account listings.

admin_account_list_action_spec
#

auth/admin_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "required"; roles: string[]; }; side_effects: false; input: ZodDefault<ZodObject<{ acting: ZodOptional<$ZodBranded<ZodUUID, "Uuid", "out">>; limit: ZodOptional<...>; offset: ZodOptional<...>; }, $strict>>; output: ...

rate_limit: 'account' bounds admin-side scraping of the account table via (limit, offset) walking โ€” admin trust is not a substitute for a read-rate cap when the listing is paginated and cross-account (yields every account + actor + active role_grant in the system).

ADMIN_ACCOUNT_LIST_DEFAULT_LIMIT
#

ADMIN_ACCOUNT_LIST_LIMIT_MAX
#

admin_accounts_rpc_context
#

ui/admin_accounts_state.svelte.ts view source

{ get: () => () => AdminAccountsRpc | null; set: (value?: (() => AdminAccountsRpc | null) | undefined) => () => AdminAccountsRpc | null; }

Svelte context carrying the reactive AdminAccountsRpc accessor. The provisioner (typically the admin route shell) calls set(() => rpc); consumers read with const get_rpc = admin_accounts_rpc_context.get(); and either pass the accessor straight to AdminAccountsState/ AdminSessionsState or wrap it with const rpc = $derived(get_rpc()); for direct RPC calls. Unset context falls back to () => null so components mounted without a provisioner surface the usual "rpc adapter not wired" path.

admin_invites_rpc_context
#

admin_only_field_blocklist
#

admin_session_list_action_spec
#

auth/admin_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "required"; roles: string[]; }; side_effects: false; input: ZodDefault<ZodObject<{ acting: ZodOptional<$ZodBranded<ZodUUID, "Uuid", "out">>; }, $strict>>; output: ZodObject<...>; async: true; description: string; r...

rate_limit: 'account' bounds cross-account scraping of every active auth_session row โ€” no pagination, but the read is unbounded across accounts and reveals one row per live cookie globally.

admin_session_revoke_all_action_spec
#

auth/admin_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "required"; roles: string[]; }; side_effects: true; input: ZodObject<{ account_id: $ZodBranded<ZodUUID, "Uuid", "out">; acting: ZodOptional<...>; }, $strict>; output: ZodObject<...>; async: true; description: strin...

admin_token_revoke_all_action_spec
#

auth/admin_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "required"; roles: string[]; }; side_effects: true; input: ZodObject<{ account_id: $ZodBranded<ZodUUID, "Uuid", "out">; acting: ZodOptional<...>; }, $strict>; output: ZodObject<...>; async: true; description: strin...

AdminAccountEntryJson
#

auth/account_schema.ts view source

ZodObject<{ account: ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; username: ZodPipe<ZodString, ZodTransform<string, string>>; ... 4 more ...; updated_by: ZodNullable<...>; }, $strict>; actor: ZodNullable<...>; role_grants: ZodArray<...>; pending_offers: ZodArray<...>; }, $strict>

Zod schema for an admin account listing entry (account + actor + role_grants + pending offers).

AdminAccountJson
#

auth/account_schema.ts view source

ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; username: ZodPipe<ZodString, ZodTransform<string, string>>; email: ZodNullable<ZodEmail>; email_verified: ZodBoolean; created_at: ZodString; updated_at: ZodString; updated_by: ZodNullable<...>; }, $strict>

Zod schema for admin-facing account data โ€” extends SessionAccountJson with audit fields.

AdminAccountListInput
#

auth/admin_action_specs.ts view source

ZodDefault<ZodObject<{ acting: ZodOptional<$ZodBranded<ZodUUID, "Uuid", "out">>; limit: ZodOptional<ZodNullable<ZodNumber>>; offset: ZodOptional<...>; }, $strict>>

Input for admin_account_list.

AdminAccountListOptions
#

AdminAccountListOutput
#

auth/admin_action_specs.ts view source

ZodObject<{ accounts: ZodArray<ZodObject<{ account: ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; username: ZodPipe<ZodString, ZodTransform<string, string>>; ... 4 more ...; updated_by: ZodNullable<...>; }, $strict>; actor: ZodNullable<...>; role_grants: ZodArray<...>; pending_offers: ZodArray<...>; }, $stric...

Output for admin_account_list.

AdminAccounts
#

AdminAccountsRpc
#

ui/admin_accounts_state.svelte.ts view source

AdminAccountsRpc

Narrow RPC surface consumed by AdminAccountsState. Consumers adapt their typed RPC client (e.g. a create_rpc_client Proxy) to this shape โ€” the state class stays decoupled from the client's Result return type so tests can inject plain-function stubs. Mirrors the RoleGrantOffersRpc pattern.

Every operation flows through RPC: the listing reuses admin_account_list, grant reuses role_grant_offer_create, revoke and retract have dedicated actions, and the session / token revoke-all mutations reuse admin_session_revoke_all and admin_token_revoke_all. Without the adapter the state class cannot fetch, grant, revoke, retract, or revoke-all sessions/tokens.

Method signatures track the underlying action specs โ€” Uuid-branded ids propagate from the wire through the state class to the components. The adapter built by create_admin_rpc_adapters therefore needs zero casts to bridge to the typed throwing Proxy.

list_accounts

type () => Promise<AdminAccountListOutput>

list_sessions

type () => Promise<AdminSessionListOutput>

create_role_grant

type (params: RoleGrantOfferCreateInput) => Promise<RoleGrantOfferCreateOutput>

revoke_role_grant

type (params: RoleGrantRevokeInput) => Promise<RoleGrantRevokeOutput>

retract_offer

type (offer_id: Uuid) => Promise<RoleGrantOfferOkOutput>

session_revoke_all

type (params: AdminSessionRevokeAllInput) => Promise<AdminSessionRevokeAllOutput>

token_revoke_all

type (params: AdminTokenRevokeAllInput) => Promise<AdminTokenRevokeAllOutput>

AdminAccountsState
#

ui/admin_accounts_state.svelte.ts view source

list

readonly

grant

readonly

revoke

readonly

retract

readonly

accounts

type Array<AdminAccountEntryJson>

grantable_roles

type Array<RoleName>

account_count

type number

readonly

constructor

type new (options?: AdminAccountsStateOptions | undefined): AdminAccountsState

options?
type AdminAccountsStateOptions | undefined
optional

fetch

type (): Promise<void>

returns Promise<void>

submit_grant

Offer the role to the recipient via the role_grant_offer_create RPC. Server returns the pending offer; the recipient must accept before the role_grant materializes. Returns the offer payload on success so callers can drive follow-up UX (e.g. seed RoleGrantOffersState.outgoing).

A re-offer from the same admin to the same (account, role) refreshes the existing pending row โ€” the returned offer id is stable across those calls.

to_actor_id (optional) narrows the offer to a specific actor on account_id; the keyed-slot key stays at account_id:role for the account-grain default (so existing consumers keep working) and becomes account_id:role:to_actor_id when actor-targeted, so the two variants can be in flight without colliding on the per-row spinner.

type (account_id: string & $brand<"Uuid">, role: string, to_actor_id?: (string & $brand<"Uuid">) | null | undefined): Promise<{ id: string & $brand<"Uuid">; ... 14 more ...; resulting_role_grant_id: (string & $brand<...>) | null; } | undefined>

account_id
type string & $brand<"Uuid">
role
type string
to_actor_id?
type (string & $brand<"Uuid">) | null | undefined
optional
returns Promise<{ id: string & $brand<"Uuid">; from_actor_id: string & $brand<"Uuid">; to_account_id: string & $brand<"Uuid">; to_actor_id: (string & $brand<"Uuid">) | null; ... 11 more ...; resulting_role_grant_id: (string & $brand<...>) | null; } | undefined>

submit_revoke

Revoke an active role_grant via the role_grant_revoke RPC.

actor_id is the natural key โ€” role_grants are actor-scoped, and the admin UI reads row.actor.id straight from the listing, so the state class takes it directly rather than deriving it from account_id. The optional reason is stamped on role_grant.revoked_reason and surfaced on the revokee's WS notification.

type (actor_id: string & $brand<"Uuid">, role_grant_id: string & $brand<"Uuid">, reason?: string | null | undefined): Promise<void>

actor_id
type string & $brand<"Uuid">
role_grant_id
type string & $brand<"Uuid">
reason?
type string | null | undefined
optional
returns Promise<void>

submit_retract

Retract a pending offer the admin issued via the role_grant_offer_retract RPC. The action handles auth, audit, and the role_grant_offer_retracted WS notification.

After success, refetches the listing so pending_offers drops the row and the "+ {role}" button un-hides.

type (offer_id: string & $brand<"Uuid">): Promise<void>

offer_id
type string & $brand<"Uuid">
returns Promise<void>

AdminAccountsStateOptions
#

ui/admin_accounts_state.svelte.ts view source

AdminAccountsStateOptions

get_rpc

Reactive accessor for the RPC adapter; returns null when unwired. Matches RoleGrantOffersStateOptions.account_id / actor_id pattern โ€” lets the component pass a $props()-sourced rpc without tripping Svelte's state_referenced_locally warning.

type () => AdminAccountsRpc | null

AdminActionOptions
#

auth/admin_actions.ts view source

AdminActionOptions

roles

Role schema result from create_role_schema(). Defaults to builtin roles only. Used to derive grantable_roles (the subset whose RoleSpec.grant_paths includes 'admin') returned by admin_account_list.

app_settings

Mutable in-memory app settings ref โ€” typically ctx.app_settings from AppServerContext. When provided, the factory wires the app_settings_get and app_settings_update handlers; the update handler mutates this ref so signup middleware reads the new value without a DB round trip. When omitted, those two methods have no handler and RPC dispatch returns method_not_found.

connection_closer

Live-connection closer โ€” when set, admin_session_revoke_all and admin_token_revoke_all handlers eagerly close affected WebSocket sockets for the target account BEFORE emitting the corresponding audit event. Mirrors the self-service surface (see AccountActionOptions.connection_closer). BackendWebsocketTransport satisfies this interface structurally. When absent, only the listener-based close (transports_ws_auth_guard) runs.

type ConnectionCloser | null

AdminAuditLog
#

AdminInvites
#

AdminInvitesRpc
#

ui/admin_invites_state.svelte.ts view source

AdminInvitesRpc

Narrow RPC surface consumed by AdminInvitesState. Consumers adapt their typed RPC client to this shape. error.data.reason on thrown errors carries the ERROR_INVITE_* constant โ€” handled by the caller when user-friendly messages are needed. Method signatures track the wire spec types directly so the adapter needs no casts.

list

type () => Promise<InviteListOutput>

create

type (params: InviteCreateInput) => Promise<InviteCreateOutput>

delete

type (params: InviteDeleteInput) => Promise<InviteDeleteOutput>

AdminInvitesState
#

ui/admin_invites_state.svelte.ts view source

list

readonly

create

readonly

remove

readonly

invites

type Array<InviteWithUsernamesJson>

invite_count

type number

readonly

unclaimed_count

type number

readonly

constructor

type new (options?: AdminInvitesStateOptions | undefined): AdminInvitesState

options?
type AdminInvitesStateOptions | undefined
optional

fetch

type (): Promise<void>

returns Promise<void>

submit_create

type (email?: string | undefined, username?: string | undefined): Promise<boolean>

email?
type string | undefined
optional
username?
type string | undefined
optional
returns Promise<boolean>

submit_delete

type (id: string & $brand<"Uuid">): Promise<void>

id
type string & $brand<"Uuid">
returns Promise<void>

AdminInvitesStateOptions
#

ui/admin_invites_state.svelte.ts view source

AdminInvitesStateOptions

get_rpc

Reactive accessor for the RPC adapter. null disables all operations (the state reports a descriptive error when mutations/fetches fire).

type () => AdminInvitesRpc | null

AdminOverview
#

AdminRoleGrantHistory
#

AdminRpcAdapters
#

AdminRpcApi
#

ui/admin_rpc_adapters.ts view source

AdminRpcApi

The wire-method surface this module needs from the typed throwing RPC client. Every method returns the unwrapped value or throws an Error carrying the JSON-RPC {code, message, data?} shape โ€” i.e. the ThrowingApi<...> view of the corresponding action specs.

Consumers pass the typed throwing Proxy returned by create_frontend_rpc_client directly. Structural typing means any superset (e.g. the consumer's full ThrowingApi<ActionsApi>) is assignable as long as these methods are present at these signatures.

admin_account_list

type () => Promise<AdminAccountListOutput>

admin_session_list

type () => Promise<AdminSessionListOutput>

admin_session_revoke_all

type ( input: AdminSessionRevokeAllInput, ) => Promise<AdminSessionRevokeAllOutput>

admin_token_revoke_all

type (input: AdminTokenRevokeAllInput) => Promise<AdminTokenRevokeAllOutput>

audit_log_list

type (input: AuditLogListInput) => Promise<AuditLogListOutput>

audit_log_role_grant_history

type ( input: AuditLogRoleGrantHistoryInput, ) => Promise<AuditLogRoleGrantHistoryOutput>

invite_list

type () => Promise<InviteListOutput>

invite_create

type (input: InviteCreateInput) => Promise<InviteCreateOutput>

invite_delete

type (input: InviteDeleteInput) => Promise<InviteDeleteOutput>

app_settings_get

type () => Promise<AppSettingsGetOutput>

app_settings_update

type (input: AppSettingsUpdateInput) => Promise<AppSettingsUpdateOutput>

role_grant_offer_create

type ( input: RoleGrantOfferCreateInput, ) => Promise<RoleGrantOfferCreateOutput>

role_grant_offer_retract

type (input: RoleGrantOfferRetractInput) => Promise<RoleGrantOfferOkOutput>

role_grant_revoke

type (input: RoleGrantRevokeInput) => Promise<RoleGrantRevokeOutput>

AdminSessionJson
#

auth/audit_log_schema.ts view source

ZodObject<{ id: ZodString; account_id: $ZodBranded<ZodUUID, "Uuid", "out">; created_at: ZodString; expires_at: ZodString; last_seen_at: ZodString; username: ZodString; }, $strict>

Zod schema for admin session listing (session + username).

AdminSessionListInput
#

AdminSessionListOutput
#

auth/admin_action_specs.ts view source

ZodObject<{ sessions: ZodArray<ZodObject<{ id: ZodString; account_id: $ZodBranded<ZodUUID, "Uuid", "out">; created_at: ZodString; expires_at: ZodString; last_seen_at: ZodString; username: ZodString; }, $strict>>; }, $strict>

Output for admin_session_list. Cross-account listing; fan-out already scoped by role auth.

AdminSessionRevokeAllInput
#

auth/admin_action_specs.ts view source

ZodObject<{ account_id: $ZodBranded<ZodUUID, "Uuid", "out">; acting: ZodOptional<$ZodBranded<ZodUUID, "Uuid", "out">>; }, $strict>

Input for admin_session_revoke_all.

AdminSessionRevokeAllOutput
#

AdminSessions
#

AdminSessionsState
#

ui/admin_sessions_state.svelte.ts view source

list

readonly

revoke_sessions

readonly

revoke_tokens

readonly

sessions

type Array<AdminSessionJson>

active_count

type number

readonly

constructor

type new (options?: AdminSessionsStateOptions | undefined): AdminSessionsState

options?
type AdminSessionsStateOptions | undefined
optional

fetch

type (): Promise<void>

returns Promise<void>

submit_revoke_sessions

type (account_id: string & $brand<"Uuid">): Promise<void>

account_id
type string & $brand<"Uuid">
returns Promise<void>

submit_revoke_tokens

type (account_id: string & $brand<"Uuid">): Promise<void>

account_id
type string & $brand<"Uuid">
returns Promise<void>

AdminSessionsStateOptions
#

ui/admin_sessions_state.svelte.ts view source

AdminSessionsStateOptions

Options for AdminSessionsState.

The RPC adapter drives every operation (listing + the two revoke-all mutations). Without it, the slots' run() calls fail with 'rpc adapter not wired' on error.

get_rpc

Reactive accessor for the RPC adapter; returns null when unwired. Mirrors AdminAccountsStateOptions.get_rpc so a single adapter instance backs both states without tripping Svelte's state_referenced_locally warning.

type () => AdminAccountsRpc | null

AdminSettings
#

AdminSurface
#

AdminTokenRevokeAllInput
#

auth/admin_action_specs.ts view source

ZodObject<{ account_id: $ZodBranded<ZodUUID, "Uuid", "out">; acting: ZodOptional<$ZodBranded<ZodUUID, "Uuid", "out">>; }, $strict>

Input for admin_token_revoke_all.

AdminTokenRevokeAllOutput
#

AdversarialHeaderCase
#

testing/adversarial_headers.ts view source

AdversarialHeaderCase

A header-level attack case for middleware stack testing.

name

type string

headers

type Record<string, string>

expected_status

type number

expected_error

type string

expected_error_schema

Zod schema to validate error response body against. Defaults to ApiError when expected_error is set.

type z.ZodType

validate_expectation

Whether the request should reach token validation or be short-circuited by earlier middleware.

type 'called' | 'not_called'

AdversarialTestOptions
#

testing/attack_surface.ts view source

AdversarialTestOptions

Options for adversarial test runners (auth enforcement and input validation).

build

Build the app surface bundle (surface + route specs + middleware specs).

type () => AppSurfaceSpec

roles

All roles in the app (e.g. ['admin', 'keeper']).

type Array<string>

Alignment
#

all_account_action_specs
#

auth/account_action_specs.ts view source

{ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; }[]

All self-service account action specs โ€” a codegen-ready registry. Consumers spread this into their own action-spec array to include account methods in a typed client surface.

all_actor_lookup_action_specs
#

auth/actor_lookup_action_specs.ts view source

readonly [{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "none"; }; side_effects: false; input: ZodObject<{ ids: ZodArray<$ZodBranded<ZodUUID, "Uuid", "out">>; }, $strict>; output: ZodObject<...>; async: true; rate_limit: "account"; description: string; }]

All actor_lookup action specs โ€” independent opt-in registry. Consumers spread alongside all_standard_action_specs if they want the labels arc; not folded into the standard bundle because consumers without a byline surface can skip it.

all_actor_search_action_specs
#

auth/actor_search_action_specs.ts view source

readonly [{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "none"; }; side_effects: false; input: ZodObject<{ query: ZodString; scope_ids: ZodOptional<ZodArray<$ZodBranded<...>>>; limit: ZodOptional<...>; }, $strict>; ... 4 more ...; description: string; }]

All actor_search action specs โ€” independent opt-in registry. Like all_actor_lookup_action_specs, not folded into all_standard_action_specs because consumers without a person-target picker can skip it.

all_admin_action_specs
#

auth/admin_action_specs.ts view source

{ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; }[]

All admin action specs โ€” a codegen-ready registry. Consumers spread this into their own action-spec array to include admin methods in a typed client surface. Always includes the two app-settings specs; the runtime factory only wires their handlers when AdminActionOptions.app_settings is provided.

all_fuz_auth_action_spec_registries
#

auth/all_action_spec_registries.ts view source

readonly FuzAuthActionSpecRegistry[]

Every fuz_auth action-spec registry, in dependency-stable order.

Update this list when a new fuz_auth registry lands. The walker tests (action_spec_input_invariants.test.ts, all_action_spec_registries.acting_biconditional.test.ts) iterate over it โ€” a missing entry silently skips coverage, which is the failure mode the registry-of-registries shape exists to prevent.

all_role_grant_offer_action_specs
#

auth/role_grant_offer_action_specs.ts view source

{ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; }[]

All role-grant-offer action specs โ€” a codegen-ready registry. Consumers spread this into their own action-spec array to include offer lifecycle + revoke methods in a typed client surface.

all_self_service_role_action_specs
#

auth/self_service_role_action_specs.ts view source

readonly { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; }[]

All self-service role action specs โ€” a codegen-ready registry. Single-element post-unification, kept for symmetry with the other all_*_action_specs exports so codegen and frontend bundles import the same shape.

all_standard_action_specs
#

auth/standard_action_specs.ts view source

readonly { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; }[]

Combined spec registry for the standard RPC surface (admin + role_grant_offer + account). Symmetric with create_standard_rpc_actions.

Spec count is the sum of the three sub-registries. Adding a method to any sub-registry surfaces here automatically.

API_TOKEN_ID_REGEX
#

API_TOKEN_INDEX
#

API_TOKEN_PREFIX
#

API_TOKEN_SCHEMA
#

auth/auth_ddl.ts view source

"\nCREATE TABLE IF NOT EXISTS api_token (\n id TEXT PRIMARY KEY,\n account_id UUID NOT NULL REFERENCES account(id) ON DELETE CASCADE,\n name TEXT NOT NULL,\n token_hash TEXT NOT NULL,\n expires_at TIMESTAMPTZ,\n last_used_at TIMESTAMPTZ,\n last_used_ip TEXT,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()\n)"

ApiError
#

ApiToken
#

auth/account_schema.ts view source

ApiToken

API token for CLI/programmatic access.

id

type string

account_id

type Uuid

name

type string

token_hash

type string

expires_at

type string | null

last_used_at

type string | null

last_used_ip

type string | null

created_at

type string

ApiTokenId
#

ApiTokenQueryDeps
#

app_settings_get_action_spec
#

auth/admin_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "required"; roles: string[]; }; side_effects: false; input: ZodDefault<ZodObject<{ acting: ZodOptional<$ZodBranded<ZodUUID, "Uuid", "out">>; }, $strict>>; output: ZodObject<...>; async: true; description: string; }

app_settings_rpc_context
#

APP_SETTINGS_SCHEMA
#

auth/auth_ddl.ts view source

"\nCREATE TABLE IF NOT EXISTS app_settings (\n id INTEGER PRIMARY KEY DEFAULT 1 CHECK (id = 1),\n open_signup BOOLEAN NOT NULL DEFAULT false,\n updated_at TIMESTAMPTZ,\n updated_by UUID\n)"

APP_SETTINGS_SEED
#

app_settings_update_action_spec
#

auth/admin_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "required"; roles: string[]; }; side_effects: true; input: ZodObject<{ open_signup: ZodBoolean; acting: ZodOptional<...>; }, $strict>; output: ZodObject<...>; async: true; description: string; rate_limit: "account"...

AppBackend
#

server/app_backend.ts view source

AppBackend

Result of create_app_backend() โ€” database metadata + deps bundle.

This is the initialized backend, not the HTTP server. Pass it to create_app_server() to assemble the Hono app.

deps

type AppDeps

db_type

type DbType

db_name

type string

migration_results

Migration results from create_app_backend โ€” auth migrations plus any consumer namespaces passed via migration_namespaces.

type ReadonlyArray<MigrationResult>
readonly

close

Close the database connection. Bound to the actual driver.

type () => Promise<void>

AppDeps
#

auth/deps.ts view source

AppDeps

Stateless capabilities bundle for fuz_app backends.

Injectable and swappable per environment (production vs test). Does not contain config (static values) or runtime state (mutable refs).

stat

Get file/directory stats, or null if path doesn't exist.

type (path: string) => Promise<StatResult | null>

read_text_file

Read a file as text.

type (path: string) => Promise<string>

delete_file

Delete a file.

type (path: string) => Promise<void>

keyring

HMAC-SHA256 cookie signing keyring.

type Keyring

password

Password hashing operations. Use argon2_password_deps in production.

db

Database instance.

type Db

log

Structured logger instance.

type Logger

audit

Bound audit emitter. Closes over the pool, the on_audit_event subscriber chain, and the optional AuditLogConfig. Built once at backend assembly via create_audit_emitter so handlers can never accidentally write audits against the request transaction โ€” there is no pool slot on the handler context.

apply_authorization_phase
#

auth/request_context.ts view source

(deps: QueryDeps, account_id: string | null, auth: { account: "none" | "optional" | "required"; actor: "none" | "optional" | "required"; roles?: readonly string[] | undefined; credential_types?: readonly string[] | undefined; }, acting_value: string | undefined): Promise<...>

Apply the dispatcher's authorization phase against the flat-record RouteAuth shape. Shared by the route-spec wrapper, the HTTP RPC dispatcher, and the per-message WS dispatcher. Phase order: pre-validation 401 โ†’ input validation 400 โ†’ authorization phase โ†’ post-authorization 403.

Pure data โ€” the function does not touch a Hono context. Each transport passes account_id (extracted from its own credential surface) and binds the returned AuthorizationResult to its wire shape. The REST pipeline additionally writes REQUEST_CONTEXT_KEY on c for downstream require_role / require_credential_types middleware that still reads the resolved context off the Hono context.

Branching by auth.account ร— auth.actor:

- Both 'none' โ†’ {ok: true, request_context: null}. Public actions never see a RequestContext. - account_id == null on any non-public route โ†’ same null request_context. The 'required' callers were already rejected at the pre-validation gate in the dispatcher; only genuine anonymous access on an 'optional' axis lands here. - actor === 'none' โ†’ builds account-only context via build_account_context. Null lookup โ†’ account_vanished 500 failure. - actor === 'required' โ†’ resolves the actor from acting_value (or single-actor account); failures map to 400 / 500. - actor === 'optional' โ†’ same as 'required' except multi-actor accounts without an acting value fall back to account-only context (no actor_required 400). Bad acting ids still 400.

500 branches stay distinct: ERROR_NO_ACTORS_ON_ACCOUNT (signup invariant violation), ERROR_ACCOUNT_VANISHED (torn read after resolve).

deps

account_id

type string | null

auth

type { account: "none" | "optional" | "required"; actor: "none" | "optional" | "required"; roles?: readonly string[] | undefined; credential_types?: readonly string[] | undefined; }

acting_value

type string | undefined

returns

Promise<AuthorizationResult>

apply_middleware_specs
#

http/route_spec.ts view source

(app: Hono<BlankEnv, BlankSchema, "/">, specs: MiddlewareSpec[]): void

Apply named middleware specs to a Hono app.

app

type Hono<BlankEnv, BlankSchema, "/">

specs

type MiddlewareSpec[]

returns

void

apply_route_specs
#

http/route_spec.ts view source

(app: Hono<BlankEnv, BlankSchema, "/">, specs: RouteSpec[], resolve_auth_guards: AuthGuardResolver, log: Logger, db: Db, authorize?: AuthorizationHandler | undefined): void

Apply route specs to a Hono app.

For each spec: resolves auth to guards via the provided resolver, adds input validation middleware (for routes with non-null input schemas), runs the optional authorization phase to resolve the acting actor + build the request context, wraps handler with DEV-only output and error validation, wraps with error catch layer (catches ThrownJsonrpcError and generic errors), and registers the route.

Per-route middleware order: params โ†’ query โ†’ pre-validation auth guards (401) โ†’ input validation (400) โ†’ authorization phase โ†’ post-authorization auth guards (403) โ†’ handler. The 401 check runs before any body parsing so unauthenticated callers never see route-shape information from parse failures. Input validation runs before the authorization phase (validate first, authorize after) so the authorization phase reads c.var.validated_input.acting as a typed Zod field instead of pre-parsing the raw body. Role / credential-type denials still surface 403 last; trade-off is that authenticated-but-unauthorized callers can distinguish 400 (validation) from 403 (authorization), a defense-in-depth concession deemed acceptable because the route surface is public via spec/codegen JSON.

Each handler receives a RouteContext with: - db: transaction-scoped when RouteSpec.transaction is true; pool-level otherwise - pending_effects: eager fire-and-forget pool-write queue - post_commit_effects: deferred-thunk queue (push via emit_after_commit)

Also enforces registry-time invariant 2 from the auth-shape design: auth.actor !== 'none' โŸบ input or query declares acting?: ActingActor. REST is bi-located (GETs declare acting on query, mutations on input), so the check passes both slots; the action-dispatcher registries (compile_action_registry) share the same helper with input only โ€” ActionSpec has no query shape.

app

type Hono<BlankEnv, BlankSchema, "/">

specs

type RouteSpec[]

resolve_auth_guards

log

type Logger

db

used for transaction wrapping and RouteContext

type Db

authorize?

optional authorization phase; runs after input validation

type AuthorizationHandler | undefined
optional

returns

void

throws

  • Error - if two specs share the same `method` + `path` (each combination must be unique), or if any spec violates the actor-acting biconditional

AppServer
#

server/app_server.ts view source

AppServer

Result of create_app_server().

app

type Hono

surface_spec

Surface spec โ€” serializable surface + raw specs that produced it.

bootstrap_status

app_settings

Global app settings (mutable ref โ€” mutated by settings admin route).

migration_results

Migration results from create_app_backend (auth + any migration_namespaces passed there).

type ReadonlyArray<MigrationResult>

audit_sse

Factory-managed audit log SSE. Non-null when the audit_log_sse option was passed to create_app_server, null when omitted. Use require_audit_sse(server) to assert the invariant.

type AuditLogSse | null

ws_endpoints

Path-keyed map of mounted WS endpoints. Each value is the BackendWebsocketTransport create_app_server registered connections against โ€” supplied via WsEndpointSpec.transport or auto-created when omitted. Retain for broadcast / fan-out:

app_server.ws_endpoints['/api/ws'].send_to_account(account_id, msg);

Empty when no ws_endpoints were mounted.

type Readonly<Record<string, BackendWebsocketTransport>>

close

Close the database connection. Propagated from AppBackend.

type () => Promise<void>

AppServerContext
#

server/app_server.ts view source

AppServerContext

Context passed to create_route_specs.

deps

type AppDeps

backend

bootstrap_status

session_options

type SessionOptions<string>

ip_rate_limiter

Shared IP rate limiter (from options). null when not configured.

type RateLimiter | null

login_account_rate_limiter

Per-account login rate limiter (from options). null when not configured.

type RateLimiter | null

signup_account_rate_limiter

Per-account signup rate limiter (from options). null when not configured.

type RateLimiter | null

action_ip_rate_limiter

Per-IP action-dispatcher rate limiter โ€” shared across HTTP RPC + WS. null when not configured.

type RateLimiter | null

action_account_rate_limiter

Per-actor action-dispatcher rate limiter โ€” shared across HTTP RPC + WS. null when not configured.

type RateLimiter | null

app_settings

Global app settings (mutable ref โ€” mutated by settings admin route).

audit_sse

Factory-managed audit log SSE. Non-null when the audit_log_sse option was passed to create_app_server, null when omitted. Use require_audit_sse(ctx) to assert the invariant.

type AuditLogSse | null

AppServerOptions
#

server/app_server.ts view source

AppServerOptions

Configuration for create_app_server().

Requires a pre-initialized AppBackend from create_app_backend(). Two explicit steps: init backend then assemble server.

backend

Pre-initialized backend from create_app_backend().

session_options

Session options for cookie-based auth.

type SessionOptions<string>

allowed_origins

Parsed allowed origin patterns.

type Array<RegExp>

proxy

Trusted proxy options.

type { trusted_proxies: Array<string>; get_connection_ip: (c: Context) => string | undefined; }

ip_rate_limiter

Shared IP rate limiter for login, bootstrap, and bearer auth. Omit or undefined to use a default limiter (5 attempts per 15 minutes). Pass null to explicitly disable rate limiting. Also available on AppServerContext for route factory callbacks.

type RateLimiter | null

login_account_rate_limiter

Per-account rate limiter for login attempts. Omit or undefined to use a default limiter (10 attempts per 30 minutes). Pass null to explicitly disable rate limiting. Also available on AppServerContext for route factory callbacks.

type RateLimiter | null

signup_account_rate_limiter

Per-account rate limiter for signup attempts, keyed by submitted username. Omit or undefined to use a default limiter (10 attempts per 30 minutes). Pass null to explicitly disable rate limiting. Also available on AppServerContext for route factory callbacks.

type RateLimiter | null

bearer_ip_rate_limiter

Rate limiter for bearer token auth attempts (per-IP). Omit or undefined to use a default limiter (5 attempts per 15 minutes). Pass null to explicitly disable rate limiting.

type RateLimiter | null

action_ip_rate_limiter

Per-IP rate limiter for the action dispatchers (HTTP RPC + WebSocket). Consulted for actions whose spec declares rate_limit: 'ip' or 'both'. Same limiter applies across transports โ€” one budget per action. Omit or undefined to use a default limiter (600 attempts per 15 minutes โ€” permissive). Pass null to explicitly disable. Also available on AppServerContext for consumers wiring register_action_ws.

type RateLimiter | null

action_account_rate_limiter

Per-actor rate limiter for the action dispatchers (HTTP RPC + WebSocket). Consulted for actions whose spec declares rate_limit: 'account' or 'both'. Keyed on request_context.actor.id (post-auth). Omit or undefined to use a default limiter (1200 attempts per 15 minutes โ€” permissive). Pass null to explicitly disable. Also available on AppServerContext for consumers wiring register_action_ws.

type RateLimiter | null

max_body_size

Maximum allowed request body size in bytes. Omit or undefined to use the default (1 MiB). Pass null to explicitly disable body size limiting.

type number | null

daemon_token_state

Daemon token state for keeper auth. Omit to disable.

bootstrap

Bootstrap options. Omit to skip bootstrap status check and routes.

surface_route

Set to false to disable the auto-created surface route (GET /api/surface). Default: auto-created (authenticated).

type false

create_route_specs

Build route specs from the initialized backend. Called after all middleware is ready.

type (context: AppServerContext) => Array<RouteSpec>

transform_middleware

Optional: transform middleware specs before applying.

type (specs: Array<MiddlewareSpec>) => Array<MiddlewareSpec>

audit_log_sse

Enable factory-managed audit log SSE.

When truthy, creates an AuditLogSse instance internally, appends the SSE listener to backend.deps.audit.on_event_chain (composing with the consumer's on_audit_event callback rather than rebuilding AppDeps), and auto-includes audit_log_event_specs in the surface. The result is exposed on AppServerContext (for route factories) and AppServer (for the caller), always typed as AuditLogSse | null โ€” when this option is set, the field is non-null. Use require_audit_sse(ctx) to assert the invariant in route factories that depend on it.

Pass true for defaults (admin role), or {role: 'custom'} for a custom role. Omit to wire audit SSE manually.

type true | {role?: string}

event_specs

SSE event specs for surface generation. Defaults to [] (no SSE events).

type Array<EventSpec>

rpc_endpoints

RPC endpoint specs โ€” single source of truth for both surface generation *and* live dispatch. Each entry is mounted via create_rpc_endpoint against the assembled Hono app, so consumers no longer call create_rpc_endpoint themselves inside create_route_specs.

Accepts either an array (evaluated eagerly) or a factory (ctx: AppServerContext) => Array<RpcEndpointSpec> (evaluated after the server context is assembled). Use the factory form when action lists depend on ctx.deps / ctx.app_settings โ€” e.g. create_standard_rpc_actions(ctx.deps, {app_settings: ctx.app_settings}).

type Array<RpcEndpointSpec> | ((context: AppServerContext) => Array<RpcEndpointSpec>)

upgradeWebSocket

Hono adapter's upgradeWebSocket helper. Required whenever ws_endpoints resolves to a non-empty array โ€” create_app_server throws at assembly otherwise. Omit (along with ws_endpoints) when the consumer doesn't mount any WS endpoints. The same adapter helper services every WsEndpointSpec mounted from ws_endpoints โ€” one adapter per app.

For Node, import {upgradeWebSocket} from '@hono/node-ws'. For Deno, import {upgradeWebSocket} from 'hono/deno'. Test harnesses use create_stub_upgrade from $lib/testing/ws_round_trip.ts.

type UpgradeWebSocket

ws_endpoints

WebSocket endpoint specs โ€” single source of truth for both surface generation *and* live dispatch. Each entry is auto-mounted via register_ws_endpoint against the assembled Hono app, so consumers no longer call register_ws_endpoint themselves.

Accepts either an array (evaluated eagerly) or a factory (ctx: AppServerContext) => ReadonlyArray<WsEndpointSpec> (evaluated after the server context is assembled). Use the factory form when action lists depend on ctx.deps / ctx.action_*_rate_limiter โ€” e.g. when spreading create_standard_rpc_actions(ctx.deps, ...) over WS.

When non-empty, upgradeWebSocket must be supplied (throws otherwise). A factory returning [] does NOT trip the check โ€” feature-flag gated WS surfaces stay safe.

Duplicate path values across two WsEndpointSpecs throw at mount time (Hono would silently shadow them otherwise).

Each spec's auth_guard? defaults to true โ€” the factory composes create_ws_auth_guard + create_ws_logout_closer against the mounted transport and appends them to deps.audit.on_event_chain. Wiring is deduped by transport reference identity so two specs sharing one BackendWebsocketTransport instance get a single pair of listeners; wrapped / proxied transports dedupe as separate entries (set auth_guard: false on duplicates and compose against the underlying transport once).

type | ReadonlyArray<WsEndpointSpec> | ((context: AppServerContext) => ReadonlyArray<WsEndpointSpec>)

env_schema

Env schema for surface generation. Defaults to BaseServerEnv โ€” pass an extended schema (typically BaseServerEnv.extend({...})) when the consumer adds app-specific env vars.

type z.ZodObject

post_route_middleware

Middleware applied after routes, before static serving. Included in surface.

type Array<MiddlewareSpec>

static_serving

Static file serving. Omit if not serving static files.

type { serve_static: ServeStaticFactory; /** Root directory for static files. Default `'./build'`. */ root?: string; /** Optional SPA fallback path served for client-side routes. */ spa_fallback?: string; /** * Predicate deciding which paths receive the SPA fallback. * Default: every path that is not under `/api/`. Only consulted * when `spa_fallback` is set. */ is_spa_route?: (path: string) => boolean; }

await_pending_effects

Await all pending fire-and-forget effects before returning the response. Use in tests so audit log assertions don't need polling. Default false (production: true fire-and-forget).

type boolean

on_effect_error

Called when a pending effect rejects. Use for monitoring, metrics, or alerting in production. Only called when await_pending_effects is false (production mode).

type (error: unknown, context: EffectErrorContext) => void

env_values

Env values for startup summary logging.

type Record<string, unknown>

AppSettings
#

AppSettingsGetInput
#

AppSettingsGetOutput
#

auth/admin_action_specs.ts view source

ZodObject<{ settings: ZodObject<{ open_signup: ZodBoolean; updated_at: ZodNullable<ZodString>; updated_by: ZodNullable<$ZodBranded<ZodUUID, "Uuid", "out">>; updated_by_username: ZodNullable<...>; }, $strict>; }, $strict>

Output for app_settings_get.

AppSettingsJson
#

auth/app_settings_schema.ts view source

ZodObject<{ open_signup: ZodBoolean; updated_at: ZodNullable<ZodString>; updated_by: ZodNullable<$ZodBranded<ZodUUID, "Uuid", "out">>; }, $strict>

Zod schema for client-safe app settings data.

AppSettingsRpc
#

ui/app_settings_state.svelte.ts view source

AppSettingsRpc

Narrow RPC surface consumed by AppSettingsState. Consumers adapt their typed RPC client to this shape. Method signatures track the wire spec inputs/outputs directly so the adapter needs no casts.

get

type () => Promise<AppSettingsGetOutput>

update

type (params: AppSettingsUpdateInput) => Promise<AppSettingsUpdateOutput>

AppSettingsState
#

ui/app_settings_state.svelte.ts view source

list

readonly

update

readonly

settings

type AppSettingsWithUsernameJson | null

constructor

type new (options?: AppSettingsStateOptions | undefined): AppSettingsState

options?
type AppSettingsStateOptions | undefined
optional

fetch

type (): Promise<void>

returns Promise<void>

update_open_signup

type (value: boolean): Promise<void>

value
type boolean
returns Promise<void>

AppSettingsStateOptions
#

ui/app_settings_state.svelte.ts view source

AppSettingsStateOptions

get_rpc

Reactive accessor for the RPC adapter. null disables all operations (the state reports a descriptive error when fetch/update fires).

type () => AppSettingsRpc | null

AppSettingsUpdateInput
#

AppSettingsUpdateOutput
#

auth/admin_action_specs.ts view source

ZodObject<{ ok: ZodLiteral<true>; settings: ZodObject<{ open_signup: ZodBoolean; updated_at: ZodNullable<ZodString>; updated_by: ZodNullable<$ZodBranded<ZodUUID, "Uuid", "out">>; updated_by_username: ZodNullable<...>; }, $strict>; }, $strict>

Output for app_settings_update.

AppSettingsWithUsernameJson
#

auth/app_settings_schema.ts view source

ZodObject<{ open_signup: ZodBoolean; updated_at: ZodNullable<ZodString>; updated_by: ZodNullable<$ZodBranded<ZodUUID, "Uuid", "out">>; updated_by_username: ZodNullable<...>; }, $strict>

Zod schema for admin app settings with resolved updater username.

AppShell
#

ui/AppShell.svelte view source

children

type Snippet

sidebar

type Snippet

sidebar_width?

Sidebar width in pixels when shown.

type number
optional

sidebar_state?

Optional pre-built SidebarState for sharing visibility across shells.

optional

keyboard_shortcut?

Single-key shortcut that toggles the sidebar (e.g. 'b'). false disables.

type string | false
optional

show_toggle?

Whether to render the built-in (or custom) toggle button.

type boolean
optional

toggle_button?

Custom toggle-button renderer; receives the title, visibility, and toggle callback.

type Snippet<[{title: string; show_sidebar: boolean; toggle: () => void}]>
optional

AppSurface
#

http/surface.ts view source

AppSurface

Generated attack surface โ€” JSON-serializable.

middleware

type Array<AppSurfaceMiddleware>

routes

type Array<AppSurfaceRoute>

rpc_endpoints

type Array<AppSurfaceRpcEndpoint>

ws_endpoints

type Array<AppSurfaceWsEndpoint>

env

type Array<AppSurfaceEnv>

events

type Array<AppSurfaceEvent>

diagnostics

type Array<AppSurfaceDiagnostic>

AppSurfaceDiagnostic
#

http/surface.ts view source

AppSurfaceDiagnostic

Assembly-time diagnostic collected during surface generation or server assembly.

level

type 'warning' | 'info'

category

type string

message

type string

source

type string

AppSurfaceEnv
#

http/surface.ts view source

AppSurfaceEnv

An env var in the generated attack surface (JSON-serializable).

name

type string

description

type string

sensitivity

Sensitivity level from .meta({sensitivity}). null when not sensitive.

type Sensitivity | null

has_default

type boolean

optional

type boolean

AppSurfaceEvent
#

http/surface.ts view source

AppSurfaceEvent

An SSE event in the generated attack surface (JSON-serializable).

method

type string

description

type string

channel

type string | null

params_schema

type unknown

AppSurfaceMiddleware
#

http/surface.ts view source

AppSurfaceMiddleware

A middleware in the generated attack surface (JSON-serializable).

name

type string

path

type string

error_schemas

JSON Schema representations of error responses, keyed by HTTP status code. null when none.

type Record<string, unknown> | null

AppSurfaceRoute
#

http/surface.ts view source

AppSurfaceRoute

A route in the generated attack surface (JSON-serializable).

method

type string

path

type string

auth

applicable_middleware

type Array<string>

description

type string

is_mutation

Whether this route mutates state (POST, PUT, DELETE, PATCH).

type boolean

transaction

Whether this route's handler runs inside a database transaction.

type boolean

rate_limit_key

Rate limit key type declared on the route spec. null when not rate-limited.

type RateLimitKey | null

params_schema

JSON Schema representation of the URL path params schema. null when no params.

type unknown

query_schema

JSON Schema representation of the URL query params schema. null when no query schema.

type unknown

input_schema

JSON Schema representation of the request body schema. null for no-body routes.

type unknown

output_schema

JSON Schema representation of the success response schema.

type unknown

error_schemas

JSON Schema representations of error responses, keyed by HTTP status code. null when none.

type Record<string, unknown> | null

AppSurfaceRpcEndpoint
#

http/surface.ts view source

AppSurfaceRpcEndpoint

An RPC endpoint in the generated attack surface (JSON-serializable).

path

type string

methods

type Array<AppSurfaceRpcMethod>

AppSurfaceRpcMethod
#

http/surface.ts view source

AppSurfaceRpcMethod

A method within an RPC endpoint in the generated attack surface (JSON-serializable).

name

type string

auth

input_schema

JSON Schema representation of the input schema. null for null-input methods.

type unknown

output_schema

JSON Schema representation of the output schema.

type unknown

side_effects

type boolean

description

type string

rate_limit_key

Rate limit key declared on the action spec. null when not rate-limited.

type RateLimitKey | null

AppSurfaceSpec
#

http/surface.ts view source

AppSurfaceSpec

The surface bundled with the source specs that produced it.

AppSurface is JSON-serializable (snapshots, UI, startup logging) โ€” it's the observability layer, written to disk by gro gen for human inspection + drift detection.

AppSurfaceSpec is runtime-only โ€” tests, introspection, attack surface assertions. Both in-process and cross-process tests construct an AppSurfaceSpec in TS via create_test_app_surface_spec (or a consumer equivalent); the cross-process-ness lives in the transport + per-test fixture, not the schema source.

surface

route_specs

type Array<RouteSpec>

middleware_specs

type Array<MiddlewareSpec>

rpc_endpoints

type Array<RpcEndpointSpec>

ws_endpoints

type Array<WsEndpointSpec>

AppSurfaceWsEndpoint
#

http/surface.ts view source

AppSurfaceWsEndpoint

A WebSocket endpoint in the generated attack surface (JSON-serializable).

path

type string

allowed_origins

Upgrade-time origin allowlist, one entry per WsEndpointSpec.allowed_origins regex stringified via RegExp.prototype.toString() ('/<source>/<flags>'). Empty array when no origins were declared (any-origin); reviewers read this as the exact pattern matched at the upgrade gate, not a wildcard approximation. Reconstruct via new RegExp(source, flags) if needed.

type ReadonlyArray<string>

required_roles

Upgrade-time role gate โ€” empty array when no required_roles was declared (any-authenticated). Documents the coarse gate; per-action auth on each method covers per-message authorization.

type ReadonlyArray<string>

methods

type Array<AppSurfaceWsMethod>

AppSurfaceWsMethod
#

http/surface.ts view source

AppSurfaceWsMethod

A method within a WebSocket endpoint in the generated attack surface (JSON-serializable).

name

type string

kind

request_response (inbound dispatch) or remote_notification (server โ†’ client).

auth

Per-action auth shape. null for remote_notification (server โ†’ client) โ€” notifications have no inbound dispatch and therefore no auth axis. request_response always carries a RouteAuth.

type RouteAuth | null

input_schema

JSON Schema of the input schema. null for nullary inputs.

type unknown

output_schema

JSON Schema of the output schema.

type unknown

description

type string

side_effects

type boolean

rate_limit_key

Rate limit key declared on the action spec. null when not rate-limited.

type RateLimitKey | null

argon2_password_deps
#

assert_404_schemas_use_specific_errors
#

testing/surface_invariants.ts view source

(surface: AppSurface): void

Routes declaring 404 error schemas should use specific z.literal() or z.enum() error codes, not generic z.string().

A generic 404 schema (ApiError with z.string()) means the error code is unconstrained โ€” the handler could return any string, making client error handling fragile. Routes with params (:id) are the primary 404 producers; their error schemas should use specific constants like ERROR_ACCOUNT_NOT_FOUND.

Only flags routes that have params_schema (param-driven resource lookup) โ€” routes declaring 404 for other reasons (e.g., bootstrap not configured) may legitimately use generic schemas.

surface

returns

void

assert_close_call
#

testing/connection_closer_helpers.ts view source

(call: RecordedClose | undefined, method: "account" | "token" | "session", id: string): void

Pin {method, id} on a single recorded close call without baking in the at: N sequence number. Use at every "did the closer fire?" assertion site; the sequence number is only meaningful for dedicated ordering tests (paired with create_emit_ordering_audit_factory).

Throws via assert.ok if call is undefined โ€” index a recorded calls array directly (calls[0]) and let this helper handle the missing-element case.

call

type RecordedClose | undefined

method

type "account" | "token" | "session"

id

type string

returns

void

assert_descriptions_present
#

assert_error_code_status_consistency
#

testing/surface_invariants.ts view source

(surface: AppSurface): void

The same z.literal() error code should not appear at different HTTP status codes across routes.

Extracts const values from error schema error properties (which correspond to z.literal() in the Zod source). Walks union branches (anyOf from z.union, oneOf from z.discriminatedUnion) so literal codes nested inside merged unions (e.g. validation 400 + actor-resolution 400) are still tracked. Flags when the same literal appears at different status codes โ€” e.g., ERROR_INVALID_CREDENTIALS at both 401 and 403 would be a bug.

Only checks const values (literal schemas). Generic z.string() schemas (which produce {type: 'string'}) and z.enum() schemas are ignored โ€” the literal-only narrow keeps the check unambiguous.

surface

returns

void

assert_error_coverage
#

testing/error_coverage.ts view source

(collector: ErrorCoverageCollector, route_specs: RouteSpec[], options?: ErrorCoverageOptions | undefined): void

Assert error coverage meets a minimum threshold.

Computes the ratio of exercised error paths to total declared error paths. For routes whose status error schema names specific codes (z.literal or z.enum), each declared code counts as one coverage path; for schemas without declared codes (ApiError/z.string()), the status counts as one path. A status-only observation covers all declared codes for that status (the "any-code" rule).

When min_coverage is 0 (default), logs coverage info without failing. When > 0, fails if coverage is below the threshold.

collector

route_specs

type RouteSpec[]

options?

type ErrorCoverageOptions | undefined
optional

returns

void

throws

  • AssertionError - if `min_coverage > 0` and the covered/total ratio

assert_error_schema_tightness
#

testing/surface_invariants.ts view source

(surface: AppSurface, options?: ErrorSchemaTightnessOptions | undefined): void

Assert that all error schemas meet a minimum specificity threshold.

Calls audit_error_schema_tightness and fails on any entry below the configured threshold. Use allowlist and ignore_statuses to exclude known exceptions during progressive tightening.

surface

options?

type ErrorSchemaTightnessOptions | undefined
optional

returns

void

throws

  • AssertionError - listing every route ร— status combination whose error

assert_error_schema_valid
#

testing/assertions.ts view source

(lookup: Map<string, Partial<Record<number, ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>>>>, route: AppSurfaceRoute, status: number, body: unknown): void

Assert that an error schema exists for a route+status and validate the body against it.

Protected routes should always have auto-derived error schemas (401 for authenticated, 403 for role-restricted). A missing schema indicates a gap in error schema derivation.

lookup

map from "METHOD /path" to merged error schemas

type Map<string, Partial<Record<number, ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>>>>

route

the surface route to validate against

status

expected HTTP status code

type number

body

the parsed response body to validate

type unknown

returns

void

throws

  • AssertionError - if no schema is declared for the route+status pair.
  • ZodError - if the body does not satisfy the declared schema.

assert_error_schemas_structurally_valid
#

testing/surface_invariants.ts view source

(surface: AppSurface): void

Every route's declared error schemas must have an error field at the top level (conforming to the ApiError base shape {error: string}).

Walks union branches (anyOf from z.union, oneOf from z.discriminatedUnion) so every emit shape inside a merged 400 / 404 is checked, not just the top-level wrapper.

Catches typos in error schema definitions and ensures consumers can always read .error from error responses.

surface

returns

void

assert_full_middleware_stack
#

testing/assertions.ts view source

(surface: AppSurface, path_prefix: string, expected_middleware: string[]): void

Verify every route under a path prefix has the exact expected middleware stack.

surface

the app surface to check

path_prefix

prefix to filter routes (e.g. '/api/')

type string

expected_middleware

the exact middleware names in order

type string[]

returns

void

throws

  • AssertionError - if no routes match `path_prefix`, or if any matching

assert_input_routes_declare_400
#

assert_jsonrpc_error_response
#

testing/rpc_helpers.ts view source

(body: unknown, expected_code?: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<"JsonrpcServerErrorCode">) | undefined): void

Assert that a response body is a valid JSON-RPC error response.

Validates the structure matches JsonrpcErrorResponse and optionally checks the error code.

body

type unknown

expected_code?

optional error code to assert

type -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<"JsonrpcServerErrorCode">) | undefined
optional

returns

void

assert_jsonrpc_success_response
#

testing/rpc_helpers.ts view source

(body: unknown, output_schema?: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>> | undefined): void

Assert that a response body is a valid JSON-RPC success response.

Validates the structure matches JsonrpcResponse. When output_schema is provided, also validates the result field against the declared output schema โ€” matching the REST round-trip's assert_response_matches_spec.

body

type unknown

output_schema?

optional Zod schema to validate the result field against

type ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>> | undefined
optional

returns

void

assert_keeper_routes_under_prefix
#

testing/surface_invariants.ts view source

(surface: AppSurface, prefixes?: string[]): void

Keeper-protected routes must be under expected path prefixes.

Catches keeper routes accidentally placed outside the API namespace (e.g., a keeper route at /health or /admin/ instead of /api/...).

surface

prefixes

type string[]
default DEFAULT_KEEPER_ROUTE_PREFIXES

returns

void

assert_middleware_errors_propagated
#

assert_mutation_routes_use_post
#

testing/surface_invariants.ts view source

(surface: AppSurface): void

Routes with non-null input schemas should use POST (or other mutation methods), not GET.

GET routes with request bodies are technically allowed by HTTP but semantically suspicious โ€” they bypass browser security assumptions about GET being idempotent. Query-string-driven filtering (audit log, list endpoints) should use params schemas or query string parsing, not input schemas.

Note: RPC endpoints (create_rpc_endpoint) use input: z.null() on their route specs โ€” the dispatcher handles body/query parsing internally. Real input schemas live in rpc_endpoints surface, not on routes; see assert_rpc_ws_surface_invariants for the parallel checks over RPC/WS method shapes.

surface

returns

void

assert_no_duplicate_routes
#

assert_no_error_info_leakage
#

testing/integration_helpers.ts view source

(body: unknown, context: string): void

Assert that an error response contains no leaky field values.

Checks both field names and string values for patterns indicating stack traces, SQL, or internal paths. Accepts unknown so callers pass response bodies / nested envelope fields directly without intermediate as casts; non-object bodies skip the field-name check.

body

type unknown

context

description for error messages

type string

returns

void

assert_no_sensitive_fields_in_json
#

testing/integration_helpers.ts view source

(body: unknown, blocklist: readonly string[], context: string): void

Assert that a parsed JSON body contains no fields from the given blocklist.

body

type unknown

blocklist

type readonly string[]

context

description for error messages

type string

returns

void

assert_no_unexpected_public_mutations
#

testing/surface_invariants.ts view source

(surface: AppSurface, allowlist?: string[]): void

Public mutation routes (auth: none + is_mutation) must be in the allowlist.

Catches accidentally unprotected POST/PUT/DELETE routes. Routes like login and bootstrap are public mutations by design โ€” they go in the allowlist.

surface

allowlist

type string[]
default []

returns

void

assert_non_admin_schemas_no_admin_fields
#

testing/data_exposure.ts view source

(surface: AppSurface, admin_only_fields?: readonly string[]): void

Assert that non-admin route output schemas don't contain admin-only fields.

surface

admin_only_fields

type readonly string[]
default admin_only_field_blocklist

returns

void

assert_only_expected_public_routes
#

testing/assertions.ts view source

(surface: AppSurface, expected_public: string[]): void

Bidirectional check: no unexpected public routes, no missing expected ones.

surface

the app surface to check

expected_public

format: ['GET /health', 'POST /api/account/login']

type string[]

returns

void

throws

  • AssertionError - if the live surface has public routes not in

assert_output_schemas_no_sensitive_fields
#

testing/data_exposure.ts view source

(surface: AppSurface, sensitive_fields?: readonly string[]): void

Assert that no output schema in the surface contains sensitive field names.

surface

sensitive_fields

type readonly string[]
default sensitive_field_blocklist

returns

void

assert_params_routes_declare_400
#

assert_protected_routes_declare_401
#

assert_query_routes_declare_400
#

assert_rate_limit_retry_after_header
#

testing/integration_helpers.ts view source

(response: Response, body: { retry_after: number; }): void

Assert that a 429 response includes a valid Retry-After header matching the JSON body's retry_after field.

response

type Response

body

type { retry_after: number; }

returns

void

assert_response_matches_spec
#

testing/integration_helpers.ts view source

(route_specs: RouteSpec[], method: string, path: string, response: Response): Promise<void>

Validate a response body against the route spec's declared schemas.

For 2xx responses, validates against spec.output. For error responses, validates against the merged error schema for that status code.

route_specs

type RouteSpec[]

method

type string

path

type string

response

type Response

returns

Promise<void>

throws

  • Error - if no route spec matches `method` + `path`, if the response

assert_role_routes_declare_403
#

assert_route_auth_acting_biconditional
#

http/auth_shape.ts view source

(auth: { account: "none" | "optional" | "required"; actor: "none" | "optional" | "required"; roles?: readonly string[] | undefined; credential_types?: readonly string[] | undefined; }, slots: ActingSlots, context: string): void

Registry-time biconditional check: `auth.actor !== 'none' โŸบ some supplied slot declares acting?: ActingActor`. Throws on violation.

The slot set differs by surface: REST passes {input, query} (both locatable, query only set for GETs); action dispatchers pass {input} (no query shape on ActionSpec). The throw message lists the slots that were actually in play, so an actor-required action without acting doesn't point the operator at a query slot that doesn't exist on their spec.

Called by every dispatcher registration loop (apply_route_specs, compile_action_registry) on every spec it accepts.

auth

the route/action's auth shape

type { account: "none" | "optional" | "required"; actor: "none" | "optional" | "required"; roles?: readonly string[] | undefined; credential_types?: readonly string[] | undefined; }

slots

the spec's acting-bearing schemas; query omitted on action call sites

context

identifier for the throwing message (route key, RPC method, etc.)

type string

returns

void

throws

  • Error - when the biconditional is violated

assert_row
#

db/assert_row.ts view source

<T>(row: T | undefined, context?: string | undefined): T

Assert that a row is present, throwing a descriptive error if missing.

Use after INSERT ... RETURNING queries where the database guarantees a row is returned on success. Replaces bare row! non-null assertions with an explicit runtime check.

row

the row from query_one (T | undefined) or rows[0] (T | undefined)

type T | undefined

context?

optional context for the error message (e.g. table or operation name)

type string | undefined
optional

returns

T

the row, guaranteed non-undefined

throws

  • Error - if `row` is `undefined`

assert_rpc_method_descriptions_present
#

assert_rpc_ws_surface_invariants
#

testing/surface_invariants.ts view source

(surface: AppSurface): void

Run all RPC / WS structural invariants. Options-free โ€” applies universally to the surface.rpc_endpoints and surface.ws_endpoints slots produced by generate_app_surface.

Parallel of assert_surface_invariants for the non-REST surfaces. Within-endpoint duplicate method names and the auth-shape biconditional are already enforced at startup by compile_action_registry (see actions/CLAUDE.md ยงRegistry compile) โ€” these assertions cover only the contract-surface concerns that a runtime registration check cannot: empty descriptions, missing protocol-action spread on WS endpoints, and kind โ‡” auth drift on WS methods.

surface

returns

void

throws

  • AssertionError - on the first invariant violation; the message

assert_schema_snapshots_equal
#

testing/schema_parity.ts view source

(a: SchemaSnapshot, b: SchemaSnapshot, labels?: SchemaDiffLabels): void

Throw if the two snapshots disagree. The error message names the impls (via labels) and lists every diff, so the failure is self-diagnosing.

Consumers wire this after bootstrapping each impl against an isolated DB:

await drop_recreate_db('zzz_test'); await spawn_backend(deno_config); const snapshot_deno = await query_schema_snapshot(db, {}); await drop_recreate_db('zzz_test'); await spawn_backend(rust_config); const snapshot_rust = await query_schema_snapshot(db, {}); assert_schema_snapshots_equal(snapshot_deno, snapshot_rust, {a: 'deno', b: 'rust'});

a

b

labels

default {}

returns

void

assert_sensitive_routes_rate_limited
#

testing/surface_invariants.ts view source

(surface: AppSurface, sensitive_patterns?: (string | RegExp)[]): void

Sensitive routes must declare rate limiting (rate_limit_key is non-null) or have 429 in their error schemas.

Matches routes against sensitive patterns and flags any that lack rate limit declarations. Catches forgotten rate limiting on credential-handling routes.

surface

sensitive_patterns

type (string | RegExp)[]
default DEFAULT_SENSITIVE_PATTERNS

returns

void

assert_surface_deterministic
#

testing/assertions.ts view source

(build_surface: () => AppSurface): void

Verify surface generation is deterministic (build twice, compare).

build_surface

type () => AppSurface

returns

void

assert_surface_invariants
#

testing/surface_invariants.ts view source

(surface: AppSurface): void

Run all structural invariants. Options-free โ€” applies universally.

Catches schema/surface generation bugs: missing 401/403/400 declarations, empty descriptions, duplicate routes, middleware-injected error codes unpropagated to routes, structurally invalid error schemas, error codes appearing at multiple statuses, and generic 404 schemas on param routes.

surface

returns

void

throws

  • AssertionError - on the first invariant violation; the message names

assert_surface_matches_snapshot
#

testing/assertions.ts view source

(surface: AppSurface, snapshot_path: string): void

Compare live surface against a committed snapshot JSON file.

Failure message instructs the developer to run gro gen to update the snapshot โ€” every fuz_app consumer wires the snapshot through a *.gen.ts file so regeneration goes through the same pipeline as the rest of the generated artifacts.

surface

the live surface to check

snapshot_path

absolute path to the committed JSON snapshot

type string

returns

void

throws

  • AssertionError - if the live surface does not deep-equal the snapshot,

assert_surface_security_policy
#

testing/surface_invariants.ts view source

(surface: AppSurface, options?: SurfaceSecurityPolicyOptions): void

Run security policy invariants. Configurable with sensible defaults.

Checks: - Sensitive routes are rate-limited - No unexpected public mutation routes - Input schemas use mutation methods (not GET) - Keeper routes under expected prefixes

surface

options

default {}

returns

void

throws

  • AssertionError - on the first policy violation; the message names

assert_valid_sql_identifier
#

db/sql_identifier.ts view source

(name: string): string

Assert that a string is a valid SQL identifier.

Use this before interpolating table or column names into DDL queries where parameterized placeholders ($1) are not supported.

name

the identifier to validate

type string

returns

string

the validated identifier

throws

  • Error - if the identifier contains characters outside `[a-zA-Z0-9_]`

assert_ws_endpoints_include_protocol_actions
#

testing/surface_invariants.ts view source

(surface: AppSurface): void

Every WS endpoint's methods includes every protocol action method (heartbeat, cancel).

Consumers register WS endpoints by spreading protocol_actions from actions/protocol.ts before their own actions:

ws_endpoints: [{path: '/api/ws', actions: [...protocol_actions, ...consumer_actions], ...}]

Forgetting the spread compiles cleanly but breaks at runtime: client-side heartbeats and cancel notifications get method_not_found from the dispatcher, so disconnect detection silently regresses and per-request cancel never aborts the matching handler. Catch the mistake at the surface layer rather than at runtime.

surface

returns

void

assert_ws_method_descriptions_present
#

assert_ws_notifications_have_null_auth
#

testing/surface_invariants.ts view source

(surface: AppSurface): void

WS methods follow the kind โ‡” auth biconditional emitted by surface generation: kind === 'remote_notification' โŸบ auth === null.

generate_app_surface produces this shape directly from the action spec union (notifications carry auth: null per ActionSpecUnion; request_response carries a RouteAuth). The assertion guards against drift if a future surface emitter, transform, or test fixture violates it โ€” and gives consumers a clear failure message when a hand-built surface mocks the shape incorrectly.

surface

returns

void

AsyncSlot
#

ui/async_slot.svelte.ts view source

Reactive container for a single async operation.

generics

T

default void

E

default string

status

type AsyncStatus

data

type T | undefined

error

type E | null

error_data

The raw caught value from the last failed run(), for programmatic inspection.

type unknown

initial

Convenience derived: status === 'initial'.

type boolean

readonly

loading

Convenience derived: status === 'pending'.

type boolean

readonly

succeeded

Convenience derived: status === 'success'.

type boolean

readonly

failed

Convenience derived: status === 'failure'.

type boolean

readonly

constructor

type new <T = void, E = string>(options?: AsyncSlotOptions<T, E>): AsyncSlot<T, E>

options
type AsyncSlotOptions<T, E>
default {}

run

Run an async operation. The callback receives an AbortSignal it can forward to fetch / RPC clients that support cancellation; the slot also discards superseded results internally even if the callback ignores the signal.

Supersession rule: a second run() aborts the first's signal AND silently drops its commit if it resolves anyway. So back-to-back-to-back run() calls leave only the last call's result in data.

Abort rule: a run() that throws because of its own signal (manual abort(), external options.signal, OR supersession by another run()) does NOT promote to 'failure'. Manual / external aborts revert status to the previous resolved state ('initial' if no run() has ever succeeded, 'success' otherwise). Supersession is handled by the bail-on-mismatch check, leaving the second run's 'pending' standing.

type (fn: (signal: AbortSignal) => Promise<T>, options?: RunOptions): Promise<T | undefined>

fn
type (signal: AbortSignal) => Promise<T>
options
default {}
returns Promise<T | undefined>

the resolved value on success; undefined on failure, abort, or supersession

abort

Manually abort the in-flight run, if any. Reverts status synchronously to the prior resolved state โ€” 'initial' if no run() (or set()) has ever succeeded on this slot, 'success' otherwise. The aborted run's eventual resolution / rejection is dropped without writing to state (the run's Promise resolves to undefined).

type (reason?: unknown): void

reason?
type unknown
optional
returns void

set

Replace data directly and mark the slot 'success'. For post-mutation hydration where the calling RPC already returned the canonical row (parallels CellState.set_cell).

Aborts any in-flight run() first โ€” without this, the in-flight callback could resolve after set() and overwrite the explicit value (the bail-on-mismatch check only fires when #controller was rotated).

type (data: T): void

data
type T
returns void

reset

Reset to 'initial', clear data / error / error_data, and abort any in-flight run. After reset() the slot looks like a fresh instance with no initial option.

type (): void

returns void

AsyncSlotOptions
#

ui/async_slot.svelte.ts view source

AsyncSlotOptions<T, E>

generics

T

E

default string

initial

Seed data and put the slot in 'success' before any run(). Useful when the page already has the resource in hand (SSR hydration, a mutation response, hand-off from a parent slot).

type T

map_error

Convert a caught throw into the error value stored in {@link AsyncSlot.error}. Default extracts Error.message (falling back to 'Request failed' for non-Error throws). Pass to_rpc_error_message to unwrap JSON-RPC data.reason codes.

type (e: unknown) => E

preserve_error_on_retry

When true, the previous error / error_data survive the start of a new run() until the next success (or another failure overwrites them). Useful for retry UX that wants to keep the failure message visible alongside an inline spinner. Default false โ€” run() clears the error at the start so the pending state reads "no current error."

type boolean

audit_error_schema_tightness
#

testing/surface_invariants.ts view source

(surface: AppSurface): ErrorSchemaAuditEntry[]

Audit error schema tightness across all routes in a surface.

Reports which route x status code combinations use generic ApiError (z.string()) vs specific z.literal() or z.enum() error codes. Use the output to prioritize progressive tightening of error schemas.

surface

returns

ErrorSchemaAuditEntry[]

audit entries for every route x status combination

AUDIT_EVENT_TYPE_NAME_REGEX
#

auth/audit_log_schema.ts view source

RegExp

Letter start, then letters, digits, _, ., /, -. Accepts snake_case, dotted, and namespaced consumer conventions; rejects empty strings, leading separators, whitespace, and control characters.

AUDIT_EVENT_TYPES
#

auth/audit_log_schema.ts view source

readonly ["login", "logout", "bootstrap", "signup", "password_change", "session_revoke", "session_revoke_all", "token_create", "token_revoke", "token_revoke_all", "role_grant_create", ... 9 more ..., "app_settings_update"]

All tracked auth event types. Frozen to convert accidental in-process mutation (test cross-contamination, cast escapes) into loud TypeErrors. Not a security boundary โ€” in-process code has many other paths to subvert audit logging.

AUDIT_LOG_CHANNEL
#

AUDIT_LOG_DEFAULT_LIMIT
#

audit_log_event_specs
#

AUDIT_LOG_INDEXES
#

audit_log_list_action_spec
#

auth/admin_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "required"; roles: string[]; }; side_effects: false; input: ZodDefault<ZodObject<{ event_type: ZodOptional<ZodNullable<ZodString>>; ... 5 more ...; acting: ZodOptional<...>; }, $strict>>; output: ZodObject<...>; as...

rate_limit: 'account' bounds admin-side enumeration of the entire audit log via (limit, offset) walking โ€” same shape as admin_account_list_action_spec. The listing carries cross-account forensic detail (target ids, IPs, metadata), so the read-rate cap is the only check that distinguishes a human reviewer from a scraping script.

AUDIT_LOG_LIST_LIMIT_MAX
#

audit_log_role_grant_history_action_spec
#

auth/admin_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "required"; roles: string[]; }; side_effects: false; input: ZodDefault<ZodObject<{ limit: ZodOptional<ZodNullable<ZodNumber>>; offset: ZodOptional<...>; acting: ZodOptional<...>; }, $strict>>; output: ZodObject<......

rate_limit: 'account' bounds admin-side enumeration of the role_grant history via (limit, offset) walking โ€” same shape as audit_log_list, narrower projection but identical scraping vector.

audit_log_rpc_context
#

AUDIT_LOG_SCHEMA
#

auth/audit_log_ddl.ts view source

"\nCREATE TABLE IF NOT EXISTS audit_log (\n id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n seq BIGSERIAL NOT NULL,\n event_type TEXT NOT NULL,\n outcome TEXT NOT NULL DEFAULT 'success',\n actor_id UUID REFERENCES actor(id) ON DELETE SET NULL,\n account_id UUID REFERENCES account(id) ON DELETE SET NULL,\n ta...

Audit log DDL โ€” CREATE TABLE + index statements for the audit_log table.

Consumed by auth/migrations.ts. Separated from auth/audit_log_schema.ts so the schema module stays Zod-only (paired with auth/auth_ddl.ts and auth/role_grant_offer_ddl.ts).

Multi-actor invariants the envelope columns assume:

- actor_id + account_id, when both populated, refer to the same account (derivable via actor.account_id). Denormalized for indexed audit queries; do not let them disagree. - target_actor_id + target_account_id, same rule when both populated. - target_account_id is the SSE/WS socket-close key โ€” sessions stay account-grain after multi-actor lands, so this column carries the routing identity even on actor-bound events. - target_actor_id is populated iff the event subject is actor-bound (see AuditLogEvent.target_actor_id doc-comment for the rule).

AUDIT_LOG_SSE_MAX_PER_SCOPE
#

realtime/sse_auth_guard.ts view source

10

Default max concurrent SSE subscribers per session scope for the audit log.

The audit log SSE subscribes with scope = session_hash and groups = [account_id]. Only scope is capped โ€” so this limits tabs per session. An account's total streams across all sessions is bounded transitively by max_sessions ร— AUDIT_LOG_SSE_MAX_PER_SCOPE. 10 tabs per session is a comfortable ceiling for normal use; consumers raising it above ~50 should consider server-side connection limits.

audit_metadata_schemas
#

auth/audit_log_schema.ts view source

Readonly<{ login: ZodNullable<ZodObject<{ username: ZodString; }, $loose>>; logout: ZodNull; bootstrap: ZodNullable<ZodObject<{ error: ZodString; }, $loose>>; ... 17 more ...; app_settings_update: ZodObject<...>; }>

Per-event-type metadata Zod schemas. z.looseObject so consumers can add fields while known ones are validated. The record is frozen to catch mutation bugs at the key level (e.g. tests that try to swap in a stub schema); the Zod schemas themselves are reachable and mutable โ€” freeze isn't a security boundary.

AuditCompletenessTestOptions
#

testing/audit_completeness.ts view source

AuditCompletenessTestOptions

setup_test

Per-test fixture-producing function. The audit suite calls this in every test() body โ€” auth_integration_truncate_tables clears the audit log between tests, so each test re-bootstraps the keeper and the observer admin against a fresh table.

surface_source

App surface (with route specs). Constructed in TS by the consumer; same shape for in-process and cross-process tests. The audit suite is Tier 2 today (stays in-process per the cross-backend-integration design), but takes the same surface shape as Tier 1 suites for options uniformity.

capabilities

Backend capability declarations.

session_options

Session config โ€” needed for factory-form rpc_endpoints resolution.

type SessionOptions<string>

rpc_endpoints

RPC endpoint specs โ€” required. The admin role_grant flow is RPC-only and the suite hard-fails without it.

AuditEmitFn
#

auth/audit_emitter.ts view source

AuditEmitFn

Signature of AuditEmitter.emit โ€” captured by the inner closure so emit_role_grant_target reaches the decorated function rather than a this.emit lookup. Exposed as a type so EmitDecorator can name the inner / outer slot.

AuditEmitMarker
#

AuditEmitRoleGrantContext
#

auth/audit_emitter.ts view source

AuditEmitRoleGrantContext

Context required by AuditEmitter.emit_role_grant_target โ€” adds client_ip so the helper can lift the ip: ctx.client_ip boilerplate every role-grant-shape emit site repeated.

inheritance

client_ip

Resolved client IP from the trusted-proxy middleware โ€” 'unknown' if not resolved.

type string

AuditEmitter
#

auth/audit_emitter.ts view source

AuditEmitter

Bound audit-emit capability. Built once at backend assembly via create_audit_emitter; lives on AppDeps.audit so factories never see the pool.

on_event_chain

Mutable subscriber chain. create_app_server appends the factory-managed audit-log SSE listener and per-endpoint WS auth guards / logout closers here so SSE + WS fan-out compose on top of the consumer's on_audit_event callback without shallow-copying AppDeps. Consumers can also append listeners directly for setups that don't run through create_app_server.

type Array<(event: AuditLogEvent) => void>
readonly

AuditEmitterContext
#

auth/audit_emitter.ts view source

AuditEmitterContext

Per-request context required by AuditEmitter.emit โ€” just the eager pending_effects queue. The bound emitter carries its own log reference inside the closure, so per-call contexts don't need one.

Audit emits are eager-only by design: the bound emitter fires the pool write immediately and pushes the in-flight Promise<void> here. They never go through emit_after_commit โ€” pool-routed audit writes are already rollback-resilient because they run outside the request transaction, so the post-commit timing the deferred queue provides would only delay forensic visibility without any safety benefit.

Both RouteContext and ActionContext structurally satisfy this shape (they each carry pending_effects), so handlers pass route / ctx directly.

pending_effects

type Array<Promise<void>>

AuditEventHandler
#

actions/transports_ws_auth_guard.ts view source

AuditEventHandler

Audit-event callback shape โ€” the function CreateAuditEmitterOptions.on_audit_event accepts and that the helpers in this module return.

Exported so consumers composing multiple handlers (typically create_ws_auth_guard + create_ws_logout_closer + their own pre-existing on_audit_event) can annotate their composed callback without reaching for Parameters<typeof create_ws_auth_guard>[0].

AuditEventType
#

auth/audit_log_schema.ts view source

ZodEnum<{ invite_create: "invite_create"; invite_delete: "invite_delete"; app_settings_update: "app_settings_update"; login: "login"; logout: "logout"; bootstrap: "bootstrap"; signup: "signup"; ... 13 more ...; role_grant_offer_supersede: "role_grant_offer_supersede"; }>

Zod schema for audit event types.

AuditEventTypeName
#

AuditFactory
#

server/app_backend.ts view source

AuditFactory

Callback that builds the bound AuditEmitter after the backend's pool Db and Logger exist. Required on CreateAppBackendOptions so the consumer owns subscriber-chain composition and AuditLogConfig selection without the factory holding a default.

The factory is invoked exactly once during create_app_backend, after create_db resolves and migrations run. The emitter it returns lands on AppDeps.audit and is captured by every query/handler that reaches deps.audit.emit(...).

The canonical body is a one-liner over create_audit_emitter:

audit_factory: ({db, log}) => create_audit_emitter({ db, log, on_audit_event, audit_log_config, })

Returning an emitter built against a different db than the one passed in would route audit writes to a different pool than handlers query โ€” the callback shape exists specifically to make that mistake structurally impossible.

AuditLogConfig
#

auth/audit_log_schema.ts view source

AuditLogConfig

Configuration bundle for audit-log event types and metadata schemas.

Lets consumers extend the closed AUDIT_EVENT_TYPES enum with their own event strings (and metadata Zod schemas) without forking. Pass to create_audit_emitter (or query_audit_log for in-tx call sites) as the optional config argument; both default to builtin_audit_log_config.

The DB column is TEXT NOT NULL and never enforced an enum, so consumer event types round-trip through query_audit_log_list and SSE identically to builtins.

Constructed configs are deep-frozen (wrapper, event_types, metadata_schemas) to catch accidental mutation bugs early. Not a security boundary against in-process code, which can subvert audit logging through other paths.

event_types

All recognized event-type strings โ€” fuz_app builtins plus consumer extras.

type ReadonlyArray<string>
readonly

metadata_schemas

Per-event-type metadata schemas. Missing entries skip metadata validation for that type (row still written; metadata stored as raw JSONB).

type Readonly<Record<string, z.ZodType>>
readonly

AuditLogEvent
#

auth/audit_log_schema.ts view source

AuditLogEvent

Audit log row from the database. See AuditLogEventJson for event_type widening rationale.

id

type Uuid

seq

type number

event_type

outcome

actor_id

Operator (the actor that initiated the event) โ€” populated when the request resolved an acting actor.

Resolution is driven per-request by the route-spec wrapper / RPC dispatcher; a route gets an acting actor when its input schema declares acting?: ActingActor or its auth requires role_grants (role / keeper). Account-grain operations declare neither, so no actor is resolved and actor_id is null: login (also pre-credential), logout, signup, bootstrap, password_change, session/token revoke, app_settings_update, invite events. Role grant events, admin actions, and actor-targeted offers populate this with the initiator's actor.

type Uuid | null

account_id

type Uuid | null

target_account_id

type Uuid | null

target_actor_id

Actor-grain target โ€” populated when the event subject is bound to a specific actor.

Concretely: - Always populated: role_grant_revoke and role_grant_create (admin direct-grant, self-service toggle, and in-tx role_grant_offer_accept all populate both target columns โ€” the role_grant's grantee is the actor-grain subject regardless of who initiated the grant), role_grant_offer_accept on accept (the accept binds the actor deterministically), role_grant_offer_decline (the grantor actor โ€” decline is *to* the offering actor). - Conditionally populated: offer-shape events (role_grant_offer_create, _expire, _retract, _supersede) carry the actor when the offer was actor-targeted at create time (role_grant_offer.to_actor_id set), null when the offer was account-grain (any actor on to_account_id may accept). - Not populated: admin actions, account-shape events (login, logout, signup, bootstrap, password_change, session/token revoke, app_settings_update, invite events) โ€” subject is the account or no specific resource, not an actor-bound role_grant. - Not populated: events whose principal isn't an actor-bound resource (e.g. consumer events that name a non-actor scope in metadata).

Multi-actor invariants this column relies on: when both target_actor_id and target_account_id are populated they refer to the same account (actor.account_id-derivable). The invariant holds uniformly across every populated event including decline (the grantor's account is joined into the decline RETURNING) and the supersede cascade (the recipient account is known on role_grant_offer.to_account_id). target_account_id stays the SSE/WS socket-close key because sessions remain account-grain after multi-actor lands.

type Uuid | null

ip

type string | null

created_at

type string

metadata

type Record<string, unknown> | null

AuditLogEventJson
#

auth/audit_log_schema.ts view source

ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; seq: ZodNumber; event_type: ZodString; outcome: ZodEnum<{ success: "success"; failure: "failure"; }>; ... 6 more ...; metadata: ZodNullable<...>; }, $strict>

Zod schema for client-safe audit log event.

event_type is AuditEventTypeName (regex-validated string) โ€” matches the AuditLogEvent row and the DB's TEXT NOT NULL column. Consumer types registered via create_audit_log_config({extra_events}) round-trip through queries, on_audit_event callbacks, and JSON-RPC responses identically to builtins. AuditLogInput<T> stays parameterized on the write side so AuditMetadataMap narrowing via get_audit_metadata works.

AuditLogEventWithUsernamesJson
#

auth/audit_log_schema.ts view source

ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; seq: ZodNumber; event_type: ZodString; outcome: ZodEnum<{ success: "success"; failure: "failure"; }>; ... 8 more ...; target_username: ZodNullable<...>; }, $strict>

Zod schema for audit log events with resolved usernames.

AuditLogInput
#

auth/audit_log_schema.ts view source

AuditLogInput<T>

Input for creating an audit log entry.

generics

T

constraint string

event_type

type T

outcome

actor_id

type Uuid | null

account_id

type Uuid | null

target_account_id

type Uuid | null

target_actor_id

type Uuid | null

ip

type string | null

metadata

Per-event-type metadata. Builtin T narrows to AuditMetadataMap[T]; consumer strings widen to a generic record (validation runs against AuditLogConfig.metadata_schemas at insert time).

type T extends AuditEventType ? (AuditMetadataMap[T] & Record<string, unknown>) | null : Record<string, unknown> | null

AuditLogListInput
#

auth/admin_action_specs.ts view source

ZodDefault<ZodObject<{ event_type: ZodOptional<ZodNullable<ZodString>>; outcome: ZodOptional<ZodNullable<ZodEnum<{ success: "success"; failure: "failure"; }>>>; ... 4 more ...; acting: ZodOptional<...>; }, $strict>>

Input for audit_log_list. All filter fields are optional โ€” omit for the default newest-first page. since_seq exists for SSE reconnection gap fill (caller supplies the highest seq seen; server returns everything after).

AuditLogListOptions
#

auth/audit_log_schema.ts view source

AuditLogListOptions

Options for listing audit log entries.

limit

type number

offset

type number

event_type

Event-type filter. Accepts any string โ€” builtins or consumer-registered via create_audit_log_config({extra_events}). The DB column is TEXT NOT NULL with no CHECK, so unknown strings simply match nothing.

type string

event_type_in

type Array<string>

account_id

type Uuid

outcome

since_seq

When set, only return events with seq greater than this value. Enables SSE reconnection gap fill.

type number

AuditLogListOutput
#

auth/admin_action_specs.ts view source

ZodObject<{ events: ZodArray<ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; seq: ZodNumber; event_type: ZodString; outcome: ZodEnum<{ success: "success"; failure: "failure"; }>; ... 8 more ...; target_username: ZodNullable<...>; }, $strict>>; }, $strict>

Output for audit_log_list.

AuditLogRoleGrantHistoryInput
#

auth/admin_action_specs.ts view source

ZodDefault<ZodObject<{ limit: ZodOptional<ZodNullable<ZodNumber>>; offset: ZodOptional<ZodNullable<ZodNumber>>; acting: ZodOptional<...>; }, $strict>>

Input for audit_log_role_grant_history.

AuditLogRoleGrantHistoryOutput
#

auth/admin_action_specs.ts view source

ZodObject<{ events: ZodArray<ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; seq: ZodNumber; event_type: ZodString; outcome: ZodEnum<{ success: "success"; failure: "failure"; }>; ... 8 more ...; target_username: ZodNullable<...>; }, $strict>>; }, $strict>

Output for audit_log_role_grant_history.

AuditLogRouteOptions
#

auth/audit_log_routes.ts view source

AuditLogRouteOptions

Options for audit log route specs.

required_role

Role required to access audit routes. Default 'admin'.

type string

stream

When provided, includes an SSE route at /audit/stream for realtime audit events. The subscribe function receives the stream, channels, and the subscriber's account_id as an identity key โ€” enabling close_by_identity() for auth revocation.

type { subscribe: (stream: SseStream<SseNotification>, options?: SubscribeOptions) => () => void; log: Logger; }

AuditLogRpc
#

ui/audit_log_state.svelte.ts view source

AuditLogRpc

Narrow RPC surface consumed by AuditLogState. Consumers adapt their typed RPC client to this shape. Mirrors AdminAccountsRpc / AdminInvitesRpc. Method signatures track the wire spec inputs/outputs directly so the adapter needs no casts.

list

type (input?: AuditLogListInput) => Promise<AuditLogListOutput>

role_grant_history

type ( input?: AuditLogRoleGrantHistoryInput, ) => Promise<AuditLogRoleGrantHistoryOutput>

AuditLogSse
#

realtime/sse_auth_guard.ts view source

AuditLogSse

Convenience factory result for audit log SSE.

Satisfies AuditLogRouteOptions['stream'] and provides the combined on_audit_event callback (broadcast + guard).

subscribe

Subscribe function โ€” pass as part of stream option to create_audit_log_route_specs.

type (stream: SseStream<SseNotification>, options?: SubscribeOptions) => () => void

log

Logger โ€” pass as part of stream option to create_audit_log_route_specs.

type Logger

on_audit_event

Combined broadcast + guard callback. Wired by create_app_server's audit_log_sse option, or compose inside the consumer's audit_factory body.

type (event: AuditLogEvent) => void

registry

The underlying registry โ€” exposed for subscriber count monitoring.

type SubscriberRegistry<SseNotification>

AuditLogState
#

ui/audit_log_state.svelte.ts view source

list

readonly

role_grant_history

readonly

events

type Array<AuditLogEventWithUsernamesJson>

role_grant_history_events

type Array<RoleGrantHistoryEventJson>

count

type number

readonly

connected

Whether the SSE stream is currently connected.

constructor

type new (options?: AuditLogStateOptions | undefined): AuditLogState

options?
type AuditLogStateOptions | undefined
optional

fetch

type (options?: { event_type?: string | null | undefined; outcome?: "success" | "failure" | null | undefined; account_id?: (string & $brand<"Uuid">) | null | undefined; limit?: number | null | undefined; offset?: number | ... 1 more ... | undefined; since_seq?: number | ... 1 more ... | undefined; acting?: (string & $brand<...>) | undefined; } | undefined): Promise<...>

options?
type { event_type?: string | null | undefined; outcome?: "success" | "failure" | null | undefined; account_id?: (string & $brand<"Uuid">) | null | undefined; limit?: number | null | undefined; offset?: number | ... 1 more ... | undefined; since_seq?: number | ... 1 more ... | undefined; acting?: (string & $brand<...>) | ...
optional
returns Promise<void>

fetch_role_grant_history

type (limit?: number | undefined, offset?: number | undefined): Promise<void>

limit?
type number | undefined
optional
offset?
type number | undefined
optional
returns Promise<void>

subscribe

Connect to the SSE stream for realtime audit events.

New events are prepended to events. EventSource auto-reconnects on transient errors; since_seq fills gaps on reconnection.

type (): () => void

returns () => void

cleanup function that closes the connection

disconnect

Close the SSE connection.

type (): void

returns void

AuditLogStateOptions
#

ui/audit_log_state.svelte.ts view source

AuditLogStateOptions

get_rpc

Reactive accessor for the RPC adapter. Matches the get_rpc pattern on AdminAccountsState โ€” null disables fetch operations (SSE still works).

type () => AuditLogRpc | null

stream_url

SSE stream URL. Defaults to the shipped admin audit-log stream route.

type string

AuditMetadataMap
#

AuditOutcome
#

AUTH_API_TOKEN_ID_KEY
#

auth_drop_tables
#

testing/db.ts view source

readonly ["app_settings", "invite", "audit_log", "api_token", "auth_session", "role_grant", "role_grant_offer", "actor", "account", "bootstrap_lock"]

All auth tables in drop order (children first for FK safety).

The full set created by auth_migrations โ€” use for clean-slate test DB initialization. auth_truncate_tables is the subset for between-test data cleanup (excludes audit_log).

When adding tables to auth_migrations, add them here too.

auth_integration_truncate_tables
#

testing/db.ts view source

string[]

Auth tables including audit_log โ€” for integration tests that exercise the full middleware stack (login, admin, rate limiting).

Separate from auth_truncate_tables because unit-level DB tests that don't touch audit logging don't need to truncate it.

AUTH_MIGRATION_NAMESPACE
#

auth_migration_ns
#

auth_migrations
#

auth/migrations.ts view source

Migration[]

Auth schema migrations in order.

- v0: Full auth schema โ€” account (with email_verified), actor, role_grant, auth_session, api_token, audit_log (with seq), bootstrap_lock, invite, app_settings, plus all indexes and seeds. - v1: role_grant_offer table for consentful grants; adds scope_id / scope_kind / source_offer_id / revoked_reason to role_grant and swaps the (actor_id, role) partial unique index for a scope-aware variant using the index-side 'GLOBAL' token + all-zeros sentinel UUID. The (scope_kind, scope_id) pair is enforced paired-null by role_grant_scope_kind_paired / role_grant_offer_scope_kind_paired CHECK constraints โ€” both null for global, both non-null for scoped. The role_grant_offer table carries a superseded_at terminal state; its partial unique index is scoped by (to_account, role, scope_kind, scope, from_actor) so multiple grantors may coexist. scope_kind is informative-only in v1 (registry-membership validation against create_scope_kind_schema); v2 may add INSERT-time (role, scope_kind) enforcement.

AUTH_SESSION_EXTEND_THRESHOLD_MS
#

AUTH_SESSION_INDEXES
#

AUTH_SESSION_LIFETIME_MS
#

AUTH_SESSION_SCHEMA
#

auth/auth_ddl.ts view source

"\nCREATE TABLE IF NOT EXISTS auth_session (\n id TEXT PRIMARY KEY,\n account_id UUID NOT NULL REFERENCES account(id) ON DELETE CASCADE,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n expires_at TIMESTAMPTZ NOT NULL,\n last_seen_at TIMESTAMPTZ NOT NULL DEFAULT NOW()\n)"

AUTH_SESSION_TOKEN_HASH_KEY
#

auth/request_context.ts view source

"auth_session_token_hash"

Hono context variable name for the authenticated session token hash.

Set by create_request_context_middleware after a successful session lookup. null when the request is unauthenticated or authenticated via a non-session credential (bearer token, daemon token). Exposed so handlers can scope per-session resources (e.g., SSE stream identity for targeted disconnection on session_revoke) without re-hashing the token.

auth_state_context
#

ui/auth_state.svelte.ts view source

{ get: (error_message?: string | undefined) => AuthState; get_maybe: () => AuthState | undefined; set: (value: AuthState) => AuthState; }

Svelte context for AuthState. Use auth_state_context.set(state) in the provider and auth_state_context.get() to access.

auth_truncate_tables
#

testing/db.ts view source

string[]

Auth table names in truncation order (children first for FK safety).

Consumer projects can spread this into their own list and append app-specific tables.

AuthActionHandler
#

actions/action_rpc.ts view source

AuthActionHandler<TInput, TOutput>

Handler signature for an account-grain RPC action โ€” auth.account === 'required' and auth.actor === 'none'. Mirrors ActionHandler but tightens the ctx.auth slot to the non-null RequestContext (with actor: null).

generics

TInput

default any

TOutput

default any

AuthAxisState
#

http/auth_shape.ts view source

ZodEnum<{ none: "none"; optional: "optional"; required: "required"; }>

Per-axis auth state โ€” names the dispatcher's behavior on account and actor independently:

- 'none' โ€” explicitly skipped, even when the credential provides it. Public actions (no auth surface) and notifications declare this. - 'optional' โ€” surfaced if the credential provides it, null otherwise. Identity-aware reads with anonymous fallback (cell_get-style) declare this on account / actor. - 'required' โ€” must be resolved; the dispatcher rejects requests that fail to provide it (401 for account === 'required' without a credential; the authorization phase 4xx for actor === 'required' without an actor binding).

AuthCleanupDeps
#

auth/cleanup.ts view source

AuthCleanupDeps

Dependencies for the cleanup helpers.

inheritance

extends:

log

type Logger

audit

Bound audit emitter. cleanup_expired_role_grant_offers writes via audit.emit_pool (the captured pool + config + listener chain), so one slot covers both row persistence and SSE/WS fan-out. Required โ€” production wiring always has a bound emitter on AppDeps.audit, and tests that need a no-op pass create_test_audit_emitter().

AuthCleanupResult
#

auth/cleanup.ts view source

AuthCleanupResult

Result of run_auth_cleanup.

expired_sessions

Number of expired session rows deleted.

type number

expired_offers

Number of expired role_grant offer rows audit-stamped.

type number

AuthGuardResolver
#

AuthGuards
#

http/route_spec.ts view source

AuthGuards

Two-phase auth guard set returned by AuthGuardResolver.

pre_validation runs before input validation โ€” 401 checks live here so unauthenticated callers never see route-shape information from input parsing failures. post_authorization runs after the authorization phase has populated RequestContext โ€” role / keeper checks live here because they read c.var.request_context.role_grants.

pre_validation

type Array<MiddlewareHandler>

post_authorization

type Array<MiddlewareHandler>

AuthMiddlewareOptions
#

auth/middleware.ts view source

AuthMiddlewareOptions

Per-factory configuration for the standard auth middleware stack.

allowed_origins

type Array<RegExp>

session_options

type SessionOptions<string>

path

Path pattern for middleware (default: '/api/*').

type string

daemon_token_state

Daemon token state for keeper auth. Omit to disable daemon token middleware.

bearer_ip_rate_limiter

Rate limiter for bearer token auth attempts (per-IP). Pass null to disable.

type RateLimiter | null

AuthorizationFailureBody
#

auth/request_context.ts view source

AuthorizationFailureBody

Resolution-failure shape returned by apply_authorization_phase. Each transport binds this to the appropriate wire shape โ€” REST emits the body directly via c.json(body, status); the RPC dispatcher folds it into a JSON-RPC error envelope {jsonrpc, id, error: {code, message, data}}.

The auth phase deliberately stops short of constructing a Response so the same failure flows through every transport without the auth-domain code knowing about JSON-RPC. See ../../../CLAUDE.md ยงCleanest architecture takes priority for the rationale.

AuthorizationHandler
#

http/route_spec.ts view source

AuthorizationHandler

Per-route authorization phase. Runs after pre-validation auth guards AND input validation; resolves the acting actor (when auth.actor !== 'none') by reading c.var.validated_input.acting and sets the request context on the Hono context. Per-route order in apply_route_specs: params โ†’ query โ†’ pre-validation auth (401) โ†’ input validation (400) โ†’ authorization phase โ†’ post-authorization auth (403) โ†’ handler.

Returns a Response to short-circuit (resolution failure โ†’ 400 / 500), or void to continue. The http framework stays auth-agnostic โ€” fuz_app provides the implementation via create_fuz_authorization_handler in auth/request_context.ts.

AuthorizationResult
#

auth/request_context.ts view source

AuthorizationResult

Result of the authorization phase. Pure data โ€” the auth domain stops short of touching the Hono context or producing a Response so HTTP RPC, WS, and REST each bind the same shape to their wire surface.

- {ok: true, request_context} โ€” request_context is non-null on resolved (actor-bound or account-only) outcomes; null for public actions ({account: 'none', actor: 'none'}) and for genuine anonymous access on an 'optional' axis. Public and unauthenticated collapse to the same null request_context; every transport already treated them identically. - {ok: false, status, body} โ€” 400/500 failure. status is narrowed to the two values the auth phase emits, so Hono's c.json status overload accepts the literals directly. The 500 reasons stay distinct in body: no_actors_on_account (signup invariant violation); account_vanished (torn read after resolve).

authorize_admin_or_holder
#

auth/role_grant_offer_actions.ts view source

(auth: RequestContext, input: { to_account_id: string; role: string; scope_id: string | null; }, deps: Pick<RouteFactoryDeps, "log">, ctx: ActionContext): boolean | Promise<...>

Authorization callback that admits any admin and otherwise falls back to the symmetric default (caller must hold the offered role globally).

The admin-grant-path filter in create_handler runs before the authorize callback, so this never sees roles whose grant_paths omits 'admin'. Drop into create_role_grant_offer_actions({authorize: authorize_admin_or_holder}) (or any factory that forwards authorize, e.g. create_standard_rpc_actions) for the common "admins offer anything; users offer what they hold" pattern. Scope-aware policies (e.g. classroom_teacher offering classroom_student in their own scope) wrap this and short-circuit true before delegating.

auth

input

type { to_account_id: string; role: string; scope_id: string | null; }

deps

type Pick<RouteFactoryDeps, "log">

ctx

returns

boolean | Promise<boolean>

AuthSession
#

auth/account_schema.ts view source

AuthSession

Server-side auth session, keyed by blake3 hash of session token.

id

type string

account_id

type Uuid

created_at

type string

expires_at

type string

last_seen_at

type string

AuthSessionJson
#

auth/account_schema.ts view source

ZodObject<{ id: ZodString; account_id: $ZodBranded<ZodUUID, "Uuid", "out">; created_at: ZodString; expires_at: ZodString; last_seen_at: ZodString; }, $strict>

Zod schema for AuthSession โ€” id is the blake3 hash, safe for client.

AuthSessionRouteOptions
#

auth/account_routes.ts view source

AuthSessionRouteOptions

Shared options for route factories that create sessions and rate-limit by IP.

Extended by AccountRouteOptions and SignupRouteOptions. Consumers can destructure these from AppServerContext once and spread into multiple factories.

session_options

type SessionOptions<string>

ip_rate_limiter

Rate limiter for auth attempts, keyed by client IP. Pass null to disable.

type RateLimiter | null

AuthState
#

ui/auth_state.svelte.ts view source

verifying

verified

verify_error

type string | null

account

type SessionAccount | null

actor

type ActorSummaryJson | null

role_grants

type Array<RoleGrantSummaryJson>

active_role_grants

type Array<RoleGrantSummaryJson>

readonly

roles

type Array<string>

readonly

needs_bootstrap

True when bootstrap is available (no accounts exist yet).

check_session

Check auth state and bootstrap availability.

Fetches GET /api/account/status โ€” returns account info (200) or 401 with optional bootstrap_available flag. Called on init, and after login/bootstrap to refresh state.

type (): Promise<void>

returns Promise<void>

login

Log in with username and password. Translates 401 / 429 to friendly messages on verify_error; refreshes the session via check_session on success.

type (username: string, password: string): Promise<boolean>

username
type string
password
type string
returns Promise<boolean>

true if login succeeded, false otherwise

bootstrap

Bootstrap the first keeper account using a single-use token.

type (token: string, username: string, password: string): Promise<boolean>

token
type string
username
type string
password
type string
returns Promise<boolean>

true if bootstrap succeeded, false otherwise

signup

Sign up via invite (or open signup, when app_settings.open_signup is true server-side). Translates 403 / 409 / 429 to friendly messages on verify_error.

type (username: string, password: string, email?: string | undefined): Promise<boolean>

username
type string
password
type string
email?
type string | undefined
optional
returns Promise<boolean>

true if signup succeeded, false otherwise

logout

Log out โ€” best-effort POST /api/account/logout to clear the session cookie, then clears local state regardless of the network outcome.

type (): Promise<void>

returns Promise<void>

AuthTestApps
#

testing/auth_apps.ts view source

AuthTestApps

Pre-built Hono apps for each auth level, shared across adversarial test suites.

public

type Hono

authed

type Hono

keeper

type Hono

by_role

type Map<string, Hono>

BackendBootstrapConfig
#

testing/cross_backend/backend_config.ts view source

BackendBootstrapConfig

Auth-bootstrap configuration for a spawnable test binary. The runner writes token to token_path before launching the child, then POSTs bootstrap_path (default /api/account/bootstrap) with the token plus the username / password to mint the keeper account and capture the session cookie. After health-probe, the runner reads daemon_token_path to load the binary's deterministic daemon token, which default_cross_process_setup threads onto the per-test TestFixture for _testing_reset calls and other keeper-credential operations.

token_path

Path the binary reads for the bootstrap token (env: *_BOOTSTRAP_TOKEN_PATH).

type string
readonly

token

Token text written to token_path before spawn.

type string
readonly

username

Username for the bootstrapped keeper.

type string
readonly

password

Password for the bootstrapped keeper.

type string
readonly

daemon_token_path

Path the test binary writes its daemon-token JSON to on boot (env: *_DAEMON_TOKEN_PATH). spawn_backend reads this file once after the health probe succeeds and threads the token onto BackendHandle.daemon_token for _testing_reset calls plus any other admin/keeper-gated cross-process tests.

type string
readonly

BackendCapabilities
#

testing/cross_backend/capabilities.ts view source

BackendCapabilities

Optional behaviors a backend may support. Each flag's TSDoc names the tests that gate on it; add a new flag here before referencing it from a suite body, and document the gating tests inline.

bearer_auth

Bearer token auth (Authorization: Bearer <token>) is wired through the backend's middleware stack. Gates the bearer-token cases in describe_standard_integration_tests and describe_rate_limiting_tests.

type boolean
readonly

trusted_proxy

Trusted-proxy XFF parsing is wired (X-Forwarded-For etc.). Gates the proxy-resolution cases in describe_standard_integration_tests and the future cross-process proxy integration suite.

type boolean
readonly

login_rate_limit

Per-account login rate limiting is wired. Gates the per-account rate-limit cases in describe_rate_limiting_tests.

type boolean
readonly

ws

WebSocket transport is reachable end-to-end. Gates the cross-process WS round-trip suite; the in-process describe_ws_round_trip_tests runs against register_action_ws directly and ignores this flag.

type boolean
readonly

sse

SSE transport is reachable end-to-end. Gates the cross-process SSE close-detection cases; in-process SSE uses the on_audit_event hook and ignores this flag.

type boolean
readonly

in_process_only

Test has direct access to backend-internal state (keyring for signing cookies, DB pool for FK-structural raw queries). Always true for in-process Hono via default_in_process_setup; always false cross-process. Gates the 3 keyring reads in describe_standard_integration_tests (expired-cookie generation) and the FK-structural raw query in describe_audit_completeness_tests.

type boolean
readonly

BackendConfig
#

testing/cross_backend/backend_config.ts view source

BackendConfig

Configuration for one spawnable test backend. Consumer factories (deno_backend_config(), rust_backend_config()) produce these and the runner consumes them through spawn_backend.

Path defaults match the standard fuz_app surface โ€” Deno + Rust spine (zzz_server, zap_server, testing_spine_stub) all converge on /api/account/{bootstrap,login,logout,password}, /api/rpc, /api/ws, /health. Override only when a backend deliberately diverges (which it shouldn't, per the contract).

name

Diagnostic label ("deno", "rust", "spine_stub"). Surfaces in test output.

type string
readonly

start_command

argv passed to the spawn. The first entry is the binary path.

type ReadonlyArray<string>
readonly

base_url

Base URL for HTTP requests, including port (e.g. http://localhost:8788).

type string
readonly

rpc_path

JSON-RPC endpoint mount point. Default /api/rpc.

type string
readonly

ws_path

WebSocket endpoint mount point. Default /api/ws.

type string
readonly

health_path

Readiness probe path. Default /health.

type string
readonly

bootstrap_path

Bootstrap POST path. Default /api/account/bootstrap.

type string
readonly

cookie_name

Session cookie name the backend issues. Default fuz_session per the ecosystem convergence; consumers using a custom session name (legacy zzz_session, etc.) override. default_cross_process_setup extracts the per-account session value from the transport jar by this name so the cross-process TestAccount.session_cookie matches the in-process shape.

type string
readonly

startup_timeout_ms

How long to wait for the health probe (ms) before giving up.

type number
readonly

env

Env vars merged into the child process. Must include the binary's *_BOOTSTRAP_TOKEN_PATH + *_DAEMON_TOKEN_PATH env var names so the binary reads/writes the right files. Also must include the binary's *_ALLOWED_ORIGINS (typically 'http://localhost:*' for cross-process tests).

type Readonly<Record<string, string>>
readonly

bootstrap

Auth bootstrap details โ€” see BackendBootstrapConfig.

readonly

capabilities

Capabilities this backend supports โ€” drives test_if(capabilities.X, ...) gating in suite bodies. See capabilities.ts for the vocabulary and existing flags. Cross-process backends set in_process_only: false.

readonly

BackendHandle
#

testing/cross_backend/spawn_backend.ts view source

BackendHandle

Handle returned by spawn_backend โ€” passed to per-test setup helpers.

config

The config used to spawn this backend. Carried for diagnostic + downstream access.

readonly

child

Child process reference โ€” exposed for diagnostic logging only.

type ChildProcess
readonly

daemon_token

Deterministic daemon token captured from config.bootstrap.daemon_token_path after the binary booted. default_cross_process_setup builds keeper-daemon-token headers from this for _testing_reset calls.

type string
readonly

teardown

SIGTERM the child's process group, drain stderr, await exit. Idempotent โ€” calls after the first are no-ops.

type () => Promise<void>
readonly

BackendWebsocketTransport
#

actions/transports_ws_backend.ts view source

inheritance

transport_name

readonly

add_connection

Add a new WebSocket connection with auth info. Session connections pass a token hash for targeted revocation. Bearer token connections (api_token) pass the api_token.id so the socket can be closed when that specific token is revoked without tearing down the account's other sockets. Daemon-token connections pass null for both โ€” they're only reachable via close_sockets_for_account.

type (ws: WSContext<unknown>, token_hash: string | null, account_id: string & $brand<"Uuid">, api_token_id?: string | null): string & $brand<"Uuid">

ws
type WSContext<unknown>
token_hash
type string | null
account_id
type string & $brand<"Uuid">
api_token_id
type string | null
default null
returns string & $brand<"Uuid">

the freshly assigned connection_id (branded Uuid)

remove_connection

Remove a WebSocket connection and its auth tracking data. Idempotent โ€” safe to call after revocation has already cleaned up.

type (ws: WSContext<unknown>): void

ws
type WSContext<unknown>
returns void

close_sockets_for_session

Close all sockets associated with a specific session token hash.

type (token_hash: string): number

token_hash
type string
returns number

the number of sockets closed

close_sockets_for_account

Close all sockets associated with a specific account.

type (account_id: string & $brand<"Uuid">): number

account_id
type string & $brand<"Uuid">
returns number

the number of sockets closed

close_sockets_for_token

Close all sockets associated with a specific API token.

Used on token_revoke audit events so revoking one token doesn't tear down the account's session-authenticated sockets or other tokens' sockets.

type (api_token_id: string): number

api_token_id
type string
returns number

the number of sockets closed

send

type (message: { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }, options?: TransportSendOptions | undefined): Promise<...>

message
type { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }
options?
type TransportSendOptions | undefined
optional
returns Promise<{ [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; } | { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<...>); message: string; data?: unknown; }; }>

send

type (message: { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }, options?: TransportSendOptions | undefined): Promise<...>

message
type { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }
options?
type TransportSendOptions | undefined
optional
returns Promise<{ [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; } | { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<...>); message: string; data?: unknown; }; }>

send

type (message: { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }, options?: TransportSendOptions | undefined): Promise<...>

message
type { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }
options?
type TransportSendOptions | undefined
optional
returns Promise<{ [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; } | { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<...>); message: string; data?: unknown; }; }>

broadcast_filtered

Broadcast to connections whose identity satisfies a predicate.

Used by the broadcast API when a consumer supplies a subscription ACL hook (e.g. zap's zap_run_created only reaches the account that owns the run). When no ACL is needed, callers should prefer send(message) / #broadcast to skip the per-connection predicate overhead.

type (message: { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; } | { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<...>); message: string; data?: unknown; }; } | { ...; }, predicate: (identity: ConnectionIdentity) => boolean): number

message
type { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; } | { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<...>); message: string; data?: unknown; }; } | { ...; }
predicate
type (identity: ConnectionIdentity) => boolean
returns number

the number of sockets the message was sent to

send_to_account

Send a message to every socket bound to a specific account.

Targeted per-account fan-out for any flow where the delivery target is a single known account. Prefer this over broadcast_filtered when the filter is exactly "this account_id"; reach for broadcast_filtered when the ACL is an arbitrary predicate over ConnectionIdentity.

Mirrors close_sockets_for_account on the send side: every connection for the account (session, bearer, and daemon-token) receives the message.

type (account_id: string & $brand<"Uuid">, message: { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; } | { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { ...; }; } | { ...; }): number

account_id
type string & $brand<"Uuid">
message
type { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; } | { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<...>); message: string; data?: unknown; }; } | { ...; }
returns number

the number of sockets the message was sent to

is_ready

type (): boolean

returns boolean

get_connection_count

Number of currently tracked WebSocket connections.

Read-only counter intended for telemetry, logging, and tests. Counts every entry in the connection map โ€” including connections that have been closed by the peer but not yet removed by the WS adapter's onClose callback.

type (): number

returns number

baseline
#

db/migrate.ts view source

(db: Db, ns: MigrationNamespace, names: readonly string[]): Promise<void>

Insert tracker rows for the named migrations of a namespace without executing them.

Used to promote an existing schema (e.g. produced by a pre-0.42 build, preserved through a tracker-shape upgrade) into the new identity tracker. baseline() trusts the operator-supplied list โ€” it does not verify that the schema actually matches what the named migrations would have produced. Pair with a schema-assertion script post-baseline before re-enabling traffic.

Contract: - Probes for the pre-0.42 tracker shape; throws old-tracker-shape if found (DDL with IF NOT EXISTS would otherwise no-op against the old table and the INSERT would fail with a confusing column-not-found). - Creates the new-shape schema_version table if missing โ€” cutover scripts that just dropped the old-shape table can call baseline() directly with no separate DDL step. - Acquires the same per-namespace advisory lock as run_migrations (with the same try/catch fallback for environments lacking pg_advisory_lock). - Refuses if any tracker rows already exist *for this namespace* โ€” lets multi-call baseline scripts resume after partial failure (completed namespaces guard themselves while remaining ones still run). - Verifies the supplied names are a strict prefix of the namespace's current migrations array โ€” a name not in the array, or out of order, errors before any INSERT. - Writes sequences 0..N-1 in one transaction.

db

the database instance

type Db

ns

the namespace whose migrations are being baselined

names

prefix of ns.migrations[].name to record as already-applied

type readonly string[]

returns

Promise<void>

throws

  • MigrationError - with `kind` of `old-tracker-shape`,

BaseServerEnv
#

server/env.ts view source

ZodObject<{ NODE_ENV: ZodEnum<{ development: "development"; production: "production"; }>; PORT: ZodDefault<ZodCoercedNumber<unknown>>; HOST: ZodDefault<ZodString>; ... 9 more ...; SMTP_PASSWORD: ZodOptional<...>; }, $strict>

Base Zod schema for server environment variables.

Provides the common fields used by fuz apps: server config, database, auth, security, public URLs, and SMTP.

Apps can use directly or extend with app-specific fields via .extend().

BearerAuthMocks
#

testing/middleware.ts view source

BearerAuthMocks

Mocks bundle returned by create_bearer_auth_mocks.

mock_validate

type ReturnType<typeof vi.fn>

mock_find_by_id

type ReturnType<typeof vi.fn>

mock_find_actor_by_id

type ReturnType<typeof vi.fn>

mock_find_actors_by_account

type ReturnType<typeof vi.fn>

mock_find_active_for_actor

type ReturnType<typeof vi.fn>

BearerAuthTestCase
#

testing/middleware.ts view source

BearerAuthTestCase

A full test case for the table-driven bearer auth runner.

inheritance

validate_expectation

Whether the request should reach token validation or be short-circuited.

type 'called' | 'not_called'

assert_account_set

If true, assert ACCOUNT_ID_KEY was set and CREDENTIAL_TYPE_KEY is 'api_token'.

type boolean

expected_account_id

Expected ACCOUNT_ID_KEY value when assert_account_set is true.

type string

expected_api_token_id

If set, assert AUTH_API_TOKEN_ID_KEY was set to this value after a successful bearer auth.

type string

assert_context_preserved

If true, assert the pre-existing session ACCOUNT_ID_KEY and credential type are preserved.

type boolean

assert_mocks

Optional callback for custom spy assertions on the mocks bundle.

type (mocks: BearerAuthMocks) => void

BearerAuthTestOptions
#

testing/middleware.ts view source

BearerAuthTestOptions

Mock configuration for bearer auth middleware test setup.

name

Test description.

type string

headers

Request headers.

type Record<string, string>

pre_context

Pre-set request context (simulates session already resolved).

mock_validate_result

What query_validate_api_token() returns.

type unknown

mock_find_by_id_result

What query_account_by_id() returns.

type unknown

mock_find_actor_by_id_result

What query_actor_by_id() returns.

type unknown

mock_role_grants_result

What query_role_grant_find_active_for_actor() returns.

type unknown

expected_status

Expected HTTP status, or 'next' if the middleware should call next().

type number | 'next'

expected_error

Expected error field in JSON response body.

type string

expected_error_schema

Zod schema to validate error response body against. Defaults to ApiError when expected_error is set.

type z.ZodType

bootstrap
#

testing/transports/bootstrap.ts view source

(options: BootstrapOptions): Promise<BootstrapResult>

Fire POST {config.bootstrap_path} and capture the keeper session.

options

returns

Promise<BootstrapResult>

throws

  • Error - when the binary refuses bootstrap (non-2xx response) or

bootstrap_account
#

auth/bootstrap_account.ts view source

(deps: BootstrapAccountDeps, provided_token: string, input: BootstrapAccountInput): Promise<BootstrapAccountResult>

Bootstrap the first account with keeper and admin privileges.

Uses an atomic bootstrap_lock UPDATE to prevent concurrent bootstrap attempts (TOCTOU). The full flow runs in a single transaction:

1. Read and verify the bootstrap token (before transaction) 2. Hash the password (CPU-intensive, before transaction) 3. Acquire the bootstrap lock atomically (inside transaction) 4. Create account + actor 5. Grant keeper and admin role_grants (no expiry, granted_by = null) 6. Delete the token file (after commit, reported via token_file_deleted)

deps

database, token path, filesystem callbacks, and password hashing

provided_token

the bootstrap token from the user

type string

input

username and password

returns

Promise<BootstrapAccountResult>

the created account, actor, and role_grants โ€” or a bootstrap failure

bootstrap_backend
#

testing/cross_backend/bootstrap_backend.ts view source

(config: BackendConfig): Promise<BootstrappedBackendHandle>

Spawn the test binary described by config, bootstrap a keeper, and return the enriched handle.

The keeper transport is constructed against config.base_url with no initial cookies; bootstrap() populates its jar with the session cookie returned by POST {config.bootstrap_path}. Subsequent calls against bootstrapped.keeper_transport are authenticated as keeper.

Mirrors the composition default_cross_process_setup's caller would otherwise hand-roll in every consumer's globalSetup.

config

returns

Promise<BootstrappedBackendHandle>

BOOTSTRAP_LOCK_SCHEMA
#

auth/auth_ddl.ts view source

"\nCREATE TABLE IF NOT EXISTS bootstrap_lock (\n id INTEGER PRIMARY KEY DEFAULT 1 CHECK (id = 1),\n bootstrapped BOOLEAN NOT NULL DEFAULT false\n)"

BOOTSTRAP_LOCK_SEED
#

auth/auth_ddl.ts view source

"\nINSERT INTO bootstrap_lock (id, bootstrapped)\n SELECT 1, EXISTS(SELECT 1 FROM account)\n ON CONFLICT DO NOTHING"

Seed the bootstrap_lock table, setting bootstrapped based on whether accounts exist.

bootstrap_test_keeper
#

testing/app_server.ts view source

(options: CreateTestAccountWithCredentialsOptions): Promise<{ account: { id: string & $brand<"Uuid">; username: string; }; actor: { ...; }; api_token: string; session_cookie: string; }>

Bootstrap the test-DB keeper. Direct-query shortcut for the default create_test_app path โ€” bootstrap is not what most tests exercise, so we skip the real bootstrap_account flow (no audit row, no on_bootstrap callback). Tests that need the full success-path flow use create_test_app_for_bootstrap instead.

Flips bootstrap_lock.bootstrapped = true so the post-insert DB state matches a real bootstrap completion โ€” production code can trust the lock as the single signal without a belt-and-suspenders query_account_has_any defense.

options

returns

Promise<{ account: { id: string & $brand<"Uuid">; username: string; }; actor: { id: string & $brand<"Uuid">; }; api_token: string; session_cookie: string; }>

BootstrapAccountDeps
#

auth/bootstrap_account.ts view source

BootstrapAccountDeps

Dependencies for bootstrap_account.

db

type Db

token_path

Path to the bootstrap token file on disk.

type string

read_text_file

Read a file's contents as a string.

type (path: string) => Promise<string>

delete_file

Delete a file.

type (path: string) => Promise<void>

password

Only hashing is needed โ€” verification happens separately during login.

type Pick<PasswordHashDeps, 'hash_password'>

log

Structured logger instance.

type Logger

BootstrapAccountFailure
#

BootstrapAccountInput
#

BootstrapAccountResult
#

BootstrapAccountSuccess
#

auth/bootstrap_account.ts view source

BootstrapAccountSuccess

Successful bootstrap result with the created entities.

ok

type true

account

type Account

actor

type Actor

role_grants

type {keeper: RoleGrant; admin: RoleGrant}

token_file_deleted

Whether the bootstrap token file was successfully deleted after account creation.

type boolean

BootstrapDisabledOptions
#

BootstrapForm
#

BootstrapInput
#

auth/bootstrap_routes.ts view source

ZodObject<{ token: ZodString; username: ZodPipe<ZodString, ZodTransform<string, string>>; password: ZodString; }, $strict>

Input for POST /bootstrap. token is the one-shot token file contents.

BootstrapLiveOptions
#

server/app_server.ts view source

BootstrapLiveOptions

mode

type 'live'

token_path

type string

route_prefix

Route prefix for bootstrap routes. Default '/api/account'.

type string

on_bootstrap

Called after successful bootstrap (account + session created). Use for app-specific post-bootstrap work like generating API tokens.

type (result: BootstrapAccountSuccess, c: Context) => Promise<void>

BootstrapOptions
#

testing/transports/bootstrap.ts view source

BootstrapOptions

Input for bootstrap().

transport

The cookie-threading HTTP transport pointed at the binary. After bootstrap() resolves, the transport carries the keeper session cookie โ€” every later call against it is authenticated as keeper.

readonly

config

Backend config โ€” used for bootstrap_path plus the bootstrap.username / bootstrap.password / bootstrap.token credentials. The runner already wrote bootstrap.token to bootstrap.token_path before spawning, so the binary picks the token up at startup.

readonly

BootstrapOutput
#

auth/bootstrap_routes.ts view source

ZodObject<{ ok: ZodLiteral<true>; account: ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; username: ZodPipe<ZodString, ZodTransform<string, string>>; }, $strict>; actor: ZodObject<...>; }, $strict>

Output for POST /bootstrap. Session cookie is the operative side effect.

BootstrappedBackendHandle
#

testing/cross_backend/setup.ts view source

BootstrappedBackendHandle

Cross-process backend handle enriched with the bootstrapped keeper's captured credentials. Consumers compose this in vitest's globalSetup:

const handle = await spawn_backend(config); const keeper_transport = create_fetch_transport({base_url: config.base_url}); const keeper = await bootstrap({transport: keeper_transport, config}); const bootstrapped: BootstrappedBackendHandle = { ...handle, keeper_transport, keeper_account: keeper.account, keeper_actor: keeper.actor, keeper_cookies: keeper.cookies, };

default_cross_process_setup(bootstrapped, options) reads from this shape โ€” the per-test fixture closes over the keeper credentials so cross-process tests can drive admin-RPC / audit-observer flows against the long-lived bootstrapped admin alongside the per-test signup+login account.

inheritance

extends:

keeper_transport

Transport carrying the keeper session cookie + cookie jar.

readonly

keeper_account

Keeper account JSON captured from POST /bootstrap.

type {readonly id: Uuid; readonly username: string}
readonly

keeper_actor

Keeper actor JSON captured from POST /bootstrap.

type {readonly id: Uuid}
readonly

keeper_cookies

Raw keeper Set-Cookie values โ€” thread into ws_transport for keeper-authenticated WS upgrades.

type ReadonlyArray<string>
readonly

BootstrapResult
#

testing/transports/bootstrap.ts view source

BootstrapResult

The keeper credentials captured from POST /api/account/bootstrap.

transport

Same transport that came in, now carrying the keeper session cookie in its jar. Returned for call-site clarity (callers don't have to remember the mutation happens in place).

readonly

account

Account JSON returned by POST /bootstrap.

type {readonly id: Uuid; readonly username: string}
readonly

actor

Actor JSON returned by POST /bootstrap.

type {readonly id: Uuid}
readonly

cookies

Raw Set-Cookie values for threading into a WS transport.

type ReadonlyArray<string>
readonly

BootstrapRouteOptions
#

auth/bootstrap_routes.ts view source

BootstrapRouteOptions

Per-factory configuration for bootstrap route specs.

bootstrap_status is runtime state (a mutable ref), not a dep or options value โ€” it is passed through so the route handler can flip it on success.

session_options

type SessionOptions<string>

bootstrap_status

Shared mutable reference โ€” flipped to false after successful bootstrap.

on_bootstrap

Called after successful bootstrap (account + session created). Use for app-specific post-bootstrap work like generating API tokens.

type (result: BootstrapAccountSuccess, c: Context) => Promise<void>

ip_rate_limiter

Rate limiter for bootstrap attempts (per-IP). Pass null to disable.

type RateLimiter | null

BootstrapServerOptions
#

server/app_server.ts view source

BootstrapServerOptions

Bootstrap configuration for AppServerOptions.bootstrap.

Discriminated union over three deployment intents. Distinct from BootstrapRouteOptions in auth/bootstrap_routes.ts โ€” that one is per-factory runtime state (mutable bootstrap_status ref, rate limiter); this one is the consumer-facing server option that create_app_server reads at startup to decide whether to mount the routes and where.

Three modes: - disabled โ€” no route mounted, nothing in /api/surface. Equivalent to omitting bootstrap entirely; the explicit mode is for documentation and reviewable intent at the wiring layer. - surface_only โ€” route present, permanent 403 via check_bootstrap_status. For tests asserting on the disabled-but-present wire shape. - live โ€” route mounted, real token verification. Success path reachable. token_path is required (non-nullable).

BootstrapStatus
#

BootstrapSuccessTestOptions
#

testing/bootstrap_success.ts view source

BootstrapSuccessTestOptions

session_options

type SessionOptions<string>

create_route_specs

Same factory the consumer's production server uses.

type (ctx: AppServerContext) => Array<RouteSpec>

rpc_endpoints

RPC endpoints โ€” passed through to create_app_server for shape parity.

bootstrap

Live bootstrap config โ€” the suite drives POST /bootstrap against bootstrap.token_path. The suite does NOT assert on on_bootstrap callback invocation (Hono-coupled signature is in-process only); assertions land on observable DB state.

bootstrap_token

Override the synthetic token text. Default deterministic.

type string

BootstrapSurfaceOnlyOptions
#

server/app_server.ts view source

BootstrapSurfaceOnlyOptions

mode

type 'surface_only'

route_prefix

Route prefix for surface generation. Default '/api/account'.

type string

BootstrapTestKeeperOptions
#

BroadcastApi
#

build_account_context
#

auth/request_context.ts view source

(deps: QueryDeps, account_id: string): Promise<RequestContext | null>

Build an account-only RequestContext (no actor, no role_grants) from an account id.

Used by the dispatcher's authorization phase for authenticated routes that don't need an acting actor โ€” account-grain operations (logout, password change, account self-service). Lets handlers read auth.account.id / auth.account.username uniformly with role_grant-bound routes; the cost is one extra query_account_by_id per request.

Returns null when the account row is missing (e.g. deleted between the auth middleware's session lookup and the dispatcher) โ€” caller surfaces that as a 500 since it represents a torn read.

deps

query dependencies

account_id

the account to build context for

type string

returns

Promise<RequestContext | null>

an account-only request context, or null if the account is missing

build_broadcast_api
#

testing/ws_round_trip.ts view source

<TApi extends object>(options: { harness: WsTestHarness; specs: readonly ({ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 7 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; })[]; }): TApi

Wire a typed broadcast API against the harness's transport, matching how a consumer's real backend composes the stack. Returns the typed API so tests can call .zap_run_created(...) / .workspace_changed(...) etc. directly.

const harness = create_ws_test_harness({actions}); const broadcast = build_broadcast_api<MyBackendActionsApi>({ harness, specs: my_broadcast_action_specs, }); const client = await harness.connect(keeper_identity()); await broadcast.zap_run_created({run_id: '...', ...}); await client.wait_for(is_notification('zap_run_created'));

options

type { harness: WsTestHarness; specs: readonly ({ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 7 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; })[]; }

returns

TApi

build_request_context
#

auth/request_context.ts view source

(deps: QueryDeps, account_id: string, actor_id: string): Promise<RequestActorContext | null>

Build a full RequestContext from an account id and an explicit actor id (already resolved via resolve_acting_actor).

Loads account + the named actor + the actor's active role_grants. Verifies the actor.account_id === account.id binding so downstream handlers can trust ctx.actor.account_id === ctx.account.id. Returns null when the account is missing, the actor is missing, or the actor doesn't belong to the supplied account.

Called by the route-spec / RPC dispatcher's authorization phase for routes that need an acting actor; account-grain routes use build_account_context instead.

deps

query dependencies

account_id

the account to build context for

type string

actor_id

the actor this request acts as

type string

returns

Promise<RequestActorContext | null>

a request context, or null if account/actor not found or mismatched

build_role_grant_offer_accepted_notification
#

auth/role_grant_offer_notifications.ts view source

(params: { offer: { id: string & $brand<"Uuid">; from_actor_id: string & $brand<"Uuid">; to_account_id: string & $brand<"Uuid">; to_actor_id: (string & $brand<"Uuid">) | null; ... 11 more ...; resulting_role_grant_id: (string & $brand<...>) | null; }; }): { ...; }

params

type { offer: { id: string & $brand<"Uuid">; from_actor_id: string & $brand<"Uuid">; to_account_id: string & $brand<"Uuid">; to_actor_id: (string & $brand<"Uuid">) | null; ... 11 more ...; resulting_role_grant_id: (string & $brand<...>) | null; }; }

returns

{ [x: string]: unknown; jsonrpc: "2.0"; method: string; params?: { [x: string]: unknown; } | undefined; }

build_role_grant_offer_declined_notification
#

auth/role_grant_offer_notifications.ts view source

(params: { offer: { id: string & $brand<"Uuid">; from_actor_id: string & $brand<"Uuid">; to_account_id: string & $brand<"Uuid">; to_actor_id: (string & $brand<"Uuid">) | null; ... 11 more ...; resulting_role_grant_id: (string & $brand<...>) | null; }; }): { ...; }

params

type { offer: { id: string & $brand<"Uuid">; from_actor_id: string & $brand<"Uuid">; to_account_id: string & $brand<"Uuid">; to_actor_id: (string & $brand<"Uuid">) | null; ... 11 more ...; resulting_role_grant_id: (string & $brand<...>) | null; }; }

returns

{ [x: string]: unknown; jsonrpc: "2.0"; method: string; params?: { [x: string]: unknown; } | undefined; }

build_role_grant_offer_received_notification
#

auth/role_grant_offer_notifications.ts view source

(params: { offer: { id: string & $brand<"Uuid">; from_actor_id: string & $brand<"Uuid">; to_account_id: string & $brand<"Uuid">; to_actor_id: (string & $brand<"Uuid">) | null; ... 11 more ...; resulting_role_grant_id: (string & $brand<...>) | null; }; }): { ...; }

params

type { offer: { id: string & $brand<"Uuid">; from_actor_id: string & $brand<"Uuid">; to_account_id: string & $brand<"Uuid">; to_actor_id: (string & $brand<"Uuid">) | null; ... 11 more ...; resulting_role_grant_id: (string & $brand<...>) | null; }; }

returns

{ [x: string]: unknown; jsonrpc: "2.0"; method: string; params?: { [x: string]: unknown; } | undefined; }

build_role_grant_offer_retracted_notification
#

auth/role_grant_offer_notifications.ts view source

(params: { offer: { id: string & $brand<"Uuid">; from_actor_id: string & $brand<"Uuid">; to_account_id: string & $brand<"Uuid">; to_actor_id: (string & $brand<"Uuid">) | null; ... 11 more ...; resulting_role_grant_id: (string & $brand<...>) | null; }; }): { ...; }

params

type { offer: { id: string & $brand<"Uuid">; from_actor_id: string & $brand<"Uuid">; to_account_id: string & $brand<"Uuid">; to_actor_id: (string & $brand<"Uuid">) | null; ... 11 more ...; resulting_role_grant_id: (string & $brand<...>) | null; }; }

returns

{ [x: string]: unknown; jsonrpc: "2.0"; method: string; params?: { [x: string]: unknown; } | undefined; }

build_role_grant_offer_supersede_notification
#

auth/role_grant_offer_notifications.ts view source

(params: { offer: { id: string & $brand<"Uuid">; from_actor_id: string & $brand<"Uuid">; to_account_id: string & $brand<"Uuid">; to_actor_id: (string & $brand<"Uuid">) | null; ... 11 more ...; resulting_role_grant_id: (string & $brand<...>) | null; }; reason: "sibling_accepted" | ... 1 more ... | "scope_destroyed"; cause_id: string & $brand<...>; }): { ...; }

params

type { offer: { id: string & $brand<"Uuid">; from_actor_id: string & $brand<"Uuid">; to_account_id: string & $brand<"Uuid">; to_actor_id: (string & $brand<"Uuid">) | null; ... 11 more ...; resulting_role_grant_id: (string & $brand<...>) | null; }; reason: "sibling_accepted" | ... 1 more ... | "scope_destroyed"; cause_id:...

returns

{ [x: string]: unknown; jsonrpc: "2.0"; method: string; params?: { [x: string]: unknown; } | undefined; }

build_role_grant_revoke_notification
#

auth/role_grant_offer_notifications.ts view source

(params: { role_grant_id: string & $brand<"Uuid">; role: string; scope_id: (string & $brand<"Uuid">) | null; reason: string | null; }): { [x: string]: unknown; jsonrpc: "2.0"; method: string; params?: { ...; } | undefined; }

params

type { role_grant_id: string & $brand<"Uuid">; role: string; scope_id: (string & $brand<"Uuid">) | null; reason: string | null; }

returns

{ [x: string]: unknown; jsonrpc: "2.0"; method: string; params?: { [x: string]: unknown; } | undefined; }

build_test_backend_paths
#

builtin_audit_log_config
#

builtin_credential_type_meta
#

auth/credential_type_schema.ts view source

ReadonlyMap<string, CredentialTypeMeta>

Builtin credential-type metadata. Not overridable by consumers.

Typed ReadonlyMap for the contract โ€” but JS Maps don't honor Object.freeze for .set / .delete / .clear (they mutate internal slots, not own properties), so freeze adds no runtime guard here. Read once at startup by create_credential_type_schema; runtime mutation has no effect on already-built schemas.

BUILTIN_CREDENTIAL_TYPES
#

builtin_grant_path_meta
#

auth/grant_path_schema.ts view source

ReadonlyMap<string, GrantPathMeta>

Builtin grant-path metadata. Not overridable by consumers.

Typed ReadonlyMap for the contract โ€” but JS Maps don't honor Object.freeze for .set / .delete / .clear (they mutate internal slots, not own properties), so freeze adds no runtime guard here. Read once at startup by create_grant_path_schema; runtime mutation has no effect on already-built schemas.

BUILTIN_GRANT_PATHS
#

builtin_role_specs_by_name
#

auth/role_schema.ts view source

ReadonlyMap<string, RoleSpec>

Builtin role specs, keyed by role name. Not overridable by consumers โ€” read once at startup by create_role_schema and the action factories that fall back to builtins when no consumer roles is supplied. ReadonlyMap encodes the contract; runtime mutation has no effect on already-built role schemas (the factory copies entries into a fresh Map).

BUILTIN_ROLES
#

BuiltinCredentialType
#

BuiltinGrantPath
#

BuiltinRole
#

cancel_action
#

actions/cancel.ts view source

Action<{ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | {...

Protocol-action tuple โ€” spread into the server's actions array (or via protocol_actions from actions/protocol.ts) so the dispatcher registers the spec for input validation and so create_rpc_client codegen sees the method. The client doesn't need to call it directly; FrontendWebsocketClient.request({signal}) sends the cancel notification automatically when the signal fires.

cancel_action_spec
#

actions/cancel.ts view source

{ method: string; kind: "remote_notification"; initiator: "frontend"; auth: null; side_effects: true; input: ZodObject<{ request_id: ZodUnion<readonly [ZodString, ZodNumber]>; }, $strict>; output: ZodVoid; async: true; description: string; }

ActionSpec for the shared cancel. auth: null matches every other remote-notification spec โ€” upgrade-time auth has already admitted the socket, so per-action auth on a fire-and-forget notification is moot. The per-connection {request_id โ†’ AbortController} map enforces socket-scoped ownership naturally: a different socket's cancel for the same id misses in its own map.

cancel_handler
#

actions/cancel.ts view source

(): void

Placeholder handler โ€” cancel semantics are owned by register_action_ws, not invoked per-handler. Exported for symmetry with the Action tuple shape; the dispatcher short-circuits cancel notifications before any handler lookup happens.

returns

void

CancelNotificationParams
#

actions/cancel.ts view source

ZodObject<{ request_id: ZodUnion<readonly [ZodString, ZodNumber]>; }, $strict>

Params for the cancel notification. request_id is the id of the pending request to abort. Must match the id of a request sent on the same socket; cancels from other sockets (or for unknown ids) are ignored.

canonicalize_ip
#

http/ip_canonical.ts view source

(ip: string): string

Canonicalize an IP address string.

Returns the RFC 5952 canonical form for parseable IPv4 or IPv6 input. Returns the input unchanged (only lowercased) when the input is non-IP ('unknown'), malformed ('attacker:controlled', '::1\n'), or any string the strict char-set filter rejects.

Idempotent. canonicalize_ip(canonicalize_ip(x)) === canonicalize_ip(x) for every input.

Order-safe for IPv4-mapped IPv6. The ::ffff: prefix strip runs AFTER the canonical emit because the canonical form of an IPv4-mapped IPv6 address is the dotted form (::ffff:127.0.0.1, not ::ffff:7f00:1). Stripping before canonicalize would miss the full-hex form. Closes the normalize_ipv4_mapped_collapse_is_order_safe test from the Rust port.

ip

type string

returns

string

examples

canonicalize_ip('::0001') // โ†’ '::1' canonicalize_ip('0:0:0:0:0:0:0:1') // โ†’ '::1' canonicalize_ip('2001:0DB8::0001') // โ†’ '2001:db8::1' canonicalize_ip('::ffff:127.0.0.1') // โ†’ '127.0.0.1' canonicalize_ip('0:0:0:0:0:ffff:7f00:1') // โ†’ '127.0.0.1' canonicalize_ip('::ffff:1') // โ†’ '::ffff:1' (NOT IPv4-mapped โ€” group[5] is 0, not ffff) canonicalize_ip('127.0.0.1') // โ†’ '127.0.0.1' canonicalize_ip('not-an-ip') // โ†’ 'not-an-ip' (passes through) canonicalize_ip('::1\n') // โ†’ '::1\n' (fails char-set; passes through) canonicalize_ip('203.0.113.1:8080') // โ†’ '203.0.113.1:8080' (passes through; validate_ip_strict rejects)

CardinalPosition
#

check_bootstrap_status
#

auth/bootstrap_routes.ts view source

(deps: CheckBootstrapStatusDeps, options: { token_path: string | null; }): Promise<BootstrapStatus>

Check bootstrap availability at startup.

Bootstrap is available when: 1. A token path is configured 2. The token file exists on disk 3. The bootstrap_lock table shows bootstrapped = false

deps

filesystem and database access for the check

options

static configuration including token_path

type { token_path: string | null; }

returns

Promise<BootstrapStatus>

an object with available (boolean) and token_path (string | null)

check_daemon_health
#

cli/daemon.ts view source

(deps: FetchDeps, port: number, host?: string, timeout_ms?: number): Promise<boolean>

Check if a daemon is healthy by probing its /health endpoint.

Complements is_daemon_running (PID check) with an HTTP liveness probe. Requires the daemon to register a /health route (e.g. via create_health_route_spec).

deps

runtime with fetch capability

port

port the daemon should be listening on

type number

host

hostname (default localhost)

type string
default 'localhost'

timeout_ms

request timeout in milliseconds (default 2000)

type number
default 2000

returns

Promise<boolean>

true if the health endpoint responds with 2xx

check_error_response_fields
#

testing/integration_helpers.ts view source

(body: Record<string, unknown>): string[]

List the fields in an error response body that are not in the known-safe set.

Error schemas use z.looseObject (intentional โ€” multiple producers), but test responses should be checked for fields that could leak information.

body

type Record<string, unknown>

returns

string[]

array of unexpected field names (empty = clean)

CheckBootstrapStatusDeps
#

auth/bootstrap_routes.ts view source

CheckBootstrapStatusDeps

Dependencies for checking bootstrap status at startup.

stat

type (path: string) => Promise<StatResult | null>

db

type Db

log

type Logger

cleanup_expired_role_grant_offers
#

auth/cleanup.ts view source

(deps: AuthCleanupDeps): Promise<number>

Sweep expired role_grant offers and emit one role_grant_offer_expire audit event per row.

Returns the count of offers audit-stamped. The offer rows themselves are preserved โ€” offers carry audit value for the history view even after expiry, and accepted rows are the provenance for the resulting role_grant (deleting expired rows would not threaten that, but keeping them uniform with the retention policy for terminal rows is simpler).

deps

returns

Promise<number>

clear_session_cookie
#

ClientApiTokenJson
#

auth/account_schema.ts view source

ZodObject<{ id: ZodString; account_id: $ZodBranded<ZodUUID, "Uuid", "out">; name: ZodString; expires_at: ZodNullable<ZodString>; last_used_at: ZodNullable<...>; last_used_ip: ZodNullable<...>; created_at: ZodString; }, $strict>

Zod schema for client-safe API token listing (excludes token_hash).

CliLogger
#

cli/logger.ts view source

CliLogger

error

Logs an error via Logger (gets Logger's error prefix).

type (...args: Array<unknown>) => void

warn

Logs a warning via Logger (gets Logger's warn prefix).

type (...args: Array<unknown>) => void

info

Logs info via Logger (gets Logger's label prefix).

type (...args: Array<unknown>) => void

debug

Logs debug via Logger (gets Logger's debug prefix).

type (...args: Array<unknown>) => void

raw

Logs raw output via Logger (no prefix, no level filtering).

type (...args: Array<unknown>) => void

success

Logs a success message with [done] prefix at info level.

type (msg: string) => void

skip

Logs a skip message with [skip] prefix at info level.

type (msg: string) => void

step

Logs a step message with ==> prefix at info level.

type (msg: string) => void

header

Logs a header with === title === decoration at info level.

type (title: string) => void

dim

Logs a dimmed message at info level.

type (msg: string) => void

logger

The underlying Logger instance.

type Logger

collect_json_keys_recursive
#

testing/integration_helpers.ts view source

(value: unknown): Set<string>

Recursively collect all key names from a parsed JSON value.

Walks objects and arrays to find every property name at any nesting depth.

value

type unknown

returns

Set<string>

collect_json_schema_property_names
#

testing/data_exposure.ts view source

(schema: unknown): Set<string>

Recursively collect all property names from a JSON Schema.

Walks properties, items, allOf/anyOf/oneOf, and additionalProperties to find every declared field name at any depth.

schema

type unknown

returns

Set<string>

collect_middleware_errors
#

http/surface.ts view source

(middleware: MiddlewareSpec[], route_path: string): Partial<Record<number, ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>>> | null

Collect error schemas from all middleware that applies to a route path.

middleware

type MiddlewareSpec[]

route_path

type string

returns

Partial<Record<number, ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>>> | null

merged middleware error schemas, or null if none

colors
#

cli/util.ts view source

{ readonly green: "" | "\u001B[32m"; readonly yellow: "" | "\u001B[33m"; readonly blue: "" | "\u001B[34m"; readonly red: "" | "\u001B[31m"; readonly cyan: "" | "\u001B[36m"; readonly dim: "" | "\u001B[2m"; readonly bold: "" | "\u001B[1m"; readonly reset: "" | "\u001B[0m"; }

ColumnInfo
#

http/db_routes.ts view source

ColumnInfo

Column metadata from information_schema.

column_name

type string

data_type

type string

is_nullable

type string

ColumnLayout
#

ColumnSnapshot
#

testing/schema_introspect.ts view source

ColumnSnapshot

Per-column structural metadata.

data_type

SQL standard type name from information_schema.columns.data_type.

type string
readonly

udt_name

Postgres-native type name from information_schema.columns.udt_name.

type string
readonly

is_nullable

true when the column accepts NULL.

type boolean
readonly

column_default

Default-value expression as Postgres reports it, or null if none.

type string | null
readonly

is_identity

true when the column was declared GENERATED ... AS IDENTITY.

type boolean
readonly

CommandDeps
#

runtime/deps.ts view source

CommandDeps

Command execution.

run_command

Run a command and return the result. Never throws โ€” failures surface as success: false.

options.cwd sets the child's working directory. options.signal aborts the child when the signal fires. options.timeout_ms kills the child after the given duration and returns timed_out: true on the result.

type ( cmd: string, args: Array<string>, options?: RunCommandOptions, ) => Promise<CommandResult>

CommandMeta
#

cli/help.ts view source

CommandMeta<TCategory>

Command metadata for help generation.

generics

TCategory

constraint string
default string

schema

type z.ZodType

summary

type string

usage

type string

category

type TCategory

CommandResult
#

runtime/deps.ts view source

CommandResult

Result of executing a command.

timed_out is present only when timeout_ms was passed in RunCommandOptions and the process was killed after exceeding the timeout. Callers that pass timeout_ms should check this flag to distinguish timeout from exit-code failure.

success

type boolean

code

type number

stdout

type string

stderr

type string

timed_out

type boolean

compile_action_registry
#

actions/compile_action_registry.ts view source

(actions: readonly Action<{ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<...>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }>[], ctx_label: string): ActionRegistryCompileResult

Validate registry-time invariants and build the dispatcher's method โ†’ action lookup.

actions

polymorphic action array; HTTP RPC passes RpcAction[] (narrower), WebSocket passes Action[] (kind-polymorphic โ€” handler-less notification specs are accepted)

type readonly Action<{ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ....

ctx_label

per-spec error-message prefix, e.g. 'RPC action' or 'WS action'. Combined with the spec method as ${ctx_label} "${method}".

type string

returns

ActionRegistryCompileResult

throws

  • Error - on biconditional violation, rate-limit/account-axis mismatch, JSON-RPC null-input, or duplicate method.

compose_gen_file
#

actions/action_codegen.ts view source

(input: { origin_path: string; imports: ImportBuilder; blocks: readonly string[]; }): string

Wrap the per-*.gen.ts boilerplate (banner + imports.build() + blocks join + template literal) into one call. Returns the full file body as a string ready to return from a Gen function.

Each consumer producer collapses to one compose_gen_file call wrapping the helper invocations.

input

type { origin_path: string; imports: ImportBuilder; blocks: readonly string[]; }

returns

string

examples

export const gen: Gen = ({origin_path}) => { const imports = new ImportBuilder(); return compose_gen_file({ origin_path, imports, blocks: [ generate_action_specs_record(all_action_specs, imports), generate_action_inputs_outputs(all_action_specs, imports), generate_action_event_datas(all_action_specs, imports), ], }); };

Empty blocks ('') are filtered out so helpers that short-circuit on empty spec sets don't introduce stray double blank lines.

confirm
#

cli/util.ts view source

(runtime: TerminalDeps, message: string): Promise<boolean>

Prompt for yes/no confirmation.

runtime

runtime with stdout_write and stdin_read capabilities

message

message to display

type string

returns

Promise<boolean>

true if user confirms, false otherwise

ConfirmButton
#

ui/ConfirmButton.svelte view source

onconfirm

type (popover: Popover) => void

popover_button_attrs?

type SvelteHTMLElements['button'] | undefined
optional

hide_on_confirm?

type boolean | undefined
optional

popover_content?

Unlike on PopoverButton this is optional and has a confirm arg

type Snippet<[popover: Popover, confirm: () => void]> | undefined
optional

popover_button_content?

Content for the popover button

type Snippet<[popover: Popover, confirm: () => void]> | undefined
optional

children?

Unlike on PopoverButton this has a confirm arg

type Snippet<[popover: Popover, confirm: () => void]> | undefined
optional

label?

Simple string content for the trigger. Mutually exclusive with children.

type string | undefined
optional

pending?

When true, the trigger is disabled and a spinner overlays the content (mirrors PendingButton). The label / children stay rendered underneath so the button keeps its size.

type boolean | undefined
optional

ConnectionCloser
#

actions/connection_closer.ts view source

ConnectionCloser

Narrow capability โ€” three idempotent socket-close methods, each returning the number of sockets actually closed (zero when none matched). Callers typically ignore the return value (used by telemetry / tests).

close_sockets_for_session

Close every connection authenticated with a session whose blake3 hash matches session_token_hash. Idempotent โ€” calling on an already-closed session is a no-op.

type (session_token_hash: string) => number

close_sockets_for_token

Close every connection authenticated with the given API token id. Idempotent โ€” calling on an already-revoked token is a no-op.

type (api_token_id: string) => number

close_sockets_for_account

Close every connection bound to account_id, regardless of credential type (session / api_token / daemon_token). Coarse closure used when every credential on an account is invalidated โ€” password change, session-revoke-all, token-revoke-all, logout. Idempotent.

type (account_id: string) => number

ConnectionIdentity
#

actions/transports_ws_backend.ts view source

ConnectionIdentity

Auth identity attached to a single WebSocket connection.

One record per connection. token_hash is set for cookie-session connections, api_token_id for bearer (api_token) connections, and both are null for daemon-token connections (reachable only via BackendWebsocketTransport.close_sockets_for_account).

token_hash

Blake3 session token hash, or null for non-session credentials.

type string | null

account_id

Authenticated account id. Always set.

type Uuid

api_token_id

api_token.id for bearer-authenticated connections, else null.

type string | null

CoverageFilterOptions
#

testing/error_coverage.ts view source

CoverageFilterOptions

Options controlling which routes/statuses are considered for coverage.

ignore_routes

Routes to skip, in 'METHOD /path' format.

type Array<string>

ignore_statuses

HTTP status codes to skip.

type Array<number>

create_account_actions
#

auth/account_actions.ts view source

(deps: Pick<RouteFactoryDeps, "log" | "audit">, options?: AccountActionOptions): RpcAction[]

Create the self-service account RPC actions.

deps

RouteFactoryDeps (log, audit, โ€ฆ). audit.emit writes audit rows via the captured pool; the bound emitter encapsulates on_audit_event fan-out and the optional AuditLogConfig.

type Pick<RouteFactoryDeps, "log" | "audit">

options

per-factory configuration

default {}

returns

RpcAction[]

the RpcAction array to spread into a create_rpc_endpoint call

create_account_route_specs
#

auth/account_routes.ts view source

(deps: RouteFactoryDeps, options: AccountRouteOptions): RouteSpec[]

Create account route specs for session-based auth.

The returned specs cover the three flows that stay REST after the RPC migration (login, logout, password change). Self-service session/token management and verify are on auth/account_actions.ts.

deps

stateless capabilities (keyring, password, log)

options

per-factory configuration (session_options, ip_rate_limiter, login_account_rate_limiter)

returns

RouteSpec[]

route specs (not yet applied to Hono)

create_account_status_route_spec
#

auth/account_routes.ts view source

(options?: AccountStatusOptions | undefined): RouteSpec

Create the account status route spec.

Handles both authenticated and unauthenticated requests: - Authenticated: returns {account} with 200 - Unauthenticated: returns 401 with optional bootstrap_available flag

This eliminates the need for a separate /health fetch on page load โ€” the frontend gets both session state and bootstrap availability in one request.

options?

optional configuration (bootstrap_status for bootstrap detection)

type AccountStatusOptions | undefined
optional

returns

RouteSpec

a single account status route spec

create_action_event
#

actions/action_event.ts view source

<TMethod extends string = string>(environment: ActionEventEnvironment, spec: { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<...>>; ... 7 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }, input: unknown, initial_phase?: "send_request" | ... 8 more ... | undefined): ActionEvent<...>

Create an action event from a spec and initial input.

environment

spec

type { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }

input

type unknown

initial_phase?

type "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute" | undefined
optional

returns

ActionEvent<TMethod, "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute", "initial" | "parsed" | "handling" | "handled" | "failed">

throws

  • Error - if `initial_phase` is omitted and the executor cannot

create_action_event_from_json
#

actions/action_event.ts view source

<TMethod extends string = string>(json: ActionEventDataUnion<TMethod>, environment: ActionEventEnvironment): ActionEvent<TMethod, "send_request" | ... 7 more ... | "execute", "initial" | ... 3 more ... | "failed">

Reconstruct an action event from serialized JSON data.

json

type ActionEventDataUnion<TMethod>

environment

returns

ActionEvent<TMethod, "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute", "initial" | "parsed" | "handling" | "handled" | "failed">

throws

  • Error - if the JSON's `method` field has no spec registered in `environment`

create_action_event_spec
#

actions/action_bridge.ts view source

(spec: { method: string; kind: "request_response" | "remote_notification" | "local_call"; initiator: "frontend" | "backend" | "both"; auth: { account: "none" | "optional" | "required"; actor: "none" | ... 1 more ... | "required"; roles?: readonly string[] | undefined; credential_types?: readonly string[] | undefined; } | null; ... 7 more ...; rate_limit?: "both" | ... 2 more ... | undefined; }, options?: ActionEventOptions | undefined): EventSpec

Derive an EventSpec from an ActionSpec.

Only remote_notification actions can become push events.

spec

the action spec (must have kind: 'remote_notification')

type { method: string; kind: "request_response" | "remote_notification" | "local_call"; initiator: "frontend" | "backend" | "both"; auth: { account: "none" | "optional" | "required"; actor: "none" | ... 1 more ... | "required"; roles?: readonly string[] | undefined; credential_types?: readonly string[] | undefined; } | n...

options?

optional event-specific options (channel)

type ActionEventOptions | undefined
optional

returns

EventSpec

throws

  • Error - if `spec.kind` is not `'remote_notification'`

create_action_route_spec
#

actions/action_bridge.ts view source

(spec: { method: string; kind: "request_response" | "remote_notification" | "local_call"; initiator: "frontend" | "backend" | "both"; auth: { account: "none" | "optional" | "required"; actor: "none" | ... 1 more ... | "required"; roles?: readonly string[] | undefined; credential_types?: readonly string[] | undefined; } | null; ... 7 more ...; rate_limit?: "both" | ... 2 more ... | undefined; }, options: ActionRouteOptions): RouteSpec

Derive a RouteSpec from an ActionSpec and options.

Only request_response actions (which require non-null auth) can become routes. remote_notification actions (auth null) should use create_action_event_spec. local_call actions are not for HTTP transport.

Error schemas are transport-specific (keyed by HTTP status codes) and belong on the options, not the action spec. Action specs define the contract; transport concerns like HTTP error codes are added at the bridge layer.

spec

the action spec (must have non-null auth)

type { method: string; kind: "request_response" | "remote_notification" | "local_call"; initiator: "frontend" | "backend" | "both"; auth: { account: "none" | "optional" | "required"; actor: "none" | ... 1 more ... | "required"; roles?: readonly string[] | undefined; credential_types?: readonly string[] | undefined; } | n...

options

HTTP-specific options (path, handler, optional overrides)

returns

RouteSpec

throws

  • Error - if `spec.auth` is null (only `request_response` actions can

create_actor_lookup_actions
#

create_actor_search_actions
#

create_admin_actions
#

auth/admin_actions.ts view source

(deps: Pick<RouteFactoryDeps, "log" | "audit">, options?: AdminActionOptions): RpcAction[]

Create the admin-only RPC actions.

deps

RouteFactoryDeps (log, audit, โ€ฆ). log drives RPC- internal error logging; audit.emit writes audit rows via the captured pool. The bound emitter encapsulates on_audit_event fan-out and the optional AuditLogConfig.

type Pick<RouteFactoryDeps, "log" | "audit">

options

role schema for grantable_roles derivation

default {}

returns

RpcAction[]

the RpcAction array to spread into a create_rpc_endpoint call

create_admin_rpc_adapters
#

ui/admin_rpc_adapters.ts view source

(api: AdminRpcApi): AdminRpcAdapters

Build the four admin RPC adapters from a typed throwing RPC client.

Method-name mapping:

| Narrow RPC method | Action spec method | | ----------------------------------- | ---------------------------- | | admin_accounts.list_accounts | admin_account_list | | admin_accounts.list_sessions | admin_session_list | | admin_accounts.create_role_grant | role_grant_offer_create | | admin_accounts.revoke_role_grant | role_grant_revoke | | admin_accounts.retract_offer | role_grant_offer_retract | | admin_accounts.session_revoke_all | admin_session_revoke_all | | admin_accounts.token_revoke_all | admin_token_revoke_all | | admin_invites.list | invite_list | | admin_invites.create | invite_create | | admin_invites.delete | invite_delete | | audit_log.list | audit_log_list | | audit_log.role_grant_history | audit_log_role_grant_history | | app_settings.get | app_settings_get | | app_settings.update | app_settings_update |

All four adapter factories call through the same api โ€” consumers pass the typed throwing Proxy from create_frontend_rpc_client once, regardless of how many admin surfaces they mount.

api

returns

AdminRpcAdapters

create_app_backend
#

server/app_backend.ts view source

(options: CreateAppBackendOptions): Promise<AppBackend>

Initialize the backend: database + auth migrations + deps.

Calls create_db โ†’ run_migrations (auth namespace, then any migration_namespaces from options in order) โ†’ audit_factory({db, log}) and bundles the result with the provided keyring and password deps.

options

keyring, password deps, audit_factory, optional database URL, and optional migration_namespaces

returns

Promise<AppBackend>

app backend with deps, database metadata, and combined migration results

throws

  • Error - if `migration_namespaces` contains a namespace in `reserved_migration_namespaces`

create_app_server
#

server/app_server.ts view source

(options: AppServerOptions): Promise<AppServer>

Create a fully assembled Hono app with auth, middleware, and routes.

Handles the assembly lifecycle: proxy middleware โ†’ auth middleware โ†’ bootstrap status โ†’ route specs โ†’ surface generation โ†’ Hono app assembly โ†’ static serving. Database migrations belong to the backend lifecycle โ€” pass migration_namespaces to create_app_backend.

When audit_log_sse is set, the SSE registry's listener is appended to backend.deps.audit.on_event_chain โ€” no shallow-copy of AppDeps. The audit_sse field on the returned AppServer (and the AppServerContext passed to create_route_specs) is non-null in that case; consumers can call require_audit_sse(ctx) / require_audit_sse(server) to assert the invariant.

options

returns

Promise<AppServer>

assembled Hono app, backend, surface build, and bootstrap status

create_app_surface_spec
#

create_audit_emitter
#

create_audit_log_config
#

auth/audit_log_schema.ts view source

(options?: CreateAuditLogConfigOptions | undefined): AuditLogConfig

Build an AuditLogConfig by merging fuz_app builtins with consumer extras.

Throws when an extra_events key collides with a builtin event type, or fails AuditEventTypeName format validation.

Call once at startup; pass the result into the consumer's audit_factory body โ€” typically `({db, log}) => create_audit_emitter({db, log, audit_log_config, ...})` โ€” so it gets captured inside the bound AppDeps.audit emitter. Builtin handlers omit the audit_log_config slot and pick up builtin_audit_log_config.

options?

type CreateAuditLogConfigOptions | undefined
optional

returns

AuditLogConfig

throws

  • Error - when an `extra_events` key collides with a builtin event type or fails `AuditEventTypeName` format validation

create_audit_log_route_specs
#

auth/audit_log_routes.ts view source

(options?: AuditLogRouteOptions | undefined): RouteSpec[]

Create the optional audit-log SSE route spec.

Returns an empty array when options.stream is not set โ€” no REST routes live here apart from the stream.

options?

optional stream wiring + role override

type AuditLogRouteOptions | undefined
optional

returns

RouteSpec[]

the SSE route spec (when options.stream is provided) or an empty array

create_audit_log_sse
#

realtime/sse_auth_guard.ts view source

(options: { role?: string | undefined; log: Logger; max_per_scope?: number | null | undefined; }): AuditLogSse

Create a complete audit log SSE setup with broadcasting and auth guard.

Combines SubscriberRegistry, create_sse_auth_guard, and the broadcast call into a single object. The result satisfies AuditLogRouteOptions['stream'] and provides the on_audit_event listener for the audit emitter's chain.

Most consumers pass audit_log_sse: true to create_app_server and never touch this directly โ€” the factory builds an AuditLogSse, appends audit_sse.on_audit_event to backend.deps.audit.on_event_chain, and exposes it via AppServerContext.audit_sse. Reach for the manual path (compose inside audit_factory body, or audit.on_event_chain.push(audit_sse.on_audit_event) post-assembly) only when wiring outside create_app_server.

options

factory options

type { role?: string | undefined; log: Logger; max_per_scope?: number | null | undefined; }

returns

AuditLogSse

audit log SSE setup (stream options + on_audit_event + registry)

examples

const audit_sse = create_audit_log_sse({log}); // Inside the audit_factory body on CreateAppBackendOptions: audit_factory: ({db, log}) => create_audit_emitter({ db, log, on_audit_event: audit_sse.on_audit_event, }), // In create_route_specs: create_audit_log_route_specs({stream: audit_sse}); // In create_app_server options: event_specs: audit_log_event_specs,

create_auth_middleware_specs
#

auth/middleware.ts view source

(deps: AppDeps, options: AuthMiddlewareOptions): Promise<MiddlewareSpec[]>

Create the auth middleware stack.

Returns [origin, session, request_context, bearer_auth] middleware specs for the given path pattern. When daemon_token_state is provided, appends a 5th daemon_token layer. Apps can append extra entries for non-standard paths (e.g., tx's /tx binary endpoint).

deps

stateless capabilities (keyring, db)

type AppDeps

options

middleware configuration (allowed_origins, session_options, path, daemon_token_state)

returns

Promise<MiddlewareSpec[]>

the middleware spec array

create_auth_test_apps
#

testing/auth_apps.ts view source

(route_specs: RouteSpec[], roles: string[]): AuthTestApps

Create one Hono test app per auth level.

route_specs

the route specs to register

type RouteSpec[]

roles

all roles in the app

type string[]

returns

AuthTestApps

create_banner
#

create_bearer_auth_middleware
#

auth/bearer_auth.ts view source

(deps: QueryDeps, ip_rate_limiter: RateLimiter | null, log: Logger): MiddlewareHandler

Create middleware that authenticates via bearer token.

Soft-fails for invalid, expired, or empty tokens โ€” calls next() without setting account identity, letting downstream auth enforcement (the RPC dispatcher's pre-validation / post-authorization auth gates or require_auth) return a consistent JSON-RPC or route-level error. This avoids leaking token-specific diagnostics (invalid_token, account_not_found) that could aid enumeration attacks, and ensures public actions are not blocked by bad credentials.

Rejects bearer tokens when an Origin or Referer header is present โ€” browsers must use cookie auth to reduce attack surface. Auth scheme matching is case-insensitive per RFC 7235. On success, sets c.var.auth_account_id, CREDENTIAL_TYPE_KEY = 'api_token', and AUTH_API_TOKEN_ID_KEY. Skips when an account is already authenticated (e.g. by session middleware). Acting-actor resolution + RequestContext construction are deferred to the dispatcher's authorization phase.

Rate limiting (429) is the only hard-fail โ€” it's a throttling concern independent of auth identity.

deps

query dependencies (pool-level db for middleware)

ip_rate_limiter

per-IP rate limiter for bearer token attempts (null to disable)

type RateLimiter | null

log

the logger instance

type Logger

returns

MiddlewareHandler

create_bearer_auth_mocks
#

create_bearer_auth_test_app
#

testing/middleware.ts view source

(tc: BearerAuthTestOptions, ip_rate_limiter?: RateLimiter | null): { app: Hono<BlankEnv, BlankSchema, "/">; mocks: BearerAuthMocks; }

Create a Hono app wired with create_bearer_auth_middleware using mocked deps.

The route handler at /api/test returns the resolved context in the response body, enabling assertions on REQUEST_CONTEXT_KEY and CREDENTIAL_TYPE_KEY.

tc

ip_rate_limiter

type RateLimiter | null
default null

returns

{ app: Hono<BlankEnv, BlankSchema, "/">; mocks: BearerAuthMocks; }

create_bootstrap_route_specs
#

auth/bootstrap_routes.ts view source

(deps: RouteFactoryDeps, options: BootstrapRouteOptions): RouteSpec[]

Create bootstrap route specs for first-time account creation.

deps

stateless capabilities including filesystem access

options

per-factory configuration (session, token path, bootstrap status)

returns

RouteSpec[]

route specs (not yet applied to Hono)

create_broadcast_api
#

actions/broadcast_api.ts view source

<TApi extends object>(options: CreateBroadcastApiOptions): TApi

Builds a typed broadcast API from a set of action specs.

For each spec, adds a method keyed by spec.method that: - Validates input against the spec's Zod schema (logs and returns on failure) - Creates a JSON-RPC notification from the validated input - Broadcasts via the peer (filtered by should_deliver when supplied)

Silently returns when no transport is ready (e.g. before any clients connect). Errors during send are logged but never thrown โ€” broadcasts are fire-and-forget from the handler's perspective.

Typed consumer surface

Consumers declare an explicit interface and pin it via the type parameter:

export interface BackendActionsApi { filer_change: (input: ActionInputs['filer_change']) => Promise<void>; workspace_changed: (input: ActionInputs['workspace_changed']) => Promise<void>; } const api = create_broadcast_api<BackendActionsApi>({ peer: backend.peer, specs: [filer_change_action_spec, workspace_changed_action_spec], });

The cast is unchecked โ€” callers must keep the interface and the specs array in sync. Codegen (action_collections.gen.ts) is a natural fit if the consumer already generates per-method type maps.

options

returns

TApi

create_cli_logger
#

cli/logger.ts view source

(logger: Logger): CliLogger

Creates a CLI logger wrapping a Logger with semantic output methods.

logger

the Logger instance to wrap

type Logger

returns

CliLogger

a CliLogger with CLI semantic methods mapped to Logger levels

create_credential_type_schema
#

auth/credential_type_schema.ts view source

(consumer_types?: Record<string, CredentialTypeMeta>): CredentialTypeSchemaResult

Create a credential-type schema from the builtin set plus optional consumer-declared additions.

Builtins (session, api_token, daemon_token) are always present; consumer entries that collide with a builtin name throw at construction. Pass the result into create_role_schema's optional credential_types parameter so each role's required_credential_types entries are validated against this set at construction time.

consumer_types

optional consumer-declared credential-type set with optional metadata

type Record<string, CredentialTypeMeta>
default {}

returns

CredentialTypeSchemaResult

{CredentialType, credential_types} โ€” Zod schema and metadata map

throws

  • Error - if any `consumer_types` key fails the `CredentialTypeName` regex, collides with a builtin name, or appears more than once

examples

// simple โ€” builtins only const {CredentialType, credential_types} = create_credential_type_schema(); // with consumer extensions const {CredentialType} = create_credential_type_schema({ sso_assertion: {description: 'OIDC SSO assertion bound to an IdP-asserted account.'}, });

create_daemon_token_middleware
#

auth/daemon_token_middleware.ts view source

(state: DaemonTokenState, deps: QueryDeps): MiddlewareHandler

Create middleware that authenticates via daemon token.

Checks the X-Daemon-Token header. Behavior: - No header: pass through (don't touch existing context). - Header present + Zod-invalid: return 401 (fail-closed). - Header present + invalid value: return 401 (fail-closed, no downgrade). - Header present + valid + keeper_account_id null: return 503. - Header present + valid + ok: set `c.var.auth_account_id = state.keeper_account_id, CREDENTIAL_TYPE_KEY = 'daemon_token'` (overrides any existing session / bearer identity).

Acting-actor resolution + RequestContext construction are deferred to the dispatcher's authorization phase. Multi-actor keeper accounts surface actor_required from there if a daemon caller doesn't pass an explicit acting value.

state

the daemon token runtime state

deps

returns

MiddlewareHandler

create_database
#

dev/setup.ts view source

(deps: CommandDeps, db_name: string, options?: CreateDatabaseOptions | undefined): Promise<CommandResult>

Create a PostgreSQL database if createdb is available.

Does not throw โ€” returns the underlying command result so callers can decide how to react to a missing createdb or an "already exists" failure.

deps

command execution capability

db_name

database name to create

type string

options?

logger

type CreateDatabaseOptions | undefined
optional

returns

Promise<CommandResult>

the command result

create_db
#

db/create_db.ts view source

(database_url: string): Promise<CreateDbResult>

Create a database connection based on a URL.

The close callback is bound to the actual driver โ€” callers never need to know which driver is in use.

For direct driver construction without URL routing, import create_pg_db from db/db_pg.ts or create_pglite_db from db/db_pglite.ts.

database_url

connection URL (postgres://, postgresql://, file://, or memory://)

type string

returns

Promise<CreateDbResult>

database instance, close callback, type, and display name

throws

  • Error - if `database_url` uses an unsupported scheme. Driver

create_db_route_specs
#

create_deno_runtime
#

runtime/deno.ts view source

(args: readonly string[]): RuntimeDeps

Create a runtime backed by Deno APIs.

Returns an object satisfying all *Deps interfaces from runtime/deps.ts. Pass to shared functions that accept EnvDeps, FsReadDeps, etc.

args

CLI arguments (typically Deno.args)

type readonly string[]

returns

RuntimeDeps

runtime implementation using Deno APIs

create_describe_db
#

testing/db.ts view source

(factories: DbFactory | DbFactory[], truncate_tables: string[]): (name: string, fn: (get_db: () => Db) => void) => void

Create a describe_db function bound to specific factories and truncate tables.

Returns a 2-arg (name, fn) function that runs the test suite against each factory. Each factory gets its own describe block with a shared database instance, automatic beforeEach truncation, and afterAll cleanup. Skipped factories use describe.skip.

factories

one or more database factories to run suites against

type DbFactory | DbFactory[]

truncate_tables

tables to truncate between tests (children first for FK safety)

type string[]

returns

(name: string, fn: (get_db: () => Db) => void) => void

create_emit_ordering_audit_factory
#

testing/audit_drift_guard.ts view source

<E extends { kind: string; at: number; }>(seq_ref: { value: number; }, events_ref: (AuditEmitMarker | E)[], extra_options?: Omit<CreateAuditEmitterOptions, "db" | ... 1 more ... | "emit_decorator"> | undefined): AuditFactory

Build an audit_factory that produces a real create_audit_emitter with its emit decorated to push a {kind: 'emit', at: seq.value++} marker into a shared sequence + events array. Used by the close-vs-emit ordering test to compose against a shared sequence counter (typically create_recording_closer(seq_ref) capturing eager-close calls).

Pass the returned factory through create_test_app({audit_factory: โ€ฆ}) โ€” the test backend invokes it with its constructed {db, log} and lands the decorated emitter on backend.deps.audit. Production handlers dereference deps.audit.emit at call time, so the decorator sees every subsequent handler invocation. The underlying emit still runs โ€” the decorator records the call, it does not suppress side effects.

Scope โ€” both emit and emit_role_grant_target. The decorator is captured by emit_role_grant_target's closure inside create_audit_emitter (and re-exposed as the outer emit slot), so role-grant-shape emissions land in events_ref alongside bare emit calls. emit_pool and notify are not decorated โ€” they take AuditLogInput / AuditLogEvent directly without going through emit, so handler-side emit_pool writes (today only auth/cleanup.ts) skip capture. Close-firing handlers all reach for emit or emit_role_grant_target, so the ordering test sees them regardless of which entry point a future refactor picks.

Optionally accept extra_options to thread on_audit_event / audit_log_config into the inner emitter โ€” useful when a test wants both ordering capture and a real SSE/WS guard wired into the same emitter chain.

seq_ref

type { value: number; }

events_ref

type (AuditEmitMarker | E)[]

extra_options?

type Omit<CreateAuditEmitterOptions, "db" | "log" | "emit_decorator"> | undefined
optional

returns

AuditFactory

create_expired_test_cookie
#

create_extract_global_flags
#

cli/args.ts view source

<T extends Record<string, unknown>>(schema: ZodType<T, unknown, $ZodTypeInternals<T, unknown>>, fallback: T): (unparsed: ParsedArgs) => { flags: T; remaining: ParsedArgs; }

Create a project-specific global flag extractor.

Returns a function that separates global flags from command-specific args. The schema defines which flags are global (with aliases via .meta({aliases})), and the fallback provides defaults when parsing fails.

schema

Zod schema for global flags

type ZodType<T, unknown, $ZodTypeInternals<T, unknown>>

fallback

default values when parsing fails

type T

returns

(unparsed: ParsedArgs) => { flags: T; remaining: ParsedArgs; }

extractor function (unparsed) => {flags, remaining}

create_fake_hono_context
#

testing/ws_round_trip.ts view source

(opts: FakeHonoContextOptions): Context<any, any, {}>

Build a fake Hono Context exposing the auth keys the dispatcher reads via c.get(...). Only .get() is populated โ€” no other Hono context surface is simulated.

opts

returns

Context<any, any, {}>

create_fake_ws
#

testing/ws_round_trip.ts view source

(): FakeWs

Build a real WSContext backed by in-memory send/close capture. Parsing of outgoing frames is left to the caller โ€” sends holds the raw strings as the dispatcher wrote them.

returns

FakeWs

create_fetch_transport
#

testing/transports/fetch_transport.ts view source

(options: FetchTransportOptions): FetchTransport

Build a cookie-threading transport pinned to options.base_url. The returned function carries a private Map<name, cookie-head> jar that updates on every response's Set-Cookie and re-sends on every subsequent request.

Request rewriting:

- Absolute URLs (http://other.example/...) pass through verbatim โ€” handy for cross-origin negative tests that target a deliberately different host. - Relative URLs are resolved against base_url. - Origin is set to options.origin ?? base_url unless the caller already provided one. - Cookie is set from the jar unless the caller already provided one.

options

returns

FetchTransport

create_frontend_rpc_client
#

actions/frontend_rpc_client.ts view source

<TApi extends object>(options: CreateFrontendRpcClientOptions<TApi>): FrontendRpcClient<TApi>

Build a frontend-only typed RPC client. See module doc for the bundle's design.

options

type CreateFrontendRpcClientOptions<TApi>

returns

FrontendRpcClient<TApi>

create_fuz_authorization_handler
#

auth/request_context.ts view source

(deps: QueryDeps): (c: Context<any, any, {}>, spec: RouteSpec) => Promise<void | Response>

Create the route-spec authorization handler used by apply_route_specs.

Reads acting off c.var.validated_input (or c.var.validated_query for GET routes) โ€” input validation runs first, so the authorization phase consumes the typed Zod field instead of pre-parsing the body. Public routes (auth.account === 'none' && auth.actor === 'none') skip the phase entirely.

Per registry-time invariant 2, auth.actor !== 'none' โŸบ the input (or query) schema declares acting?: ActingActor โ€” so reading from c.var.validated_input.acting / c.var.validated_query.acting is type-safe.

Resolved contexts land on REQUEST_CONTEXT_KEY so the post-authorization REST middleware (require_role, require_credential_types) reads the actor-bound context off c.var. The HTTP RPC and WS dispatchers consume the apply_authorization_phase outcome directly without round-tripping through c.var.

deps

returns

(c: Context<any, any, {}>, spec: RouteSpec) => Promise<void | Response>

create_grant_path_schema
#

auth/grant_path_schema.ts view source

(consumer_paths?: Record<string, GrantPathMeta>): GrantPathSchemaResult

Create a grant-path schema from the builtin set plus optional consumer-declared additions.

Builtins (admin, self_service, system, bootstrap) are always present; consumer entries that collide with a builtin name throw at construction. Pass the result into create_role_schema's optional grant_paths parameter so each role's grant_paths entries are validated against this set at construction time.

consumer_paths

optional consumer-declared grant-path set with optional metadata

type Record<string, GrantPathMeta>
default {}

returns

GrantPathSchemaResult

{GrantPath, grant_paths} โ€” Zod schema and metadata map

throws

  • Error - if any `consumer_paths` key fails the `GrantPathName` regex, collides with a builtin name, or appears more than once

examples

// simple โ€” builtins only const {GrantPath, grant_paths} = create_grant_path_schema(); // with consumer extensions const {GrantPath} = create_grant_path_schema({ invite_only: {description: 'Granted by claiming a consumer-issued invite.'}, });

create_health_route_spec
#

http/common_routes.ts view source

(): RouteSpec

Create a public health check route spec.

Infrastructure endpoint for uptime monitors and load balancers. Bootstrap availability is exposed via /api/account/status instead.

returns

RouteSpec

create_help
#

cli/help.ts view source

<TCategory extends string>(options: HelpOptions<TCategory>): HelpGenerator

Create a help generator configured for an application.

options

help configuration

type HelpOptions<TCategory>

returns

HelpGenerator

help generator with generate_main_help, generate_command_help, and get_help_text

create_initial_data
#

actions/action_event_helpers.ts view source

(kind: "request_response" | "remote_notification" | "local_call", phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute", method: string, executor: "frontend" | "backend", input: unknown): { ...; }

kind

type "request_response" | "remote_notification" | "local_call"

phase

type "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"

method

type string

executor

type "frontend" | "backend"

input

type unknown

returns

{ kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }

create_jsonrpc_error_response
#

http/jsonrpc_helpers.ts view source

(id: string | number | null, error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<"JsonrpcServerErrorCode">); message: string; data?: unknown; }): { ...; }

Creates a JSON-RPC error response message.

id

type string | number | null

error

type { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<"JsonrpcServerErrorCode">); message: string; data?: unknown; }

returns

{ [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<"JsonrpcServerErrorCode">); message: string; data?: unknown; }; }

create_jsonrpc_error_response_from_thrown
#

http/jsonrpc_helpers.ts view source

(id: string | number | null, error: unknown): { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<...>); message: string; data?: unknown; }; }

Creates a JSON-RPC error response from any error. Handles ThrownJsonrpcError (preserves code/message/data) and regular Error objects (maps to internal_error, includes stack in DEV).

id

type string | number | null

error

type unknown

returns

{ [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<"JsonrpcServerErrorCode">); message: string; data?: unknown; }; }

create_jsonrpc_notification
#

http/jsonrpc_helpers.ts view source

(method: string, params: { [x: string]: unknown; } | undefined): { [x: string]: unknown; jsonrpc: "2.0"; method: string; params?: { [x: string]: unknown; } | undefined; }

Creates a JSON-RPC notification message (no id, no response expected).

method

type string

params

type { [x: string]: unknown; } | undefined

returns

{ [x: string]: unknown; jsonrpc: "2.0"; method: string; params?: { [x: string]: unknown; } | undefined; }

create_jsonrpc_request
#

http/jsonrpc_helpers.ts view source

(method: string, params: { [x: string]: unknown; } | undefined, id: string | number): { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }

Creates a JSON-RPC request message.

method

type string

params

type { [x: string]: unknown; } | undefined

id

type string | number

returns

{ [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }

create_jsonrpc_response
#

http/jsonrpc_helpers.ts view source

(id: string | number, result: JSONType): { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; }

Creates a JSON-RPC success response message.

id

type string | number

result

type JSONType

returns

{ [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; }

create_keyring
#

auth/keyring.ts view source

(env_value: string | undefined): Keyring | null

Create a keyring from environment variable.

Keys are separated by __ for rotation support. First key is used for signing, all keys are tried for verification.

CryptoKeys are cached on first use for performance.

Security: key rotation is an operational concern. Old keys remain valid for verification indefinitely โ€” a leaked old key can forge session cookies until it is removed from SECRET_FUZ_COOKIE_KEYS. After rotating to a new signing key, remove the old key within a grace period (e.g. 24โ€“48 hours, long enough for active sessions to re-sign with the new key via cookie refresh). Treat SECRET_FUZ_COOKIE_KEYS changes as security-critical deploys.

env_value

the SECRET_FUZ_COOKIE_KEYS environment variable

type string | undefined

returns

Keyring | null

keyring or null if no keys configured

create_mock_fs
#

testing/mock_fs.ts view source

(initial_files?: Record<string, string>): MockFs

Creates an in-memory file system for tests.

read_file throws an ENOENT-tagged error for missing paths so callers can exercise the same "file doesn't exist" code path as node:fs.

initial_files

type Record<string, string>
default {}

returns

MockFs

create_mock_runtime
#

runtime/mock.ts view source

(args?: string[]): MockRuntime

Create a mock RuntimeDeps for testing.

The mock exit records the code on exit_calls and throws MockExitError (so the never-returning contract holds in tests). fetch throws TypeError when no mock_fetch_responses pattern matches the request URL.

args

type string[]
default []

returns

MockRuntime

MockRuntime with controllable state

examples

const runtime = create_mock_runtime(['apply', 'zap.ts']); runtime.mock_env.set('HOME', '/home/test'); runtime.mock_fs.set('/home/test/.app/config.json', '{}'); await some_function(runtime); assert.strictEqual(runtime.command_calls.length, 1); assert.deepStrictEqual(runtime.exit_calls, [0]);

create_namespace_qualifier
#

actions/action_codegen.ts view source

(sources: readonly SpecSource[], imports: ImportBuilder): { qualify_spec: (spec: { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; ... 8 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }) => string; all_specs: readonly ({ ...; } | ... 1 more ... | { ...; })[]; }

Multi-source consumer helper. Takes a list of {ns, module, specs} rows, registers import * as ns from module for each on imports, builds the method_to_ns lookup with duplicate-method detection, and returns {qualify_spec, all_specs} ready to thread through the high-level helpers.

Closes the per-file boilerplate gap that kept tx + visiones on hand-rolled template strings even after qualify_spec? landed in API review II โ€” the per-call callback wasn't enough; the import dance + dup-check was the real boilerplate.

sources

type readonly SpecSource[]

imports

returns

{ qualify_spec: (spec: { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<...>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }) => string; all_specs: rea...

throws

  • Error - if two sources contain the same method name (same-method

examples

const sources = [ {ns: 'tx_specs', module: './action_specs.js', specs: all_zap_action_specs}, {ns: 'admin_specs', module: '@fuzdev/fuz_app/auth/admin_action_specs.js', specs: all_admin_action_specs}, ]; export const gen: Gen = ({origin_path}) => { const imports = new ImportBuilder(); const {qualify_spec, all_specs} = create_namespace_qualifier(sources, imports); return compose_gen_file({ origin_path, imports, blocks: [ generate_action_specs_record(all_specs, imports, {qualify_spec}), generate_action_inputs_outputs(all_specs, imports, {qualify_spec}), ], }); };

create_node_runtime
#

runtime/node.ts view source

(args?: readonly string[]): RuntimeDeps

Create a RuntimeDeps backed by Node.js APIs.

args

CLI arguments (typically process.argv.slice(2))

type readonly string[]
default process.argv.slice(2)

returns

RuntimeDeps

RuntimeDeps implementation using Node.js runtime

create_noop_stub
#

testing/stubs.ts view source

<T = any>(_label: string, overrides?: Record<string, unknown> | undefined): T

Create a Proxy where every method access returns a no-op async function.

Use for deps that may be reached during "correct auth passes guard" tests but whose return values don't matter. Unlike the explicit method listing, this auto-updates when interfaces change.

_label

type string

overrides?

explicit properties to set (e.g. {db: stub_db})

type Record<string, unknown> | undefined
optional

returns

T

create_pg_db
#

db/db_pg.ts view source

(pool: Pool): DbDriverResult

Create a Db backed by a pg.Pool.

Owns the transaction implementation, acquiring a dedicated pool client per transaction.

pool

an already-constructed pg.Pool

type Pool

returns

DbDriverResult

the Db instance and a close callback bound to pool.end()

create_pg_factory
#

testing/db.ts view source

(init_schema: (db: Db) => Promise<void>, test_url?: string | undefined): DbFactory

Create a pg (PostgreSQL) database factory for tests.

Skipped when test_url is not provided. Drops schema_version before running init_schema, forcing migrations to re-evaluate against the actual tables. Prevents stale tracker rows from skipping migrations when DDL changes between test sessions.

For full clean-slate behavior (recommended), call drop_auth_schema(db) at the start of init_schema before running migrations. This handles upstream schema changes that go beyond adding new tables/columns.

init_schema

callback to initialize the database schema

type (db: Db) => Promise<void>

test_url?

PostgreSQL connection URL (e.g. from TEST_DATABASE_URL)

type string | undefined
optional

returns

DbFactory

a factory that creates pg databases. The returned create() throws when test_url is unset (despite the skip: true flag โ€” defense against direct invocation), and rewrites Postgres "database does not exist" errors into a createdb hint message.

create_pglite_db
#

db/db_pglite.ts view source

(pglite: PGlite): DbDriverResult

Create a Db backed by a PGlite instance.

Delegates transactions to PGlite's native transaction() method.

pglite

an already-constructed PGlite instance

type PGlite

returns

DbDriverResult

the Db instance and a close callback bound to pglite.close()

create_pglite_factory
#

testing/db.ts view source

(init_schema: (db: Db) => Promise<void>): DbFactory

Create a pglite (in-memory) database factory for tests.

Always enabled โ€” no external dependencies required. Shares a single PGlite WASM instance across all factories in the same vitest worker thread (one test file). Subsequent create() calls reset the schema via DROP SCHEMA public CASCADE instead of paying the WASM cold-start cost again.

init_schema

callback to initialize the database schema

type (db: Db) => Promise<void>

returns

DbFactory

create_proxy_middleware
#

http/proxy.ts view source

(options: ProxyOptions): MiddlewareHandler

Create a Hono middleware that resolves the client IP from trusted proxies.

Sets client_ip on the Hono context for downstream use by get_client_ip. All client IPs are normalized (lowercase, IPv4-mapped IPv6 stripped).

Resolution logic: 1. No X-Forwarded-For โ†’ use connection IP directly. 2. X-Forwarded-For present but connection is untrusted โ†’ ignore header (spoofed by a direct attacker), use connection IP. 3. X-Forwarded-For present and connection is trusted โ†’ walk header right-to-left, strip trusted entries, use first untrusted entry.

options

trusted proxy configuration

returns

MiddlewareHandler

throws

  • Error - if any entry in `options.trusted_proxies` is invalid (parsed eagerly via `parse_proxy_entry`)

create_proxy_middleware_spec
#

http/proxy.ts view source

(options: ProxyOptions): MiddlewareSpec

Create a middleware spec for trusted proxy resolution.

Apply before auth middleware so client_ip is available for rate limiting.

options

trusted proxy configuration

returns

MiddlewareSpec

create_rate_limiter
#

rate_limiter.ts view source

(options?: Partial<RateLimiterOptions> | undefined): RateLimiter

Create a RateLimiter with sensible defaults for per-IP login protection.

options?

override individual options; unset fields use default_login_ip_rate_limit

type Partial<RateLimiterOptions> | undefined
optional

returns

RateLimiter

create_recording_audit_emitter
#

testing/audit_drift_guard.ts view source

(calls_ref?: AuditLogInput<"invite_create" | "invite_delete" | "app_settings_update" | "login" | "logout" | "bootstrap" | "signup" | "password_change" | "session_revoke" | "session_revoke_all" | ... 10 more ... | "role_grant_offer_supersede">[] | undefined): RecordingAuditEmitter

Build a no-op AuditEmitter that records every emit, emit_pool, and emit_role_grant_target call into calls as an AuditLogInput. Use to capture audit metadata shapes in unit tests (e.g. password change failure outcome, role-grant create denial) without standing up the full PGlite + query_audit_log pipeline.

Capture scope โ€” all four production fan-out shapes. emit_role_grant_target mirrors create_audit_emitter's lift logic in place โ€” actor_id / account_id / ip are populated from auth + ctx and the event_type / outcome / target_*_id / metadata fields forward from the input envelope. Tests asserting on role-grant-shape emissions read out of the same homogeneous calls array. notify is a no-op; on_event_chain is an empty array.

emit AND emit_pool both append to calls so cleanup-sweep tests (which use emit_pool exclusively โ€” see auth/cleanup.ts) can also read assertions off the same array.

Pass calls_ref to write into a caller-owned array (callers that declared const events: Array<AuditLogInput> = [] and want to keep the reference). Omit to let the helper allocate a fresh array and return it on the calls field of the result.

The returned emitter is deliberately NOT frozen โ€” slots stay mutable so a test can override one when it needs bespoke shape (e.g. an emit_pool that throws on the first call). The production create_audit_emitter freeze invariant exists to catch the patch_audit_emit_capture hot-patch footgun against the closure-captured emit; the recording emitter has no inner closure, so the freeze isn't load-bearing here.

calls_ref?

type AuditLogInput<"invite_create" | "invite_delete" | "app_settings_update" | "login" | "logout" | "bootstrap" | "signup" | "password_change" | "session_revoke" | "session_revoke_all" | ... 10 more ... | "role_grant_offer_supersede">[] | undefined
optional

returns

RecordingAuditEmitter

create_recording_closer
#

testing/connection_closer_helpers.ts view source

(seq_ref?: { value: number; } | undefined): RecordingCloser

Build a ConnectionCloser that records every call into calls rather than touching real transports. Each method returns 1 ("one socket closed") regardless of whether a real socket exists โ€” handlers typically ignore the return value.

Pass seq_ref to share the sequence counter with a sibling create_emit_ordering_audit_factory so tests can pin close-vs-emit ordering at the handler call site. Without seq_ref, the closer uses a fresh internal counter โ€” at: N values within a single test are meaningful, but cannot be compared against audit emit ordering.

seq_ref?

type { value: number; } | undefined
optional

returns

RecordingCloser

create_request_context_middleware
#

auth/request_context.ts view source

(deps: QueryDeps, log: Logger, session_context_key?: string): MiddlewareHandler

Create middleware that authenticates the account from a session cookie.

Reads the session identity (set by session middleware), looks up the auth_session, and on a valid session sets c.var.auth_account_id, CREDENTIAL_TYPE_KEY = 'session', and AUTH_SESSION_TOKEN_HASH_KEY. Touches the session (fire-and-forget). Does not load actor or role_grants; REQUEST_CONTEXT_KEY is left null โ€” the route-spec / RPC dispatcher authorization phase resolves the acting actor and builds the full RequestContext when the route needs one.

Invalid / missing session leaves all keys null and calls next() โ€” require_auth / require_role enforce.

deps

query dependencies (pool-level db for middleware)

log

the logger instance

type Logger

session_context_key

the Hono context key where session middleware stored the session token

type string
default 'auth_session_id'

returns

MiddlewareHandler

create_role_grant_offer_actions
#

auth/role_grant_offer_actions.ts view source

(deps: Pick<RouteFactoryDeps, "log" | "audit"> & { notification_sender?: NotificationSender | null | undefined; }, options?: RoleGrantOfferActionOptions): RpcAction[]

Create the seven role-grant-offer RPC actions (six offer-lifecycle methods plus role_grant_revoke).

deps

RouteFactoryDeps (log, audit, โ€ฆ) plus optional notification_sender for WS fan-out โ€” when absent, WS fan-out is silently skipped (DB-only side effects still happen). Consumers wiring BackendWebsocketTransport assign its instance directly (the transport's send_to_account signature accepts the broader JsonrpcMessageFromServerToClient, which is contravariantly compatible)

type Pick<RouteFactoryDeps, "log" | "audit"> & { notification_sender?: NotificationSender | null | undefined; }

options

role schema, default TTL, authorization override

default {}

returns

RpcAction[]

the RpcAction array to spread into a create_rpc_endpoint call

create_role_schema
#

auth/role_schema.ts view source

(consumer_roles: readonly RoleSpec[], options?: CreateRoleSchemaOptions): RoleSchemaResult

Create a role schema and spec map that extends the builtins with app-defined roles.

Call once at server init. The returned Role schema validates role strings at I/O boundaries (grant endpoint, role_grant queries). The role_specs map is read by middleware for required_credential_types checks and by admin / self-service factories to derive their default eligibility filters from RoleSpec.grant_paths.

Construction-time guards (all fire on misconfiguration):

1. Every consumer_roles[i].name matches RoleName regex. 2. No two consumer roles share a name. 3. No consumer role collides with a builtin (keeper / admin). 4. When options.credential_types is supplied, every entry in required_credential_types is registered in that map. 5. When options.scope_kinds is supplied, every entry in applicable_scope_kinds is registered in that map. (Builtins declare empty applicable_scope_kinds, so they pass any registry.) 6. When options.grant_paths is supplied, every entry in grant_paths is registered in that map. (Builtins use only 'admin' and 'bootstrap', both of which are builtin grant paths, so they pass the default registry from create_grant_path_schema().)

consumer_roles

app-defined role specs

type readonly RoleSpec[]

options

optional registries for cross-axis validation

default {}

returns

RoleSchemaResult

{Role, role_specs} โ€” Zod schema and full spec map

throws

  • Error - if any `consumer_roles` entry fails any of the construction-time guards above

examples

// visiones โ€” opt into all four registries for full construction-time validation const credential_types = create_credential_type_schema(); const scope_kinds = create_scope_kind_schema({ classroom: {description: 'A classroom โ€” teacher and student role_grants scope here.'}, }); const grant_paths = create_grant_path_schema(); const {Role, role_specs} = create_role_schema( [ { name: 'teacher', description: 'Educator role. Web-grantable; applies at classroom scope.', grant_paths: ['admin'], applicable_scope_kinds: ['classroom'], }, ], {credential_types, scope_kinds, grant_paths}, );

create_rpc_client
#

actions/rpc_client.ts view source

<TApi extends object>(options: CreateRpcClientOptions<TApi>): TApi

Creates a Proxy-based API from action specs.

Method calls are dynamically dispatched based on the action spec's kind: - request_response โ†’ send request, await response, return Result - remote_notification โ†’ send notification, return Result - local_call โ†’ execute locally (sync or async), return Result or throw

Generic TApi is the consumer's typed Proxy interface (typically a codegen-derived ActionsApi). Required โ€” no default, so forgetting it is a type error rather than a silent slide into any. The `as unknown as TApi` coercion lives inside this function so call sites get a typed return without a cast at the seam. TApi is a type-layer promise about what the Proxy responds to; the runtime walks specs (kept in sync by the consumer, codegen recommended).

const api_result = create_rpc_client<MyActionsApi>({peer, environment});

options

type CreateRpcClientOptions<TApi>

returns

TApi

a Proxy typed as TApi that responds to any method name found in the environment's specs

create_rpc_endpoint
#

actions/action_rpc.ts view source

(options: CreateRpcEndpointOptions): RouteSpec[]

Single JSON-RPC 2.0 endpoint โ€” the canonical RPC transport binding.

Returns two RouteSpec entries (GET + POST on the same path) for apply_route_specs. The internal dispatcher handles:

1. Parse envelope โ€” POST: JSON body as JsonrpcRequest. GET: method and params from query string. 2. Lookup method โ€” find the RpcAction by method name. 3. Pre-validation auth โ€” short-circuit unauthenticated when no account is on the request, before input validation runs. 4. Authorization phase โ€” resolve the acting actor (when the action's auth requires role_grants or its input declares acting?: ActingActor) and build the request context. Runs before input validation so role-grant-grain auth checks return 403 before 400 invalid_params; acting is read from raw params via a string typeguard. 5. Post-authorization auth โ€” enforce role / keeper requirements against the request context. 6. Validate params โ€” parse input against the action's input schema. 7. Rate limit โ€” per-action IP / account throttling. 8. Dispatch โ€” acquire DB handle (transaction for mutations, pool for reads), construct ActionContext, call handler, return JSON-RPC response.

GET is restricted to side_effects: false actions (cacheable reads). All errors use JSON-RPC format: {jsonrpc, id, error: {code, message, data?}}.

The RouteSpecs use auth: {type: 'none'} because auth is checked per-action inside the dispatcher, and transaction: false because transaction scope is per-action (mutations get a transaction, reads get pool).

options

endpoint path, actions, and logger

returns

RouteSpec[]

route specs (GET + POST) ready for apply_route_specs

throws

  • Error - if two actions share the same `spec.method` (registration-time

create_rpc_get_url
#

testing/rpc_helpers.ts view source

(endpoint_path: string, method: string, params?: unknown, id?: string | number): string

Build a GET URL with JSON-RPC query parameters.

endpoint_path

the RPC endpoint path (e.g., /api/rpc)

type string

method

type string

params?

params (omit for parameterless methods)

type unknown
optional

id

request id (default 'test')

type string | number
default 'test'

returns

string

create_rpc_post_init
#

testing/rpc_helpers.ts view source

(method: string, params?: unknown, id?: string | number): RequestInit

Create a RequestInit for a JSON-RPC POST request.

method

type string

params?

params (omit for parameterless methods; null is also stripped for ergonomic call sites โ€” JSON-RPC 2.0 ยง4.2 forbids "params": null on the wire, and create_rpc_endpoint rejects z.null() action input schemas at registration). Tests that need to construct a literal "params": null envelope (e.g. asserting envelope-level rejection) should build the body inline rather than route through this helper.

type unknown
optional

id

request id (default 'test')

type string | number
default 'test'

returns

RequestInit

create_scope_kind_schema
#

auth/scope_kind_schema.ts view source

(consumer_kinds: Record<string, ScopeKindMeta>): ScopeKindSchemaResult

Create a scope-kind schema from a consumer-declared registry.

Open registry โ€” no builtins. The 'GLOBAL' token used inside the partial unique indexes on role_grant and role_grant_offer is not a registry entry (it's an index expression only) and cannot collide with consumer-declared kinds because the regex rejects uppercase.

Call once at server init. Pass the result into create_role_schema's optional scope_kinds parameter so each role's applicable_scope_kinds entries are validated against this set at construction time. v1 keeps applicable_scope_kinds informative-only (registry-membership validation only); v2 may add INSERT-time (role, scope_kind) enforcement once the shape is clear from real consumer usage.

consumer_kinds

the consumer-declared scope-kind set with optional metadata

type Record<string, ScopeKindMeta>

returns

ScopeKindSchemaResult

{ScopeKind, scope_kinds} โ€” Zod schema and metadata map

throws

  • Error - if any `consumer_kinds` key fails the `ScopeKindName` regex or appears more than once

examples

// visiones const {ScopeKind, scope_kinds} = create_scope_kind_schema({ classroom: {description: 'A classroom โ€” teacher and student role_grants scope here.'}, });

create_self_service_role_actions
#

auth/self_service_role_actions.ts view source

(deps: Pick<RouteFactoryDeps, "log" | "audit">, options?: SelfServiceRoleActionsOptions): RpcAction[]

Build the unified self-service role toggle RPC action.

deps

RouteFactoryDeps (log, audit, โ€ฆ); audit.emit writes audit rows via the captured pool. The bound emitter encapsulates on_audit_event fan-out and the optional AuditLogConfig.

type Pick<RouteFactoryDeps, "log" | "audit">

options

optional eligible-role override plus optional role schema for default-eligibility derivation

default {}

returns

RpcAction[]

the RpcAction array to spread into a create_rpc_endpoint call

throws

  • Error - at factory time if any `eligible_roles` entry is missing from `options.roles.role_specs`

create_server_status_route_spec
#

http/common_routes.ts view source

(options: ServerStatusOptions): RouteSpec

Create an authenticated server status route spec.

Returns version and uptime. Unlike the public health check, this requires authentication.

options

returns

RouteSpec

create_session_and_set_cookie
#

create_session_config
#

auth/session_cookie.ts view source

(cookie_name: string): SessionOptions<string>

Create a session config for raw session token identity.

The standard pattern: cookie stores the raw session token, server hashes it (blake3) to look up the auth_session row. Only the cookie_name varies per app.

cookie_name

cookie name (e.g. 'zap_session', 'visiones_session')

type string

returns

SessionOptions<string>

a SessionOptions<string> ready for use with session middleware

create_session_cookie_value
#

create_session_middleware
#

auth/session_middleware.ts view source

<TIdentity>(keyring: Keyring, options: SessionOptions<TIdentity>): MiddlewareHandler

Create session middleware that parses cookies and sets identity on context.

Always sets the identity on context (null when invalid/missing) for type-safe reads. Uses options.context_key as the Hono context variable name.

keyring

key ring for cookie verification

type Keyring

options

session configuration

type SessionOptions<TIdentity>

returns

MiddlewareHandler

create_signup_route_specs
#

create_sse_auth_guard
#

realtime/sse_auth_guard.ts view source

<T>(registry: SubscriberRegistry<T>, required_role: string | null, log: Logger): (event: AuditLogEvent) => void

Create an audit event handler that closes SSE streams on auth changes.

Closes streams when: - role_grant_revoke fires for the required_role targeting a connected subscriber - session_revoke_all targets a connected subscriber (consistent invalidation) - password_change targets a connected subscriber (sessions revoked implicitly)

The registry must use account_id as the identity key when subscribing (passed as the third argument to registry.subscribe()).

registry

the subscriber registry to guard

type SubscriberRegistry<T>

required_role

the role that grants access to the SSE endpoint, or null to skip role_grant_revoke handling entirely (for streams not gated by a specific role_grant)

type string | null

log

logger for disconnect events

type Logger

returns

(event: AuditLogEvent) => void

an on_audit_event callback

create_sse_response
#

realtime/sse.ts view source

<T = unknown>(c: Context<any, any, {}>, log: Logger): { response: Response; stream: SseStream<T>; }

Create an SSE response for a Hono context.

Wraps Hono's streamSSE to provide a {response, stream} API compatible with SubscriberRegistry push-based broadcasting. The callback suspends via a promise that resolves on client disconnect or explicit close(), keeping the stream alive for external sends.

Uses hono_stream.write() directly (not writeSSE) to avoid Hono's HTML callback resolution โ€” keeps the same data: JSON\n\n format.

c

type Context<any, any, {}>

log

logger for serialization and on_close listener errors

type Logger

returns

{ response: Response; stream: SseStream<T>; }

object with the streaming Response and an SseStream controller

create_standard_adversarial_cases
#

testing/adversarial_headers.ts view source

(allowed_origin: string): AdversarialHeaderCase[]

7 standard adversarial header cases applicable to any middleware stack.

Origin verification is Origin-only โ€” fuz_app's verify_request_source no longer falls back to Referer (matches zzz_server::auth::is_request_origin_allowed). Bearer auth still treats a Referer header as a browser-context indicator and silently discards the bearer token โ€” so Referer-bearing requests reach the route as unauthenticated rather than 403.

allowed_origin

an origin that passes the origin check

type string

returns

AdversarialHeaderCase[]

create_standard_rpc_actions
#

auth/standard_rpc_actions.ts view source

(deps: StandardRpcActionsDeps, options?: StandardRpcActionsOptions): RpcAction[]

Build the combined admin + role-grant-offer + account RPC action set.

Spreads create_admin_actions(deps, {roles, app_settings}), create_role_grant_offer_actions(deps, {roles, default_ttl_ms, authorize}), and create_account_actions(deps, {max_tokens}). The shared roles option flows to admin + role-grant-offer.

deps

StandardRpcActionsDeps (log, audit from RouteFactoryDeps; optional notification_sender for WS fan-out)

options

role schema, optional app-settings ref, role-grant-offer config, account config

default {}

returns

RpcAction[]

RPC actions to pass as rpc_endpoints or spread into create_rpc_endpoint

create_static_middleware
#

server/static.ts view source

(serve_static: ServeStaticFactory, options?: { root?: string | undefined; spa_fallback?: string | undefined; is_spa_route?: ((path: string) => boolean) | undefined; } | undefined): MiddlewareHandler[]

Create static file serving middleware for SvelteKit static builds.

Returns an array of middleware handlers to register on '/*'.

serve_static

runtime-specific serveStatic factory

options?

optional root directory and SPA fallback path

type { root?: string | undefined; spa_fallback?: string | undefined; is_spa_route?: ((path: string) => boolean) | undefined; } | undefined
optional

returns

MiddlewareHandler[]

create_stub_api_middleware
#

testing/stubs.ts view source

(options?: { include_daemon_token?: boolean | undefined; } | undefined): MiddlewareSpec[]

Create the API middleware stub array matching create_auth_middleware_specs output.

options?

type { include_daemon_token?: boolean | undefined; } | undefined
optional

returns

MiddlewareSpec[]

create_stub_app_deps
#

create_stub_app_server_context
#

testing/stubs.ts view source

(session_options: SessionOptions<string>): AppServerContext

Create a stub AppServerContext for attack surface testing.

Provides sensible defaults for all fields. Pass session_options since it varies per consumer; other fields use stubs/nulls.

session_options

consumer's session config (required โ€” varies per app)

type SessionOptions<string>

returns

AppServerContext

create_stub_audit_sse
#

testing/stubs.ts view source

(): AuditLogSse

Build a no-op AuditLogSse for tests that wire audit_sse into the surface helper but don't assert on SSE fan-out or subscriber state.

subscribe returns a no-op cleanup; on_audit_event is a no-op; the registry is a fresh SubscriberRegistry instance (call sites that inspect .size or call .close_* see a real registry, so writes are isolated per test). Tests that need real SSE plumbing build it via create_audit_log_sse against create_test_app.

returns

AuditLogSse

create_stub_db
#

testing/stubs.ts view source

(): Db

Create a stub Db for handler tests that use apply_route_specs with declarative transactions.

Returns a real Db instance with: - query returns empty rows (safety net for unmocked query functions) - query_one returns undefined - transaction(fn) calls fn(db) synchronously (no real transaction)

returns

Db

create_stub_upgrade
#

testing/ws_round_trip.ts view source

(): StubUpgrade

Build a fake upgradeWebSocket that captures the createEvents callback. The returned middleware is inert โ€” tests drive createEvents directly.

returns

StubUpgrade

create_surface_route_spec
#

http/common_routes.ts view source

(options: SurfaceRouteOptions): RouteSpec

Create an authenticated route spec that serves the AppSurface as JSON.

Surface data reveals API structure (routes, auth, schemas), so this requires authentication like the server status route.

options

returns

RouteSpec

create_test_account
#

testing/entities.ts view source

(overrides?: TestAccountOverrides | undefined): Account

Create a test Account with sensible defaults.

overrides?

type TestAccountOverrides | undefined
optional

returns

Account

create_test_account_with_actor
#

testing/db_entities.ts view source

(db: Db, options: { username: string; password_hash?: string | undefined; }): Promise<TestAccountWithActor>

Create an account + actor row pair in the database for tests.

Wraps query_create_account_with_actor with a default password_hash so suites that don't exercise password verification can stay terse. Replaces the per-file create_user / create_test_actor / create_test_account helpers that had accumulated across the auth test suite.

db

type Db

options

type { username: string; password_hash?: string | undefined; }

returns

Promise<TestAccountWithActor>

create_test_account_with_credentials
#

testing/app_server.ts view source

(options: CreateTestAccountWithCredentialsOptions): Promise<{ account: { id: string & $brand<"Uuid">; username: string; }; actor: { ...; }; api_token: string; session_cookie: string; }>

Create a test account with credentials. Use for additional accounts minted alongside the keeper (e.g. TestApp.create_account for cross-account / multi-user tests). Does NOT flip bootstrap_lock โ€” non-keeper accounts should not appear to the system as bootstrap having happened.

Creates an account with actor, grants roles, creates an API token, creates a session, and signs a session cookie.

options

returns

Promise<{ account: { id: string & $brand<"Uuid">; username: string; }; actor: { id: string & $brand<"Uuid">; }; api_token: string; session_cookie: string; }>

create_test_actor
#

testing/entities.ts view source

(overrides?: TestActorOverrides | undefined): Actor

Create a test Actor with sensible defaults.

overrides?

type TestActorOverrides | undefined
optional

returns

Actor

create_test_app
#

testing/app_server.ts view source

(options: CreateTestAppOptions): Promise<TestApp>

Create a fully assembled test app with a Hono server, middleware, and routes.

Combines create_test_app_server + create_app_server into a single call. Disables rate limiters and logging by default (test-friendly).

A fresh Hono app is created each call โ€” middleware closures bind to the server's deps (db, keyring), so reuse across servers is unsafe. The expensive resource (PGlite WASM) is cached separately in test_db.ts.

options

test app configuration

returns

Promise<TestApp>

a TestApp ready for HTTP testing

create_test_app_for_bootstrap
#

testing/app_server.ts view source

(options: CreateTestAppForBootstrapOptions): Promise<TestAppForBootstrap>

Create a test app in the pre-bootstrap state for exercising the bootstrap success path end-to-end.

Skips the keeper pre-creation create_test_app does by default โ€” bootstrap_lock.bootstrapped stays at false and the DB has no accounts. The fs stubs return options.bootstrap_token when the bootstrap handler reads bootstrap.token_path, so a POST /bootstrap with {token: bootstrap_token, username, password} reaches the success branch.

Pair with describe_bootstrap_success_tests for the consumer-runnable suite that drives the full happy path + adjacent assertions on observable state (account exists, audit row emitted, on_bootstrap callback fired).

options

bootstrap config + factory inputs

returns

Promise<TestAppForBootstrap>

a TestAppForBootstrap ready for the test to drive bootstrap

create_test_app_from_specs
#

testing/auth_apps.ts view source

(route_specs: RouteSpec[], auth_ctx?: RequestContext | undefined, credential_type?: "session" | "api_token" | "daemon_token" | undefined): Hono<BlankEnv, BlankSchema, "/">

Create a Hono test app from route specs with optional auth context.

route_specs

the route specs to register

type RouteSpec[]

auth_ctx?

optional request context to inject via middleware

type RequestContext | undefined
optional

credential_type?

optional credential type (default: 'session' when auth_ctx provided)

type "session" | "api_token" | "daemon_token" | undefined
optional

returns

Hono<BlankEnv, BlankSchema, "/">

create_test_app_server
#

create_test_app_surface_spec
#

testing/stubs.ts view source

(options: CreateTestAppSurfaceSpecOptions): AppSurfaceSpec

Create an AppSurfaceSpec for the standard testing suites.

Used by both in-process and cross-process tests as the schema source โ€” the cross-process-ness lives in the transport + per-test fixture, not here. The on-disk *_attack_surface.json snapshot is observability (gen-time drift detection via assert_surface_matches_snapshot); the suites consume the spec object this function returns, not the JSON file.

Mirrors create_app_server's route assembly: consumer routes + factory-managed bootstrap routes + surface generation. If create_app_server changes how it wires routes, update this helper to stay in sync (single source of truth for all consumers).

options

surface spec options

returns

AppSurfaceSpec

the surface spec for the standard suites

create_test_audit_emitter
#

testing/stubs.ts view source

(): AuditEmitter

Build a no-op AuditEmitter for tests that don't assert on audit fan-out.

emit / emit_role_grant_target are no-ops; emit_pool resolves immediately; notify is a no-op; on_event_chain is a frozen empty array โ€” pushing onto it throws at runtime, so a test that wires a listener fails loudly instead of silently never firing. Tests asserting on real audit-row persistence (or on listener fan-out) build a real emitter via create_audit_emitter against a stub or real DB โ€” create_test_app already does this on the test backend.

returns

AuditEmitter

create_test_audit_event
#

testing/entities.ts view source

(overrides?: TestAuditEventOverrides | undefined): AuditLogEvent

Create a test AuditLogEvent with sensible defaults.

overrides?

type TestAuditEventOverrides | undefined
optional

returns

AuditLogEvent

create_test_context
#

testing/entities.ts view source

(role_grants?: TestRoleGrantOverrides[]): RequestContext

Create a test RequestContext with role_grants from partial overrides.

role_grants

type TestRoleGrantOverrides[]
default [{}]

returns

RequestContext

create_test_middleware_stack_app
#

testing/middleware.ts view source

(options?: TestMiddlewareStackOptions | undefined): TestMiddlewareStackApp

Create a Hono app with real proxy + origin + bearer middleware for integration testing.

All DB queries return undefined (no real database needed). The echo route at TEST_MIDDLEWARE_PATH returns {ok, client_ip, has_context}.

options?

type TestMiddlewareStackOptions | undefined
optional

returns

TestMiddlewareStackApp

the app and mock spies (reconfigure via mockImplementation for valid-token paths)

create_test_request_context
#

create_test_role_grant
#

testing/entities.ts view source

(overrides?: TestRoleGrantOverrides | undefined): RoleGrant

Create a test RoleGrant with sensible defaults.

overrides?

type TestRoleGrantOverrides | undefined
optional

returns

RoleGrant

create_test_role_grant_direct
#

testing/db_entities.ts view source

(db: Db, input: CreateRoleGrantInput): Promise<RoleGrant>

Materialize a role_grant directly via query_create_role_grant, bypassing the production offer/accept consent flow.

In-process only. This helper takes a raw Db handle and seeds rows without firing audit fan-out, WebSocket broadcasts, or the _supersede notification chain a real grant emits. Cross-process suites must instead drive role_grant_offer_create_action_spec + role_grant_offer_accept_action_spec via role_grant_helpers.ts's role_grant_offer_and_accept so the fixture observes the full post-commit fan-out the way production does โ€” otherwise tests would mask real divergence between the TS and Rust spines.

Use this helper for query-level (*.db.test.ts) tests that exercise revoke or isolation semantics โ€” not the consent path itself. The schema's source_offer_id = null shape is an intentional admin-direct escape; this helper exposes it so suites don't reimplement the same direct-seed wrapper.

db

type Db

input

returns

Promise<RoleGrant>

create_testing_actions
#

testing/cross_backend/testing_reset_actions.ts view source

(deps: AppDeps, options: CreateTestingActionsOptions): RpcAction[]

Build the testing RPC actions for a test binary's registry.

Returns _testing_reset โ€” the single privileged action test binaries register. The test binary calls this at server-assembly time and registers the result on its dispatcher.

The reset action's table-wipe list mirrors auth_integration_truncate_tables from testing/db.ts โ€” the canonical "auth tables a between-test reset must clear" set. testing_reset_actions.coverage.test.ts enforces the set-equality invariant so a future auth migration that adds a table to that list without updating this handler fails CI.

deps

type AppDeps

options

returns

RpcAction[]

create_throwing_api
#

actions/rpc_client.ts view source

<TApi extends object>(api_result: TApi): ThrowingApi<TApi>

Wrap a typed RPC client so every call resolves to its unwrapped value or throws an Error carrying the JSON-RPC {code, message, data?} shape.

Implementation is a Proxy because the underlying create_rpc_client return is itself a Proxy with no concrete keys โ€” a key-by-key wrap would need to enumerate the typed surface, which only the consumer's generated ActionsApi interface knows.

Pass-through on non-Result returns is deliberate: sync local_call Proxy methods return values directly (see create_sync_local_call_method above). The Proxy can't distinguish those at get-time, so the wrapper inspects result shape at call-time and only unwraps when it sees a Result. Non-object returns pass through unchanged.

Only {code, data} cross onto the thrown Error โ€” name / stack are left as the Error's own properties so attacker-shaped result.error payloads cannot overwrite them.

Recommended consumer convention: create_frontend_rpc_client ships both shapes by default โ€” api (throwing) for hot-path call sites and api_result (Result) for sites that inspect error.data.reason without try/catch. Result is the protocol primitive; this wrapper is the ergonomic layer over it. Picking is per call site โ€” both Proxies share the same underlying transport.

Catch blocks read err.data?.reason โ€” optional chaining required because JSON-RPC data is spec-level optional.

On unknown string-keyed methods, the get trap returns a function that throws "rpc method not found: <prop>" on invocation โ€” clearer than the JS default "api.foo is not a function". Symbol props and then stay undefined so the Proxy isn't accidentally treated as a thenable (await api would otherwise probe then and trip the thrower).

api_result

typed Result-returning RPC client from create_rpc_client<ActionsApi>(...). The "_result" suffix names what the underlying calls return (Result<{value}, {error}>).

type TApi

returns

ThrowingApi<TApi>

create_throwing_stub
#

testing/stubs.ts view source

<T = any>(label: string): T

Create a Proxy that throws descriptive errors on any property access or method call.

Use for deps that should never be reached during a test. If a test accidentally calls through to a throwing stub, the error message identifies exactly which stub was hit, catching test bugs that would silently pass with {} as any.

JS-internal probes (Symbol, then, constructor, $$typeof) return undefined so the proxy doesn't crash framework-level identity checks; toJSON returns "[throwing_stub:label]" so accidental serialization surfaces the stub's identity in console output rather than silent "{}".

label

descriptive name for error messages (e.g. 'keyring', 'db')

type string

returns

T

throws

  • Error - on any non-internal property access, labeled with the stub

create_validated_broadcaster
#

realtime/sse.ts view source

<T extends SseNotification>(broadcaster: { broadcast: (channel: string, data: T) => void; }, event_specs: EventSpec[], log: Logger): { broadcast: (channel: string, data: T) => void; }

Create a broadcaster that validates events in DEV mode.

In DEV: warns on unknown methods and invalid params. In production: passes through with zero overhead.

broadcaster

duck-typed broadcaster (e.g. SubscriberRegistry)

type { broadcast: (channel: string, data: T) => void; }

event_specs

event specs to validate against

type EventSpec[]

log

logger used to emit DEV warnings on unknown methods or param mismatches

type Logger

returns

{ broadcast: (channel: string, data: T) => void; }

validated broadcaster wrapper (passthrough in production)

create_validated_keyring
#

auth/keyring.ts view source

(env_value: string | undefined): ValidatedKeyringResult

Validate and create a keyring in one step.

Returns a discriminated union so callers handle exit/logging their own way (e.g. Deno.exit(1) vs runtime.exit(1)).

env_value

the SECRET_FUZ_COOKIE_KEYS environment variable

type string | undefined

returns

ValidatedKeyringResult

{ok: true, keyring} or {ok: false, errors}

create_ws_auth_guard
#

actions/transports_ws_auth_guard.ts view source

(transport: BackendWebsocketTransport, log: Logger): AuditEventHandler

Create an audit event handler that closes WebSocket connections on auth changes.

Ignores outcome === 'failure' events โ€” they carry attacker-controlled identifiers (e.g. a session_revoke that the DB rejected still records the submitted session_id), so reacting to them would let any authenticated user close another user's socket by guessing a session hash or token id.

transport

log

logger for disconnect events (info level on non-zero closures)

type Logger

returns

AuditEventHandler

an on_audit_event callback suitable for create_audit_emitter's on_audit_event slot, or for appending onto audit.on_event_chain post-assembly. The returned callback mutates transport (closing matching sockets via close_sockets_for_session / _token / _account) on every relevant event.

create_ws_logout_closer
#

actions/transports_ws_auth_guard.ts view source

(transport: BackendWebsocketTransport, log: Logger): AuditEventHandler

Create an audit event handler that closes WebSocket connections on user-initiated logout.

Sibling helper to create_ws_auth_guard โ€” kept separate because ws_disconnect_event_types deliberately omits logout (admin-initiated revocations use session_revoke, while logout is the user-initiated case). Multiple consumers hand-rolled this same branch before extraction.

Compose with create_ws_auth_guard to handle both kinds of disconnect:

const ws_guard = create_ws_auth_guard(transport, log); const ws_logout_closer = create_ws_logout_closer(transport, log); const on_audit_event = (event: AuditLogEvent): void => { ws_guard(event); ws_logout_closer(event); };

Ignores outcome === 'failure' events โ€” failed logouts carry unauthenticated identifiers (no session to close anyway), and reacting to them would let an unauthenticated probe close the targeted account's sockets by submitting a logout for an arbitrary account_id.

transport

log

logger for disconnect events (info level on non-zero closures)

type Logger

returns

AuditEventHandler

an on_audit_event callback wireable alongside create_ws_auth_guard. The returned callback mutates transport via close_sockets_for_account on every successful logout event with a non-empty account_id.

create_ws_test_harness
#

testing/ws_round_trip.ts view source

(options: CreateWsTestHarnessOptions): WsTestHarness

Create a WebSocket test harness for the given specs + handlers.

Registers against a throwaway Hono app with a fake upgradeWebSocket; the captured events factory is invoked per connect() with a synthesized Hono context carrying the requested auth identity. Returned clients drive the real onOpen/onMessage/onClose path against a real WSContext.

options

returns

WsTestHarness

create_ws_transport
#

testing/transports/ws_transport.ts view source

(options: WsTransportOptions): Promise<WsClient>

Build a real-upgrade WS client pinned to options.base_url + ws_path.

Resolves once the upgrade succeeds and the socket is in OPEN state; rejects if the upgrade is refused (401, allowlist rejection, network failure). Incoming messages are JSON-parsed and pushed onto the messages array; wait_for checks already-received messages first before waiting for new arrivals.

options

returns

Promise<WsClient>

throws

  • Error - if the upgrade fails (status, network) โ€” the rejection

CreateAccountInput
#

CreateAppBackendOptions
#

server/app_backend.ts view source

CreateAppBackendOptions

Input for create_app_backend().

keyring is passed pre-validated โ€” callers handle their own error reporting (e.g., tx uses runtime.exit(1) on invalid keys).

stat

Get file/directory stats, or null if path doesn't exist.

type (path: string) => Promise<StatResult | null>

read_text_file

Read a file as text.

type (path: string) => Promise<string>

delete_file

Delete a file.

type (path: string) => Promise<void>

database_url

Database connection URL (postgres://, file://, or memory://).

type string

keyring

Validated cookie signing keyring.

type Keyring

password

Password hashing implementation. Use argon2_password_deps in production.

log

Structured logger instance. Omit for default (new Logger('server')).

type Logger

audit_factory

Build the bound AuditEmitter once the backend's pool Db + Logger exist. Required โ€” the factory owns subscriber-chain composition and AuditLogConfig selection without create_app_backend holding a default. Typical body:

audit_factory: ({db, log}) => create_audit_emitter({ db, log, on_audit_event, audit_log_config, })

Additional listeners (factory-managed audit SSE, per-endpoint WS auth guards) are appended at create_app_server time via audit.on_event_chain.push(...).

migration_namespaces

Additional migration namespaces to run after the builtin auth namespace. The shared schema_version table records one row per applied migration (namespace, name, sequence); order is append-only so forward-only guarantees hold per-namespace.

Names in reserved_migration_namespaces (currently ['fuz_auth']) are rejected at startup. Omit for no extra namespaces. This is the only place to splice consumer migrations โ€” DB init belongs to the backend lifecycle, not server assembly.

type ReadonlyArray<MigrationNamespace>

CreateAuditEmitterOptions
#

auth/audit_emitter.ts view source

CreateAuditEmitterOptions

db

Pool-level Db. Captured by every emit call.

type Db

log

Logger for write + listener-callback failures.

type Logger

on_audit_event

Initial subscriber appended to on_event_chain. Omit for backends that compose listeners post-assembly (e.g. via audit_log_sse).

type ((event: AuditLogEvent) => void) | null

audit_log_config

Audit-log config. Defaults to builtin_audit_log_config. Consumer- extended configs from create_audit_log_config({extra_events}) get registered here once at backend assembly.

emit_decorator

Test-only hook to wrap emit at construction time. The decorated function is captured by emit_role_grant_target's closure and is the function exposed on the returned AuditEmitter, so both call shapes route through it โ€” see EmitDecorator for the rationale.

Leave unset in production. The intended caller is create_emit_ordering_audit_factory in testing/audit_drift_guard.ts.

CreateAuditLogConfigOptions
#

auth/audit_log_schema.ts view source

CreateAuditLogConfigOptions

extra_events

Extra event types keyed by event-type string. Value is a Zod metadata schema, or null to register the type without validation (row still written, metadata stored as raw JSONB).

Collisions with builtin event-type strings throw at construction. Schemas are run via safeParse at insert time; mismatches log + count but never throw (fail-open โ€” see the drift counters in auth/audit_log_queries.ts).

type Readonly<Record<string, z.ZodType | null>>

CreateBroadcastApiOptions
#

actions/broadcast_api.ts view source

CreateBroadcastApiOptions

peer

The peer holding the transport registry used for sends.

specs

Notification specs to expose as broadcast methods. Typically the remote_notification specs whose initiator is backend (or both). Other kinds are accepted โ€” the helper only uses spec.method and spec.input โ€” but the typical use is notifications.

type ReadonlyArray<ActionSpecUnion>

log

Logger for validation/send errors. Defaults to a [broadcast] namespace.

type LoggerType | null

should_deliver

Optional per-connection ACL predicate. When set, the broadcast fans out via the transport's broadcast_filtered (feature-detected) โ€” each connection's identity is checked before the message is sent. When unset, the transport broadcasts unfiltered via transport.send.

Requires a transport that implements FilterableBroadcastTransport (today: only BackendWebsocketTransport). If set and the active transport is not filterable, the send is skipped and an error logged.

CreateDatabaseOptions
#

CreateDbResult
#

db/create_db.ts view source

CreateDbResult

Result of database initialization.

db

type Db

close

Close the database connection. Bound to the actual driver at construction.

type () => Promise<void>

db_type

type DbType

db_name

type string

CreateFrontendRpcClientOptions
#

actions/frontend_rpc_client.ts view source

CreateFrontendRpcClientOptions<TApi>

generics

TApi

constraint object
default object

specs

Action specs the typed Proxy can dispatch. Methods absent from this list silently return undefined from the Proxy โ€” the generic TApi cannot constrain runtime membership, so consumers must keep this list in sync with the typed surface (codegen recommended).

Protocol actions (heartbeat, cancel) are not auto-spread โ€” they're filtered out of generated action_specs by codegen's include_protocol_actions: false default and consumers spread them in explicitly so the contract stays visible at every registration site. For WS-using consumers, spread protocol_action_specs from actions/protocol.ts here: specs: [...protocol_action_specs, ...action_specs]. HTTP-only consumers can omit them.

type ReadonlyArray<ActionSpecUnion>

path

HTTP RPC endpoint path for the default FrontendHttpTransport. Defaults to /api/rpc. Ignored when transports is provided.

type string

transports

Optional explicit transport list. When provided, the default FrontendHttpTransport(path) is not registered โ€” the caller is responsible for at least one ready transport. Use for WS-first or WS+HTTP mixed setups.

type ReadonlyArray<Transport>

transport_for_method

Optional per-method transport selector โ€” pure pass-through to create_rpc_client. Return the transport name to use for a given method, or undefined to fall back to the peer's default selection.

Useful when methods are registered on different backend dispatchers (e.g. streaming actions on WS, REST RPC on HTTP) โ€” a tx-style mixed setup. Per-call RpcClientCallOptions.transport_name overrides this for individual dispatches.

on_action_event

Optional callback fired once per dispatched action โ€” pure pass-through to create_rpc_client. Used by zzz-style consumers that thread the ActionEvent into a reactive cell (add_from_json + listen_to_action_event) for pending / failed / value derivations.

event.spec.method and event.data.method narrow to keyof TApi & string โ€” drop the as ActionMethod cast at the call site when TApi is a generated ActionsApi interface.

type (event: ActionEvent<keyof TApi & string>) => void

lookup_action_handler

Optional handler resolver. Wired onto environment.lookup_action_handler โ€” the registry the dispatcher uses to find handlers for inbound messages and lifecycle phases. Defaults to () => undefined, which is fine for HTTP-only frontends that never receive a server-pushed notification or register a receive_error recovery hook.

Common reasons to provide this: - Server-pushed notifications over WS โ€” return a handler for (method, 'receive') so a remote_notification arriving on the socket dispatches to your subscriber bus (tx-style). - Per-method retry / telemetry on errors โ€” return a handler for (method, 'receive_error'). Note that as of the extract_action_result fix, a missing handler already produces {ok: false, error} โ€” the stub is no longer required just to surface server errors.

type ActionEventEnvironment['lookup_action_handler']

CreateInviteInput
#

auth/invite_schema.ts view source

CreateInviteInput

Input for creating an invite.

email

type Email | null

username

type Username | null

created_by

type Uuid | null

CreateRoleGrantInput
#

auth/account_schema.ts view source

CreateRoleGrantInput

actor_id

type Uuid

role

type string

scope_kind

Machine-readable kind for the scope_id. Required iff scope_id is set; must be null/omitted when scope_id is null. The DB-level role_grant_scope_kind_paired CHECK rejects mismatched pairs.

type string | null

scope_id

Scope the grant applies to. null / omitted grants a global role_grant.

type Uuid | null

expires_at

type Date | null

granted_by

type Uuid | null

source_offer_id

Offer id that produced this role_grant. Set by query_accept_offer; leave unset for direct grants.

type Uuid | null

CreateRoleGrantOfferInput
#

auth/role_grant_offer_schema.ts view source

CreateRoleGrantOfferInput

Input for query_role_grant_offer_create.

expires_at must be supplied โ€” the query layer does not apply a default, so callers can thread their own TTL (typically ROLE_GRANT_OFFER_DEFAULT_TTL_MS).

from_actor_id

type Uuid

to_account_id

type Uuid

to_actor_id

Optional actor-grain target on the recipient account. When set, query_role_grant_offer_create validates that the actor belongs to to_account_id and stamps the column; accept then matches against this specific actor. Omit (or pass null) for the account-grain default โ€” any actor on to_account_id may accept.

type Uuid | null

role

type string

scope_kind

Machine-readable kind for the scope_id. Required iff scope_id is set; must be null when scope_id is null (DB-level CHECK rejects the mismatch). Consumer-declared via create_scope_kind_schema(...).

type string | null

scope_id

type Uuid | null

message

type string | null

expires_at

type Date

CreateRoleSchemaOptions
#

auth/role_schema.ts view source

CreateRoleSchemaOptions

Optional registries to validate RoleSpec cross-axis fields against at construction time.

credential_types

Pass create_credential_type_schema() to validate RoleSpec.required_credential_types entries.

scope_kinds

Pass create_scope_kind_schema() to validate RoleSpec.applicable_scope_kinds entries.

grant_paths

Pass create_grant_path_schema() to validate RoleSpec.grant_paths entries.

CreateRpcClientOptions
#

actions/rpc_client.ts view source

CreateRpcClientOptions<TApi>

Options for create_rpc_client.

generics

TApi

constraint object
default object

peer

environment

on_action_event

Optional callback fired once per dispatched action with the live ActionEvent. Consumers wire reactive state here โ€” e.g. zzz's Actions cell calls add_from_json + listen_to_action_event inside the callback so its history stays decoupled from the rpc_client surface.

event.spec.method and event.data.method narrow to keyof TApi & string โ€” drop the as ActionMethod cast at the call site when TApi is a generated ActionsApi interface.

type (event: ActionEvent<keyof TApi & string>) => void

transport_for_method

Optional per-method transport selector. When provided, the client calls peer.send(msg, {transport_name}) with the returned transport for each request_response / remote_notification dispatch. Returning undefined falls back to the peer's default selection.

CreateRpcEndpointOptions
#

actions/action_rpc.ts view source

CreateRpcEndpointOptions

Options for create_rpc_endpoint.

path

Mount path for the endpoint (e.g., /api/rpc).

type string

actions

RPC actions to serve.

type Array<RpcAction>

log

Logger instance for handler context.

type Logger

action_ip_rate_limiter

Per-IP rate limiter consulted for actions whose spec declares rate_limit: 'ip' or 'both'. null disables the IP check. Per-action gate via action.spec.rate_limit. Same limiter is shared with the WebSocket action dispatcher โ€” one budget per action, not per transport.

type RateLimiter | null

action_account_rate_limiter

Per-account rate limiter consulted for actions whose spec declares rate_limit: 'account' or 'both'. Keyed on request_context.account.id (account-grain โ€” billed to the authenticated account regardless of which actor was resolved). null disables the account check. Same limiter is shared with the WebSocket action dispatcher.

type RateLimiter | null

CreateSessionAndSetCookieOptions
#

auth/session_middleware.ts view source

CreateSessionAndSetCookieOptions

keyring

Keyring for cookie signing.

type Keyring

deps

Query deps (needs db for session creation).

c

Hono context for setting the cookie.

type Context

account_id

The account to create a session for.

type string

session_options

Session cookie configuration.

type SessionOptions<string>

max_sessions

Per-account session cap (null to skip enforcement).

type number | null

CreateTestAccountOptions
#

testing/cross_backend/setup.ts view source

CreateTestAccountOptions

Options for TestFixture.create_account โ€” mints an additional bootstrapped account alongside the keeper. Matches the existing TestApp.create_account signature so the migration to fixture-style reads is a one-site call rewrite per use.

username

type string
readonly

password_value

type string
readonly

roles

type Array<string>
readonly

CreateTestAccountWithCredentialsOptions
#

CreateTestAppForBootstrapOptions
#

testing/app_server.ts view source

CreateTestAppForBootstrapOptions

Configuration for create_test_app_for_bootstrap. Like CreateTestAppOptions but the keeper-related fields drop (no pre-bootstrap keeper) and bootstrap is required + narrowed to live mode (the helper exists specifically to drive the success path).

session_options

type SessionOptions<string>

create_route_specs

type (context: AppServerContext) => Array<RouteSpec>

rpc_endpoints

app_options

bootstrap

Live bootstrap config โ€” the test drives POST /bootstrap against this.

bootstrap_token

Token contents the stub fs returns when reading bootstrap.token_path. The test posts a body containing this same value as token to satisfy the timing-safe equality check inside bootstrap_account.

type string

db

type Db

db_type

type DbType

password

audit_factory

CreateTestAppOptions
#

testing/app_server.ts view source

CreateTestAppOptions

Configuration for create_test_app.

inheritance

create_route_specs

Route spec factory โ€” called with the assembled AppServerContext.

type (context: AppServerContext) => Array<RouteSpec>

rpc_endpoints

RPC endpoints mounted by create_app_server โ€” eager array or (ctx: AppServerContext) => Array<RpcEndpointSpec> factory. Single source of truth; the equivalent slot under app_options is Omit'd so setup-time path lookup and runtime dispatch read from one place. Symmetric with the suite-level rpc_endpoints option on describe_standard_admin_integration_tests etc.

bootstrap

Bootstrap config โ€” symmetric with AppServerOptions.bootstrap. Same single-source-of-truth precedent as rpc_endpoints: setup-time surface generation and runtime dispatch both read this slot, so the equivalent field under app_options is Omit'd. Discriminated union over {mode: 'disabled' | 'surface_only' | 'live'}. Omit (or pass {mode: 'disabled'}) for the default โ€” no bootstrap route mounted.

For tests that exercise the bootstrap success path against a real token + empty DB, use create_test_app_for_bootstrap instead โ€” it skips the keeper pre-creation that blocks the success branch.

app_options

Optional overrides for AppServerOptions. Excludes fields create_test_app manages directly: backend, session_options, create_route_specs, rpc_endpoints, bootstrap (top-level slots above).

CreateTestAppSurfaceSpecOptions
#

testing/stubs.ts view source

CreateTestAppSurfaceSpecOptions

session_options

Consumer's session config (required โ€” varies per app).

type SessionOptions<string>

create_route_specs

Consumer's route factory โ€” receives the same AppServerContext as production.

type (ctx: AppServerContext) => Array<RouteSpec>

env_schema

Env schema for surface generation (default: BaseServerEnv).

type z.ZodObject

event_specs

SSE event specs for surface generation.

type Array<EventSpec>

rpc_endpoints

RPC endpoint specs for surface generation.

Accepts either an array (eager) or a factory (ctx: AppServerContext) => Array<RpcEndpointSpec> โ€” symmetric with create_app_server's rpc_endpoints option, so consumers can pass the same factory to both entry points. The factory runs once against the stub AppServerContext this helper already builds.

type Array<RpcEndpointSpec> | ((ctx: AppServerContext) => Array<RpcEndpointSpec>)

ws_endpoints

WebSocket endpoint specs for surface generation. Symmetric with create_app_server's ws_endpoints option โ€” pass the same value to both entry points so the attack surface tests see the same WS endpoints production auto-mounts. The factory runs once against the stub AppServerContext this helper already builds. No upgradeWebSocket needed โ€” this helper produces an AppSurfaceSpec only, never mounts.

type | ReadonlyArray<WsEndpointSpec> | ((ctx: AppServerContext) => ReadonlyArray<WsEndpointSpec>)

transform_middleware

Transform middleware array (e.g., zap's extend_middleware_for_zap_binary).

type (specs: Array<MiddlewareSpec>) => Array<MiddlewareSpec>

bootstrap

Bootstrap config โ€” symmetric with AppServerOptions.bootstrap. Discriminated by mode: 'disabled' skips the route (same as omission), 'surface_only' mounts the route shape, 'live' accepts a token_path for production symmetry (surface assembly only uses it for shape symmetry; the value is a live-execution concern handled by create_test_app โ†’ create_app_server).

Surface assembly only reads route_prefix (default '/api/account').

CreateTestingActionsOptions
#

testing/cross_backend/testing_reset_actions.ts view source

CreateTestingActionsOptions

session_options

Session cookie options โ€” the reset action uses these when signing the fresh keeper's (and any extra accounts') session cookies. Pass the same SessionOptions the live create_app_server call was wired with.

type SessionOptions<string>
readonly

daemon_token_state

Daemon-token runtime state โ€” the reset action mutates state.keeper_account_id to point at the freshly seeded keeper after the old row is wiped. Pass the same DaemonTokenState instance the daemon-token middleware reads.

readonly

reset_state

Consumer-supplied callback invoked after the auth-table reset. testing_zzz_server clears workspace registry + terminals + the scoped FS scratch dir here; testing_spine_stub has no domain layer and passes a no-op (or omits the option). Runs inside the same RPC dispatch as the auth-table writes, so a throw surfaces to the caller as a JSON-RPC error and the per-test fixture short-circuits.

type () => Promise<void> | void
readonly

CreateWsTestHarnessOptions
#

testing/ws_round_trip.ts view source

CreateWsTestHarnessOptions

actions

The actions registered on this endpoint โ€” matches the shape register_action_ws accepts. Each entry is a {spec, handler?} tuple; shared fuz_app primitives (like heartbeat_action) can be spread in alongside consumer-specific actions.

type ReadonlyArray<Action>

transport

Pass a pre-created transport to share with a broadcast API.

heartbeat

Threaded through to register_action_ws. Defaults to false in tests โ€” fake timers + receive-silence detection need explicit opt-in and per- test tuning to avoid spurious closes.

type RegisterActionWsOptions['heartbeat']

log

Optional logger. Defaults to a silent [ws-test] logger.

type Logger

on_socket_open

Threaded straight through to register_action_ws.

type RegisterActionWsOptions['on_socket_open']

on_socket_close

Threaded straight through to register_action_ws.

type RegisterActionWsOptions['on_socket_close']

CREDENTIAL_TYPE_API_TOKEN
#

auth/credential_type_schema.ts view source

"api_token"

HTTP Authorization: Bearer API token credential. The wire literal 'api_token' aligns with the api_token storage table name; the constant is named _API_TOKEN (not _BEARER) to keep wire and storage nomenclature in lockstep.

CREDENTIAL_TYPE_DAEMON_TOKEN
#

CREDENTIAL_TYPE_KEY
#

CREDENTIAL_TYPE_NAME_REGEX
#

CREDENTIAL_TYPE_SESSION
#

CREDENTIAL_TYPES
#

hono_context.ts view source

readonly ["session", "api_token", "daemon_token"]

The credential types that can authenticate a request โ€” the closed set of fuz_app builtins. The open registry on top (create_credential_type_schema(consumer_types)) is consulted at registry time by create_role_schema for RoleSpec.required_credential_types validation; the wire-validated CredentialType enum here stays narrow because middleware only ever sets one of the three builtins.

CredentialType
#

hono_context.ts view source

ZodEnum<{ session: "session"; api_token: "api_token"; daemon_token: "daemon_token"; }>

Credential type โ€” how a request was authenticated.

CredentialTypeMeta
#

auth/credential_type_schema.ts view source

CredentialTypeMeta

Per-credential-type metadata. description is admin-UI-facing copy (mirrors RoleSpec.description and ScopeKindMeta.description). Open shape so v2 can extend without a breaking change.

description

type string

CredentialTypeName
#

CredentialTypeRequiredError
#

http/error_schemas.ts view source

ZodObject<{ error: ZodLiteral<"credential_type_required">; required_credential_types: ZodReadonly<ZodArray<ZodString>>; }, $loose>

Credential-type error โ€” returned by the dispatcher's post-authorization credential gate (and the require_credential_types REST middleware) when the request's credential type isn't in the route's auth.credential_types allowlist.

required_credential_types carries what the route declared (['daemon_token'] for keeper; future gates carry their own labels). Symmetric with PermissionError's required_roles: clients see what the route demanded, not what their credential is.

CredentialTypeSchemaResult
#

auth/credential_type_schema.ts view source

CredentialTypeSchemaResult

The result of create_credential_type_schema โ€” a Zod schema and metadata map.

CredentialType

Zod schema that validates credential-type name strings against the registered set (builtins + consumer-declared). Use at I/O boundaries (admin UIs, codegen) and as the construction-time check inside create_role_schema for every RoleSpec.required_credential_types entry.

type z.ZodType<string>

credential_types

Map of every registered credential-type to its metadata. Keyed by name. Read at startup by admin / codegen surfaces.

type ReadonlyMap<string, CredentialTypeMeta>

CrossProcessSetupOptions
#

testing/cross_backend/setup.ts view source

CrossProcessSetupOptions

extra_keeper_roles

Additional roles to grant the fresh keeper on every per-test reset, *in addition to* the [ROLE_KEEPER, ROLE_ADMIN] defaults the _testing_reset action seeds. Cross-process mirror of in-process extra_keeper_roles on default_in_process_suite_options.

Costs nothing extra per test โ€” the _testing_reset action seeds the keeper in a single transaction regardless of how many roles are in the list.

ROLE_ADMIN is already in the default set, so admin-suite consumers usually pass an empty / omitted array. Consumer-defined roles (e.g. teacher) are passed here when the keeper-acting test needs them.

Keeper โ‰  admin. Tests that need a *non-admin* secondary account with ROLE_KEEPER declare it via extra_accounts โ€” ROLE_KEEPER's RoleSpec.grant_paths is bootstrap-only, so it can only be granted at the test-binary bootstrap-equivalent step.

type ReadonlyArray<string>
readonly

extra_accounts

Bootstrap-time secondary accounts seeded alongside the keeper on every per-test reset. See ExtraAccountSpec for why this is a cradle-only bypass. The reset action seeds them in the same transaction as the keeper.

type ReadonlyArray<ExtraAccountSpec>
readonly

DAEMON_TOKEN_HEADER
#

DaemonInfo
#

cli/daemon.ts view source

ZodObject<{ version: ZodNumber; pid: ZodNumber; port: ZodNumber; started: ZodString; app_version: ZodString; }, $strict>

Daemon info schema for ~/.{name}/run/daemon.json.

DaemonToken
#

DaemonTokenRotation
#

DaemonTokenRotationOptions
#

auth/daemon_token_middleware.ts view source

DaemonTokenRotationOptions

Options for daemon token rotation.

token_path

Absolute path the token file is written to. Caller computes from its own conventions โ€” e.g. get_daemon_token_path(runtime, app_name) for the standard ~/.{name}/run/daemon_token layout, or a path derived from PUBLIC_<APP>_DIR for cross-process test setups that isolate the app dir to a tmpdir.

type string

rotation_interval_ms

Rotation interval in ms. Default: 30000 (30s).

type number

DaemonTokenState
#

auth/daemon_token.ts view source

DaemonTokenState

Mutable runtime state for daemon token rotation.

This is runtime state (not AppDeps or *Options) โ€” it changes during operation. Created at server startup, passed to the middleware factory.

current_token

Current valid token.

type string

previous_token

Previous token, still valid during the race window. null before first rotation.

type string | null

rotated_at

When the last rotation occurred.

type Date

keeper_account_id

The account ID of the keeper (resolved at startup, set by on_bootstrap).

type string | null

DaemonTokenWriteDeps
#

DataExposureTestOptions
#

testing/data_exposure.ts view source

DataExposureTestOptions

setup_test

Per-test fixture-producing function (per-describe cadence).

surface_source

App surface for schema-level + route-iteration checks. Constructed in TS by the consumer; same shape for in-process and cross-process tests.

capabilities

Backend capability declarations.

sensitive_fields

Fields that must never appear in any response. Default: sensitive_field_blocklist.

type ReadonlyArray<string>

admin_only_fields

Fields that must not appear in non-admin responses. Default: admin_only_field_blocklist.

type ReadonlyArray<string>

skip_routes

Routes to skip, in 'METHOD /path' format.

type Array<string>

Datatable
#

DATATABLE_COLUMN_WIDTH_DEFAULT
#

DATATABLE_MIN_COLUMN_WIDTH
#

DatatableColumn
#

ui/datatable.ts view source

DatatableColumn<T>

Column definition for a Datatable.

generics

T

default unknown

key

Row data accessor key.

type string & keyof T

label

Header label text.

type string

width

Initial column width in pixels.

type number

min_width

Minimum column width in pixels.

type number

format

Format a cell value for display. Falls back to format_value when absent.

type (value: T[keyof T], row: T) => string

Db
#

db/db.ts view source

Database wrapper providing a consistent query and transaction interface.

Construct via create_pg_db() from db/db_pg.ts or create_pglite_db() from db/db_pglite.ts for proper transaction support, or via create_db() for URL-based auto-detection.

examples

const {db, close} = await create_db('postgres://...'); const users = await db.query<User>('SELECT * FROM users WHERE active = $1', [true]); await db.transaction(async (tx) => { await tx.query('INSERT INTO users ...'); await tx.query('INSERT INTO audit_log ...'); }); await close();

client

type DbClient

readonly

constructor

type new (options: DbDeps): Db

options
type DbDeps

query

Execute a query and return all rows.

type <T>(text: string, values?: unknown[] | undefined): Promise<T[]>

text

SQL text with $1, $2, ... parameter placeholders

type string
values?

parameter values bound to the placeholders in text

type unknown[] | undefined
optional
returns Promise<T[]>

the result rows, typed as T

query_one

Execute a query and return the first row, or undefined if no rows.

type <T>(text: string, values?: unknown[] | undefined): Promise<T | undefined>

text

SQL text with $1, $2, ... parameter placeholders

type string
values?

parameter values bound to the placeholders in text

type unknown[] | undefined
optional
returns Promise<T | undefined>

the first row, or undefined when the result set is empty

transaction

Run a function inside a database transaction.

The callback receives a transaction-scoped Db. Queries inside the callback go through the transaction connection; queries outside use the pool normally. Commits on success, rolls back on error.

type <T>(fn: (tx_db: Db) => Promise<T>): Promise<T>

fn

async function receiving a transaction-scoped Db

type (tx_db: Db) => Promise<T>
returns Promise<T>

the value returned by fn

throws
  • Error - propagated from `fn` after `ROLLBACK`, or from the driver

DB_TABLE_ROWS_DEFAULT_LIMIT
#

DB_TABLE_ROWS_LIMIT_MAX
#

DbClient
#

db/db.ts view source

DbClient

Minimal interface that both pg and pglite satisfy.

query

type <T = unknown>(text: string, values?: Array<unknown>) => Promise<{rows: Array<T>}>

DbDeps
#

db/db.ts view source

DbDeps

Configuration for constructing a Db with transaction support.

transaction is injected by create_db which knows the driver. For pg: acquires a dedicated pool client per transaction. For PGlite: delegates to pglite.transaction().

client

transaction

type <T>(fn: (tx_db: Db) => Promise<T>) => Promise<T>

DbDriverResult
#

db/db.ts view source

DbDriverResult

Result of constructing a driver-specific Db.

Returned by create_pg_db() and create_pglite_db(). The close callback is bound to the actual driver โ€” callers never need to know which driver is in use.

db

type Db

close

Close the database connection. Bound to the actual driver at construction.

type () => Promise<void>

DbFactory
#

testing/db.ts view source

DbFactory

Factory interface for creating test database instances.

name

type string

create

type () => Promise<Db>

close

type (db: Db) => Promise<void>

skip

type boolean

skip_reason

type string

DbRouteOptions
#

http/db_routes.ts view source

DbRouteOptions

Per-factory configuration for db routes.

db_type

type DbType

db_name

type string

extra_stats

Optional callback to provide app-specific stats in the health response.

type (db: Db) => Promise<Record<string, unknown>>

log

Optional logger for server-side diagnostics (e.g. FK violation details).

type Logger

DbStatus
#

db/status.ts view source

DbStatus

Full database status snapshot.

connected

Whether the database is reachable.

type boolean

error

Error message if connection failed.

type string

table_count

Number of public tables.

type number

tables

Per-table row counts.

type Array<TableStatus>

migrations

Per-namespace migration status.

type Array<MigrationStatus>

old_tracker_shape

True if the pre-0.42 schema_version shape (with a version column) was detected. The runner refuses to start in this state โ€” operators see this flag as their cue to drop the table or call baseline().

type boolean

DbType
#

DeclinedOffer
#

default_action_account_rate_limit
#

rate_limiter.ts view source

RateLimiterOptions

Default options for per-actor action-dispatcher rate limiting: 1200 attempts per 15 minutes. Shared by the HTTP RPC and WebSocket action dispatchers. Permissive โ€” sustained ~80/min is well above any human admin workflow; an oracle probing 10k addresses still finishes in ~2 hours, slow enough to surface in audit. Tighten downstream.

default_action_ip_rate_limit
#

rate_limiter.ts view source

RateLimiterOptions

Default options for per-IP action-dispatcher rate limiting: 600 attempts per 15 minutes. Shared by the HTTP RPC and WebSocket action dispatchers (one budget per action, not per transport). Permissive โ€” catches runaway scripts and egregious oracle probes, but well above human or normal automation pace. Tighten downstream for stricter deployments.

default_audit_factory
#

server/app_backend.ts view source

(params: { db: Db; log: Logger; }): AuditEmitter

Trivial AuditFactory for consumers that don't compose on_audit_event or audit_log_config. Equivalent to ({db, log}) => create_audit_emitter({db, log}) โ€” exported so the default case stays a single-symbol reference rather than five tokens of boilerplate at every consumer.

Use the inline form when you need to thread on_audit_event / audit_log_config / emit_decorator; the factory composes those three fields itself so there's nothing this constant can pass through.

params

type { db: Db; log: Logger; }

returns

AuditEmitter

DEFAULT_BACKOFF_FACTOR
#

DEFAULT_CLOSE_CODE
#

DEFAULT_COLLECTIONS_PATH
#

default_cross_process_setup
#

testing/cross_backend/setup.ts view source

(handle: ReconstructedBootstrappedBackendHandle, options?: CrossProcessSetupOptions | undefined): SetupTest

Build a SetupTest against a spawned + bootstrapped backend.

Per-test body (unconditional reset โ€” fresh keeper every test):

1. Fire _testing_reset via the keeper's daemon-token channel. The action wipes auth tables, seeds a fresh keeper (with extra_keeper_roles applied), seeds any extra_accounts, and returns the new credentials. 2. Build the TestFixture closing over the new keeper as the fixture's primary account / actor (matching in-process semantics). fixture.extra_accounts[username] exposes any bootstrap-time secondaries. 3. fixture.create_account() mints additional *post-bootstrap* accounts via the production signup + login flow (invite โ†’ signup โ†’ login โ†’ token). Roles go through offer/accept (production consent path).

No reset: boolean opt-in โ€” every test runs against a freshly bootstrapped keeper. This converges in-process and cross-process keeper lifetimes; mutation-cascade tests (password change, revoke-all) and hardcoded-username signup tests work uniformly.

handle

options?

type CrossProcessSetupOptions | undefined
optional

returns

SetupTest

default_error_schema_tightness
#

testing/surface_invariants.ts view source

ErrorSchemaTightnessOptions

Baseline error schema tightness applied by describe_standard_attack_surface_tests when no config is passed.

Uses min_specificity: 'enum' (the assertion default) with ignore_statuses for middleware-derived status codes that are commonly generic (auth middleware produces multiple error codes at 401/403, and 429 comes from rate limiters), and allowlist seeded with fuz_app_stock_route_tightness_allowlist so fuz_app-shipped routes with heterogeneous generic schemas don't force every consumer to hand-maintain an identical allowlist. Consumers can pass a narrower config with project-specific allowlist entries, or pass null to skip the assertion entirely.

default_format_scope
#

ui/format_scope.ts view source

(args: { scope_id: string | null; role: string; }): string | null

Default FormatScope โ€” always returns null so callers fall back to the raw uuid.

args

type { scope_id: string | null; role: string; }

returns

string | null

DEFAULT_HEARTBEAT_INTERVAL
#

DEFAULT_HEARTBEAT_RECEIVE_TIMEOUT
#

default_in_process_setup
#

testing/cross_backend/setup.ts view source

(options: InProcessSetupOptions): SetupTest

Build a SetupTest that creates a fresh TestApp per call via create_test_app and projects it into the TestFixture shape.

Same factory inputs create_test_app already takes โ€” this helper is a projection layer, not a new lifecycle. fuz_app's own src/test/ and consumer suites pass default_in_process_setup({...factory_inputs}) in place of the old per-suite factory-input bundle. The extra_accounts slot (see InProcessSetupOptions) seeds bootstrap-time secondaries directly via create_test_account_with_credentials against the same DB the keeper just landed on โ€” mirrors the cross-process _testing_reset cradle so suite bodies read fixture.extra_accounts[username] uniformly regardless of transport.

The describe-level auth_integration_truncate_tables / pglite WASM cache lifecycle stays in create_pglite_factory / create_describe_db (testing/db.js) โ€” default_in_process_setup doesn't manage db state beyond what create_test_app already does.

options

returns

SetupTest

default_in_process_suite_options
#

testing/cross_backend/setup.ts view source

<const O extends DefaultInProcessSuiteOptions>(options: O): { setup_test: SetupTest; surface_source: AppSurfaceSpec; capabilities: BackendCapabilities; session_options: O["session_options"]; create_route_specs: O["create_route_specs"]; rpc_endpoints: O["rpc_endpoints"]; }

Build the full in-process suite bundle in a single helper invocation. Output covers {setup_test, surface_source, capabilities} plus every factory input the Tier 1 suites read at their top level (session_options, create_route_specs, rpc_endpoints) โ€” so the call site spreads once and adds only suite-specific extras (roles, skip_routes, input_overrides, db_factories, ...).

// Suite-extras-free call: helper output is the entire options bag. describe_round_trip_validation(default_in_process_suite_options({ session_options, create_route_specs, rpc_endpoints: [rpc_endpoint_spec], })); // With suite-specific extras: spread and add. describe_standard_admin_integration_tests({ ...default_in_process_suite_options({ session_options, create_route_specs, rpc_endpoints, extra_keeper_roles: [ROLE_ADMIN], }), roles, });

Suites that don't read session_options / rpc_endpoints at their top level (round_trip, data_exposure) accept the spread anyway โ€” excess properties on spread sources aren't checked by TS, and the uniform shape keeps consumer call sites mechanical.

options

type O

returns

{ setup_test: SetupTest; surface_source: AppSurfaceSpec; capabilities: BackendCapabilities; session_options: O["session_options"]; create_route_specs: O["create_route_specs"]; rpc_endpoints: O["rpc_endpoints"]; }

DEFAULT_INTEGRATION_ERROR_COVERAGE
#

testing/error_coverage.ts view source

0.2

Default minimum error coverage threshold for the standard integration and admin test suites. Conservative โ€” not all error paths are exercisable in the composable suites. Consumers should increase as their test suites mature.

default_login_account_rate_limit
#

DEFAULT_LOGIN_FAIL_FLOOR_MS
#

auth/account_routes.ts view source

250

Default minimum wall-clock time (ms) for a login failure (401) response.

Picked to exceed the p99 of every 401 code path (Argon2id dominates at ~100ms, plus DB + overhead). The handler races failure work against sleep(floor + jitter) via await, so observed response time = max(work, delay). Found-vs-not-found and rate-limit-skipped-vs-not paths converge. Only 401 is padded โ€” 429 stays fast by design to keep rate-limit DoS handling cheap.

DEFAULT_LOGIN_FAIL_JITTER_MS
#

auth/account_routes.ts view source

25

Default uniform jitter window (ยฑms) layered on the floor.

Random jitter prevents a stable clamp point from leaking whenever a path occasionally exceeds the floor. Math.random is sufficient โ€” we only need unpredictability of the exact delay, not cryptographic guarantees.

default_login_ip_rate_limit
#

DEFAULT_MAX_BODY_SIZE
#

DEFAULT_MAX_SESSIONS
#

DEFAULT_MAX_TOKENS
#

DEFAULT_METATYPES_PATH
#

DEFAULT_QUEUE_MAX_SIZE
#

DEFAULT_RATE_LIMITER_MAX_KEYS
#

rate_limiter.ts view source

100000

Default tracked-key cap: bounds worst-case memory under key-enumeration attacks (an attacker rotating source IPs cannot grow the backing map indefinitely between cleanup ticks). Tuned to comfortably fit real traffic for a single-instance deployment while capping memory at a few MB in the worst case.

DEFAULT_RECONNECT_DELAY
#

DEFAULT_RECONNECT_DELAY_MAX
#

DEFAULT_ROTATION_INTERVAL_MS
#

DEFAULT_SERVER_HEARTBEAT_TIMEOUT
#

default_setup_logger
#

DEFAULT_SIGNUP_FAIL_FLOOR_MS
#

auth/signup_routes.ts view source

250

Default minimum wall-clock time (ms) for a signup denial (403 / 409) response.

Parallel to login's DEFAULT_LOGIN_FAIL_FLOOR_MS. Without a floor, an attacker can distinguish ERROR_NO_MATCHING_INVITE (cheap โ€” bails before Argon2 + tx) from ERROR_SIGNUP_CONFLICT (Argon2 + tx + rollback) via response time and use the gap as a username-enumeration oracle. Picked to exceed the p99 of every denial code path (Argon2id dominates at ~100ms, plus DB + overhead). 429 stays fast by design (same precedent as login) so rate-limit DoS handling stays cheap.

DEFAULT_SIGNUP_FAIL_JITTER_MS
#

auth/signup_routes.ts view source

25

Default uniform jitter window (ยฑms) layered on the floor.

Random jitter prevents a stable clamp point from leaking whenever a path occasionally exceeds the floor. Math.random is sufficient โ€” we only need unpredictability of the exact delay, not cryptographic guarantees.

DEFAULT_SPECS_MODULE
#

default_test_bootstrap_token
#

testing/cross_backend/default_secrets.ts view source

"test_bootstrap_token_for_cross_be"

Fixed bootstrap token written to each backend's token_path before spawn. The test binary reads + consumes this via its *_BOOTSTRAP_TOKEN_PATH env var; the harness POSTs the same token to /api/account/bootstrap to mint the keeper account. Any 32+ char string works โ€” the binary just compares bytes, no entropy required for tests.

default_test_cookie_keys
#

default_test_keeper_password
#

default_test_keeper_username
#

DEFAULT_TEST_PASSWORD
#

testing/app_server.ts view source

"test-password-123"

Default password for bootstrapped test accounts. Shared between the in-process keeper bootstrap (bootstrap_test_keeper, create_test_account_with_credentials, create_test_app_server, TestApp.create_account) and the cross-process bootstrap (cross_backend/setup.ts). The two paths MUST agree โ€” when they diverged during the 3d cross-process lift, ~20 login tests 401'd silently against the cross-process backend because the per-test fixture minted accounts under a different default than the integration suite's hardcoded login bodies expected. Consumers hardcoding the literal string in test bodies should import this constant instead so a future divergence becomes a typecheck miss rather than a runtime password mismatch.

DefaultInProcessSuiteOptions
#

testing/cross_backend/setup.ts view source

DefaultInProcessSuiteOptions

Consumer-facing options for default_in_process_suite_options โ€” the minimal factory inputs both default_in_process_setup and create_test_app_surface_spec consume to produce the {setup_test, surface_source, capabilities} bundle.

session_options

type SessionOptions<string>

create_route_specs

type (ctx: AppServerContext) => Array<RouteSpec>

rpc_endpoints

bootstrap

Bootstrap config โ€” top-level slot, single source of truth for both surface generation and live dispatch. Same precedent as rpc_endpoints. Discriminated by mode; omit for the default (no bootstrap route mounted).

app_options

extra_keeper_roles

Additional roles to grant the bootstrapped keeper alongside ROLE_KEEPER โ€” additive, never replaces. The keeper account always holds ROLE_KEEPER (otherwise daemon-token auth breaks); pass extras here for suites that need additional role coverage.

Admin-suite consumers pass [ROLE_ADMIN] so the default keeper can hit admin-gated RPC methods. describe_standard_admin_integration_tests and describe_audit_completeness_tests need this.

type Array<string>

extra_accounts

Bootstrap-time secondary accounts seeded alongside the keeper. See ExtraAccountSpec for the cradle-only-bypass rationale. Same shape as the cross-process extra_accounts option โ€” suites read seeded accounts from fixture.extra_accounts[username] regardless of transport.

type ReadonlyArray<ExtraAccountSpec>

surface_source

Pre-built AppSurfaceSpec โ€” overrides the default which calls create_test_app_surface_spec against the same factory inputs. Pass when surface assembly needs fields outside the shared subset (e.g. env_schema, event_specs, ws_endpoints, transform_middleware).

derive_error_schemas
#

http/error_schemas.ts view source

({ auth, has_input, has_params, has_query, rate_limit, }: DeriveErrorSchemasOptions): Partial<Record<number, ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>>>

__0

returns

Partial<Record<number, ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>>>

derive_http_method
#

DeriveErrorSchemasOptions
#

http/error_schemas.ts view source

DeriveErrorSchemasOptions

Derive error schemas from a route's auth requirement, input schema, and rate limit config.

Returns the error schemas that middleware will auto-produce for this route. Route handlers can declare additional error schemas via RouteSpec.errors; explicit entries override auto-derived ones for the same status code.

Derivation rules under the new flat-record auth shape: - Has input / params / query schema: 400 (ValidationError). - auth.account === 'required' or auth.actor === 'required': 401 (ApiError) โ€” pre-validation 401 fires when the credential isn't there. 'optional' does not derive 401. - auth.roles?.length: 403 (PermissionError carrying required_roles). - auth.credential_types?.length: 403 (CredentialTypeRequiredError carrying required_credential_types โ€” symmetric with PermissionError). Today the only credential gate is keeper; future gates reuse the literal. - auth.actor !== 'none' ('optional' or 'required'): extends 400 with ActorRequiredError / ActorNotOnAccountError and adds 500 union of NoActorsOnAccountError / AccountVanishedError. The dispatcher's authorization phase emits these whenever it tries to resolve an actor. - rate_limit: 429 (RateLimitError with retry_after).

auth

has_input

type boolean

has_params

type boolean

has_query

type boolean

rate_limit

describe_adversarial_404
#

testing/adversarial_404.ts view source

(options: AdversarialTestOptions): void

Generate adversarial 404 response validation tests.

For each route with params + 404 in error_schemas: 1. Creates a stub handler returning 404 with the declared error code 2. Fires a request with valid-format params (nil UUIDs for UUID params) 3. Validates response status is 404 4. Validates response body matches the declared 404 Zod schema

options

returns

void

describe_adversarial_auth
#

testing/attack_surface.ts view source

(options: AdversarialTestOptions): void

Generate adversarial HTTP auth enforcement test suites.

Describe blocks: - unauthenticated โ†’ 401 โ€” every protected route - wrong role โ†’ 403 โ€” every role route, tested with all non-matching roles - authenticated without role โ†’ 403 โ€” every role route, no-role context - correct auth passes guard โ€” every protected route, assert not 401/403

options

returns

void

describe_adversarial_input
#

testing/adversarial_input.ts view source

(options: AdversarialTestOptions): void

Generate adversarial input validation test suites.

Tests input body validation and params validation for all routes. Uses correct auth credentials so auth guards pass and validation middleware is actually exercised.

options

returns

void

describe_audit_completeness_tests
#

testing/audit_completeness.ts view source

(options: AuditCompletenessTestOptions): void

Composable audit log completeness test suite.

Verifies that every auth mutation route produces the correct audit log event type. Exercises routes via HTTP requests against a real PGlite database, then reads events back through the audit_log_list RPC (the production observation path the admin UI consumes).

options

returns

void

throws

  • Error - at setup time when `options.rpc_endpoints` is empty โ€” the

describe_bearer_auth_cases
#

testing/middleware.ts view source

(suite_name: string, cases: BearerAuthTestCase[], ip_rate_limiter?: RateLimiter | null): void

Run a table of bearer auth middleware test cases.

Generates one test() per case inside a describe() block.

suite_name

type string

cases

type BearerAuthTestCase[]

ip_rate_limiter

type RateLimiter | null
default null

returns

void

describe_bootstrap_success_tests
#

describe_data_exposure_tests
#

testing/data_exposure.ts view source

(options: DataExposureTestOptions): void

Composable data exposure test suite.

Three test groups: 1. Schema-level โ€” walk JSON Schema output/error schemas for sensitive field names 2. Runtime โ€” fire real requests and check response bodies against blocklists 3. Cross-privilege โ€” admin routes return 403 for non-admin, error responses contain no sensitive fields

options

returns

void

describe_rate_limiting_tests
#

testing/rate_limiting.ts view source

(options: RateLimitingTestOptions): void

Standard rate limiting integration test suite.

Creates 3 test groups: 1. IP rate limiting on login โ€” fires max_attempts + 1 login requests, verifies the last returns 429 with a valid RateLimitError body. 2. Per-account rate limiting on login โ€” fires max_attempts + 1 login requests with the same username, verifies the last returns 429. 3. Bearer auth IP rate limiting โ€” fires max_attempts + 1 bearer requests with an invalid token, verifies the last returns 429.

Each test group asserts that required routes exist, failing with a descriptive message if the consumer's route specs are misconfigured.

options

returns

void

throws

  • Error - at setup time when `options.rpc_endpoints` is empty โ€” the

describe_round_trip_validation
#

testing/round_trip.ts view source

(options: RoundTripTestOptions): void

Run schema-driven round-trip validation tests.

For each route: 1. Resolve URL with valid params 2. Generate a valid request body (or use override) 3. Pick auth headers matching the route's auth requirement 4. Fire the request through fixture.transport and validate the response

SSE routes are skipped by Content-Type sniff. Routes returning non-2xx with valid input are still validated against their declared error schemas.

options

returns

void

describe_rpc_attack_surface_tests
#

testing/rpc_attack_surface.ts view source

(options: RpcAttackSurfaceOptions): void

Run the standard RPC attack surface test suite.

Generates 3 test groups: 1. Auth enforcement โ€” per-method auth checks via JSON-RPC envelopes 2. Adversarial envelopes โ€” malformed JSON-RPC requests 3. Adversarial params โ€” schema-invalid params per method

Skips silently when surface.rpc_endpoints is empty.

options

returns

void

describe_rpc_round_trip_tests
#

testing/rpc_round_trip.ts view source

(options: RpcRoundTripTestOptions): void

Run schema-driven round-trip validation for RPC endpoints.

For each method: 1. Generate valid params from the action's input schema 2. Fire a POST request with JSON-RPC envelope 3. For side_effects: false methods, also fire a GET request 4. Validate response is well-formed JSON-RPC; successful responses are also validated against the method's declared output schema

Error responses (from missing DB state, etc.) are expected and validated as well-formed JSON-RPC errors. Successful responses are validated against action.spec.output.

options

returns

void

describe_sse_route_tests
#

testing/sse_round_trip.ts view source

(options: SseRouteTestOptions): void

Run SSE route validation tests.

For each route: opens an authenticated SSE connection, asserts the connected comment, fires the trigger, validates the resulting payload, then asserts close-on-revoke (unless opted out).

options

returns

void

throws

  • Error - at setup time when `options.rpc_endpoints` is empty โ€” the

describe_standard_admin_integration_tests
#

testing/admin_integration.ts view source

(options: StandardAdminIntegrationTestOptions): void

Standard admin integration test suite for fuz_app admin routes.

Exercises account listing, role_grant grant/revoke (via RPC), session management, token management, audit log reads, admin-to-admin isolation, and 401/403 error-coverage on the admin REST surface. Output-schema conformance is not in scope โ€” see the module docstring for the suites that cover it.

options

returns

void

throws

  • Error - at setup time when `options.rpc_endpoints` is empty โ€” admin

describe_standard_adversarial_headers
#

testing/adversarial_headers.ts view source

(suite_name: string, options: TestMiddlewareStackOptions, allowed_origin: string, extra_cases?: AdversarialHeaderCase[] | undefined): void

Create a middleware stack app with standard adversarial header tests.

Convenience wrapper combining create_test_middleware_stack_app and create_standard_adversarial_cases. Generates one test() per case inside a describe() block โ€” asserts body content for both error and success cases, and verifies that mock_validate was (or was not) reached per the case's validate_expectation flag, ensuring earlier middleware actually short-circuits before token validation in the rejection cases.

suite_name

the describe block name

type string

options

middleware stack configuration

allowed_origin

an origin that passes the origin check (used for standard cases)

type string

extra_cases?

additional cases appended after the 7 standard ones

type AdversarialHeaderCase[] | undefined
optional

returns

void

describe_standard_attack_surface_tests
#

testing/attack_surface.ts view source

(options: StandardAttackSurfaceOptions): void

Run the standard attack surface test suite.

Test groups: 1. Snapshot โ€” live surface matches committed JSON 2. Determinism โ€” building twice yields identical results 3. Public routes โ€” bidirectional check (no unexpected, no missing) 4. Middleware stack โ€” every API route has the full middleware chain 5. Surface invariants โ€” structural assertions over surface.routes (error schemas, descriptions, duplicates, consistency) 6. RPC/WS surface invariants โ€” structural assertions over surface.rpc_endpoints + surface.ws_endpoints (descriptions, protocol-action spread, kind โ‡” auth) 7. Security policy โ€” rate limiting on sensitive routes, no unexpected public mutations, method conventions 8. Error schema tightness โ€” informational log of generic vs specific error schemas, plus assertion against default_error_schema_tightness by default (opt out with error_schema_tightness: null) 9. Adversarial auth โ€” unauthenticated/wrong-role/correct-auth enforcement 10. Adversarial input โ€” input body and params validation 11. Adversarial 404 โ€” stub 404 handlers, validate response bodies against declared schemas

Consumer test files call this with project-specific options, then add any project-specific assertions in additional describe blocks.

options

returns

void

describe_standard_cross_process_tests
#

describe_standard_integration_tests
#

testing/integration.ts view source

(options: StandardIntegrationTestOptions): void

Standard integration test suite for fuz_app auth routes.

Exercises login/logout, cookie attributes, session security, session revocation, password change (incl. API token revocation), origin verification, bearer auth (incl. browser context discard on mutations), token revocation, cross-account isolation, expired credential rejection, signup invite edge cases, and response body validation.

Each test group asserts that required routes exist, failing with a descriptive message if the consumer's route specs are misconfigured.

The two signup-invite-edge-case tests call invite_create_action_spec (admin-gated) over the fixture's session, so consumers wiring signup + admin actions must thread extra_keeper_roles: [ROLE_ADMIN] through either default_in_process_suite_options or `default_cross_process_setup(handle, {extra_keeper_roles: [ROLE_ADMIN]}). In both modes the fixture's fixture.account` is the fresh keeper, and the extra-keeper-roles list grants the bootstrapped keeper additional roles inline (cross-process via _testing_reset's bootstrap-time seeding; in-process via bootstrap_test_keeper) โ€” no per-role RPC cost, no offer/accept round-trip. The tests run against the production open_signup: false default โ€” the cross-process per-test secondary mint via fixture.create_account() is invite-gated (keeper drives invite_create before signup) so the harness doesn't need to flip the setting. Consumers that don't wire signup or invite_create silently skip these two tests.

options

returns

void

throws

  • Error - at setup time when `options.rpc_endpoints` is empty โ€” the

describe_standard_tests
#

testing/standard.ts view source

(options: StandardTestOptions): void

Run the full standard test bundle โ€” integration, admin (when roles provided), audit completeness (when roles provided), bootstrap success (when bootstrap.mode === 'live'), round trip, RPC round trip, data exposure, rate limiting.

options

returns

void

detect_format
#

testing/schema_generators.ts view source

(field_schema: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>): string | null

Detect format constraints on a field by converting to JSON Schema. Returns format string (e.g. 'uuid', 'email') or null.

field_schema

type ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>

returns

string | null

diff_schema_snapshots
#

testing/schema_parity.ts view source

(a: SchemaSnapshot, b: SchemaSnapshot): SchemaDiff[]

Structural diff between two snapshots โ€” empty array means parity holds.

Order of diffs is deterministic: schema_version first, then tables in sorted order (with column/index/constraint sub-diffs grouped per table), then sequences. Consumers can rely on this for stable diff output.

a

b

returns

SchemaDiff[]

disconnect_event_types
#

realtime/sse_auth_guard.ts view source

ReadonlySet<string>

Audit event types that trigger SSE stream disconnection.

role_grant_revoke requires the revoked role to match the guard's required_role (or is skipped entirely when required_role is null โ€” useful for streams not gated by any specific role_grant). session_revoke_all and password_change close every stream for the target account. session_revoke closes only the stream tied to the specific revoked session (matched by the blake3 session hash in event.metadata.session_id) โ€” closing all of a user's streams for a single-session revoke would be over-aggressive.

dispatch_ws_message
#

testing/ws_round_trip.ts view source

(on_message: (evt: MessageEvent<WSMessageReceive>, ws: WSContext<unknown>) => void, event: MessageEvent<any>, ws: WSContext<unknown>): Promise<...>

Hono types WSEvents.onMessage as () => void | Promise<void>. Awaits only the Promise branch so tests observe full dispatch (auth, validation, handler, send).

on_message

type (evt: MessageEvent<WSMessageReceive>, ws: WSContext<unknown>) => void

event

type MessageEvent<any>

ws

type WSContext<unknown>

returns

Promise<void>

drop_auth_schema
#

testing/db.ts view source

(db: Db): Promise<void>

Drop all auth tables and schema version tracking for a clean slate.

Recommended at the start of init_schema callbacks for create_pg_factory. Persistent test databases can accumulate stale schema from previous fuz_app versions โ€” this ensures migrations run against a truly empty database. Safe on fresh databases (IF EXISTS on all statements). No-op effect for PGlite (already fresh), but harmless to call unconditionally.

db

type Db

returns

Promise<void>

EffectErrorContext
#

server/app_server.ts view source

EffectErrorContext

Context passed to on_effect_error when a pending effect rejects.

method

HTTP method of the request that spawned the effect.

type string

path

URL path of the request that spawned the effect.

type string

Email
#

primitive_schemas.ts view source

ZodEmail

Email validation. Lives here rather than @fuzdev/fuz_util because every current consumer pairs it with Username (signup, invites, audit log) โ€” keeping the two together avoids a cross-package import for the identity-primitive bundle. Promote to fuz_util if a non-identity consumer surfaces.

emit_after_commit
#

http/pending_effects.ts view source

(ctx: EmitAfterCommitContext, fn: () => void | Promise<void>): void

Defer a side effect until after the handler's transaction commits.

Pushes a raw thunk onto ctx.post_commit_effects โ€” the flush middleware (in server/app_server.ts and the per-message WS dispatcher) is the only site that ever invokes fn. This is load-bearing: a previous implementation queued Promise.resolve().then(fn), which JS's microtask scheduler drains before the wrapping await db.query('COMMIT') resumes โ€” fn fired mid-transaction and a rollback would leak a notification for state that never landed.

The thunk shape closes that gap by deferring the work to flush time. The flush owns the per-thunk try/catch + log.error so any directly-pushed thunk (tests included) cannot escape the safety net.

ctx

context carrying log and the post_commit_effects queue

fn

side effect to run after commit; may return void or Promise<void>

type () => void | Promise<void>

returns

void

EmitAfterCommitContext
#

EmitDecorator
#

auth/audit_emitter.ts view source

EmitDecorator

Wrap the bound emit before it gets captured by emit_role_grant_target's closure and exposed on the returned AuditEmitter. Test instrumentation uses this to record emit invocation ordering against external markers (e.g. eager ConnectionCloser calls in connection_closer.db.test.ts) without paying the freeze-breaking footgun the pre-decorator patch_audit_emit_capture hot-patcher had.

Because the inner closure captures the decorated function (not the outer slot reference), emit_role_grant_target also routes through the wrap โ€” the close-vs-emit ordering helper sees role-grant-shape emissions, not just bare emit calls. Production never sets this.

env_schema_to_surface
#

http/surface.ts view source

(schema: ZodObject<$ZodLooseShape, $strip>): AppSurfaceEnv[]

Convert env schema to surface entries using .meta() metadata.

schema

Zod object schema with .meta() on fields

type ZodObject<$ZodLooseShape, $strip>

returns

AppSurfaceEnv[]

EnvDeps
#

runtime/deps.ts view source

EnvDeps

Environment variable access.

env_get

Get an environment variable value.

type (name: string) => string | undefined

env_set

Set an environment variable.

type (name: string, value: string) => void

EnvValidationError
#

env/load.ts view source

Error thrown when environment validation fails.

Contains structured information for apps to format their own error messages.

inheritance

extends:
  • Error

raw

The raw env values that were read.

type Record<string, string | undefined>

readonly

zod_error

The Zod validation error.

type z.core.$ZodError

readonly

all_undefined

True if every env var was undefined (nothing loaded).

type boolean

readonly

constructor

type new (raw: Record<string, string | undefined>, zod_error: $ZodError<unknown>): EnvValidationError

raw
type Record<string, string | undefined>
zod_error
type $ZodError<unknown>

format_issues

Format Zod validation issues as human-readable strings.

type (): string[]

returns string[]

array of formatted issue strings like "PORT: Expected number"

EnvValidationResult
#

env/resolve.ts view source

EnvValidationResult

Result of env var validation.

Uses discriminated union for better type narrowing: - ok: true, missing: null โ€” all vars present - ok: false, missing: EnvVarRef[] โ€” some vars missing

EnvVarRef
#

env/resolve.ts view source

EnvVarRef

An env var reference found in a config.

name

Variable name (without $$ delimiters).

type string

path

Path where the reference was found (e.g., "target.host", "resources[3].path").

type string

optional

Whether the reference is optional ($$?VAR$$). Optional refs resolve to the empty string when unset and are skipped by validate_env_vars โ€” a var that's intentionally blank doesn't count as missing.

type boolean

ERROR_ACCOUNT_NOT_FOUND
#

ERROR_ACCOUNT_VANISHED
#

http/error_schemas.ts view source

"account_vanished"

Authentication validated an account, but a follow-up read in the authorization phase came back null โ€” the account or its named actor row was deleted between the credential check and the dispatcher's build_request_context / build_account_context step. Torn read, not a missing-actor invariant violation. Surfaced as 500 so the operator sees the race signal; clients can retry. Distinct from ERROR_ACCOUNT_NOT_FOUND (stale token referencing a long-deleted account, raised at credential validation) and ERROR_NO_ACTORS_ON_ACCOUNT (the actor list enumerated empty).

ERROR_ACTOR_NOT_ON_ACCOUNT
#

ERROR_ACTOR_REQUIRED
#

http/error_schemas.ts view source

"actor_required"

Multi-actor account requires the request to carry an explicit acting field naming the actor the request is acting as, so the dispatcher's authorization phase doesn't pick a default actor silently. Returned with the available actors so the client can prompt.

ERROR_ACTOR_SEARCH_SCOPE_REQUIRED
#

auth/actor_search_action_specs.ts view source

"actor_search_scope_required"

Reason: scope_ids was empty and the caller is not admin. Distinct from standard invalid_params issues so the visiones picker can surface a specific "pick a scope first" message rather than echoing Zod issues.

ERROR_ALREADY_BOOTSTRAPPED
#

ERROR_AUTHENTICATION_REQUIRED
#

ERROR_BEARER_REJECTED_BROWSER
#

ERROR_CREDENTIAL_TYPE_REQUIRED
#

http/error_schemas.ts view source

"credential_type_required"

Route requires a credential type the request didn't arrive on. Symmetric with ERROR_INSUFFICIENT_PERMISSIONS + required_roles: the body carries required_credential_types: ReadonlyArray<string> โ€” what the route demanded, not what arrived. Today the only credential gate is keeper (['daemon_token']); future gates (agent_token, group_actor_token) reuse the same literal and label themselves through the array.

ERROR_DATABASE_CONNECTION_FAILED
#

ERROR_FORBIDDEN_ORIGIN
#

ERROR_FOREIGN_KEY_VIOLATION
#

ERROR_INSUFFICIENT_PERMISSIONS
#

ERROR_INVALID_CREDENTIALS
#

ERROR_INVALID_DAEMON_TOKEN
#

ERROR_INVALID_EVENT_TYPE
#

ERROR_INVALID_JSON_BODY
#

ERROR_INVALID_QUERY_PARAMS
#

ERROR_INVALID_REQUEST_BODY
#

ERROR_INVALID_ROUTE_PARAMS
#

ERROR_INVALID_TOKEN
#

ERROR_INVITE_ACCOUNT_EXISTS_EMAIL
#

ERROR_INVITE_ACCOUNT_EXISTS_USERNAME
#

ERROR_INVITE_DUPLICATE
#

ERROR_INVITE_NOT_FOUND
#

ERROR_KEEPER_ACCOUNT_NOT_CONFIGURED
#

ERROR_KEEPER_ACCOUNT_NOT_FOUND
#

ERROR_NO_ACTORS_ON_ACCOUNT
#

http/error_schemas.ts view source

"no_actors_on_account"

Authenticated account exists but has no actors. Server invariant violation โ€” signup / bootstrap always create an actor in the same transaction. Surfaced from the dispatcher's authorization phase as a 500 so the operator sees the corruption signal rather than a confusing 4xx. Distinct from ERROR_ACCOUNT_VANISHED: the actor list was enumerated successfully and came back empty.

ERROR_NO_MATCHING_INVITE
#

ERROR_PAYLOAD_TOO_LARGE
#

ERROR_RATE_LIMIT_EXCEEDED
#

ERROR_ROLE_GRANT_NOT_FOUND
#

ERROR_ROLE_GRANT_OFFER_ACTOR_ACCOUNT_MISMATCH
#

ERROR_ROLE_GRANT_OFFER_ACTOR_MISMATCH
#

ERROR_ROLE_GRANT_OFFER_EXPIRED
#

ERROR_ROLE_GRANT_OFFER_NOT_AUTHORIZED
#

auth/role_grant_offer_action_specs.ts view source

"role_grant_offer_not_authorized"

Error reason โ€” caller is not authorized to offer this role (default policy: caller lacks the role; consumer authorize callback may add further policy).

ERROR_ROLE_GRANT_OFFER_NOT_FOUND
#

ERROR_ROLE_GRANT_OFFER_ROLE_NOT_GRANTABLE
#

ERROR_ROLE_GRANT_OFFER_SELF_TARGET
#

ERROR_ROLE_GRANT_OFFER_TERMINAL
#

ERROR_ROLE_NOT_SELF_SERVICE_ELIGIBLE
#

ERROR_ROLE_NOT_WEB_GRANTABLE
#

ERROR_ROW_NOT_FOUND
#

ERROR_SIGNUP_CONFLICT
#

ERROR_TABLE_NO_PRIMARY_KEY
#

ERROR_TABLE_NOT_FOUND
#

ERROR_TOKEN_FILE_MISSING
#

ErrorCoverageCollector
#

testing/error_coverage.ts view source

Tracks which route ร— status (and route ร— status ร— code) combinations have been exercised in tests.

Use record() to log an observed status (optionally with the body's error code), or assert_and_record() to combine response validation with tracking (auto-extracts body.error from the response when present). After all tests, call uncovered() to find declared error paths never exercised.

An observation recorded without a code still satisfies "any-code" coverage requirements for the same status โ€” i.e., if a caller records just the status, all declared codes for that status are considered covered. Per-code tracking is additive: callers who know the body's error value should pass it to get precise per-code gap reporting on routes with literal/enum error schemas.

observed

Observed keys: "METHOD /spec-path:STATUS" or "METHOD /spec-path:STATUS:CODE".

Both shapes coexist โ€” the code-less key marks the status as covered at any code; a code-bearing key adds per-code precision.

type Set<string>

readonly

record

Record an observed error status (optionally with the body's error code) for a route.

Resolves the concrete request path back to the spec template path (e.g., /api/accounts/abc โ†’ /api/accounts/:id). When code is provided, it is stored alongside the status for per-code coverage tracking.

type (route_specs: RouteSpec[], method: string, path: string, status: number, code?: string | undefined): void

route_specs
type RouteSpec[]
method
type string
path

request path (may be concrete)

type string
status
type number
code?

observed body error code (pass when the route's error schema declares specific codes via z.literal or z.enum)

type string | undefined
optional
returns void

assert_and_record

Validate a response against its route spec and record the status.

Wraps assert_response_matches_spec and records the status code. For error responses, auto-extracts body.error from the JSON body (via a cloned response, so the original stream stays usable) and records it for per-code coverage. Pass an explicit code to override the auto-extracted value or when the body was already consumed.

type (route_specs: RouteSpec[], method: string, path: string, response: Response, code?: string | undefined): Promise<void>

route_specs
type RouteSpec[]
method
type string
path
type string
response
type Response
code?

observed body error code (override; if omitted and the response body is a JSON object with a string error field, that value is auto-extracted)

type string | undefined
optional
returns Promise<void>
throws
  • Error - if the response body fails the route spec's declared

uncovered

Find declared error paths that were never observed.

Computes the declared set from merge_error_schemas for each route spec. For statuses whose error schema names specific codes (via z.literal or z.enum), reports per-code rows; otherwise reports one row per status. A status-only observation (no code) satisfies all declared codes for that status โ€” the "any-code" rule.

type (route_specs: RouteSpec[], options?: CoverageFilterOptions | undefined): UncoveredEntry[]

route_specs
type RouteSpec[]
options?
type CoverageFilterOptions | undefined
optional
returns UncoveredEntry[]

ErrorCoverageOptions
#

ErrorSchemaAuditEntry
#

ErrorSchemaSpecificity
#

ErrorSchemaTightnessOptions
#

events_to_surface
#

http/surface.ts view source

(event_specs: EventSpec[]): AppSurfaceEvent[]

Convert SSE event specs to surface entries.

event_specs

type EventSpec[]

returns

AppSurfaceEvent[]

EventSpec
#

realtime/sse.ts view source

EventSpec

Spec for a push event โ€” declares params schema, description, and channel.

method

Event method name, used as the JSON-RPC notification method.

type string

params

Zod schema for the notification params payload.

type z.ZodType

description

Human-readable description for surface output and docs.

type string

channel

Channel this event broadcasts on. Omit for cross-channel events.

type string

ExtraAccountFixture
#

testing/cross_backend/setup.ts view source

ExtraAccountFixture

Bootstrap-time-seeded secondary account exposed on the fixture.

account

type {readonly id: Uuid; readonly username: string}
readonly

actor

type {readonly id: Uuid}
readonly

api_token

type string
readonly

session_cookie

type string
readonly

create_session_headers

type (extra?: Record<string, string>) => Record<string, string>
readonly

create_bearer_headers

type (extra?: Record<string, string>) => Record<string, string>
readonly

ExtraAccountSpec
#

testing/cross_backend/setup.ts view source

ExtraAccountSpec

Spec for a bootstrap-time secondary account seeded alongside the keeper by _testing_reset (cross-process) or create_test_app (in-process). Used for accounts whose required roles aren't admin-grantable via offer/accept โ€” primarily ROLE_KEEPER (whose RoleSpec.grant_paths is bootstrap-only), where the only way to land the grant is at the bootstrap-equivalent setup step.

For admin-grantable roles, prefer fixture.create_account({roles}) โ€” that goes through the production offer/accept handlers and observes audit + WS fan-out. extra_accounts is the cradle-only bypass; the runtime has no equivalent action.

username

type string
readonly

password_value

type string
readonly

roles

type ReadonlyArray<string>
readonly

extract_action_result
#

actions/action_event_helpers.ts view source

(event: ActionEvent<string, "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute", "initial" | "parsed" | "handling" | "handled" | "failed">): Result<...>

Pull the terminal Result from an action event.

data.error populated โ†’ error path (covers both explicit failed and the unhandled receive_error / send_error case where no handler was registered for the error phase). step === 'handled' โ†’ success path.

event

type ActionEvent<string, "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute", "initial" | "parsed" | "handling" | "handled" | "failed">

returns

Result<{ value: unknown; }, { error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<"JsonrpcServerErrorCode">); message: string; data?: unknown; }; }>

throws

  • Error - if the event is in a non-terminal state (programming error โ€”

extract_declared_error_codes
#

testing/error_coverage.ts view source

(schema: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>): string[] | null

Extract declared error code values from an error response schema.

Recognizes schemas shaped like z.object({error: z.literal(...)}) or z.object({error: z.enum([...])}) (incl. looseObject/strictObject). Returns the set of declared code values, or null if the schema doesn't expose a literal/enum error field (e.g., bare ApiError with z.string()).

Used by coverage reporting to split a single declared status into per-code rows when the route's error schema names specific codes.

schema

type ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>

returns

string[] | null

FakeHonoContextOptions
#

FakeWs
#

testing/ws_round_trip.ts view source

FakeWs

A WSContext paired with capture arrays. Use sends to assert on outgoing frames; use closes to assert on revocation / close.

ws

type WSContext

sends

type Array<string>

closes

type Array<{code?: number; reason?: string}>

FetchDeps
#

runtime/deps.ts view source

FetchDeps

HTTP fetch capability.

fetch

Fetch a URL. Same signature as the global fetch.

type typeof globalThis.fetch

FetchTransport
#

testing/transports/fetch_transport.ts view source

FetchTransport

The transport shape: callable as RpcTestTransport plus a cookies() accessor that returns the current jar state. The accessor exists so ws_transport can thread the session cookie onto the WS upgrade without an HTTP round trip.

inheritance

cookies

Snapshot of every cookie currently in the jar, formatted as full Set-Cookie values (name=value). Used by ws_transport to compose the Cookie header on the upgrade request.

type () => ReadonlyArray<string>
readonly

FetchTransportOptions
#

testing/transports/fetch_transport.ts view source

FetchTransportOptions

Construction options for create_fetch_transport.

base_url

Base URL the binary is reachable at โ€” e.g. http://localhost:8788.

type string
readonly

initial_cookies

Initial cookie values to seed the jar. Pass the Set-Cookie values captured from a prior bootstrap() call to keep the keeper session across a transport-recreation boundary. Each entry is a full Set-Cookie value (the same string Headers.getSetCookie() returns).

type ReadonlyArray<string>
readonly

origin

Origin header threaded onto every request when the caller hasn't set one. Defaults to base_url; backends running with ALLOWED_ORIGINS=http://localhost:* accept http://localhost:<port> matching the spawned binary.

Pass null to disable the default โ€” useful for bearer-only probes that must not look like browser-context requests (the auth middleware silently discards bearer credentials when Origin/Referer is present). Callers can still set Origin per-call via init.headers.

type string | null
readonly

filter_authenticated_routes
#

http/surface_query.ts view source

(surface: AppSurface): AppSurfaceRoute[]

Filter routes that require basic authentication only โ€” account === 'required' with no role / credential gate.

surface

returns

AppSurfaceRoute[]

filter_keeper_routes
#

filter_mutation_routes
#

filter_protected_routes
#

filter_public_routes
#

filter_rate_limited_routes
#

filter_role_routes
#

filter_routes_by_prefix
#

filter_routes_for_role
#

http/surface_query.ts view source

(surface: AppSurface, role: string): AppSurfaceRoute[]

Filter routes whose auth.roles includes the named role.

surface

role

type string

returns

AppSurfaceRoute[]

filter_routes_with_input
#

filter_routes_with_params
#

filter_routes_with_query
#

FilterableBroadcastTransport
#

actions/transports_ws_backend.ts view source

FilterableBroadcastTransport

Structural capability for transports that can broadcast with a per-connection ACL predicate. Named separately from Transport so the broadcast API can feature-detect without importing a concrete class.

ConnectionIdentity is the auth-gated identity shape used today. When a second implementation (e.g. SSE backend transport) lands with a different identity, consider parameterizing on TIdentity.

inheritance

extends:

broadcast_filtered

type ( message: JsonrpcMessageFromServerToClient, predicate: (identity: ConnectionIdentity) => boolean, ) => number

find_auth_route
#

testing/integration_helpers.ts view source

(specs: RouteSpec[], suffix: "/login" | "/logout" | "/password" | "/verify" | "/signup" | "/bootstrap", method: RouteMethod): RouteSpec | undefined

Find a REST auth route by suffix and method.

Decouples tests from consumer route prefix (/api/account/login, /api/auth/login, etc.). suffix must be one of rest_auth_route_suffixes โ€” throws otherwise so an RPC-only method path (e.g. /sessions/revoke-all) fails loudly at the call site instead of silently returning undefined.

specs

type RouteSpec[]

suffix

type "/login" | "/logout" | "/password" | "/verify" | "/signup" | "/bootstrap"

method

returns

RouteSpec | undefined

throws

  • Error - if `suffix` is not in `rest_auth_route_suffixes`.

find_route_spec
#

testing/integration_helpers.ts view source

(specs: RouteSpec[], method: string, path: string): RouteSpec | undefined

Find a route spec matching the given method and path.

Supports both exact matches and parameterized paths (:param segments).

specs

type RouteSpec[]

method

type string

path

request path (exact or with concrete param values)

type string

returns

RouteSpec | undefined

find_rpc_action
#

testing/rpc_helpers.ts view source

(rpc_endpoints: readonly RpcEndpointSpec[], method: string): { path: string; action: RpcAction; } | undefined

Find the RpcAction for a method within a set of RPC endpoint specs. Returns both the endpoint path and the matched action. undefined when the method is not registered.

rpc_endpoints

type readonly RpcEndpointSpec[]

method

type string

returns

{ path: string; action: RpcAction; } | undefined

find_rpc_method
#

testing/rpc_helpers.ts view source

(rpc_endpoints: readonly AppSurfaceRpcEndpoint[], method: string): { path: string; method_spec: AppSurfaceRpcMethod; } | undefined

Find the generated surface entry for a method โ€” the shape returned by generate_app_surface (JSON-serializable, useful for schema assertions at the boundary of a consumer test).

rpc_endpoints

type readonly AppSurfaceRpcEndpoint[]

method

type string

returns

{ path: string; method_spec: AppSurfaceRpcMethod; } | undefined

flush_pending_effects
#

http/pending_effects.ts view source

(effects: readonly Promise<void>[], log: Logger, on_rejection?: ((reason: unknown) => void) | undefined): Promise<void>

Drain an eager pending_effects queue: Promise.allSettled the in-flight handles, route every rejection through log.error, and fan out to on_rejection when supplied (production wires this to on_effect_error for monitoring).

Returned promise resolves once every effect has settled. Never rejects. No-op when effects is empty (common on read-only requests).

Symmetric with flush_post_commit_effects for the deferred queue.

effects

type readonly Promise<void>[]

log

type Logger

on_rejection?

type ((reason: unknown) => void) | undefined
optional

returns

Promise<void>

flush_post_commit_effects
#

http/pending_effects.ts view source

(effects: readonly (() => void | Promise<void>)[], log: Logger): Promise<void>

Drain a post_commit_effects queue: invoke each thunk under try/catch, collect any returned promises, and Promise.allSettled them. Synchronous throws and async rejections are routed through log.error so one failing effect cannot starve siblings.

Returned promise resolves once every thunk has finished. Never rejects.

effects

type readonly (() => void | Promise<void>)[]

log

type Logger

returns

Promise<void>

ForeignKeyError
#

http/error_schemas.ts view source

ZodObject<{ error: ZodLiteral<"foreign_key_violation">; }, $loose>

Foreign key violation error โ€” returned when a delete is blocked by references.

format_arg_name
#

cli/help.ts view source

(prop: ZodSchemaProperty): string

Format argument name with short aliases for display.

Only single-char aliases are shown (e.g., -h, --help). Flags use snake_case (e.g., --env_file, --detect_only).

prop

schema property

type ZodSchemaProperty

returns

string

formatted name string

format_audit_metadata
#

ui/ui_format.ts view source

(event_type: string, metadata: Record<string, unknown> | null): string

Format audit event metadata for display based on event type.

event_type

builtin or consumer-registered audit event type

type string

metadata

type Record<string, unknown> | null

returns

string

format_datetime_local
#

ui/ui_format.ts view source

(timestamp: string | number | Date): string

Format a timestamp as an absolute datetime string for title attributes.

timestamp

type string | number | Date

returns

string

readable absolute datetime like "2026-03-21 14:30:00 UTC"

format_db_status
#

db/status.ts view source

(status: DbStatus): string

Format a DbStatus as a human-readable string for CLI output.

status

the status to format

returns

string

multi-line string suitable for console output

format_env_display_value
#

env/mask.ts view source

(value: unknown, secret: boolean): string

Format an env value for display, masking secrets.

value

the env value to format

type unknown

secret

whether the value is secret and should be masked

type boolean

returns

string

display string โ€” masked placeholder for secrets, string values as-is, non-strings JSON-stringified

format_missing_env_vars
#

env/resolve.ts view source

(missing: EnvVarRef[], options?: FormatMissingEnvVarsOptions | undefined): string

Format missing env vars error message.

Groups refs by variable name so each missing var is shown once with all paths where it's referenced.

missing

missing env var references (may contain duplicate names)

type EnvVarRef[]

options?

formatting options

type FormatMissingEnvVarsOptions | undefined
optional

returns

string

formatted error message for display

format_relative_time
#

ui/ui_format.ts view source

(timestamp: string | number | Date, now?: number): string

Format a timestamp as a relative time string.

timestamp

type string | number | Date

now

type number
default Date.now()

returns

string

human-friendly relative time (e.g. "2m ago", "3h ago", "5d ago", "2mo ago", "1y ago")

format_route_key
#

format_schema_diffs
#

testing/schema_parity.ts view source

(diffs: readonly SchemaDiff[], labels?: SchemaDiffLabels): string

Render a diff list as a human-readable multi-line string. Empty diffs produce an empty string.

diffs

type readonly SchemaDiff[]

labels

default {}

returns

string

format_scope_context
#

format_uptime
#

ui/ui_format.ts view source

(ms: number): string

Format milliseconds as a human-friendly uptime string.

ms

type number

returns

string

human-friendly duration (e.g. "45s", "12m", "3h 15m", "2d 5h")

format_value
#

ui/ui_format.ts view source

(value: unknown): string

Format an arbitrary value for table cell display.

value

type unknown

returns

string

FormatMissingEnvVarsOptions
#

FormatScope
#

ui/format_scope.ts view source

FormatScope

Render a {scope_id, role} pair as a human label. Return null to fall back to the raw scope uuid (or a caller-chosen global_label when scope_id is null).

Returning null for unknown scope ids (stale cache, revoked resource) is the recommended pattern โ€” components show the raw uuid rather than a misleading blank.

FormState
#

ui/form_state.svelte.ts view source

form

Creates a form attachment that handles Enter key advancing between focusable elements and tracks field touched state via delegated focusout.

Fields are identified by their name attribute.

type (): Attachment<HTMLFormElement>

returns Attachment<HTMLFormElement>
throws
  • Error - in DEV when called while already attached, or when an

is_touched

Whether a field has been blurred at least once.

type (field: string): boolean

field
type string
returns boolean

show

Whether to show validation errors for a field. Returns true if the field has been blurred or a submit attempt was made.

type (field: string): boolean

field
type string
returns boolean

touch

Programmatically marks a field as touched without requiring a blur event.

type (field: string): void

field
type string
returns void

focus

Focuses the named input within the form.

type (field: string): void

field
type string
returns void

attempt

Marks the form as having been submitted, causing all field errors to show.

type (): void

returns void

reset

Resets all touched and attempted state.

type (): void

returns void

FrontendHttpTransport
#

actions/transports_http.ts view source

Thin fetch adapter for the JSON-RPC endpoint. POST by default; GET when the optional has_side_effects(method) callback returns false for the method (matches create_rpc_endpoint's GET convention). On non-OK HTTP responses, synthesizes a JSON-RPC error envelope via http_status_to_jsonrpc_error_code. Always reports ready.

inheritance

implements:

transport_name

readonly

constructor

type new (url: string, headers?: Record<string, string> | undefined, has_side_effects?: ((method: string) => boolean) | undefined): FrontendHttpTransport

url
type string
headers?
type Record<string, string> | undefined
optional
has_side_effects?
type ((method: string) => boolean) | undefined
optional

send

type (message: { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }, options?: TransportSendOptions | undefined): Promise<...>

message
type { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }
options?
type TransportSendOptions | undefined
optional
returns Promise<{ [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; } | { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<...>); message: string; data?: unknown; }; }>

send

type (message: { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }, options?: TransportSendOptions | undefined): Promise<...>

message
type { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }
options?
type TransportSendOptions | undefined
optional
returns Promise<{ [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; } | { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<...>); message: string; data?: unknown; }; }>

send

type (message: { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }, options?: TransportSendOptions | undefined): Promise<...>

message
type { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }
options?
type TransportSendOptions | undefined
optional
returns Promise<{ [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; } | { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<...>); message: string; data?: unknown; }; }>

is_ready

type (): boolean

returns boolean

FrontendRpcClient
#

actions/frontend_rpc_client.ts view source

FrontendRpcClient<TApi>

Bundle returned by create_frontend_rpc_client.

generics

TApi

api

Typed throwing Proxy. await api.method(input) returns the unwrapped value or throws an Error with {code, data} from the JSON-RPC error. Default for call sites that don't inspect errors.

type ThrowingApi<TApi>

api_result

Typed Result-shaped Proxy. await api_result.method(input) returns Result<{value}, {error: JsonrpcErrorObject}>. Use when call sites inspect error.data.reason without try/catch, or when Error allocation per {ok: false} would be wasteful.

type TApi

peer

Underlying peer โ€” exposed for consumers that need to register more transports or send raw messages.

environment

Action environment โ€” exposed for consumers that need to share it (e.g. attach a notification handler registry).

FrontendWebsocketClient
#

actions/socket.svelte.ts view source

Reactive WebSocket client implementing WebsocketConnection.

Construct with a URL and optional config; call connect() to open the socket and begin auto-reconnect. Register message/error handlers via add_message_handler / add_error_handler โ€” both return unsubscribe functions. FrontendWebsocketTransport consumes this as its connection.

Session-revocation close codes (WS_CLOSE_SESSION_REVOKED) put the client in a permanently-closed state; reconnecting would just loop on 401.

inheritance

implements:

ws

type WebSocket | null

status

type SocketStatus

reconnect_count

type number

current_reconnect_delay

type number

last_connect_time

Epoch ms of the most recent successful open. Never cleared on close.

type number | null

last_close_time

Epoch ms of the most recent close event or client-initiated close.

type number | null

last_close_code

Close code from the most recent close. Initial null means "never closed."

type number | null

last_close_reason

Reason string from the most recent close event (may be empty).

type string | null

last_send_error

The error thrown by the most recent attempted send(), or null if the most recent attempt succeeded or none has been attempted yet. Populated when the underlying ws.send throws (e.g., buffer full, serialization error); reset to null on the next successful send. Not touched when send() short-circuits because the socket is not connected โ€” consult connected for that case. Wrappers surfacing per-message failure reasons can read this after a false return from send().

type Error | null

connected

type boolean

readonly

constructor

type new (url: string, options?: FrontendWebsocketClientOptions): FrontendWebsocketClient

url
type string
options
default {}

set_reconnect

Swap the auto-reconnect policy in place. Accepts the same shape as the constructor's reconnect option: false disables reconnect, true or null/omitted restores the defaults, or a config object customizes specific fields (missing fields fall back to defaults, not "keep current" โ€” each call defines the whole policy atomically, same as the constructor).

In-flight reconnect schedules are monotonically shortened: the effective total wait from arm-time never exceeds what the new policy prescribes. If the new target is already past the time already elapsed, the reconnect fires immediately (on the next tick). The wait is never extended.

Turning reconnect off while a reconnect timer is pending cancels that timer and transitions status to closed (since the lie of 'reconnecting' would be visible to UI indicators). Turning it back on does not synthesize a reconnect โ€” wait for the next close.

type (reconnect?: boolean | FrontendWebsocketReconnectOptions | null): void

reconnect
type boolean | FrontendWebsocketReconnectOptions | null
default null
returns void

set_heartbeat

Swap the heartbeat policy in place. Accepts the same shape as the constructor's heartbeat option: false disables the timer, true or null/omitted restores the defaults, or a config object customizes specific fields (missing fields fall back to defaults, not "keep current" โ€” each call defines the whole policy atomically, same as the constructor and set_reconnect).

When connected, the live timer is restarted immediately so the new interval / receive_timeout take effect without a reconnect; when disconnected, just stashes the policy for the next open.

type (heartbeat?: boolean | FrontendWebsocketHeartbeatOptions | null): void

heartbeat
type boolean | FrontendWebsocketHeartbeatOptions | null
default null
returns void

cancel_reconnect

Cancel a scheduled reconnect without closing the client or disabling auto-reconnect. Transitions status from reconnecting โ†’ closed and resets the backoff counters โ€” the next close still triggers a fresh reconnect cycle under the current policy. No-op when no reconnect is pending.

Use this when UI state asks "stop trying for now" without the finality of disconnect (which also rejects pending/queued requests and clears heartbeat) or the policy change of set_reconnect(false) (which disables future reconnects). The queue stays intact so that calling connect later flushes buffered work.

type (): void

returns void

connect

Open the WebSocket. No-op on SSR, or if the session has been revoked. Cancels any pending reconnect and tears down any existing connection first; an open prior socket is closed with a normal-closure code.

type (): void

returns void

disconnect

Close the WebSocket, cancel any pending reconnect, and reset the reconnect backoff counters. Puts the client in closed status; call connect() to reopen. Safe to call more than once.

type (code?: number): void

code
type number
default DEFAULT_CLOSE_CODE
returns void

[Symbol.dispose]

Explicit-resource-management hook โ€” supports using client = new FrontendWebsocketClient(url).

type (): void

returns void

send

type (data: object): boolean

data
type object
returns boolean

request

Promise-based JSON-RPC over the socket. Auto-assigns a monotonic request id (or uses an explicit one supplied via options.id โ€” used by FrontendWebsocketTransport which delegates to this method and has its own peer-minted UUID), tracks the pending promise, and resolves when the server sends a matching response.

Callers supplying an explicit options.id are responsible for uniqueness โ€” the pending map is keyed by id, and a duplicate silently overwrites the prior entry. Auto-minted ids are monotonic and never collide with themselves or with peer-minted UUIDs (the types differ: integer vs string).

While the socket is disconnected, the request is buffered in a bounded queue (default-on, DEFAULT_QUEUE_MAX_SIZE) and flushed on reopen. Pass {queue: false} to reject immediately when disconnected โ€” used internally by the heartbeat, which must not fight the queue for the disconnect-detection slot.

On AbortSignal fire: rejects the local promise *and* sends the shared cancel notification (cancel_action_spec.method) so the server-side dispatcher can abort the matching handler's ctx.signal. Suppressed for queued-but-never-sent (server doesn't know about it) and response-beat-cancel races.

type <R = unknown>(method: string, params?: unknown, options?: { signal?: AbortSignal | undefined; queue?: boolean | undefined; id?: string | number | undefined; }): Promise<R>

method
type string
params
type unknown
default {}
options
type { signal?: AbortSignal | undefined; queue?: boolean | undefined; id?: string | number | undefined; }
default {}
returns Promise<R>
throws
  • ThrownJsonrpcError - on the returned promise โ€” never thrown

add_message_handler

type (handler: SocketMessageHandler): () => void

handler
returns () => void

add_error_handler

type (handler: SocketErrorHandler): () => void

handler
returns () => void

FrontendWebsocketClientOptions
#

actions/socket.svelte.ts view source

FrontendWebsocketClientOptions

reconnect

Auto-reconnect policy. false disables reconnect entirely; true or omit for default timing; pass an object to customize.

type boolean | FrontendWebsocketReconnectOptions | null

heartbeat

Activity-aware heartbeat. true/null/omit for defaults; false disables the timer entirely (only do this if the server side is also running without heartbeat); pass an object to tune interval / receive_timeout.

type boolean | FrontendWebsocketHeartbeatOptions | null

queue

Durable queue for FrontendWebsocketClient.request. true or omit for defaults; false disables buffering (requests while disconnected reject immediately). Raw FrontendWebsocketClient.send is never queued โ€” use request() for RPC semantics.

type boolean | FrontendWebsocketQueueOptions

log

Optional logger for diagnostic messages.

type Logger | null

FrontendWebsocketHeartbeatOptions
#

actions/socket.svelte.ts view source

FrontendWebsocketHeartbeatOptions

interval

Idle duration (ms) after which a heartbeat is sent. Reset by any send or receive โ€” chatty clients never emit extras. Defaults to DEFAULT_HEARTBEAT_INTERVAL.

type number

receive_timeout

Receive-silence (ms) after which the client closes the socket with WS_CLOSE_CLIENT_HEARTBEAT_TIMEOUT, letting auto-reconnect kick in. Should be a comfortable multiple of interval. Defaults to DEFAULT_HEARTBEAT_RECEIVE_TIMEOUT.

type number

FrontendWebsocketQueueOptions
#

FrontendWebsocketReconnectOptions
#

actions/socket.svelte.ts view source

FrontendWebsocketReconnectOptions

delay

Base reconnect delay in ms. Defaults to 1000.

type number

delay_max

Max reconnect delay in ms (cap on exponential backoff). Defaults to 10000.

type number

factor

Exponential backoff factor. Defaults to 1.5.

type number

FrontendWebsocketTransport
#

actions/transports_ws.ts view source

Thin adapter over WebsocketRpcConnection (canonical implementation: FrontendWebsocketClient). Routes inbound server-pushed requests and notifications into the supplied receive callback; responses are owned by the connection's own request() pending map and are ignored here.

inheritance

implements:

transport_name

readonly

constructor

type new (connection: WebsocketRpcConnection, receive: (data: unknown) => Promise<unknown>): FrontendWebsocketTransport

connection
receive
type (data: unknown) => Promise<unknown>

send

type (message: { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }, options?: TransportSendOptions | undefined): Promise<...>

message
type { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }
options?
type TransportSendOptions | undefined
optional
returns Promise<{ [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; } | { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<...>); message: string; data?: unknown; }; }>

send

type (message: { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }, options?: TransportSendOptions | undefined): Promise<...>

message
type { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }
options?
type TransportSendOptions | undefined
optional
returns Promise<{ [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; } | { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<...>); message: string; data?: unknown; }; }>

send

type (message: { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }, options?: TransportSendOptions | undefined): Promise<...>

message
type { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }
options?
type TransportSendOptions | undefined
optional
returns Promise<{ [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; } | { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<...>); message: string; data?: unknown; }; }>

is_ready

type (): boolean

returns boolean

dispose

Detach the inbound message and error handlers registered on the connection. Idempotent โ€” subsequent calls no-op. Does not close the underlying connection (that lifecycle is owned by the caller).

type (): void

returns void

FsReadDeps
#

runtime/deps.ts view source

FsReadDeps

File system read operations.

stat

Get file/directory stats, or null if path doesn't exist.

type (path: string) => Promise<StatResult | null>

read_text_file

Read a file as text. Throws if the file does not exist.

type (path: string) => Promise<string>

read_file

Read a file as bytes. Throws if the file does not exist.

type (path: string) => Promise<Uint8Array>

read_text_from_offset

Read text starting from a byte offset. Throws if the file does not exist.

Returns content, bytes_read, and file_size so callers can detect truncation (when file_size < offset) and tail incrementally without re-reading the whole file.

type (path: string, offset: number) => Promise<ReadTextFromOffsetResult>

readdir

List directory entries (names, not full paths). Throws if the directory does not exist.

type (path: string) => Promise<Array<string>>

FsRemoveDeps
#

runtime/deps.ts view source

FsRemoveDeps

File system remove operations.

remove

Remove a file or directory.

type (path: string, options?: {recursive?: boolean}) => Promise<void>

FsWriteDeps
#

runtime/deps.ts view source

FsWriteDeps

File system write operations.

mkdir

Create a directory.

type (path: string, options?: {recursive?: boolean}) => Promise<void>

write_text_file

Write text to a file.

type (path: string, content: string) => Promise<void>

write_file

Write bytes to a file.

type (path: string, data: Uint8Array) => Promise<void>

rename

Rename (move) a file.

type (old_path: string, new_path: string) => Promise<void>

fuz_app_stock_route_tightness_allowlist
#

testing/surface_invariants.ts view source

readonly string[]

Routes shipped by fuz_app whose error schemas require a tightness exemption.

Currently empty โ€” every fuz_app-shipped route (account login/password/ bootstrap/signup, db health/tables/:name/tables/:name/rows/:id) was tightened in place to z.enum([...]) / z.literal(...) against every emit-site error code.

Kept as a forward-compatibility hook: when new stock routes ship with heterogeneous error surfaces that need an interim generic schema, add them here instead of forcing every consumer to hand-maintain the entry.

Paths assume the standard /api/account + /api/db prefixes used by every fuz_app consumer. Merged into default_error_schema_tightness.allowlist so consumers calling assert_error_schema_tightness directly inherit the exemptions; the standard attack-surface suite also prepends these entries underneath any consumer-supplied allowlist so project-specific entries are additive.

fuz_auth_guard_resolver
#

auth/auth_guard_resolver.ts view source

(auth: { account: "none" | "optional" | "required"; actor: "none" | "optional" | "required"; roles?: readonly string[] | undefined; credential_types?: readonly string[] | undefined; }): AuthGuards

Standard auth guard resolver for fuz_app.

Reads each axis of the four-axis RouteAuth shape and emits the corresponding middleware:

- account === 'required' or actor === 'required' โ†’ pre-validation require_auth - roles?.length โ†’ post-authorization require_role(roles) (multi-role any-of) - credential_types?.length โ†’ post-authorization require_credential_types(types)

Multiple post-authorization guards run in declaration order: credential type check first (since failing it implies the request can never resolve a usable identity), role check second.

auth

type { account: "none" | "optional" | "required"; actor: "none" | "optional" | "required"; roles?: readonly string[] | undefined; credential_types?: readonly string[] | undefined; }

returns

AuthGuards

fuz_session_config
#

FuzAuthActionSpecRegistry
#

auth/all_action_spec_registries.ts view source

FuzAuthActionSpecRegistry

One named entry in the registry-of-registries.

name

Stable identifier matching the source bundle name ('admin', 'role_grant_offer', etc.).

type string

specs

The bundle's spec array โ€” kept readonly here even when the source declares it mutable.

type ReadonlyArray<RequestResponseActionSpec>

generate_action_event_datas
#

actions/action_codegen.ts view source

(specs: readonly ({ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; })[], imports: ImportBuilder, options?: { ...; } | undefined): string

Emit the ActionEventDatas interface โ€” one ActionEvent*Data variant per method, parameterized by the spec's kind: - request_response โ†’ ActionEventRequestResponseData<method, input, output> - remote_notification โ†’ ActionEventRemoteNotificationData<method, input> - local_call โ†’ ActionEventLocalCallData<method, input, output>

Adds the per-kind data type imports (only the kinds that appear in specs).

specs

type readonly ({ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } ...

imports

options?

type { same_file?: boolean | undefined; collections_path?: string | undefined; include_protocol_actions?: boolean | undefined; } | undefined
optional

returns

string

generate_action_inputs_outputs
#

actions/action_codegen.ts view source

(specs: readonly ({ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; })[], imports: ImportBuilder, options?: { ...; } | undefined): string

Emit ActionInputs + ActionOutputs runtime consts and matching interfaces. The runtime consts reference specs.{method}_action_spec.input / .output; the interfaces use z.infer.

Adds import {z} from 'zod'; and the * as specs namespace import.

specs

type readonly ({ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } ...

imports

options?

type { specs_module?: string | undefined; qualify_spec?: ((spec: { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 7 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }) => string)...
optional

returns

string

generate_action_method_enum_block
#

actions/action_codegen.ts view source

(specs: readonly ({ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; })[], imports: ImportBuilder, options: { ...; }): string

Emit a single named z.enum([...]) + z.infer block for an arbitrary spec subset. Lower-level escape hatch from generate_action_method_enums โ€” for cross-product or domain-specific enums the built-in discriminator doesn't cover.

Mirrors the built-in helper's contract: protocol actions filtered by default, empty subsets return '' (skip rather than emit z.enum([])), zod import registered idempotently only when at least one method qualifies.

The cross-product space is open-ended; rather than grow the ActionMethodEnumKind discriminator one cross-product at a time, callers own the subset shape โ€” name, jsdoc, predicate.

specs

type readonly ({ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } ...

imports

options

type { name: string; jsdoc: string; predicate: (spec: { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 7 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }) => boolean; include_p...

returns

string

generate_action_method_enums
#

actions/action_codegen.ts view source

(specs: readonly ({ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; })[], imports: ImportBuilder, options?: { ...; } | undefined): string

Emit one or more z.enum([...]) declarations for action method names โ€” ActionMethod, RequestResponseActionMethod, RemoteNotificationActionMethod, LocalCallActionMethod, FrontendActionMethod, BackendActionMethod, FrontendRequestResponseMethod, BackendRequestResponseMethod, BroadcastActionMethod. Pairs each runtime const with a z.infer type alias under the same identifier.

Protocol-action methods (heartbeat, cancel) are filtered out by default โ€” pass include_protocol_actions: true if a consumer genuinely wants them on their typed surface. Empty kinds are skipped so the helper never emits z.enum([]) (zod runtime-throws on that).

Adds import {z} from 'zod'; to imports only when at least one block is emitted (idempotent).

For genuinely cross-product enums the discriminator doesn't cover, use generate_action_method_enum_block โ€” caller owns the predicate, name, and jsdoc.

specs

type readonly ({ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } ...

imports

options?

type { emit?: ReadonlySet<ActionMethodEnumKind> | undefined; include_protocol_actions?: boolean | undefined; } | undefined
optional

returns

string

generate_action_specs_record
#

actions/action_codegen.ts view source

(specs: readonly ({ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; })[], imports: ImportBuilder, options?: { ...; } | undefined): string

Emit the ActionSpecs runtime const + interface + the `action_specs: Array<ActionSpecUnion> value bundling every spec. Adds the * as specs` namespace import + the ActionSpecUnion type import.

specs

type readonly ({ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } ...

imports

options?

type { specs_module?: string | undefined; qualify_spec?: ((spec: { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 7 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }) => string)...
optional

returns

string

generate_actions_api_method_signature
#

actions/action_codegen.ts view source

(spec: { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }, imports: ImportBuilder, options?: { ...; } | undefined): string

Generates one method line of the typed FrontendActionsApi interface for a single spec. Encapsulates the input/options/return-type signature shape so the surface evolves in one place when fields like signal or transport_name are added to per-call options.

Async methods (request_response, remote_notification, async local_call) get an optional second options?: RpcClientCallOptions arg ({signal?, transport_name?, queue?}) and a Promise<Result<...>> return type. Sync local_call methods omit the options arg โ€” signal can't cooperatively interrupt a synchronous handler and there's no transport to select. remote_notification is async because create_remote_notification_method returns a Promise that resolves to a Result<{value: void}> (success) or Result<{error}> (transport send failure). Earlier emit shapes declared notifications as => void โ€” regenerate consumer typed clients to pick up the corrected return.

Registers exactly the imports the emitted line references on imports: ActionInputs (when the spec has input), ActionOutputs (always), RpcClientCallOptions (async only), and Result + JsonrpcErrorObject (any return shape that wraps the value in Result<{value}, {error}> โ€” every async method, plus sync local_call when `sync_returns_value: false). Mirrors the leaf-level pattern get_handler_return_type` already follows so wrappers no longer pre-register imports a per-spec emit might not actually use.

Optional-input detection. The emitted parameter is input?: (caller may omit the argument) when either (a) the schema accepts undefined โ€” z.optional(z.strictObject(...)) and similar wrappers โ€” or (b) the schema accepts the empty object {} โ€” `z.strictObject({acting: ActingActor})` and other all-optional-fields strict objects. The second probe mirrors the dispatcher's HTTP convention (raw_params ?? {} for non-z.void() schemas in actions/action_rpc.ts / http/route_spec.ts): if a request with no params reaches the handler, this is the value the schema is asked to validate. A schema with required fields fails both probes and stays input: (required at the typed surface). Refinements and transforms run as part of safeParse, so their accept/reject decisions feed into the optional/required choice naturally.

spec

type { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }

imports

options?

type { sync_returns_value?: boolean | undefined; collections_path?: string | undefined; } | undefined
optional

returns

string

one line like foo: (input: ActionInputs['foo'], options?: RpcClientCallOptions) => Promise<Result<...>>;

generate_api_token
#

auth/api_token.ts view source

(): { token: string; id: string; token_hash: string; }

Generate a new API token with its hash and public id.

The raw token is returned exactly once โ€” callers must present it to the user immediately.

returns

{ token: string; id: string; token_hash: string; }

the raw token, a public id, and the blake3 hash for storage

generate_app_surface
#

generate_backend_action_handlers_map
#

actions/action_codegen.ts view source

(imports: ImportBuilder, options?: { type_name?: string | undefined; method_enum_name?: string | undefined; context_type?: string | undefined; collections_path?: string | undefined; metatypes_path?: string | undefined; } | undefined): string

Emit the BackendActionHandlers mapped type โ€” one entry per BackendRequestResponseMethod, each (input, ctx) => output | Promise<output>. Replaces the hand-maintained Exclude<> + parallel mapped-type pattern (zzz had this at zzz/src/lib/server/zzz_action_handlers.ts:42-66).

The context type is consumer-defined (e.g. zzz's ZzzHandlerContext). Pass context_type to name it; the helper assumes it's importable or defined in the emitted module's scope (consumer's responsibility).

Adds ActionInputs / ActionOutputs type imports from collections_path and the BackendRequestResponseMethod import from metatypes_path.

imports

options?

type { type_name?: string | undefined; method_enum_name?: string | undefined; context_type?: string | undefined; collections_path?: string | undefined; metatypes_path?: string | undefined; } | undefined
optional

returns

string

generate_backend_actions_api
#

actions/action_codegen.ts view source

(specs: readonly ({ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; })[], imports: ImportBuilder, options?: { ...; } | undefined): string

Emit BOTH the typed BackendActionsApi interface AND the broadcast_action_specs runtime array. The interface is shaped for create_broadcast_api: backend-initiated remote_notification methods, each (input) => Promise<void>. The array bundles the matching specs as a ReadonlyArray<ActionSpecUnion>.

Filter: kind === 'remote_notification' && initiator !== 'frontend', additionally excluding methods that are the target of another spec's streams field. Streams targets (e.g. completion_progress, ollama_progress) are request-scoped notifications invoked via ctx.notify inside their parent handler โ€” they're never callable through the broadcast API. The discriminator is ActionSpec.streams, not a manual exclusion list.

Adds the * as specs namespace import (from specs_module), the ActionInputs type import (from collections_path), and the ActionSpecUnion type import.

Method signature shape today is (input) => Promise<void> โ€” matches the fire-and-forget runtime of create_broadcast_api. Generalizing per-kind via generate_actions_api_method_signature is deferred until a second backend runtime constructor lands.

specs

type readonly ({ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } ...

imports

options?

type { specs_module?: string | undefined; collections_path?: string | undefined; qualify_spec?: ((spec: { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; ... 8 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }) => string) | undefined; include_protocol_a...
optional

returns

string

generate_daemon_token
#

generate_frontend_action_handlers
#

actions/action_codegen.ts view source

(specs: readonly ({ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; })[], imports: ImportBuilder, options?: { ...; } | undefined): string

Emit the FrontendActionHandlers interface โ€” wraps generate_phase_handlers with the TypedActionEvent action-event type and standard 1-tab per-method indentation. Pairs with generate_typed_action_event_alias (emits the matching TypedActionEvent alias) โ€” call both in the same gen producer.

specs

type readonly ({ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } ...

imports

options?

type { collections_path?: string | undefined; include_protocol_actions?: boolean | undefined; } | undefined
optional

returns

string

generate_frontend_actions_api
#

actions/action_codegen.ts view source

(specs: readonly ({ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; })[], imports: ImportBuilder, options?: { ...; } | undefined): string

Emit the FrontendActionsApi interface โ€” one method signature per spec via generate_actions_api_method_signature. Optionally filter the spec set (e.g. omit additional methods alongside the default protocol-action filter) via method_filter.

Imports are registered by the leaf generate_actions_api_method_signature per emitted line โ€” only what the spec set actually references shows up on imports. A spec set with no async methods skips RpcClientCallOptions; one with no inputs skips ActionInputs; sync local_call methods with sync_returns_value: true (the default) skip Result / JsonrpcErrorObject.

The interface name is fixed at FrontendActionsApi โ€” the symmetric counterpart of BackendActionsApi. Earlier consumer-named variants (MyActionsApi, VisionesActionsApi) were retired in API review III to make the side-of-the-wire intent visible at every call site. If a consumer needs a different name they hand-roll the interface (the helper's job is the standard symmetric shape).

specs

type readonly ({ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } ...

imports

options?

type { method_filter?: ((spec: { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 7 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }) => boolean) | undefined; collections_path?: ...
optional

returns

string

generate_input_test_cases
#

testing/adversarial_input.ts view source

(input_schema: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>): InputTestCase[]

Generate adversarial test cases for a route's input schema.

Produces focused, non-redundant cases: - Whole-body: send array instead of object, extra unknown key - Missing required fields (without defaults) - One wrong-type value per field - Null for required non-nullable fields - One format violation per constrained field

input_schema

type ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>

returns

InputTestCase[]

throws

  • Error - if the seed body built by `generate_valid_value` fails

generate_params_test_cases
#

testing/adversarial_input.ts view source

(params_schema: ZodObject<$ZodLooseShape, $strip>): ParamsTestCase[]

Generate adversarial test cases for a route's params schema.

Params are always strings from URL segments. Only generates cases for format-constrained fields (uuid, pattern) since unconstrained string params accept any string value.

params_schema

type ZodObject<$ZodLooseShape, $strip>

returns

ParamsTestCase[]

generate_phase_handlers
#

actions/action_codegen.ts view source

(spec: { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }, executor: "frontend" | "backend", imports: ImportBuilder, options?: { ...; } | undefined): string

Generates the phase handlers for an action spec using the unified ActionEvent type with the new phase/step type parameters.

Returns '' when the spec contributes no phases on the given executor side (e.g. a backend-only local_call asked for 'frontend'). Upstream wrappers compose blocks with .filter(Boolean) so empty entries are dropped from the generated handler map. The earlier shape was ${method}?: never, which read as "calling this here is a type error" but in practice produced useless rows on FrontendActionHandlers for methods that don't belong on this side at all โ€” drop the row instead so the typed surface only carries methods the executor actually handles.

spec

type { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }

executor

type "frontend" | "backend"

imports

options?

type { action_event_type?: string | undefined; collections_path?: string | undefined; } | undefined
optional

returns

string

generate_position_styles
#

ui/position_helpers.ts view source

(position?: Position, align?: Alignment, offset?: string): Record<string, string>

Generates CSS positioning styles for UI elements.

position

default 'center'

align

default 'center'

offset

distance from the position (CSS value)

type string
default '0'

returns

Record<string, string>

throws

  • UnreachableError - if `position` is not a known `Position` value

generate_query_test_cases
#

testing/adversarial_input.ts view source

(query_schema: ZodObject<$ZodLooseShape, $strip>): QueryTestCase[]

Generate adversarial test cases for a route's query schema.

Query params are always strings from the URL. Generates cases for: - Missing required fields - Format violations on constrained fields (uuid, pattern)

query_schema

type ZodObject<$ZodLooseShape, $strip>

returns

QueryTestCase[]

generate_random_base64url
#

crypto.ts view source

(byte_length?: number): string

Generate a cryptographically random base64url string.

byte_length

number of random bytes (default 32 = 256 bits)

type number
default 32

returns

string

base64url-encoded string without padding

generate_random_key
#

dev/setup.ts view source

(deps: CommandDeps): Promise<string>

Generate a random base64 key using openssl.

deps

command execution capability

returns

Promise<string>

a random 32-byte base64-encoded key

throws

  • Error - if `openssl rand` fails or is unavailable

generate_session_token
#

generate_typed_action_event_alias
#

actions/action_codegen.ts view source

(imports: ImportBuilder, options?: { collections_path?: string | undefined; metatypes_path?: string | undefined; } | undefined): string

Emit the fixed-shape TypedActionEvent alias used by FrontendActionHandlers to narrow ActionEvent.data against the consumer's generated ActionEventDatas map. Registers the four fuz_app type imports it needs (ActionEvent, ActionEventPhase, ActionEventStep, ActionEventDatas) plus the ActionMethod type import โ€” sourced from collections_path and metatypes_path respectively.

Pair with generate_action_method_enums (emits ActionMethod into metatypes_path) and generate_action_event_datas (emits ActionEventDatas into collections_path).

imports

options?

type { collections_path?: string | undefined; metatypes_path?: string | undefined; } | undefined
optional

returns

string

generate_valid_body
#

testing/schema_generators.ts view source

(input_schema: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>): Record<string, unknown> | undefined

Generate a valid request body for a route's input schema.

input_schema

type ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>

returns

Record<string, unknown> | undefined

a generated body that passes safeParse, or undefined for null / non-object schemas

throws

  • Error - if the generated body fails `input_schema.safeParse` โ€” catches

generate_valid_value
#

testing/schema_generators.ts view source

(field: ZodFieldInfo, field_schema: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>): unknown

Generate a valid-ish value for a field based on its base type.

field

type ZodFieldInfo

field_schema

type ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>

returns

unknown

GenerateAppSurfaceOptions
#

http/surface.ts view source

GenerateAppSurfaceOptions

route_specs

type Array<RouteSpec>

middleware_specs

type Array<MiddlewareSpec>

env_schema

type z.ZodObject

event_specs

type Array<EventSpec>

rpc_endpoints

type Array<RpcEndpointSpec>

ws_endpoints

Mounted WS endpoints (the same array create_app_server.ws_endpoints auto-mounts). Each entry's actions surface into AppSurface.ws_endpoints[i].methods for attack-surface tests + startup logging.

type ReadonlyArray<WsEndpointSpec>

get_app_dir
#

cli/config.ts view source

(runtime: Pick<EnvDeps, "env_get">, name: string): string | null

Get the CLI config directory path (~/.{name}).

runtime

runtime with env_get capability

type Pick<EnvDeps, "env_get">

name

application name (e.g., "tx", "zzz")

type string

returns

string | null

path to config directory, or null if $HOME is not set

get_audit_metadata
#

auth/audit_log_schema.ts view source

<T extends AuditEventType>(event: AuditLogEvent & { event_type: T; }): AuditMetadataMap[T] | null

Narrow metadata type for a known event type.

Use after checking event_type to get typed metadata access.

event

type AuditLogEvent & { event_type: T; }

returns

AuditMetadataMap[T] | null

get_audit_metadata_validation_failures
#

get_audit_unknown_event_type_failures
#

get_client_ip
#

http/proxy.ts view source

(c: Context<any, any, {}>): string

Read the resolved client IP from the Hono context.

Returns 'unknown' if the proxy middleware has not run or no IP is available. Set by create_proxy_middleware.

c

type Context<any, any, {}>

returns

string

get_config_path
#

cli/config.ts view source

(runtime: Pick<EnvDeps, "env_get">, name: string): string | null

Get the CLI config file path (~/.{name}/config.json).

runtime

runtime with env_get capability

type Pick<EnvDeps, "env_get">

name

application name

type string

returns

string | null

path to config.json, or null if $HOME is not set

get_daemon_info_path
#

cli/daemon.ts view source

(runtime: Pick<EnvDeps, "env_get">, name: string): string | null

Get the daemon info file path (~/.{name}/run/daemon.json).

runtime

runtime with env_get capability

type Pick<EnvDeps, "env_get">

name

application name

type string

returns

string | null

path to daemon.json, or null if $HOME is not set

get_daemon_token_path
#

auth/daemon_token_middleware.ts view source

(runtime: Pick<EnvDeps, "env_get">, name: string): string | null

Get the daemon token file path (~/.{name}/run/daemon_token).

runtime

runtime with env_get capability

type Pick<EnvDeps, "env_get">

name

application name

type string

returns

string | null

path to daemon_token, or null if $HOME is not set

get_env_var_names
#

env/resolve.ts view source

(value: string): string[]

Get list of env var names referenced in a string.

Escaped references are skipped; optional and required references are both included (callers that care about the distinction should use scan_env_vars which preserves the optional flag per ref).

value

string to scan

type string

returns

string[]

array of variable names (without $$ delimiters)

get_executor_phases
#

actions/action_codegen.ts view source

(spec: { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }, executor: "frontend" | "backend"): ("send_request" | ... 7 more ... | "execute")[]

Phases an executor can handle for the given spec โ€” kind + initiator โ†’ set of phases.

spec

type { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }

executor

type "frontend" | "backend"

returns

("send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute")[]

get_handler_return_type
#

actions/action_codegen.ts view source

(spec: { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }, phase: "send_request" | ... 7 more ... | "execute", imports: ImportBuilder, collections_path?: string): string

Gets the handler return type for a specific phase and spec. Adds an ActionOutputs import (from collections_path) when the phase carries an output (request_response receive_request, local_call execute).

spec

type { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }

phase

type "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"

imports

collections_path

type string
default DEFAULT_COLLECTIONS_PATH

returns

string

get_initial_phase
#

actions/action_event_helpers.ts view source

(kind: "request_response" | "remote_notification" | "local_call", initiator: "frontend" | "backend" | "both", executor: "frontend" | "backend"): "send_request" | "receive_request" | ... 7 more ... | null

kind

type "request_response" | "remote_notification" | "local_call"

initiator

type "frontend" | "backend" | "both"

executor

type "frontend" | "backend"

returns

"send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute" | null

get_request_context
#

auth/request_context.ts view source

(c: Context<any, any, {}>): RequestContext | null

Get the request context from a Hono context, or null if unauthenticated.

c

the Hono context

type Context<any, any, {}>

returns

RequestContext | null

the request context, or null

get_route_error_schema
#

testing/assertions.ts view source

(lookup: Map<string, Partial<Record<number, ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>>>>, route: AppSurfaceRoute, status: number): ZodType<...> | undefined

Look up the merged error schema for a route+status from a pre-built schema lookup.

lookup

map from "METHOD /path" to merged error schemas

type Map<string, Partial<Record<number, ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>>>>

route

the surface route to look up

status

HTTP status code

type number

returns

ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>> | undefined

the Zod schema for that route+status, or undefined when no error schema is declared for the status code

get_route_input
#

http/route_spec.ts view source

<S extends z.ZodType>(c: Context<any, any, {}>, schema: S): output<S>

Get validated input from the Hono context.

Call after the input validation middleware has run. Pass the route's input Zod schema to infer the typed shape directly:

const input = get_route_input(c, my_route_spec.input);

Or pass an explicit type argument when the schema isn't in scope:

const input = get_route_input<MyInput>(c);

c

type Context<any, any, {}>

schema

type S

returns

output<S>

generics

S

constraint z.ZodType

get_route_params
#

http/route_spec.ts view source

<S extends z.ZodType>(c: Context<any, any, {}>, schema: S): output<S>

Get validated URL path params from the Hono context.

Call after the params validation middleware has run. Pass the route's params schema to infer the typed shape, or supply an explicit type argument. See get_route_input for the two call shapes.

c

type Context<any, any, {}>

schema

type S

returns

output<S>

generics

S

constraint z.ZodType

get_route_query
#

http/route_spec.ts view source

<S extends z.ZodType>(c: Context<any, any, {}>, schema: S): output<S>

Get validated URL query params from the Hono context.

Call after the query validation middleware has run. Pass the route's query schema to infer the typed shape, or supply an explicit type argument. See get_route_input for the two call shapes.

c

type Context<any, any, {}>

schema

type S

returns

output<S>

generics

S

constraint z.ZodType

get_session_cookie
#

grant_key
#

ui/admin_accounts_state.svelte.ts view source

(account_id: string & $brand<"Uuid">, role: string, to_actor_id?: (string & $brand<"Uuid">) | null | undefined): string

Compose the grant keyed-slot key for an offer. Account-grain offers key on ${account_id}:${role}; actor-targeted offers add the actor suffix so the two variants can be in flight simultaneously without colliding on per-row spinners.

account_id

type string & $brand<"Uuid">

role

type string

to_actor_id?

type (string & $brand<"Uuid">) | null | undefined
optional

returns

string

GRANT_PATH_ADMIN
#

GRANT_PATH_BOOTSTRAP
#

GRANT_PATH_NAME_REGEX
#

GRANT_PATH_SELF_SERVICE
#

GRANT_PATH_SYSTEM
#

GrantPathMeta
#

auth/grant_path_schema.ts view source

GrantPathMeta

Per-grant-path metadata. description is admin-UI-facing copy (mirrors RoleSpec.description and ScopeKindMeta.description). Open shape so v2 can extend without a breaking change.

description

type string

GrantPathName
#

GrantPathSchemaResult
#

auth/grant_path_schema.ts view source

GrantPathSchemaResult

The result of create_grant_path_schema โ€” a Zod schema and metadata map.

GrantPath

Zod schema that validates grant-path name strings against the registered set (builtins + consumer-declared). Use at I/O boundaries (admin UIs, codegen) and as the construction-time check inside create_role_schema for every RoleSpec.grant_paths entry.

type z.ZodType<string>

grant_paths

Map of every registered grant-path to its metadata. Keyed by name. Read at startup by admin / codegen surfaces.

type ReadonlyMap<string, GrantPathMeta>

HandlerForSpec
#

actions/action_rpc.ts view source

HandlerForSpec<TSpec>

Conditional handler shape for rpc_action โ€” picks the narrowest ctx.auth type the dispatcher's runtime guarantee allows:

- auth.actor === 'required' โ†’ ActorActionHandler (ctx.auth: RequestActorContext). - auth.account === 'required' && auth.actor === 'none' โ†’ AuthActionHandler (ctx.auth: RequestContext). - else (public, optional axes) โ†’ ActionHandler (ctx.auth: RequestContext | null).

The bracketed form [T] extends ['required'] defeats distributive conditionals so a degraded AuthAxisState union (when the spec was typed without preserving its literal) falls through to the loosest tier instead of collapsing to the narrowest.

generics

TSpec

has_any_scoped_role
#

auth/request_context.ts view source

(ctx: RequestContext | null, roles: readonly string[], scope_id: string | null, now?: Date): boolean

Whether the request context holds an active role_grant for any role in roles at scope_id. Empty roles short-circuits to false โ€” documents intent at the call site ("zero roles trivially admit no-one"). Same scope and null-tolerance semantics as has_scoped_role.

ctx

the request context, or null for unauthenticated callers

type RequestContext | null

roles

the roles that would admit the caller (any-of)

type readonly string[]

scope_id

the scope to check (null for global)

type string | null

now

current time (defaults to new Date(), pass for testability)

type Date
default new Date()

returns

boolean

true iff the actor holds an active role_grant for any role in roles at the requested scope

has_env_vars
#

env/resolve.ts view source

(value: string): boolean

Check if a string contains unresolved env var references.

Escaped references (\$$VAR$$) do not count โ€” they're literal text once resolved.

value

string to check

type string

returns

boolean

true if string contains unescaped $$VAR$$ patterns

has_role
#

auth/request_context.ts view source

(ctx: RequestContext | null, role: string, now?: Date): boolean

Check if a request context has an active role_grant for a given role.

Checks the role_grants already loaded in the context (no DB query). Null-tolerant โ€” null ctx (unauthenticated) returns false. Symmetric with has_scoped_role / has_any_scoped_role so the three helpers compose freely in the same predicate (e.g. has_role(auth, ADMIN) || has_scoped_role(auth, role, scope)).

ctx

the request context, or null for unauthenticated callers

type RequestContext | null

role

the role to check

type string

now

current time (defaults to new Date(), pass for testability and hot-path efficiency)

type Date
default new Date()

returns

boolean

true if the actor has an active role_grant for the role

has_scoped_role
#

auth/request_context.ts view source

(ctx: RequestContext | null, role: string, scope_id: string | null, now?: Date): boolean

Whether the request context holds an active role_grant for role at scope_id.

Walks the in-memory ctx.role_grants snapshot loaded once per request by the route-spec / RPC dispatcher's authorization phase (when the route declares acting?: ActingActor or has role_grant-requiring auth); zero DB roundtrip per check. The "freshness" framing of a SQL re-query is illusory because the race window is between predicate and the actual mutation, not predicate and authorization load. Closing that race needs a transactional re-check inside the UPDATE/INSERT, which neither style provides.

Null-tolerant โ€” null ctx (unauthenticated) and account-grain contexts (actor: null, empty role_grants) both return false. Same convention as has_role; lets the helper drop into public ({account: 'none', actor: 'none'}) and account-grain ({account: 'required', actor: 'none'}) handlers without a manual narrow. See cell_authorize for the resource-side analog.

scope_id semantics: in-memory role_grant.scope_id is string | null, so JS === matches the SQL IS NOT DISTINCT FROM semantics exactly:

- scope_id === null matches global role_grants (scope_id IS NULL). - scope_id === '<uuid>' matches role_grants bound to that exact scope.

ctx

the request context, or null for unauthenticated callers

type RequestContext | null

role

the role to check

type string

scope_id

the scope to check (null for global)

type string | null

now

current time (defaults to new Date(), pass for testability and hot-path efficiency)

type Date
default new Date()

returns

boolean

true iff the actor holds an active role_grant for the role at the requested scope

hash_api_token
#

auth/api_token.ts view source

(token: string): string

Hash an API token for storage using blake3.

token

the raw API token

type string

returns

string

hex-encoded blake3 hash

hash_password
#

auth/password_argon2.ts view source

(password: string): Promise<string>

Hash a password using Argon2id.

password

the plaintext password to hash

type string

returns

Promise<string>

the Argon2id hash string

hash_session_token
#

auth/session_queries.ts view source

(token: string): string

Hash a session token to its storage key using blake3.

token

the raw session token

type string

returns

string

hex-encoded blake3 hash

heartbeat_action
#

actions/heartbeat.ts view source

Action<{ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | {...

Protocol-action tuple โ€” spread into the server's actions array for dispatch (or via protocol_actions from actions/protocol.ts) so the dispatcher resolves the heartbeat handler. The frontend-side spread happens via protocol_action_specs โ€” the client doesn't run the echo handler, but the spec must be in ActionRegistry so create_rpc_client types app.api.heartbeat() against the shared spec.

heartbeat_action_spec
#

actions/heartbeat.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "none"; }; side_effects: false; input: ZodDefault<ZodObject<{}, $strict>>; output: ZodObject<...>; async: true; description: string; }

ActionSpec for the shared heartbeat. Account-required, actor-none โ€” upgrade-time auth has already admitted the socket; heartbeats don't need role gating or actor resolution. side_effects: false keeps it orthogonal to state changes.

heartbeat_handler
#

actions/heartbeat.ts view source

(): Record<string, never>

Handler โ€” nullary echo. Stateless, suitable for high-frequency pings.

returns

Record<string, never>

HelpCategory
#

cli/help.ts view source

HelpCategory<TCategory>

Category configuration for help display.

generics

TCategory

constraint string
default string

key

type TCategory

title

type string

HelpGenerator
#

cli/help.ts view source

HelpGenerator

Help generator returned by create_help.

generate_main_help

Generate main help text with all commands grouped by category.

type () => string

generate_command_help

Generate help text for a specific command.

type (command: string, meta: CommandMeta) => string

get_help_text

Get help text for a command or main help.

type (command?: string, subcommand?: string) => string

HelpOptions
#

cli/help.ts view source

HelpOptions<TCategory>

Configuration for create_help.

generics

TCategory

constraint string
default string

name

Application name (e.g., "tx", "zzz").

type string

version

Application version string.

type string

description

Short description for the main help header.

type string

commands

Command registry keyed by command path (e.g., "apply", "daemon start").

type Record<string, CommandMeta<TCategory>>

categories

Category display order for main help.

type Array<HelpCategory<TCategory>>

examples

Example commands for main help.

type Array<string>

global_args_schema

Zod schema for global arguments (shown in all help output).

type z.ZodType

use_colors

Whether to use ANSI colors in output. Defaults to true.

type boolean

http_status_to_jsonrpc_error_code
#

http/jsonrpc_errors.ts view source

(status: number): -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<"JsonrpcServerErrorCode">)

Map an HTTP status code to a JSON-RPC error code.

Returns internal_error (-32603) for unrecognized status codes.

status

type number

returns

-32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<"JsonrpcServerErrorCode">)

HTTP_STATUS_TO_JSONRPC_ERROR_CODE
#

http/jsonrpc_errors.ts view source

Record<number, -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<"JsonrpcServerErrorCode">)>

Maps HTTP status codes to JSON-RPC error codes (reverse mapping).

When multiple error codes map to the same HTTP status (e.g. parse_error and invalid_request both map to 400), the last one wins. Use for best-effort HTTP โ†’ JSON-RPC translation.

http_transport
#

testing/rpc_helpers.ts view source

(app: { request: (input: string, init: RequestInit) => Response | Promise<Response>; }): RpcTestTransport

Adapt a Hono-style app into an RpcTestTransport.

app

type { request: (input: string, init: RequestInit) => Response | Promise<Response>; }

returns

RpcTestTransport

ImportBuilder
#

actions/action_codegen.ts view source

Manages imports for generated code, building them on demand. Automatically optimizes type-only imports to use import type syntax.

Why this matters: - import type statements are completely removed during compilation - Mixed imports like import { type A, B } cannot be safely removed - This ensures optimal tree-shaking and smaller bundle sizes

examples

const imports = new ImportBuilder(); imports.add_types('./types.js', 'Foo', 'Bar'); imports.add('./utils.js', 'helper'); imports.add_type('./utils.js', 'HelperOptions'); imports.add('./action_specs.js', '* as specs'); // Generates: // import type {Foo, Bar} from './types.js'; // import {helper, type HelperOptions} from './utils.js'; // import * as specs from './action_specs.js';

imports

type Map<string, Map<string, ImportItem>>

add

Add a value import. Accepts * as ns strings as namespace imports.

type (from: string, what: string): this

from
type string
what
type string
returns this

this for chaining

add_type

Add a type-only import.

type (from: string, what: string): this

from
type string
what
type string
returns this

this for chaining

add_many

type (from: string, ...items: string[]): this

from
type string
items
type string[]
returns this

add_types

type (from: string, ...items: string[]): this

from
type string
items
type string[]
returns this

build

Generate the import statements. When every import from a module is a type, emits import type {โ€ฆ} so the whole statement disappears at compile time.

type (): string

returns string

has_imports

type (): boolean

returns boolean

preview

Build the same statement list as build without joining โ€” for inspection in tests.

type (): string[]

returns string[]

clear

Clear all imports.

type (): this

returns this

this for chaining

in_process_capabilities
#

testing/cross_backend/capabilities.ts view source

BackendCapabilities

Capability declarations for the in-process Hono transport. Every flag is true because in-process testing exercises the full backend with no missing optional behaviors. Cross-process consumers declare each flag explicitly per backend.

InProcessSetupOptions
#

testing/cross_backend/setup.ts view source

InProcessSetupOptions

Options for default_in_process_setup. Extends CreateTestAppOptions with the same extra_accounts slot the cross-process variant accepts โ€” both transports observe the same bootstrap-time secondary set so suite bodies can read fixture.extra_accounts[username] uniformly.

inheritance

extra_accounts

Additional accounts seeded at this transport's bootstrap-equivalent step. See ExtraAccountSpec for the cradle-only-bypass rationale. Most suites pass undefined / []; the ROLE_KEEPER probe (in describe_standard_admin_integration_tests) is the primary user.

type ReadonlyArray<ExtraAccountSpec>
readonly

input_schema_declares_acting
#

http/auth_shape.ts view source

(schema: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>): boolean

Whether a schema declares the canonical acting?: ActingActor field. Reference-equality on the exported ActingActor schema โ€” consumer schemas with unrelated acting fields don't trip this check.

Peels through Zod wrappers (optional, nullable, default, transform, pipe, prefault) via zod_unwrap_to_object so a spec authored as z.optional(z.strictObject({acting: ActingActor})) or z.strictObject({acting: ActingActor}).default({}) still trips the predicate.

schema

type ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>

returns

boolean

install_audit_drift_guard
#

testing/audit_drift_guard.ts view source

(): void

Register per-test beforeEach + afterEach hooks that catch any audit emission with a metadata shape that fails its audit_metadata_schemas entry, or an event_type not present in the active AuditLogConfig.

The production validation in query_audit_log is fail-open โ€” it bumps process-wide counters and proceeds, so a regression that emits an undeclared metadata field or a typo'd event-type lands a row that passes downstream queries but breaks forensics. Tests that exercise audit emits should fail loudly when this happens.

Call at the top of every describe / describe_db block that fires audit writes through deps.audit.emit. Resets counters before each test and asserts zero on completion.

Pair with await_pending_effects: true (the default for create_test_app) so fire-and-forget audit writes have completed by the time the after-each check observes counter state.

returns

void

Invite
#

auth/invite_schema.ts view source

Invite

Invite row from the database.

id

type Uuid

email

type Email | null

username

type Username | null

claimed_by

type Uuid | null

claimed_at

type string | null

created_at

type string

created_by

type Uuid | null

invite_create_action_spec
#

auth/admin_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "required"; roles: string[]; }; side_effects: true; input: ZodObject<{ email: ZodOptional<ZodNullable<ZodEmail>>; username: ZodOptional<...>; acting: ZodOptional<...>; }, $strict>; output: ZodObject<...>; async: tr...

invite_delete_action_spec
#

auth/admin_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "required"; roles: string[]; }; side_effects: true; input: ZodObject<{ invite_id: $ZodBranded<ZodUUID, "Uuid", "out">; acting: ZodOptional<...>; }, $strict>; output: ZodObject<...>; async: true; description: string...

INVITE_INDEXES
#

invite_list_action_spec
#

auth/admin_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "required"; roles: string[]; }; side_effects: false; input: ZodDefault<ZodObject<{ acting: ZodOptional<$ZodBranded<ZodUUID, "Uuid", "out">>; }, $strict>>; output: ZodObject<...>; async: true; description: string; r...

rate_limit: 'account' bounds admin-side scraping of the invite table โ€” bounded by table size, but every row carries email + username + creator/claimer identifiers worth defense-in-depth against an admin mutation oracle running scripted reads alongside invite_create.

INVITE_SCHEMA
#

auth/auth_ddl.ts view source

"\nCREATE TABLE IF NOT EXISTS invite (\n id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n email TEXT,\n username TEXT,\n claimed_by UUID REFERENCES account(id) ON DELETE SET NULL,\n claimed_at TIMESTAMPTZ,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n created_by UUID REFERENCES actor(id) ON DELETE SET NU...

InviteCreateInput
#

auth/admin_action_specs.ts view source

ZodObject<{ email: ZodOptional<ZodNullable<ZodEmail>>; username: ZodOptional<ZodNullable<ZodPipe<ZodString, ZodTransform<string, string>>>>; acting: ZodOptional<...>; }, $strict>

Input for invite_create. At least one of email / username must be provided.

InviteCreateOutput
#

auth/admin_action_specs.ts view source

ZodObject<{ ok: ZodLiteral<true>; invite: ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; email: ZodNullable<ZodEmail>; username: ZodNullable<...>; claimed_by: ZodNullable<...>; claimed_at: ZodNullable<...>; created_at: ZodString; created_by: ZodNullable<...>; }, $strict>; }, $strict>

Output for invite_create.

InviteDeleteInput
#

auth/admin_action_specs.ts view source

ZodObject<{ invite_id: $ZodBranded<ZodUUID, "Uuid", "out">; acting: ZodOptional<$ZodBranded<ZodUUID, "Uuid", "out">>; }, $strict>

Input for invite_delete.

InviteDeleteOutput
#

InviteJson
#

auth/invite_schema.ts view source

ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; email: ZodNullable<ZodEmail>; username: ZodNullable<ZodPipe<ZodString, ZodTransform<string, string>>>; claimed_by: ZodNullable<...>; claimed_at: ZodNullable<...>; created_at: ZodString; created_by: ZodNullable<...>; }, $strict>

Zod schema for client-safe invite data.

InviteListInput
#

InviteListOutput
#

auth/admin_action_specs.ts view source

ZodObject<{ invites: ZodArray<ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; email: ZodNullable<ZodEmail>; username: ZodNullable<ZodPipe<ZodString, ZodTransform<string, string>>>; ... 5 more ...; claimed_by_username: ZodNullable<...>; }, $strict>>; }, $strict>

Output for invite_list. Uses the enriched row including creator/claimer usernames.

InviteWithUsernamesJson
#

auth/invite_schema.ts view source

ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; email: ZodNullable<ZodEmail>; username: ZodNullable<ZodPipe<ZodString, ZodTransform<string, string>>>; ... 5 more ...; claimed_by_username: ZodNullable<...>; }, $strict>

Zod schema for invite data with resolved creator/claimer usernames.

IP_LITERAL_CHARS
#

http/ip_canonical.ts view source

RegExp

Allowed character set for a bare IP literal.

Covers the union of IPv4 (digits + .), IPv6 (hex digits + :), and IPv4-mapped IPv6 forms (::ffff:127.0.0.1). Anything outside this set โ€” brackets, whitespace, control bytes, letters gโ€“z โ€” disqualifies the input from parsing.

Same regex proxy.ts's validate_ip_strict uses; exported here so both modules can share one source of truth.

ipv6_bigint_to_canonical
#

http/ip_canonical.ts view source

(bits: bigint): string

Convert a 128-bit IPv6 binary value into its RFC 5952 canonical string form.

- IPv4-mapped (groups[0..5] = 0, groups[5] = 0xffff) emits the ::ffff:a.b.c.d dotted form per RFC 5952 ยง5. - Otherwise: lowercase hex with no leading zeros per group (ยง4.1), the longest run of consecutive zero groups (โ‰ฅ 2 groups) is replaced with :: (ยง4.2.1, ยง4.2.3), and on equal-length runs the first one wins (ยง4.2.3). Single-zero groups stay as 0 (ยง4.2.2).

Pure helper exported for the test suite to exercise the canonicalization invariants directly without a full convertIPv6ToBinary round-trip.

bits

the 128-bit IPv6 value as bigint. Must satisfy 0n <= bits < 2n ** 128n; throws RangeError otherwise. Silent truncation would mask caller bugs since the bit-extraction loop only consumes the low 128 bits.

type bigint

returns

string

throws

  • when - `bits` is negative or exceeds 128 bits

is_action_complete
#

actions/action_event_helpers.ts view source

(data: { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }): boolean

data

type { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }

returns

boolean

is_action_spec
#

actions/action_spec.ts view source

(value: unknown): value is { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<...>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }

Structural type guard for any ActionSpecUnion variant โ€” checks kind is one of the three known values.

value

type unknown

returns

boolean

IS_CI
#

is_credential_gated_auth
#

http/auth_shape.ts view source

(auth: { account: "none" | "optional" | "required"; actor: "none" | "optional" | "required"; roles?: readonly string[] | undefined; credential_types?: readonly string[] | undefined; }): boolean

True iff the route declares any credential-type gate (auth.credential_types?.length).

auth

type { account: "none" | "optional" | "required"; actor: "none" | "optional" | "required"; roles?: readonly string[] | undefined; credential_types?: readonly string[] | undefined; }

returns

boolean

is_daemon_running
#

cli/daemon.ts view source

(runtime: CommandDeps, pid: number): Promise<boolean>

Check if a process is running by PID.

runtime

runtime with command execution capability

pid

process ID to check

type number

returns

Promise<boolean>

true if the process is running

is_execute
#

actions/action_event_helpers.ts view source

(data: { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }): data is ActionEventLocalCallData & { ...; }

data

type { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }

returns

boolean

is_failed
#

actions/action_event_helpers.ts view source

(data: { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }): data is { ...; } & { ...; }

data

type { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }

returns

boolean

is_filterable_broadcast_transport
#

is_handled
#

actions/action_event_helpers.ts view source

(data: { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }): data is { ...; } & { ...; }

data

type { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }

returns

boolean

is_handling
#

actions/action_event_helpers.ts view source

(data: { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }): data is { ...; } & { ...; }

data

type { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }

returns

boolean

is_initial
#

actions/action_event_helpers.ts view source

(data: { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }): data is { ...; } & { ...; }

data

type { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }

returns

boolean

is_jsonrpc_error_response
#

http/jsonrpc_helpers.ts view source

(message: unknown): message is { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<"JsonrpcServerErrorCode">); message: string; data?: unknown; }; }

Checks if a value is a JSON-RPC error response (has error + id).

message

type unknown

returns

boolean

is_jsonrpc_message
#

http/jsonrpc_helpers.ts view source

(message: unknown): message is { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; } | { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; } | { ...; } | { ...; } | ({ ...; } | ... 2 more ... | { ...; })[]

Checks if a value is any valid JSON-RPC message or batch array.

message

type unknown

returns

boolean

is_jsonrpc_notification
#

http/jsonrpc_helpers.ts view source

(message: unknown): message is { [x: string]: unknown; jsonrpc: "2.0"; method: string; params?: { [x: string]: unknown; } | undefined; }

Checks if a value is a JSON-RPC notification (has method, no id).

message

type unknown

returns

boolean

is_jsonrpc_object
#

http/jsonrpc_helpers.ts view source

(message: unknown): message is { jsonrpc: "2.0"; }

Checks if a value is a JSON-RPC object (has jsonrpc: '2.0').

message

type unknown

returns

boolean

is_jsonrpc_request
#

http/jsonrpc_helpers.ts view source

(message: unknown): message is { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; method: string; params?: { [x: string]: unknown; } | undefined; }

Checks if a value is a JSON-RPC request (has method + id).

message

type unknown

returns

boolean

is_jsonrpc_request_id
#

http/jsonrpc_helpers.ts view source

(id: unknown): id is string | number

Checks if a value is a valid JSON-RPC request id (string or finite number).

id

type unknown

returns

boolean

is_jsonrpc_response
#

http/jsonrpc_helpers.ts view source

(message: unknown): message is { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; }

Checks if a value is a JSON-RPC success response (has result + id).

message

type unknown

returns

boolean

is_keeper_auth
#

http/auth_shape.ts view source

(auth: { account: "none" | "optional" | "required"; actor: "none" | "optional" | "required"; roles?: readonly string[] | undefined; credential_types?: readonly string[] | undefined; }): boolean

True iff the route is the keeper bucket โ€” credential gate restricted to daemon_token. Keeper is the only credential gate today; if more land, this filter widens. Knows the 'daemon_token' literal directly (the keeper composition is fuz_app's only registered credential gate).

auth

type { account: "none" | "optional" | "required"; actor: "none" | "optional" | "required"; roles?: readonly string[] | undefined; credential_types?: readonly string[] | undefined; }

returns

boolean

is_local_call
#

actions/action_event_helpers.ts view source

(data: { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }): data is ActionEventLocalCallData

data

type { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }

returns

boolean

is_notification
#

testing/transports/ws_client.ts view source

(method: string): (msg: unknown) => boolean

Predicate matching a JSON-RPC notification with the given method name.

method

type string

returns

(msg: unknown) => boolean

is_notification_receive
#

actions/action_event_helpers.ts view source

(data: { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }): data is ({ ...; } & { ...; }) | ... 3 more ... | ({ ...; } & { ...; })

data

type { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }

returns

boolean

is_notification_send
#

actions/action_event_helpers.ts view source

(data: { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }): data is ({ ...; } & { ...; }) | ... 3 more ... | ({ ...; } & { ...; })

data

type { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }

returns

boolean

is_notification_send_with_parsed_input
#

actions/action_event_helpers.ts view source

<TMethod extends string = string>(data: { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }): data is ({ ...; } & { ...; }) | ({ ...; } & { ...; })

data

type { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }

returns

boolean

is_notification_with
#

testing/transports/ws_client.ts view source

<P>(method: string, match: (params: P) => boolean): (msg: unknown) => msg is JsonrpcNotificationFrame<P>

Type-guard combinator: match a notification whose typed params satisfies match. Collapses the common test pattern of casting msg to JsonrpcNotificationFrame<P> in every predicate body.

const match_roster_for = (id: Uuid) => is_notification_with<RosterChangedParams>( WORLD_METHODS.roster_changed, (params) => params.character_id === id && !params.removed, ); const roster = await client.wait_for(match_roster_for(char_id));

method

type string

match

type (params: P) => boolean

returns

(msg: unknown) => msg is JsonrpcNotificationFrame<P>

is_null_schema
#

http/schema_helpers.ts view source

(schema: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>): boolean

Check if a schema is exactly z.null().

Uses instanceof rather than runtime parsing to avoid false positives from z.nullable(z.string()) or similar schemas that accept null but also accept other values.

schema

type ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>

returns

boolean

is_parsed
#

actions/action_event_helpers.ts view source

(data: { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }): data is { ...; } & { ...; }

data

type { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }

returns

boolean

is_pg_unique_violation
#

db/pg_error.ts view source

(error: unknown): boolean

Check if an error is a PostgreSQL unique constraint violation (error code 23505).

error

the caught error

type unknown

returns

boolean

true if the error is a unique constraint violation

is_plain_authenticated_auth
#

http/auth_shape.ts view source

(auth: { account: "none" | "optional" | "required"; actor: "none" | "optional" | "required"; roles?: readonly string[] | undefined; credential_types?: readonly string[] | undefined; }): boolean

True iff the route is plain authenticated โ€” account === 'required' with no role gate and no credential gate. Account-grain authenticated routes (logout, password change, account self-service) fall here.

auth

type { account: "none" | "optional" | "required"; actor: "none" | "optional" | "required"; roles?: readonly string[] | undefined; credential_types?: readonly string[] | undefined; }

returns

boolean

is_protocol_action_method
#

actions/action_codegen.ts view source

(method: string): method is "heartbeat" | "cancel"

Type predicate for filtering protocol-action methods out of a typed FrontendActionsApi method_filter. Avoids the (... as never) cast required to call Array.prototype.includes on the readonly tuple at narrow string types.

method

type string

returns

boolean

examples

generate_frontend_actions_api(specs, imports, { method_filter: (s) => !is_protocol_action_method(s.method), });

is_public_auth
#

http/auth_shape.ts view source

(auth: { account: "none" | "optional" | "required"; actor: "none" | "optional" | "required"; roles?: readonly string[] | undefined; credential_types?: readonly string[] | undefined; }): boolean

True iff the route is fully public โ€” both account and actor axes are 'none'. Public routes skip the dispatcher's authorization phase entirely (per registry-time invariant 4 they also cannot declare roles or credential gates).

auth

type { account: "none" | "optional" | "required"; actor: "none" | "optional" | "required"; roles?: readonly string[] | undefined; credential_types?: readonly string[] | undefined; }

returns

boolean

is_receive_request
#

actions/action_event_helpers.ts view source

(data: { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }): data is ({ ...; } & { ...; }) | ... 3 more ... | ({ ...; } & { ...; })

data

type { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }

returns

boolean

is_receive_response
#

actions/action_event_helpers.ts view source

(data: { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }): data is ({ ...; } & { ...; }) | ... 3 more ... | ({ ...; } & { ...; })

data

type { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }

returns

boolean

is_remote_notification
#

actions/action_event_helpers.ts view source

(data: { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }): data is ActionEventRemoteNotificationData

data

type { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }

returns

boolean

is_request_response
#

actions/action_event_helpers.ts view source

(data: { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }): data is ActionEventRequestResponseData

data

type { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }

returns

boolean

is_response_for
#

testing/transports/ws_client.ts view source

(id: string | number): (msg: unknown) => boolean

Predicate matching a JSON-RPC response frame (success or error) for the given request id.

id

type string | number

returns

(msg: unknown) => boolean

is_role_auth
#

http/auth_shape.ts view source

(auth: { account: "none" | "optional" | "required"; actor: "none" | "optional" | "required"; roles?: readonly string[] | undefined; credential_types?: readonly string[] | undefined; }): boolean

True iff the route declares any role gate (auth.roles?.length).

auth

type { account: "none" | "optional" | "required"; actor: "none" | "optional" | "required"; roles?: readonly string[] | undefined; credential_types?: readonly string[] | undefined; }

returns

boolean

is_role_grant_active
#

auth/account_schema.ts view source

(p: { revoked_at?: string | null | undefined; expires_at: string | null; }, now?: Date): boolean

p

type { revoked_at?: string | null | undefined; expires_at: string | null; }

now

type Date
default new Date()

returns

boolean

is_send_request
#

actions/action_event_helpers.ts view source

(data: { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }): data is ({ ...; } & { ...; }) | ... 3 more ... | ({ ...; } & { ...; })

data

type { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }

returns

boolean

is_send_request_with_parsed_input
#

actions/action_event_helpers.ts view source

<TMethod extends string = string>(data: { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }): data is ({ ...; } & { ...; }) | ({ ...; } & { ...; })

data

type { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }

returns

boolean

is_send_response
#

actions/action_event_helpers.ts view source

(data: { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }): data is ({ ...; } & { ...; }) | ... 3 more ... | ({ ...; } & { ...; })

data

type { kind: "request_response" | "remote_notification" | "local_call"; phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"; ... 9 more ...; notification: { ...; } | null; }

returns

boolean

is_strict_object_schema
#

http/schema_helpers.ts view source

(schema: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>): boolean

Check if a schema is a strict object (z.strictObject()).

Strict objects set catchall to ZodNever to reject unknown keys. Regular z.object() has catchall: undefined (strips unknown keys in Zod 4).

schema

type ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>

returns

boolean

is_trusted_ip
#

http/proxy.ts view source

(ip: string, proxies: ParsedProxy[]): boolean

Check whether ip matches any entry in the trusted proxy list.

Normalizes ip before matching (lowercase, IPv4-mapped IPv6 stripped). Uses validate_ip_strict to reject malformed input โ€” without strict validation, Hono's lax distinctRemoteAddr would let an entry like '203.0.113.1:8080' (false-positive 'IPv6') reach convertIPv6ToBinary in the CIDR-match branch and throw.

ip

type string

proxies

type ParsedProxy[]

returns

boolean

is_void_schema
#

http/schema_helpers.ts view source

(schema: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>): boolean

Check if a schema is exactly z.void().

RPC action specs use z.void() to declare a parameterless method โ€” JSON-RPC 2.0 forbids params: null (params must be omitted or be a Structured value), so z.void() is the correct schema for "no params" and the dispatcher maps absent params to undefined for these specs.

schema

type ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>

returns

boolean

jsonrpc_error_code_to_http_status
#

http/jsonrpc_errors.ts view source

(code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<"JsonrpcServerErrorCode">)): ContentfulStatusCode

Map a JSON-RPC error code to an HTTP status code.

Returns 500 for unrecognized codes (consumer-defined codes without a mapping default to internal server error). The return is narrowed to Hono's ContentfulStatusCode so call sites can pass the result to c.json(body, status) without as any โ€” 499 (nginx "client closed request") is non-standard and gets absorbed by the cast here rather than at every dispatcher branch.

code

type -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<"JsonrpcServerErrorCode">)

returns

ContentfulStatusCode

JSONRPC_ERROR_CODE_TO_HTTP_STATUS
#

http/jsonrpc_errors.ts view source

Record<number, number>

Maps JSON-RPC error codes to HTTP status codes.

Extensible โ€” consumers with domain-specific error codes assign directly (JSONRPC_ERROR_CODE_TO_HTTP_STATUS[-32020] = 502) at module load. The lookup function reads at call time, so mutation is the supported extension mechanism.

jsonrpc_error_code_to_name
#

http/jsonrpc_errors.ts view source

(code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<"JsonrpcServerErrorCode">)): JsonrpcErrorName

Map a JSON-RPC error code to its canonical name ('not_found', 'forbidden', etc.). Falls back to 'internal_error' for codes outside the standard taxonomy so REST emitters that read this for their error field always have a stable string to emit.

code

type -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<"JsonrpcServerErrorCode">)

returns

JsonrpcErrorName

JSONRPC_ERROR_CODE_TO_NAME
#

http/jsonrpc_errors.ts view source

Readonly<Record<number, JsonrpcErrorName>>

Reverse map of JSONRPC_ERROR_CODES โ€” JSON-RPC error code โ†’ name.

Used by REST emitters that need a stable string identifier for the code in their flat-shape error body ({error: '<name>', ...}) without inventing a separate vocabulary. Built once at module load from the canonical JSONRPC_ERROR_CODES map so the two cannot drift.

Consumer-defined codes outside the standard taxonomy are not present; jsonrpc_error_code_to_name falls back to 'internal_error' so the REST shape always carries some reason rather than undefined.

JSONRPC_ERROR_CODES
#

http/jsonrpc_errors.ts view source

Readonly<Record<JsonrpcErrorName, -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<"JsonrpcServerErrorCode">)>>

Standard JSON-RPC error codes (5) plus general application codes (10).

Extensible โ€” consumers add domain-specific codes to their own objects by casting as JsonrpcErrorCode. Application codes use the -32000 to -32099 range reserved by the JSON-RPC spec.

Frozen with Object.freeze to convert accidental mutation (test cross-contamination, cast escapes) into loud TypeErrors. Spread into a fresh object to extend.

jsonrpc_error_messages
#

http/jsonrpc_errors.ts view source

Readonly<Record<JsonrpcErrorName, (...args: any[]) => { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<"JsonrpcServerErrorCode">); message: string; data?: unknown; }>>

Named constructors for JsonrpcErrorObject values.

Each function creates a JSON-RPC error object with the correct code and a sensible default message. Used by the catch layer in apply_route_specs to build response bodies.

Frozen so tests must compose new objects rather than monkey-patch.

jsonrpc_errors
#

http/jsonrpc_errors.ts view source

{ readonly parse_error: (...args: any[]) => ThrownJsonrpcError; readonly invalid_request: (...args: any[]) => ThrownJsonrpcError; readonly method_not_found: (...args: any[]) => ThrownJsonrpcError; ... 11 more ...; readonly request_cancelled: (...args: any[]) => ThrownJsonrpcError; }

Named constructors for ThrownJsonrpcError.

Usage: throw jsonrpc_errors.not_found('user') or throw jsonrpc_errors.forbidden().

JSONRPC_INTERNAL_ERROR
#

JSONRPC_INVALID_PARAMS
#

JSONRPC_INVALID_REQUEST
#

JSONRPC_METHOD_NOT_FOUND
#

JSONRPC_PARSE_ERROR
#

JSONRPC_SERVER_ERROR_END
#

JSONRPC_SERVER_ERROR_START
#

JSONRPC_VERSION
#

JsonrpcErrorCode
#

http/jsonrpc.ts view source

ZodUnion<readonly [ZodLiteral<-32700>, ZodLiteral<-32600>, ZodLiteral<-32601>, ZodLiteral<-32602>, ZodLiteral<-32603>, $ZodBranded<...>]>

A valid JSON-RPC error code โ€” one of the 5 standard codes or a server-defined code in the -32000 to -32099 range.

JsonrpcErrorName
#

JsonrpcErrorObject
#

http/jsonrpc.ts view source

ZodObject<{ code: ZodUnion<readonly [ZodLiteral<-32700>, ZodLiteral<-32600>, ZodLiteral<-32601>, ZodLiteral<-32602>, ZodLiteral<-32603>, $ZodBranded<...>]>; message: ZodString; data: ZodOptional<...>; }, $loose>

Error object within a JSON-RPC error response.

JsonrpcErrorResponse
#

http/jsonrpc.ts view source

ZodObject<{ jsonrpc: ZodLiteral<"2.0">; id: ZodNullable<ZodUnion<readonly [ZodString, ZodNumber]>>; error: ZodObject<{ code: ZodUnion<readonly [ZodLiteral<-32700>, ... 4 more ..., $ZodBranded<...>]>; message: ZodString; data: ZodOptional<...>; }, $loose>; }, $loose>

A response that indicates an error occurred.

JsonrpcErrorResponseFrame
#

testing/transports/ws_client.ts view source

JsonrpcErrorResponseFrame<D>

generics

D

default unknown

jsonrpc

type typeof JSONRPC_VERSION

id

type number | string

error

type {code: number; message: string; data?: D}

JsonrpcMcpMeta
#

JsonrpcMessage
#

http/jsonrpc.ts view source

ZodUnion<readonly [ZodObject<{ jsonrpc: ZodLiteral<"2.0">; id: ZodUnion<readonly [ZodString, ZodNumber]>; method: ZodString; params: ZodOptional<ZodObject<{}, $loose>>; }, $loose>, ZodObject<...>, ZodObject<...>, ZodObject<...>]>

Any valid JSON-RPC message (request, notification, response, or error response).

JsonrpcMessageFromClientToServer
#

http/jsonrpc.ts view source

ZodUnion<readonly [ZodObject<{ jsonrpc: ZodLiteral<"2.0">; id: ZodUnion<readonly [ZodString, ZodNumber]>; method: ZodString; params: ZodOptional<ZodObject<{}, $loose>>; }, $loose>, ZodObject<...>]>

Messages a client can send to a server (request or notification).

JsonrpcMessageFromServerToClient
#

http/jsonrpc.ts view source

ZodUnion<readonly [ZodObject<{ jsonrpc: ZodLiteral<"2.0">; method: ZodString; params: ZodOptional<ZodObject<{}, $loose>>; }, $loose>, ZodObject<...>, ZodObject<...>]>

Messages a server can send to a client (notification, response, or error response).

JsonrpcMethod
#

JsonrpcNotification
#

http/jsonrpc.ts view source

ZodObject<{ jsonrpc: ZodLiteral<"2.0">; method: ZodString; params: ZodOptional<ZodObject<{}, $loose>>; }, $loose>

A notification which does not expect a response.

JsonrpcNotificationFrame
#

JsonrpcNotificationParams
#

http/jsonrpc.ts view source

ZodObject<{}, $loose>

Notification params โ€” loose object. Per-action schemas validate _meta content.

JsonrpcProgressToken
#

http/jsonrpc.ts view source

ZodUnion<readonly [ZodString, ZodNumber]>

A progress token, used to associate progress notifications with the original request.

JsonrpcRequest
#

http/jsonrpc.ts view source

ZodObject<{ jsonrpc: ZodLiteral<"2.0">; id: ZodUnion<readonly [ZodString, ZodNumber]>; method: ZodString; params: ZodOptional<ZodObject<{}, $loose>>; }, $loose>

A request that expects a response.

JsonrpcRequestId
#

http/jsonrpc.ts view source

ZodUnion<readonly [ZodString, ZodNumber]>

A uniquely identifying id for a request in JSON-RPC. Like MCP, excludes null.

JsonrpcRequestParams
#

http/jsonrpc.ts view source

ZodObject<{}, $loose>

Request params โ€” loose object. Per-action schemas validate _meta content.

JsonrpcRequestParamsMeta
#

http/jsonrpc.ts view source

ZodObject<{ progressToken: ZodOptional<ZodUnion<readonly [ZodString, ZodNumber]>>; }, $loose>

Request params metadata โ€” extends MCP meta with optional progress token.

JsonrpcResponse
#

http/jsonrpc.ts view source

ZodObject<{ jsonrpc: ZodLiteral<"2.0">; id: ZodUnion<readonly [ZodString, ZodNumber]>; result: ZodJSONSchema; }, $loose>

A successful (non-error) response to a request.

JsonrpcResponseOrError
#

http/jsonrpc.ts view source

ZodUnion<readonly [ZodObject<{ jsonrpc: ZodLiteral<"2.0">; id: ZodUnion<readonly [ZodString, ZodNumber]>; result: ZodJSONSchema; }, $loose>, ZodObject<...>]>

A successful response or an error response.

JsonrpcResult
#

http/jsonrpc.ts view source

ZodJSONSchema

Result โ€” any JSON value per JSON-RPC 2.0 ยง5. Per-action spec.output is the actual contract; the envelope only asserts presence + JSON-ness.

z.json() is required (not implicitly optional like z.unknown() / z.any(), which would let an error envelope {jsonrpc, id, error} parse successfully against the success envelope and break union discrimination).

JsonrpcServerErrorCode
#

http/jsonrpc.ts view source

$ZodBranded<ZodNumber, "JsonrpcServerErrorCode", "out">

A server-defined error code in the -32000 to -32099 range.

JsonrpcSuccessResponseFrame
#

keeper_identity
#

KeeperHeaderProvider
#

testing/integration_helpers.ts view source

KeeperHeaderProvider

Header-builder triple shared by TestApp (in-process) and TestFixture (cross-backend fixture protocol). Both satisfy this shape structurally โ€” pick_auth_headers accepts either without a cast.

create_session_headers

type (extra?: Record<string, string>) => Record<string, string>

create_bearer_headers

type (extra?: Record<string, string>) => Record<string, string>

create_daemon_token_headers

type (extra?: Record<string, string>) => Record<string, string>

KeyedAsyncSlot
#

ui/keyed_async_slot.svelte.ts view source

Reactive container for many concurrent async operations keyed by K.

generics

K

T

default void

E

default string

constructor

type new <K, T = void, E = string>(options?: KeyedAsyncSlotOptions<T, E>): KeyedAsyncSlot<K, T, E>

options
type KeyedAsyncSlotOptions<T, E>
default {}

has

Reactive โ€” true once run(key, ...) has been called and the entry hasn't been deleted.

type (key: K): boolean

key
type K
returns boolean

get

Direct access to the underlying AsyncSlot for key, or undefined if no run() has been issued for it yet. Reactive on map population and on the slot's $state.raw fields.

Prefer the sugar getters ({@link loading}, {@link error}) for templates; reach for get(key) when you need error_data, data, or to call abort() / set() / reset() on the underlying slot.

type (key: K): AsyncSlot<T, E> | undefined

key
type K
returns AsyncSlot<T, E> | undefined

loading

Reactive โ€” false for keys that have never been used.

type (key: K): boolean

key
type K
returns boolean

error

Reactive โ€” null when the key has no entry or hasn't failed.

type (key: K): E | null

key
type K
returns E | null

failed

Reactive โ€” false for keys that have never been used.

type (key: K): boolean

key
type K
returns boolean

succeeded

Reactive โ€” false for keys that have never been used.

type (key: K): boolean

key
type K
returns boolean

keys

Reactive iterator over every key with state.

type (): IterableIterator<K>

returns IterableIterator<K>

values

Reactive iterator over every slot.

type (): IterableIterator<AsyncSlot<T, E>>

returns IterableIterator<AsyncSlot<T, E>>

entries

Reactive iterator over [key, slot] pairs.

type (): IterableIterator<[K, AsyncSlot<T, E>]>

returns IterableIterator<[K, AsyncSlot<T, E>]>

run

Run an async operation for key. Lazily creates an AsyncSlot for the key on first use, inheriting the constructor's map_error / preserve_error_on_retry options.

Supersession is scoped to key: a second run(key, ...) aborts the first's signal AND drops its commit. Calls on different keys are fully independent (each has its own AbortController).

type (key: K, fn: (signal: AbortSignal) => Promise<T>, options?: RunOptions | undefined): Promise<T | undefined>

key
type K
fn
type (signal: AbortSignal) => Promise<T>
options?
type RunOptions | undefined
optional
returns Promise<T | undefined>

the resolved value on success; undefined on failure, abort, or supersession.

abort

Abort the in-flight run for key, if any. No-op when the key has no entry. The slot stays in the map at its prior resolved status โ€” call {@link delete} to remove the entry entirely.

type (key: K, reason?: unknown): void

key
type K
reason?
type unknown
optional
returns void

abort_all

Abort every in-flight run. Resolved entries stay in the map โ€” call {@link reset} to clear them too.

type (reason?: unknown): void

reason?
type unknown
optional
returns void

delete

Abort the in-flight run for key (if any) and remove the entry from the map. After delete(key), has(key) returns false and the sugar getters report the no-entry defaults โ€” typically how a UI dismisses a per-row error indicator.

type (key: K): boolean

key
type K
returns boolean

true if the key had an entry.

reset

Abort every in-flight run and clear the map. The keyed slot looks like a fresh instance afterwards.

type (): void

returns void

KeyedAsyncSlotOptions
#

ui/keyed_async_slot.svelte.ts view source

KeyedAsyncSlotOptions<T, E>

Constructor options for KeyedAsyncSlot. Propagated to every child AsyncSlot at lazy creation time.

initial from {@link AsyncSlotOptions} is deliberately omitted โ€” keyed slots have no per-key seed concept (the entries don't exist until run() creates them).

generics

T

E

default string

Keyring
#

auth/keyring.ts view source

Keyring

Opaque keyring that encapsulates secret keys. Only exposes sign/verify operations, never the raw keys.

sign

Sign a value with HMAC SHA-256.

type (value: string) => Promise<string>

verify

Verify a signed value and extract the original. Tries all keys in order to support key rotation.

type (signed_value: string) => Promise<{value: string; key_index: number} | null>

list_roles_with_grant_path
#

auth/role_schema.ts view source

(role_specs: ReadonlyMap<string, RoleSpec>, grant_path: string): string[]

Filter helper: list every role whose grant_paths includes the given path.

role_specs

type ReadonlyMap<string, RoleSpec>

grant_path

type string

returns

string[]

load_config
#

cli/config.ts view source

<T>(runtime: Pick<FsReadDeps, "stat" | "read_text_file"> & LogDeps, path: string, schema: ZodType<T, unknown, $ZodTypeInternals<T, unknown>>): Promise<...>

Load CLI configuration from a JSON file with Zod schema validation.

runtime

runtime with file read capability

type Pick<FsReadDeps, "stat" | "read_text_file"> & LogDeps

path

path to the config JSON file

type string

schema

Zod schema to validate against

type ZodType<T, unknown, $ZodTypeInternals<T, unknown>>

returns

Promise<T | null>

parsed config, or null if file doesn't exist or is invalid

load_env
#

env/load.ts view source

<T extends z.ZodObject>(schema: T, get_env: (key: string) => string | undefined): output<T>

Load and validate env vars against a Zod schema.

schema

Zod object schema defining expected env vars

type T

get_env

function to read an env var by key

type (key: string) => string | undefined

returns

output<T>

validated env object

throws

  • EnvValidationError - if Zod validation fails

load_env_file
#

env/dotenv.ts view source

(runtime: Pick<FsReadDeps, "read_text_file">, path: string): Promise<Record<string, string> | null>

Load and parse an env file.

Returns null only when the file does not exist. Other read errors (permission denied, I/O failure, etc.) are re-thrown so callers can distinguish "no file" from "couldn't read".

runtime

runtime with read_text_file capability

type Pick<FsReadDeps, "read_text_file">

path

path to env file

type string

returns

Promise<Record<string, string> | null>

parsed env record, or null if file doesn't exist

throws

  • Error - if reading fails for any reason other than `ENOENT` / `NotFound`

LocalCallActionSpec
#

actions/action_spec.ts view source

ZodObject<{ method: ZodString; initiator: ZodEnum<{ frontend: "frontend"; backend: "backend"; both: "both"; }>; side_effects: ZodBoolean; input: ZodCustom<ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>, ZodType<...>>; ... 7 more ...; auth: ZodDefault<...>; }, $strict>

Local calls can wrap synchronous or asynchronous actions, and are the escape hatch for remote APIs that do not support SAES.

log_db_factory_status
#

testing/db.ts view source

(factories: DbFactory[]): void

Log factory status to console.

factories

type DbFactory[]

returns

void

log_env_validation_error
#

env/load.ts view source

(error: EnvValidationError, label?: string | undefined): void

Log formatted env validation issues to stderr.

Handles the common case: labels each Zod issue with an optional prefix. Callers who want app-specific "getting started" instructions should check error.all_undefined before calling this.

error

the env validation error

label?

optional prefix for log lines (e.g., 'zap daemon', 'env')

type string | undefined
optional

returns

void

log_startup_summary
#

server/startup.ts view source

(surface: AppSurface, log: Logger, env_values?: Record<string, unknown> | undefined): void

Log a startup summary from an AppSurface.

Logs route count, middleware count, env breakdown (when non-empty), and event/channel counts (when non-empty). When env_values is provided, non-secret values are logged and secrets are masked with ***.

surface

log

type Logger

env_values?

optional env values to log (secrets are masked)

type Record<string, unknown> | undefined
optional

returns

void

LogDeps
#

runtime/deps.ts view source

LogDeps

Warning/diagnostic output.

warn

Log a warning message.

type (...args: Array<unknown>) => void

LoginForm
#

ui/LoginForm.svelte view source

username_label?

Label and placeholder for the username field โ€” set when the surface accepts only one of username/email so the UX matches.

type string
optional

redirect_on_login?

Path to navigate to on successful login.

type string
optional

LoginInput
#

auth/account_routes.ts view source

ZodObject<{ username: ZodPipe<ZodString, ZodTransform<string, string>>; password: ZodString; }, $strict>

Input for POST /login. Accepts a username or email in the username field.

LoginOutput
#

LogoutButton
#

LogoutInput
#

LogoutOutput
#

auth/account_routes.ts view source

ZodObject<{ ok: ZodLiteral<true>; username: ZodString; }, $strict>

Output for POST /logout. Includes the revoked account's username for UI redraw.

make_default_rust_backend_config
#

make_default_ts_backend_config
#

MakeDefaultRustBackendConfigOptions
#

testing/cross_backend/default_backend_configs.ts view source

MakeDefaultRustBackendConfigOptions

name

Diagnostic label; also used as the tmpdir prefix when paths is omitted.

type string
readonly

port

TCP port the binary listens on.

type number
readonly

start_command

argv passed to the spawn (first entry is the binary).

type ReadonlyArray<string>
readonly

database_url

Required โ€” Rust needs real Postgres (PGlite isn't reachable from tokio-postgres). Consumers typically supply 'postgres://localhost/{repo}_test_{name}'.

type string
readonly

extra_env

Merged on top of the generic env baseline; later keys win.

type Readonly<Record<string, string>>
readonly

capabilities

readonly

paths

Pre-computed paths; defaults to build_test_backend_paths(name).

readonly

bootstrap_overrides

Override individual bootstrap fields (username/password/token).

type Partial<BackendBootstrapConfig>
readonly

port_env_var

Env-var name the binary reads for its port. Defaults to 'PORT'. Consumers whose binary reads a different name (e.g. 'ZZZ_PORT') override.

type string
readonly

rust_log

Initial value for RUST_LOG. Defaults to 'info'. Consumers pass their binary-specific module filter (e.g. 'info,zzz_server=info,testing_zzz_server=info').

type string
readonly

MakeDefaultTsBackendConfigOptions
#

testing/cross_backend/default_backend_configs.ts view source

MakeDefaultTsBackendConfigOptions

name

Diagnostic label; also used as the tmpdir prefix when paths is omitted.

type string
readonly

port

TCP port the binary listens on.

type number
readonly

start_command

argv passed to the spawn (first entry is the binary).

type ReadonlyArray<string>
readonly

database_url

Defaults to 'memory://' (in-memory PGlite).

type string
readonly

extra_env

Merged on top of the generic env baseline; later keys win.

type Readonly<Record<string, string>>
readonly

capabilities

readonly

paths

Pre-computed paths; defaults to build_test_backend_paths(name).

readonly

bootstrap_overrides

Override individual bootstrap fields (username/password/token).

type Partial<BackendBootstrapConfig>
readonly

port_env_var

Env-var name the binary reads for its port. Defaults to 'PORT'. Consumers whose binary reads a different name (e.g. 'ZZZ_PORT') override.

type string
readonly

MASKED_VALUE
#

MenuLink
#

merge_error_schemas
#

http/schema_helpers.ts view source

(spec: { auth: { account: "none" | "optional" | "required"; actor: "none" | "optional" | "required"; roles?: readonly string[] | undefined; credential_types?: readonly string[] | undefined; }; input: ZodType<unknown, unknown, $ZodTypeInternals<...>>; params?: ZodObject<...> | undefined; query?: ZodObject<...> | undefined; rate_limit?: "both" | ... 2 more ... | undefined; errors?: Partial<...> | undefined; }, middleware_errors?: Partial<...> | ... 1 more ... | undefined): Partial<...> | null

Merge auto-derived, middleware, and explicit error schemas for a route spec.

Merge order: derived -> middleware -> explicit route errors. Later layers override earlier ones for the same status code.

spec

the route spec (needs auth, input, params, rate_limit, errors)

type { auth: { account: "none" | "optional" | "required"; actor: "none" | "optional" | "required"; roles?: readonly string[] | undefined; credential_types?: readonly string[] | undefined; }; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; params?: ZodObject<...> | undefined; query?: ZodObject<...> ...

middleware_errors?

errors contributed by middleware whose path matches the route

type Partial<Record<number, ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>>> | null | undefined
optional

returns

Partial<Record<number, ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>>> | null

merged error schemas, or null if empty

middleware_applies
#

http/schema_helpers.ts view source

(mw_path: string, route_path: string): boolean

Check if a middleware path pattern applies to a route path.

Supports Hono-style patterns: - /api/* matches /api/anything - /api/zap/* matches /api/zap/runs but not /api/account/login - Exact match: /health matches /health

mw_path

type string

route_path

type string

returns

boolean

MiddlewareSpec
#

Migration
#

db/migrate.ts view source

Migration

A single migration: a name + an up function applied inside a transaction.

Throw from up to roll back the entire chain.

name

type string

up

type (db: Db) => Promise<void>

MigrationError
#

db/migrate.ts view source

Tagged error thrown by run_migrations and baseline.

Branch on .kind; the message carries an operator-facing remediation hint.

inheritance

extends:
  • Error

kind

type MigrationErrorKind

readonly

namespace

type string

readonly

at_index

type number

readonly

unknown_names

type ReadonlyArray<string>

readonly

constructor

type new (kind: MigrationErrorKind, message: string, context?: MigrationErrorContext | undefined): MigrationError

kind
message
type string
context?
type MigrationErrorContext | undefined
optional

MigrationErrorContext
#

db/migrate.ts view source

MigrationErrorContext

Structured context passed alongside a MigrationError.

namespace

type string

at_index

type number

unknown_names

type ReadonlyArray<string>

cause

type unknown

MigrationErrorKind
#

MigrationNamespace
#

db/migrate.ts view source

MigrationNamespace

A named group of ordered migrations.

Array index = position in the chain. Pre-stable: bodies, names, and positions can change between versions (consumers re-bootstrap on upgrade).

namespace

type string

migrations

type Array<Migration>

MigrationResult
#

db/migrate.ts view source

MigrationResult

Result of running migrations for a single namespace.

namespace

type string

applied_names

Migrations applied in this run, in sequence-ascending (execution) order.

type Array<string>

MigrationStatus
#

db/status.ts view source

MigrationStatus

Migration status for a single namespace.

namespace

type string

applied_names

Names of migrations recorded in the tracker, sequence-ascending.

type Array<string>

pending_names

Names of code migrations not yet applied (suffix of the code array).

type Array<string>

up_to_date

Whether applied_names is the full code array (no pending work).

type boolean

MinimalActionEnvironment
#

testing/ws_round_trip.ts view source

Minimal ActionEventEnvironment for tests that instantiate an ActionPeer without pulling in the full runtime. Pre-loads a spec map from the supplied list.

inheritance

executor

type 'frontend' | 'backend'

constructor

type new (specs: readonly ({ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; })[]): MinimalActionEnvironment

specs
type readonly ({ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } ...

lookup_action_handler

type (): undefined

returns undefined

lookup_action_spec

type (method: string): { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 7 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; } | undefined

method
type string
returns { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }...

MockExitError
#

runtime/mock.ts view source

Error thrown when mock runtime.exit() is called.

Tests can catch this to verify exit behavior.

inheritance

extends:
  • Error

code

type number

readonly

constructor

type new (code: number): MockExitError

code
type number

MockFs
#

testing/mock_fs.ts view source

MockFs

In-memory file system mock for tests that use dependency-injected read_file and write_file callbacks. Avoids module-level mocking.

read_file

type (path: string, encoding: string) => Promise<string>

write_file

type (path: string, content: string, encoding: string) => Promise<void>

get_file

type (path: string) => string | undefined

MockRuntime
#

runtime/mock.ts view source

MockRuntime

Mock RuntimeDeps with observable state for assertions.

inheritance

extends:

mock_env

Mock environment variables.

type Map<string, string>

mock_fs

Mock file system (path -> content).

type Map<string, string>

mock_fs_bytes

Mock binary file system (path -> bytes).

type Map<string, Uint8Array>

mock_dirs

Mock directories that exist.

type Set<string>

exit_calls

Exit calls recorded (exit codes).

type Array<number>

command_calls

Commands executed. Captures options when passed so tests can assert cwd/timeout/signal.

type Array<{cmd: string; args: Array<string>; options?: RunCommandOptions}>

command_inherit_calls

Commands executed with inherit.

type Array<{cmd: string; args: Array<string>}>

stdout_writes

Stdout writes recorded.

type Array<string>

mock_command_results

Mock command results (cmd -> result).

type Map<string, CommandResult>

stdin_buffer

Stdin buffer for input simulation.

type Uint8Array | null

fetch_calls

Fetch calls recorded.

type Array<{input: string | URL | Request; init?: RequestInit}>

mock_fetch_responses

Mock fetch responses (URL substring -> Response).

type Map<string, Response>

needs_account
#

http/auth_shape.ts view source

(auth: { account: "none" | "optional" | "required"; actor: "none" | "optional" | "required"; roles?: readonly string[] | undefined; credential_types?: readonly string[] | undefined; }): boolean

True iff the route declares an account axis ('optional' or 'required'). Per registry-time invariant 3 this is implied by needs_actor(auth) in v1 (no accountless actors yet).

auth

type { account: "none" | "optional" | "required"; actor: "none" | "optional" | "required"; roles?: readonly string[] | undefined; credential_types?: readonly string[] | undefined; }

returns

boolean

needs_actor
#

http/auth_shape.ts view source

(auth: { account: "none" | "optional" | "required"; actor: "none" | "optional" | "required"; roles?: readonly string[] | undefined; credential_types?: readonly string[] | undefined; }): boolean

True iff the route declares an actor axis ('optional' or 'required'). Equivalent to "the dispatcher's authorization phase may resolve an actor for this request" โ€” which by registry-time invariant 2 also means the input (or query, on REST GETs) declares acting?: ActingActor.

auth

type { account: "none" | "optional" | "required"; actor: "none" | "optional" | "required"; roles?: readonly string[] | undefined; credential_types?: readonly string[] | undefined; }

returns

boolean

NginxValidationResult
#

server/validate_nginx.ts view source

NginxValidationResult

Result of validating an nginx config template string.

ok

True when no errors were detected. Warnings do not affect this flag.

type boolean

warnings

Non-fatal issues โ€” missing optional headers, weakened defaults, etc.

type Array<string>

errors

Fatal issues โ€” missing /api block, missing required security headers, etc.

type Array<string>

no_nested_transaction
#

db/db.ts view source

<T>(fn: (tx_db: Db) => Promise<T>): Promise<T>

Sentinel transaction function for transaction-scoped Db instances.

Used by driver adapters when constructing the inner Db passed to transaction callbacks.

fn

type (tx_db: Db) => Promise<T>

returns

Promise<T>

throws

  • Error - always โ€” nested transactions are not supported

NoActorsOnAccountError
#

normalize_ip
#

http/proxy.ts view source

(ip: string): string

Normalize an IP address for consistent matching and storage.

Delegates to canonicalize_ip from ip_canonical.ts โ€” collapses RFC 5952-equivalent IPv6 forms (::1, ::0001, 0:0:0:0:0:0:0:1) into a single key, emits IPv4-mapped IPv6 in dotted form, and strips the ::ffff: prefix from dotted IPv4-mapped values so the bucket collapses to plain IPv4.

- Lowercases for case-insensitive IPv6 comparison. - Idempotent: calling twice produces the same result. - Safe on non-IP strings: normalize_ip('unknown') returns 'unknown'. Malformed inputs ('attacker:controlled', '::1\n', '203.0.113.1:8080') pass through unchanged so downstream validate_ip_strict can still reject them โ€” canonicalization never erases the malformed-form signal.

ip

type string

returns

string

NotificationSender
#

auth/role_grant_offer_notifications.ts view source

NotificationSender

Narrow structural capability for sending a JSON-RPC notification to every socket bound to an account.

BackendWebsocketTransport satisfies this interface โ€” its send_to_account(account_id, message) signature accepts the broader JsonrpcMessageFromServerToClient type, which is contravariantly compatible with JsonrpcNotification here. The interface stays local so handlers don't couple to the concrete transport, and tests can inject a capturing stub with no WS machinery.

Returns the number of sockets the notification was sent to โ€” callers typically ignore it (used by telemetry / tests).

send_to_account

type (account_id: Uuid, message: JsonrpcNotification) => number

OpenSignupToggle
#

parse_action_event
#

actions/action_event.ts view source

(raw_json: unknown, environment: ActionEventEnvironment): ActionEvent<string, "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute", "initial" | ... 3 more ... | "failed">

raw_json

type unknown

environment

returns

ActionEvent<string, "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute", "initial" | "parsed" | "handling" | "handled" | "failed">

parse_allowed_origins
#

http/origin.ts view source

(env_value: string | undefined): RegExp[]

Parses FUZ_ALLOWED_ORIGINS env var into regex matchers for request source verification. Origin allowlisting for locally-running services โ€” not the CSRF layer (that's SameSite: strict on session cookies).

Accepts comma-separated patterns with limited wildcards: - Exact origins: https://api.fuz.dev - Wildcard subdomains: https://*.fuz.dev (matches exactly one subdomain level) - Multiple wildcards: https://*.staging.*.fuz.dev (for deep subdomains) - Wildcard ports: http://localhost:* (matches any port or no port) - IPv6 addresses: http://[::1]:3000, https://[2001:db8::1] - Combined: https://*.fuz.dev:*

Examples: - http://localhost:3000,https://prod.fuz.dev - https://*.api.fuz.dev,http://127.0.0.1:* - http://[::1]:*,https://*.*.corp.fuz.dev:*

env_value

type string | undefined

returns

RegExp[]

throws

  • Error - if any individual pattern is invalid (missing protocol, partial wildcards, etc.)

parse_command_args
#

cli/args.ts view source

<T extends Record<string, unknown>>(remaining: ParsedArgs, schema: ZodType<T, unknown, $ZodTypeInternals<T, unknown>>): ParseResult<T>

Parse command-specific args against a Zod schema.

Validates remaining args (after global flag extraction) with alias expansion and returns a typed result or a prettified error string.

remaining

remaining args after global flag extraction

type ParsedArgs

schema

Zod schema for the command

type ZodType<T, unknown, $ZodTypeInternals<T, unknown>>

returns

ParseResult<T>

parse result with typed data or error message

parse_db_name
#

dev/setup.ts view source

(url: string): string | null

Extract the database name from a PostgreSQL URL.

url

type string

returns

string | null

the database name, or null if the URL is invalid or has no path

parse_dotenv
#

env/dotenv.ts view source

(content: string): Record<string, string>

Parse a dotenv-format string into a record.

Values wrapped in "..." have \\ โ†’ \, \" โ†’ ", \n โ†’ newline, and \r โ†’ carriage-return decoded (symmetric with the writer in update_env_variable). Values wrapped in '...' are taken literally โ€” no escape processing. Unquoted values are unchanged.

Inline comments are stripped after a closing quote (e.g. KEY="v" # c โ†’ v) and after whitespace on unquoted values (e.g. KEY=v # c โ†’ v). Unquoted values keep # literal when no whitespace precedes it so URL fragments like KEY=https://x.com#frag round-trip unchanged.

Trailing whitespace on unquoted values is lost (the raw value is trimmed); wrap the value in "..." or '...' to preserve surrounding spacing.

content

dotenv file content

type string

returns

Record<string, string>

parsed key-value pairs

parse_proxy_entry
#

http/proxy.ts view source

(entry: string): ParsedProxy

Parse a trusted proxy entry string into a structured form.

Accepts plain IPs ('127.0.0.1', '::1') and CIDR notation ('10.0.0.0/8', 'fe80::/10'). Plain IPs are normalized (lowercase, IPv4-mapped IPv6 stripped) and validated. CIDR prefixes are validated against address family bounds.

entry

IP address or CIDR notation

type string

returns

ParsedProxy

throws

  • Error - on invalid IP, invalid CIDR network, or NaN/negative/over-range prefix

parse_response_error
#

ui/ui_fetch.ts view source

(response: Response, fallback?: string | undefined): Promise<string>

Safely extract an error message from a non-ok response.

Handles responses with non-JSON bodies (e.g. HTML 404 pages) that would throw on response.json().

response

type Response

fallback?

message when no .error field is found

type string | undefined
optional

returns

Promise<string>

parse_session
#

auth/session_cookie.ts view source

<TIdentity>(signed_value: string | undefined, keyring: Keyring, options: SessionOptions<TIdentity>, now_seconds?: number | undefined): Promise<ParsedSession<...> | null | undefined>

Parse a signed session cookie value.

The signed value format is ${encode(identity)}:${expires_at}. Tries all keys in order to support key rotation. The result's should_refresh_expiration flag fires when the cookie is within options.refresh_threshold_seconds of expires_at.

signed_value

the raw cookie value (signed)

type string | undefined

keyring

key ring for verification

type Keyring

options

session configuration with decode logic

type SessionOptions<TIdentity>

now_seconds?

current time in seconds (for testing)

type number | undefined
optional

returns

Promise<ParsedSession<TIdentity> | null | undefined>

ParsedSession if valid, null if invalid/expired, undefined if empty/missing

ParsedProxy
#

ParsedSession
#

auth/session_cookie.ts view source

ParsedSession<TIdentity>

Result of parsing a signed session cookie.

generics

TIdentity

identity

The decoded identity.

type TIdentity

should_refresh_signature

True if verified with a non-primary key (needs re-signing).

type boolean

should_refresh_expiration

True if the embedded expires_at is within options.refresh_threshold_seconds of now. Signals that the cookie is valid but should be re-signed to extend its lifetime โ€” mirrors query_session_touch's DB-side extension so the cookie and server session don't drift. Always false when the threshold is 0.

type boolean

key_index

Index of the key that verified the signature.

type number

ParseResult
#

Password
#

auth/password.ts view source

ZodString

Password for account creation or password change โ€” enforces current length policy. Also usable for client-side UX validation.

PASSWORD_LENGTH_MAX
#

PASSWORD_LENGTH_MIN
#

PasswordChangeInput
#

auth/account_routes.ts view source

ZodObject<{ current_password: ZodString; new_password: ZodString; }, $strict>

Input for POST /password. current_password is minimally validated; new_password enforces the full policy.

PasswordChangeOutput
#

auth/account_routes.ts view source

ZodObject<{ ok: ZodLiteral<true>; sessions_revoked: ZodNumber; tokens_revoked: ZodNumber; }, $strict>

Output for POST /password. Counts are returned so the UI can summarize the revoke-all cascade.

PasswordHashDeps
#

auth/password.ts view source

PasswordHashDeps

Injectable password hashing dependencies.

Groups all three password operations for injection in route factories and other callers. Use Pick<PasswordHashDeps, ...> when only a subset is needed:

examples

// Login handler only needs verification password: Pick<PasswordHashDeps, 'verify_password' | 'verify_dummy'>; // Bootstrap only needs hashing password: Pick<PasswordHashDeps, 'hash_password'>;

hash_password

type (password: string) => Promise<string>

verify_password

type (password: string, password_hash: string) => Promise<boolean>

verify_dummy

type (password: string) => Promise<boolean>

PasswordProvided
#

auth/password.ts view source

ZodString

Password submitted for login or verification โ€” minimal validation for forward-compatibility if length requirements change.

PayloadTooLargeError
#

http/error_schemas.ts view source

ZodObject<{ error: ZodLiteral<"payload_too_large">; }, $loose>

Payload too large error โ€” returned when the request body exceeds the size limit.

PendingOfferSummaryJson
#

auth/account_schema.ts view source

ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; role: ZodString; scope_kind: ZodNullable<ZodString>; scope_id: ZodNullable<$ZodBranded<ZodUUID, "Uuid", "out">>; from_actor_id: $ZodBranded<...>; from_username: ZodString; created_at: ZodString; expires_at: ZodString; }, $strict>

Zod schema for a pending role_grant offer surfaced in admin account listings.

Deliberately narrower than RoleGrantOfferJson: omits message and decline_reason so cross-admin visibility of the listing does not expose grantor-authored text that the audit log also withholds. Full offer payloads remain available through the offer-specific RPC surface and the audit log when admins need them.

from_username is resolved server-side so multi-admin deployments can see at a glance whose pending offer is blocking a "+ {role}" button; the resolution runs inside the listing query's parallel batch.

perform_action
#

actions/perform_action.ts view source

(input: PerformActionInput, deps: PerformActionDeps): Promise<PerformActionResult>

The shared dispatch core. Pure data โ€” no Hono context, no socket. Each transport calls into this with pre-parsed inputs and binds the result to its wire shape.

Phase order: 401 โ†’ 400 โ†’ 403 โ†’ handler. On the test-preset path the dispatcher skips the live authorization phase and uses the supplied pre-baked context for post-authorization checks; pre-validation 401 still fires when the harness omits account_id.

input

deps

returns

Promise<PerformActionResult>

perform_action_result_to_envelope
#

actions/perform_action.ts view source

(id: string | number, result: PerformActionResult): { jsonrpc: string; id: string | number; } & ({ result: unknown; } | { error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<...>); message: string; data?: unknown; }; })

Build a JSON-RPC response envelope from a PerformActionResult for transports that wire over the JSON-RPC 2.0 message shape (HTTP RPC + WS).

id

type string | number

result

returns

{ jsonrpc: string; id: string | number; } & ({ result: unknown; } | { error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<"JsonrpcServerErrorCode">); message: string; data?: unknown; }; })

PerformActionDeps
#

actions/perform_action.ts view source

PerformActionDeps

Per-deps inputs to perform_action. Each transport supplies its own pool-level Db and rate limiters; the dispatcher wraps in a transaction iff spec.side_effects is true.

Pool-resilient fire-and-forget effects (audit writes) run through AppDeps.audit.emit from the action factory's closure โ€” the dispatcher never sees the audit emitter. The bound emitter owns the pool.

db

Pool-level DB. The dispatcher wraps in db.transaction for side_effects: true actions.

type Db

pending_effects

Eager fire-and-forget pool-write queue, flushed by the transport's try/finally via flush_pending_effects.

type Array<Promise<void>>

post_commit_effects

Deferred post-commit thunks pushed via emit_after_commit, flushed by the transport's try/finally after the handler returns.

type Array<() => void | Promise<void>>

log

Logger threaded into ActionContext.log.

type Logger

action_ip_rate_limiter

Per-IP limiter (shared across transports). null disables.

type RateLimiter | null

action_account_rate_limiter

Per-account limiter (shared across transports). null disables.

type RateLimiter | null

PerformActionInput
#

actions/perform_action.ts view source

PerformActionInput

Per-call inputs to perform_action. Each transport assembles this from its wire envelope + connection identity.

action

The resolved spec + handler (transport does method lookup).

raw_params

Raw params from the wire envelope (post-JsonrpcRequest.parse, pre-spec.input.safeParse).

type unknown

request_id

JSON-RPC request id โ€” echoed onto the response.

account_id

Authenticated account id, or null for anonymous.

type string | null

credential_type

Credential type the request arrived on, or null for anonymous.

type CredentialType | null

client_ip

Resolved client IP ('unknown' if upstream couldn't resolve).

type string

signal

Per-request abort signal. HTTP: c.req.raw.signal. WS: AbortSignal.any([socket, request]).

type AbortSignal

notify

Send a request-scoped notification. HTTP: DEV-warn-and-drop. WS: socket-scoped.

type (method: string, params: unknown) => void

connection_id

Stable per-socket id on WS; undefined on HTTP.

type Uuid

preset

Test-harness escape hatch. When set, the live authorization phase is skipped and request_context is used directly for post-authorization checks + handler dispatch. Production callers leave this undefined.

type {request_context: RequestContext | null}

PerformActionResult
#

actions/perform_action.ts view source

PerformActionResult

Discriminated result of perform_action. Each transport binds this to its wire shape: HTTP RPC folds the error into a JSON-RPC envelope and returns via c.json; WS sends the response over the socket.

PermissionError
#

http/error_schemas.ts view source

ZodObject<{ error: ZodLiteral<"insufficient_permissions">; required_roles: ZodReadonly<ZodArray<ZodString>>; }, $loose>

Permission error โ€” returned by require_role() and the dispatcher's post-authorization role gate when the actor's role_grants don't include any of the route's auth.roles.

required_roles carries the full disjunction the route declared (auth.roles from the new flat-record shape). Single-role specs surface as a one-element array; multi-role disjunctions show every admittable role so clients can render targeted copy ("requires admin or steward").

pick_auth_headers
#

testing/integration_helpers.ts view source

(spec: RouteSpec, keeper: KeeperHeaderProvider, authed_account: TestAccount, admin_account: TestAccount): Record<...>

Pick request headers matching a route spec's auth requirement.

Maps RouteAuth onto a test account's credentials: - none โ€” origin headers only - authenticated โ€” the authed account's session cookie - role: admin โ€” the admin account's session cookie - role: <other> โ€” the keeper provider's session - keeper โ€” the keeper provider's daemon token

spec

keeper

authed_account

admin_account

returns

Record<string, string>

Popover
#

ui/popover.svelte.ts view source

Class that manages state and provides actions for popovers.

visible

Whether the popover is currently visible.

position

Position of the popover relative to its trigger.

type Position

align

Alignment along the position edge.

type Alignment

offset

Distance from the position.

disable_outside_click

Whether to disable closing when clicking outside.

popover_class

Custom class for the popover.

constructor

type new (params?: PopoverParameters | undefined): Popover

params?
type PopoverParameters | undefined
optional

update

Updates the popover configuration. Swaps popover_class on the live content element when supplied and re-syncs the outside-click handler if disable_outside_click changed.

type (params: PopoverParameters): void

params
returns void

show

Shows the popover, registering the outside-click handler and updating aria-expanded on the trigger. No-ops when already visible.

type (): void

returns void

hide

Hides the popover, removing the outside-click handler. No-ops when already hidden.

type (): void

returns void

toggle

Toggles the popover visibility, or sets it to the given value.

type (visible?: boolean): void

visible

desired visibility (defaults to the inverse of current)

type boolean
default !this.visible
returns void

container

Attachment for the container element.

type Attachment<HTMLElement>

trigger

Attachment factory for the trigger element that shows/hides the popover.

content

Attachment factory for the popover content element.

PopoverButton
#

ui/PopoverButton.svelte view source

position?

type Position | undefined
optional

align?

type Alignment | undefined
optional

disable_outside_click?

type boolean | undefined
optional

popover_class?

type string | undefined
optional

popover_attrs?

type SvelteHTMLElements['div'] | undefined
optional

popover_content

type Snippet<[popover: Popover]>

popover_container_attrs?

type SvelteHTMLElements['div'] | undefined
optional

button?

type Snippet<[popover: Popover]> | undefined
optional

children?

type Snippet<[popover: Popover]> | undefined
optional

PopoverContentParameters
#

PopoverParameters
#

ui/popover.svelte.ts view source

PopoverParameters

Parameters for configuring the popover.

position

Position of the popover relative to its trigger.

align

Alignment along the position edge.

offset

Distance from the position.

type string

disable_outside_click

Whether to disable closing when clicking outside.

type boolean

popover_class

Custom class for the popover content.

type string

onshow

Optional callback when popover is shown.

type () => void

onhide

Optional callback when popover is hidden.

type () => void

PopoverTriggerParameters
#

Position
#

prefix_route_specs
#

http/route_spec.ts view source

(prefix: string, specs: RouteSpec[]): RouteSpec[]

Prepend a prefix to all route spec paths.

prefix

the path prefix (e.g. /api/account)

type string

specs

type RouteSpec[]

returns

RouteSpec[]

a new array โ€” the input specs are not mutated

PrimaryKeyInfo
#

process_session_cookie
#

ProcessDeps
#

ProcessSessionResult
#

auth/session_cookie.ts view source

ProcessSessionResult<TIdentity>

Result of processing a session cookie.

generics

TIdentity

valid

Whether the session is valid.

type boolean

action

Action the adapter should take.

type 'none' | 'clear' | 'refresh'

new_signed_value

New signed value when action is 'refresh'.

type string

identity

The decoded identity if the cookie was valid.

type TIdentity

PROTOCOL_ACTION_METHODS
#

actions/action_codegen.ts view source

readonly ["heartbeat", "cancel"]

Method names of fuz_app's protocol actions โ€” heartbeat (auth-aware client liveness probe) and cancel (request-scoped abort signal). Consumers spread this list when filtering backend request_response methods so the dispatcher-owned protocol actions don't show up in BackendRequestResponseMethod / handler maps. Pairs with protocol_actions / protocol_action_specs from actions/protocol.ts (the runtime bundles).

protocol_action_specs
#

actions/protocol.ts view source

readonly ({ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } ...

Canonical protocol specs for ActionRegistry construction on the frontend. Spread before consumer-owned specs so dispatcher-owned methods are present in the lookup map even though codegen excludes them from the generated action_specs array:

new ActionRegistry([...protocol_action_specs, ...action_specs])

Derived from protocol_actions so a future protocol action lands in one place โ€” the two arrays cannot drift.

protocol_actions
#

actions/protocol.ts view source

readonly Action<{ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ....

Canonical protocol {spec, handler} tuples for the server's register_action_ws actions array. Spread before consumer-owned actions so disconnect detection and per-request cancel work uniformly:

register_action_ws({actions: [...protocol_actions, ...consumer_actions], ...})

ProtocolActionMethod
#

provide_admin_rpc_contexts
#

ui/admin_rpc_adapters.ts view source

(adapters: AdminRpcAdapters, options?: ProvideAdminRpcContextsOptions | undefined): void

Wire all four admin RPC contexts in a single call.

Call once at the admin shell layout (e.g. src/routes/admin/+layout.svelte) with adapters built from create_admin_rpc_adapters. Every Admin*.svelte component that reads a context below this point sees the adapters.

Each context accessor reads adapters.{domain} on every invocation, so mutating an adapter field on the same object propagates. Replacing the whole adapter set requires calling provide_admin_rpc_contexts again during init โ€” in practice this is one-shot at layout mount.

Pass options.format_scope to render role_grant/offer scope_id values as human labels across AdminAccounts, AdminRoleGrantHistory, RoleGrantOfferInbox, RoleGrantOfferForm, and RoleGrantOfferHistory. Components that accept a format_scope prop honor the prop first; the context is the fallback.

adapters

options?

type ProvideAdminRpcContextsOptions | undefined
optional

returns

void

ProvideAdminRpcContextsOptions
#

ui/admin_rpc_adapters.ts view source

ProvideAdminRpcContextsOptions

Optional knobs alongside the adapters when wiring admin contexts.

format_scope

Render {scope_id, role} as a human label across role-grant-display components. Omit (or return null) to fall back to the raw uuid.

ProxyOptions
#

http/proxy.ts view source

ProxyOptions

Configuration for trusted proxy resolution.

trusted_proxies

Trusted proxy IPs or CIDR ranges (e.g. '127.0.0.1', '10.0.0.0/8', '::1').

type Array<string>

get_connection_ip

Extract the raw TCP connection IP from the Hono context.

type (c: Context) => string | undefined

log

Optional logger for proxy resolution diagnostics.

type Logger

query_accept_offer
#

auth/role_grant_offer_queries.ts view source

(deps: QueryDeps, input: AcceptOfferInput): Promise<AcceptOfferResult>

Accept an offer atomically: mark accepted, insert the role_grant, stamp resulting_role_grant_id, supersede sibling pending offers for the same (to_account, role, scope), and emit role_grant_offer_accept + role_grant_create + one role_grant_offer_supersede per sibling. Must run inside a transaction โ€” the caller's route spec should declare transaction: true (or wrap explicitly).

Idempotent on race: if a second concurrent call observes the offer already accepted, returns the existing role_grant rather than creating a duplicate or throwing.

Error map: - RoleGrantOfferNotFoundError โ€” offer does not exist, or belongs to a different recipient (IDOR guard). The offer row is untouched. - RoleGrantOfferAlreadyTerminalError โ€” offer is declined, retracted, or superseded. - RoleGrantOfferExpiredError โ€” offer is pending but past expires_at.

Sibling supersede is what closes the "accept a pre-revoke sibling offer to bypass a revoke" path: once A is accepted, B/C/... can no longer be accepted even if the resulting role_grant is later revoked.

deps

input

returns

Promise<AcceptOfferResult>

throws

  • RoleGrantOfferNotFoundError - if the offer is missing or belongs to another recipient
  • RoleGrantOfferAlreadyTerminalError - if the offer is declined, retracted, or superseded
  • RoleGrantOfferExpiredError - if the offer is pending but past `expires_at`
  • Error - if the accepting `actor_id` does not belong to `to_account_id`, or invariant assertions fail

query_account_by_email
#

auth/account_queries.ts view source

(deps: QueryDeps, email: string): Promise<Account | undefined>

Find an account by email (case-insensitive).

deps

email

type string

returns

Promise<Account | undefined>

query_account_by_id
#

query_account_by_username
#

auth/account_queries.ts view source

(deps: QueryDeps, username: string): Promise<Account | undefined>

Find an account by username (case-insensitive).

deps

username

type string

returns

Promise<Account | undefined>

query_account_by_username_or_email
#

auth/account_queries.ts view source

(deps: QueryDeps, input: string): Promise<Account | undefined>

Find an account by username or email.

If the input contains @, tries email lookup first then username. Otherwise tries username first then email. This supports a single login field that accepts either format.

deps

query dependencies

input

username or email address

type string

returns

Promise<Account | undefined>

the matching account, or undefined

query_account_has_any
#

query_account_has_global_role
#

auth/role_grant_queries.ts view source

(deps: QueryDeps, account_id: string, role: string): Promise<boolean>

Account-grain check: does any actor on account_id hold an active global role_grant for role?

Symmetric with query_role_grant_has_role but keyed on the account instead of a single actor โ€” for surfaces with auth: actor: 'none' that don't load auth.role_grants and can't use the in-memory has_scoped_role predicate. Joins role_grant โ†’ actor; matches only global role_grants (scope_id IS NULL) since the use case is "is the caller's account broadly admin", not scope-aware.

Fast under the existing idx_role_grant_actor index โ€” the inner actor_id IN (...) subquery is index-scan, and the outer EXISTS stops at the first match.

deps

query dependencies

account_id

the account to check

type string

role

the role to check for (e.g. ROLE_ADMIN)

type string

returns

Promise<boolean>

true if any actor on the account has an active global role_grant for role

query_actor_by_id
#

query_actor_search
#

query_actors_by_account
#

auth/account_queries.ts view source

(deps: QueryDeps, account_id: string): Promise<Actor[]>

List every actor on an account, ordered by created_at.

Used by resolve_acting_actor to resolve the acting actor for a request: 1 actor picks transparently, multiple require an explicit acting field on the request payload. For lookups by id, use query_actor_by_id instead.

deps

account_id

type string

returns

Promise<Actor[]>

query_actors_by_ids
#

auth/actor_lookup_queries.ts view source

(deps: QueryDeps, ids: readonly (string & $brand<"Uuid">)[]): Promise<ActorLookupRow[]>

Resolve a batch of actor ids to (id, username, display_name). Empty input fast-paths to []. Hard-deleted actors (or account-cascade- orphaned rows) drop out of the result silently.

deps

ids

type readonly (string & $brand<"Uuid">)[]

returns

Promise<ActorLookupRow[]>

query_admin_account_list
#

auth/account_queries.ts view source

(deps: QueryDeps, options?: AdminAccountListOptions | undefined): Promise<{ account: { id: string & $brand<"Uuid">; username: string; ... 4 more ...; updated_by: (string & $brand<...>) | null; }; actor: { ...; } | null; role_grants: { ...; }[]; pending_offers: { ...; }[]; }[]>

List accounts with their actors, active role_grants, and pending inbound role_grant offers for admin display.

Pages the accounts query (one round-trip), then fans out three parallel lookups scoped to the page's account_ids (one round-trip). The role_grants and offers queries use a subquery on actor.account_id so the page bound pushes through to the DB without round-tripping actor.ids back to the application. Pending offers surface the "offer pending โ€” awaiting acceptance" UX; message is intentionally excluded (cross-admin visibility of grantor notes would expand beyond what the audit log discloses).

deps

query dependencies

options?

optional {limit, offset}. Default limit is ADMIN_ACCOUNT_LIST_DEFAULT_LIMIT; pass limit: null to disable.

type AdminAccountListOptions | undefined
optional

returns

Promise<{ account: { id: string & $brand<"Uuid">; username: string; email: string | null; email_verified: boolean; created_at: string; updated_at: string; updated_by: (string & $brand<"Uuid">) | null; }; actor: { ...; } | null; role_grants: { ...; }[]; pending_offers: { ...; }[]; }[]>

admin account entries sorted by creation date (oldest first)

query_api_token_enforce_limit
#

auth/api_token_queries.ts view source

(deps: QueryDeps, account_id: string, max_tokens: number): Promise<number>

Enforce a per-account token limit by evicting the oldest tokens.

Race safety: this function must run inside a transaction alongside the INSERT that created the new token. The caller (the account_token_create RPC handler) runs under the dispatcher's transaction path because the spec declares side_effects: true, ensuring the INSERT + enforce_limit pair is atomic โ€” concurrent token creation cannot interleave.

deps

query dependencies (must be transaction-scoped)

account_id

the account to enforce the limit for

type string

max_tokens

maximum number of tokens to keep

type number

returns

Promise<number>

the number of tokens evicted

query_api_token_list_for_account
#

auth/api_token_queries.ts view source

(deps: QueryDeps, account_id: string): Promise<Omit<ApiToken, "token_hash">[]>

List all tokens for an account (does not include hashes).

Columns are enumerated explicitly to exclude token_hash. Must be updated if the api_token table gains new columns.

deps

account_id

type string

returns

Promise<Omit<ApiToken, "token_hash">[]>

query_app_settings_load
#

auth/app_settings_queries.ts view source

(deps: QueryDeps): Promise<AppSettings>

Load the current app settings.

deps

query dependencies

returns

Promise<AppSettings>

the app settings row

throws

  • Error - if the singleton `app_settings` row is missing (migration drift โ€” should not occur in practice)

query_app_settings_load_with_username
#

auth/app_settings_queries.ts view source

(deps: QueryDeps): Promise<{ open_signup: boolean; updated_at: string | null; updated_by: (string & $brand<"Uuid">) | null; updated_by_username: string | null; }>

Load the current app settings with resolved updater username.

deps

query dependencies

returns

Promise<{ open_signup: boolean; updated_at: string | null; updated_by: (string & $brand<"Uuid">) | null; updated_by_username: string | null; }>

the app settings with updated_by_username

throws

  • Error - if the singleton `app_settings` row is missing

query_app_settings_update
#

auth/app_settings_queries.ts view source

(deps: QueryDeps, open_signup: boolean, actor_id: string): Promise<AppSettings>

Update app settings and return the updated row.

deps

query dependencies

open_signup

new value for the open_signup toggle

type boolean

actor_id

the actor making the change

type string

returns

Promise<AppSettings>

the updated app settings row

throws

  • Error - if the singleton `app_settings` row is missing

query_audit_log
#

auth/audit_log_queries.ts view source

<T extends string>(deps: QueryDeps, input: AuditLogInput<T>, config?: AuditLogConfig): Promise<AuditLogEvent>

Insert an audit log entry.

RETURNING * so callers receive DB-assigned fields (id, seq, created_at). Validates metadata against config.metadata_schemas; unknown event_type and metadata mismatches log + bump their counters but write the row anyway. Consumers extend the recognized set via create_audit_log_config({extra_events}).

In-transaction call site for query helpers that must atomically write the row alongside other mutations (e.g. query_accept_offer). Fire-and-forget call sites should reach for AppDeps.audit.emit instead โ€” that wrapper closes over the pool so audit rows persist when the parent transaction rolls back.

deps

query dependencies

input

the audit event to record

type AuditLogInput<T>

config

audit-log config. Defaults to builtin_audit_log_config.

default builtin_audit_log_config

returns

Promise<AuditLogEvent>

the inserted audit log row

query_audit_log_cleanup_before
#

auth/audit_log_queries.ts view source

(deps: QueryDeps, before: Date): Promise<number>

Delete audit log entries older than the given date.

deps

query dependencies

before

delete entries created before this date

type Date

returns

Promise<number>

the number of entries deleted

query_audit_log_list
#

auth/audit_log_queries.ts view source

(deps: QueryDeps, options?: AuditLogListOptions | undefined): Promise<AuditLogEvent[]>

List audit log entries, newest first.

deps

query dependencies

options?

filters and pagination

type AuditLogListOptions | undefined
optional

returns

Promise<AuditLogEvent[]>

matching audit log entries

query_audit_log_list_role_grant_history
#

auth/audit_log_queries.ts view source

(deps: QueryDeps, limit?: number, offset?: number): Promise<{ id: string & $brand<"Uuid">; seq: number; event_type: string; outcome: "success" | "failure"; actor_id: (string & $brand<...>) | null; ... 7 more ...; target_username: string | null; }[]>

List role_grant grant/revoke events with resolved usernames.

deps

query dependencies

limit

maximum entries to return

type number
default AUDIT_LOG_DEFAULT_LIMIT

offset

number of entries to skip

type number
default 0

returns

Promise<{ id: string & $brand<"Uuid">; seq: number; event_type: string; outcome: "success" | "failure"; actor_id: (string & $brand<"Uuid">) | null; account_id: (string & $brand<...>) | null; ... 6 more ...; target_username: string | null; }[]>

role_grant history events with username and target_username

query_audit_log_list_with_usernames
#

auth/audit_log_queries.ts view source

(deps: QueryDeps, options?: AuditLogListOptions | undefined): Promise<{ id: string & $brand<"Uuid">; seq: number; event_type: string; outcome: "success" | "failure"; ... 8 more ...; target_username: string | null; }[]>

List audit log entries with resolved usernames, newest first.

deps

query dependencies

options?

filters and pagination

type AuditLogListOptions | undefined
optional

returns

Promise<{ id: string & $brand<"Uuid">; seq: number; event_type: string; outcome: "success" | "failure"; actor_id: (string & $brand<"Uuid">) | null; account_id: (string & $brand<...>) | null; ... 6 more ...; target_username: string | null; }[]>

matching audit log entries with username and target_username

query_create_account
#

query_create_account_with_actor
#

auth/account_queries.ts view source

(deps: QueryDeps, input: CreateAccountInput): Promise<{ account: Account; actor: Actor; }>

Create an account and its actor in a single operation.

For v1, every account gets exactly one actor with the same name as the username.

deps

query dependencies

input

the account fields

returns

Promise<{ account: Account; actor: Actor; }>

the created account and actor

query_create_actor
#

auth/account_queries.ts view source

(deps: QueryDeps, account_id: string, name: string): Promise<Actor>

Create a new actor for an account.

deps

query dependencies

account_id

the owning account

type string

name

display name (defaults to account username)

type string

returns

Promise<Actor>

the created actor

query_create_api_token
#

auth/api_token_queries.ts view source

(deps: QueryDeps, id: string, account_id: string, name: string, token_hash: string, expires_at?: Date | null | undefined): Promise<ApiToken>

Store a new API token (the hash, not the raw token).

deps

query dependencies

id

the public token id (e.g. tok_abc123)

type string

account_id

the owning account

type string

name

human-readable name

type string

token_hash

blake3 hash of the raw token

type string

expires_at?

optional expiration

type Date | null | undefined
optional

returns

Promise<ApiToken>

the stored token record

query_create_invite
#

query_create_role_grant
#

auth/role_grant_queries.ts view source

(deps: QueryDeps, input: CreateRoleGrantInput): Promise<RoleGrant>

Grant a role_grant to an actor. Idempotent โ€” if an active role_grant already exists for this actor, role, and scope, returns the existing role_grant instead of creating a duplicate.

The ON CONFLICT target and the fallback SELECT both collapse NULL scopes via the same sentinel + index-side 'GLOBAL' token used by the partial unique index (role_grant_actor_role_scope_active_unique). The IS NOT DISTINCT FROM form on the fallback is deliberate โ€” plain = would miss the NULL-scope case where the conflict fired.

scope_kind is paired-null with scope_id per the role_grant_scope_kind_paired CHECK; mismatched pairs raise at the DB layer rather than producing silent rows.

deps

query dependencies

input

the role_grant fields

returns

Promise<RoleGrant>

the created or existing active role_grant

query_create_session
#

auth/session_queries.ts view source

(deps: QueryDeps, token_hash: string, account_id: string, expires_at: Date): Promise<void>

Create a new auth session.

deps

query dependencies

token_hash

blake3 hash of the session token (use hash_session_token)

type string

account_id

the account this session belongs to

type string

expires_at

when the session expires

type Date

returns

Promise<void>

query_db_status
#

db/status.ts view source

(db: Db, namespaces?: MigrationNamespace[] | undefined): Promise<DbStatus>

Query database status including connectivity, tables, and migration state.

Designed for CLI db:status commands. Does not modify the database.

db

the database instance

type Db

namespaces?

migration namespaces to check status for

type MigrationNamespace[] | undefined
optional

returns

Promise<DbStatus>

a snapshot of database status; connected: false with error set when the initial connectivity probe fails

throws

  • Error - propagated from the driver if a query fails after the

query_delete_account
#

auth/account_queries.ts view source

(deps: QueryDeps, id: string): Promise<boolean>

Delete an account. Cascades to actors, role_grants, sessions, and tokens.

deps

id

type string

returns

Promise<boolean>

query_invite_claim_unscoped
#

auth/invite_queries.ts view source

(deps: QueryDeps, invite_id: string, account_id: string): Promise<boolean>

Claim an invite by setting the claimed_by and claimed_at fields.

The _unscoped suffix is the safety signal โ€” the SQL only checks the row state (claimed_at IS NULL), not whether the claiming account's email or username matches the invite. Callers must scope the lookup upstream via one of the _find_unclaimed_match* siblings (production uses _for_update to make find + claim atomic). Skipping the find step lets a caller claim any unclaimed invite by id.

Mirrors the query_session_revoke_by_hash_unscoped precedent โ€” there is no scoped sibling because the scoping is provided by a separate find query, not by an alternate variant of this query.

deps

query dependencies

invite_id

the invite to claim

type string

account_id

the account claiming the invite

type string

returns

Promise<boolean>

true if the invite was claimed, false if already claimed or not found

query_invite_delete_unclaimed
#

auth/invite_queries.ts view source

(deps: QueryDeps, id: string): Promise<boolean>

Delete an unclaimed invite.

deps

query dependencies

id

the invite id

type string

returns

Promise<boolean>

true if deleted, false if not found or already claimed

query_invite_find_unclaimed_by_email
#

auth/invite_queries.ts view source

(deps: QueryDeps, email: string): Promise<Invite | undefined>

Find an unclaimed invite by email (case-insensitive).

deps

email

type string

returns

Promise<Invite | undefined>

query_invite_find_unclaimed_by_username
#

auth/invite_queries.ts view source

(deps: QueryDeps, username: string): Promise<Invite | undefined>

Find an unclaimed invite by username (case-insensitive).

deps

username

type string

returns

Promise<Invite | undefined>

query_invite_find_unclaimed_match_for_update
#

auth/invite_queries.ts view source

(deps: QueryDeps, email: string | null, username: string): Promise<Invite | undefined>

Find an unclaimed invite matching email and/or username, taking a row-level write lock on the matched row.

Three scoping modes:

- Email-only invite (email set, username NULL) โ†’ matches only if signup provides matching email. - Username-only invite (username set, email NULL) โ†’ matches only if signup provides matching username. - Both-field invite (both set) โ†’ requires BOTH email and username to match.

Must run inside the same transaction as query_invite_claim_unscoped: FOR UPDATE makes find + claim atomic, so a concurrent signup that matched the same invite blocks on the lock until this transaction commits/rolls back. After commit, the loser's find_for_update returns no row (the winner flipped claimed_at) and falls through to ERROR_NO_MATCHING_INVITE โ€” no race window between find and claim.

deps

query dependencies โ€” deps.db MUST be a transaction

email

email to match (or null if signup provides none)

type string | null

username

username to match

type string

returns

Promise<Invite | undefined>

the matching invite (locked), or undefined

query_invite_list_all
#

query_invite_list_all_with_usernames
#

auth/invite_queries.ts view source

(deps: QueryDeps): Promise<{ id: string & $brand<"Uuid">; email: string | null; username: string | null; claimed_by: (string & $brand<"Uuid">) | null; ... 4 more ...; claimed_by_username: string | null; }[]>

List all invites with resolved creator/claimer usernames, newest first.

deps

query dependencies

returns

Promise<{ id: string & $brand<"Uuid">; email: string | null; username: string | null; claimed_by: (string & $brand<"Uuid">) | null; claimed_at: string | null; created_at: string; created_by: (string & $brand<...>) | null; created_by_username: string | null; claimed_by_username: string | null; }[]>

invites with created_by_username and claimed_by_username

query_revoke_all_api_tokens_for_account
#

auth/api_token_queries.ts view source

(deps: QueryDeps, account_id: string): Promise<number>

Revoke all tokens for an account.

deps

query dependencies

account_id

the account whose tokens to revoke

type string

returns

Promise<number>

the number of tokens revoked

query_revoke_api_token_for_account
#

auth/api_token_queries.ts view source

(deps: QueryDeps, id: string, account_id: string): Promise<boolean>

Revoke a token only if it belongs to the specified account.

Prevents cross-account token revocation.

deps

query dependencies

id

the public token id

type string

account_id

the account that must own the token

type string

returns

Promise<boolean>

true if a token was revoked, false if not found or wrong account

query_revoke_role_grant
#

auth/role_grant_queries.ts view source

(deps: QueryDeps, role_grant_id: string & $brand<"Uuid">, actor_id: string & $brand<"Uuid">, revoked_by: (string & $brand<"Uuid">) | null, reason?: string | ... 1 more ... | undefined): Promise<...>

Revoke a role_grant by id, constrained to a specific actor.

Requires actor_id to prevent cross-account revocation (IDOR guard). Returns null if the role_grant is not found, already revoked, or belongs to a different actor.

Supersedes any pending offers for the revoked role_grant's (to_account, role, scope) in the same transaction. Prevents the "accept a pre-revoke offer to bypass the revoke" path โ€” any stale offer becomes terminal at revoke time. A fresh post-revoke grant requires the grantor to call query_role_grant_offer_create again.

deps

query dependencies

role_grant_id

the role_grant to revoke

type string & $brand<"Uuid">

actor_id

the actor that must own the role_grant

type string & $brand<"Uuid">

revoked_by

the actor who revoked it (for audit trail)

type (string & $brand<"Uuid">) | null

reason?

optional free-form reason, stamped on role_grant.revoked_reason and surfaced to the revokee notification.

type string | null | undefined
optional

returns

Promise<RevokeRoleGrantResult | null>

query_role_grant_find_account_id_for_role
#

auth/role_grant_queries.ts view source

(deps: QueryDeps, role: string): Promise<string | null>

Find the account ID of an account that holds an active role_grant for a given role.

Joins role_grant โ†’ actor โ†’ account. Returns the first match, or null if none.

deps

query dependencies

role

the role to search for

type string

returns

Promise<string | null>

the account ID, or null

query_role_grant_find_active_for_actor
#

auth/role_grant_queries.ts view source

(deps: QueryDeps, actor_id: string): Promise<RoleGrant[]>

Find all active (non-revoked, non-expired) role_grants for an actor.

deps

actor_id

type string

returns

Promise<RoleGrant[]>

query_role_grant_find_active_role_for_actor
#

auth/role_grant_queries.ts view source

(deps: QueryDeps, role_grant_id: string, actor_id: string): Promise<{ role: string; account_id: string & $brand<"Uuid">; } | null>

Look up the role of an active role_grant (constrained to a specific actor) plus the actor's account_id.

Used by admin routes to inspect the role_grant's role before acting (e.g., enforcing the admin-grant-path gate on revoke). The actor constraint mirrors query_revoke_role_grant so IDOR protection is consistent: a caller can only see role_grants belonging to the target actor.

The JOIN to actor collapses what used to be a second query_actor_by_id round-trip in the revoke handler into one read, which closes the small TOCTOU window where the actor row could be deleted between the IDOR check and the actor lookup. The account_id is needed by the audit envelope's target_account_id field and the SSE/WS socket-close fan-out targeting.

Returns null if the role_grant is not found, already revoked, or belongs to a different actor.

deps

query dependencies

role_grant_id

the role_grant id to look up

type string

actor_id

the actor that must own the role_grant

type string

returns

Promise<{ role: string; account_id: string & $brand<"Uuid">; } | null>

{role, account_id} on a match, or null

query_role_grant_has_role
#

auth/role_grant_queries.ts view source

(deps: QueryDeps, actor_id: string, role: string, scope_id?: string | null | undefined): Promise<boolean>

Check if an actor has an active role_grant for a given role.

The scope_id parameter selects between global and scoped checks: - Omitted or null โ€” matches a global role_grant (scope_id IS NULL). Pre-scope callers keep their existing semantics. - A scope uuid โ€” matches a role_grant bound to that exact scope.

The IS NOT DISTINCT FROM comparison handles the NULL case uniformly.

deps

actor_id

type string

role

type string

scope_id?

type string | null | undefined
optional

returns

Promise<boolean>

query_role_grant_list_for_actor
#

auth/role_grant_queries.ts view source

(deps: QueryDeps, actor_id: string): Promise<RoleGrant[]>

List all role_grants for an actor (including revoked/expired).

deps

actor_id

type string

returns

Promise<RoleGrant[]>

query_role_grant_offer_create
#

auth/role_grant_offer_queries.ts view source

(deps: QueryDeps, input: CreateRoleGrantOfferInput): Promise<RoleGrantOffer>

Create a new role_grant offer, or refresh an existing pending offer for the same (to_account_id, role, scope_id, from_actor_id) tuple.

Re-offer semantics: a second call by the same grantor with the same (to_account, role, scope) while pending upserts the existing row, refreshing message and expires_at (and to_actor_id โ€” supplying a different to_actor_id on re-offer narrows the existing row to the named actor; supplying null widens it back to account-grain). A different grantor offering the same (to_account, role, scope) creates a distinct row โ€” multiple pending grantors coexist. After a terminal state, a re-offer is a fresh INSERT.

Self-offer rejection: throws RoleGrantOfferSelfTargetError if the offering actor belongs to the recipient account.

Actor-targeted offers: when to_actor_id is supplied, query_accept_offer rejects any actor other than the named one. Closes the audit hole where offer-shape events would otherwise leave target_actor_id null even when the recipient binding is known at offer time. The actorโ†”account binding is verified here in one SELECT.

deps

input

returns

Promise<RoleGrantOffer>

throws

  • RoleGrantOfferSelfTargetError - if the offering actor belongs to `to_account_id`
  • RoleGrantOfferActorAccountMismatchError - if `to_actor_id` is set but does not belong to `to_account_id`

query_role_grant_offer_decline
#

auth/role_grant_offer_queries.ts view source

(deps: QueryDeps, offer_id: string, to_account_id: string, reason: string | null): Promise<DeclinedOffer | null>

Mark an offer declined.

Guarded by to_account_id (IDOR). Returns null if the offer does not exist or belongs to a different account. Throws RoleGrantOfferAlreadyTerminalError if the offer exists for the caller but is already in a terminal state.

Returns the declined offer with the grantor's from_account_id joined in via CTE โ€” the decline audit envelope populates both target_actor_id (the grantor actor) and target_account_id (the grantor account), satisfying the "both populated โ†’ same account" invariant the audit-log column comments describe.

deps

offer_id

type string

to_account_id

type string

reason

type string | null

returns

Promise<DeclinedOffer | null>

throws

  • RoleGrantOfferAlreadyTerminalError - if the offer is already accepted, declined, retracted, or superseded

query_role_grant_offer_find_pending
#

auth/role_grant_offer_queries.ts view source

(deps: QueryDeps, offer_id: string): Promise<RoleGrantOffer | null>

Look up a pending offer by id. Returns null if the offer is terminal, expired (server-side filter), or missing.

deps

offer_id

type string

returns

Promise<RoleGrantOffer | null>

query_role_grant_offer_history_for_account
#

auth/role_grant_offer_queries.ts view source

(deps: QueryDeps, account_id: string, limit?: number, offset?: number): Promise<RoleGrantOffer[]>

List every offer involving an account (either direction), newest first.

Includes terminal offers โ€” used by the grantor-side admin / history view.

deps

account_id

type string

limit

type number
default 100

offset

type number
default 0

returns

Promise<RoleGrantOffer[]>

query_role_grant_offer_list
#

auth/role_grant_offer_queries.ts view source

(deps: QueryDeps, to_account_id: string): Promise<RoleGrantOffer[]>

List pending, non-expired offers for an account, soonest expiry first.

Expired offers are filtered server-side (expires_at > NOW()) so the inbox never surfaces a row that can no longer be accepted. The periodic sweep (query_role_grant_offer_sweep_expired) handles audit tombstoning.

deps

to_account_id

type string

returns

Promise<RoleGrantOffer[]>

query_role_grant_offer_retract
#

auth/role_grant_offer_queries.ts view source

(deps: QueryDeps, offer_id: string, from_actor_id: string): Promise<RoleGrantOffer | null>

Mark an offer retracted by the grantor.

Guarded by from_actor_id (IDOR). Returns null if the offer does not exist or was issued by a different actor. Throws RoleGrantOfferAlreadyTerminalError if the offer exists for this grantor but is already in a terminal state.

deps

offer_id

type string

from_actor_id

type string

returns

Promise<RoleGrantOffer | null>

throws

  • RoleGrantOfferAlreadyTerminalError - if the offer is already accepted, declined, retracted, or superseded

query_role_grant_offer_sweep_expired
#

auth/role_grant_offer_queries.ts view source

(deps: QueryDeps): Promise<RoleGrantOffer[]>

Return pending offers whose expires_at has passed.

Callers fire role_grant_offer_expire audit events for each row. The schema does not tombstone the row, so callers are responsible for their own idempotency (e.g. check whether a role_grant_offer_expire audit event already exists for the offer id).

deps

returns

Promise<RoleGrantOffer[]>

query_role_grant_revoke_for_scope
#

auth/role_grant_queries.ts view source

(deps: QueryDeps, scope_id: string & $brand<"Uuid">, revoked_by: (string & $brand<"Uuid">) | null, reason?: string | null | undefined): Promise<RevokeForScopeResult>

Revoke every active role_grant bound to a scope and supersede every pending offer at the scope, in one cascade.

Use this from a consumer's parent-scope delete handler (e.g., classroom deletion) โ€” role_grant.scope_id and role_grant_offer.scope_id are polymorphic with no FK constraint by design, so a parent row deletion would otherwise orphan role_grants and offers. The cascade is role-agnostic: anything attached to the destroyed scope is cleaned up.

Both updates run as separate statements inside the caller's transaction (mirrors query_role_grant_revoke_role's shape). The two halves are independent โ€” orphan pending offers can exist at a scope with no active role_grants, so the supersede half always runs even when no role_grant was revoked.

deps

query dependencies

scope_id

the scope whose role_grants and offers to terminate

type string & $brand<"Uuid">

revoked_by

the actor performing the cascade (audit trail)

type (string & $brand<"Uuid">) | null

reason?

optional free-form reason, stamped on role_grant.revoked_reason.

type string | null | undefined
optional

returns

Promise<RevokeForScopeResult>

the revoked role_grants (with account_id for fan-out) and superseded offers (with from_account_id for fan-out)

query_role_grant_revoke_role
#

auth/role_grant_queries.ts view source

(deps: QueryDeps, actor_id: string, role: string, revoked_by: string | null, reason?: string | null | undefined): Promise<RevokeRoleResult>

Revoke every active role_grant an actor holds for a given role.

With scoped role_grants a single actor+role tuple can hold several active role_grants (one per scope), so this revokes all of them. Pass query_revoke_role_grant(role_grant_id, ...) when a single scoped role_grant is the target.

Also supersedes pending offers for the actor's account across every scope of this role (the actor can no longer hold the role, so any pending offer of the same role is a bypass vector).

deps

query dependencies

actor_id

the actor whose role_grants to revoke

type string

role

the role to revoke

type string

revoked_by

the actor who revoked it (for audit trail)

type string | null

reason?

optional free-form reason, stamped on role_grant.revoked_reason.

type string | null | undefined
optional

returns

Promise<RevokeRoleResult>

the list of revoked role_grants (empty if none were active) and superseded pending offers

query_schema_snapshot
#

testing/schema_introspect.ts view source

(db: Db, options?: QuerySchemaSnapshotOptions): Promise<SchemaSnapshot>

Introspect a live database into a deterministic SchemaSnapshot.

Reads information_schema and pg_catalog to capture tables, columns, indexes, constraints, sequences, and schema_version migration tracker rows. The applied_at timestamp is deliberately excluded โ€” only the set of applied migrations matters for parity.

The schema_version table itself never appears in the tables field; its structure is identical across consumers and would only add noise.

db

type Db

options

default {}

returns

Promise<SchemaSnapshot>

throws

  • Error - when the `schema_version` table is missing โ€” callers must

query_session_cleanup_expired
#

query_session_enforce_limit
#

auth/session_queries.ts view source

(deps: QueryDeps, account_id: string, max_sessions: number): Promise<number>

Enforce a per-account session limit by evicting the oldest sessions.

Keeps the newest max_sessions sessions and deletes the rest.

Race safety: this function must run inside a transaction alongside the INSERT that created the new session. All callers satisfy this requirement: - POST /login uses the default transaction: true (framework-managed transaction wrapping in apply_route_specs) - The account_token_create RPC handler runs under the dispatcher's transaction path because its spec declares side_effects: true - POST /bootstrap and POST /signup manage their own transactions and pass the transaction-scoped deps to create_session_and_set_cookie

The transaction ensures the INSERT + enforce_limit pair is atomic โ€” concurrent session creation cannot interleave between the two statements.

deps

query dependencies (must be transaction-scoped)

account_id

the account to enforce the limit for

type string

max_sessions

maximum number of sessions to keep

type number

returns

Promise<number>

the number of sessions evicted

query_session_get_valid
#

auth/session_queries.ts view source

(deps: QueryDeps, token_hash: string): Promise<AuthSession | undefined>

Get a session if it exists, is not expired, and has not been revoked.

deps

query dependencies

token_hash

blake3 hash of the session token

type string

returns

Promise<AuthSession | undefined>

query_session_list_all_active
#

auth/session_queries.ts view source

(deps: QueryDeps, limit?: number): Promise<(AuthSession & { username: string; })[]>

List all active sessions across all accounts with usernames.

deps

query dependencies

limit

maximum entries to return

type number
default 200

returns

Promise<(AuthSession & { username: string; })[]>

active sessions joined with account usernames, newest activity first

query_session_list_for_account
#

auth/session_queries.ts view source

(deps: QueryDeps, account_id: string, limit?: number): Promise<AuthSession[]>

List sessions for an account, newest first.

deps

account_id

type string

limit

type number
default 50

returns

Promise<AuthSession[]>

query_session_revoke_all_for_account
#

auth/session_queries.ts view source

(deps: QueryDeps, account_id: string): Promise<number>

Revoke all sessions for an account.

deps

account_id

type string

returns

Promise<number>

the number of sessions revoked

query_session_revoke_by_hash_unscoped
#

auth/session_queries.ts view source

(deps: QueryDeps, token_hash: string): Promise<void>

Revoke (delete) a session by its token hash, with no account scoping.

The _unscoped suffix is the safety signal โ€” there is no account_id constraint, so callers must guarantee the hash came from a trusted source (the authenticated session cookie path is the only safe production caller โ€” see auth/account_routes.ts /logout). For user-facing revocation of a specific session by ID, use query_session_revoke_for_account (IDOR-guarded).

deps

token_hash

type string

returns

Promise<void>

query_session_revoke_for_account
#

auth/session_queries.ts view source

(deps: QueryDeps, token_hash: string, account_id: string): Promise<boolean>

Revoke a session only if it belongs to the specified account.

Prevents cross-account session revocation.

deps

query dependencies

token_hash

blake3 hash of the session token

type string

account_id

the account that must own the session

type string

returns

Promise<boolean>

true if a session was revoked, false if not found or wrong account

query_session_touch
#

query_update_account_password
#

auth/account_queries.ts view source

(deps: QueryDeps, id: string, password_hash: string, updated_by: string | null, expected_hash: string): Promise<boolean>

Update the password hash for an account, conditional on the current stored hash matching expected_hash โ€” the verify-write atomic guard.

The condition closes the race where two concurrent password changes both verify against the pre-update hash (loaded by the authorization phase outside the route's transaction) and would otherwise both UPDATE, silently clobbering whichever lands first. With the conditional WHERE, the second UPDATE matches zero rows; the route reads the boolean return and surfaces 401 instead of pretending success.

Pass the same hash the verify ran against โ€” typically ctx.account.password_hash from the request context.

deps

id

type string

password_hash

type string

updated_by

type string | null

expected_hash

type string

returns

Promise<boolean>

true if the row was updated, false if expected_hash no longer matched (concurrent change won โ€” caller should treat as a stale-credential failure).

query_validate_api_token
#

auth/api_token_queries.ts view source

(deps: ApiTokenQueryDeps, raw_token: string, ip: string | undefined, pending_effects: Promise<void>[] | undefined): Promise<ApiToken | undefined>

Validate a raw API token and return the token record.

Hashes the token with blake3, looks up the hash, and checks expiration. Updates last_used_at and last_used_ip on success (fire-and-forget โ€” errors logged, never thrown).

deps

query dependencies with logger

raw_token

the raw API token from the Authorization header

type string

ip

the client IP address (for audit)

type string | undefined

pending_effects

optional array to register the usage-tracking effect for later awaiting

type Promise<void>[] | undefined

returns

Promise<ApiToken | undefined>

the token record if valid, or undefined

QueryDeps
#

QuerySchemaSnapshotOptions
#

testing/schema_introspect.ts view source

QuerySchemaSnapshotOptions

Filter options for query_schema_snapshot.

schema

Schema name to introspect โ€” defaults to 'public'. Single-schema only; cross-schema introspection isn't a current need.

type string
readonly

exclude_tables

Tables to exclude from the snapshot. The schema_version table itself is always excluded (its content is captured separately).

type ReadonlyArray<string>
readonly

rate_limit_exceeded_response
#

rate_limiter.ts view source

(c: Context<any, any, {}>, retry_after: number): Response

Build a 429 rate-limit-exceeded JSON response with Retry-After header.

c

Hono context

type Context<any, any, {}>

retry_after

seconds until the client should retry

type number

returns

Response

a 429 Response

RateLimiter
#

rate_limiter.ts view source

In-memory sliding window rate limiter.

Stores an array of timestamps per key. On check/record, timestamps outside the window are pruned. retry_after reports seconds until the oldest active timestamp expires.

The backing store is an LruMap when options.max_keys is a positive number (default DEFAULT_RATE_LIMITER_MAX_KEYS) and a plain Map when max_keys is null. The LruMap path bounds memory under key-enumeration attack at the cost of a slight per-op overhead and the LRU trade-off described on RateLimiterOptions.max_keys.

Parameters that accept RateLimiter | null (e.g. ip_rate_limiter, login_account_rate_limiter) silently disable rate limiting when null is passed โ€” no checks are performed and all requests are allowed through.

options

type RateLimiterOptions

readonly

constructor

type new (options: RateLimiterOptions): RateLimiter

options

check

Check whether key is allowed without recording an attempt.

Prunes timestamps that fell outside the window as a side effect (and removes the key entirely when none remain), so the backing map stays bounded even under read-only traffic.

type (key: string, now?: number): RateLimitResult

key

rate limit key (e.g. IP address)

type string
now

current timestamp in ms (defaults to Date.now())

type number
default Date.now()

record

Record a failed attempt for key and return the updated result.

type (key: string, now?: number): RateLimitResult

key

rate limit key (e.g. IP address)

type string
now

current timestamp in ms (defaults to Date.now())

type number
default Date.now()

reset

Clear all attempts for key (e.g. after successful login).

type (key: string): void

key
type string
returns void

cleanup

Remove entries whose timestamps are all outside the window.

type (now?: number): void

now

current timestamp in ms (defaults to Date.now())

type number
default Date.now()
returns void

dispose

Stop the cleanup timer. Safe to call multiple times.

type (): void

returns void

RateLimiterOptions
#

rate_limiter.ts view source

RateLimiterOptions

Configuration for a rate limiter instance.

max_attempts

Maximum allowed attempts within the window.

type number

window_ms

Sliding window duration in milliseconds.

type number

cleanup_interval_ms

Interval for pruning stale entries (0 disables the timer).

type number

max_keys

Maximum tracked keys. When exceeded, the least-recently-used key is evicted โ€” bounds memory under key-enumeration attacks. Default: DEFAULT_RATE_LIMITER_MAX_KEYS (100_000). Pass null to disable the cap (falls back to an unbounded Map โ€” only recommended when the key set is known to be closed, e.g. a per-account limiter keyed to a bounded-size account table).

LRU trade-off: every check / record call marks the key as most-recently-used, so keys under active attack stay fresh and won't be evicted. A slow-burn attacker spread across many low-volume keys can, however, drop out of the table and reset their budget โ€” set max_keys high enough to fit the expected legitimate key set and this stays theoretical.

type number | null

RateLimitError
#

http/error_schemas.ts view source

ZodObject<{ error: ZodLiteral<"rate_limit_exceeded">; retry_after: ZodNumber; }, $loose>

Rate limit error โ€” returned when a rate limiter rejects the request.

RateLimitingTestOptions
#

testing/rate_limiting.ts view source

RateLimitingTestOptions

Configuration for describe_rate_limiting_tests.

session_options

Session config for cookie-based auth.

type SessionOptions<string>

create_route_specs

Route spec factory โ€” same one used in production.

type (ctx: AppServerContext) => Array<RouteSpec>

app_options

Optional overrides for AppServerOptions.

db_factories

Database factories to run tests against. Default: pglite only.

type Array<DbFactory>

max_attempts

Maximum attempts before rate limiting kicks in. Default: 2 (tight limit for fast tests).

type number

rpc_endpoints

RPC endpoint specs โ€” required so the bearer-auth rate limiting test can probe an authenticated method via the account_verify RPC action. Hard-fails via require_rpc_endpoint_path on setup.

Accepts either an array (eager) or a factory (ctx: AppServerContext) => Array<RpcEndpointSpec> โ€” the factory form is required when action handlers must close over the per-test ctx.app_settings / ctx.deps. The factory must return the same endpoint path regardless of ctx โ€” it is invoked once at setup with a stub ctx for path lookup and again per-test by create_app_server for live dispatch.

RateLimitKey
#

http/error_schemas.ts view source

ZodEnum<{ both: "both"; account: "account"; ip: "ip"; }>

Rate limit key type โ€” declares what a route or RPC action's rate limiter is keyed on.

- 'ip' โ€” per-IP rate limiting (bootstrap, password change, bearer auth) - 'account' โ€” per-account rate limiting. On REST auth routes the key is the submitted identifier (login). On RPC actions (post-auth) the key is the resolved actor id (request_context.actor.id) โ€” separate namespace. - 'both' โ€” both keys.

RateLimitResult
#

rate_limiter.ts view source

RateLimitResult

Result of a rate limit check or record operation.

allowed

Whether the request is allowed.

type boolean

remaining

Remaining attempts before blocking.

type number

retry_after

Seconds until the oldest active attempt expires (0 if allowed).

type number

read_daemon_info
#

cli/daemon.ts view source

(runtime: Pick<EnvDeps, "env_get"> & Pick<FsReadDeps, "stat" | "read_text_file"> & LogDeps, name: string): Promise<{ version: number; pid: number; port: number; started: string; app_version: string; } | null>

Read and validate daemon info from the PID file.

runtime

runtime with file read and env capabilities

type Pick<EnvDeps, "env_get"> & Pick<FsReadDeps, "stat" | "read_text_file"> & LogDeps

name

application name

type string

returns

Promise<{ version: number; pid: number; port: number; started: string; app_version: string; } | null>

parsed daemon info, or null if missing or invalid

read_env_var
#

dev/setup.ts view source

(deps: Pick<FsReadDeps, "stat" | "read_text_file">, env_path: string, name: string): Promise<string | undefined>

Read a single env var from a dotenv-style file.

deps

file read capability

type Pick<FsReadDeps, "stat" | "read_text_file">

env_path

path to the .env file

type string

name

the variable name to read

type string

returns

Promise<string | undefined>

the value, or undefined if the file or variable doesn't exist

ReadTextFromOffsetResult
#

runtime/deps.ts view source

ReadTextFromOffsetResult

Result of reading text from a byte offset.

content

Decoded text content read from the offset.

type string

bytes_read

Number of bytes actually read.

type number

file_size

Total file size at the time of the read (for truncation detection).

type number

reconstruct_bootstrapped_handle
#

testing/cross_backend/setup.ts view source

(serialized: SerializableBootstrappedBackendHandle): ReconstructedBootstrappedBackendHandle

Rebuild a usable handle from the serialized subset. Synthesizes a fresh {@link FetchTransport} primed with the keeper's Set-Cookie values so _testing_reset and other keeper-authenticated calls work. The returned shape omits child and teardown โ€” lifecycle stays with globalSetup; tests that try to teardown themselves wouldn't have a serializable reference anyway.

serialized

returns

ReconstructedBootstrappedBackendHandle

ReconstructedBootstrappedBackendHandle
#

RecordedClose
#

RecordingAuditEmitter
#

testing/audit_drift_guard.ts view source

RecordingAuditEmitter

Pair returned by {@link create_recording_audit_emitter} โ€” the AuditEmitter to inject as deps.audit, plus the shared calls array that records every captured emission. Both fields are live โ€” callers read calls after exercising the handler to assert on the audit metadata shape.

emitter

calls

type Array<AuditLogInput>

RecordingCloser
#

refresh_role_grants
#

auth/request_context.ts view source

(ctx: RequestContext, deps: QueryDeps): Promise<RequestContext>

Reload active role_grants from the database, returning a new request context.

Useful for long-lived WebSocket connections where role_grants may change (grant or revoke) during the connection lifetime. Call periodically or after receiving a revocation signal.

Returns a new RequestContext with updated role_grants โ€” the original context is not mutated, making concurrent calls safe. Throws when ctx.actor is null; account-grain contexts have no role_grants to refresh.

ctx

the request context to refresh

deps

query dependencies

returns

Promise<RequestContext>

a new RequestContext with fresh role_grants

throws

  • Error - when called on an account-grain context (`actor: null`)

register_action_ws
#

actions/register_action_ws.ts view source

(options: RegisterActionWsOptions): RegisterActionWsResult

Mount a JSON-RPC WebSocket endpoint that dispatches via the shared perform_action core.

Wire behavior: - Batch JSON-RPC is rejected (single-message only). - Notifications (method + no id) are silently dropped per JSON-RPC spec. Exception: cancel notifications abort the matching pending request's ctx.signal before bubbling out. - Per-message dispatch goes through perform_action: pre-validation auth (401) โ†’ input validation (400) โ†’ authorization phase โ†’ post-authorization auth (403) โ†’ rate limit (429) โ†’ handler (with transaction wrap iff spec.side_effects: true) โ†’ DEV output validation. - Authorization phase runs per message โ€” role_grant changes during a connection lifetime are picked up on the next message without any in-place refresh. Authentication invalidation closes the socket via create_ws_auth_guard.

options

returns

RegisterActionWsResult

the transport (supplied or freshly created) โ€” retain it to wire create_ws_auth_guard or broadcast on audit events.

register_ws_endpoint
#

RegisterActionWsOptions
#

actions/register_action_ws.ts view source

RegisterActionWsOptions

Options for register_action_ws.

path

Mount path (e.g., /api/ws).

type string

app

The Hono app to mount on.

type Hono

upgradeWebSocket

Hono's upgradeWebSocket helper from the runtime adapter.

type UpgradeWebSocket

actions

The actions registered on this endpoint โ€” each carries a spec (drives method lookup, per-action auth, input/output validation) and an optional handler (omit for client-only specs like inbound notifications). Spread protocol_actions from actions/protocol.ts here to complete the disconnect-detection + per-request cancel pairing with the frontend client.

type ReadonlyArray<Action>

db

Pool-level DB. The dispatcher wraps in db.transaction for side_effects: true actions, the same way HTTP RPC does. Per-message authorization phase reads through this pool.

Audit writes and other rollback-resilient fire-and-forget calls run through AppDeps.audit.emit from the action factory's closure โ€” the dispatcher never holds an audit-side pool reference; the bound emitter owns the pool.

type Db

transport

Existing transport to register connections with. When omitted, a fresh one is created and returned in the result. Pass your own to keep a handle for create_ws_auth_guard and send_to/broadcast.

heartbeat

Server-side heartbeat policy. Default-on (receive-silence detection, 60s timeout). false disables the timer entirely โ€” only do this if the upstream stack (TCP keepalive, Cloudflare idle timeout, etc.) already owns disconnect detection. Pass an object to tune the timeout.

type boolean | ServerHeartbeatOptions

artificial_delay

Optional per-message delay for testing loading states. Ignored when 0.

type number

log

Optional logger; defaults to [ws] namespace.

type LoggerType

on_socket_open

Called once per socket, after the transport registers the connection. Awaited before any message is dispatched. Throwing logs an error and closes the socket with an internal_error frame โ€” a failing bootstrap should not leave a partially-initialized socket alive.

type (ctx: SocketOpenContext) => void | Promise<void>

on_socket_close

Called once per socket on close, *before* the transport removes the connection. Receives connection_id and identity captured at open time, so it is safe to read even when the audit guard has already torn down the transport's internal state. Errors are logged and swallowed.

type (ctx: SocketCloseContext) => void | Promise<void>

action_ip_rate_limiter

Per-IP rate limiter consulted for actions whose spec declares rate_limit: 'ip' or 'both'. null (or omitted) disables the IP check. Same limiter is shared with the HTTP RPC dispatcher so one budget covers both transports per action. Resolved at upgrade time and reused for every message on the socket.

type RateLimiter | null

action_account_rate_limiter

Per-account rate limiter consulted for actions whose spec declares rate_limit: 'account' or 'both'. Keyed on request_context.account.id. null (or omitted) disables the account check. Same limiter is shared with the HTTP RPC dispatcher.

type RateLimiter | null

RegisterActionWsResult
#

RegisterWsEndpointOptions
#

actions/register_ws_endpoint.ts view source

RegisterWsEndpointOptions

inheritance

allowed_origins

Origin allowlist regexes โ€” typically parsed from the FUZ_ALLOWED_ORIGINS env var via parse_allowed_origins. Passed straight to verify_request_source.

type ReadonlyArray<RegExp>

required_roles

Roles permitted to upgrade โ€” any-of disjunction (matches the underlying require_role semantics). Omit (or pass []) for any authenticated account (require_auth + actor resolution alone); set to e.g. [ROLE_ADMIN] to gate the endpoint behind a single role or [ROLE_ADMIN, ROLE_KEEPER] to permit either. The per-action auth in each spec still applies at dispatch time โ€” this is a coarse upgrade-time gate.

type ReadonlyArray<RoleName>

RemoteNotificationActionSpec
#

actions/action_spec.ts view source

ZodObject<{ method: ZodString; initiator: ZodEnum<{ frontend: "frontend"; backend: "backend"; both: "both"; }>; input: ZodCustom<ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>, ZodType<...>>; ... 8 more ...; async: ZodDefault<...>; }, $strict>

REQUEST_CONTEXT_KEY
#

RequestActorContext
#

auth/request_context.ts view source

RequestActorContext

Request context narrowed to a resolved acting actor.

Used by handlers bound through rpc_action against an actor-implying spec (auth.actor === 'required') โ€” the binder's conditional return type tightens ctx.auth to this shape because the dispatcher's authorization phase always resolves an actor before the handler runs. The biconditional actor !== 'none' โŸบ input declares acting?: ActingActor is enforced at registry time.

inheritance

actor

type Actor

RequestContext
#

auth/request_context.ts view source

RequestContext

The resolved identity context for an authenticated request.

actor is null on account-grain routes (no acting field on input, no role / keeper auth) โ€” those handlers don't trigger actor resolution. role_grants is empty in that case. Role grant checks (has_role, has_scoped_role, has_any_scoped_role) are null-tolerant on RequestContext | null; they additionally treat actor: null as "no role_grants" so callers don't have to narrow.

Multi-actor invariant: when populated, actor.account_id === account.id. build_request_context enforces this; the dispatcher's authorization phase rejects with actor_not_on_account before reaching the handler.

account

type Account

actor

type Actor | null

role_grants

type Array<RoleGrant>

RequestResponseActionSpec
#

actions/action_spec.ts view source

ZodObject<{ method: ZodString; initiator: ZodEnum<{ frontend: "frontend"; backend: "backend"; both: "both"; }>; side_effects: ZodBoolean; input: ZodCustom<ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>, ZodType<...>>; ... 7 more ...; async: ZodDefault<...>; }, $strict>

RequestTracker
#

actions/request_tracker.svelte.ts view source

Reactive pending-request store with per-request timeouts. Used by transports that don't delegate request/response correlation to a WebsocketRpcConnection.

pending_requests

type SvelteMap<JsonrpcRequestId, RequestTrackerItem>

readonly

request_timeout_ms

type number

readonly

constructor

type new (request_timeout_ms?: number): RequestTracker

request_timeout_ms
type number
default 120_000

track_request

Track a new request keyed by id.

type (id: string | number): Deferred<{ [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; } | { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | ... 4 more ... | (number & $brand<...>); message: string; data?: unknown; }; }>

id
type string | number
returns Deferred<{ [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; } | { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<...>); message: string; data?: unknown; }; }>

deferred resolved on response, or rejected via the timeout

resolve_request

Resolve a pending request with its response.

type (id: string | number, response: { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; } | { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | ... 4 more ... | (number & $brand<...>); message: string; data?: unknown; }; }): void

id
type string | number
response
type { [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; } | { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<...>); message: string; data?: unknown; }; }
returns void

reject_request

Reject a pending request with error_message.

type (id: string | number, error_message: { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<"JsonrpcServerErrorCode">); message: string; data?: unknown; }; }): void

id
type string | number
error_message
type { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<"JsonrpcServerErrorCode">); message: string; data?: unknown; }; }
returns void

handle_message

Handles an incoming JSON-RPC message. Resolves or rejects the associated request. Ignores notifications and unknown/invalid messages.

type (message: any): void

message
type any
returns void

cancel_request

Cancel a pending request without rejecting its deferred โ€” just cleanup. The caller's promise stays unsettled; pair with an external resolution if needed.

type (id: string | number): void

id
type string | number
returns void

cancel_all_requests

Cancel all pending requests.

type (reason?: string | undefined): void

reason?

optional reason to include in rejection

type string | undefined
optional
returns void

RequestTrackerItem
#

actions/request_tracker.svelte.ts view source

id

type JsonrpcRequestId

readonly

deferred

type Deferred<JsonrpcResponseOrError>

readonly

created

type Datetime

readonly

status

type AsyncStatus

timeout

type NodeJS.Timeout | undefined

constructor

type new (id: string | number, deferred: Deferred<{ [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; } | { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | ... 4 more ... | (number & $brand<...>); message: string; data?: unknown; }; }>, created: Datetime, status: AsyncStatus, timeout: Timeout | undefined): RequestTrackerItem

id
type string | number
deferred
type Deferred<{ [x: string]: unknown; jsonrpc: "2.0"; id: string | number; result: JSONType; } | { [x: string]: unknown; jsonrpc: "2.0"; id: string | number | null; error: { [x: string]: unknown; code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<...>); message: string; data?: unknown; }; }>
created
type Datetime
status
type AsyncStatus
timeout
type Timeout | undefined

require_audit_sse
#

server/app_server.ts view source

(source: { audit_sse: AuditLogSse | null; }): AuditLogSse

Assert that audit_sse was wired by create_app_server and return it as a non-null AuditLogSse. Throws a labelled error when the audit_log_sse option was not passed to create_app_server.

Use in route factories that depend on factory-managed audit SSE:

create_route_specs: (ctx) => create_audit_log_route_specs({ stream: require_audit_sse(ctx), }),

Preferred over ctx.audit_sse! โ€” ! lies to the type system and produces a downstream cannot-read-property crash if a consumer wires the route without enabling the option.

source

type { audit_sse: AuditLogSse | null; }

returns

AuditLogSse

require_auth
#

auth/request_context.ts view source

(c: Context<any, string, {}>, next: Next): Promise<void | Response>

Middleware that requires authentication.

Returns 401 if the auth middleware did not set c.var.auth_account_id.

c

type Context<any, string, {}>

next

type Next

returns

Promise<void | Response>

require_credential_types
#

auth/request_context.ts view source

(credential_types: readonly string[]): MiddlewareHandler

Create middleware that requires the request's credential_type to be one of the given values.

Returns 401 if unauthenticated, 403 with ERROR_CREDENTIAL_TYPE_REQUIRED + required_credential_types echoing the spec's allowlist when the wire-side credential isn't in it. Body shape is symmetric with the role gate (ERROR_INSUFFICIENT_PERMISSIONS + required_roles) and matches what the RPC dispatcher's post-auth gate emits for the same condition. Today's only credential gate is keeper (['daemon_token']); future gates (agent_token, group_actor_token) reuse this literal and label themselves through the array.

credential_types

allowed credential types (any-of)

type readonly string[]

returns

MiddlewareHandler

require_request_context
#

auth/request_context.ts view source

(c: Context<any, any, {}>): RequestContext

Get the request context, throwing if unauthenticated.

Use in route handlers where the dispatcher's authorization phase guarantees a context exists (i.e., routes with auth: {type: 'authenticated'} or stricter). Prefer this over get_request_context(c)! for explicit error handling.

c

the Hono context

type Context<any, any, {}>

returns

RequestContext

the request context (never null)

throws

  • Error - if no request context is set (dispatcher misconfiguration)

require_role
#

auth/request_context.ts view source

(roles: readonly string[]): MiddlewareHandler

Create middleware that requires the actor to hold any of the given roles globally (scope_id IS NULL).

Returns 401 if unauthenticated, 403 if none of the roles are present. Reads REQUEST_CONTEXT_KEY because role-gated routes always run the dispatcher's authorization phase before this guard (the phase sets the actor-bound RequestContext).

Uses has_any_scoped_role(ctx, roles, null) so the gate matches global / unscoped role_grants only. A scoped role_grant ({role: 'admin', scope_id: <some uuid>}) does not unlock route-spec gates that are inherently global. The same scope-aware check is mirrored in actions/action_rpc.ts (HTTP RPC dispatcher) and actions/register_action_ws.ts (WS dispatcher) so all three transports agree.

Multi-role disjunction (any-of) lets auth.roles: ['admin', 'steward'] specs translate to one middleware that admits either role. Single-role routes pass [role_name]; the array shape is uniform.

roles

the roles to admit (any-of)

type readonly string[]

returns

MiddlewareHandler

require_rpc_endpoint_path
#

testing/rpc_helpers.ts view source

(rpc_endpoints: readonly RpcEndpointSpec[]): string

Resolve a single RPC endpoint path โ€” the common case where a consumer mounts exactly one create_rpc_endpoint.

Used at suite setup time to hard-fail integration suites (admin / audit / SSE / rate-limiting) when the consumer omitted rpc_endpoints rather than letting tests fail mid-run with confusing errors.

Callers that need multi-endpoint support should iterate rpc_endpoints directly.

rpc_endpoints

type readonly RpcEndpointSpec[]

returns

string

throws

  • Error - if `rpc_endpoints` is empty (hard-fail; see the suite options

reserved_migration_namespaces
#

auth/migrations.ts view source

readonly string[]

Migration namespaces reserved by fuz_app. Consumers passing migration_namespaces to create_app_backend must choose a name not in this list โ€” the runtime check rejects matches with a thrown error. Typed as ReadonlyArray<string> (not a literal tuple) so .includes() accepts any consumer-supplied namespace string without a cast.

reset_audit_metadata_validation_failures
#

reset_audit_unknown_event_type_failures
#

reset_bootstrap_token
#

dev/setup.ts view source

(deps: FsReadDeps & FsWriteDeps & FsRemoveDeps & CommandDeps & EnvDeps, app_name: string, options?: SetupBootstrapTokenOptions | undefined): Promise<...>

Remove an existing bootstrap token and create a new one.

deps

file, command, env, and remove capabilities

type FsReadDeps & FsWriteDeps & FsRemoveDeps & CommandDeps & EnvDeps

app_name

application name

type string

options?

state_dir override, permissions, logger

type SetupBootstrapTokenOptions | undefined
optional

returns

Promise<SetupTokenResult>

result from creating the new token

reset_database
#

dev/setup.ts view source

(deps: CommandDeps & FsReadDeps & FsRemoveDeps, database_url: string, options?: ResetDatabaseOptions | undefined): Promise<...>

Reset a database to a clean slate.

For PostgreSQL: drops and recreates the database. For pglite: removes the data directory if pglite_data_dir is provided. For empty/missing URLs: skips.

deps

command and file capabilities

type CommandDeps & FsReadDeps & FsRemoveDeps

database_url

the DATABASE_URL value

type string

options?

pglite_data_dir, logger

type ResetDatabaseOptions | undefined
optional

returns

Promise<ResetDbResult>

result describing what happened

reset_mock_runtime
#

reset_pglite
#

testing/db.ts view source

(db: Db): Promise<void>

Reset a PGlite database to a clean state by dropping and recreating the public schema.

Removes all tables, sequences, indexes, types, and functions. The database instance remains usable after reset.

db

type Db

returns

Promise<void>

ResetDatabaseOptions
#

ResetDbResult
#

dev/setup.ts view source

ResetDbResult

Result of reset_database.

reset

Whether the database was actually reset.

type boolean

skipped

Whether the operation was skipped (e.g. pglite with no data dir).

type boolean

db_type

What type of database was detected.

type 'postgres' | 'pglite' | 'none'

resolve_acting_actor
#

auth/request_context.ts view source

(deps: QueryDeps, account_id: string, acting_actor_id: string | undefined): Promise<ResolveActingActorResult>

Resolve the acting actor for an authenticated request.

Called from the route-spec / RPC dispatcher's authorization phase with the authenticated account id and the validated acting value (from the request payload). Applies the uniform resolution rules:

- acting_actor_id omitted + 1 actor โ†’ use it. - acting_actor_id omitted + 0 actors โ†’ no_actors (defensive โ€” signup / bootstrap always create an actor in the same tx, so this is a server error). - acting_actor_id omitted + multiple actors โ†’ actor_required with the available list so the client can prompt; never pick silently. - acting_actor_id present + matches an actor on the account โ†’ use it. - acting_actor_id present + does not match โ†’ actor_not_on_account. The available list is intentionally not echoed in this branch (treat as opaque rejection).

deps

query dependencies

account_id

the authenticated account

type string

acting_actor_id

the requested acting actor id, or undefined

type string | undefined

returns

Promise<ResolveActingActorResult>

resolve_client_ip
#

http/proxy.ts view source

(forwarded_for: string, proxies: ParsedProxy[]): string | undefined

Resolve the real client IP from an X-Forwarded-For header value.

Walks right-to-left, skipping trusted proxy entries AND any entry that fails strict IP validation (validate_ip_strict). The first untrusted, strictly-valid entry is the client IP. If every walked entry is trusted or malformed, returns the leftmost strictly-valid (trusted) entry (likely-misconfigured all-trusted case) or undefined (everything was malformed โ€” middleware falls back to the connection IP). All entries are normalized before matching and in the returned value.

Skipping malformed entries is the rate-limit-key fix for the "attacker controls XFF and the proxy passes it through" surface โ€” without the skip, an attacker could rotate arbitrary strings (incl. 'attacker:controlled', which Hono's lax distinctRemoteAddr misclassifies as IPv6) as XFF values to get fresh per-IP rate-limit buckets. Tradeoff: legitimate non-standard proxies that include ports in XFF entries (e.g. 203.0.113.1:8080) also fail strict validation, so those entries get skipped and the rate-limit bucket collapses to the proxy's connection IP (one bucket for everyone behind that proxy). Standard proxies (nginx, cloud LBs) don't include ports.

forwarded_for

the X-Forwarded-For header value

type string

proxies

parsed trusted proxy entries

type ParsedProxy[]

returns

string | undefined

the normalized client IP, or undefined if the header is empty / all entries malformed

resolve_env_vars
#

env/resolve.ts view source

(runtime: Pick<EnvDeps, "env_get">, value: string): string

Resolve environment variable references in a string.

- $$VAR$$ resolves from the runtime env; missing values are left as-is for the validation phase to report. - $$?VAR$$ is the optional form โ€” missing or empty resolves to the empty string. Required validation skips refs marked optional. - \$$VAR$$ / \$$?VAR$$ are escapes โ€” the leading backslash is dropped and the body is emitted literally (no resolution attempted).

runtime

runtime with env_get capability

type Pick<EnvDeps, "env_get">

value

string that may contain $$VAR$$ references

type string

returns

string

string with env vars resolved

resolve_env_vars_in_object
#

env/resolve.ts view source

<T extends Record<string, unknown>>(runtime: Pick<EnvDeps, "env_get">, obj: T): T

Resolve env vars in an object's string values (shallow).

runtime

runtime with env_get capability

type Pick<EnvDeps, "env_get">

obj

object with string values

type T

returns

T

new object with env vars resolved

resolve_env_vars_required
#

env/resolve.ts view source

(runtime: Pick<EnvDeps, "env_get">, value: string, context: string): string

Resolve env vars and throw if any are missing/empty.

Use this for values that must be present. $$?VAR$$ (optional) refs resolve to the empty string on miss without contributing to the error. Escaped references (\$$VAR$$) emit literally and never check the env.

runtime

runtime with env_get capability

type Pick<EnvDeps, "env_get">

value

string with $$VAR$$ references

type string

context

description for error message (e.g., "target.host")

type string

returns

string

resolved string

throws

  • Error - if any referenced env var is missing or empty

resolve_fixture_path
#

testing/assertions.ts view source

(filename: string, import_meta_url: string): string

Resolve an absolute path relative to the caller's module.

filename

type string

import_meta_url

the caller's import.meta.url

type string

returns

string

resolve_keeper_account_id
#

auth/daemon_token_middleware.ts view source

(deps: QueryDeps): Promise<string | null>

Resolve the keeper account ID by querying for the account with an active keeper role_grant.

There is exactly one keeper account (the bootstrap account). Runs once at server startup โ€” the result is cached in DaemonTokenState.keeper_account_id. The acting actor is resolved per-request by the dispatcher's authorization phase (which runs resolve_acting_actor against this account id), so multi-actor keeper accounts surface actor_required if a daemon caller doesn't pass an explicit acting.

deps

query dependencies

returns

Promise<string | null>

the keeper account ID, or null if no keeper exists yet (pre-bootstrap)

resolve_rpc_endpoints_for_setup
#

testing/rpc_helpers.ts view source

(rpc_endpoints: RpcEndpointsSuiteOption, session_options: SessionOptions<string>): RpcEndpointSpec[]

Resolve a suite's rpc_endpoints option to an array for setup-time inspection (path lookup, action presence checks).

For the factory form this invokes the factory twice with stub AppServerContexts and asserts that both invocations produce the same (path, method-list) shape โ€” catching factories that close over mutable state or otherwise diverge across calls. The first array is returned; the second is discarded after the comparison. create_app_server invokes the factory again per-test with its real ctx, and those are the handlers that actually serve requests.

Safe as long as the factory is pure with respect to the endpoint path and the action spec.method list โ€” the canonical helpers (create_standard_rpc_actions, create_admin_actions, create_account_actions, etc.) are. Factories that return a different path based on ctx will produce a setup/runtime mismatch; the path-purity assert below surfaces that as a clear gro check error rather than a silent test/runtime drift.

rpc_endpoints

session_options

type SessionOptions<string>

returns

RpcEndpointSpec[]

throws

  • Error - if the factory's two stub-ctx invocations produce different

resolve_scope_label
#

ui/format_scope.ts view source

<G extends string | null>(scope_id: string | null, role: string, format_scope: FormatScope, global_label: G): string | G

Resolve a scope label across the context โ†’ raw-uuid fallback chain.

global_label is returned for scope_id === null. Callers pass null to render no chip (admin tables โ€” global is the implicit default) or 'global' for explicit labels (offer surfaces). The return type propagates null only when global_label is null.

scope_id

type string | null

role

type string

format_scope

global_label

type G

returns

string | G

resolve_spec_qualifier
#

actions/action_codegen.ts view source

(imports: ImportBuilder, options?: { specs_module?: string | undefined; qualify_spec?: ((spec: { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; ... 8 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }) => string) | undefined; } | undefined): (spec: { ...; } | ... 1 more ... | { ...; }) => string

Resolve a per-spec identifier qualifier with the standard default-vs-callback dance. When qualify_spec is set, returns the caller's callback verbatim and registers no imports โ€” the caller owns its namespace setup (the multi-source case where specs come from several modules). Otherwise, registers * as specs from specs_module (defaulting to './action_specs.js') on imports and returns (spec) => 'specs.' + to_action_spec_identifier(spec.method).

Used internally by every multi-source-aware helper in this module (generate_action_specs_record, generate_action_inputs_outputs, generate_backend_actions_api); exported so consumers writing their own codegen helpers can reuse the same defaulting + import-registration behavior instead of reimplementing it.

imports

options?

type { specs_module?: string | undefined; qualify_spec?: ((spec: { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 7 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }) => string)...
optional

returns

(spec: { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | {...

resolve_standard_error_schema_tightness
#

testing/attack_surface.ts view source

(consumer: ErrorSchemaTightnessOptions | null | undefined): ErrorSchemaTightnessOptions | null

Merge a consumer's error_schema_tightness option with default_error_schema_tightness so allowlist and ignore_statuses are additive rather than replacing.

- undefined โ†’ return the default as-is. - null โ†’ return null (opt out of the assertion). - object โ†’ spread the default, then consumer overrides for scalar fields (min_specificity), then concat stock-then-consumer for the list fields (allowlist, ignore_statuses) so consumer entries extend rather than replace.

Exported for direct use when a consumer calls assert_error_schema_tightness outside the standard suite but still wants the additive merge.

consumer

type ErrorSchemaTightnessOptions | null | undefined

returns

ErrorSchemaTightnessOptions | null

resolve_test_path
#

testing/auth_apps.ts view source

(path: string): string

Replace Hono route params (:foo) with dummy values for HTTP testing.

path

type string

returns

string

resolve_valid_path
#

testing/schema_generators.ts view source

(path: string, params_schema?: ZodObject<$ZodLooseShape, $strip> | undefined): string

Resolve a route path with valid-ish param values so params validation passes. Used when testing input on routes that also have params.

path

type string

params_schema?

type ZodObject<$ZodLooseShape, $strip> | undefined
optional

returns

string

ResolveActingActorResult
#

rest_auth_route_suffixes
#

testing/integration_helpers.ts view source

readonly ["/login", "/logout", "/password", "/verify", "/signup", "/bootstrap"]

REST auth route suffixes on the account/bootstrap surface โ€” the only routes still REST. find_auth_route rejects any other suffix at runtime; session/token CRUD, admin operations, and role_grant flows live on the RPC surface and should be reached via rpc_call.

RestAuthRouteSuffix
#

RevokeForScopeResult
#

auth/role_grant_queries.ts view source

RevokeForScopeResult

Result of query_role_grant_revoke_for_scope โ€” every role_grant revoked plus every pending offer superseded by the scope-wide cascade.

revoked

One entry per role_grant revoked by this call. Carries both the revokee's actor_id (the role_grant's grantee โ€” drives target_actor_id audit envelopes) and account_id (the actor's account โ€” drives target_account_id for SSE/WS socket-close fan-out). Empty array means no active role_grant was bound to the scope. scope_kind is surfaced for forensic completeness; the cascade itself keys on scope_id regardless of kind.

type Array<{ role_grant_id: Uuid; role: string; scope_kind: string | null; scope_id: Uuid; actor_id: Uuid; account_id: Uuid; }>

superseded_offers

Every pending offer at the scope โ€” tuple-matched and orphan, undifferentiated โ€” superseded in the same cascade. Each entry carries its grantor's from_account_id for role_grant_offer_supersede notification fan-out.

The caller is responsible for emitting role_grant_offer_supersede audit events with reason: 'scope_destroyed' and cause_id: <destroyed scope row id> per entry โ€” the cause of every supersede here is the scope deletion, not any individual role_grant revoke (the revokes are themselves consequences of the scope going away).

type Array<SupersededOffer>

RevokeRoleGrantResult
#

auth/role_grant_queries.ts view source

RevokeRoleGrantResult

Result of query_revoke_role_grant โ€” the revoked role_grant plus any pending offers superseded by the revoke.

id

type Uuid

role

type string

scope_kind

type string | null

scope_id

type Uuid | null

superseded_offers

Pending offers for the revoked role_grant's (account, role, scope) that were marked superseded as a side effect. Each entry carries its grantor's from_account_id so callers can fan out role_grant_offer_supersede notifications without a second round-trip. The caller is responsible for emitting a role_grant_offer_supersede audit event per entry (with reason: 'role_grant_revoked' and cause_id: <revoked role_grant id>).

type Array<SupersededOffer>

RevokeRoleResult
#

auth/role_grant_queries.ts view source

RevokeRoleResult

Result of query_role_grant_revoke_role โ€” every role_grant revoked plus the pending offers superseded by the bulk revoke.

revoked

One entry per role_grant revoked by this call. Carries the revokee's account_id so callers can fan out a role_grant_revoke notification per scope-instance. Empty array means nothing was active for (actor, role).

type Array<{ role_grant_id: string; role: string; scope_kind: string | null; scope_id: string | null; account_id: string; }>

superseded_offers

Pending offers for the actor's account+role (all scopes) superseded by the bulk revoke. Each entry carries its grantor's from_account_id so callers can fan out role_grant_offer_supersede notifications without a second round-trip.

type Array<SupersededOffer>

ROLE_ADMIN
#

ROLE_GRANT_INDEXES
#

role_grant_offer_accept_action_spec
#

auth/role_grant_offer_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "required"; }; side_effects: true; input: ZodObject<{ offer_id: $ZodBranded<ZodUUID, "Uuid", "out">; acting: ZodOptional<...>; }, $strict>; output: ZodObject<...>; async: true; description: string; error_reasons: (...

ROLE_GRANT_OFFER_ACCEPTED_NOTIFICATION_METHOD
#

role_grant_offer_accepted_notification_spec
#

auth/role_grant_offer_notifications.ts view source

{ method: string; kind: "remote_notification"; initiator: "backend"; auth: null; side_effects: true; input: ZodObject<{ offer: ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; from_actor_id: $ZodBranded<...>; ... 13 more ...; resulting_role_grant_id: ZodNullable<...>; }, $strict>; }, $strict>; output: ZodVoid; a...

role_grant_offer_and_accept
#

testing/role_grant_helpers.ts view source

(args: RoleGrantOfferAndAcceptArgs): Promise<{ offer_id: string & $brand<"Uuid">; role_grant_id: string & $brand<"Uuid">; }>

Drive the full consent flow (grantor offer โ†’ recipient accept) over the production RPC surface and return the materialized role_grant id.

grantor and recipient carry both the account id (for to_account_id derivation) and the create_session_headers factory (for cookie-threaded auth) โ€” closing that loop on a single object per party rules out caller-side header/account mismatch.

args

returns

Promise<{ offer_id: string & $brand<"Uuid">; role_grant_id: string & $brand<"Uuid">; }>

role_grant_offer_create_action_spec
#

auth/role_grant_offer_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "required"; }; side_effects: true; input: ZodObject<{ to_account_id: $ZodBranded<ZodUUID, "Uuid", "out">; ... 5 more ...; acting: ZodOptional<...>; }, $strict>; ... 4 more ...; rate_limit: "account"; }

rate_limit: 'account' throttles offer-spam at the authenticated grantor and bounds the account-existence oracle on to_account_id โ€” the same shape as invite_create_action_spec upstream addresses, where a hostile authed caller iterates recipients to probe ERROR_ACCOUNT_NOT_FOUND (and the actor-binding via ERROR_ROLE_GRANT_OFFER_ACTOR_ACCOUNT_MISMATCH) as an enumeration vector. Failure-outcome audit rows preserve the forensic trail; the rate cap closes the budget.

role_grant_offer_decline_action_spec
#

auth/role_grant_offer_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "required"; }; side_effects: true; input: ZodObject<{ offer_id: $ZodBranded<ZodUUID, "Uuid", "out">; reason: ZodOptional<...>; acting: ZodOptional<...>; }, $strict>; output: ZodObject<...>; async: true; description...

ROLE_GRANT_OFFER_DECLINED_NOTIFICATION_METHOD
#

role_grant_offer_declined_notification_spec
#

auth/role_grant_offer_notifications.ts view source

{ method: string; kind: "remote_notification"; initiator: "backend"; auth: null; side_effects: true; input: ZodObject<{ offer: ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; from_actor_id: $ZodBranded<...>; ... 13 more ...; resulting_role_grant_id: ZodNullable<...>; }, $strict>; }, $strict>; output: ZodVoid; a...

ROLE_GRANT_OFFER_DEFAULT_TTL_MS
#

role_grant_offer_history_action_spec
#

auth/role_grant_offer_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "required"; }; side_effects: false; input: ZodDefault<ZodObject<{ account_id: ZodOptional<ZodNullable<$ZodBranded<ZodUUID, "Uuid", "out">>>; limit: ZodOptional<...>; offset: ZodOptional<...>; acting: ZodOptional<.....

ROLE_GRANT_OFFER_INBOX_INDEX
#

auth/role_grant_offer_ddl.ts view source

"\nCREATE INDEX IF NOT EXISTS role_grant_offer_inbox\n ON role_grant_offer (to_account_id, expires_at)\n WHERE accepted_at IS NULL\n AND declined_at IS NULL\n AND retracted_at IS NULL\n AND superseded_at IS NULL"

Inbox lookup โ€” pending offers for an account, ordered by soonest expiry.

role_grant_offer_list_action_spec
#

auth/role_grant_offer_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "required"; }; side_effects: false; input: ZodDefault<ZodObject<{ account_id: ZodOptional<ZodNullable<$ZodBranded<ZodUUID, "Uuid", "out">>>; acting: ZodOptional<...>; }, $strict>>; output: ZodObject<...>; async: tr...

ROLE_GRANT_OFFER_MESSAGE_LENGTH_MAX
#

role_grant_offer_notification_specs
#

ROLE_GRANT_OFFER_PENDING_UNIQUE_INDEX
#

auth/role_grant_offer_ddl.ts view source

"\nCREATE UNIQUE INDEX IF NOT EXISTS role_grant_offer_pending_unique\n ON role_grant_offer (\n to_account_id,\n role,\n COALESCE(scope_kind, 'GLOBAL'),\n COALESCE(scope_id, '00000000-0000-0000-0000-000000000000'::uuid),\n from_actor_id\n )\n WHERE accepted_at IS NULL\n AND declined_at IS NULL\n ...

At most one pending offer per (to_account, role, scope_kind, scope, from_actor).

Including from_actor_id in the tuple lets multiple grantors coexist โ€” teacher A and teacher B can each have a pending classroom_student offer for the same student and scope. A same-grantor re-offer upserts the existing pending row. COALESCE collapses NULL scopes into the sentinel values so Postgres's NULL-in-unique-index quirk does not allow duplicate global pending offers; the scope_kind / scope_id pair is always either both null (global) or both non-null (scoped) per the role_grant_offer_scope_kind_paired CHECK, so the two COALESCE expressions always agree. The ON CONFLICT target in query_role_grant_offer_create must match this expression literally.

ROLE_GRANT_OFFER_RECEIVED_NOTIFICATION_METHOD
#

role_grant_offer_received_notification_spec
#

auth/role_grant_offer_notifications.ts view source

{ method: string; kind: "remote_notification"; initiator: "backend"; auth: null; side_effects: true; input: ZodObject<{ offer: ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; from_actor_id: $ZodBranded<...>; ... 13 more ...; resulting_role_grant_id: ZodNullable<...>; }, $strict>; }, $strict>; output: ZodVoid; a...

role_grant_offer_retract_action_spec
#

auth/role_grant_offer_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "required"; }; side_effects: true; input: ZodObject<{ offer_id: $ZodBranded<ZodUUID, "Uuid", "out">; acting: ZodOptional<...>; }, $strict>; output: ZodObject<...>; async: true; description: string; error_reasons: (...

ROLE_GRANT_OFFER_RETRACTED_NOTIFICATION_METHOD
#

role_grant_offer_retracted_notification_spec
#

auth/role_grant_offer_notifications.ts view source

{ method: string; kind: "remote_notification"; initiator: "backend"; auth: null; side_effects: true; input: ZodObject<{ offer: ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; from_actor_id: $ZodBranded<...>; ... 13 more ...; resulting_role_grant_id: ZodNullable<...>; }, $strict>; }, $strict>; output: ZodVoid; a...

ROLE_GRANT_OFFER_SCHEMA
#

auth/role_grant_offer_ddl.ts view source

"\nCREATE TABLE IF NOT EXISTS role_grant_offer (\n id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n from_actor_id UUID NOT NULL REFERENCES actor(id) ON DELETE CASCADE,\n to_account_id UUID NOT NULL REFERENCES account(id) ON DELETE CASCADE,\n to_actor_id UUID NULL REFERENCES actor(id) ON DELETE CASCADE,\n role T...

ROLE_GRANT_OFFER_SCOPE_KIND_GLOBAL_TOKEN
#

auth/role_grant_offer_ddl.ts view source

"GLOBAL"

Index-side token for the global case in the partial unique index. Uppercase so it cannot collide with consumer-declared ScopeKindName values (which are lowercase by regex). Never appears as a column value โ€” column-level scope_kind = NULL and scope_id = NULL together encode the global case.

ROLE_GRANT_OFFER_SCOPE_SENTINEL_UUID
#

ROLE_GRANT_OFFER_SUPERSEDE_NOTIFICATION_METHOD
#

role_grant_offer_supersede_notification_spec
#

auth/role_grant_offer_notifications.ts view source

{ method: string; kind: "remote_notification"; initiator: "backend"; auth: null; side_effects: true; input: ZodObject<{ offer: ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; from_actor_id: $ZodBranded<...>; ... 13 more ...; resulting_role_grant_id: ZodNullable<...>; }, $strict>; reason: ZodEnum<...>; cause_id:...

role_grant_offers_state_context
#

ui/role_grant_offers_state.svelte.ts view source

{ get: (error_message?: string | undefined) => RoleGrantOffersState; get_maybe: () => RoleGrantOffersState | undefined; set: (value: RoleGrantOffersState) => RoleGrantOffersState; }

Svelte context for RoleGrantOffersState. Use role_grant_offers_state_context.set(state) in the provider and role_grant_offers_state_context.get() to access.

role_grant_revoke_action_spec
#

auth/role_grant_offer_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "required"; roles: string[]; }; side_effects: true; input: ZodObject<{ actor_id: $ZodBranded<ZodUUID, "Uuid", "out">; role_grant_id: $ZodBranded<...>; reason: ZodOptional<...>; acting: ZodOptional<...>; }, $strict>...

rate_limit: 'account' bounds admin-side burn of role_grant_revoke โ€” the action is admin-gated and audit-trailed, but the per-account cap keeps a single admin script from churning role_grants in a loop and obscuring audit context for unrelated activity.

ROLE_GRANT_REVOKE_NOTIFICATION_METHOD
#

role_grant_revoke_notification_spec
#

auth/role_grant_offer_notifications.ts view source

{ method: string; kind: "remote_notification"; initiator: "backend"; auth: null; side_effects: true; input: ZodObject<{ role_grant_id: $ZodBranded<ZodUUID, "Uuid", "out">; role: ZodString; scope_id: ZodNullable<...>; reason: ZodNullable<...>; }, $strict>; output: ZodVoid; async: true; description: string; }

ROLE_GRANT_REVOKED_REASON_LENGTH_MAX
#

auth/account_schema.ts view source

500

Maximum length of the optional free-form revoked_reason attached to a revoked role_grant. Bounds the value at the schema layer so both the admin input (when the route surfaces a reason field) and the revokee-facing role_grant_revoke WS notification validate against the same ceiling.

ROLE_GRANT_SCHEMA
#

auth/auth_ddl.ts view source

"\nCREATE TABLE IF NOT EXISTS role_grant (\n id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n actor_id UUID NOT NULL REFERENCES actor(id) ON DELETE CASCADE,\n role TEXT NOT NULL,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n expires_at TIMESTAMPTZ,\n revoked_at TIMESTAMPTZ,\n revoked_by UUID REFERENCES a...

role_has_grant_path
#

auth/role_schema.ts view source

(role_specs: ReadonlyMap<string, RoleSpec>, role: string, grant_path: string): boolean

Predicate over a RoleSpec map: does the named role include the given grant path? Returns false for unknown roles. Used by admin_actions.create_admin_actions (path = 'admin') and self_service_role_actions.create_self_service_role_actions (path = 'self_service') to derive their default eligibility filters.

role_specs

type ReadonlyMap<string, RoleSpec>

role

type string

grant_path

type string

returns

boolean

ROLE_KEEPER
#

RoleGrant
#

auth/account_schema.ts view source

RoleGrant

Role grant โ€” time-bounded, revocable grant of a role to an actor.

id

type Uuid

actor_id

type Uuid

role

type string

scope_kind

Machine-readable kind tag for the polymorphic scope_id. Paired-null with scope_id per the role_grant_scope_kind_paired CHECK: both null (global) or both non-null (scoped). Consumer-declared via create_scope_kind_schema(...); v1 keeps validation registry-membership only, with no INSERT-time (role, scope_kind) enforcement.

type string | null

scope_id

Resource scope this grant applies to (e.g. a classroom id). null for global role_grants.

type Uuid | null

created_at

type string

expires_at

type string | null

revoked_at

type string | null

revoked_by

type Uuid | null

revoked_reason

Optional free-form reason attached on revoke (rides on the role_grant_revoke WS notification to the revokee).

type string | null

granted_by

type Uuid | null

source_offer_id

Offer that produced this role_grant (set by query_accept_offer). null for direct grants.

type Uuid | null

RoleGrantHistoryEventJson
#

auth/audit_log_schema.ts view source

ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; seq: ZodNumber; event_type: ZodString; outcome: ZodEnum<{ success: "success"; failure: "failure"; }>; ... 8 more ...; target_username: ZodNullable<...>; }, $strict>

Zod schema for role_grant history events with resolved usernames.

RoleGrantOffer
#

auth/role_grant_offer_schema.ts view source

RoleGrantOffer

Role grant offer row as returned by the database.

id

type Uuid

from_actor_id

type Uuid

to_account_id

type Uuid

to_actor_id

Optional actor-grain target on the recipient account. When set, accept is gated to this specific actor โ€” query_accept_offer rejects any other actor with role_grant_offer_actor_mismatch even when they belong to to_account_id. When null the offer is account-grain and any actor on to_account_id may accept (the v1 default).

Drives the audit envelope's target_actor_id on offer-shape events (role_grant_offer_create / _expire / _retract / _supersede) โ€” when set, the actor-grain forensic field carries the named actor; when null the offer-shape events leave it null by design.

type Uuid | null

role

type string

scope_kind

Machine-readable kind tag for the polymorphic scope_id. Paired-null with scope_id per the role_grant_offer_scope_kind_paired CHECK: both null (global) or both non-null (scoped). Consumer-declared via create_scope_kind_schema(...); v1 keeps validation registry-membership only, with no INSERT-time (role, scope_kind) enforcement.

type string | null

scope_id

type Uuid | null

message

type string | null

created_at

type string

expires_at

type string

accepted_at

type string | null

declined_at

type string | null

decline_reason

type string | null

retracted_at

type string | null

superseded_at

Set when the offer was obsoleted by an external event โ€” a sibling offer was accepted (yielding the role_grant this offer's role+scope maps to) or the resulting role_grant for this (to_account, role, scope) was revoked. Closes the "accept a pre-revoke offer to bypass the revoke" path.

type string | null

resulting_role_grant_id

type Uuid | null

RoleGrantOfferAcceptedParams
#

auth/role_grant_offer_notifications.ts view source

ZodObject<{ offer: ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; from_actor_id: $ZodBranded<ZodUUID, "Uuid", "out">; to_account_id: $ZodBranded<ZodUUID, "Uuid", "out">; ... 12 more ...; resulting_role_grant_id: ZodNullable<...>; }, $strict>; }, $strict>

Params for role_grant_offer_accepted โ€” recipient accepted the offer.

RoleGrantOfferAcceptInput
#

RoleGrantOfferAcceptOutput
#

auth/role_grant_offer_action_specs.ts view source

ZodObject<{ role_grant_id: $ZodBranded<ZodUUID, "Uuid", "out">; offer: ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; from_actor_id: $ZodBranded<ZodUUID, "Uuid", "out">; ... 13 more ...; resulting_role_grant_id: ZodNullable<...>; }, $strict>; superseded_offer_ids: ZodArray<...>; }, $strict>

Output for role_grant_offer_accept.

RoleGrantOfferActionOptions
#

auth/role_grant_offer_actions.ts view source

RoleGrantOfferActionOptions

roles

Role schema result from create_role_schema(). Defaults to builtin roles only. Drives the grantability gate: a role is offerable / revocable through this surface only when its RoleSpec.grant_paths includes 'admin' (the GRANT_PATH_ADMIN constant).

default_ttl_ms

TTL applied to newly-created offers. Defaults to ROLE_GRANT_OFFER_DEFAULT_TTL_MS.

type number

authorize

Custom authorization for role_grant_offer_create. The default requires the caller to hold an active role_grant for the offered role *and* the role's RoleSpec.grant_paths to include 'admin'. Consumers with richer policies (scope-aware, chained roles) override this.

RoleGrantOfferActorAccountMismatchError
#

auth/role_grant_offer_queries.ts view source

Error thrown when query_role_grant_offer_create is called with a to_actor_id that does not exist or does not belong to to_account_id. Surfaces the actorโ†”account binding mismatch at the boundary instead of letting the FK silently disagree with the recipient field.

inheritance

extends:
  • Error

constructor

type new (): RoleGrantOfferActorAccountMismatchError

RoleGrantOfferActorMismatchError
#

auth/role_grant_offer_queries.ts view source

Error thrown when an actor-targeted offer is being accepted by an actor other than offer.to_actor_id. Distinct from RoleGrantOfferNotFoundError (the IDOR mask): once an offer has been resolved to the recipient account, a wrong-actor accept on a same-account actor is a contract violation, not a privacy boundary โ€” surface a specific error so the client UI can distinguish "this offer isn't for you" from "no such offer".

inheritance

extends:
  • Error

constructor

type new (offer_id: string): RoleGrantOfferActorMismatchError

offer_id
type string

RoleGrantOfferAlreadyTerminalError
#

auth/role_grant_offer_queries.ts view source

Error thrown by offer-lifecycle queries when the offer is in a non-pending state (accepted / declined / retracted / superseded) and therefore not actionable. Distinct from RoleGrantOfferExpiredError โ€” expiry has its own user-facing story ("ask the grantor to re-send") so it travels separately.

inheritance

extends:
  • Error

constructor

type new (offer_id: string): RoleGrantOfferAlreadyTerminalError

offer_id
type string

RoleGrantOfferAndAcceptArgs
#

RoleGrantOfferCreateAuthorize
#

auth/role_grant_offer_actions.ts view source

RoleGrantOfferCreateAuthorize

Authorization callback for role_grant_offer_create. Returns true to allow, false to reject (handler converts to forbidden).

Provided with the fully-resolved request context and the parsed input (pre-TTL, pre-normalization). Consumers override the default to implement policies like "teacher may offer classroom_student only in classrooms they teach".

RoleGrantOfferCreateInput
#

auth/role_grant_offer_action_specs.ts view source

ZodObject<{ to_account_id: $ZodBranded<ZodUUID, "Uuid", "out">; to_actor_id: ZodOptional<ZodNullable<$ZodBranded<ZodUUID, "Uuid", "out">>>; ... 4 more ...; acting: ZodOptional<...>; }, $strict>

Input for role_grant_offer_create.

to_actor_id (optional) narrows the offer to a specific actor on the recipient account. When supplied, role_grant_offer_accept will only admit the named actor โ€” wrong-actor accepts reject with role_grant_offer_actor_mismatch. The audit envelope's target_actor_id is stamped from this column on the create / supersede / expire / retract events. Omit (or pass null) for the account-grain default โ€” any actor on to_account_id may accept.

RoleGrantOfferCreateOutput
#

auth/role_grant_offer_action_specs.ts view source

ZodObject<{ offer: ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; from_actor_id: $ZodBranded<ZodUUID, "Uuid", "out">; to_account_id: $ZodBranded<ZodUUID, "Uuid", "out">; ... 12 more ...; resulting_role_grant_id: ZodNullable<...>; }, $strict>; }, $strict>

Output for role_grant_offer_create.

RoleGrantOfferDeclinedParams
#

auth/role_grant_offer_notifications.ts view source

ZodObject<{ offer: ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; from_actor_id: $ZodBranded<ZodUUID, "Uuid", "out">; to_account_id: $ZodBranded<ZodUUID, "Uuid", "out">; ... 12 more ...; resulting_role_grant_id: ZodNullable<...>; }, $strict>; }, $strict>

Params for role_grant_offer_declined. The decline reason (if any) rides along inside offer.decline_reason โ€” the DB stamps it on the offer row during decline, so a sibling reason field would just duplicate it.

RoleGrantOfferDeclineInput
#

auth/role_grant_offer_action_specs.ts view source

ZodObject<{ offer_id: $ZodBranded<ZodUUID, "Uuid", "out">; reason: ZodOptional<ZodNullable<ZodString>>; acting: ZodOptional<$ZodBranded<ZodUUID, "Uuid", "out">>; }, $strict>

Input for role_grant_offer_decline.

RoleGrantOfferExpiredError
#

auth/role_grant_offer_queries.ts view source

Error thrown when an offer's expires_at has passed. The accept path enforces this independently of the sweep โ€” a stale offer past its expiry must not be accepted, even in the race window between expiry and the sweep stamping the audit event.

inheritance

extends:
  • Error

constructor

type new (offer_id: string): RoleGrantOfferExpiredError

offer_id
type string

RoleGrantOfferForm
#

ui/RoleGrantOfferForm.svelte view source

to_account_id

type string

to_actor_id?

Narrow the offer to a specific actor on to_account_id. Omit (or null, the default) for the account-grain default โ€” any actor on the recipient account may accept.

type string | null
optional

roles

Roles the caller may offer โ€” caller filters upstream (default: admin-grant-path).

type Array<string>

scope_id?

Resource scope for the offer; null (default) yields a global offer.

type string | null
optional

on_created?

type (offer: RoleGrantOfferJson) => void
optional

format_role?

type (role: string) => string
optional

RoleGrantOfferHistory
#

ui/RoleGrantOfferHistory.svelte view source

current_actor_id

Used to label a row as sent vs received. When null, direction shows as -.

type string | null

format_actor?

type (from_actor_id: string) => string
optional

format_scope?

Display label for an offer's scope. Bypasses format_scope_context when supplied โ€” return null to fall back to a truncated uuid (or 'global' for null scope_id). Omit to use the context value directly.

optional

format_role?

type (role: string) => string
optional

RoleGrantOfferHistoryInput
#

auth/role_grant_offer_action_specs.ts view source

ZodDefault<ZodObject<{ account_id: ZodOptional<ZodNullable<$ZodBranded<ZodUUID, "Uuid", "out">>>; limit: ZodOptional<ZodNullable<ZodNumber>>; offset: ZodOptional<...>; acting: ZodOptional<...>; }, $strict>>

Input for role_grant_offer_history. Returns every offer involving the account in either direction (recipient or grantor), including terminal rows, newest first. account_id is admin-only.

RoleGrantOfferHistoryOutput
#

auth/role_grant_offer_action_specs.ts view source

ZodObject<{ offers: ZodArray<ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; from_actor_id: $ZodBranded<ZodUUID, "Uuid", "out">; to_account_id: $ZodBranded<ZodUUID, "Uuid", "out">; ... 12 more ...; resulting_role_grant_id: ZodNullable<...>; }, $strict>>; }, $strict>

Output for role_grant_offer_history.

RoleGrantOfferInbox
#

ui/RoleGrantOfferInbox.svelte view source

format_actor?

Display label for from_actor_id. Defaults to a truncated uuid.

type (from_actor_id: string) => string
optional

format_scope?

Display label for an offer's scope. Bypasses format_scope_context when supplied โ€” return null to fall back to a truncated uuid (or 'global' for null scope_id). Omit to use the context value directly.

optional

format_role?

Display label for a role constant. Defaults to identity.

type (role: string) => string
optional

RoleGrantOfferJson
#

auth/role_grant_offer_schema.ts view source

ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; from_actor_id: $ZodBranded<ZodUUID, "Uuid", "out">; to_account_id: $ZodBranded<ZodUUID, "Uuid", "out">; ... 12 more ...; resulting_role_grant_id: ZodNullable<...>; }, $strict>

Zod schema for client-safe role_grant offer data.

RoleGrantOfferListInput
#

auth/role_grant_offer_action_specs.ts view source

ZodDefault<ZodObject<{ account_id: ZodOptional<ZodNullable<$ZodBranded<ZodUUID, "Uuid", "out">>>; acting: ZodOptional<$ZodBranded<ZodUUID, "Uuid", "out">>; }, $strict>>

Input for role_grant_offer_list. account_id is admin-only (inspect another account's inbox).

RoleGrantOfferListOutput
#

auth/role_grant_offer_action_specs.ts view source

ZodObject<{ offers: ZodArray<ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; from_actor_id: $ZodBranded<ZodUUID, "Uuid", "out">; to_account_id: $ZodBranded<ZodUUID, "Uuid", "out">; ... 12 more ...; resulting_role_grant_id: ZodNullable<...>; }, $strict>>; }, $strict>

Output for role_grant_offer_list.

RoleGrantOfferNotFoundError
#

auth/role_grant_offer_queries.ts view source

Error thrown when an offer cannot be located for the caller. Covers both "offer does not exist" and "offer belongs to a different recipient" (IDOR guard) โ€” the standard 404-over-403 pattern that avoids disclosing whether an offer id exists.

inheritance

extends:
  • Error

constructor

type new (offer_id: string): RoleGrantOfferNotFoundError

offer_id
type string

RoleGrantOfferNotification
#

RoleGrantOfferOkOutput
#

RoleGrantOfferReceivedParams
#

auth/role_grant_offer_notifications.ts view source

ZodObject<{ offer: ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; from_actor_id: $ZodBranded<ZodUUID, "Uuid", "out">; to_account_id: $ZodBranded<ZodUUID, "Uuid", "out">; ... 12 more ...; resulting_role_grant_id: ZodNullable<...>; }, $strict>; }, $strict>

Params for role_grant_offer_received โ€” offer delivered to its recipient.

RoleGrantOfferRetractedParams
#

auth/role_grant_offer_notifications.ts view source

ZodObject<{ offer: ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; from_actor_id: $ZodBranded<ZodUUID, "Uuid", "out">; to_account_id: $ZodBranded<ZodUUID, "Uuid", "out">; ... 12 more ...; resulting_role_grant_id: ZodNullable<...>; }, $strict>; }, $strict>

Params for role_grant_offer_retracted โ€” grantor-side retraction.

RoleGrantOfferRetractInput
#

RoleGrantOfferSelfTargetError
#

auth/role_grant_offer_queries.ts view source

Error thrown when a grantor attempts to offer a role_grant to their own account.

Enforced via a single SELECT on the grantor's actor.account_id (rather than via a CHECK constraint or a denormalized column). Resolving from the grantor side keeps the check multi-actor-correct: under multi-actor the recipient account may host many actors, but the grantor โ†’ account binding remains 1:1 by definition of actor.

inheritance

extends:
  • Error

constructor

type new (): RoleGrantOfferSelfTargetError

RoleGrantOffersRpc
#

ui/role_grant_offers_state.svelte.ts view source

RoleGrantOffersRpc

Narrow RPC surface consumed by RoleGrantOffersState. Consumers adapt their typed client (e.g. a create_rpc_client Proxy) to this shape โ€” the state class stays decoupled from the client's Result return type so tests can inject plain-function stubs.

list

type () => Promise<{offers: Array<RoleGrantOfferJson>}>

history

type (options?: { limit?: number; offset?: number; }) => Promise<{offers: Array<RoleGrantOfferJson>}>

create

type (params: { to_account_id: string; to_actor_id?: string | null; role: string; scope_id?: string | null; message?: string | null; }) => Promise<{offer: RoleGrantOfferJson}>

accept

type (offer_id: string) => Promise<{ role_grant_id: string; offer: RoleGrantOfferJson; superseded_offer_ids: Array<string>; }>

decline

type (offer_id: string, reason?: string | null) => Promise<{ok: true}>

retract

type (offer_id: string) => Promise<{ok: true}>

RoleGrantOffersState
#

ui/role_grant_offers_state.svelte.ts view source

list

readonly

list_history

readonly

create

readonly

accept

readonly

decline

readonly

retract

readonly

incoming

Pending offers for the current account, soonest-expiring first.

type Array<RoleGrantOfferJson>

readonly

outgoing

Pending offers from the current actor, newest-created first.

type Array<RoleGrantOfferJson>

readonly

history

Every offer known to this state, newest-created first. Feeds the history view.

type Array<RoleGrantOfferJson>

readonly

incoming_count

type number

readonly

constructor

type new (options: RoleGrantOffersStateOptions): RoleGrantOffersState

options

fetch

Seed the cache with the recipient-side pending inbox.

type (): Promise<void>

returns Promise<void>

fetch_history

Seed both-directions history (includes terminal rows).

type (options?: { limit?: number | undefined; offset?: number | undefined; } | undefined): Promise<void>

options?
type { limit?: number | undefined; offset?: number | undefined; } | undefined
optional
returns Promise<void>

submit_create

Issue a new offer; merges the returned offer into the cache on success.

to_actor_id (optional) narrows the offer to a specific actor on to_account_id; omit / null for the account-grain default (any actor on the recipient account may accept).

type (params: { to_account_id: string; to_actor_id?: string | null | undefined; role: string; scope_id?: string | null | undefined; message?: string | null | undefined; }): Promise<{ id: string & $brand<...>; ... 14 more ...; resulting_role_grant_id: (string & $brand<...>) | null; } | undefined>

params
type { to_account_id: string; to_actor_id?: string | null | undefined; role: string; scope_id?: string | null | undefined; message?: string | null | undefined; }
returns Promise<{ id: string & $brand<"Uuid">; from_actor_id: string & $brand<"Uuid">; to_account_id: string & $brand<"Uuid">; to_actor_id: (string & $brand<"Uuid">) | null; ... 11 more ...; resulting_role_grant_id: (string & $brand<...>) | null; } | undefined>

submit_accept

Accept an offer; stamps it terminal in the cache and drops any siblings the server superseded.

type (offer_id: string): Promise<void>

offer_id
type string
returns Promise<void>

submit_decline

type (offer_id: string, reason?: string | null | undefined): Promise<void>

offer_id
type string
reason?
type string | null | undefined
optional
returns Promise<void>

submit_retract

type (offer_id: string): Promise<void>

offer_id
type string
returns Promise<void>

subscribe

Wire a notification subscription. The handler dispatches each matching notification into apply_notification; the returned disposer unwires.

type (subscribe_fn: RoleGrantOfferSubscribe): () => void

subscribe_fn
returns () => void

apply_notification

Reduce a single WS notification into the cache. Exposed so consumers wiring their WS receiver directly (without subscribe) and tests can drive the reducer without allocating a subscription.

type (notification: RoleGrantOfferNotification): void

notification
returns void

reset

Clear the cache and reset every slot.

type (): void

returns void

RoleGrantOffersStateOptions
#

ui/role_grant_offers_state.svelte.ts view source

RoleGrantOffersStateOptions

rpc

account_id

Reactive accessor for the current account id; returns null when logged out.

type () => string | null

actor_id

Reactive accessor for the current actor id โ€” required to classify offers as outgoing. Returns null when unknown.

type () => string | null

RoleGrantOfferSubscribe
#

RoleGrantOfferSupersedeParams
#

auth/role_grant_offer_notifications.ts view source

ZodObject<{ offer: ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; from_actor_id: $ZodBranded<ZodUUID, "Uuid", "out">; to_account_id: $ZodBranded<ZodUUID, "Uuid", "out">; ... 12 more ...; resulting_role_grant_id: ZodNullable<...>; }, $strict>; reason: ZodEnum<...>; cause_id: $ZodBranded<...>; }, $strict>

Params for role_grant_offer_supersede. Fires to the grantor's sockets when their pending offer is obsoleted โ€” either by a sibling accept (reason: 'sibling_accepted'), by revoke of the resulting role_grant (reason: 'role_grant_revoked'), or by deletion of the parent scope row the offer was bound to (reason: 'scope_destroyed'). cause_id points at the accepted offer id, the revoked role_grant id, or the destroyed scope row id respectively.

RoleGrantRevokeInput
#

auth/role_grant_offer_action_specs.ts view source

ZodObject<{ actor_id: $ZodBranded<ZodUUID, "Uuid", "out">; role_grant_id: $ZodBranded<ZodUUID, "Uuid", "out">; reason: ZodOptional<ZodNullable<ZodString>>; acting: ZodOptional<...>; }, $strict>

Input for role_grant_revoke. Admin-only mutation that revokes an active role_grant on a target actor. actor_id is the natural key โ€” role_grants are actor-scoped, and the admin UI reads row.actor.id straight from the listing. Deriving actor_id from account_id would collapse under multi-actor accounts.

RoleGrantRevokeOutput
#

RoleGrantRevokeParams
#

auth/role_grant_offer_notifications.ts view source

ZodObject<{ role_grant_id: $ZodBranded<ZodUUID, "Uuid", "out">; role: ZodString; scope_id: ZodNullable<$ZodBranded<ZodUUID, "Uuid", "out">>; reason: ZodNullable<...>; }, $strict>

Params for role_grant_revoke. Delivered to the revokee's sockets when one of their active role_grants is revoked. Flat wire shape โ€” revoked_by is admin-UI-visible but deliberately omitted here (the revokee doesn't need to learn the admin's identity). Target account is implicit in the send target.

RoleGrantSummaryJson
#

auth/account_schema.ts view source

ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; role: ZodString; scope_kind: ZodNullable<ZodString>; scope_id: ZodNullable<$ZodBranded<ZodUUID, "Uuid", "out">>; created_at: ZodString; expires_at: ZodNullable<...>; granted_by: ZodNullable<...>; }, $strict>

Zod schema for the role_grant summary returned in admin account listings.

RoleName
#

RoleSchemaResult
#

auth/role_schema.ts view source

RoleSchemaResult

The result of create_role_schema โ€” a Zod schema and spec map for all roles.

Role

Zod schema that validates role strings. Use at I/O boundaries (grant endpoint, role_grant queries).

type z.ZodType<string>

role_specs

Specs for every role (builtins + app-defined). Keyed by role name.

type ReadonlyMap<string, RoleSpec>

RoleSpec
#

auth/role_schema.ts view source

RoleSpec

Configuration for a role.

Each role declares the credential types its holders must use, the scope kinds it applies to, and the grant paths through which it can be granted. Every cross-axis field is an open-registry string array โ€” required_credential_types against create_credential_type_schema, applicable_scope_kinds against create_scope_kind_schema, grant_paths against create_grant_path_schema. Pass the registry results to create_role_schema and every entry is checked at construction time.

Empty arrays carry meaning:

- required_credential_types: [] โ€” any authenticated credential type may exercise the role (the default for app-defined roles). - applicable_scope_kinds: [] โ€” the role applies at the global scope only (no scope_kind / scope_id set on its role_grants). This is the default for app-defined roles; consumers add scope kinds explicitly. - grant_paths: [] โ€” the role has no grant path declared in this registry; it is unreachable through admin / self-service / system flows. Only useful for diagnostic snapshotting.

Builtins (keeper, admin) ship preconfigured in builtin_role_specs_by_name.

name

Unique role name. Must match RoleName regex; collisions with builtins throw.

type string

description

Admin-UI-facing copy describing the role's intent.

type string

required_credential_types

Credential types whose holders are permitted to exercise this role. Each entry is checked at construction time against the credential_types registry passed to create_role_schema. Empty array = any authenticated credential type.

type ReadonlyArray<string>

applicable_scope_kinds

Scope kinds at which this role's role_grants may be granted. Each entry is checked at construction time against the scope_kinds registry passed to create_role_schema. Empty array = global only. v1 keeps this informative-only (no INSERT-time enforcement).

type ReadonlyArray<string>

grant_paths

Grant paths through which this role can be granted. Each entry is checked at construction time against the grant_paths registry passed to create_role_schema. Drives downstream defaults:

- admin_actions.grantable_roles โЇ {role : 'admin' โˆˆ grant_paths} - self_service_role_actions default eligibility โЇ {role : 'self_service' โˆˆ grant_paths}

Empty array = role is not granted via any registered path (only exists for diagnostic / future use).

type ReadonlyArray<string>

RoundTripTestOptions
#

testing/round_trip.ts view source

RoundTripTestOptions

setup_test

Per-test fixture-producing function. describe_round_trip_validation invokes this once in beforeAll (per-describe cadence โ€” see module docstring) to share a single bootstrapped keeper + accounts across every route case.

surface_source

App surface (with route specs) for route iteration. Constructed in TS by the consumer; same shape for in-process and cross-process tests.

capabilities

Backend capability declarations โ€” see cross_backend/capabilities.ts.

skip_routes

Routes to skip, in 'METHOD /path' format.

type Array<string>

input_overrides

Override generated bodies for specific routes ('METHOD /path' โ†’ body).

type Map<string, Record<string, unknown>>

RouteAuth
#

http/auth_shape.ts view source

ZodObject<{ account: ZodEnum<{ none: "none"; optional: "optional"; required: "required"; }>; actor: ZodEnum<{ none: "none"; optional: "optional"; required: "required"; }>; roles: ZodOptional<ZodReadonly<...>>; credential_types: ZodOptional<...>; }, $strict>

The canonical four-axis auth shape used by both ActionSpec.auth and RouteSpec.auth.

Cross-axis registry invariants enforced via .superRefine:

1. Roles imply actor. roles?.length โŸน actor === 'required'. Role checks read the actor's role_grants, so a role-gated spec without a resolved actor would have nothing to check. 3. No accountless actors yet. account === 'none' && actor !== 'none' is invalid in v1. The credential resolver always binds account before actor today; agent-token / group-actor credentials will lift this. 4. Unrestricted is leaf. account === 'none' && actor === 'none' โŸน no roles, no credential_types (nothing left to gate).

Invariant 2 โ€” the `actor !== 'none' โŸบ input or query declares acting?: ActingActor` biconditional โ€” needs introspection of the spec's input/query schemas, so it is checked at registration time, not on this schema. See assert_route_auth_acting_biconditional below.

RouteAuthCategory
#

http/surface_query.ts view source

RouteAuthCategory

Categorize a RouteAuth into one of the legacy auth buckets.

Returns: - 'none' for fully public routes (account === 'none' && actor === 'none') - 'keeper' when credential_types includes 'daemon_token' - 'role:<name>' for each role declared on auth.roles (multi-role specs are emitted multiple times; callers that need single-bucket grouping should pre-collapse) - 'authenticated' for account === 'required' without role / credential gate - 'optional' when either axis is 'optional' and no other bucket fits - 'other' as a last-resort bucket for shapes that don't match above

RouteContext
#

http/route_spec.ts view source

RouteContext

Per-request deps provided by the framework to route handlers.

Audit writes and other rollback-resilient fire-and-forget calls run through AppDeps.audit.emit(ctx, input) (see auth/audit_emitter.ts), which captures the pool inside its closure โ€” handlers can never accidentally write audits against the request transaction.

Routes whose body manages its own transaction (signup, bootstrap) declare transaction: false on the spec, which makes route.db the pool โ€” they reach for it directly.

db

Transaction-scoped when RouteSpec.transaction is true (the default for non-GET); pool-level otherwise.

type Db

pending_effects

Eager fire-and-forget queue โ€” push the in-flight Promise<void> for pool writes already running (audit emits, session touch, api-token usage tracking). The flush middleware drains via flush_pending_effects after the handler returns.

type Array<Promise<void>>

post_commit_effects

Deferred post-commit thunks โ€” do not push directly; reach for emit_after_commit(ctx, fn) from pending_effects.ts. The flush middleware invokes each thunk after the handler (and any wrapping db.transaction) returns, closing the microtask-ordering window that an eager Promise.resolve().then(fn) leaves open inside the transaction.

type Array<() => void | Promise<void>>

RouteErrorSchemas
#

RouteFactoryDeps
#

RouteHandler
#

http/route_spec.ts view source

RouteHandler

Route handler function โ€” receives the Hono context and a RouteContext with per-request deps (db, pending_effects).

TypeScript allows fewer params, so handlers that don't need route can use (c) => ... without changes.

RouteMethod
#

routes_by_auth_type
#

RouteSpec
#

http/route_spec.ts view source

RouteSpec

A single route definition โ€” the unit of the surface map.

input and output schemas align with SAES ActionSpec naming. Use z.null() for routes with no request body (GET, DELETE without body).

method

path

type string

auth

handler

description

type string

params

URL path parameter schema. Use z.strictObject() with string fields matching :param segments.

REST-only โ€” actions dispatch through a single JSON-RPC endpoint and encode everything in input, so params doesn't appear on ActionSpec.

type z.ZodObject

query

URL query parameter schema. Use z.strictObject() with string fields.

type z.ZodObject

input

Request body schema. Use z.null() for routes with no body.

type z.ZodType

output

Success response body schema.

type z.ZodType

rate_limit

Rate limit key type โ€” declares what this route's rate limiter is keyed on.

When set, 429 (RateLimitError) is auto-derived in derive_error_schemas. The actual RateLimiter instance is still wired imperatively in the handler โ€” this field is metadata for surface introspection and policy invariants.

errors

Handler-specific error response schemas keyed by HTTP status code.

Middleware errors (auth 401/403, validation 400, rate limit 429) are auto-derived from auth, input, and rate_limit. Declare handler-specific errors here (e.g., 404 for not-found, 409 for conflicts).

Explicit entries override auto-derived ones for the same status code.

transaction

Whether to wrap the handler in a database transaction.

When omitted, defaults are derived from the HTTP method: - GET โ†’ false (read-only, no transaction) - All others (POST, PUT, DELETE, PATCH) โ†’ true

Set explicitly to override the default (e.g., false for a POST that manages its own transaction like signup).

type boolean

rpc_action
#

actions/action_rpc.ts view source

<TSpec extends RequestResponseActionSpec>(spec: TSpec, handler: HandlerForSpec<TSpec>): RpcAction

Pair a spec with a handler while preserving per-method input/output types and selecting the narrowest ctx.auth shape the spec literal admits.

Constructing {spec, handler} literals widens handler to ActionHandler<any, any>, so spec/handler drift (renamed Zod schema, output field removal, input shape change) slips past the typechecker. rpc_action(spec, handler) binds the handler signature to (input: z.infer<spec.input>, ctx) => z.infer<spec.output> via the generic spec parameter โ€” drift surfaces at the call site.

The ctx.auth narrowing follows the spec's auth.account / auth.actor literals (see HandlerForSpec): an actor-implying spec gets ctx.auth: RequestActorContext; an account-grain spec gets ctx.auth: RequestContext; everything else stays `ctx.auth: RequestContext | null`. Handlers can rely on the dispatcher's runtime guarantee without a manual narrowing call.

Fits fuz_app's factory-closure pattern (handlers close over grantable_roles, app_settings ref, notification_sender, etc.). zzz uses a different shape โ€” a codegen-keyed Record<Method, Handler> map typed via generated ActionInputs/ActionOutputs โ€” which works when handlers are pure (no closure state) and specs are codegen-enumerated. fuz_app's admin + role-grant-offer actions have neither, so per-pair typing at the registration site is the right fit.

Spec-literal preservation is load-bearing: declare specs with satisfies RequestResponseActionSpec (canonical) so auth.actor keeps its 'required' / 'none' literal type. A spec typed directly as RequestResponseActionSpec widens the axes to AuthAxisState and the handler defaults to the loosest tier โ€” sound, but loses the ergonomic narrowing.

spec

type TSpec

handler

type HandlerForSpec<TSpec>

returns

RpcAction

examples

// actor-implying spec โ†’ ctx.auth: RequestActorContext rpc_action(role_grant_revoke_action_spec, async (input, ctx) => { const revoker_id = ctx.auth.actor.id; // no narrowing needed }); // account-grain spec โ†’ ctx.auth: RequestContext (actor: null) rpc_action(account_verify_action_spec, (_input, ctx) => { return to_session_account(ctx.auth.account); // no narrowing needed });

rpc_call
#

testing/rpc_helpers.ts view source

(args: RpcCallArgs): Promise<RpcCallResult>

One-shot JSON-RPC call over a Hono app.

Merges sensible defaults (host, origin, Content-Type) under caller-provided headers, fires POST (default) or GET, parses the envelope, and returns a discriminated result.

args

returns

Promise<RpcCallResult>

throws

  • Error - if the response body is neither a valid `JsonrpcResponse`

rpc_call_for_spec
#

testing/rpc_helpers.ts view source

<TSpec extends RequestResponseActionSpec>(args: RpcCallForSpecArgs<TSpec>): Promise<RpcCallResultForSpec<TSpec>>

Typed wrapper over rpc_call โ€” binds params to z.infer<spec.input> and the success result to z.infer<spec.output> via the generic.

Success results are validated at runtime against spec.output (same contract as rpc_call_typed); a mismatch throws. Error responses come back on the discriminated {ok: false, error} branch โ€” use this for happy-path + denial-path assertions where the error data.reason shape is still asserted manually. For adversarial input tests that send malformed params, use the untyped rpc_call.

args

type RpcCallForSpecArgs<TSpec>

returns

Promise<RpcCallResultForSpec<TSpec>>

throws

  • Error - if the success `result` does not parse against `spec.output`,

rpc_call_non_browser
#

testing/rpc_helpers.ts view source

(args: Omit<RpcCallArgs, "suppress_default_origin">): Promise<RpcCallResult>

Same as rpc_call but without the default origin header. Use for bearer-auth probes: bearer_auth discards the token when Origin or Referer is present (browser context), so a bearer probe via rpc_call would short-circuit to 401 before the token is ever validated.

Equivalent to rpc_call({...args, suppress_default_origin: true}).

args

type Omit<RpcCallArgs, "suppress_default_origin">

returns

Promise<RpcCallResult>

rpc_call_typed
#

testing/rpc_helpers.ts view source

<T>(args: RpcCallArgs, output_schema: ZodType<T, unknown, $ZodTypeInternals<T, unknown>>): Promise<T>

Same as rpc_call but parses the success result through the given output schema and returns typed data. Envelope-level failures or error responses throw โ€” use the untyped rpc_call for tests that need to assert on specific error shapes.

args

output_schema

type ZodType<T, unknown, $ZodTypeInternals<T, unknown>>

returns

Promise<T>

throws

  • Error - if the response is a JSON-RPC error, if `rpc_call` throws

RpcAction
#

RpcAttackSurfaceOptions
#

RpcCallApp
#

RpcCallArgs
#

testing/rpc_helpers.ts view source

RpcCallArgs

Arguments for rpc_call.

app

Hono-like app or bare RpcTestTransport callable.

path

RPC endpoint path, e.g. '/api/rpc'.

type string

method

JSON-RPC method name.

type string

params

Params for the call. Omit (or pass undefined) for parameterless (z.void()) methods โ€” the helper drops params from the envelope either way. See create_rpc_post_init for the null-stripping affordance and JSON-RPC 2.0 ยง4.2's prohibition on params: null.

type unknown

headers

Extra request headers (session cookie, bearer, etc.). Overrides defaults.

type Record<string, string>

id

Request id. Defaults to 'test'.

type string | number

verb

HTTP verb โ€” 'POST' (default) or 'GET' for side_effects: false methods.

type 'POST' | 'GET'

suppress_default_origin

Suppress the default origin header. Required for bearer-auth paths: bearer_auth discards the token when Origin or Referer is present (browser context), so probing it via rpc_call needs this flag โ€” or use rpc_call_non_browser, which sets it for you.

type boolean

RpcCallForSpecArgs
#

RpcCallResult
#

RpcCallResultForSpec
#

RpcClientCallOptions
#

RpcEndpointSpec
#

http/surface.ts view source

RpcEndpointSpec

An RPC endpoint definition for surface generation.

path

type string

actions

type Array<RpcAction>

RpcEndpointsSuiteOption
#

testing/rpc_helpers.ts view source

RpcEndpointsSuiteOption

Union accepted by the suite-level rpc_endpoints option โ€” eager array or a factory that takes an AppServerContext and returns endpoint specs. The factory form is required when action handlers must close over the per-test ctx.app_settings / ctx.deps (e.g. the canonical create_standard_rpc_actions(ctx.deps, {app_settings: ctx.app_settings}) pattern). create_app_server resolves either shape natively; test helpers forward the raw value to the top-level rpc_endpoints slot on CreateTestAppOptions for live dispatch.

RpcRoundTripTestOptions
#

testing/rpc_round_trip.ts view source

RpcRoundTripTestOptions

setup_test

Per-test fixture-producing function (per-describe cadence).

surface_source

App surface (with route + RPC endpoint specs) for RPC endpoint enumeration. Constructed in TS by the consumer; same shape for in-process and cross-process tests.

capabilities

Backend capability declarations.

session_options

Session config โ€” only needed to resolve factory-form rpc_endpoints against a stub AppServerContext at setup time (the actions' input schemas drive params generation; auth/dispatch run against the real backend through fixture.transport).

type SessionOptions<string>

rpc_endpoints

RPC endpoint specs โ€” eager array or factory. The factory must return the same endpoint path + spec.method list regardless of ctx (invoked once at setup with a stub ctx; the real per-test live dispatch goes through whatever the backend was started with).

skip_methods

Methods to skip, by name (e.g., 'zap_plan').

type Array<string>

input_overrides

Override generated params for specific methods (method name โ†’ params).

type Map<string, Record<string, unknown>>

RpcTestTransport
#

testing/rpc_helpers.ts view source

RpcTestTransport

Minimal transport surface โ€” the duck type Hono.request already satisfies. Extracted so test setups that want an in-process / WS / mock path can plug a different dispatcher without changing call sites.

run_auth_cleanup
#

auth/cleanup.ts view source

(deps: AuthCleanupDeps): Promise<AuthCleanupResult>

Run every auth cleanup sweep โ€” expired sessions and expired role_grant offers โ€” and return the counts.

Consumers call this from a scheduled task (setInterval, cron, etc.) alongside their own domain cleanup. Errors from individual sweeps are re-thrown so the caller's scheduler can log/alert; use the per-task helpers (query_session_cleanup_expired, cleanup_expired_role_grant_offers) directly if you need finer error isolation.

deps

returns

Promise<AuthCleanupResult>

throws

  • Error - re-thrown from any sweep that fails (no per-sweep isolation here)

run_local
#

cli/util.ts view source

(runtime: CommandDeps, command: string, args: string[]): Promise<CommandResult>

Run a local command and return the result.

runtime

runtime with run_command capability

command

command to run

type string

args

command arguments

type string[]

returns

Promise<CommandResult>

command result

run_migrations
#

db/migrate.ts view source

(db: Db, namespaces: MigrationNamespace[]): Promise<MigrationResult[]>

Run pending migrations for each namespace.

For each namespace: acquires an advisory lock, reads applied rows ordered by sequence, length-checks (binary-older-than-db short-circuits), name- prefix-verifies, then runs the pending tail in a single chain transaction. Each migration's row is INSERTed with sequence = max(sequence) + 1 for the namespace.

Length check before name verify is load-bearing: a binary-older case with a rename in the overlap would otherwise fire name-divergence-at-N first and the operator would chase a phantom source-revert before discovering the binary is the real problem.

Atomicity: any failure rolls back every migration that ran in that invocation. Namespaces are independent: a later namespace's failure does not roll back an earlier namespace that already committed.

Concurrency: per-namespace advisory locks reduce contention in multi-instance deployments but are best-effort on pool drivers (see the module docstring's "Advisory locking" notes). Correctness on concurrent boots falls out of chain-tx atomicity + the (namespace, name) PK โ€” the loser's INSERT triggers PK violation and rollback; subsequent boots see the committed state.

db

the database instance

type Db

namespaces

migration namespaces, processed in the order passed

type MigrationNamespace[]

returns

Promise<MigrationResult[]>

one result per namespace where work happened (already-up-to-date namespaces are omitted)

throws

  • MigrationError - with `kind` of `binary-older-than-db`,

RunCommandOptions
#

runtime/deps.ts view source

RunCommandOptions

Options for run_command.

cwd

Working directory for the child process.

type string

signal

AbortSignal to terminate the child process.

type AbortSignal

timeout_ms

Kill the process and return timed_out: true after this many milliseconds.

type number

RunOptions
#

ui/async_slot.svelte.ts view source

RunOptions

signal

External signal chained into the slot's internal controller. Aborts the in-flight run when fired (alongside automatic supersession by the next run() and manual {@link AsyncSlot.abort} calls).

type AbortSignal

RuntimeDeps
#

runtime/deps.ts view source

RuntimeDeps

Full runtime capabilities returned by create_deno_runtime or create_node_runtime.

Extends all *Deps interfaces with additional app-level capabilities. Functions should accept narrow *Deps interfaces, not this full type โ€” this type is for the wiring layer that creates and passes the runtime.

inheritance

env_all

Get all environment variables.

type () => Record<string, string>

args

CLI arguments passed to the program.

type ReadonlyArray<string>
readonly

cwd

Get current working directory.

type () => string

run_command_inherit

Run a command with inherited stdout/stderr (output goes directly to terminal).

type (cmd: string, args: Array<string>) => Promise<number>

rust_default_capabilities
#

testing/cross_backend/default_backend_configs.ts view source

BackendCapabilities

Capabilities for the Rust family. Adds trusted_proxy: true (the Rust spine's client-IP middleware is always wired; the env-gate just controls whether XFF is consulted vs the TCP peer IP) and login_rate_limit: true (env-gated bucket on /login + /password).

save_config
#

cli/config.ts view source

<T>(runtime: Pick<FsWriteDeps, "mkdir" | "write_text_file">, path: string, dir: string, config: T): Promise<void>

Save CLI configuration to a JSON file.

runtime

runtime with file write capability

type Pick<FsWriteDeps, "mkdir" | "write_text_file">

path

path to the config JSON file

type string

dir

directory containing the config file (created if missing)

type string

config

configuration to save

type T

returns

Promise<void>

scan_env_vars
#

env/resolve.ts view source

(obj: unknown): EnvVarRef[]

Recursively scan an object for $$VAR$$ env var references.

Walks all string values in the object tree and extracts env var names with their path context for error reporting. Escaped references (\$$VAR$$) are skipped โ€” they're literal text, not references. The optional flag on each ref distinguishes $$VAR$$ (required) from $$?VAR$$ (optional) for downstream validation.

obj

object to scan (typically a config)

type unknown

returns

EnvVarRef[]

array of env var references with paths and optional flags

schema_to_surface
#

http/schema_helpers.ts view source

(schema: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>): unknown

Convert a Zod schema to a JSON-serializable representation for the surface.

Returns null for null schemas, JSON Schema for object schemas.

schema

type ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>

returns

unknown

SchemaDiff
#

SchemaDiffLabels
#

SchemaFieldMeta
#

schema_meta.ts view source

SchemaFieldMeta

Zod .meta() shape for fuz_app schema metadata conventions.

description

type string

sensitivity

Sensitivity level for masking/redaction. 'secret' masks the value.

SchemaSnapshot
#

testing/schema_introspect.ts view source

SchemaSnapshot

Normalized database schema snapshot for parity comparison.

All fields are deterministically ordered on capture so structural equality via JSON.stringify or per-key comparison yields stable results.

schema_version

Migration tracker rows, sorted by (namespace, sequence).

type ReadonlyArray<SchemaVersionRow>
readonly

tables

Tables keyed by name.

type Record<string, TableSnapshot>
readonly

sequences

Sequences keyed by name.

type Record<string, SequenceSnapshot>
readonly

SchemaVersionRow
#

SCOPE_KIND_NAME_REGEX
#

auth/scope_kind_schema.ts view source

RegExp

Letter (lowercase a-z) start and end (or single letter), with letters and underscores in between. Mirrors RoleName. Rejects empty strings, leading or trailing underscores, uppercase, digits, and the index-side 'GLOBAL' token.

ScopeKindMeta
#

auth/scope_kind_schema.ts view source

ScopeKindMeta

Per-scope-kind metadata. description is admin-UI-facing copy (mirrors RoleSpec.description). Open shape so v2 can extend without a breaking change.

description

type string

ScopeKindName
#

ScopeKindSchemaResult
#

auth/scope_kind_schema.ts view source

ScopeKindSchemaResult

The result of create_scope_kind_schema โ€” a Zod schema and metadata map.

ScopeKind

Zod schema that validates scope-kind name strings against the registered set. Use at I/O boundaries (admin UIs, codegen) and as the construction-time check inside create_role_schema for every RoleSpec.applicable_scope_kinds entry.

type z.ZodType<string>

scope_kinds

Map of every registered scope-kind to its metadata. Keyed by name. Read at startup by admin / codegen surfaces.

type ReadonlyMap<string, ScopeKindMeta>

seed_dev_account
#

dev/setup.ts view source

(deps: SeedDevAccountDeps, input: SeedDevAccountInput, options?: { log?: SetupLogger | undefined; } | undefined): Promise<...>

Seed a development test account, bypassing username/password policy.

Idempotent by username โ€” if an account with the given username already exists, reuses it and only reconciles the requested role grants. Never updates an existing password (rerun would silently rotate it).

Intended for scripts/dev_setup.ts โ€” do not call in production.

deps

input

options?

type { log?: SetupLogger | undefined; } | undefined
optional

returns

Promise<SeedDevAccountResult>

throws

  • Error - if an existing account is found without an associated actor row

SeedDevAccountDeps
#

SeedDevAccountInput
#

dev/setup.ts view source

SeedDevAccountInput

username

Account username. Policy is bypassed โ€” any non-empty string is accepted.

type string

password

Account password. Policy is bypassed โ€” any non-empty string is accepted.

type string

roles

Roles to grant via role_grant (idempotent).

type ReadonlyArray<string>

SeedDevAccountResult
#

dev/setup.ts view source

SeedDevAccountResult

Result of seed_dev_account.

account_id

type string

actor_id

type string

created

True if a new account was created; false if one already existed.

type boolean

select_auth_app
#

testing/auth_apps.ts view source

(apps: AuthTestApps, auth: { account: "none" | "optional" | "required"; actor: "none" | "optional" | "required"; roles?: readonly string[] | undefined; credential_types?: readonly string[] | undefined; }): Hono<...>

Select the Hono test app with correct auth for a route.

apps

auth

type { account: "none" | "optional" | "required"; actor: "none" | "optional" | "required"; roles?: readonly string[] | undefined; credential_types?: readonly string[] | undefined; }

returns

Hono<BlankEnv, BlankSchema, "/">

throws

  • Error - if `auth.roles` names a role not present in `apps.by_role` โ€”

self_service_role_set_action_spec
#

auth/self_service_role_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "required"; }; side_effects: true; input: ZodObject<{ role: ZodString; enabled: ZodBoolean; acting: ZodOptional<...>; }, $strict>; output: ZodObject<...>; async: true; description: string; rate_limit: "account"; }

rate_limit: 'account' bounds audit-row churn. The toggle is idempotent (changed: false re-grants/re-revokes), but every call still writes a role_grant_create or role_grant_revoke audit row with self_service: true. Without the cap, a caller could flap the role in a loop to inflate the audit log and obscure other activity.

SelfServiceRoleActionsOptions
#

auth/self_service_role_actions.ts view source

SelfServiceRoleActionsOptions

eligible_roles

Optional override allowlist of role strings eligible for self-service. When omitted, eligibility is derived from roles.role_specs (or builtin_role_specs_by_name when roles is also omitted) by selecting every role whose RoleSpec.grant_paths includes 'self_service'. Pass an empty array to lock the surface down (every call comes back as forbidden with reason role_not_self_service_eligible).

When supplied alongside roles, every entry is checked against roles.role_specs at factory time so typos throw at startup.

type ReadonlyArray<string>

roles

Optional role schema. Drives default eligibility derivation from RoleSpec.grant_paths and validates the eligible_roles override (when supplied) against the registered role set.

SelfServiceRoleSetInput
#

SelfServiceRoleSetOutput
#

auth/self_service_role_action_specs.ts view source

ZodObject<{ ok: ZodLiteral<true>; enabled: ZodBoolean; changed: ZodBoolean; }, $strict>

Output for self_service_role_set. enabled echoes the post-call state (always equals the input enabled on success). changed is true only when the call mutated โ€” re-grants / re-revokes return false.

sensitive_field_blocklist
#

Sensitivity
#

sensitivity.ts view source

"secret"

Sensitivity level for a schema field.

- 'secret' โ€” value is masked in logs and UI (e.g. passwords, API keys, signing keys)

SequenceSnapshot
#

SerializableBootstrappedBackendHandle
#

testing/cross_backend/setup.ts view source

SerializableBootstrappedBackendHandle

Serializable subset of {@link BootstrappedBackendHandle} suitable for vitest's project.provide() โ€” vitest 4 hard-rejects non-serializable values, so the live child: ChildProcess + teardown: () => Promise<void> + keeper_transport: FetchTransport (closure) must stay in the globalSetup process. The handful of fields tests actually read (config, daemon_token, keeper_account, keeper_actor, keeper_cookies) round-trip through structured clone fine.

globalSetup calls {@link serialize_bootstrapped_handle} before project.provide; test files call {@link reconstruct_bootstrapped_handle} on the injected value to rebuild a usable handle (without child / teardown โ€” lifecycle stays with globalSetup).

config

type BackendHandle['config']
readonly

daemon_token

type BackendHandle['daemon_token']
readonly

keeper_account

type BootstrappedBackendHandle['keeper_account']
readonly

keeper_actor

type BootstrappedBackendHandle['keeper_actor']
readonly

keeper_cookies

type ReadonlyArray<string>
readonly

serialize_bootstrapped_handle
#

testing/cross_backend/setup.ts view source

(handle: BootstrappedBackendHandle): SerializableBootstrappedBackendHandle

Strip the non-serializable members so the result can be passed to vitest's project.provide. Call in globalSetup before provide.

handle

returns

SerializableBootstrappedBackendHandle

ServerEnvOptions
#

server/env.ts view source

ServerEnvOptions

Validated server env config โ€” the artifacts create_app_server() needs.

ok

type true

keyring

type Keyring

allowed_origins

type Array<RegExp>

bootstrap_token_path

type string | null

ServerEnvOptionsError
#

server/env.ts view source

ServerEnvOptionsError

Error from validate_server_env โ€” keyring or origin validation failed.

ok

type false

field

type 'SECRET_FUZ_COOKIE_KEYS' | 'FUZ_ALLOWED_ORIGINS'

errors

type Array<string>

ServerEnvOptionsResult
#

ServerHeartbeatOptions
#

ServerStatusOptions
#

http/common_routes.ts view source

ServerStatusOptions

Options for the authenticated server status route.

version

Application version string.

type string

get_uptime_ms

Returns milliseconds since server start.

type () => number

ServeStaticFactory
#

server/static.ts view source

ServeStaticFactory

Factory function that creates a static file serving middleware.

Matches the signature of serveStatic from hono/deno and @hono/node-server/serve-static.

ServeStaticOptions
#

server/static.ts view source

ServeStaticOptions

Options for serve_static factory functions (matches Hono's serveStatic signature).

root

type string

rewriteRequestPath

type (path: string) => string

mimes

type Record<string, string>

SESSION_AGE_MAX
#

session_cookie_options
#

SESSION_REFRESH_THRESHOLD_S
#

session_touch_fire_and_forget
#

auth/session_queries.ts view source

(deps: QueryDeps, token_hash: string, pending_effects: Promise<void>[] | undefined, log: Logger): Promise<void>

Touch a session without blocking the caller.

Errors are logged to console โ€” session touching never breaks request flows. Pass pending_effects (from c.var.pending_effects) to register the promise for test flushing.

deps

query dependencies

token_hash

blake3 hash of the session token

type string

pending_effects

optional array to register the effect for later awaiting

type Promise<void>[] | undefined

log

the logger instance

type Logger

returns

Promise<void>

the settled promise (callers may ignore it โ€” fire-and-forget semantics preserved)

SessionAccount
#

auth/account_schema.ts view source

SessionAccount

Account without sensitive fields, scoped to the authenticated user's own session.

id

type Uuid

username

email

type Email | null

email_verified

type boolean

created_at

type string

SessionAccountJson
#

auth/account_schema.ts view source

ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; username: ZodPipe<ZodString, ZodTransform<string, string>>; email: ZodNullable<ZodEmail>; email_verified: ZodBoolean; created_at: ZodString; }, $strict>

Zod schema for SessionAccount โ€” account without sensitive fields.

SessionCookieOptions
#

auth/session_cookie.ts view source

SessionCookieOptions

Cookie options for session cookies.

path

type string

httpOnly

type boolean

secure

type boolean

sameSite

type 'strict' | 'lax' | 'none'

maxAge

type number

SessionListInput
#

SessionListOutput
#

auth/account_action_specs.ts view source

ZodObject<{ sessions: ZodArray<ZodObject<{ id: ZodString; account_id: $ZodBranded<ZodUUID, "Uuid", "out">; created_at: ZodString; expires_at: ZodString; last_seen_at: ZodString; }, $strict>>; }, $strict>

Output for account_session_list.

SessionOptions
#

auth/session_cookie.ts view source

SessionOptions<TIdentity>

Configuration for a session cookie format.

Apps provide encode/decode to control the identity portion of the cookie payload.

The TIdentity type parameter determines the trust model: - string (e.g. a session_id) โ€” the cookie references a server-side session record, enabling per-session revocation and metadata. Use when you need admin controls like "revoke all sessions" or per-session audit trails. - number (e.g. an account_id) โ€” the cookie directly encodes the user identity, requiring no server-side session state. Simpler, but individual sessions can only be invalidated by rotating the signing key (which invalidates all sessions).

generics

TIdentity

examples

// zap: 3-part format (admin:session_id) const zap_config: SessionOptions<string> = { cookie_name: 'zap_session', context_key: 'auth_session_id', encode_identity: (session_id) => `admin:${session_id}`, decode_identity: (payload) => { const parts = payload.split(':'); if (parts.length !== 2 || parts[0] !== 'admin') return null; return parts[1] || null; }, }; // visiones: 1-part format (account_id) const visiones_config: SessionOptions<number> = { cookie_name: 'session_id', context_key: 'auth_session_id', encode_identity: (id) => String(id), decode_identity: (payload) => { const n = parseInt(payload, 10); return Number.isFinite(n) && n > 0 ? n : null; }, };

cookie_name

type string

context_key

Hono context variable name for the identity.

type string

max_age

Cookie lifetime in seconds. Single source of truth for both the embedded expires_at (via create_session_cookie_value) and the cookie's HTTP Max-Age attribute (via set_session_cookie). Defaults to SESSION_AGE_MAX (30 days). The cookie_options slot intentionally cannot carry maxAge so the two values can't drift.

type number

refresh_threshold_seconds

Threshold (seconds) for expiration-based cookie refresh. When a parsed cookie's expires_at - now <= refresh_threshold_seconds, process_session_cookie returns action: 'refresh' with a freshly-signed value (extending the embedded expiration by max_age). Defaults to SESSION_REFRESH_THRESHOLD_S (1 day). Set to 0 to disable.

type number

cookie_options

type Partial<Omit<SessionCookieOptions, 'maxAge'>>

encode_identity

Encode identity into the cookie payload (before the :expires_at suffix).

type (identity: TIdentity) => string

decode_identity

Decode identity from cookie payload. Return null if invalid.

type (payload: string) => TIdentity | null

SessionRevokeAllInput
#

SessionRevokeAllOutput
#

SessionRevokeInput
#

SessionRevokeOutput
#

set_mock_stdin
#

runtime/mock.ts view source

(runtime: MockRuntime, input: string): void

Set stdin buffer for simulating user input.

runtime

input

string to provide as stdin input

type string

returns

void

set_session_cookie
#

setup_bootstrap_token
#

dev/setup.ts view source

(deps: FsReadDeps & FsWriteDeps & CommandDeps & EnvDeps, app_name: string, options?: SetupBootstrapTokenOptions | undefined): Promise<...>

Create a bootstrap token file if it doesn't exist.

The token is a one-shot secret used to create the first admin account. Stored at ~/.{app_name}/secret_bootstrap_token by default.

deps

file, command, and env capabilities

type FsReadDeps & FsWriteDeps & CommandDeps & EnvDeps

app_name

application name (used for default state directory)

type string

options?

state_dir override, permissions, logger

type SetupBootstrapTokenOptions | undefined
optional

returns

Promise<SetupTokenResult>

result indicating whether a token was created

setup_env_file
#

dev/setup.ts view source

(deps: FsReadDeps & FsWriteDeps & CommandDeps, env_path: string, example_path: string, options?: SetupEnvOptions | undefined): Promise<...>

Create an env file from its example template, auto-generating SECRET_FUZ_COOKIE_KEYS.

If the file already exists, backfills any empty values that have generators. Idempotent โ€” safe to re-run.

deps

file read, write, and command capabilities

type FsReadDeps & FsWriteDeps & CommandDeps

env_path

path for the env file (e.g. .env.development)

type string

example_path

path to the example template

type string

options?

extra replacements, permissions, logger

type SetupEnvOptions | undefined
optional

returns

Promise<SetupEnvResult>

result indicating whether the file was created or updated

SetupBootstrapTokenOptions
#

dev/setup.ts view source

SetupBootstrapTokenOptions

state_dir

State directory override. Defaults to ~/.{app_name}.

type string

set_permissions

Optional callback to set file/directory permissions.

type (path: string, mode: number) => Promise<void>

log

SetupEnvOptions
#

dev/setup.ts view source

SetupEnvOptions

Options for setup_env_file.

replacements

Extra env var replacements beyond the default SECRET_FUZ_COOKIE_KEYS.

Keys are env var names, values are async generators. Replaces ^KEY=$ (empty value) patterns in the env file.

type Record<string, () => Promise<string>>

set_permissions

Optional callback to set file permissions (e.g. Deno.chmod).

type (path: string, mode: number) => Promise<void>

log

SetupEnvResult
#

dev/setup.ts view source

SetupEnvResult

Result of setup_env_file.

created

Whether a new file was created (vs updating existing).

type boolean

updated

Whether any values were generated/replaced.

type boolean

path

The env file path.

type string

SetupLogger
#

dev/setup.ts view source

SetupLogger

Optional logger for setup helpers.

Functions that accept a logger use it for status messages. When omitted, a default bracket-format logger writes to console.

ok

type (msg: string) => void

skip

type (msg: string) => void

error

type (msg: string) => void

SetupTest
#

testing/cross_backend/setup.ts view source

SetupTest

Per-test fixture-producing function. Invoked once inside every test() body. The implementation captures factory inputs (in-process) or a long-running backend handle (cross-process) and creates a fresh per-test bundle on each call.

SetupTokenResult
#

should_allow_origin
#

http/origin.ts view source

(origin: string, allowed_patterns: readonly RegExp[]): boolean

Tests if a request source (origin or referer) matches any of the allowed patterns. Pattern matching is case-insensitive for domains (as per web standards).

origin

type string

allowed_patterns

type readonly RegExp[]

returns

boolean

should_validate_output
#

actions/action_event_helpers.ts view source

(kind: "request_response" | "remote_notification" | "local_call", phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"): boolean

kind

type "request_response" | "remote_notification" | "local_call"

phase

type "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"

returns

boolean

ShouldDeliverFn
#

actions/broadcast_api.ts view source

ShouldDeliverFn

Per-connection delivery predicate for subscription ACLs.

Called once per connection for every broadcast send. Returning false skips that connection. Keep it fast โ€” this runs in the broadcast hot path.

input is the already-validated payload (matches the spec's input schema); method is the action method name.

sidebar_state_context
#

SidebarState
#

ui/sidebar_state.svelte.ts view source

constructor

type new (options?: SidebarStateOptions | undefined): SidebarState

options?
type SidebarStateOptions | undefined
optional

toggle_sidebar

type (value?: boolean): void

value
type boolean
default !this.show_sidebar
returns void

activate

Show the sidebar and enable the toggle. The returned disposer hides and disables on cleanup โ€” pair with $effect for scoped activation.

type (): () => void

returns () => void

SidebarStateOptions
#

ui/sidebar_state.svelte.ts view source

SidebarStateOptions

enabled

Reactive getter that controls whether the sidebar is enabled. When supplied, overrides the internal enabled state โ€” show_sidebar auto-returns false while the getter returns false.

type () => boolean

SignupForm
#

SignupInput
#

auth/signup_routes.ts view source

ZodObject<{ username: ZodPipe<ZodString, ZodTransform<string, string>>; password: ZodString; email: ZodOptional<ZodEmail>; }, $strict>

Input for POST /signup. email is optional and must match any referenced invite.

SignupOutput
#

auth/signup_routes.ts view source

ZodObject<{ ok: ZodLiteral<true>; account: ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; username: ZodPipe<ZodString, ZodTransform<string, string>>; }, $strict>; actor: ZodObject<...>; }, $strict>

Output for POST /signup.

Session cookie is the operative side effect. The returned account and actor mirror BootstrapOutput so cross-process per-test setup can read the per-test identity straight off the signup response.

SignupRouteOptions
#

auth/signup_routes.ts view source

SignupRouteOptions

Per-factory configuration for signup route specs.

inheritance

signup_account_rate_limiter

Rate limiter for signup attempts, keyed by submitted username. Pass null to disable.

type RateLimiter | null

app_settings

Mutable ref to app settings โ€” when open_signup is true, invite check is skipped.

signup_fail_floor_ms

Minimum wall-clock time (ms) for signup denial responses (403 / 409). Set to 0 or a negative number to disable (e.g., in tests). Default DEFAULT_SIGNUP_FAIL_FLOOR_MS. 429 responses are not floored.

type number

signup_fail_jitter_ms

Uniform jitter window (ยฑms) layered on the floor. Set to 0 to disable jitter while keeping the floor. Default DEFAULT_SIGNUP_FAIL_JITTER_MS.

type number

socket_status_to_async_status
#

actions/socket.svelte.ts view source

(status: SocketStatus, revoked: boolean): AsyncStatus

Project SocketStatus onto fuz_util's AsyncStatus โ€” the 5-way โ†’ 4-way mapping every consumer re-derives to surface connection state to UI (loading indicators, retry banners). Collapses reconnecting into failure (UI shows "lost, retrying") and splits closed by revoked so a terminal session-revocation read as failure while a clean client- initiated close reads as initial (the "not connected, not trying" state).

status

revoked

whether the session has been permanently revoked (typically FrontendWebsocketClient.revoked)

type boolean

returns

AsyncStatus

SocketCloseContext
#

actions/register_action_ws.ts view source

SocketCloseContext

Context passed to the on_socket_close hook.

Fires before transport.remove_connection runs, so consumer cleanup can still read identity before it's torn down. Fires for both client-initiated closes (Hono onClose) and server-initiated closes via audit revocation (the audit guard calls ws.close(), which triggers Hono's onClose).

ws

The raw WebSocket context at close time.

type WSContext

connection_id

Connection id captured at open time.

type Uuid

identity

Auth identity captured at open time โ€” still valid even if the transport already cleaned up.

SocketErrorHandler
#

SocketMessageHandler
#

SocketOpenContext
#

actions/register_action_ws.ts view source

SocketOpenContext

Context passed to the on_socket_open hook.

Fires after the transport has registered the new connection (so connection_id is valid) but before any client message can dispatch. Consumers use this to bootstrap per-socket domain state โ€” e.g. spawning a per-account unit and pushing an initial state snapshot.

ws

The raw WebSocket context โ€” exposed for edge cases; prefer notify for sends.

type WSContext

connection_id

Connection id assigned by BackendWebsocketTransport.add_connection.

type Uuid

identity

Auth identity registered for this connection.

notify

Send a JSON-RPC notification to just this socket. Mirrors ctx.notify on per-message handler contexts โ€” same socket-scoped semantics.

type (method: string, params: unknown) => void

signal

Fires when this socket closes โ€” threaded through to every handler's ctx.signal.

type AbortSignal

SocketStatus
#

actions/socket.svelte.ts view source

SocketStatus

Client-side WebSocket status.

- initial โ€” never connected; connect() has not been called. - connecting โ€” WebSocket readyState === CONNECTING. - connected โ€” WebSocket readyState === OPEN. - reconnecting โ€” close fired; waiting out backoff before next attempt. - closed โ€” socket is not open. Terminal only when revoked is true or auto-reconnect is disabled; otherwise connect() reopens.

spawn_backend
#

testing/cross_backend/spawn_backend.ts view source

(config: BackendConfig): Promise<BackendHandle>

Spawn config.start_command and return a handle once the binary is health-probe-ready and the daemon-token file is readable.

Errors at any stage SIGTERM the child group before rethrowing โ€” the caller never sees a half-started backend.

config

returns

Promise<BackendHandle>

SpecSource
#

actions/action_codegen.ts view source

SpecSource

One source in a multi-source consumer's namespace map. ns is the local alias used inside the generated file; module is the import path; specs is the runtime spec array. create_namespace_qualifier consumes a list of these.

ns

type string

module

type string

specs

type ReadonlyArray<ActionSpecUnion>

SSE_CONNECTED_COMMENT
#

realtime/sse.ts view source

": connected\n\n"

SSE comment sent on connect to flush headers through proxies. Exported for test assertions.

SseNotification
#

realtime/sse.ts view source

SseNotification

Notification shape aligned with JSON-RPC 2.0.

Uses {method, params} to match the JSON-RPC notification format.

method

Notification method name (e.g. 'run_created', 'host_updated').

type string

params

Method-specific payload.

type unknown

SseRouteTestOptions
#

testing/sse_round_trip.ts view source

SseRouteTestOptions

session_options

Session config for cookie-based auth.

type SessionOptions<string>

create_route_specs

Route spec factory โ€” same shape as production.

type (ctx: AppServerContext) => Array<RouteSpec>

app_options

Optional overrides for AppServerOptions.

db_factories

Database factories to run tests against. Default: pglite only.

type Array<DbFactory>

on_audit_event

Backend audit event callback โ€” threaded to create_test_app_server. Use to wire a close-on-revoke guard for consumer SSE registries (e.g., via create_sse_auth_guard) so session_revoke_all actually closes the tested streams.

type (event: AuditLogEvent) => void

rpc_endpoints

RPC endpoint specs โ€” required so the close-on-revoke assertion can dispatch account_session_revoke_all via RPC (there is no REST equivalent). Hard-fails via require_rpc_endpoint_path on setup.

Accepts either an array (eager) or a factory (ctx: AppServerContext) => Array<RpcEndpointSpec> โ€” the factory form is required when action handlers must close over the per-test ctx.app_settings / ctx.deps. The factory must return the same endpoint path regardless of ctx โ€” it is invoked once at setup with a stub ctx for path lookup and again per-test by create_app_server for live dispatch.

routes

SSE routes to exercise.

type Array<SseRouteTestSpec>

SseRouteTestSpec
#

testing/sse_round_trip.ts view source

SseRouteTestSpec

Config for a single SSE route under test.

path

Full HTTP path of the SSE endpoint (e.g., '/api/zap/subscribe').

type string

trigger

Fire an event matching one of the declared event_specs that should reach the open stream. Called after the : connected comment is observed. The triggered frame must be a JSON-serializable {method, params} payload.

type (ctx: {test_app: TestApp; account: TestAccount}) => Promise<void>

event_specs

Event specs to validate the triggered payload against. When omitted, the payload is only asserted to be well-formed {method, params}.

type Array<EventSpec>

assert_closes_on_revoke

Whether to assert the stream closes after session_revoke_all. Default true. Set false for endpoints that don't wire a close-on-revoke guard (leaves a TODO to fix, rather than silently passing).

type boolean

SseStream
#

realtime/sse.ts view source

SseStream<T>

Generic SSE stream controller interface.

Transport-agnostic โ€” works with any serializable type.

generics

T

default unknown

send

Send data to the client as a JSON SSE event.

type (data: T) => void

comment

Send a comment (for keep-alive pings).

type (text: string) => void

close

Close the stream.

type () => void

on_close

Register a listener called when the stream closes (client disconnect or explicit close).

type (fn: () => void) => void

StandardAdminIntegrationTestOptions
#

testing/admin_integration.ts view source

StandardAdminIntegrationTestOptions

setup_test

Per-test fixture-producing function. The admin suite calls this in every test() body โ€” auth_integration_truncate_tables clears account, so each test re-bootstraps the keeper.

surface_source

App surface (with route specs + middleware specs) for route iteration and error-coverage scoping. Constructed in TS by the consumer (same shape for in-process and cross-process tests).

capabilities

Backend capability declarations.

session_options

Session config โ€” needed for cookie_name + factory-form rpc_endpoints resolution.

type SessionOptions<string>

roles

Role schema result from create_role_schema() โ€” used to determine valid/invalid/web-grantable roles.

rpc_endpoints

RPC endpoint specs โ€” the source RpcAction arrays. Required; role_grant grant/revoke are RPC-only and the suite hard-fails without them.

admin_prefix

Path prefix where admin routes are mounted (e.g., '/api/admin'). Used by the 401/403 error-coverage probe to scope to fuz_app admin routes only, avoiding app-specific admin-gated routes that may use stub deps. Default '/api/admin'.

type string

StandardAttackSurfaceOptions
#

testing/attack_surface.ts view source

StandardAttackSurfaceOptions

Options for the standard attack surface test suite.

build

Build the app surface bundle (surface + route specs + middleware specs).

type () => AppSurfaceSpec

snapshot_path

Absolute path to the committed snapshot JSON file.

type string

expected_public_routes

Expected public routes, e.g. ['GET /health', 'POST /api/account/login'].

type Array<string>

expected_api_middleware

Expected middleware names for API routes, e.g. ['origin', 'session', 'request_context', 'bearer_auth'].

type Array<string>

roles

All roles in the app (e.g. ['admin', 'keeper']).

type Array<string>

api_path_prefix

Path prefix for middleware stack assertion. Default '/api/'.

type string

security_policy

Security policy configuration. Omit for sensible defaults.

error_schema_tightness

Error schema tightness assertion config. Defaults to default_error_schema_tightness (ignores 401/403/429, min_specificity: 'enum', allowlist seeded with fuz_app_stock_route_tightness_allowlist).

Consumer-supplied allowlist and ignore_statuses are additive โ€” the suite merges them underneath the stock defaults, so project-specific entries don't need to re-list fuz_app's own stock routes. Pass a narrower config to extend either list or tighten min_specificity; pass null to skip the assertion and keep the audit log informational-only.

type ErrorSchemaTightnessOptions | null

StandardCrossProcessTestOptions
#

testing/cross_backend/standard.ts view source

StandardCrossProcessTestOptions

Configuration for describe_standard_cross_process_tests.

Mirrors StandardTestOptions minus the in-process-only knobs (create_route_specs, bootstrap, rate_limiting_app_options, bootstrap_token) โ€” those drive the three omitted suites.

setup_test

Per-test fixture-producing function.

surface_source

App surface. Constructed in TS by the consumer; same shape for in-process and cross-process tests.

capabilities

Backend capability declarations.

session_options

Session config โ€” needed for cookie_name + factory-form rpc_endpoints resolution.

type SessionOptions<string>

rpc_endpoints

RPC endpoint specs โ€” required. The standard integration tests drive account_verify, account_session_*, account_token_* through the RPC surface (and admin tests, when wired, drive role_grant grant/revoke through it too).

roles

Role schema result from create_role_schema(). When provided, the admin integration suite is included.

admin_prefix

Path prefix where admin routes are mounted. Default '/api/admin'.

type string

error_coverage_min

Forwarded to describe_standard_integration_tests โ€” overrides the default error-coverage threshold on the scoped REST surface. Set to 0 to skip the assertion entirely.

type number

StandardIntegrationTestOptions
#

testing/integration.ts view source

StandardIntegrationTestOptions

setup_test

Per-test fixture-producing function. The integration suite calls this in every test() body โ€” auth_integration_truncate_tables clears account, so each test re-bootstraps the keeper.

surface_source

App surface (with route specs + middleware specs) for route iteration and error-coverage scoping. The same shape feeds both in-process and cross-process tests โ€” the test process always constructs the spec in TS (via create_test_app_surface_spec or a consumer's equivalent); cross-process-ness is a property of the transport + per-test fixture, not the schema source. The on-disk auth_attack_surface.json is an observability artifact for human inspection + gen-time drift gating, not the source the test runtime reads from.

capabilities

Backend capability declarations โ€” companion to fixture.in_process narrowing.

session_options

Session config โ€” needed to resolve factory-form rpc_endpoints against a stub AppServerContext at setup time and to read cookie_name for manual cookie composition in the origin-verify cases.

type SessionOptions<string>

rpc_endpoints

RPC endpoint specs โ€” required. This suite dispatches account_verify, account_session_*, and account_token_* via rpc_call_for_spec (the /api/account/verify REST route is a status-only nginx shim with no payload). Hard-fails via require_rpc_endpoint_path on setup so consumer projects see a clear setup error instead of confusing test failures.

Accepts either an array (eager) or a factory โ€” see rpc_helpers.ts for the union semantics. The factory must return the same endpoint path regardless of ctx โ€” invoked once at setup with a stub ctx for path lookup; the running backend handles live dispatch.

error_coverage_min

Minimum error-coverage ratio to enforce on the scoped REST surface (login / logout / password / signup + the shared RPC endpoint). Default DEFAULT_INTEGRATION_ERROR_COVERAGE (0.2). Set to 0 to skip the assertion entirely โ€” useful for consumers with minimal route sets whose declared error codes outpace the suite's denial-path drivers.

type number

StandardRpcActionsDeps
#

auth/standard_rpc_actions.ts view source

StandardRpcActionsDeps

Dependencies for create_standard_rpc_actions.

Stack-standard RouteFactoryDeps slice (log, audit) plus an optional notification_sender consumed only by the role-grant-offer sub-factory for WS fan-out. Admin and account sub-factories ignore notification_sender.

inheritance

extends:
  • Pick<RouteFactoryDeps, 'log' | 'audit'>

notification_sender

type NotificationSender | null

StandardRpcActionsOptions
#

StandardTestOptions
#

testing/standard.ts view source

StandardTestOptions

Configuration for describe_standard_tests.

setup_test

Per-test fixture-producing function.

surface_source

App surface. Constructed in TS by the consumer; same shape for in-process and cross-process tests.

capabilities

Backend capability declarations.

session_options

Session config โ€” needed for cookie_name + factory-form rpc_endpoints resolution.

type SessionOptions<string>

create_route_specs

Route spec factory โ€” same one used in production. Required by describe_rate_limiting_tests, which builds a fresh TestApp per test (bypasses the shared setup_test fixture) so it can pass tight per-test rate-limiter overrides.

type (ctx: AppServerContext) => Array<RouteSpec>

rpc_endpoints

RPC endpoint specs โ€” required. The standard integration tests drive account_verify, account_session_*, account_token_* through the RPC surface (and admin tests, when wired, drive role_grant grant/revoke through it too).

roles

Role schema result from create_role_schema(). When provided, admin integration + audit completeness suites are included.

bootstrap

Bootstrap config โ€” when set to mode: 'live', the bootstrap success suite runs against create_test_app_for_bootstrap. Other modes ('disabled' / 'surface_only' / omission) silent-skip the suite.

rate_limiting_app_options

Optional overrides forwarded to describe_rate_limiting_tests.

admin_prefix

Path prefix where admin routes are mounted. Default '/api/admin'.

type string

error_coverage_min

Forwarded to describe_standard_integration_tests โ€” overrides the default error-coverage threshold on the scoped REST surface. Set to 0 to skip the assertion entirely.

type number

bootstrap_token

Override the bootstrap-success suite's synthetic token.

type string

start_daemon_token_rotation
#

auth/daemon_token_middleware.ts view source

(runtime: Pick<EnvDeps, "env_get"> & Pick<FsWriteDeps, "mkdir" | "write_text_file" | "rename"> & { chmod?: ((path: string, mode: number) => Promise<...>) | undefined; } & FsRemoveDeps, deps: QueryDeps, options: DaemonTokenRotationOptions, log: Logger): Promise<...>

Start daemon token rotation.

Generates an initial token, writes it to disk, resolves the keeper account, and sets up periodic rotation. Returns the mutable state object and a stop function.

runtime

runtime with file and remove capabilities

type Pick<EnvDeps, "env_get"> & Pick<FsWriteDeps, "mkdir" | "write_text_file" | "rename"> & { chmod?: ((path: string, mode: number) => Promise<void>) | undefined; } & FsRemoveDeps

deps

query dependencies for resolving keeper account

options

rotation configuration

log

the logger instance

type Logger

returns

Promise<DaemonTokenRotation>

rotation state and stop function

StatResult
#

stop_daemon
#

cli/daemon.ts view source

(runtime: Pick<EnvDeps, "env_get"> & Pick<FsReadDeps, "stat" | "read_text_file"> & FsRemoveDeps & CommandDeps & LogDeps, name: string): Promise<...>

Stop a running daemon by sending SIGTERM and cleaning up the PID file.

Returns a result object instead of logging directly, separating lifecycle from presentation. Errors removing the PID file are swallowed (the daemon's own shutdown handler may have removed it concurrently).

runtime

runtime with command, file, and env capabilities

type Pick<EnvDeps, "env_get"> & Pick<FsReadDeps, "stat" | "read_text_file"> & FsRemoveDeps & CommandDeps & LogDeps

name

application name

type string

returns

Promise<StopDaemonResult>

result describing the outcome

StopDaemonResult
#

cli/daemon.ts view source

StopDaemonResult

Result of a stop_daemon operation.

stopped

Whether a daemon was stopped.

type boolean

pid

PID of the stopped daemon, if any.

type number

message

Human-readable message describing the outcome.

type string

stub
#

stub_app_deps
#

stub_handler
#

stub_mw
#

testing/stubs.ts view source

(_c: any, next: any): Promise<void>

Stub middleware that passes through.

_c

type any

next

type any

returns

Promise<void>

stub_password_deps
#

testing/app_server.ts view source

PasswordHashDeps

Fast password stub for tests that don't exercise login/password flows.

Hashes are deterministic (stub_hash_<password>) and verify correctly, so auth bootstrap and session creation work without Argon2 overhead.

StubUpgrade
#

SubscribeOptions
#

realtime/subscriber_registry.ts view source

SubscribeOptions

Options for SubscriberRegistry.subscribe.

channels

Channels to subscribe to. Empty/absent = all channels.

type ReadonlyArray<string>

scope

Primary (capped) identity โ€” e.g., session hash. Subject to max_per_scope and matched by close_by_identity.

type string

groups

Grouping identities โ€” e.g., account id. Matched by close_by_identity but NOT subject to the cap. Use for coarse-targeted close.

type ReadonlyArray<string>

Subscriber
#

realtime/subscriber_registry.ts view source

Subscriber<T>

generics

T

stream

type SseStream<T>

channels

Channels this subscriber listens to. null means all channels.

type Set<string> | null

scope

Primary (capped) identity. null when none.

type string | null

groups

Grouping identities for close_by_identity. null when none.

type Set<string> | null

SubscriberRegistry
#

realtime/subscriber_registry.ts view source

Generic subscriber registry with channel-based filtering and identity-keyed disconnection.

Subscribers connect with optional channel filters, a capped scope, and uncapped groups. Broadcasts go to a specific channel and reach only matching subscribers. close_by_identity force-closes all subscribers whose scope or groups contain the given key โ€” use for auth revocation.

generics

T

examples

const registry = new SubscriberRegistry<SseNotification>(); // subscriber connects (from SSE endpoint) const unsubscribe = registry.subscribe(stream, {channels: ['runs']}); // when a run changes registry.broadcast('runs', {method: 'run_created', params: {run}}); // subscriber disconnects unsubscribe();
// scope = session hash (capped), groups = [account id] (close-only) const unsubscribe = registry.subscribe(stream, { channels: ['audit_log'], scope: session_hash, groups: [account_id], }); // coarse โ€” close all of a user's streams on role revocation registry.close_by_identity(account_id); // fine โ€” close just the stream(s) tied to a specific session registry.close_by_identity(session_hash);

constructor

type new <T>(options?: SubscriberRegistryOptions | undefined): SubscriberRegistry<T>

options?
type SubscriberRegistryOptions | undefined
optional

subscribe

Add a subscriber.

type (stream: SseStream<T>, options?: SubscribeOptions | undefined): () => void

stream

SSE stream to send data to

type SseStream<T>
options?

channel filter and identity slots (scope + groups)

type SubscribeOptions | undefined
optional
returns () => void

unsubscribe function

broadcast

Broadcast data to all subscribers on a channel.

Subscribers with no channel filter receive all broadcasts. Subscribers with a channel filter only receive matching broadcasts.

type (channel: string, data: T): void

channel
type string
data
type T
returns void

close_by_identity

Force-close all subscribers whose scope or groups match the given key.

Closes each matching stream and removes the subscriber from the registry. Use for auth revocation โ€” when a user's permissions change, close their SSE connections so they must reconnect and re-authenticate.

type (identity: string): number

identity

the identity key to match (checked against scope and groups)

type string
returns number

the number of subscribers closed

SubscriberRegistryOptions
#

realtime/subscriber_registry.ts view source

SubscriberRegistryOptions

Options for SubscriberRegistry.

max_per_scope

Max subscribers sharing a single scope. On subscribe, when the count of subscribers with the same scope reaches this limit, the oldest matching subscriber(s) are closed before the new one is added. null (default) disables the cap. groups identities are never capped.

type number | null

SuiteAppOptions
#

testing/app_server.ts view source

Partial<Omit<AppServerOptions, "backend" | "bootstrap" | "session_options" | "create_route_specs" | "rpc_endpoints">>

app_options shape accepted by create_test_app and the DB-backed suite helpers. Excludes fields the helpers manage directly โ€” backend / session_options / create_route_specs are constructed by the helper itself; rpc_endpoints and bootstrap live on top-level options so setup-time surface lookup and runtime dispatch read from one source of truth.

SupersededOffer
#

auth/role_grant_offer_schema.ts view source

SupersededOffer

A superseded offer row annotated with the grantor's account_id.

Carried by superseded_offers in accept/revoke query results so callers can fan out role_grant_offer_supersede notifications to the grantor's sockets without a second round-trip. Populated via a CTE join on actor in the supersede UPDATE.

inheritance

from_account_id

type Uuid

surface_auth_summary
#

http/surface_query.ts view source

(surface: AppSurface): { none: number; authenticated: number; optional: number; role: Map<string, number>; keeper: number; other: number; }

Summarize route auth distribution across the surface.

Categorical view over the four-axis flat record. Multi-role specs contribute one count per role they admit.

surface

returns

{ none: number; authenticated: number; optional: number; role: Map<string, number>; keeper: number; other: number; }

counts by auth category, with role counts broken out by role name

SurfaceExplorer
#

SurfaceRouteOptions
#

SurfaceSecurityPolicyOptions
#

testing/surface_invariants.ts view source

SurfaceSecurityPolicyOptions

Configuration for security policy invariants.

All fields have sensible defaults. Pass overrides for project-specific needs.

sensitive_route_patterns

Path patterns for routes that should be rate-limited. Default: common sensitive REST patterns (login, password, bootstrap). account_token_create lives on the RPC surface; per-method RPC rate limiting is a separate invariant if consumers want it.

type Array<string | RegExp>

public_mutation_allowlist

Routes explicitly allowed to be public mutations (e.g., webhooks, bootstrap). Format: 'METHOD /path' (e.g., 'POST /api/account/login').

type Array<string>

keeper_route_prefixes

Allowed path prefixes for keeper-protected routes. Default: ['/api/']. Catches keeper routes outside expected namespaces.

type Array<string>

TABLE_LIMIT_MAX
#

TableInfo
#

TableSnapshot
#

testing/schema_introspect.ts view source

TableSnapshot

Per-table structural metadata.

columns

Column metadata keyed by column name (sorted on serialization).

type Record<string, ColumnSnapshot>
readonly

indexes

Index definitions as Postgres renders them via pg_indexes.indexdef.

type ReadonlyArray<{readonly name: string; readonly definition: string}>
readonly

constraints

Constraint definitions as Postgres renders them via pg_get_constraintdef.

type ReadonlyArray<{ readonly name: string; readonly type: string; readonly definition: string; }>
readonly

TableState
#

ui/table_state.svelte.ts view source

list

readonly

table_name

type string

columns

type Array<ColumnInfo>

rows

type Array<Record<string, unknown>>

total

offset

limit

primary_key

type string | null

deleting

type string | null

delete_error

type string | null

showing_start

readonly

showing_end

readonly

has_prev

readonly

has_next

readonly

fetch

Fetch a page of rows for table_name from GET /api/db/tables/{table_name}. limit is clamped to [1, TABLE_LIMIT_MAX].

type (table_name: string, offset?: number, limit?: number): Promise<void>

table_name
type string
offset
type number
default 0
limit
type number
default 100
returns Promise<void>

go_prev

type (): void

returns void

go_next

type (): void

returns void

delete_row

Delete a row by its primary key via DELETE /api/db/tables/{table_name}/rows/{pk}. Optimistically drops it from rows and decrements total on success; surfaces server errors on delete_error.

type (row: Record<string, unknown>): Promise<boolean>

row
type Record<string, unknown>
returns Promise<boolean>

true when the row was removed; false on missing primary key or server error

TableStatus
#

TableWithCount
#

TerminalDeps
#

runtime/deps.ts view source

TerminalDeps

Terminal I/O operations.

stdout_write

Write bytes to stdout.

type (data: Uint8Array) => Promise<number>

stdin_read

Read bytes from stdin, or null on EOF.

type (buffer: Uint8Array) => Promise<number | null>

TEST_CLIENT_IP
#

TEST_CONTEXT_PRESET_KEY
#

hono_context.ts view source

"test_context_preset"

Hono context variable name for the test-harness pre-baked context flag.

Test harnesses (create_test_app_from_specs, create_fake_hono_context, the WS round-trip connect() helper, plus per-test middleware that pre-populates REQUEST_CONTEXT_KEY) set this to true so apply_authorization_phase skips its DB-backed actor resolution and trusts the supplied RequestContext. Production middleware never sets this key โ€” only test code does. The flag is the explicit escape hatch that replaced the implicit "is REQUEST_CONTEXT_KEY already set?" probe, so that future production code consulting REQUEST_CONTEXT_KEY cannot silently bypass the live build.

TEST_COOKIE_SECRET
#

test_if
#

testing/cross_backend/capabilities.ts view source

(cond: boolean, name: string, fn: () => void | Promise<void>): void

Conditional test() wrapper โ€” registers a vitest case only when cond is true; otherwise registers it as .skip so the run still surfaces the gated coverage in the report.

Thin wrapper around vitest's test.skipIf(!cond) with the argument order flipped to match the more readable test_if(capabilities.bearer_auth, ...) call pattern.

cond

type boolean

name

type string

fn

type () => void | Promise<void>

returns

void

TEST_MIDDLEWARE_PATH
#

TestAccount
#

testing/app_server.ts view source

TestAccount

A bootstrapped test account with credentials.

account

type {id: Uuid; username: string}

actor

type {id: Uuid}

session_cookie

Signed session cookie value.

type string

api_token

Raw API token for Bearer auth.

type string

create_session_headers

Build request headers with this account's session cookie.

type (extra?: Record<string, string>) => Record<string, string>

create_bearer_headers

Build request headers with this account's Bearer token.

type (extra?: Record<string, string>) => Record<string, string>

TestAccountFixture
#

TestAccountOverrides
#

TestAccountWithActor
#

TestActorOverrides
#

TestApp
#

testing/app_server.ts view source

TestApp

A fully assembled test app โ€” Hono app + backend + helpers.

app

type Hono

backend

surface_spec

surface

route_specs

type Array<RouteSpec>

create_session_headers

Build request headers with the bootstrapped session cookie.

type (extra?: Record<string, string>) => Record<string, string>

create_bearer_headers

Build request headers with the bootstrapped Bearer token.

type (extra?: Record<string, string>) => Record<string, string>

create_daemon_token_headers

Build request headers with the daemon token (keeper auth).

type (extra?: Record<string, string>) => Record<string, string>

create_account

Create an additional account with credentials.

type (options?: { username?: string; password_value?: string; roles?: Array<string>; }) => Promise<TestAccount>

cleanup

Cleanup resources (delegates to TestAppServer.cleanup).

type () => Promise<void>

TestAppForBootstrap
#

testing/app_server.ts view source

TestAppForBootstrap

A fully assembled test app in the pre-bootstrap state โ€” empty DB, bootstrap_lock.bootstrapped = false, no keeper account. Test drives POST /bootstrap itself.

app

type Hono

backend

surface_spec

surface

route_specs

type Array<RouteSpec>

create_request_headers

Build host/origin request headers for the anonymous bootstrap POST.

type (extra?: Record<string, string>) => Record<string, string>

cleanup

Release test resources (no-op when DB is injected or factory-cached).

type () => Promise<void>

TestAppServer
#

testing/app_server.ts view source

TestAppServer

An AppBackend with a bootstrapped account, API token, and session cookie.

inheritance

extends:

account

The bootstrapped account.

type {id: Uuid; username: string}

actor

The actor linked to the account.

type {id: Uuid}

api_token

Raw API token for Bearer auth.

type string

session_cookie

Signed session cookie value for cookie auth.

type string

keyring

Keyring used for cookie signing โ€” exposed for forging expired/tampered cookies in tests.

type Keyring

cleanup

Release test resources (no-op when DB is injected or factory-cached).

type () => Promise<void>

TestAppServerOptions
#

testing/app_server.ts view source

TestAppServerOptions

Configuration for create_test_app_server.

session_options

Session options โ€” needed for cookie signing.

type SessionOptions<string>

db

Existing database โ€” skips internal DB creation when provided. Caller owns the DB lifecycle.

type Db

db_type

Database driver type โ€” only used when db is provided. Default: 'pglite-memory'.

type DbType

password

Password implementation. Default: stub_password_deps. Pass argon2_password_deps for tests that exercise login.

username

Username for the bootstrapped account. Default: 'keeper'.

type string

password_value

Password for the bootstrapped account. Default: DEFAULT_TEST_PASSWORD.

type string

roles

Roles to grant. Default: [ROLE_KEEPER].

type Array<string>

audit_factory

Build the bound AuditEmitter used by the test backend. Defaults to default_audit_factory (a no-listener create_audit_emitter over the test backend's {db, log}). Pass a custom factory when a test needs: - to capture audit events (compose on_audit_event inside the body) - to register consumer event-type schemas (pass audit_log_config) - to instrument emit ordering (create_emit_ordering_audit_factory) - to wrap or replace the emitter for some other reason

Matches the production shape โ€” create_app_backend requires an audit_factory and create_test_app_server mirrors that contract end-to-end. The earlier on_audit_event / audit_log_config sugar fields were removed alongside the CreateAppBackendOptions rename.

TestAuditEventOverrides
#

TestBackendPaths
#

testing/cross_backend/build_test_backend_paths.ts view source

TestBackendPaths

Generic per-backend paths every cross-process test binary needs. Consumers extend this with their own domain paths.

- root โ€” the per-backend subtree under os.tmpdir(). Compose consumer-specific paths under here. - bootstrap_token_path โ€” FUZ_BOOTSTRAP_TOKEN_PATH; harness writes the bootstrap token here before spawn. - daemon_token_path โ€” where init_daemon_token (Rust) and the TS server's daemon-token writer land the token (under {root}/run/).

root

type string
readonly

bootstrap_token_path

type string
readonly

daemon_token_path

type string
readonly

TestFixture
#

testing/cross_backend/setup.ts view source

TestFixture

The per-test bundle returned by SetupTest. Every Tier 1 suite body reads exclusively from this shape โ€” no test_app.backend.* reads remain in the suite bodies.

Discriminated by in_process: when true, keyring and backend_internals are present (compile-time narrowed); when false, they're absent and the suite body must either run via the public wire (cross-process) or gate the test with test_if(capabilities.in_process_only, ...). The discriminant value mirrors BackendCapabilities.in_process_only โ€” both source from the same producer (default_in_process_setup vs. cross-process variant).

Suite bodies narrow with assert(fixture.in_process) after setup_test(); sites that reach for keyring or backend_internals are in-process-only by structure and the assertion surfaces a clear failure if a future cross-process consumer reaches them without a test_if gate.

TestFixtureBase
#

testing/cross_backend/setup.ts view source

TestFixtureBase

Fields shared by every TestFixture regardless of transport. The discriminated union below adds in-process-only fields conditionally.

Keeper โ‰  admin. fixture.account / fixture.actor refer to the fresh keeper seeded per test. The keeper account holds ROLE_KEEPER + ROLE_ADMIN by default โ€” matching the production bootstrap_account flow. The ROLE_KEEPER role itself does *not* grant admin reach; the bootstrap account just happens to hold both as separate grants. Tests probing the keeper-vs-admin separation (e.g. "non-admin cannot list accounts") declare a secondary at setup-time via extra_accounts: [{username, roles: [ROLE_KEEPER]}] and read it from fixture.extra_accounts[username].

transport

Transport for this test's HTTP requests. Typed as FetchTransport so cross-process tests can call transport.cookies() for WS upgrade cookie threading; in-process provides a no-op cookies() returning [] (in-process tests construct cookies via create_session_headers directly and don't thread WS through this channel).

readonly

fresh_transport

Build a brand-new FetchTransport with an empty cookie jar pinned to the same backend. Use for unauthed assertions (`no cookie on protected route returns 401`, bearer-only calls expected to fall through to the unauthenticated path) where the per-test session cookie carried by transport's jar would otherwise leak into the request and convert a 401 into a 200.

New-per-call, not memoized โ€” each invocation returns a fresh instance. If a call mutates the jar (e.g. an unauthed login attempt returning Set-Cookie) it can't pollute sibling calls.

Pass origin: null for bearer-only probes that must look like non-browser callers โ€” the auth middleware silently discards bearer credentials when Origin/Referer is present, so a default Origin: <base_url> would convert "bearer + no Origin โ†’ 200" into "bearer + Origin โ†’ discarded โ†’ 401" cross-process. In-process the wrapper is stateless and the option is a no-op (no auto-Origin to suppress).

In-process this is functionally identical to transport (the wrapper's cookies(): [] is a no-op already); cross-process the returned transport starts with an empty jar at the same base_url.

type (options?: {readonly origin?: string | null}) => FetchTransport
readonly

account

The freshly-bootstrapped keeper account.

type {readonly id: Uuid; readonly username: string}
readonly

actor

The actor linked to the keeper account.

type {readonly id: Uuid}
readonly

create_session_headers

Build request headers with the keeper's session cookie.

type (extra?: Record<string, string>) => Record<string, string>
readonly

create_bearer_headers

Build request headers with the keeper's bearer token.

type (extra?: Record<string, string>) => Record<string, string>
readonly

create_daemon_token_headers

Build request headers with the daemon token (keeper auth).

type (extra?: Record<string, string>) => Record<string, string>
readonly

create_account

Mint an additional bootstrapped account for cross-account / multi-user tests. In-process: re-uses create_test_account_with_credentials against the same DB; cross-process: goes through the consumer-supplied DB-admin channel.

type (options?: CreateTestAccountOptions) => Promise<TestAccountFixture>
readonly

extra_accounts

Bootstrap-time-seeded secondaries, keyed by their declared username. Populated from the extra_accounts option passed to default_in_process_setup / default_cross_process_setup. Empty for suites that don't declare any.

type Readonly<Record<string, ExtraAccountFixture>>
readonly

testing_reset_action_spec
#

testing/cross_backend/testing_reset_actions.ts view source

{ readonly method: "_testing_reset"; readonly kind: "request_response"; readonly initiator: "frontend"; readonly auth: { readonly account: "required"; readonly actor: "none"; readonly credential_types: readonly [...]; }; ... 4 more ...; readonly description: "Test-binary only โ€” wipe auth tables, re-bootstrap a fresh...

The _testing_reset action spec.

Input: - extra_keeper_roles โ€” roles to grant the fresh keeper *in addition to* [ROLE_KEEPER, ROLE_ADMIN] (matching production bootstrap). - extra_accounts โ€” additional accounts to seed at this same bootstrap-equivalent step. Each entry's roles are direct-granted (bypassing offer/accept) because the seed is *part of bootstrap*, not a post-bootstrap action. Use this for accounts whose required roles aren't admin-grantable via offer/accept (e.g. ROLE_KEEPER, whose RoleSpec.grant_paths is bootstrap-only). For admin-grantable roles, prefer fixture.create_account({roles}) (offer/accept production path).

Output: keeper credentials plus a parallel array of seeded extra_accounts (same order as input). The per-test fixture closes over the returned values; subsequent calls in the same test see the fresh keeper and any requested secondaries.

auth gates on the daemon-token credential โ€” the keeper holds it exclusively. The action is internally privileged (it runs direct DB writes the production wire never exposes); daemon-token auth is the structural fence.

testing_reset_wiped_tables
#

TestingRateLimiter
#

testing/testing_rate_limiter.ts view source

RateLimiter plus bucket tracking. Every check/record call adds its key to #seen_keys; reset removes it; reset_all clears every tracked bucket. Drop-in replacement anywhere a RateLimiter is expected โ€” the type is nominally compatible via subclassing.

inheritance

extends:

check

type (key: string, now?: number | undefined): RateLimitResult

key
type string
now?
type number | undefined
optional

record

type (key: string, now?: number | undefined): RateLimitResult

key
type string
now?
type number | undefined
optional

reset

type (key: string): void

key
type string
returns void

reset_all

Clear every bucket this limiter has been asked about. Idempotent; safe to call before any check/record activity. Designed to be invoked from a _testing_reset handler's reset_state callback so the test binary's rate-limit buckets don't leak across test cases.

type (): void

returns void

TestMiddlewareStackApp
#

testing/middleware.ts view source

TestMiddlewareStackApp

app

type Hono

mock_validate

type ReturnType<typeof vi.fn>

mock_find_by_id

type ReturnType<typeof vi.fn>

mock_find_actor_by_id

type ReturnType<typeof vi.fn>

mock_find_actors_by_account

type ReturnType<typeof vi.fn>

mock_find_active_for_actor

type ReturnType<typeof vi.fn>

TestMiddlewareStackOptions
#

testing/middleware.ts view source

TestMiddlewareStackOptions

trusted_proxies

Trusted proxy IPs.

type Array<string>

allowed_origins

Comma-separated allowed origin patterns.

type string

connection_ip

Connection IP or factory.

type string | (() => string | undefined)

ip_rate_limiter

Rate limiter for bearer auth.

type RateLimiter | null

TestRoleGrantOverrides
#

ThrowingApi
#

actions/rpc_client.ts view source

ThrowingApi<TApi>

Maps a typed ActionsApi to a throwing variant.

For each method whose return type matches the create_rpc_client shape (Promise<Result<{value: T}, {error: JsonrpcErrorObject}>>), the wrapped method returns Promise<T> directly. Other shapes (notifications typed as => void, sync local_call methods) pass through unchanged โ€” there is nothing to unwrap.

Input + options parameters are preserved verbatim via ...args: infer TArgs so the conditional matches both required-input (input: T) and optional-input (input?: T / nullary) signatures uniformly. Required-input shapes (e.g. admin_session_revoke_all(input: AdminSessionRevokeAllInput)) are not assignable to a (input?: TInput) => โ€ฆ pattern under --strictFunctionTypes, so an earlier (input?, options?) => form silently fell through to TApi[K] and left those methods Result-shaped โ€” create_admin_rpc_adapters(api) would then reject the typed throwing Proxy because half its surface still returned Result<...>. The rest-args form preserves both required and optional parameters and resolves the gap.

generics

TApi

ThrownJsonrpcError
#

http/jsonrpc_errors.ts view source

Error class carrying a JSON-RPC error code โ€” thrown by handlers, caught by apply_route_specs and mapped to HTTP status + JSON-RPC error response.

Named for what it is: an error with a JSON-RPC error code that gets thrown.

inheritance

extends:
  • Error

code

type JsonrpcErrorCode

data

type unknown

constructor

type new (code: -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<"JsonrpcServerErrorCode">), message: string, data?: unknown, options?: ErrorOptions | undefined): ThrownJsonrpcError

code
type -32700 | -32600 | -32601 | -32602 | -32603 | (number & $brand<"JsonrpcServerErrorCode">)
message
type string
data?
type unknown
optional
options?
type ErrorOptions | undefined
optional

to_action_spec_identifier
#

to_action_spec_input_identifier
#

to_action_spec_output_identifier
#

to_admin_account
#

auth/account_schema.ts view source

(account: Account): { id: string & $brand<"Uuid">; username: string; email: string | null; email_verified: boolean; created_at: string; updated_at: string; updated_by: (string & $brand<...>) | null; }

Convert an Account to an AdminAccountJson for admin listings.

account

the full account record

type Account

returns

{ id: string & $brand<"Uuid">; username: string; email: string | null; email_verified: boolean; created_at: string; updated_at: string; updated_by: (string & $brand<"Uuid">) | null; }

the admin-safe account with audit fields

to_jsonrpc_message_id
#

http/jsonrpc_helpers.ts view source

(message_or_id: unknown): string | number | null

Extracts a JSON-RPC request id from a message or raw value. Returns null if no valid id can be extracted.

message_or_id

type unknown

returns

string | number | null

to_jsonrpc_params
#

http/jsonrpc_helpers.ts view source

(input: unknown): Record<string, any> | undefined

Normalizes input to JSON-RPC params format. Returns undefined for null/undefined, wraps primitives in {value}.

input

type unknown

returns

Record<string, any> | undefined

to_jsonrpc_result
#

http/jsonrpc_helpers.ts view source

(output: unknown): Record<string, any>

Normalizes output to JSON-RPC result format. Returns empty object for null/undefined, wraps primitives in {value}.

output

type unknown

returns

Record<string, any>

to_max_length
#

cli/help.ts view source

<T>(items: T[], to_string: (item: T) => string): number

Get maximum length from array.

items

array of items

type T[]

to_string

function to convert item to string for length measurement

type (item: T) => string

returns

number

maximum string length

to_role_grant_offer_json
#

auth/role_grant_offer_schema.ts view source

(offer: RoleGrantOffer): { id: string & $brand<"Uuid">; from_actor_id: string & $brand<"Uuid">; to_account_id: string & $brand<"Uuid">; ... 12 more ...; resulting_role_grant_id: (string & $brand<...>) | null; }

Convert a RoleGrantOffer row to its JSON payload shape.

offer

returns

{ id: string & $brand<"Uuid">; from_actor_id: string & $brand<"Uuid">; to_account_id: string & $brand<"Uuid">; to_actor_id: (string & $brand<"Uuid">) | null; ... 11 more ...; resulting_role_grant_id: (string & $brand<...>) | null; }

to_session_account
#

TokenCreateInput
#

TokenCreateOutput
#

auth/account_action_specs.ts view source

ZodObject<{ ok: ZodLiteral<true>; token: ZodString; id: ZodString; name: ZodString; }, $strict>

Output for account_token_create. token is returned exactly once.

TokenListInput
#

TokenListOutput
#

auth/account_action_specs.ts view source

ZodObject<{ tokens: ZodArray<ZodObject<{ id: ZodString; account_id: $ZodBranded<ZodUUID, "Uuid", "out">; name: ZodString; expires_at: ZodNullable<ZodString>; last_used_at: ZodNullable<...>; last_used_ip: ZodNullable<...>; created_at: ZodString; }, $strict>>; }, $strict>

Output for account_token_list. Hashes are excluded.

TokenRevokeInput
#

TokenRevokeOutput
#

TransitionFunction
#

Transport
#

TransportForMethod
#

actions/rpc_client.ts view source

TransportForMethod

Optional per-method transport selector. Return the transport to use for a given method, or undefined to let the peer pick via its fallback rules.

Useful when methods are registered on different backend dispatchers โ€” e.g. a streaming action mounted on the WebSocket endpoint while the rest of the RPC surface lives on HTTP.

TransportName
#

Transports
#

actions/transports.ts view source

allow_fallback

Whether to allow fallback to other transports if the current one is not available.

type boolean

register_transport

Registers a transport. The first transport registered also becomes the current.

type (transport: Transport): void

transport
returns void

set_current_transport

Switch the current transport selection by name.

type (transport_name: string): void

transport_name
type string
returns void
throws
  • Error - if no transport with `transport_name` has been registered

get_transport

Resolve a transport. With allow_fallback, walks specified โ†’ current โ†’ any-ready; without, returns the named transport (or current) only when it's ready.

type (transport_name?: string | undefined): Transport | null

transport_name?
type string | undefined
optional
returns Transport | null

the resolved transport, or null when none is ready

is_ready

type (): boolean | null

returns boolean | null

get_current_transport

type (): Transport | null

returns Transport | null

get_current_transport_name

type (): string | null

returns string | null

get_transport_by_name

type (transport_name: string): Transport | null

transport_name
type string
returns Transport | null

TransportSendOptions
#

actions/transports.ts view source

TransportSendOptions

Per-call options accepted by every transport's send. Optional and extensible โ€” adding a field is non-breaking. Source of truth for the shared option shape; ActionPeerSendOptions and RpcClientCallOptions extend it.

signal

Per-call cancellation. Bottoms out at FrontendWebsocketClient.request({signal}) on the WS path (sends the shared cancel notification on abort) and at fetch({signal}) on HTTP. Backend transport has no per-call abort surface to honor.

type AbortSignal

queue

Per-call durable-queue opt-in. Names the client-authoritative vs server-authoritative distinction โ€” server-authoritative consumers (e.g. zzz completion calls) fail fast with service_unavailable when the transport is down; client-authoritative consumers (games, real-time apps) buffer and replay on reconnect because the user already committed to the action at click time. Honored only by FrontendWebsocketTransport on the request_response path (default false). HTTP and backend transports ignore it; WS notifications also ignore it and always fail-fast when disconnected (fire-and-forget connection.send has no queue semantic).

type boolean

truncate_middle
#

ui/ui_format.ts view source

(str: string, max_length: number, separator?: string): string

Truncate a string by keeping the start and end, with a separator in the middle.

str

type string

max_length

total length including separator

type number

separator

type string
default 'โ€ฆ'

returns

string

the truncated string, or the original if it fits

truncate_uuid
#

ui/ui_format.ts view source

(uuid: string): string

Truncate a UUID for display, keeping start and end visible.

uuid

type string

returns

string

a 12-character truncated UUID like a1b2cโ€ฆ7890

ts_default_capabilities
#

testing/cross_backend/default_backend_configs.ts view source

BackendCapabilities

Capabilities shared by TS-family backends โ€” same canonical implementation, same feature set. No trusted-proxy phase (the test binary doesn't enable proxy parsing) and no per-account login rate limit (the TS canonical path leaves the limiter null in test mode).

ui_fetch
#

ui/ui_fetch.ts view source

(input: RequestInfo | URL, init?: RequestInit | undefined): Promise<Response>

Fetch with credentials included (sends cookies).

input

type RequestInfo | URL

init?

type RequestInit | undefined
optional

returns

Promise<Response>

UncoveredEntry
#

testing/error_coverage.ts view source

UncoveredEntry

Uncovered entry โ€” either a status-level row (no code) or a specific-code row.

method

type string

path

type string

status

type number

code

Declared code value missing, when the status's error schema names specific codes.

type string

UNKNOWN_ERROR_MESSAGE
#

update_env_variable
#

env/update_env_variable.ts view source

(key: string, value: string, options: UpdateEnvVariableOptions): Promise<void>

Updates or adds an environment variable in the .env file. Preserves existing formatting, comments, and other variables.

Behavior: - Duplicate keys: updates the LAST occurrence (matches dotenv behavior) - Inline comments: preserved after the value (e.g., KEY=value # comment) - Quote style: preserved from original (quoted/unquoted)

key

the environment variable name (e.g., 'SOME_CONFIGURATION_KEY')

type string

value

the new value for the environment variable

type string

options

file path and optional read/write overrides

returns

Promise<void>

throws

  • Error - if the file read fails for any reason other than `ENOENT`, or if the write fails

UpdateAppSettingsInput
#

UpdateEnvVariableOptions
#

env/update_env_variable.ts view source

UpdateEnvVariableOptions

Options for updating environment variables in a .env file.

env_file_path

Path to the .env file.

type string

read_file

Function to read file contents (defaults to node:fs/promises readFile).

type (path: string, encoding: string) => Promise<string>

write_file

Function to write file contents (defaults to node:fs/promises writeFile).

type (path: string, content: string, encoding: string) => Promise<void>

Username
#

primitive_schemas.ts view source

ZodPipe<ZodString, ZodTransform<string, string>>

Username for account creation โ€” starts with letter, alphanumeric/dash/underscore middle, ends with alphanumeric. No @ or . allowed.

Canonicalized to lowercase at parse time. The regex rejects whitespace outright, so .trim() is unnecessary here. Storage is canonical across every creation site (bootstrap, signup, admin-create, invite acceptance) because the schema is the single source of truth โ€” eliminates the per-caller trim().toLowerCase() ritual and keeps the LOWER(username) = LOWER($1) lookup contract simple.

USERNAME_LENGTH_MAX
#

USERNAME_LENGTH_MIN
#

USERNAME_PROVIDED_LENGTH_MAX
#

UsernameProvided
#

primitive_schemas.ts view source

ZodPipe<ZodString, ZodTransform<string, string>>

Username submitted for login or lookup โ€” minimal validation for forward-compatibility if format rules change.

Canonicalized via .trim().toLowerCase() at parse time so login's per-account rate-limit key and DB lookup see a uniform value regardless of casing or surrounding whitespace. Mirrors the storage canonicalization on Username so submission and storage agree.

VALID_SQL_IDENTIFIER
#

db/sql_identifier.ts view source

RegExp

Pattern matching valid SQL identifiers: starts with a letter or underscore, followed by letters, digits, or underscores.

validate_daemon_token
#

auth/daemon_token.ts view source

(provided: string, state: DaemonTokenState): boolean

Validate a daemon token against the current state.

Accepts both the current and previous token (2-token race window). Uses timing-safe comparison.

provided

the token from the X-Daemon-Token header

type string

state

the daemon token state

returns

boolean

true if the token is valid

validate_env_vars
#

env/resolve.ts view source

(runtime: Pick<EnvDeps, "env_get">, refs: EnvVarRef[]): EnvValidationResult

Validate that all referenced env vars exist in the environment.

Returns all missing refs (including duplicates by name). Grouping and deduplication is handled by format_missing_env_vars at display time. Refs marked optional: true (from $$?VAR$$ syntax) are skipped โ€” a deliberately-blank var is contract, not a missing dependency.

runtime

runtime with env_get capability

type Pick<EnvDeps, "env_get">

refs

env var references from scan_env_vars

type EnvVarRef[]

returns

EnvValidationResult

validation result with any missing vars

validate_ip_strict
#

http/proxy.ts view source

(ip: string): "IPv4" | "IPv6" | undefined

Strict IP validity check.

Defense in depth around Hono's hono/utils/ipaddr helpers, which are lax in two ways:

1. distinctRemoteAddr classifies anything-with-a-colon as 'IPv6', including 'host:port', 'attacker:controlled', '203.0.113.1:8080'. 2. convertIPv6ToBinary silently accepts malformed forms like '[::1]:8080' and '::1\n', parsing them as inconsistent binary values that would still serve as distinct rate-limit keys for an attacker rotating the suffix.

Strict validation here is two-layered: a character-set pre-filter (IP_LITERAL_CHARS), then a round-trip through convertIPv*ToBinary to confirm the input parses cleanly. Either layer alone has holes; together they reject every input form we've seen Hono mis-handle.

Used as the security primitive for any code path that takes an IP string from an untrusted source (XFF, query params) and uses it as a key (rate limiting, audit subject) or compares it against trusted proxies via CIDR (where the latent throw would otherwise bubble out).

ip

type string

returns

"IPv4" | "IPv6" | undefined

the address family on success, undefined if the string is not a strictly-valid IP

validate_keyring
#

auth/keyring.ts view source

(env_value: string | undefined): string[]

Validate key ring configuration.

Returns an error when no keys are configured (undefined, empty string, or all-separator input like '____'), and for each key shorter than MIN_KEY_LENGTH characters.

env_value

the SECRET_FUZ_COOKIE_KEYS environment variable

type string | undefined

returns

string[]

array of validation errors (empty if valid)

validate_nginx_config
#

server/validate_nginx.ts view source

(config: string): NginxValidationResult

Validate an nginx config template string for security properties.

Checks for required security headers, Authorization stripping in /api blocks, and the nginx add_header inheritance gotcha. Designed for fuz_app consumer deploy configs (zap.ts NGINX_CONFIG constants).

Limitations: string pattern matching, not a real nginx parser. Catches common omissions in fuz_app deploy configs but won't catch all possible misconfigurations.

config

type string

returns

NginxValidationResult

validate_phase_for_kind
#

actions/action_event_helpers.ts view source

(kind: "request_response" | "remote_notification" | "local_call", phase: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"): void

Validate that phase is one of the phases allowed for kind per action_event_phase_by_kind.

kind

type "request_response" | "remote_notification" | "local_call"

phase

type "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"

returns

void

throws

  • Error - if `phase` is not valid for `kind`

validate_phase_transition
#

actions/action_event_helpers.ts view source

(from: "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute", to: "send_request" | "receive_request" | ... 6 more ... | "execute"): void

Validate that a phase chain is legal per action_event_phase_transitions.

from

type "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"

to

type "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"

returns

void

throws

  • Error - if `from โ†’ to` is not the permitted next phase (or `from` is terminal)

validate_server_env
#

server/env.ts view source

(env: { NODE_ENV: "development" | "production"; PORT: number; HOST: string; DATABASE_URL: string; SECRET_FUZ_COOKIE_KEYS: string; FUZ_ALLOWED_ORIGINS: string; PUBLIC_FUZ_API_URL: string; ... 5 more ...; SMTP_PASSWORD?: string | undefined; }): ServerEnvOptionsResult

Validate a loaded BaseServerEnv and produce the artifacts needed for server init.

Handles keyring validation, origin parsing, and bootstrap token path extraction. Returns a Result so callers handle errors their own way (exit, logging, etc).

env

a loaded and Zod-validated BaseServerEnv

type { NODE_ENV: "development" | "production"; PORT: number; HOST: string; DATABASE_URL: string; SECRET_FUZ_COOKIE_KEYS: string; FUZ_ALLOWED_ORIGINS: string; PUBLIC_FUZ_API_URL: string; PUBLIC_FUZ_WEBSOCKET_URL?: string | undefined; ... 4 more ...; SMTP_PASSWORD?: string | undefined; }

returns

ServerEnvOptionsResult

{ok: true, keyring, allowed_origins, bootstrap_token_path} or {ok: false, field, errors}

validate_step_transition
#

actions/action_event_helpers.ts view source

(from: "initial" | "parsed" | "handling" | "handled" | "failed", to: "initial" | "parsed" | "handling" | "handled" | "failed"): void

Validate that a step transition is legal per action_event_step_transitions.

from

type "initial" | "parsed" | "handling" | "handled" | "failed"

to

type "initial" | "parsed" | "handling" | "handled" | "failed"

returns

void

throws

  • Error - if `from โ†’ to` is not a permitted transition

ValidatedKeyringResult
#

ValidationError
#

http/error_schemas.ts view source

ZodObject<{ error: ZodEnum<{ invalid_request_body: "invalid_request_body"; invalid_json_body: "invalid_json_body"; invalid_route_params: "invalid_route_params"; invalid_query_params: "invalid_query_params"; }>; issues: ZodOptional<...>; }, $loose>

Input validation error โ€” returned when params / query / body fails Zod parsing, or when the request body is not valid JSON.

error is one of the four validation codes the framework emits. issues carries Zod's validation issues for diagnostic display on the three schema-failure cases (invalid_request_body, invalid_route_params, invalid_query_params). The invalid_json_body case (request body parse failure or non-object root) emits no issues, so the field is optional.

verify_dummy
#

auth/password_argon2.ts view source

(password: string): Promise<boolean>

Verify a password against a dummy hash for timing attack resistance.

Always returns false, but takes the same time as a real verification. Call when account lookup fails to prevent timing-based user enumeration.

password

the plaintext password to "verify"

type string

returns

Promise<boolean>

always false

verify_password
#

auth/password_argon2.ts view source

(password: string, password_hash: string): Promise<boolean>

Verify a password against an Argon2id hash.

password

the plaintext password to verify

type string

password_hash

the Argon2id hash to verify against

type string

returns

Promise<boolean>

true if the password matches

verify_request_source
#

http/origin.ts view source

(allowed_patterns: readonly RegExp[]): Handler

Middleware that verifies the request source against an allowlist.

Origin allowlisting (not the CSRF layer โ€” that's SameSite: strict cookies): - Checks the Origin header (if present) against the allowlist - Allows requests without an Origin header (direct access, curl, etc.)

Origin-only by design โ€” Fetch spec mandates Origin on every unsafe method (POST / PUT / DELETE / PATCH) regardless of Referrer-Policy, so every real browser request on the state-changing surface carries it. Non-browser clients (curl, server-to-server, CLI) don't ship auto- attached session cookies, so CSRF isn't the relevant threat there โ€” auth (bearer / daemon token) is the actual control. A Referer fallback would only widen the accepted-shape envelope without closing a real CSRF hole; mirrors zzz_server::auth::is_request_origin_allowed.

allowed_patterns

compiled regex patterns from parse_allowed_origins

type readonly RegExp[]

returns

Handler

VerifyInput
#

WebsocketConnection
#

actions/transports_ws.ts view source

WebsocketConnection

Minimal interface for a WebSocket connection, decoupled from the concrete Socket Cell.

send

type (data: object) => boolean

connected

type boolean
readonly

add_message_handler

type (handler: (event: MessageEvent) => void) => () => void

add_error_handler

type (handler: (event: Event) => void) => () => void

WebsocketRpcConnection
#

actions/transports_ws.ts view source

WebsocketRpcConnection

RPC-capable WebSocket connection โ€” a WebsocketConnection that also handles request/response correlation with timeout, queue, AbortSignal cancel, and explicit-id support. Required by FrontendWebsocketTransport so it can delegate the pending-map bookkeeping to one canonical implementation (FrontendWebsocketClient) instead of running a parallel one.

Consumer wrappers around FrontendWebsocketClient (e.g. zzz's Socket) implement this by adding a one-line delegate to the underlying client's request.

inheritance

request

type ( method: string, params: unknown, options?: {signal?: AbortSignal; queue?: boolean; id?: JsonrpcRequestId}, ) => Promise<unknown>

write_daemon_info
#

cli/daemon.ts view source

(runtime: Pick<EnvDeps, "env_get"> & Pick<FsWriteDeps, "mkdir" | "write_text_file" | "rename">, name: string, info: { version: number; pid: number; port: number; started: string; app_version: string; }): Promise<...>

Write daemon info to the PID file, creating directories as needed.

runtime

runtime with file write and env capabilities

type Pick<EnvDeps, "env_get"> & Pick<FsWriteDeps, "mkdir" | "write_text_file" | "rename">

name

application name

type string

info

daemon info to write

type { version: number; pid: number; port: number; started: string; app_version: string; }

returns

Promise<void>

throws

  • Error - if `$HOME` is not set

write_daemon_token
#

auth/daemon_token_middleware.ts view source

(runtime: DaemonTokenWriteDeps, token_path: string, token: string): Promise<void>

Write the current token to disk atomically.

Uses write_file_atomic (temp file + rename) and optionally sets mode 0600.

On-disk format is JSON {"token": "..."} โ€” the wrapper leaves room for future fields (rotated_at, version) without changing every reader. Both the TS cross-backend harness reader (spawn_backend.read_daemon_token) and the Rust daemon-token writer match this shape.

runtime

runtime with file write capabilities

token_path

path to write the token

type string

token

the raw token string

type string

returns

Promise<void>

write_file_atomic
#

runtime/fs.ts view source

(deps: Pick<FsWriteDeps, "write_text_file" | "rename">, path: string, content: string): Promise<void>

Write a file atomically via temp file + rename.

Writes to <path>.tmp then renames over path so readers either see the old contents or the full new contents โ€” never a partial write.

deps

type Pick<FsWriteDeps, "write_text_file" | "rename">

path

type string

content

type string

returns

Promise<void>

throws

  • Error - if `write_text_file` or `rename` rejects (permissions, disk full, cross-device rename, etc.)

WS_CLIENT_DEFAULT_TIMEOUT_MS
#

WS_CLOSE_CLIENT_HEARTBEAT_TIMEOUT
#

WS_CLOSE_SERVER_HEARTBEAT_TIMEOUT
#

WS_CLOSE_SESSION_REVOKED
#

ws_disconnect_event_types
#

actions/transports_ws_auth_guard.ts view source

ReadonlySet<string>

Audit event types that trigger WebSocket socket closure.

- session_revoke โ€” close only the socket tied to the revoked session hash. - token_revoke โ€” close only the socket(s) authenticated with the revoked api_token.id. - session_revoke_all / token_revoke_all / password_change โ€” close every socket for the affected account (all credentials invalidated).

role_grant_revoke is intentionally omitted: the WS transport does not track per-connection role requirements, so role-scoped disconnection would require either closing all sockets (too aggressive) or new tracking (out of scope). Consumers that need it compose their own callback.

WsClient
#

testing/transports/ws_client.ts view source

WsClient

A test WS client: send requests, inspect / await incoming messages.

send

Send a JSON-RPC message (request or notification) to the server.

type (message: unknown) => Promise<void>

request

Send a JSON-RPC request and await its response. Resolves with the result; throws with a useful message (code, text, and any data payload) on an error frame โ€” without this, asserting on result.foo for a failed request throws Cannot read property 'foo' of undefined, hiding the real cause. Use send + wait_for(is_response_for(id)) directly when the test needs to assert on the error frame itself.

type <R = unknown>( id: number | string, method: string, params: unknown, timeout_ms?: number, ) => Promise<R>

close

Close the connection. Returns a promise that resolves once the transport's own cleanup (and any on_socket_close for the in-process driver) has completed โ€” tests that assert on post-close state should await.

type (code?: number, reason?: string) => Promise<void>

messages

Every message the server has sent, in arrival order.

type ReadonlyArray<unknown>
readonly

wait_for

Wait until a message satisfies predicate. Matches are checked against already-received messages first, then new arrivals until the timeout (defaults to WS_CLIENT_DEFAULT_TIMEOUT_MS).

When predicate is a type guard (e.g. is_notification_with<P>), the result is narrowed automatically and callers don't need to spell <JsonrpcNotificationFrame<P>> on the call site.

type { <T>(predicate: (msg: unknown) => msg is T, timeout_ms?: number): Promise<T>; // eslint-disable-next-line @typescript-eslint/unified-signatures <T = unknown>(predicate: (msg: unknown) => boolean, timeout_ms?: number): Promise<T>; }

WsConnectIdentity
#

testing/ws_round_trip.ts view source

WsConnectIdentity

Auth identity for a mock connection.

account_id

Account id for the connection. Defaults to a fresh uuid per call.

type Uuid

credential_type

Credential type. Defaults to 'session'. Keeper actions require 'daemon_token'.

session_id

Session id (any string). Defaults to a fresh uuid. Hashed by the dispatcher.

type string

api_token_id

Api token id; set for bearer connections, null otherwise.

type string | null

roles

Roles to grant via active role_grants. Pass [ROLE_KEEPER] for keeper actions.

type Array<string>

WsEndpointSpec
#

actions/ws_endpoint_spec.ts view source

WsEndpointSpec

Declarative description of a WebSocket endpoint to be auto-mounted by create_app_server.

Single source of truth for mount + surface โ€” the same array drives register_ws_endpoint-style upgrade wiring AND the surface.ws_endpoints slot emitted into AppSurface, so consumers cannot drift their declared actions from what dispatch actually serves.

path

Hono mount path (e.g. /api/ws).

type string

allowed_origins

Origin allowlist regexes โ€” typically parsed via parse_allowed_origins. Passed straight to verify_request_source on upgrade.

type ReadonlyArray<RegExp>

actions

The actions registered on this endpoint. Spread protocol_actions from actions/protocol.ts first to complete the disconnect-detection + per-request cancel pairing with the frontend client.

type ReadonlyArray<Action>

required_roles

Roles permitted to upgrade โ€” any-of disjunction. Omit (or pass []) to skip the upgrade-time role gate; per-action auth on each spec still applies at dispatch time via perform_action. Pass [ROLE_ADMIN] for a zap-style admin-only WS endpoint.

type ReadonlyArray<RoleName>

transport

Existing transport to register connections with. Auto-created when omitted. Either way the mounted transport is reachable on AppServer.ws_endpoints[path] for broadcast / fan-out.

heartbeat

Server-side heartbeat policy. Default-on (60s receive-silence timeout). Set false only when an upstream stack (TCP keepalive, Cloudflare idle timeout) already owns disconnect detection.

type boolean | ServerHeartbeatOptions

artificial_delay

Optional per-message delay for testing loading states.

type number

on_socket_open

Called once per socket after transport.add_connection but before the first message dispatches. See RegisterActionWsOptions.on_socket_open.

type (ctx: SocketOpenContext) => void | Promise<void>

on_socket_close

Called once per socket on close, before transport.remove_connection. See RegisterActionWsOptions.on_socket_close.

type (ctx: SocketCloseContext) => void | Promise<void>

auth_guard

Default true โ€” auto-composes create_ws_auth_guard + create_ws_logout_closer against this endpoint's transport and appends them to deps.audit.on_event_chain. Wiring is deduped by transport reference identity (WeakSet<BackendWebsocketTransport>), so two WsEndpointSpecs sharing the exact same instance get a single pair of listeners.

Shared-transport OR-semantics. When multiple WsEndpointSpecs share one transport, the guard is wired iff any of those specs has auth_guard !== false. To opt out for a shared transport, every sibling spec must pass auth_guard: false. The default is "fail safe" โ€” easier to enable than disable, and predictable regardless of spec order.

Reference-identity dedupe means wrapped or proxied transports dedupe as separate entries โ€” a consumer threading every transport through a tracing / DI / metrics shim will get a fresh pair of listeners per shimmed reference, even when the underlying transport is the same. If you wrap or proxy, set `auth_guard: false on the duplicate WsEndpointSpec`s and compose create_ws_auth_guard / create_ws_logout_closer against the underlying transport once.

Set false when a consumer needs to compose their own callback from scratch โ€” or to opt out of the auto-wiring entirely.

NOTE: does NOT close sockets on role_grant_revoke โ€” that omission is deliberate (per-connection role tracking is out of scope). A user whose admin role is revoked keeps their socket open; the next message gets forbidden from the per-message authorization phase. Consumers wanting role-revoke disconnection use extra_audit_handlers.

type boolean

extra_audit_handlers

Extra audit-event handlers appended to deps.audit.on_event_chain AFTER the standard auth_guard wiring (when enabled). By the time these run, the standard guards may have already closed sockets. Use for role-revoke disconnection, custom analytics, etc.

Never deduped โ€” consumer-owned; pass the same handler twice and it fires twice.

type ReadonlyArray<AuditEventHandler>

WsTestHarness
#

testing/ws_round_trip.ts view source

WsTestHarness

A harness instance โ€” transport handle + connection factory.

transport

connect

Open a mock connection. Resolves after on_socket_open (and the transport's register_ws) completes, so broadcasts issued immediately after the await reach the connection. Earlier revisions returned synchronously and required a settle_open() microtask drain โ€” no longer necessary.

Returns the shared WsClient interface โ€” same surface the cross-process driver in transports/ws_transport.ts implements, so assertion helpers and suite bodies work against either impl.

type (identity?: WsConnectIdentity) => Promise<WsClient>

WsTransportOptions
#

testing/transports/ws_transport.ts view source

WsTransportOptions

Construction options for create_ws_transport.

base_url

Base URL the binary is reachable at โ€” e.g. http://localhost:8788. Converted to ws:// for the upgrade.

type string
readonly

ws_path

WebSocket endpoint path on the binary (e.g. /api/ws).

type string
readonly

cookies

Session cookie values (full Set-Cookie strings as FetchTransport.cookies() returns them) threaded onto the upgrade Cookie header. Without these the upgrade is anonymous and per-action auth fails on the first message.

type ReadonlyArray<string>
readonly

origin

Origin header for the upgrade. Backends running with ALLOWED_ORIGINS=http://localhost:* accept http://localhost:<port>. Defaults to base_url โ€” acceptable because cross-process tests always run against localhost.

type string
readonly

default_timeout_ms

Optional per-call default for wait_for timeouts. Falls back to WS_CLIENT_DEFAULT_TIMEOUT_MS if omitted.

type number
readonly