/**
 * The redaction pass engine every egress tier runs on, and the core bracket RENDERER of the vocabulary's answer.
 * Which text is a credential is the vocabulary's answer (credential-vocabulary.ts); which passes a text meets is
 * its tier's (untrusted-egress.ts).
 */
import type { RedactionConfidence, RedactionSource, ValueFamilyRow } from "./credential-vocabulary.js";
export type { RedactionConfidence, RedactionSource } from "./credential-vocabulary.js";
/** One redaction hit: what was detected, where (ORIGINAL-input coordinates), how confidently, the marker
 *  literal written in its place, which rule table minted it, and — present when a vocabulary row minted it — the
 *  value family (the row's stable id; a host-leak hit such as a URL or a path names none). */
export interface RedactionFinding {
    kind: string;
    span: readonly [number, number];
    confidence: RedactionConfidence;
    marker: string;
    source: RedactionSource;
    family?: string;
}
/** The minimum a finding must declare to be summarizable. Both text findings ({@link RedactionFinding})
 *  and the env arm's entry findings satisfy it, so {@link summarizeRedactions} is ONE helper rather than
 *  one per material kind. */
export interface SummarizableFinding {
    kind: string;
    confidence: RedactionConfidence;
}
/** ANG-3 (envelope declaration) — render findings as ONE human-readable line, e.g.
 *  `"3 redactions: prefixed-token (high) x1, url (medium) x1, fs-path (low) x1"`, so an upper layer can
 *  declare to its consumer how much was removed and how confidently.
 *
 *  PURE, and deliberately only that: it reads the array, returns a string, and injects nothing anywhere.
 *  Attaching this line to an output is the caller's decision — a redaction pipeline that silently
 *  appended prose to the very text it was asked to bound would break both the size contract
 *  (`boundedString`) and the byte-invariance the whole channel is built on.
 *
 *  Grouping is by kind AND confidence together: collapsing on kind alone would report whichever
 *  confidence happened to arrive first for the rest of that group, which is exactly the silent
 *  mis-statement ANG-4 exists to prevent. */
export declare function summarizeRedactions(findings: readonly SummarizableFinding[]): string;
/** The optional collector every redaction entry point accepts. `preexistingMarkers` (ANG-11) counts
 *  marker-shaped literals ALREADY present in the input before any pass ran — a nonzero value means the
 *  text arrived pre-redacted or carries caller-declared markers, either way "marker present" is not proof this
 *  pipeline ran. Caller-owned: pass `{ findings: [] }` and read it back after the call. */
export interface RedactionReport {
    findings: RedactionFinding[];
    preexistingMarkers?: number;
}
/** A declared redaction pass — the unit {@link runRedactionPasses} executes and reports on. */
export interface RedactionPass {
    kind: string;
    confidence: RedactionConfidence;
    marker: string;
    /** The rule table that owns this pass's rule — copied verbatim onto every finding it mints (ANG-11), whoever
     *  runs the pass. */
    source: RedactionSource;
    re: RegExp;
    /** A literal replacement (only `$1` substitution is used by these passes) or a replacer fn. */
    replace: string | ((match: string, ...groups: string[]) => string);
    /** The value family a hit belongs to: one id, or — for a pass joining several rows — the id of the row that
     *  matches at the hit's offset in the pass input. Absent = the pass is no vocabulary row. */
    family?: string | ((input: string, at: number) => string);
}
/**
 * Run the declared passes in order, collecting findings (original-input spans) when a report is given.
 *
 * FORMAT CHARACTERS (#532): the passes scan a VIEW of the input with every `\p{Cf}` removed, so a
 * credential split by a zero-width character is one token to the scanner, not two fragments of which
 * only the first (or neither) matches. The OUTPUT keeps every format character that sits OUTSIDE a
 * replaced span — a joiner in an emoji sequence, a non-joiner in Persian text, a soft hyphen in a word
 * — and drops only those INSIDE the span the marker replaces (they were part of the secret). A
 * format-free input takes the exact historical path (byte-identical output). The view's replacements and
 * every boundary scan's are taken as disjoint spans of their input (a later pass that matched across an
 * earlier pass's inserted text is rendered from the removals instead), so the spans always map back
 * exactly and no scan is skipped.
 */
export declare function runRedactionPasses(input: string, passes: readonly RedactionPass[], report?: RedactionReport): string;
/**
 * The egress view rendered as passes, in the vocabulary's order: one pass per group (a group of several rows is ONE
 * leftmost alternation, its hits attributed to the row that matches at the hit's offset). A row whose wide form
 * captures a label keeps it ahead of the marker; `replacers` renders a kind whose marker placement is a policy (the
 * URL userinfo).
 */
export declare function egressPasses(groups: ReadonlyArray<readonly ValueFamilyRow[]>, replacers?: Readonly<Record<string, (match: string, ...groups: string[]) => string>>): RedactionPass[];
