import type { PgTransaction } from "drizzle-orm/pg-core";
import * as schema from "./schema";
export type TenantTx = PgTransaction<any, typeof schema, any>;
export interface TenantContext {
    workspaceId: number | string;
    userId: number | string;
}
/**
 * The one place a tenant-scoped request enters a transaction (ADR-003 / §4.5).
 * `SET LOCAL` is transaction-scoped, so RLS's `current_setting('app.current_*')`
 * is only ever valid for the lifetime of the callback. Uses `set_config(...,
 * true)` rather than a literal `SET LOCAL` string so the values stay
 * parameterised — never string-interpolate caller-supplied ids into SQL here.
 *
 * Every Core function that accepts a caller-supplied resource id used together
 * with another id (e.g. "pin message X into channel Y") must still fetch the
 * more-specific resource and assert the relationship before writing — RLS
 * scopes by workspace_id, not by the specific-resource relationship, and FK
 * validation itself bypasses RLS. See the pin_message-style gap in project
 * history; do not assume RLS alone makes cross-resource writes safe.
 */
export declare function withTenant<T>(ctx: TenantContext, fn: (tx: TenantTx) => Promise<T>): Promise<T>;
/**
 * For queries that are inherently cross-tenant from the *user's* point of
 * view — "list every workspace I belong to" — rather than scoped to one
 * workspace. Leaves `app.current_workspace_id` unset; relies on each
 * RLS-protected table's `self_membership` policy (see sql/rls.sql), which is
 * keyed on `current_user_id` alone. Never use this for a query that accepts
 * a caller-supplied resource id — that still needs `withTenant` plus the
 * fetch-and-check pattern for cross-resource relationships.
 */
export declare function withUser<T>(userId: number | string, fn: (tx: TenantTx) => Promise<T>): Promise<T>;
//# sourceMappingURL=tenant.d.ts.map