import type { SqlParserLike } from './parser.js';
/** Configuration for {@link TenantScopeRewriter}. */
export interface TenantScopeConfig {
    /** The column that carries the tenant key on every scoped table (e.g. `base_id`, `org_id`). */
    tenantColumn: string;
    /** Tables that must be constrained to the caller's tenant when referenced. */
    scopedTables: string[];
}
/**
 * Rewrites a SELECT so every reference to a scoped table is constrained to a
 * single tenant: `<tenantColumn> = '<tenantRef>'` is AND-ed into the WHERE for
 * each scoped table in the FROM. An existing predicate for a different tenant
 * is rejected (no cross-tenant reads). `tenantRef === undefined` is the
 * privileged path and passes the SQL through unchanged.
 *
 * CRITICAL: only a strictly `=== undefined` tenantRef is privileged. A `null`
 * or empty-string tenantRef is NOT privileged — it flows into the rewrite and
 * injects a predicate that matches nothing (fail-closed), so a missing tenant
 * can never accidentally read every tenant's rows.
 *
 * Scoped mode rejects CTEs, UNION/INTERSECT/EXCEPT, and subqueries in FROM:
 * those make it impossible to statically guarantee every tenant-bearing source
 * is constrained, so we fail closed and ask the caller to rephrase.
 *
 * The `node-sql-parser` `Parser` is injected (see {@link loadSqlParser}) so this file never imports the
 * optional peer at module load.
 */
export declare class TenantScopeRewriter {
    private readonly parser;
    private readonly tenantColumn;
    private readonly scopedTables;
    constructor(config: TenantScopeConfig, parser: SqlParserLike);
    /** Rewrite `sql` to constrain scoped tables to `tenantRef`. Strictly-`undefined` → pass through. */
    rewrite(sql: string, tenantRef: string | undefined): string;
    /**
     * Every tenant-column `=` predicate anywhere in the tree (recurses into both `AND` and `OR`).
     * Used ONLY for the mismatch check: a query naming a foreign tenant anywhere must be rejected,
     * even where that predicate cannot be relied on to actually constrain the result set.
     */
    private collectAllTenantPredicates;
    /**
     * Tenant-column `=` predicates on the top-level `AND` spine only. Descent stops at `OR` (and at
     * any operator other than `AND`/`=`, e.g. `NOT`, which the parser represents as a `unary_expr`
     * and so is never a `binary_expr` here) because only a conjunctively-combined predicate is
     * guaranteed to hold for every row the query can return. Used for coverage: a table alias is
     * "already scoped" only when one of these covers it.
     */
    private collectConjunctiveTenantPredicates;
    private extractTenantPredicate;
    private buildTenantEquality;
    private andCondition;
    private forceParens;
}
//# sourceMappingURL=tenant-scope.d.ts.map