/**
 * registryReplayGuard — G2 replay/freshness + unknown-key constraint (spec §8 G2).
 *
 * Validates an incoming (pulled) registry entry before it is applied locally.
 * Signed-commit verification (v3) already rejects unsigned/revoked commits;
 * this guard adds the content-level checks a signature alone cannot give:
 *
 *  1. Replay/freshness — a pulled entry whose per-author `syncSequence` is not
 *     strictly greater than the last applied for its author is discarded.
 *  2. Epoch floor — a pulled entry whose `authoredUnderEpoch` is below the
 *     current committed epoch is discarded. This catches the case a per-author
 *     sequence cannot: a machine that wiped/restored local state (sequence
 *     resets to 0) or re-keyed cannot smuggle in an authority-bearing write,
 *     because its stale leaseEpoch is rejected regardless of a locally-monotonic
 *     sequence.
 *  3. Unknown-key first commit — the FIRST commit from a previously-unseen
 *     machineId is accepted ONLY if it is role:standby + rejoined:true (or a
 *     pairing-join record). Any unknown-key first commit asserting an awake
 *     role or a lease claim is rejected — a rejoining machine must pull-and-read
 *     before writing, never assert its stale prior role.
 *
 * Pure logic, unit-tested on both sides of every boundary.
 */
import type { MachineRegistryEntry } from './types.js';
export interface ReplayGuardInput {
    machineId: string;
    /** The incoming (pulled) entry for this machine. */
    incoming: MachineRegistryEntry;
    /** The locally-known entry for this machine (undefined = previously unseen). */
    local?: MachineRegistryEntry;
    /** The current committed lease epoch (registry.lease?.epoch ?? 0). */
    currentCommittedEpoch: number;
    /** Whether this incoming entry carries a valid pairing-join record (allows an awake-less first write). */
    hasValidJoinRecord?: boolean;
}
export interface ReplayDecision {
    accept: boolean;
    reason: string;
}
export declare function evaluateRegistryEntry(input: ReplayGuardInput): ReplayDecision;
/**
 * Reconcile a full incoming registry against the local one, entry by entry.
 * Returns the entries to apply (accepted) and the rejected ones with reasons
 * (logged, never applied). The lease object is reconciled separately by the
 * FencedLease layer (epoch CAS), not here.
 */
export declare function reconcileRegistryEntries(opts: {
    localEntries: Record<string, MachineRegistryEntry>;
    incomingEntries: Record<string, MachineRegistryEntry>;
    currentCommittedEpoch: number;
    joinRecords?: ReadonlySet<string>;
}): {
    accepted: Record<string, MachineRegistryEntry>;
    rejected: Array<{
        machineId: string;
        reason: string;
    }>;
};
//# sourceMappingURL=registryReplayGuard.d.ts.map