/**
 * @sanity/ailf-core — Run-provenance ownership policy evaluator
 *
 * The single, pure policy evaluator both enforcement gates call — T1 (API
 * gateway, before dispatch) and T2 (eval runner, before the canonical store
 * write) — so verdicts and user-facing messages can never drift between the
 * two call sites. Zero I/O: typed input + policy in, typed verdict out.
 *
 * `owner.team` is freeform-by-design (D0037): external teams name themselves
 * and internal names drift, so it was never validated against a closed enum.
 * This evaluator refines that into "freeform-but-required for all, known-slug
 * for `official`" — a completeness/validity gate, not an authorization gate
 * (it checks that a run *declares* a valid team, not that the caller is
 * *entitled* to it). See D0055 on why authorization stays with Sanity roles.
 *
 * The policy is data (`SERVER_FLOOR` is option B encoded as a value), so a
 * consumer repo can *strengthen* the floor via `mergeProvenancePolicy` but
 * never weaken it. Reuses the shared owner-team helpers
 * (`KNOWN_OWNER_TEAMS` / `normalizeOwnerTeam` / `isKnownOwnerTeam`) so the
 * known-list and alias-folding stay in one place.
 *
 * @see docs/design-docs/run-provenance-ownership-enforcement.md
 * @see docs/exec-plans/run-provenance-ownership-enforcement.md
 * @see docs/decisions/D0037-run-classification-and-ownership-taxonomy.md
 */
import { type RunClassification } from "../../ailf-shared/index.d.ts";
/** Per-field enforcement strength, ordered `off < warn < error`. */
export type ProvenanceFieldSeverity = "off" | "warn" | "error";
/**
 * A classification-conditional rule layered on top of the baseline severities.
 * `require.team` tightens the team check for the matched classification:
 * `"present"` only demands a non-empty, well-formed slug; `"known"` additionally
 * demands membership in {@link KNOWN_OWNER_TEAMS}. `require.individual` demands
 * an `owner.individual` at the given severity.
 */
export interface ProvenanceRule {
    when: {
        classification: RunClassification;
    };
    require: {
        team?: "present" | "known";
        individual?: ProvenanceFieldSeverity;
    };
}
/**
 * A complete provenance policy. The baseline (unconditional) severity for each
 * field, plus classification-conditional rules. `SERVER_FLOOR` is the canonical
 * instance; projects strengthen it via {@link mergeProvenancePolicy}.
 */
export interface ProvenancePolicy {
    /** Baseline team check: presence + slug shape + non-placeholder + non-"unknown". */
    team: ProvenanceFieldSeverity;
    /** Baseline (unconditional) `owner.individual` requirement. */
    individual: ProvenanceFieldSeverity;
    /** Reserved: `classification` is always a valid enum, so this is a no-op condition key. */
    classification: ProvenanceFieldSeverity;
    /** Baseline (unconditional) `purpose` requirement. */
    purpose: ProvenanceFieldSeverity;
    rules: ProvenanceRule[];
}
/**
 * The provenance fields an evaluation run declares. `classification` is always
 * present and valid (the runner defaults missing/invalid → `"adhoc"` before
 * this runs); `owner` and its fields are what this evaluator validates.
 */
export interface ProvenanceInput {
    classification: RunClassification;
    owner?: {
        team?: string;
        individual?: string;
    };
    purpose?: string;
}
/** Which provenance field a violation concerns. */
export type ProvenanceField = "team" | "individual" | "classification" | "purpose";
/**
 * A single policy violation. `message` states the exact problem; `remediation`
 * names the fix surfaces and points at `npx @sanity/ailf teams`. Both gates
 * inherit identical wording from here, so CLI and gateway never diverge.
 */
export interface ProvenanceViolation {
    field: ProvenanceField;
    severity: "error" | "warn";
    code: ProvenanceViolationCode;
    message: string;
    remediation: string;
}
/** Stable, machine-readable violation codes. */
export type ProvenanceViolationCode = "team_missing" | "team_placeholder" | "team_malformed" | "team_unknown_for_official" | "team_unknown_soft" | "individual_missing_for_official" | "individual_missing" | "purpose_missing";
/**
 * The result of evaluating a {@link ProvenanceInput} against a
 * {@link ProvenancePolicy}. `ok` is `false` iff any violation has
 * `severity: "error"`. `normalizedTeam` is the canonical (alias-folded) slug,
 * present only when the team clears the baseline (so consumers can echo the
 * slug they would record, even for an `official`-unknown error).
 */
export interface ProvenanceVerdict {
    ok: boolean;
    violations: ProvenanceViolation[];
    normalizedTeam?: string;
}
/**
 * A well-formed owner-team slug: lowercase letters/digits/hyphens, starting
 * with an alphanumeric. Non-global so it is safe to reuse with `.test()`.
 */
export declare const OWNER_TEAM_SLUG_PATTERN: RegExp;
/**
 * Option B, encoded as data: every run needs a present, well-formed,
 * non-placeholder, non-"unknown" `owner.team`; `classification: official`
 * additionally requires a known team slug and an `owner.individual`. Everything
 * else is floor-only — unknown slugs are accepted and soft-warned, faithful to
 * D0037's freeform spirit. External teams are never blocked.
 *
 * Frozen: it is the non-negotiable floor both gates import, so it must not be
 * mutated in place (vitest reuses one process per worker — accidental mutation
 * would leak across tests). Strengthen it via {@link mergeProvenancePolicy},
 * which returns a fresh policy.
 */
export declare const SERVER_FLOOR: ProvenancePolicy;
/**
 * Nearest known team slug to a misspelling, or `undefined` when nothing is close
 * enough. Ties broken by `KNOWN_OWNER_TEAMS` order (stable, declaration order).
 * An already-known slug is not a misspelling, so it returns `undefined`.
 */
export declare function suggestKnownTeam(slug: string): string | undefined;
/**
 * Evaluate a run's declared provenance against a policy. Pure and deterministic.
 *
 * Evaluation order: normalize `team` (folding aliases like `core-docs → docs`),
 * apply the baseline team check at `policy.team` severity (raised to `error`
 * when a matching rule requires the team be present/known), then the
 * classification-conditional known/individual rules, then the unconditional
 * `individual`/`purpose` baselines. A team that fails the baseline short-circuits
 * the known/soft checks (no point reporting "unknown team" for a missing one).
 */
export declare function evaluateProvenance(input: ProvenanceInput, policy: ProvenancePolicy): ProvenanceVerdict;
/**
 * Combine the server floor with an optional project policy. A project may only
 * *strengthen*: each field's severity is the stricter of the two
 * (`max` over `off < warn < error`), and rules are unioned — a project can add
 * rules but cannot remove a floor rule. This is what makes the floor
 * non-negotiable while allowing per-repo opt-in strictness on top.
 */
export declare function mergeProvenancePolicy(floor: ProvenancePolicy, project?: Partial<ProvenancePolicy>): ProvenancePolicy;
