auth/audit_log_schema.ts

Audit log types and client-safe Zod schemas.

Records auth mutations (login, logout, grant, revoke, etc.) for security monitoring and operational visibility.

Table DDL and indexes live in auth/audit_log_ddl.ts.

Declarations
#

20 declarations

view source

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).

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_DEFAULT_LIMIT
#

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.

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
#

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

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

AuditMetadataMap
#

AuditOutcome
#

BUILTIN_AUDIT_LOG_CONFIG
#

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 to create_app_backend (which threads it into AppDeps.audit). 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

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>>

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

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.

Depends on
#

Imported by
#