import { type Injector } from 'graphql-modules';
import { CloudinaryProvider } from '../../app-providers/cloudinary.js';
import { DBProvider } from '../../app-providers/db.provider.js';
import { IngestOutcome } from '../contracts.js';
import { EmailIngestionControlProvider } from './email-ingestion-control.provider.js';
export type IngestInput = {
    grantJti: string;
    idempotencyKey: string;
    tenantId: string;
    messageId: string;
    rawMessageHash: string;
    correlationId?: string;
    extractedDocuments: Array<{
        hash: string;
        sizeBytes: number;
        mimeType: string;
        filename?: string | null;
        /** Base64-encoded document bytes (inline transport); omitted = metadata only. */
        content?: string | null;
    }>;
};
export type IngestResult = {
    outcome: typeof IngestOutcome.INSERTED;
    ingestId: string;
    auditId: string;
} | {
    outcome: typeof IngestOutcome.DUPLICATE;
    existingIngestId: string | null;
    auditId: string;
} | {
    outcome: typeof IngestOutcome.QUARANTINED;
    auditId: string;
    reasonCode: string;
} | {
    outcome: typeof IngestOutcome.REJECTED;
    reasonCode: string;
};
/**
 * Orchestrates the v2 ingest flow for gateway-initiated ingestion.
 *
 * The caller presents a gateway_control_plane auth token with an empty
 * businessId, so TenantAwareDBClient (which derives the tenant from the auth
 * session) cannot be used here — the authoritative tenant comes from the
 * single-use, cryptographically-validated grant instead. To still get RLS as a
 * second defense layer, all tenant-bound reads/writes run inside one
 * transaction whose `app.current_business_id` is pinned to the grant tenant
 * (see {@link withTenantContext}); the `tenant_isolation` WITH CHECK policies
 * on the idempotency/dedup/quarantine tables then enforce
 * `owner_id = tenantId` on top of the explicit owner_id filters in each query.
 *
 * Flow: grant validation → idempotency check → dedup check → quarantine or insert.
 */
export declare class EmailIngestionIngestProvider {
    private dbProvider;
    private controlProvider;
    private cloudinaryProvider;
    constructor(dbProvider: DBProvider, controlProvider: EmailIngestionControlProvider, cloudinaryProvider: CloudinaryProvider);
    performIngest(input: IngestInput, injector: Injector): Promise<IngestResult>;
    /**
     * Prepare documents for persistence WITHOUT holding the write transaction open:
     * dedup new documents by hash (a short read), then upload to Cloudinary and OCR
     * (Anthropic) in parallel, outside any transaction. This mirrors the legacy
     * `getDocumentFromFile` path (Cloudinary upload + `getOcrData` + `figureOutSides`)
     * so v2 produces the same classified documents as `insertEmailDocuments`, but
     * owned by the grant tenant (the auth-coupled providers cannot run in the gateway
     * control-plane context).
     *
     * The hash matches the legacy `hashStringToInt(file.text())` scheme so the dedup
     * is consistent across both paths; re-deliveries short-circuit here and never
     * re-upload or re-OCR. Metadata-only entries (no inline bytes) yield an empty
     * result. OCR failure is non-fatal — the document falls back to UNPROCESSED
     * rather than failing the whole ingest.
     */
    private prepareDocuments;
    /**
     * Insert already-prepared (uploaded + OCR'd) documents under one charge, owned
     * by the grant tenant. Runs entirely inside the caller's transaction with no
     * network I/O. Returns the created charge id.
     */
    private insertPreparedDocuments;
    private persistIdempotencyAndDedup;
}
