/**
 * design/179 §5/§8 / design/389 — the file backend of the permission-rule store's DURABLE partition (one
 * bucket file per owner), plus the file home of the ORG partition's durable state (`org.json`).
 *
 * ## Schema 4 only
 *
 * Every row carries its `behavior`; the org state lives in one `org.json`, never inside a bucket. The
 * reader accepts schema 4 ONLY: any other schema word is refused whole, loudly, bytes left untouched —
 * this engine performs no migration of an older engine's buckets.
 *
 * ## Why this store builds its own symlink refusal
 *
 * The other file stores canonicalize with `realpath`, which RESOLVES a symlink rather than refusing one —
 * the right answer for a data directory, the wrong one for a file that decides what runs without asking.
 * So the refusal is assembled here from the pieces this repository already uses elsewhere: the directory
 * is `lstat`ed and refused if it is a symlink, not a directory, or owned by another user; the temp file is
 * opened `O_EXCL | O_NOFOLLOW` so no planted link is ever traversed; the publish is the standard
 * write-temp → fsync → rename → fsync-dir sequence; and the READ side `lstat`s too, because `readFileSync`
 * follows a link happily.
 *
 * ## One writer, enforced — reading is unrestricted
 *
 * Atomic rename keeps a file from tearing; it does not make "read the revision, decide, write" atomic. Two
 * processes can each read revision N, and the second rename discards the first one's add — or its
 * TOMBSTONE, leaving a rule somebody deleted standing.
 *
 * Three attempts at solving that inside the file established what does NOT work. Declaring single-process
 * use does not hold when the provider is independently constructible. A hand-rolled advisory lock brings
 * its own ownership bugs: pruning an abandoned lock races the next holder for the same path, and expiring
 * by age kills a live-but-slow writer. Write-then-read-back does not close it either — two writers can
 * each rename and each verify before the other renames, so both report success and one write is gone.
 * That last one is the instructive failure: no scheme that reasons only about the FILE can serialize
 * transactions, because the window opens before the first byte is written.
 *
 * So the boundary is enforced where it can be. Obtaining the WRITE face acquires the same process-level
 * lock the rest of this file-store family uses — write-then-link acquisition, no expiry by age, and a
 * prune only for a definitively dead owner — and a second holder, in this process or another, is refused
 * loudly instead of interleaving. Inside the one process that holds it, transactions are serialized and
 * the existing revision check is then a true compare-and-set.
 *
 * READING takes nothing. The gate reads on every shell call and must never be able to fail on a lock, so
 * the lock rides on the write face alone. A deployment that genuinely needs concurrent writers wants a
 * backend with real atomic compare-and-set, which is what the store seam exists for.
 *
 * ## Corruption is a whole-file refusal
 *
 * A file that does not parse, or whose checksum does not match its contents, yields ZERO rules and a loud
 * disclosure — never a partial load. Half a rule set is a set nobody reviewed. Note what the checksum is
 * and is not: it detects corruption, and it does not detect an editor, because an editor recomputes it.
 * For this backend the trust is host = user, exactly as for the settings file it mirrors.
 */
import type { PersistedRule, RuleTombstone } from "../../core/permission-rule-model.js";
import type { DurableRulePartition, DurableRulePartitionProvider, PermissionRuleWriter, QuarantinedRuleAdd, RuleOwner, RuleSyncFrontier, StoredRules, WritableDurableRulePartition } from "../../core/permission-rule-store.js";
import { PERMISSION_RULE_WRITER } from "../../core/permission-rule-store.js";
import type { OrgRuleStatePersistence, PersistedOrgRuleState } from "../../core/permission-rule-org.js";
import type { StoreDurability, StoreFidelity } from "../../core/checkpoint-store.js";
/**
 * The on-disk shape of one bucket. `schemaVersion` is the only field a future reader may rely on before
 * validating. Schema 4: the five core fields plus the OPTIONAL `sync` block (observation vector + round
 * timestamp) and `quarantined` area (rows moved out of the live view, bytes preserved); every rule,
 * tombstone and quarantine row carries its `behavior`. The org state is NOT here — see {@link OrgStateFile}.
 */
interface RuleFile {
    schemaVersion: 4;
    actor: string;
    counter: number;
    rev: number;
    rules: PersistedRule[];
    tombstones: RuleTombstone[];
    sync?: {
        observedVector?: RuleSyncFrontier;
        lastRoundAtMs?: number;
    };
    quarantined?: QuarantinedRuleAdd[];
    checksum: string;
}
/** The deployment-wide org state file: last-known-good snapshot + anti-rollback high-water, one blob. */
interface OrgStateFile {
    schemaVersion: 1;
    state: PersistedOrgRuleState;
    checksum: string;
}
/** The org partition's durable home in a rule directory. */
export declare const ORG_STATE_FILE = "org.json";
/** The anti-rollback contract's DESIGNED refusal (a lower high-water mark, or different content under
 *  the same revision) — distinguished by class from every other install failure, because the two are
 *  handled in opposite directions by the migration: a refusal means the block is superseded and may be
 *  dropped; anything else means the block has no second home yet and the legacy copy must be kept. */
export declare class OrgRevisionRefusal extends Error {
}
/** The local-owner bucket's FIXED file name — never a principal-hash path (identity absence is a
 *  structural position, not a name; design/182 §4.5). Cannot collide with `forPrincipal` names, which
 *  are 64 hex characters. */
declare const LOCAL_OWNER_FILE = "local-owner.json";
/** The durable adoption marker (design/182 §4.5 — the recoverable six-phase state machine's truth). */
export type RuleAdoptionFile = {
    schemaVersion: 1;
    marker: {
        from: RuleOwner;
        toPrincipal: string;
        phase: 2 | 3 | 4 | 5;
    };
} | {
    schemaVersion: 1;
    adopted: {
        from: RuleOwner;
        toPrincipal: string;
        atMs: number;
    };
};
/** The ADOPTION voice of {@link judgeRuleAdoptionFile}: the adoption helper's reader is the operator who repairs the
 *  marker, so it names the directory. A corrupt marker THROWS. */
export declare function readRuleAdoptionFile(dir: string): RuleAdoptionFile | undefined;
/** Atomically publish the adoption marker (same write-temp → fsync → rename discipline as the store). */
export declare function writeRuleAdoptionFile(dir: string, content: RuleAdoptionFile): void;
/** One principal's rule file. */
declare class FileDurableRulePartition implements WritableDurableRulePartition {
    private readonly dir;
    private readonly file;
    private readonly acquireWriteLock;
    private readonly onError?;
    readonly durability: StoreDurability;
    readonly fidelity: StoreFidelity;
    constructor(dir: string, file: string, acquireWriteLock: () => void, onError?: ((message: string) => void) | undefined);
    /** Read and validate. Any refusal answers with an empty set AND says so — never a silent empty store. The answer's
     *  sentence names no location ({@link refusalText}); the disclosure that accompanies it does. */
    private read;
    private disclose;
    /**
     * design/382 §4.3 — the AT-REST half of the durable two-member scope face: rows carrying a session
     * scope, read out of persisted bytes (a hand edit or a foreign writer — the engine's own write arms
     * refuse them loudly), are DROPPED from every read face and DISCLOSED. Never quarantined (the
     * quarantine area is itself durable), never silently ridden: a session authorization must not gain
     * an afterlife by being planted where the store cannot legally hold it. The write base
     * (`current()`) is deliberately NOT screened — foreign bytes are left in place for a person to look
     * at, exactly like every other damaged-row posture here; they simply never reach a live view, the
     * sync wire (`readRaw`) or adjudication.
     */
    private screenDurableRows;
    private write;
    list(): Promise<StoredRules>;
    /** The quarantine area (design/182 §5.2/§8.3): introspection only — never part of `list()`. Its posture
     *  on an unreadable bucket is `list()`'s, for the reason `list()` has it: "the quarantine is empty" and
     *  "the bucket cannot be read" are different facts about rows a person is meant to go and look at, and a
     *  face that answers the first about the second is the one shape this store never renders. An ABSENT
     *  bucket is still an empty quarantine. */
    quarantined(): Promise<QuarantinedRuleAdd[]>;
    /**
     * The current file, for a WRITE.
     *
     * Only genuine absence initializes a fresh one. An unreadable file — bad JSON, a failed checksum, an
     * unexpected shape, a planted symlink — makes every write throw, and the original bytes are left exactly
     * where they are. Treating corruption as emptiness here is what turns a recoverable incident into an
     * unrecoverable one: the next redemption would write a fresh file over the damaged one, discarding every
     * standing rule, every tombstone, the revision and the replica identity, along with the evidence of what
     * went wrong. Reads already answer zero rules for the same condition, so the lane stays fail-closed
     * while a person looks at the file.
     */
    private current;
    /**
     * Publish `next` and confirm it is readable and is the version just written.
     *
     * This is an integrity check, not concurrency control — a write lock is what makes the transaction
     * atomic (see the module doc). What it catches is the write that did not survive its own round trip:
     * a filesystem that reordered, a partial device failure, or a hand edit landing at exactly the wrong
     * moment. Failing here is loud rather than a reported conflict, because under the lock there is no
     * legitimate writer to have lost a race to.
     */
    private writeAndVerify;
    /** Serializes this process's transactions. With the write lock held, this is the whole of the
     *  serialization the revision check needs. */
    private writeChain;
    private serialize;
    /** Acquiring the write face takes the process lock; reading never does. */
    get [PERMISSION_RULE_WRITER](): PermissionRuleWriter;
    private readonly writer;
}
/**
 * The file-backed provider. One file per principal, named by a digest of the principal so no identity
 * string ever becomes a path component.
 *
 * An absent principal resolves to a store that reads zero rules and refuses to write — an unauthenticated
 * task does not share anyone's bucket.
 *
 * ROOT FREEZE (design/183 invariant I6, backlog #136⑤): every sibling file store gates construction on
 * the DATA ROOT's adoption marker, but this provider is built over the RULE BUCKET directory, which is
 * a caller-chosen path that need not sit under (or equal) the data root — so `dir` is not a usable
 * anchor for that gate and the bucket was writable straight through a root freeze. The anchor is
 * therefore taken EXPLICITLY, via `opts.dataRoot`: supply it whenever the rule bucket belongs to a data
 * root that `adoptLocalDataRoot` may adopt, and construction is refused while that root is mid-adoption
 * exactly like `FileStorageBackend`'s. Omitting it keeps the previous behavior (no root gate) — which is
 * also the EXEMPTION the adoption machine itself rides: its nested design/182 rule leg constructs this
 * provider without a `dataRoot` precisely because it runs while the marker is in flight, and the
 * bucket-level marker (read in `forPrincipal`/`forLocalOwner`) is what governs writes inside that arc.
 */
export declare class FileDurableRulePartitionProvider implements DurableRulePartitionProvider {
    private readonly dir;
    private readonly onError?;
    private lock;
    private orgPersistence;
    constructor(dir: string, onError?: ((message: string) => void) | undefined, opts?: {
        /** The data root whose adoption marker gates construction (design/183 I6). Absent ⇒ no root gate. */
        dataRoot?: string;
    });
    /** The org partition's durable home in this directory (design/182 §7.4 contract; `org.json`). Shares
     *  this provider's writer lock — an install is a write. */
    /** {@link judgeRuleAdoptionFile} at request time (owner resolution runs on every read), in {@link refusalText}'s voice. */
    private adoptionMarker;
    orgStatePersistence(): OrgRuleStatePersistence;
    private fileOrgPersistence;
    /** Take the writer lock, once, on first use of a write face. Reading never calls this. */
    private acquireWriteLock;
    forPrincipal(principal: string | undefined): DurableRulePartition;
    /** The read-only resolution of an adoption SOURCE: post-flip (phase ≥ 4 / terminal) always the
     *  target; pre-flip, whichever path currently holds the bytes (source first — it is the pre-flip
     *  truth when both somehow exist, which the resume path refuses loudly anyway). */
    private readOnlySourceView;
    /**
     * design/182 §4.5 (F-011) — the identity-less LOCAL bucket: a fixed file name, never a principal-hash
     * path. Once an adoption reached phase 4 (or its permanent terminal record), local-owner resolution
     * points at the adopted principal's bucket FOREVER — the marker is the truth the host configuration
     * reads, not the other way round, so a crash between marker and host-config change cannot fork writes
     * into a retired bucket. A corrupt marker throws (fail-closed) rather than guessing an owner.
     */
    forLocalOwner(): DurableRulePartition;
    /** Release the writer lock. A long-lived deployment holds it for its lifetime; a test or a short-lived
     *  tool releases so the next holder is not told a live process owns the directory. */
    dispose(): void;
}
/** The hash-derived file name of one principal's bucket — shared with the adoption helper so the rename
 *  and the resolver can never disagree about where a principal lives. */
export declare function principalRuleFileName(principal: string): string;
export { LOCAL_OWNER_FILE };
export type { FileDurableRulePartition, RuleFile, OrgStateFile };
