/**
 * HttpLeaseTransport — the low-latency wire path for the fenced lease (spec §6:
 * "the low-latency authoritative copy of the lease travels over the tunnel").
 *
 * Implements LeaseTransport over the existing authenticated machine-to-machine
 * HTTP channel (signRequest + machineAuthMiddleware, the same path /api/heartbeat
 * uses). The git copy remains the durable audit/CAS substrate; this transport
 * ACCELERATES acquisition + carries renewals, and a holder that cannot reach
 * peers for > leaseTtlMs self-suspends (the renewal-requires-medium rule).
 *
 * observed() returns the freshest lease this machine has RECEIVED from a peer
 * (fed by the /api/lease endpoint via recordObserved) plus the per-holder nonce
 * map for replay detection. isReachable() reflects whether a recent broadcast
 * reached at least one peer.
 *
 * The HTTP layer is injected (fetchImpl) so the broadcast/observe/reachability
 * logic is unit-testable without a network.
 */
import type { LeaseTransport } from './LeaseCoordinator.js';
import type { LeaseRecord } from './types.js';
export interface LeasePeer {
    machineId: string;
    /** Base URL of the peer (its lastKnownUrl / tunnel URL). */
    url: string;
}
export interface HttpLeaseTransportDeps {
    selfMachineId: string;
    signingKeyPem: string;
    /** Resolve the current set of reachable peers (excludes self). */
    peers: () => LeasePeer[];
    /** Monotonic per-request sequence (reuse the machine's nonce/sequence source). */
    nextSequence: () => number;
    /** Injected fetch (defaults to global fetch). */
    fetchImpl?: typeof fetch;
    /** How recent a successful broadcast counts as "reachable". Default = leaseTtlMs. */
    reachabilityWindowMs?: number;
    /**
     * Per-request abort timeout (P19 brake: a hung socket must not wedge the
     * caller's fixed-cadence loop — the pull loop's `leasePulling` guard would
     * otherwise stay held forever). Default 30s: the timeout must sit ABOVE the
     * fleet's documented 5–40s receiver-side event-loop-stall envelope's bulk —
     * a slow-but-alive peer must NOT be converted into "no medium", because a
     * failed broadcast feeds the renewal path's self-suspend (second-pass
     * reviewer finding). A truly hung socket never returns, so 30s bounds the
     * wedge exactly as well as a smaller value would. server.ts derives this
     * from leaseTtlMs (min(ttl/2, 30s)).
     */
    requestTimeoutMs?: number;
    /**
     * Coarse-reminder interval for the per-peer failure log gate (P19 brake:
     * per-attempt logging is amplification — a down peer at a 5s cadence wrote
     * ~17k lines/day). Default 360 consecutive failures (~30min at 5s).
     */
    failureLogEveryN?: number;
    now?: () => number;
    logger?: (msg: string) => void;
}
export declare class HttpLeaseTransport implements LeaseTransport {
    private readonly d;
    private lastObserved;
    private lastNonceByHolder;
    private lastBroadcastOkAt;
    private lastPullOkAt;
    private readonly windowMs;
    private readonly requestTimeoutMs;
    /** State-change failure logging (first/Nth/recovery) — never per-attempt. */
    private readonly logGate;
    constructor(deps: HttpLeaseTransportDeps);
    /** Gated failure/recovery logging — emits only on state changes + coarse reminders. */
    private logFailure;
    private logSuccess;
    private now;
    private log;
    /**
     * Broadcast our lease to every peer over the authenticated channel. Resolves
     * true if at least one peer accepted (we have a live medium); false if none
     * were reachable.
     */
    broadcast(lease: LeaseRecord): Promise<boolean>;
    observed(): {
        lease: LeaseRecord | null;
        lastNonceByHolder: Record<string, number>;
    };
    isReachable(): boolean;
    /**
     * Record a lease received from a peer (called by the /api/lease endpoint after
     * machine-auth verification). Keeps only the highest-epoch observed lease and
     * advances the per-holder nonce watermark (replay detection happens in
     * FencedLease.acceptTunnelLease which reads this map).
     */
    recordObserved(lease: LeaseRecord): void;
    /**
     * Active PULL (Cross-Machine Coherence): GET a peer's current lease over the
     * authenticated channel and fold it into our effective view via the SAME
     * recordObserved path the push receiver uses. This lets a standby *ask* for the
     * holder's lease instead of only waiting to be pushed to — so a quiet or one-way
     * network can't blind it. Returns the peer's lease (may name a third machine as
     * holder — re-served), or null when the peer has none / is unreachable.
     *
     * Uses POST /api/lease/pull with a signed empty body: machine-auth is body-hash
     * based (signs SHA256(body)), so a POST with `{}` authenticates cleanly where a
     * GET (whose body fetch would drop) cannot. A successful pull — even one that
     * returns no lease — proves reachability.
     */
    pullPeer(peer: LeasePeer): Promise<LeaseRecord | null>;
    /**
     * Best-effort fan-out pull of every peer's lease. Failures are advisory (a peer
     * being unreachable is data, not an error) — mirrors broadcast()'s tolerance.
     * Cadence/jitter is owned by the caller (the standby loop), not here.
     */
    pullAllPeers(): Promise<void>;
}
//# sourceMappingURL=HttpLeaseTransport.d.ts.map