/**
 * ADR-095 G2 — pluggable transport for hive-mind consensus protocols.
 *
 * The raft/byzantine/gossip consensus implementations historically used a
 * local `EventEmitter` for *everything* — both observability events
 * ("leader.elected", "consensus.achieved") AND inter-node messages
 * (append-entries, vote requests, pre-prepare/prepare/commit). The latter
 * never actually crossed a process or node boundary: a node "sent" a
 * message by `emit`ting it locally and synthesizing the peer's reply
 * inline. That's the single-process limitation #G2 names.
 *
 * This module separates the inter-node-message dimension behind a
 * `ConsensusTransport` interface. Two implementations:
 *
 *   - `LocalTransport` — an in-process registry. Multiple consensus
 *     instances in the same Node process share a registry and deliver
 *     messages to each other synchronously. Matches the current
 *     single-process behavior; the default so nothing breaks.
 *   - `FederationTransport` (separate file, ADR-104 wire) — serializes
 *     ConsensusMessages into federation envelopes, signs them with the
 *     node's Ed25519 key, sends over WS via agentic-flow/transport/loader,
 *     and dispatches inbound envelopes with signature verification.
 *
 * Observability events stay on the consensus class's own EventEmitter —
 * this is purely the messaging layer.
 *
 * No new dependencies: Ed25519 signing uses Node's built-in `crypto`
 * (`generateKeyPairSync('ed25519')` + `sign`/`verify` with `null` algorithm,
 * which is correct for Ed25519).
 */
/** A message exchanged between consensus nodes. */
export interface ConsensusMessage {
    /** Protocol message type — e.g. 'append-entries', 'request-vote', 'pre-prepare', 'prepare', 'commit', 'gossip', 'gossip-ack'. */
    readonly type: string;
    /** Sender node id. */
    readonly from: string;
    /** Recipient node id. Omit for broadcast. */
    readonly to?: string;
    /** Protocol payload (term, log entries, vote, digest, …). */
    readonly payload: unknown;
    /** Raft term, when applicable. Lets the transport drop stale-term messages cheaply. */
    readonly term?: number;
    /** PBFT view number, when applicable. */
    readonly viewNumber?: number;
    /** Monotonic per-sender sequence number — replay defense. */
    readonly seq?: number;
    /** Ed25519 signature (base64) over `canonicalizeForSigning(msg)`. */
    readonly signature?: string;
}
/**
 * A reply to a `send()`. Protocols use this for the request-response legs
 * (request-vote → vote-response, append-entries → append-entries-response).
 * Broadcasts don't get replies; responses arrive via `onMessage`.
 */
export type ConsensusReply = ConsensusMessage | null;
export type ConsensusMessageHandler = (msg: ConsensusMessage) => Promise<ConsensusReply | void> | ConsensusReply | void;
export interface ConsensusTransport {
    /** This node's id (the one consensus protocols use as `from`). */
    readonly nodeId: string;
    /**
     * Send a message to a specific peer. Resolves with the peer's reply
     * (or `null` if the peer ack'd without a reply), rejects on timeout or
     * unreachable peer. `timeoutMs` defaults to the transport's configured value.
     */
    send(to: string, msg: Omit<ConsensusMessage, 'from'>, timeoutMs?: number): Promise<ConsensusReply>;
    /** Broadcast to all currently-reachable peers. Resolves once dispatched; replies (if any) arrive via onMessage. */
    broadcast(msg: Omit<ConsensusMessage, 'from'>): Promise<void>;
    /** Register the inbound-message handler. Calling again replaces the previous handler. */
    onMessage(handler: ConsensusMessageHandler): void;
    /** Currently-reachable peer node ids (excludes self). */
    peers(): readonly string[];
    /** Tear down. After close(), send/broadcast reject. */
    close(): Promise<void>;
}
export interface NodeKeyPair {
    /** Ed25519 private key in PKCS8 PEM. */
    readonly privateKeyPem: string;
    /** Ed25519 public key in SPKI PEM. */
    readonly publicKeyPem: string;
}
/** Generate a fresh Ed25519 keypair for a consensus node. */
export declare function generateNodeKeyPair(): NodeKeyPair;
/**
 * Canonical byte string for signing. Deterministic across hosts: deep-sorted-key
 * JSON of the message's content fields (everything except `signature`).
 */
export declare function canonicalizeForSigning(msg: Omit<ConsensusMessage, 'signature'>): Buffer;
/** Stable digest of a message's content — handy for dedup and logging. */
export declare function messageDigest(msg: Omit<ConsensusMessage, 'signature'>): string;
/** Sign a message with an Ed25519 private key (PEM). Returns base64 signature. */
export declare function signMessage(msg: Omit<ConsensusMessage, 'signature'>, privateKeyPem: string): string;
/**
 * Verify a signed message against a peer's Ed25519 public key (PEM).
 * Returns true iff the signature is present and valid over the message's
 * content fields. Fail-closed: a missing signature returns false.
 */
export declare function verifyMessage(msg: ConsensusMessage, publicKeyPem: string): boolean;
/**
 * Shared registry of LocalTransport instances. Multiple consensus nodes in
 * the same process register here; send/broadcast deliver to peers' handlers.
 * Use a fresh registry per test to keep tests isolated.
 */
export declare class LocalTransportRegistry {
    private readonly nodes;
    register(t: LocalTransport): void;
    unregister(nodeId: string): void;
    get(nodeId: string): LocalTransport | undefined;
    peerIds(exclude: string): string[];
}
/** Process-wide default registry. Tests should pass their own. */
export declare const defaultLocalRegistry: LocalTransportRegistry;
export interface LocalTransportOptions {
    readonly registry?: LocalTransportRegistry;
    readonly defaultTimeoutMs?: number;
    /** Optional Ed25519 keypair — when set, outbound messages are signed and inbound are verified against the sender's pubkey (resolved via `resolvePeerPublicKey`). */
    readonly keyPair?: NodeKeyPair;
    /** Map a peer nodeId → its Ed25519 public key PEM. Required if `keyPair` is set and you want verification. */
    readonly resolvePeerPublicKey?: (nodeId: string) => string | undefined;
}
export declare class LocalTransport implements ConsensusTransport {
    readonly nodeId: string;
    private readonly registry;
    private readonly defaultTimeoutMs;
    private readonly keyPair?;
    private readonly resolvePeerPublicKey?;
    private handler;
    private closed;
    private seqCounter;
    /** Per-sender last-seen seq for replay defense (only used when signed). */
    private readonly lastSeenSeq;
    constructor(nodeId: string, opts?: LocalTransportOptions);
    onMessage(handler: ConsensusMessageHandler): void;
    peers(): readonly string[];
    private stamp;
    /** Deliver an inbound message to a target's handler, with optional sig + replay checks. */
    private deliver;
    send(to: string, msg: Omit<ConsensusMessage, 'from'>, timeoutMs?: number): Promise<ConsensusReply>;
    broadcast(msg: Omit<ConsensusMessage, 'from'>): Promise<void>;
    close(): Promise<void>;
}
//# sourceMappingURL=transport.d.ts.map