/**
 * SelfUnblockChecklist — the deterministic, code-driven exhaustion checklist that
 * COMPLETES the constitutional standard "Self-Unblock Before Escalating"
 * (docs/specs/self-unblock-before-escalating.md).
 *
 * Foundation (§0): this does NOT fork a parallel gate. BlockerLedger's
 * `settleTrueBlocker` already MANDATES a recorded failed self-fetch/dry-run before
 * a credential/account blocker can settle as a `true-blocker`. The MISSING half
 * was a STANDARD, code-driven set of sources an agent must have probed first —
 * turning "you must record a failed attempt" into "here is the ordered list of
 * places a self-unblockable credential could live, all of which came up empty".
 *
 * What this module provides (the four genuine additions over BlockerLedger):
 *   1. A deterministic relevance matcher (`isScopeRelevant`) — a credential's
 *      declared scope tag is "relevant" to a target zone/service iff a
 *      deterministic tag/zone match (domain hierarchy + wildcard). Ambiguous,
 *      conflicting, or MISSING metadata fails CLOSED. NO LLM in this path.
 *   2. An ORDERED probe runner (`SelfUnblockChecklist.run`) — cheapest/local
 *      first, short-circuit on the first `holdsRelevantCred: true`. Each probe is
 *      independently timeout-bounded BY CLASS (local sub-second; remote 10–15s),
 *      failing toward `reachable: false` on timeout.
 *   3. A durable run STORE (`SelfUnblockRunStore`) — persists each run keyed by an
 *      immutable runId; `loadRun(runId)` is what BlockerLedger LOADS + verifies so
 *      a caller cannot mint a run the runner did not produce (closes the round-1
 *      "self-asserted/gameable list" finding mechanically).
 *   4. The ladder/rung-floor helper (`resolveRung` / `rungToAuthorityCheck`) — maps
 *      the human-requirement ladder (§3) onto BlockerLedger's existing
 *      `AuthorityCheckEvidence`; enforces the rung FLOOR (capability ≠ authority).
 *
 * Signal vs Authority: this module RECORDS and STRUCTURES. The one judgment —
 * the `true-blocker` settle — stays with BlockerLedger's injected Tier-1
 * authority. This module never blocks an outbound message.
 *
 * Ships DARK behind the existing `monitoring.blockerLedger.*` gate (dev-gate via
 * omitted `enabled`). When the run store is not injected into BlockerLedger, the
 * existing caller-supplied `failedAttempt` path is unchanged.
 */
/** The ordered probe sources (cheapest/local first). Closed taxonomy. */
export declare const SELF_UNBLOCK_PROBE_SOURCES: readonly ["own-vault", "org-bitwarden", "cloud-vercel", "cloud-cloudflare", "cloud-github", "cloud-launchd", "mcp-tools", "browser-playwright", "controlled-resource"];
export type SelfUnblockProbeSource = (typeof SELF_UNBLOCK_PROBE_SOURCES)[number];
/** Timeout CLASS per probe — local/keychain probes are sub-second; remote 10–15s. */
export type ProbeTimeoutClass = 'local' | 'remote';
/** Default timeout budget (ms) per class. */
export declare const PROBE_TIMEOUT_MS: Record<ProbeTimeoutClass, number>;
/** Which class each source belongs to (drives the per-probe timeout). */
export declare const PROBE_SOURCE_CLASS: Record<SelfUnblockProbeSource, ProbeTimeoutClass>;
/** A single probe's structured result (stamped, never free-form). */
export interface SelfUnblockProbeResult {
    /** Which source was probed. */
    source: SelfUnblockProbeSource;
    /** Could the source be reached at all? false on timeout/error (fails closed). */
    reachable: boolean;
    /**
     * Does this source hold a credential RELEVANT to the target? Decided
     * DETERMINISTICALLY by `isScopeRelevant` (never an LLM). Missing/ambiguous
     * scope metadata fails CLOSED → false.
     */
    holdsRelevantCred: boolean;
    /** ISO timestamp the probe ran. */
    probedAt: string;
    /**
     * Optional short note for the audit surface (untrusted free text — surfaced via
     * BlockerLedger's `<blocker-ledger-data>` envelope, never an instruction).
     */
    detail?: string;
    /** The scope tags this source advertised that were CHECKED against the target. */
    matchedScopeTags?: string[];
}
/** A complete checklist run, keyed by an immutable runId. */
export interface SelfUnblockRun {
    /** Immutable id the runner mints (the caller cannot forge one). */
    runId: string;
    /** The blocker target this run probed (a zone/service, e.g. `cloudflare:feedback.dawn-tunnel.dev`). */
    target: string;
    /** Required attempt TYPE this run produces evidence for (matches BlockerLedger's taxonomy). */
    requiredAttemptType: 'self-fetch' | 'dry-run';
    /** The ordered per-probe results (short-circuited after the first hit, if any). */
    probes: SelfUnblockProbeResult[];
    /** ISO timestamp the run finished. */
    completedAt: string;
    /**
     * True iff EVERY probe came up `holdsRelevantCred: false` — a genuine
     * exhaustion. A run with any `holdsRelevantCred: true` is NOT exhausted (the
     * agent should self-unblock with that credential, not escalate).
     */
    exhausted: boolean;
}
/**
 * A parsed scope tag: `service:scope` (e.g. `cloudflare:dawn-tunnel.dev`,
 * `vercel:project`, `cloudflare:*.dawn-tunnel.dev`).
 */
export interface ScopeTag {
    service: string;
    scope: string;
}
/**
 * Parse a `service:scope` tag. Returns null when the shape is malformed (a tag
 * the matcher must treat as ambiguous → fail closed).
 *
 * A scope is allowed to contain ':' (rare), so only the FIRST colon splits
 * service from scope. An empty service or empty scope is malformed.
 */
export declare function parseScopeTag(tag: unknown): ScopeTag | null;
/**
 * Is a credential whose declared scope tag is `credTag` RELEVANT to the blocker
 * `target` (also a `service:scope` tag)? Deterministic. Fails CLOSED on any
 * malformed/missing/cross-service input.
 *
 * - Both tags must parse (`service:scope`).
 * - The SERVICE must match exactly (a Vercel cred is never relevant to a
 *   Cloudflare target).
 * - The SCOPE must match per `domainScopeMatches`.
 */
export declare function isScopeRelevant(credTag: unknown, target: unknown): boolean;
/**
 * Given a set of scope tags a source advertises, is ANY of them relevant to the
 * target? An empty/undefined set fails CLOSED → false (under-tagged credential is
 * simply not surfaced). Returns the matching tags for the audit surface.
 */
export declare function relevantScopeTags(advertised: unknown, target: string): string[];
/**
 * What a probe provider returns. The provider is responsible ONLY for reaching the
 * source and listing the scope tags the source ADVERTISES; the checklist runner
 * applies the deterministic relevance match. A provider that cannot reach the
 * source returns `{ reachable: false }` (or throws/times out → the runner records
 * `reachable: false`).
 */
export interface ProbeProviderResult {
    reachable: boolean;
    /** The scope tags this source advertises (e.g. the zones a CF token can edit). */
    advertisedScopeTags?: string[];
    /** Optional short audit note. */
    detail?: string;
}
/** One source's probe implementation. MUST be self-bounded but the runner also
 *  enforces a hard per-class timeout so a hung provider degrades to unreachable. */
export type ProbeProvider = (target: string) => Promise<ProbeProviderResult>;
/** The full set of injectable providers, one per source. */
export type ProbeProviders = Partial<Record<SelfUnblockProbeSource, ProbeProvider>>;
/** The read interface BlockerLedger depends on (the ONLY surface it needs). */
export interface SelfUnblockRunLoader {
    loadRun(runId: string): SelfUnblockRun | null;
}
/**
 * Durable JSONL store for checklist runs. One run per line, keyed by an immutable
 * runId. `loadRun` is skip-corrupt-lines tolerant + bounded (precedent:
 * ReapLog.read). A run is APPEND-only; the store never mutates a prior run.
 */
export declare class SelfUnblockRunStore implements SelfUnblockRunLoader {
    private readonly runsPath;
    /** Bound on how many trailing lines `loadRun` will scan (newest runs win). */
    private readonly maxScan;
    constructor(opts: {
        stateDir: string;
        maxScan?: number;
    });
    /** The file the store reads/writes (exposed for tests). */
    get path(): string;
    /** Append a completed run. Best-effort durable (atomic append). */
    save(run: SelfUnblockRun): void;
    /**
     * Load a run by id, scanning the trailing `maxScan` lines newest-first so a
     * recent run is found fast and a corrupt/partial line never fails the read.
     * Returns null when the id is unknown.
     */
    loadRun(runId: string): SelfUnblockRun | null;
    /** Read the most-recent `limit` runs (newest last) for the read surface. */
    list(limit?: number): SelfUnblockRun[];
}
export interface SelfUnblockChecklistOptions {
    /** Injectable providers. A missing provider is treated as `reachable: false`. */
    providers?: ProbeProviders;
    /** The durable run store. */
    store: SelfUnblockRunStore;
    /** Injectable clock for deterministic tests. */
    now?: () => Date;
    /** Override timeout budgets (tests). */
    timeoutMs?: Partial<Record<ProbeTimeoutClass, number>>;
    /** Inject the runId minter (tests assert it is the runner's, not the caller's). */
    mintRunId?: () => string;
}
export declare class SelfUnblockChecklist {
    private readonly providers;
    private readonly store;
    private readonly now;
    private readonly timeouts;
    private readonly mintRunId;
    constructor(opts: SelfUnblockChecklistOptions);
    /**
     * Run the ORDERED checklist against `target`, short-circuiting on the first
     * `holdsRelevantCred: true`. Persists the run and returns it.
     *
     * `requiredAttemptType` matches BlockerLedger's taxonomy: `self-fetch` for the
     * credential/account-kind blockers (vault/cloud-account probes), `dry-run`
     * otherwise.
     */
    run(input: {
        target: string;
        requiredAttemptType: 'self-fetch' | 'dry-run';
    }): Promise<SelfUnblockRun>;
    /** Probe ONE source with a hard per-class timeout. Fails toward `reachable: false`. */
    private probeOne;
    /** Reject after `ms`, so a hung provider can never stall the path. */
    private withTimeout;
}
/** The ladder rungs (§3). */
export type SelfUnblockRung = 0 | 1 | 2;
/**
 * An action CLASS that carries a rung FLOOR. The four floor-raising properties
 * (§3, capability ≠ authority): an action that is irreversible, cost-bearing
 * above a threshold, out-of-original-scope, or policy-sensitive has a MINIMUM
 * rung of 1 (approval) EVEN IF a self-unblock credential exists.
 */
export interface ActionClass {
    /** Cannot be undone (a delete, a wire, a publish). */
    irreversible?: boolean;
    /** Bears cost above the approval threshold. */
    costBearingAboveThreshold?: boolean;
    /** Outside the goal's originally-granted scope. */
    outOfScope?: boolean;
    /** Policy-sensitive (legal, PII export, etc.). */
    policySensitive?: boolean;
}
/** True iff the action class triggers the rung-1 floor. */
export declare function actionTriggersRungFloor(action: ActionClass | undefined): boolean;
export interface ResolveRungInput {
    /**
     * The run that probed the blocker. When `exhausted` is false (a relevant cred
     * was found), the agent can self-unblock → rung 0 UNLESS the action floor
     * raises it. When exhausted, no self-unblock cred exists → at least rung 1
     * (approval) and rung 2 if the dependency is an operator-only secret.
     */
    run: SelfUnblockRun;
    /** The action class (drives the rung floor). */
    action?: ActionClass;
    /**
     * Is the unblock dependency an operator-only secret/account (the rung-2 case)?
     * Derived from BlockerLedger's taxonomy at the caller; rung 2 is the credential
     * only an authorized employee can produce.
     */
    operatorOnlySecret?: boolean;
}
export interface RungResolution {
    /** The resolved rung. */
    rung: SelfUnblockRung;
    /** Whether the rung was RAISED by the action-class floor (vs the base resolution). */
    raisedByFloor: boolean;
    /** Human-readable reason (untrusted-safe — plain enum-derived text). */
    reason: string;
}
/**
 * Resolve the lowest legitimate rung for a blocker, ENFORCING the rung floor.
 *
 * Base resolution:
 *   - run NOT exhausted (a self-unblock cred exists) → rung 0 (nothing required)
 *   - run exhausted + operator-only secret              → rung 2 (operator-only credential)
 *   - run exhausted otherwise                           → rung 1 (an approval)
 *
 * Floor (capability ≠ authority): if the action class is irreversible /
 * cost-bearing-above-threshold / out-of-scope / policy-sensitive, the rung can
 * never be BELOW 1 — even a rung-0 self-unblock is raised to rung 1 (approval).
 */
export declare function resolveRung(input: ResolveRungInput): RungResolution;
/**
 * Map a resolved rung onto BlockerLedger's existing `AuthorityCheckEvidence`
 * shape (§3 — the rung is recorded there, NOT in a new field). A rung-1 grant
 * MUST resolve against a VERIFIED principal (Know Your Principal): when the rung
 * is >=1 and the grant matters, `principalVerified` must be true or the grant is
 * not honored. This function refuses to assert `userHasAuthority: true` for an
 * unverified principal.
 */
export declare function rungToAuthorityCheck(input: {
    resolution: RungResolution;
    /** Was the approving/granting principal VERIFIED (mandate / verified-operator surface)? */
    principalVerified: boolean;
}): {
    agentHasAuthority: boolean;
    userHasAuthority: boolean;
    note: string;
};
//# sourceMappingURL=SelfUnblockChecklist.d.ts.map