/**
 * design/182 §7 / design/389 — the ORG partition of the permission-rule store: core's half of the contract.
 *
 * Org rules and personal rules are opposite in polarity (deny/ask vs allow), authority (a server-side
 * administrator publish vs one human click per add) and evolution (whole-snapshot replacement vs
 * convergent merge). So the org layer has NO CRDT, no tombstones and no join: the server is the single
 * authority, a client holds a read-only versioned snapshot, an update is a whole replacement (revision
 * strictly ordered), and a rollback is a NEW revision carrying old content. Cross-layer tombstones are
 * structurally impossible — an org rule never enters `PersistedRule`, and an org snapshot replace
 * never touches a personal store's bytes. The two layers meet only at the CONSUMPTION site, where org
 * deny/ask folds strict-side: **org deny > org ask (non-dismissable) > personal allow rule > bare ask**.
 *
 * ## Availability semantics (the fail-closed shape, ruled through three review rounds)
 *
 * A deployment DECLARES governance by handing `createPermissionRuleStoreProvider` an `org` partition
 * config — governance is never inferred from a provider happening to be wired somewhere, and a config
 * naming no snapshot source is a loud boot contradiction instead of a silently ungoverned deployment.
 * Under that declaration the org adjudication surface must ALWAYS be effective:
 *  - the last successfully installed snapshot persists durably (`PersistedOrgRuleState`) and keeps
 *    adjudicating while the provider is unreachable, up to a deployment-configured staleness bound;
 *  - beyond the bound (or before any snapshot was ever installed) the resolution is `unavailable`, and
 *    the CONSUMING gate must fail the ENTIRE decision boundary closed: every terminal allow — policy
 *    allow and default allow included — tightens to an ask carrying `decisionReason: "org_unavailable"`
 *    AND `requiresRealApproval: true` (the same non-dismissable bit an org ask itself carries; without
 *    it a blanket `onAsk: "allow"` deployment would clear the synthetic ask — a third fail-open path),
 *    with the personal-rule lane and the auto-mode classifier both disarmed. That obligation lives at
 *    the gate integration; THIS module's contract is to report `unavailable` honestly and never lapse
 *    into an empty-rules answer that reads as "not governed".
 *
 * ## Anti-rollback
 *
 * `revision` is an orderable server-monotone number, and the installed high-water mark persists with
 * the snapshot in ONE atomic write: a replayed older snapshot (fresh `fetchedAtMs`, old content) is
 * refused and disclosed — identity comparison alone cannot catch it, and an in-memory-only mark would
 * accept revision N−1 after a restart. Signature / predecessor chaining belongs to the privilege-
 * separation ticket; the high-water mark is the floor that needs no key distribution.
 */
import { type PersistedRule, type RuleRejectCode } from "./permission-rule-model.js";
import type { PermissionRuleStore } from "./permission-rule-provider.js";
/** One org rule. There is structurally no allow bucket (design/179 §9: the org layer only tightens). */
export interface OrgPermissionRule {
    rule: string;
    behavior: "deny" | "ask";
}
/** The read-only versioned snapshot a client holds. */
export interface OrgRuleSnapshot {
    /** Server-monotone orderable revision. A snapshot below the persisted high-water mark is refused. */
    revision: number;
    rules: OrgPermissionRule[];
    /** Reserved for the privilege-separation ticket's signed-snapshot contract. Carried, not verified here. */
    signature?: string;
    /** Observation timestamp (epoch ms) — staleness input only, never adjudication input. */
    fetchedAtMs: number;
}
/** Where the deployment fetches the current snapshot. `undefined` = the provider has none to give. */
export interface OrgRuleSnapshotProvider {
    current(): Promise<OrgRuleSnapshot | undefined>;
}
/**
 * The durable org state: last-known-good snapshot + the anti-rollback high-water mark, installed in one
 * atomic write. SQL twin note (server/org ticket): `revision_high_water` and `installed_at_ms` are
 * structured columns (`_ms` suffix for epoch milliseconds); the snapshot itself is a JSON blob — it is
 * installed and read whole, never row-queried.
 */
export interface PersistedOrgRuleState {
    revisionHighWater: number;
    snapshot: OrgRuleSnapshot;
    installedAtMs: number;
}
/** The durable home of {@link PersistedOrgRuleState}. The file backend implements it over a
 *  deployment-level `org.json` published with the same O_EXCL/fsync/rename discipline as the rule files
 *  (`FileDurableRulePartitionProvider.orgStatePersistence()`); a SQL twin keeps one blob row.
 *
 *  CONTRACT: `installOrgState` must REFUSE (throw) an install that would LOWER the persisted
 *  `revisionHighWater` — the overlay serializes its own resolves, but two overlay instances over one
 *  durable home can interleave read-then-write, and the backend's atomic write is the one place the
 *  lowering can be caught. The file backend enforces this under its write serialization. */
export interface OrgRuleStatePersistence {
    readOrgState(): Promise<PersistedOrgRuleState | undefined>;
    installOrgState(state: PersistedOrgRuleState): Promise<void>;
}
/** The `decisionReason` the consuming gate stamps on the synthetic asks it mints while org adjudication
 *  is unavailable. Exported so the gate integration and its tests share one spelling — and TYPED as the
 *  member of {@link import("./tool-policy.js").DecisionReason} it must equal, so the constant and the
 *  vocabulary cannot drift into two spellings of one word. */
export declare const ORG_UNAVAILABLE_DECISION_REASON: Extract<import("./tool-policy.js").DecisionReason, "org_unavailable">;
/**
 * How long a single org adjudication may take before the consuming gate stops waiting and reads the
 * answer as UNAVAILABLE (its fail-closed word).
 *
 * A bound is MANDATORY rather than optional because of where this call sits: on the hot path of every
 * governed tool call, and — on the durable resume leg — after the checkpoint has been consumed and the
 * start frame emitted. A provider that never settles would otherwise wedge the call past any task
 * deadline (tasks carry no walltime by default), leaving the frame unpaired and the approval spent with
 * nothing retryable. A hang is the one outcome worse than either verdict.
 *
 * The value matches the auto-mode classifier's per-round-trip cap — the other model/network call the
 * permission path makes — because the reasoning is the same: a governance lookup that takes longer than
 * this is indistinguishable from an outage, and an outage is exactly what the unavailable arm is for.
 * The task's own abort signal still applies in parallel; whichever fires first ends the wait.
 */
export declare const ORG_ADJUDICATION_TIMEOUT_MS = 15000;
/**
 * Await `p`, but settle with `fallback` if the deadline elapses or the signal fires first.
 *
 * Shared by both org consumption sites so one bound cannot drift into two. Deliberately NOT `.unref()`
 * on the timer: this is a foreground rescue timer, and the caller is awaiting it inside the control
 * flow — an unref'd timer stops firing in exactly the situation it exists for (an otherwise idle loop).
 * A rejecting `p` also lands on the fallback: the callers' fail-closed word is the same either way, and
 * an escaping rejection here would turn a dependency failure into a task crash.
 */
export declare function settleOrgVerdictWithin<T>(p: Promise<T>, fallback: T, opts: {
    signal?: AbortSignal;
    timeoutMs: number;
    /**
     * backlog #136④ — which arm WON, reported at the moment it won. A consumer that wants to tell a
     * cancelled wait from an unreadable provider cannot get that by sampling `signal.aborted` after
     * the await: a cancellation queued between the settlement and the continuation reads identically
     * to one that actually ended the wait, and the operator-facing account would name the wrong
     * cause. Called at most once, before `p` resolves, and only for the two non-provider arms —
     * absent call ⇒ the awaited promise itself settled.
     */
    onFallback?: (cause: "aborted" | "timeout") => void;
}): Promise<T>;
/** The `decisionReason` of a decision an ORG RULE produced (a deny, or a non-dismissable ask). Same
 *  single-spelling contract as {@link ORG_UNAVAILABLE_DECISION_REASON}. */
export declare const ORG_RULE_DECISION_REASON: Extract<import("./tool-policy.js").DecisionReason, "org_rule">;
/** How far into the future a snapshot's `fetchedAtMs` may sit before it is refused — ordinary NTP-level
 *  clock skew passes; a far-future timestamp (which would satisfy the staleness bound INDEFINITELY,
 *  turning fail-closed into evergreen freshness) does not. */
export declare const ORG_FETCHED_AT_SKEW_ALLOWANCE_MS: number;
/** The org partition's resolution word. `ungoverned` is the store's answer on a deployment that
 *  configured no org partition — a fourth member so "no org layer here" is never spelled as an
 *  empty `fresh` snapshot. */
export type OrgRuleStatus = "fresh" | "last-known-good" | "unavailable" | "ungoverned";
/** What one resolution reports. `rules` is empty ⟺ status `unavailable`/`ungoverned` or the snapshot
 *  is empty — the cases are distinguished by `status`, never by the emptiness of the list. */
export interface OrgRuleResolution {
    source: "org";
    status: OrgRuleStatus;
    rules: OrgPermissionRule[];
    revision?: number;
    /** Honest-disclosure lines: source failures, refused snapshots, rollback refusals. */
    disclosures: string[];
}
/** The org partition engine the unified store composes (design/389): fetch → validate → install-if-newer
 *  → judge freshness, one serialized chain per deployment. */
export interface OrgRulePartition {
    resolve(): Promise<OrgRuleResolution>;
}
/** The partition config a deployment hands to `createPermissionRuleStoreProvider({ org })`. Its
 *  PRESENCE is the governance declaration. */
export interface OrgRulePartitionConfig {
    /** Where the deployment fetches the current snapshot. Required — a governed declaration without a
     *  source is a configuration contradiction and refuses to boot. */
    source: OrgRuleSnapshotProvider;
    /** Durable LKG + high-water home. Omitted ⇒ process-local only, DISCLOSED on every resolution: a
     *  restart then forgets both the last-known-good snapshot and the anti-rollback mark. */
    persistence?: OrgRuleStatePersistence;
    stalenessBoundMs: number;
    now?: () => number;
}
/** The ungoverned resolution — what a store with no org partition answers. */
export declare const UNGOVERNED_ORG_RESOLUTION: Readonly<OrgRuleResolution>;
/**
 * Construct the org partition engine for a GOVERNED deployment. This constructor IS the boot gate:
 *  - a declaration WITHOUT a snapshot source is a configuration contradiction and refuses to boot —
 *    a silently ungoverned "governed" deployment is precisely the failure this bit exists to prevent
 *    (the type requires `source`; the check is executed for a JavaScript caller);
 *  - `stalenessBoundMs` follows the knob discipline: a non-number, NaN, non-finite or non-positive
 *    bound is refused loudly, never coerced.
 */
export declare function createOrgRulePartition(cfg: OrgRulePartitionConfig): OrgRulePartition;
/**
 * Which entries of an org snapshot the CURRENT rule validator refuses — the published deny/ask rules
 * that can match nothing on this build. Empty ⟺ every rule is enforceable.
 *
 * Separate from {@link validateOrgSnapshot} because BOTH gates need it: the install gate (a fetched
 * snapshot) and the serving gate (backlog #177 — a snapshot persisted by an earlier build is read back
 * and served without ever having met this validator). It reports every offender rather than the first,
 * since a refusal an administrator cannot act on names no line to fix.
 */
export declare function unenforceableOrgRules(rules: readonly OrgPermissionRule[]): Array<{
    rule: string;
    code: RuleRejectCode;
}>;
/**
 * design/182 §7.2 — which org rule speaks for this command, if any. Deny outranks ask; within a
 * behavior the first textual match wins (reporting order only — all denies are the same one answer).
 * Matching uses the SAME parser and the SAME tightening reach the personal deny/ask rows use
 * ({@link programRunReachOf}: an interpreter-headed prefix deny like `Bash(node:*)` is a
 * legitimately wide tightening and matches; a segment hit is a hit; a call the lexer cannot read
 * against a rule is an ASK with the reason — fail closed, never silence).
 *
 * The skip below is a defensive floor, and what stands behind it is worth stating precisely: rules that
 * arrive from the org partition's `resolve` ({@link createOrgRulePartition}) have passed {@link validateOrgSnapshot} on BOTH the install
 * and the serving path (backlog #177), so an unenforceable entry cannot reach here through the overlay
 * — the whole snapshot is refused, or the resolution reports `unavailable`, and either way it is
 * disclosed. A caller that hands this function a snapshot it obtained ELSEWHERE gets no such guarantee:
 * the skip is silent, and naming the dead entries is that caller's job — {@link unenforceableOrgRules}
 * is the shared way to do it.
 */
export declare function orgRuleVerdictFor(rules: readonly OrgPermissionRule[], call: {
    tool: string;
    command: string;
}): OrgRuleVerdict | undefined;
/** The org layer's answer for one call: which rule spoke, with what behavior — and, when the call could
 *  not be READ against the org's rules, the lexer's reason beside the first rule it could not judge
 *  (`behavior` is then `ask`: the org published a rule that may reach this call, and nobody can say). */
export interface OrgRuleVerdict {
    readonly behavior: "deny" | "ask";
    readonly rule: string;
    readonly unreadable?: string;
}
/**
 * design/182 §7.3 / design/389 — the SHADOW predicate the unified store's read face applies to every
 * personal allow row: does an org DENY reach this rule's own command pattern? An org deny does not
 * delete a personal rule — the personal rule is the user's approval record, and the org's power is to
 * OVERRIDE it, not to self-declare its removal — so a shadowed rule reports `shadowed-by-org` and comes
 * back by itself when the org deny is withdrawn.
 *
 * The SAME reach the gate uses ({@link ruleReachesProgramRun}), so the view and the decision cannot
 * disagree about whether a deny touches this rule at all. A personal rule may name a connector chain, and a deny on one
 * of its segments shadows it exactly as a deny on the whole does.
 *
 * WHAT `shadowed-by-org` DOES AND DOES NOT CLAIM: the predicate asks whether the deny reaches the
 * personal rule's own command PATTERN — one exemplar — not whether it covers every call that pattern
 * admits. The two differ for a PREFIX personal rule under a narrower deny: `Bash(git status:*)` with an
 * org deny of exactly `Bash(git status)` reports shadowed, yet `git status --short` is still admitted at
 * the gate. The inverse partial overlap (personal `Bash(git:*)`, org deny `Bash(git status:*)`) reports
 * live while part of its reach is denied. A truthful answer needs pattern CONTAINMENT and a third status
 * for partial overlap, which is an API change with its own design; what the two-value view is honest
 * about today is "this rule is touched by a deny" / "no deny mentions it". The gate is the authority
 * either way. org ASK rules do not shadow: the personal lane never consumes a `requiresRealApproval`
 * ask, so the two never actually meet on one call.
 *
 * design/382 §2.6 — a Read directory rule is never org-shadowed in this version: the org layer has no
 * Read grammar (a snapshot carrying one refuses whole at the validator), so there is no deny that could
 * reach it, and its `command` is a PATH that must not be fed to the shell lane's segment reader as
 * though it were a command line.
 */
export declare function orgRuleShadows(orgRules: readonly OrgPermissionRule[], rule: Pick<PersistedRule, "tool" | "command">): boolean;
/** The shadow predicate with the org denies parsed ONCE — what a read over many rows uses. */
export declare function compileOrgShadowPredicate(orgRules: readonly OrgPermissionRule[]): (rule: Pick<PersistedRule, "tool" | "command">) => boolean;
/** Does this store carry a write face? Re-exported convenience for org-ticket integrations that need to
 *  distinguish a read-only projection from a writable personal bucket without importing the writer seam. */
export declare function isWritablePermissionRuleStore(store: PermissionRuleStore): boolean;
