/**
 * Role grant offer types and client-safe schemas.
 *
 * An offer is a pending grant awaiting recipient consent. Lifecycle states
 * are mutually exclusive via a CHECK constraint (`role_grant_offer_single_terminal`):
 * at most one of `accepted_at` / `declined_at` / `retracted_at` may be set.
 * On accept, the offer's `resulting_role_grant_id` links to the role_grant row
 * produced by `query_accept_offer`.
 *
 * Table DDL and index-side sentinel constants live in `auth/role_grant_offer_ddl.ts`.
 *
 * @module
 */
import { z } from 'zod';
import { Uuid } from '@fuzdev/fuz_util/id.js';
/** Maximum length of the optional message attached to an offer. */
export declare const ROLE_GRANT_OFFER_MESSAGE_LENGTH_MAX = 500;
/** Default TTL for a newly created offer — 30 days. Matches GitHub org-invite expiry. */
export declare const ROLE_GRANT_OFFER_DEFAULT_TTL_MS: number;
/** Role grant offer row as returned by the database. */
export interface RoleGrantOffer {
    id: Uuid;
    from_actor_id: Uuid;
    to_account_id: Uuid;
    /**
     * 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.
     */
    to_actor_id: Uuid | null;
    role: string;
    /**
     * 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.
     */
    scope_kind: string | null;
    scope_id: Uuid | null;
    message: string | null;
    created_at: string;
    expires_at: string;
    accepted_at: string | null;
    declined_at: string | null;
    decline_reason: string | null;
    retracted_at: string | null;
    /**
     * 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.
     */
    superseded_at: string | null;
    resulting_role_grant_id: Uuid | null;
}
/**
 * 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.
 */
export interface SupersededOffer extends RoleGrantOffer {
    from_account_id: Uuid;
}
/**
 * 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`).
 */
export interface CreateRoleGrantOfferInput {
    from_actor_id: Uuid;
    to_account_id: Uuid;
    /**
     * 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.
     */
    to_actor_id?: Uuid | null;
    role: string;
    /**
     * 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(...)`.
     */
    scope_kind?: string | null;
    scope_id?: Uuid | null;
    message?: string | null;
    expires_at: Date;
}
/** Zod schema for client-safe role_grant offer data. */
export declare const RoleGrantOfferJson: z.ZodObject<{
    id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
    from_actor_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
    to_account_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
    to_actor_id: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
    role: z.ZodString;
    scope_kind: z.ZodNullable<z.ZodString>;
    scope_id: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
    message: z.ZodNullable<z.ZodString>;
    created_at: z.ZodString;
    expires_at: z.ZodString;
    accepted_at: z.ZodNullable<z.ZodString>;
    declined_at: z.ZodNullable<z.ZodString>;
    decline_reason: z.ZodNullable<z.ZodString>;
    retracted_at: z.ZodNullable<z.ZodString>;
    superseded_at: z.ZodNullable<z.ZodString>;
    resulting_role_grant_id: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
}, z.core.$strict>;
export type RoleGrantOfferJson = z.infer<typeof RoleGrantOfferJson>;
/** Convert a `RoleGrantOffer` row to its JSON payload shape. */
export declare const to_role_grant_offer_json: (offer: RoleGrantOffer) => RoleGrantOfferJson;
//# sourceMappingURL=role_grant_offer_schema.d.ts.map