import { type FieldError } from './validation.js';
import { type IncomingFile } from './files.js';
import type { FormDefinition, FormField, SpamStatus } from './types.js';
export interface SubmissionConfirmation {
    type: 'message' | 'redirect';
    message?: string;
    redirectUrl?: string;
}
export interface SubmissionContext {
    /** Raw field values from the request (object keyed by field key). */
    values: Record<string, unknown>;
    /** Already-validated file uploads to attach after the row is created. */
    files?: IncomingFile[];
    ip?: string;
    userAgent?: string | null;
    referrer?: string | null;
    origin?: string | null;
    pageUrl?: string | null;
    /** Opaque attribution blob captured client-side; stored as-is. */
    attribution?: Record<string, unknown> | null;
    /** Milliseconds between render and submit (for the time-trap spam check). */
    elapsedMs?: number | null;
}
export interface SubmissionResult {
    submissionId: string;
    entryNumber: number | null;
    spamStatus: SpamStatus;
    confirmation: SubmissionConfirmation;
}
/** Thrown when field validation fails; mapped to HTTP 422 by the API layer. */
export declare class SubmissionValidationError extends Error {
    fieldErrors: FieldError[];
    constructor(fieldErrors: FieldError[]);
}
/** Resolve the field schema the submission should be validated against. */
declare function resolveFields(form: FormDefinition): Promise<{
    fields: FormField[];
    versionId: string | null;
}>;
export interface SubmissionSideEffectInput {
    form: FormDefinition;
    fields: FormField[];
    data: Record<string, unknown>;
    submissionId: string;
    entryNumber: number | null;
    spamStatus: SpamStatus;
    sender: {
        name: string | null;
        email: string | null;
    };
    submittedAt: string;
    formSlug: string;
}
/**
 * Best-effort notification + webhook fan-out after a submission is persisted.
 * Exported so the API layer (or tests) can await it deterministically; the
 * pipeline itself fires it without blocking the public response. Every branch
 * is wrapped so a single failing channel can't take down the others.
 */
export declare function runSubmissionSideEffects(input: SubmissionSideEffectInput): Promise<void>;
/**
 * Process a validated request into a persisted submission. Throws
 * `SubmissionValidationError` when field validation fails so the caller can
 * return a structured 422.
 */
export declare function processSubmission(form: FormDefinition, ctx: SubmissionContext): Promise<SubmissionResult>;
export interface PublicFormField {
    id: string;
    key: string;
    label: string;
    type: string;
    required: boolean;
    placeholder?: string;
    helpText?: string;
    defaultValue?: unknown;
    options?: {
        label: string;
        value: string;
    }[];
    width?: string;
    sortOrder: number;
    validationRules?: Record<string, unknown>;
    conditionalLogic?: unknown;
}
export interface PublicForm {
    id: string;
    name: string;
    slug: string;
    description?: string;
    fields: PublicFormField[];
    submitPath: string;
    successMessage?: string;
    redirectUrl?: string;
    spam: {
        honeypotFieldKey?: string;
        minSubmitSeconds?: number;
    };
    captcha?: {
        provider: string;
        siteKey: string;
    };
    schemaVersionId?: string | null;
}
/**
 * Project a form definition into the public, embeddable schema. Strips every
 * server-only concern (access rules, notification recipients, webhook secrets,
 * blocklists, encryption flags) so nothing sensitive leaks to the browser.
 */
export declare function buildPublicForm(form: FormDefinition, fields: FormField[], schemaVersionId: string | null, options?: {
    captcha?: {
        provider: string;
        siteKey: string;
    };
}): PublicForm;
export { resolveFields as resolveSubmissionFields };
//# sourceMappingURL=submission.d.ts.map