/**
 * WS5.2 R12 — Revocation / de-authorization data-plane executor (Mechanism B, the DEFAULT).
 *
 * "Stop following to machine X" is TWO things: a control-plane mandate revocation (PIN-gated on the
 * Mandates tab; the agent CANNOT revoke — that authority stays with MandateGate) PLUS a real
 * data-plane effect. This module is the data-plane half: it CONSUMES a revocation signal (the
 * control-plane revoke already happened) and computes the honest data-plane outcome. It NEVER
 * self-revokes the mandate and is NOT a new blocking authority — it is a deterministic planner +
 * honest-state surface over INJECTED side-effect deps (logout, slot delete, SubscriptionPool.remove,
 * attention emit, pending store). No direct I/O in the logic; every effect is injected so each is
 * independently unit-testable (mirrors AccountFollowMeService / Grants / Orchestrator style).
 *
 * R12 has three honesty-load-bearing branches:
 *
 *   (i)  COOPERATIVE, still-paired target ONLINE (R12.i): the data-plane effect is local & total —
 *        the target logs the account OUT of its config-home, deletes the per-account slot, and
 *        SubscriptionPool.remove(accountId) fires on the target. End state: `removed`.
 *
 *   (ii) DE-PAIRED / HOSTILE / non-cooperative holder (S8 / R12.i corrected): a B-minted credential
 *        is an independently-refreshable real OAuth login; instar CANNOT force the logout remotely.
 *        The HONEST revocation path is provider-side de-authorization. We surface a phone-first
 *        instruction ("machine X still holds its own live login for account Y — de-authorize/rotate
 *        at <provider> to kill it"), NEVER a false "removed everywhere". End state:
 *        `provider-rotation-required`. (When a machine de-pairs, MachineStatus flips to 'revoked' —
 *        that flip is the caller's; this module READS that status and refuses to claim a wipe.)
 *
 *   (iii) OFFLINE-honest pending, BOUNDED (R12.iii): a still-paired target that is OFFLINE at revoke
 *        time gets its control-plane revoke immediately, but the data-plane wipe becomes a DURABLE
 *        pending action fired when it reconnects ("write it down durably, fire on return", the
 *        cross-machine-secret-sync pattern). Dashboard shows `revocation-pending`, NEVER `removed`.
 *        The pending wipe is NOT unbounded: after a fixed, operator-tunable reconnect-deadline it
 *        ESCALATES to a LOUD `revocation-FAILED — rotate at provider NOW` aggregated HIGH attention
 *        item (resume-queue give-up discipline). Honest end state of an offline-forever / terminated
 *        VM is "rotate at provider", never a silently-aging "pending".
 *
 * FAIL CLOSED on uncertainty: if we cannot positively confirm the cooperative-online wipe path
 * (unknown reachability, revoked status, the wipe effect threw), we NEVER report `removed` — we fall
 * to pending or provider-rotation-required. Deny-by-default for the optimistic "removed" claim.
 *
 * Mechanism A (sealed-transport) is dark/refused-for-Anthropic; per R9 it is out of scope here
 * beyond the minimal `mechanism` discriminator — a Mechanism-A revoke ALSO requires the wipe verb +
 * an unconditional provider-rotation prompt (a delivered credential cannot be un-delivered), so this
 * module flags `providerRotationRequired: true` for any Mechanism-A revoke regardless of branch.
 */
export type RevocationMechanism = 're-mint' | 'credential-transport';
/** Target reachability/cooperation posture at revoke time — drives the R12 branch. */
export type TargetPosture = 'cooperative-online' | 'offline' | 'revoked';
/** Honest end-state of a revocation's DATA plane (never conflate with the control-plane revoke). */
export type RevocationDataState = 'removed' | 'revocation-pending' | 'revocation-failed' | 'provider-rotation-required';
export interface RevocationRequest {
    accountId: string;
    /** Operator-facing account email (shown in honest operator messaging). */
    accountEmail: string;
    targetMachineId: string;
    /** Operator-facing nickname of the target machine (shown in honest operator messaging). */
    targetMachineNickname: string;
    /** Provider name for the provider-side de-authorization instruction (e.g. 'Anthropic'). */
    provider: string;
    /** The mandate id whose control-plane revoke triggered this data-plane effect (audit). */
    mandateId: string;
    /** Default 're-mint' (Mechanism B). 'credential-transport' ⇒ unconditional provider rotation. */
    mechanism?: RevocationMechanism;
}
/** A phone-first provider-side de-authorization instruction — a real instruction, NOT a "handled" claim. */
export interface ProviderRotationInstruction {
    kind: 'provider-rotation-required';
    accountId: string;
    accountEmail: string;
    targetMachineId: string;
    targetMachineNickname: string;
    provider: string;
    /** Plain-English, honest message surfaced to the operator (never implies instar removed it). */
    message: string;
}
/** A LOUD aggregated attention item for an offline target that gave up (R12.iii give-up). */
export interface RevocationFailedAttention {
    /** Stable id so the item dedups per (account,target) — one running item, not a flood (P17). */
    id: string;
    title: string;
    body: string;
    priority: 'high';
    source: 'agent';
}
/** A durable pending-wipe record — fired on the target's reconnect; bounded by the deadline. */
export interface PendingWipeRecord {
    accountId: string;
    targetMachineId: string;
    mandateId: string;
    provider: string;
    accountEmail: string;
    targetMachineNickname: string;
    mechanism: RevocationMechanism;
    /** When the control-plane revoke fired — the deadline clock starts here. */
    revokedAt: number;
    /** Absolute deadline; after this a still-pending wipe escalates to revocation-failed. */
    deadlineAt: number;
}
/** Durable persistence seam for pending wipes (production: JSON/SQLite; tests: in-memory). */
export interface PendingWipeStore {
    /** Upsert keyed on `${accountId}::${targetMachineId}`. */
    put(record: PendingWipeRecord): void;
    /** Resolve (the wipe fired) — remove the pending record. */
    remove(accountId: string, targetMachineId: string): void;
    get(accountId: string, targetMachineId: string): PendingWipeRecord | undefined;
    all(): PendingWipeRecord[];
}
export declare function inMemoryPendingWipeStore(): PendingWipeStore;
/** Outcome of an attempted cooperative-online data-plane wipe (each step injected). */
export interface CooperativeWipeResult {
    loggedOut: boolean;
    slotDeleted: boolean;
    poolRemoved: boolean;
}
export interface AccountFollowMeRevocationDeps {
    /** Master gate: the whole feature is dark unless this is true (single-machine / flag-off ⇒ no-op). */
    enabled: () => boolean;
    /**
     * Execute the cooperative data-plane wipe ON the (online, still-paired) target: framework logout
     * against that CLAUDE_CONFIG_DIR + delete the per-account slot + SubscriptionPool.remove(accountId).
     * MUST throw or return all-false on any failure — we then fail closed (never claim `removed`).
     */
    cooperativeWipe: (req: RevocationRequest) => CooperativeWipeResult;
    /** Durable pending-wipe ledger (offline path). */
    pendingStore: PendingWipeStore;
    /** Raise ONE aggregated LOUD attention item (offline give-up). */
    emitRevocationFailed: (item: RevocationFailedAttention) => void;
    /** Reconnect-deadline before an offline pending wipe escalates to revocation-failed (ms). */
    reconnectDeadlineMs: () => number;
    now?: () => number;
    log?: (msg: string) => void;
}
export type RevocationOutcome = {
    state: RevocationDataState;
    accountId: string;
    targetMachineId: string;
    /** True whenever provider-side rotation is the (only) complete revocation — caller surfaces it. */
    providerRotationRequired: boolean;
    /** Present for the de-paired/hostile and Mechanism-A paths — a real phone-first instruction. */
    providerRotation?: ProviderRotationInstruction;
    /** Present on the cooperative-online success path. */
    wipe?: CooperativeWipeResult;
    reason: string;
};
export declare class AccountFollowMeRevocation {
    private readonly deps;
    private readonly now;
    constructor(deps: AccountFollowMeRevocationDeps);
    private rotationInstruction;
    /**
     * Revoke account access on `targetMachineId` given the control-plane revoke already fired. The
     * `posture` (computed by the caller from authoritative registry state — online flag, MachineStatus)
     * selects the R12 branch. Returns the HONEST data-plane outcome; never claims `removed` it can't
     * confirm. A no-op (`provider-rotation-required` with a no-op message) when the feature is dark.
     */
    revoke(req: RevocationRequest, posture: TargetPosture): RevocationOutcome;
    /**
     * A previously-offline target reconnected — fire its durable pending wipe (R12.iii). Drives the
     * SAME cooperative wipe as the online path; on success the pending record is cleared and we report
     * `removed`. On failure/partial we keep the record (it may still escalate at the deadline).
     * A no-op if no pending record exists for (account, target) or the feature is dark.
     */
    onTargetReconnect(accountId: string, targetMachineId: string): RevocationOutcome | null;
    /**
     * Sweep durable pending wipes whose reconnect-deadline has passed and escalate each to a LOUD
     * `revocation-FAILED — rotate at provider NOW` aggregated HIGH attention item (R12.iii give-up).
     * Each escalated record is removed from the pending store (its honest end-state is now provider
     * rotation, never a silently-aging "pending"). Returns the records that escalated. Caller runs
     * this on a cadence (resume-queue drainer style). No-op when the feature is dark.
     */
    sweepDeadlines(): RevocationFailedAttention[];
    /**
     * Honest dashboard state for an (account, target) pair: a live pending record reports
     * `revocation-pending` (or `revocation-failed` once past its deadline), else null (no pending
     * revocation in flight). Read surface — never mutates.
     */
    pendingStateFor(accountId: string, targetMachineId: string): RevocationDataState | null;
}
//# sourceMappingURL=AccountFollowMeRevocation.d.ts.map