/**
 * OwnershipApplier — the cross-machine half of the transfer fix (spec
 * docs/specs/live-user-channel-proof-standard.md §7.2). It runs OFF the routing
 * hot path (on a periodic tick) and materializes durable local ownership records
 * from the REPLICATED coherence-journal placement entries, so the machine a topic
 * was transferred TO actually resolves itself (or the true owner) as the owner on
 * the next inbound message.
 *
 * The bug it closes (2026-06-15): /pool/transfer wrote the target's ownership into
 * the SOURCE machine's in-memory Map and emitted a placement entry to the journal.
 * The journal entry REPLICATES to peers (peers/<machineId>.topic-placement.jsonl),
 * but no one ever turned a replicated placement entry back into an ownership record
 * on the receiving machine — so the target's owner-resolution read null and the
 * router re-placed the topic locally instead of forwarding. This applier is exactly
 * that missing step.
 *
 * Correctness model: a placement entry carries (topic, owner, ownershipEpoch). The
 * applier takes the HIGHEST-epoch placement per topic across all streams (own +
 * peer replicas) and adopts it into the local durable store via the store's
 * fast-forward CAS — which lands ONLY if it strictly advances the local epoch. So
 * a stale replicated entry can never clobber a fresher local decision, and the
 * (topic, epoch) ordering is the same key the journal dedupes on. This adopts an
 * ALREADY-DECIDED ownership (a replication step), not a new FSM transition — hence
 * it writes the record directly rather than running place/claim actions.
 *
 * Split-brain: the applier does NOT independently re-solve lease split-brain (the
 * spec's narrowed claim). It adopts the highest-epoch placement; under a healthy
 * single-holder lease that is correct, and a genuine lease split-brain surfaces via
 * the existing lease-attention path. Lease-epoch fencing inside the placement entry
 * is a tracked follow-on (PlacementData does not yet carry leaseEpoch).
 */
import type { SessionOwnershipStore } from './SessionOwnershipRegistry.js';
/** The minimal slice of CoherenceJournalReader the applier needs (for testability). */
export interface PlacementReader {
    query(opts: {
        kind?: string;
        limit?: number;
        topic?: number;
    }): {
        entries: Array<{
            topic?: number;
            machine: string;
            data: Record<string, unknown>;
            source?: string;
        }>;
    };
}
export interface OwnershipApplierDeps {
    /** Reads replicated + own placement entries (CoherenceJournalReader). */
    reader: PlacementReader;
    /** The SAME durable store the SessionOwnershipRegistry reads — so a materialized
     *  record is immediately visible to owner-resolution / routing. */
    store: SessionOwnershipStore;
    /**
     * This machine's mesh id — used ONLY for the SELF-vs-peer log label, never for
     * materialization (every placement is adopted regardless of owner). Accepts a
     * **late-bound getter** so a caller can wire the applier before `_meshSelfId` is
     * resolved without capturing a stale `null` (the boot-ordering hazard this fix closes);
     * a plain string still works for callers/tests that already have the id.
     */
    selfMachineId: string | (() => string | null | undefined);
    /** Max placement entries to scan per tick (bounded cost). Default 1000. */
    scanLimit?: number;
    logger?: (msg: string) => void;
    now?: () => number;
}
export interface OwnershipApplyResult {
    /** Distinct topics that had a placement entry this tick. */
    examined: number;
    /** Topics whose local ownership record was advanced from a (newer) placement. */
    materialized: number;
}
export declare class OwnershipApplier {
    private readonly d;
    constructor(deps: OwnershipApplierDeps);
    private now;
    private log;
    /** Resolve the (possibly late-bound) self machine id at tick time, for the log label only. */
    private resolveSelf;
    /**
     * One pass: adopt the highest-epoch placement per topic into the local store.
     * Returns counts for observability. Never throws — a read/parse failure degrades
     * to "materialized fewer this tick", never a crash on the routing-adjacent path.
     */
    tick(): OwnershipApplyResult;
}
//# sourceMappingURL=OwnershipApplier.d.ts.map