/**
 * AgentTrustManager — Per-agent trust profiles for inter-agent communication.
 *
 * Part of Threadline Protocol Phase 5. Tracks trust between THIS agent and
 * remote agents it communicates with. Unlike AdaptiveTrust (user→agent trust),
 * this manages agent→agent trust in the Threadline mesh.
 *
 * Trust rules (Section 7.3/7.4):
 * - ALL trust level UPGRADES require source: 'user-granted' — NO auto-escalation
 * - Auto-DOWNGRADE only: circuit breaker (3 activations in 24h → untrusted),
 *   crypto verification failure → untrusted, 90 days no interaction → downgrade one level
 * - All trust changes logged to append-only audit trail
 *
 * Storage:
 * - Profiles: {stateDir}/threadline/trust-profiles.json
 * - Audit trail: {stateDir}/threadline/trust-audit.jsonl
 */
import { type PendingPairingRecord } from './PairingPendingStore.js';
export type AgentTrustLevel = 'untrusted' | 'verified' | 'trusted' | 'autonomous';
export type AgentTrustSource = 'user-granted' | 'paired-machine-granted' | 'setup-default'
/**
 * Out-of-band SAS-verified pairing (Secure A2A Verified Pairing, §3.3).
 * Structurally un-self-grantable: ONLY `markMutualVerified` may set this source.
 * The generic setter (`applyTrustLevel`/`setTrustLevelByFingerprint`) REJECTS it
 * as input (returns false), so credential-share can never be self-granted.
 */
 | 'mutual-verified';
/**
 * Pairing lifecycle state stored ON the trust profile (single source of truth, §3.7).
 * `pending-verification` after a handshake; `mutual-verified` once the operator
 * SAS-confirms; `verification-failed` on an operator-asserted mismatch.
 *
 * `identity-verified` (§3.8, FD11) is the INHERITED state on a machine OTHER than the
 * one whose operator SAS-compared: a replicated `mutual-verified` RESULT from a peer
 * machine, HONORED by pinning the peer's identity key. It asserts "this identity key was
 * SAS-verified by a human SOMEWHERE" — it is NOT by itself channel-ready: credential-share
 * on THIS machine additionally requires THIS machine's own live encrypted channel (the
 * outbound CredentialShareGate enforces the encrypted-path half). It cannot be reached
 * locally (only an inbound replicated record sets it), so it can never be self-granted.
 */
export type PairingState = 'pending-verification' | 'mutual-verified' | 'verification-failed' | 'identity-verified';
export interface AgentTrustHistory {
    messagesReceived: number;
    messagesResponded: number;
    successfulInteractions: number;
    failedInteractions: number;
    lastInteraction: string;
    streakSinceIncident: number;
}
export interface AgentTrustProfile {
    agent: string;
    /** Cryptographic fingerprint (Ed25519-derived). Primary identity key. */
    fingerprint?: string;
    level: AgentTrustLevel;
    source: AgentTrustSource;
    history: AgentTrustHistory;
    allowedOperations: string[];
    blockedOperations: string[];
    createdAt: string;
    updatedAt: string;
    /** Pairing lifecycle state. Absent = no pairing handshake has occurred. */
    pairingState?: PairingState;
    /** Identifies THIS handshake instance (epoch binding, FD4). */
    pairingId?: string;
    /** The peer's Ed25519 identity public key (hex) bound by the human's verification. */
    peerIdentityPub?: string;
    /** SAS fingerprint (FD3) — logged/audited value; the SAS WORDS are never stored here. */
    sasFingerprint?: string;
    /** When this side's operator SAS-confirmed the peer (ISO-8601). */
    verifiedAt?: string;
    /** Optional liveness flag (FD8): a signature-verified inbound peer receipt arrived. */
    peerAcked?: boolean;
    /** When the pairingState is `identity-verified` (§3.8), the machine id whose operator
     *  SAS-compared (carried by the replicated record). Audit/observability only. */
    inheritedFromMachine?: string;
}
export interface TrustAuditEntry {
    timestamp: string;
    agent: string;
    previousLevel: AgentTrustLevel;
    newLevel: AgentTrustLevel;
    source: AgentTrustSource | 'system';
    reason: string;
    userInitiated: boolean;
}
export interface TrustChangeNotification {
    agent: string;
    previousLevel: AgentTrustLevel;
    newLevel: AgentTrustLevel;
    reason: string;
    userInitiated: boolean;
}
/** Callback for trust change notifications */
export type TrustChangeCallback = (notification: TrustChangeNotification) => void;
/**
 * Verified-pairing replication emitter (Secure A2A Verified Pairing §3.8 / FD11),
 * injected by server.ts ONLY when the journal-backed emitter exists AND
 * `multiMachine.stateSync.threadlinePairing.enabled` is true (default false ⇒ NOT
 * injected ⇒ a strict no-op). Replicates ONLY the verified-IDENTITY RESULT across the
 * agent's OWN machines — NEVER the SAS, shared secret, or relay token (the emitter is
 * handed ONLY the 5-field result; it has no access to the SAS store). The emitter
 * NEVER throws out of a mutation (a replication failure must never break a local trust
 * write), so the manager calls it best-effort.
 */
export interface PairingReplicationEmitter {
    /** Emit a `put` for a freshly mutual-verified pairing (the 5-field result). */
    emitVerified(result: {
        peerFp: string;
        peerIdentityPub: string;
        verifiedAt: string;
        verifiedOnMachine: string;
    }): void;
    /** Emit a `delete` tombstone for a revoked / verification-failed pairing (un-verify
     *  sticks pool-wide), keyed on the peer fingerprint. */
    emitRevoke(peerFp: string, deletedAt: string): void;
}
export interface InteractionStats {
    messagesReceived: number;
    messagesResponded: number;
    successfulInteractions: number;
    failedInteractions: number;
    successRate: number;
    streakSinceIncident: number;
    lastInteraction: string | null;
}
/**
 * The credential-bearing operation (Secure A2A Verified Pairing, §3.3).
 * Deliberately NOT a member of any `DEFAULT_ALLOWED_OPS` level: it is allowed
 * ONLY for a peer whose trustSource === 'mutual-verified' AND level >= 'trusted'
 * (never by 'autonomous' alone, never by 'setup-default'/auto-handshake).
 * That gate lives in `isCredentialShareAllowed*`, not the level table.
 */
export declare const CREDENTIAL_SHARE_OP = "credential-share";
export declare class AgentTrustManager {
    private readonly threadlineDir;
    private readonly profilesPath;
    private readonly auditPath;
    private profiles;
    private onTrustChange;
    private saveDirty;
    private saveTimer;
    /** Machine-local 0600 store for pending-verification SAS words (FD4). */
    private readonly pendingStore;
    /** Verified-pairing replication emitter (§3.8, injected/dark by default). Absent ⇒
     *  strict no-op (single-machine behavior). */
    private pairingReplication?;
    /** This machine's id (stamped into a replicated `verifiedOnMachine`). Absent ⇒ '?'. */
    private machineId;
    constructor(options: {
        stateDir: string;
        onTrustChange?: TrustChangeCallback;
        /** This machine's id, stamped into a replicated verified-identity result (§3.8). */
        machineId?: string;
    });
    /**
     * Late-bind the verified-pairing replication emitter (§3.8). server.ts constructs the
     * journal-backed emitter AFTER the trust manager; passing undefined detaches (back to
     * single-machine no-op). Idempotent. Optionally re-sets the machine id used for a
     * replicated `verifiedOnMachine`.
     */
    setPairingReplicationEmitter(emitter: PairingReplicationEmitter | undefined, machineId?: string): void;
    /**
     * Get trust profile for an agent by name or fingerprint.
     * Checks direct key match first (name or fingerprint), then scans
     * profile display names for backwards compatibility.
     */
    getProfile(agentNameOrFingerprint: string): AgentTrustProfile | null;
    /**
     * Get or create a trust profile for an agent.
     * New agents start as 'untrusted' with 'setup-default' source.
     */
    getOrCreateProfile(agentName: string): AgentTrustProfile;
    /**
     * Get trust profile by cryptographic fingerprint.
     * Used for relay inbound messages where identity is fingerprint-based.
     */
    getProfileByFingerprint(fingerprint: string): AgentTrustProfile | null;
    /**
     * Get or create a trust profile keyed by fingerprint.
     * For relay agents, the fingerprint IS the identity.
     * Relay agents default to 'verified' (can send messages) rather than
     * 'untrusted' (probes only), since they've already authenticated with the relay.
     *
     * IMPORTANT: Always keys by fingerprint to avoid collisions between
     * same-named agents on different machines. Display name is stored in
     * the profile's `agent` field for human readability.
     */
    getOrCreateProfileByFingerprint(fingerprint: string, displayName?: string): AgentTrustProfile;
    /**
     * Get trust level by fingerprint. Returns 'untrusted' for unknown agents.
     */
    getTrustLevelByFingerprint(fingerprint: string): AgentTrustLevel;
    /**
     * Get allowed operations by fingerprint.
     */
    getAllowedOperationsByFingerprint(fingerprint: string): string[];
    /**
     * Set trust level by fingerprint.
     * Operates directly on the fingerprint-keyed profile to avoid
     * name collision issues with setTrustLevel's name-based lookup.
     */
    setTrustLevelByFingerprint(fingerprint: string, level: AgentTrustLevel, source: AgentTrustSource, reason?: string, displayName?: string): boolean;
    /**
     * Record a received message by fingerprint (debounced save).
     */
    recordMessageReceivedByFingerprint(fingerprint: string): void;
    /**
     * Set trust level for an agent (by name).
     * UPGRADES require source: 'user-granted' or 'paired-machine-granted'.
     * Returns true if the change was applied, false if rejected.
     */
    setTrustLevel(agentName: string, level: AgentTrustLevel, source: AgentTrustSource, reason?: string): boolean;
    /**
     * Core trust level application logic. Shared by name-based and fingerprint-based paths.
     */
    private applyTrustLevel;
    /**
     * Record a pending-verification pairing after a handshake.
     *
     * Writes the (replicated) pairing state ON the trust profile AND the
     * sensitive SAS words into the machine-local 0600 pending store. A NEW
     * handshake (new pairingId) resets pairingState to 'pending-verification'
     * and clears any prior verifiedAt/peerAcked (FD4) — a fresh epoch discards
     * the prior confirmation.
     *
     * Returns false for a self-pair (peerFp === ownFp, FD12). Does NOT touch the
     * trust source or level — that only happens at `markMutualVerified`.
     */
    recordPendingVerification(peerFp: string, args: {
        pairingId: string;
        peerIdentityPub: string;
        sasWords: string[];
        sasFingerprint: string;
        ownFp: string;
        displayName?: string;
    }): boolean;
    /**
     * THE ONLY code path that may set trustSource='mutual-verified' (§3.3).
     *
     * Preconditions:
     * - `operatorConfirm` must be truthy (the operator-PIN check happens at the
     *   route layer; here we require the flag is present).
     * - `peerFp !== ownFp` (FD12 self-pair guard).
     * - The pairing must be in 'pending-verification' (or already 'mutual-verified')
     *   for the SAME pairingId (epoch binding — a stale pairingId is rejected).
     *
     * Write order (§3.7): pairing record fields written → trust source/level set
     * LAST, so a partial failure fails closed (never source-without-record).
     * Raises level to 'trusted' if currently below it (never to 'autonomous', FD6).
     * Discards the machine-local pending SAS store on success.
     *
     * Returns false if any precondition fails (no mutation).
     */
    markMutualVerified(peerFp: string, args: {
        pairingId: string;
        operatorConfirm: boolean;
        peerAcked?: boolean;
        ownFp?: string;
    }): boolean;
    /**
     * Mark a pairing 'verification-failed' (operator-asserted SAS mismatch, §3.2).
     * Forces the peer to 'untrusted', clears the mutual-verified source, and
     * discards the pending SAS store. NOT used for a missing-receipt timeout
     * (that simply stays 'pending-verification').
     */
    markVerificationFailed(peerFp: string, reason: string): boolean;
    /**
     * Set the optional `peerAcked` liveness flag (FD8) — driven ONLY by a real
     * signature-verified inbound receipt at the receipt-handling layer. Never
     * elevates trust on its own; a missing receipt never strands verification.
     */
    recordPeerAck(peerFp: string, pairingId: string): boolean;
    /** Read the pending SAS record (incl. words) for a peer — operator surface only. */
    getPendingPairing(peerFp: string): PendingPairingRecord | null;
    /**
     * Honor a replicated `mutual-verified` RESULT from a PEER MACHINE by PINNING the
     * record's identity key (Secure A2A Verified Pairing §3.8 / FD11, codex finding 1).
     *
     * This is the ONLY path that sets `pairingState='identity-verified'` — the INHERITED
     * state on a machine OTHER than the one whose operator SAS-compared. It is driven ONLY
     * by an inbound replicated record (the union read), NEVER by a local actor — so it can
     * never be self-granted, and it can never set the LOCAL `mutual-verified` state (that
     * stays reserved for THIS machine's own operator confirm).
     *
     * KEY-PINNING (the load-bearing rule): the caller passes the identity key THIS
     * machine's own live handshake presented for the peer (`presentedIdentityPub`), or
     * undefined if there is no live handshake yet. If a live handshake's key DIFFERS from
     * the pinned `peerIdentityPub`, the inheritance is REFUSED and the local pairing is
     * DOWNGRADED to `pending-verification` (re-verify on this machine) — a
     * fingerprint-substitution attempt, never auto-honored.
     *
     * INHERITED ≠ CHANNEL-READY: `identity-verified` asserts only "this identity key was
     * SAS-verified by a human somewhere". credential-share on THIS machine additionally
     * requires THIS machine's own live encrypted channel — the outbound CredentialShareGate
     * enforces that encrypted-path half (it is a SEPARATE precondition).
     *
     * Returns true iff the inheritance was honored (state set to identity-verified). A
     * mismatch returns false AND downgrades. The trust source is set `mutual-verified`
     * (so the identity HALF of the credential gate passes) at level `trusted` — but NEVER
     * raises beyond trusted, and a local `mutual-verified`/`verification-failed` state is
     * not clobbered (a machine that already did its own thing wins).
     */
    inheritReplicatedVerification(peerFp: string, args: {
        peerIdentityPub: string;
        verifiedAt?: string;
        verifiedOnMachine?: string;
        presentedIdentityPub?: string;
        displayName?: string;
    }): boolean;
    /** Downgrade a profile to pending-verification + drop any credential-share authorization
     *  (a key-pin mismatch on an inherited record, §3.8). Internal helper. */
    private downgradeToPending;
    /**
     * Whether `credential-share` is allowed for a peer (by fingerprint).
     * TRUE iff trustSource === 'mutual-verified' AND level >= 'trusted' (§3.3).
     * Never granted by 'autonomous' alone, never by 'setup-default'/auto-handshake.
     */
    isCredentialShareAllowedByFingerprint(fingerprint: string): boolean;
    /**
     * Profile-level credential-share check — the IDENTITY half (shared by fingerprint +
     * name paths). TRUE iff trustSource === 'mutual-verified' AND level >= 'trusted' AND
     * the pairingState is either:
     *   - `mutual-verified` (THIS machine's operator SAS-confirmed), OR
     *   - `identity-verified` (an INHERITED, key-pinned verification from a peer machine,
     *     §3.8) — the identity key was SAS-verified by a human somewhere and pinned here.
     *
     * NOTE: the inherited `identity-verified` floor satisfies the IDENTITY half ONLY. The
     * CHANNEL half (this machine's own live encrypted+signed path — never plaintext, §3.5)
     * is enforced SEPARATELY by `evaluateOutboundCredentialShare` via `hasEncryptedSendPath`.
     * So credential-share on a machine that inherited the verification = inherited
     * identity-verified (here) AND that machine's own encrypted channel (the outbound gate).
     */
    isCredentialShareAllowedForProfile(profile: AgentTrustProfile | null): boolean;
    /**
     * Record a successful or failed interaction with an agent.
     */
    recordInteraction(agentName: string, success: boolean, details?: string): void;
    /**
     * Record a received message from an agent.
     */
    recordMessageReceived(agentName: string): void;
    /**
     * Record a response sent to an agent.
     */
    recordMessageResponded(agentName: string): void;
    /**
     * Check if an agent is allowed to perform an operation.
     * Checks both trust-level defaults and explicit allowed/blocked lists.
     */
    checkPermission(agentName: string, operation: string): boolean;
    /**
     * Get interaction statistics for an agent.
     */
    getInteractionStats(agentName: string): InteractionStats | null;
    /**
     * Safety-only auto-downgrade. Never auto-upgrades.
     * Called by CircuitBreaker (3 activations in 24h) or on crypto failure.
     */
    autoDowngrade(agentName: string, reason: string): boolean;
    /**
     * Check for staleness-based auto-downgrade.
     * If an agent hasn't interacted in 90 days, downgrade one level.
     * Returns true if a downgrade occurred.
     */
    checkStalenessDowngrade(agentName: string, nowMs?: number): boolean;
    /**
     * List all trust profiles, optionally filtered by trust level.
     */
    listProfiles(filter?: {
        level?: AgentTrustLevel;
        source?: AgentTrustSource;
    }): AgentTrustProfile[];
    /**
     * Block a specific operation for an agent.
     */
    blockOperation(agentName: string, operation: string): void;
    /**
     * Unblock a specific operation for an agent.
     */
    unblockOperation(agentName: string, operation: string): void;
    /**
     * Read audit trail entries. Returns all entries or last N entries.
     */
    readAuditTrail(limit?: number): TrustAuditEntry[];
    /**
     * Force reload profiles from disk.
     */
    reload(): void;
    /**
     * Flush any pending saves and stop the debounce timer.
     * Call on shutdown for clean exit.
     */
    flush(): void;
    /**
     * Schedule a debounced save (dirty-flag + interval flush).
     * Avoids synchronous disk writes on every message received.
     */
    private scheduleSave;
    private loadProfiles;
    private save;
    private writeAudit;
    private compareTrust;
}
//# sourceMappingURL=AgentTrustManager.d.ts.map