/**
 * 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`.
 *
 * @module
 */
import { z } from 'zod';
import { Uuid } from '@fuzdev/fuz_util/id.js';
/**
 * 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.
 */
export declare const AUDIT_EVENT_TYPES: readonly ["login", "logout", "bootstrap", "signup", "password_change", "session_revoke", "session_revoke_all", "token_create", "token_revoke", "token_revoke_all", "role_grant_create", "role_grant_revoke", "role_grant_offer_create", "role_grant_offer_accept", "role_grant_offer_decline", "role_grant_offer_retract", "role_grant_offer_expire", "role_grant_offer_supersede", "invite_create", "invite_delete", "account_delete", "account_purge", "account_undelete", "actor_delete", "actor_purge", "actor_undelete", "app_settings_update"];
/** Zod schema for audit event types. */
export declare const AuditEventType: z.ZodEnum<{
    bootstrap: "bootstrap";
    login: "login";
    logout: "logout";
    signup: "signup";
    password_change: "password_change";
    session_revoke: "session_revoke";
    session_revoke_all: "session_revoke_all";
    token_create: "token_create";
    token_revoke: "token_revoke";
    token_revoke_all: "token_revoke_all";
    role_grant_create: "role_grant_create";
    role_grant_revoke: "role_grant_revoke";
    role_grant_offer_create: "role_grant_offer_create";
    role_grant_offer_accept: "role_grant_offer_accept";
    role_grant_offer_decline: "role_grant_offer_decline";
    role_grant_offer_retract: "role_grant_offer_retract";
    role_grant_offer_expire: "role_grant_offer_expire";
    role_grant_offer_supersede: "role_grant_offer_supersede";
    invite_create: "invite_create";
    invite_delete: "invite_delete";
    account_delete: "account_delete";
    account_purge: "account_purge";
    account_undelete: "account_undelete";
    actor_delete: "actor_delete";
    actor_purge: "actor_purge";
    actor_undelete: "actor_undelete";
    app_settings_update: "app_settings_update";
}>;
export type AuditEventType = z.infer<typeof AuditEventType>;
/**
 * Letter start, then letters, digits, `_`, `.`, `/`, `-`. Accepts snake_case,
 * dotted, and namespaced consumer conventions; rejects empty strings, leading
 * separators, whitespace, and control characters.
 */
export declare const AUDIT_EVENT_TYPE_NAME_REGEX: RegExp;
/** Zod schema for valid audit event-type name strings. */
export declare const AuditEventTypeName: z.ZodString;
export type AuditEventTypeName = z.infer<typeof AuditEventTypeName>;
/** Zod schema for audit event outcomes. */
export declare const AuditOutcome: z.ZodEnum<{
    success: "success";
    failure: "failure";
}>;
export type AuditOutcome = z.infer<typeof AuditOutcome>;
/**
 * 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.
 */
export declare const audit_metadata_schemas: Readonly<{
    login: z.ZodNullable<z.ZodObject<{
        username: z.ZodString;
    }, z.core.$loose>>;
    logout: z.ZodNull;
    bootstrap: z.ZodNullable<z.ZodObject<{
        error: z.ZodString;
    }, z.core.$loose>>;
    signup: z.ZodObject<{
        username: z.ZodString;
        invite_id: z.ZodOptional<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
        open_signup: z.ZodOptional<z.ZodBoolean>;
        reason: z.ZodOptional<z.ZodString>;
        email: z.ZodOptional<z.ZodEmail>;
    }, z.core.$loose>;
    password_change: z.ZodNullable<z.ZodObject<{
        sessions_revoked: z.ZodOptional<z.ZodNumber>;
        tokens_revoked: z.ZodOptional<z.ZodNumber>;
        reason: z.ZodOptional<z.ZodEnum<{
            concurrent_change: "concurrent_change";
        }>>;
        credential_type: z.ZodOptional<z.ZodEnum<{
            daemon_token: "daemon_token";
            session: "session";
            api_token: "api_token";
        }>>;
    }, z.core.$loose>>;
    session_revoke: z.ZodObject<{
        session_id: z.ZodString;
        credential_type: z.ZodOptional<z.ZodEnum<{
            daemon_token: "daemon_token";
            session: "session";
            api_token: "api_token";
        }>>;
    }, z.core.$loose>;
    session_revoke_all: z.ZodObject<{
        count: z.ZodOptional<z.ZodNumber>;
        reason: z.ZodOptional<z.ZodString>;
        attempted_account_id: z.ZodOptional<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
        credential_type: z.ZodOptional<z.ZodEnum<{
            daemon_token: "daemon_token";
            session: "session";
            api_token: "api_token";
        }>>;
    }, z.core.$loose>;
    token_create: z.ZodObject<{
        token_id: z.ZodString;
        name: z.ZodString;
        credential_type: z.ZodOptional<z.ZodEnum<{
            daemon_token: "daemon_token";
            session: "session";
            api_token: "api_token";
        }>>;
    }, z.core.$loose>;
    token_revoke: z.ZodObject<{
        token_id: z.ZodString;
        credential_type: z.ZodOptional<z.ZodEnum<{
            daemon_token: "daemon_token";
            session: "session";
            api_token: "api_token";
        }>>;
    }, z.core.$loose>;
    token_revoke_all: z.ZodObject<{
        count: z.ZodOptional<z.ZodNumber>;
        reason: z.ZodOptional<z.ZodString>;
        attempted_account_id: z.ZodOptional<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
    }, z.core.$loose>;
    role_grant_create: z.ZodObject<{
        role: z.ZodString;
        role_grant_id: z.ZodOptional<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
        scope_id: z.ZodOptional<z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>>;
        source_offer_id: z.ZodOptional<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
        self_service: z.ZodOptional<z.ZodBoolean>;
    }, z.core.$loose>;
    role_grant_revoke: z.ZodObject<{
        role: z.ZodString;
        role_grant_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
        scope_id: z.ZodOptional<z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>>;
        reason: z.ZodOptional<z.ZodString>;
        self_service: z.ZodOptional<z.ZodBoolean>;
    }, z.core.$loose>;
    role_grant_offer_create: z.ZodObject<{
        offer_id: z.ZodOptional<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
        role: z.ZodString;
        scope_id: z.ZodOptional<z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>>;
        to_account_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
    }, z.core.$loose>;
    role_grant_offer_accept: z.ZodObject<{
        offer_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
        role_grant_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
        role: z.ZodString;
        scope_id: z.ZodOptional<z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>>;
    }, z.core.$loose>;
    role_grant_offer_decline: z.ZodObject<{
        offer_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
        role: z.ZodString;
        scope_id: z.ZodOptional<z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>>;
        reason: z.ZodOptional<z.ZodString>;
    }, z.core.$loose>;
    role_grant_offer_retract: z.ZodObject<{
        offer_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
        role: z.ZodString;
        scope_id: z.ZodOptional<z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>>;
    }, z.core.$loose>;
    role_grant_offer_expire: z.ZodObject<{
        offer_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
        role: z.ZodString;
        scope_id: z.ZodOptional<z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>>;
    }, z.core.$loose>;
    role_grant_offer_supersede: z.ZodObject<{
        offer_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
        role: z.ZodString;
        scope_id: z.ZodOptional<z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>>;
        reason: z.ZodEnum<{
            sibling_accepted: "sibling_accepted";
            role_grant_revoked: "role_grant_revoked";
            scope_destroyed: "scope_destroyed";
        }>;
        cause_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
    }, z.core.$loose>;
    invite_create: z.ZodObject<{
        invite_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
        email: z.ZodNullable<z.ZodString>;
        username: z.ZodNullable<z.ZodString>;
    }, z.core.$loose>;
    invite_delete: z.ZodObject<{
        invite_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
    }, z.core.$loose>;
    account_delete: z.ZodObject<{
        username: z.ZodOptional<z.ZodString>;
        email: z.ZodOptional<z.ZodNullable<z.ZodString>>;
        reason: z.ZodOptional<z.ZodString>;
        attempted_account_id: z.ZodOptional<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
    }, z.core.$loose>;
    account_purge: z.ZodObject<{
        username: z.ZodOptional<z.ZodString>;
        email: z.ZodOptional<z.ZodNullable<z.ZodString>>;
        reason: z.ZodOptional<z.ZodString>;
        attempted_account_id: z.ZodOptional<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
    }, z.core.$loose>;
    account_undelete: z.ZodObject<{
        username: z.ZodOptional<z.ZodString>;
        email: z.ZodOptional<z.ZodNullable<z.ZodString>>;
        reason: z.ZodOptional<z.ZodString>;
        attempted_account_id: z.ZodOptional<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
    }, z.core.$loose>;
    actor_delete: z.ZodObject<{
        name: z.ZodOptional<z.ZodString>;
    }, z.core.$loose>;
    actor_purge: z.ZodObject<{
        name: z.ZodOptional<z.ZodString>;
    }, z.core.$loose>;
    actor_undelete: z.ZodObject<{
        name: z.ZodOptional<z.ZodString>;
    }, z.core.$loose>;
    app_settings_update: z.ZodObject<{
        setting: z.ZodString;
        old_value: z.ZodUnknown;
        new_value: z.ZodUnknown;
    }, z.core.$loose>;
}>;
/** Mapped type of metadata shapes per event type, derived from Zod schemas. */
export type AuditMetadataMap = {
    [K in AuditEventType]: z.infer<(typeof audit_metadata_schemas)[K]>;
};
/** Audit log row from the database. See `AuditLogEventJson` for `event_type` widening rationale. */
export interface AuditLogEvent {
    id: Uuid;
    seq: number;
    event_type: AuditEventTypeName;
    outcome: AuditOutcome;
    /**
     * 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.
     */
    actor_id: Uuid | null;
    account_id: Uuid | null;
    target_account_id: Uuid | null;
    /**
     * 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.
     */
    target_actor_id: Uuid | null;
    ip: string | null;
    created_at: string;
    metadata: Record<string, unknown> | null;
}
/**
 * Narrow metadata type for a known event type.
 *
 * Use after checking `event_type` to get typed metadata access.
 */
export declare const get_audit_metadata: <T extends AuditEventType>(event: AuditLogEvent & {
    event_type: T;
}) => AuditMetadataMap[T] | null;
/** Input for creating an audit log entry. */
export interface AuditLogInput<T extends string = AuditEventType> {
    event_type: T;
    outcome?: AuditOutcome;
    actor_id?: Uuid | null;
    account_id?: Uuid | null;
    target_account_id?: Uuid | null;
    target_actor_id?: Uuid | null;
    ip?: string | null;
    /**
     * 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).
     */
    metadata?: T extends AuditEventType ? (AuditMetadataMap[T] & Record<string, unknown>) | null : Record<string, unknown> | null;
}
/**
 * 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.
 */
export interface AuditLogConfig {
    /** All recognized event-type strings — fuz_app builtins plus consumer extras. */
    readonly event_types: ReadonlyArray<string>;
    /**
     * Per-event-type metadata schemas. Missing entries skip metadata
     * validation for that type (row still written; metadata stored as raw JSONB).
     */
    readonly metadata_schemas: Readonly<Record<string, z.ZodType>>;
}
/** Builtin fuz_app audit-log config — every existing event type and its metadata schema. */
export declare const builtin_audit_log_config: AuditLogConfig;
/** Options for `create_audit_log_config`. */
export interface CreateAuditLogConfigOptions {
    /**
     * 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`).
     */
    extra_events?: Readonly<Record<string, z.ZodType | null>>;
}
/**
 * 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`.
 *
 * @throws Error when an `extra_events` key collides with a builtin event type or fails `AuditEventTypeName` format validation
 */
export declare const create_audit_log_config: (options?: CreateAuditLogConfigOptions) => AuditLogConfig;
/** Default page size for audit log listings. */
export declare const AUDIT_LOG_DEFAULT_LIMIT = 50;
/** Options for listing audit log entries. */
export interface AuditLogListOptions {
    limit?: number;
    offset?: number;
    /**
     * 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.
     */
    event_type?: string;
    event_type_in?: Array<string>;
    account_id?: Uuid;
    outcome?: AuditOutcome;
    /** When set, only return events with `seq` greater than this value. Enables SSE reconnection gap fill. */
    since_seq?: number;
}
/**
 * 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.
 */
export declare const AuditLogEventJson: z.ZodObject<{
    id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
    seq: z.ZodNumber;
    event_type: z.ZodString;
    outcome: z.ZodEnum<{
        success: "success";
        failure: "failure";
    }>;
    actor_id: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
    account_id: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
    target_account_id: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
    target_actor_id: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
    ip: z.ZodNullable<z.ZodString>;
    created_at: z.ZodString;
    metadata: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
}, z.core.$strict>;
export type AuditLogEventJson = z.infer<typeof AuditLogEventJson>;
/** Zod schema for audit log events with resolved usernames. */
export declare const AuditLogEventWithUsernamesJson: z.ZodObject<{
    id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
    seq: z.ZodNumber;
    event_type: z.ZodString;
    outcome: z.ZodEnum<{
        success: "success";
        failure: "failure";
    }>;
    actor_id: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
    account_id: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
    target_account_id: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
    target_actor_id: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
    ip: z.ZodNullable<z.ZodString>;
    created_at: z.ZodString;
    metadata: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
    username: z.ZodNullable<z.ZodString>;
    target_username: z.ZodNullable<z.ZodString>;
}, z.core.$strict>;
export type AuditLogEventWithUsernamesJson = z.infer<typeof AuditLogEventWithUsernamesJson>;
/** Zod schema for role_grant history events with resolved usernames. */
export declare const RoleGrantHistoryEventJson: z.ZodObject<{
    id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
    seq: z.ZodNumber;
    event_type: z.ZodString;
    outcome: z.ZodEnum<{
        success: "success";
        failure: "failure";
    }>;
    actor_id: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
    account_id: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
    target_account_id: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
    target_actor_id: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
    ip: z.ZodNullable<z.ZodString>;
    created_at: z.ZodString;
    metadata: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
    username: z.ZodNullable<z.ZodString>;
    target_username: z.ZodNullable<z.ZodString>;
}, z.core.$strict>;
export type RoleGrantHistoryEventJson = z.infer<typeof RoleGrantHistoryEventJson>;
/** Zod schema for admin session listing (session + username). */
export declare const AdminSessionJson: z.ZodObject<{
    id: z.ZodString;
    account_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
    created_at: z.ZodString;
    expires_at: z.ZodString;
    last_seen_at: z.ZodString;
    username: z.ZodString;
}, z.core.$strict>;
export type AdminSessionJson = z.infer<typeof AdminSessionJson>;
//# sourceMappingURL=audit_log_schema.d.ts.map