import type { Pool, PoolClient } from 'pg';
/**
 * Unique role name per worker. `process.pid` alone is not enough: in Vitest's
 * thread pool, parallel workers share one process (and thus one pid), so a random
 * suffix is appended to avoid role-name collisions across concurrent test files.
 */
export declare const RLS_TEST_ROLE: string;
/** A table privilege grant: e.g. `{ table: 'sort_codes', privileges: 'INSERT, SELECT' }`. */
export interface RlsRoleGrant {
    /** Unqualified table name (schema prefix is added automatically). */
    table: string;
    /** Comma-separated SQL privileges, e.g. `'SELECT'` or `'INSERT, SELECT'`. */
    privileges: string;
}
export interface RlsRoleOptions {
    /** Table privileges to grant the role for the queries under test. */
    grants?: RlsRoleGrant[];
}
/**
 * Idempotently create the per-process non-superuser RLS role and grant it schema
 * usage plus any requested table privileges.
 *
 * `CREATE ROLE` / `GRANT` are not meant to be rolled back per-test, so this runs
 * on its own connection outside any test transaction. Call from `beforeAll` and
 * pair with {@link dropRlsRole} in `afterAll`.
 */
export declare function ensureRlsRole(pool: Pool, options?: RlsRoleOptions): Promise<void>;
/**
 * Drop the RLS role. Mirror of {@link ensureRlsRole}.
 *
 * A bare `DROP ROLE` would fail while the role still holds the schema/table grants
 * from ensureRlsRole — Postgres tracks them in pg_shdepend and refuses to drop a
 * role other objects depend on. So we first `DROP OWNED BY`, which revokes every
 * privilege granted to the role in the current database, then drop the role. The
 * whole thing is guarded on role existence so a failed setup (role never created)
 * surfaces the real error instead of a "role does not exist" during teardown.
 */
export declare function dropRlsRole(pool: Pool): Promise<void>;
/**
 * Run `fn` with the connection's role dropped to the non-superuser RLS role, so
 * Postgres evaluates the RLS policies. The role switch is confined to a SAVEPOINT:
 * on success the role is reset and the savepoint released; on any error the
 * savepoint is rolled back (which also restores the original role) and the error
 * is rethrown for the caller to interpret (e.g. `42501` = WITH CHECK rejection).
 *
 * Set the relevant `app.*` session variables BEFORE calling this — as superuser,
 * before privileges are dropped.
 */
export declare function runAsRlsRole<T>(client: PoolClient, fn: () => Promise<T>): Promise<T>;
