/**
 * vault D6 — named addressing resolution + id-pinning (repo-first-onramp
 * task 4.5).
 *
 * Two things live here, both Node-only (local git state):
 *
 *   - PIN read/write: `r402.repoId` (+ `r402.repoAddress`, the human name it
 *     was resolved from) in the repository's LOCAL git config
 *     (`git config --local` — this checkout's own `.git/config`, never
 *     global). "Local git state" per design D6's id-pinning paragraph.
 *   - `resolveVaultAddress`: the orchestrator the remote helper and
 *     `vault snapshot` drive — pinned id first, then dispatch on the
 *     address's form (id vs slug — {@link vaultRemoteAddressForm}), then
 *     (slug-form only, opt-in via `allow_create`) push-to-create on a miss.
 *
 * ID-PINNING RATIONALE (design D6, "resolved"): "on first contact the helper
 * resolves slug/name → repo_id and pins the immutable id in local git state.
 * Names are sugar for humans and first-time clones; every existing checkout
 * follows the id and survives any rename." Concretely: an id-form address
 * (`org_id`/`prj_...`) already survives a rename (project ids never change),
 * so pinning buys it nothing and this module never pins one. A SLUG-form
 * address re-resolves `org-slug/name → repo_id` over the network on every
 * open unless pinned — and a rename of either half would silently break that
 * resolution for an EXISTING checkout the moment it takes effect. Pinning
 * `repo_id` the first time a slug-form address resolves means every later
 * open on this checkout goes straight to `repo_id` (no resolution round-trip,
 * and no exposure to a later rename at all) — structurally better than a
 * redirect, per the design's own framing.
 */
import { type VaultRemoteAddress } from "../namespaces/repos.js";
import type { VaultTransport } from "./vault-publication.js";
import type { VaultCreationResult } from "./vault-creation-journal.js";
import type { VaultKeystore } from "./vault-keystore.js";
export interface VaultPinnedRepo {
    repo_id: string;
    /** `null` if the pin predates this field, or was written by hand. */
    resolved_from: {
        org_slug: string;
        repo_name: string;
    } | null;
    /** `null` on a legacy pin that predates the id-carrying schema (or one written by hand) — resolution then self-upgrades it through one validation read. */
    project_id: string | null;
    /** `null` on a legacy pin — see `project_id`. */
    org_id: string | null;
    /** The coordination room key (`r402.room`) — `null` on a pin written before kygit-handoff. Same value as `project_id` for a project's default room. */
    room: string | null;
}
/** Read this checkout's pinned `repo_id`, or `null` when nothing is pinned. */
export declare function readPinnedVaultRepo(repoDir: string): Promise<VaultPinnedRepo | null>;
/**
 * Pin `repo_id` into this checkout's LOCAL git config — and, when resolved
 * from a slug-form address, the address it was resolved from (diagnostic
 * only). `resolvedFrom` is omitted for an id-form pin (vault-client-
 * round-trips design D4): an id-form address has no org-slug/name pair to
 * record, and — per {@link resolveVaultAddress}'s own doc comment — the
 * design's instruction is that pinning "only resolves names"; id-form is
 * already rename-proof, so this pin exists purely to skip the resolution
 * ROUND TRIP, not to survive a rename.
 */
export declare function pinVaultRepo(repoDir: string, repoId: string, resolvedFrom?: {
    org_slug: string;
    repo_name: string;
}, ids?: {
    project_id: string;
    org_id: string;
    room_key?: string;
}): Promise<void>;
/**
 * add-room-invite design D10: a bare `rooms join <key>` arrival standing
 * inside a git repository pins `r402.orgId`/`r402.room` in this checkout's
 * LOCAL git config — the SAME two keys {@link pinVaultRepo} writes
 * alongside a vault's `r402.repoId` — but WITHOUT one, since a room-only
 * join has no vault to pin. Read back by {@link readPinnedRoomBinding},
 * independent of {@link readPinnedVaultRepo}'s own gate on `r402.repoId`
 * being present (a room-only checkout never sets it, so that reader would
 * otherwise see this pin as absent).
 */
export declare function pinRoomBinding(repoDir: string, ids: {
    org_id: string;
    room_key: string;
}): Promise<void>;
/** Read `r402.orgId`/`r402.room` directly, with NO gate on `r402.repoId` (design D10) — the counterpart read for {@link pinRoomBinding}. Either field is `null` when unset (no repository, or never pinned). */
export declare function readPinnedRoomBinding(repoDir: string): Promise<{
    org_id: string | null;
    room: string | null;
}>;
export interface VaultAddressResolution {
    repo_id: string;
    project_id: string;
    org_id: string;
    form: "id" | "slug";
    /**
     * How this resolution happened: a local git-config pin, the local
     * keystore's own project→repo file (vault-offline-clone-resolve,
     * id-form only — {@link VaultKeystore.findRepoByProject}), a live
     * network resolution, or a fresh push-to-create. `"pin"` and `"keystore"`
     * are BOTH zero-transport-operation answers (see {@link offline}); they
     * are kept distinct only so a caller that cares about provenance can tell
     * them apart — {@link recoverStaleVaultPin}'s generic `offline` check
     * treats them identically.
     */
    via: "pin" | "keystore" | "resolved" | "created";
    /** The `org-slug/name` the address named, when slug-form; `null` for id-form. */
    address: {
        org_slug: string;
        repo_name: string;
    } | null;
    /** Set only when THIS call push-to-created the vault (`via === "created"`); `null` otherwise. */
    created: {
        deduplicated: boolean;
        recovery_receipt: VaultCreationResult["recovery_receipt"];
        genesis_sha256: string;
    } | null;
    /**
     * `true` iff this resolution performed ZERO transport operations (an
     * id-carrying pin). Stale-pin recovery is then the caller's to arm on the
     * verb's first repo-scoped read — see {@link recoverStaleVaultPin}.
     */
    offline: boolean;
}
export interface ResolveVaultAddressOptions {
    keystore: VaultKeystore;
    transport: VaultTransport;
    /** The parsed remote address (`parseVaultRemoteUrl`'s output) — id-form or slug-form, undiscriminated. */
    address: VaultRemoteAddress;
    /** The local working tree, for reading/writing the pin. Omit for a repository-free read (e.g. `git ls-remote`) — pinning is then skipped, never a failure. */
    repo_dir?: string;
    /** Push-to-create on a slug-form miss (D6). `false` (the default) makes a miss an ordinary not-found refusal — the read-only path (`list`/`fetch`, `vault status`). */
    allow_create?: boolean;
    client_creation_id?: string;
    service_public_key?: Uint8Array | string;
    /** Fires once, only when THIS call allocated the vault (mirrors `Repos.capture`'s `onVaultCreated`). */
    onVaultCreated?: (created: NonNullable<VaultAddressResolution["created"]>) => void | Promise<void>;
    /**
     * vault-offline-clone-resolve (design D3): recovery-only. Skips BOTH
     * local answers — the git-config pin AND the id-form keystore consult —
     * forcing a genuine network resolution. Set exclusively by {@link
     * recoverStaleVaultPin}'s internal re-resolve call: a stale local
     * answer (a pin or a keystore file naming a repo that no longer resolves
     * or is no longer ours) must never be allowed to answer the SAME stale
     * fact back to itself, which is what would happen if recovery re-ran the
     * ordinary local-first path. Never set by an ordinary caller.
     */
    bypass_local_answers?: boolean;
}
/**
 * Resolve a parsed remote address to `{repo_id, project_id, org_id}`,
 * pinning `repo_id` in local git state on the first successful resolution —
 * of EITHER form (vault-client-round-trips design D4 widens the
 * pre-existing slug-form pin, task 4.5, to id-form too) — and, when
 * `allow_create` is set and resolution misses, push-to-create it (task
 * 4.4/4.5, design D6). A pinned id that no longer resolves (404) clears the
 * pin and re-resolves ONCE through the ordinary form-dispatch path below,
 * rather than failing on a stale local pointer.
 */
export declare function resolveVaultAddress(options: ResolveVaultAddressOptions): Promise<VaultAddressResolution>;
/**
 * Stale-pin recovery for OFFLINE resolutions (client-surface spec,
 * "Id-form remotes pin repo_id like slug-form remotes"; widened by
 * vault-offline-clone-resolve design D3 to the keystore-sourced offline
 * answer too): a pin or a keystore hit resolves with no network read, so the
 * once-in-a-lifetime stale case (a vault deleted and re-allocated out from
 * under this checkout, or a keystore file left behind by an old allocation)
 * surfaces as the VERB's first repo-scoped read failing instead of a
 * resolution failure.
 *
 * Given that failure, answer the fresh resolution to retry the verb against —
 * or `null` when there is nothing to recover:
 *
 *   - a non-vault-absent error (anything outside the not-found family and the
 *     gateway's authorize-before-reveal `VAULT_ACCESS_DENIED` fold, which
 *     deliberately makes "gone" and "not yours" one envelope) → `null`,
 *     rethrow yours;
 *   - re-resolution yielding the SAME `repo_id` → the local answer was fine
 *     and the refusal is real: the pin is restored (re-resolution re-pins
 *     it) and the answer is `null` — recovery never widens what an
 *     unauthorized caller learns (both probes return the same refusal
 *     family it already saw);
 *   - a DIFFERENT `repo_id` → the fresh resolution, pin already rewritten;
 *     the caller retries the verb exactly once.
 *
 * The re-resolve MUST bypass every local answer (`bypass_local_answers:
 * true`) — a stale keystore file (or, before this change, a stale pin) is
 * exactly the fact recovery exists to get past, so re-running the ordinary
 * local-first path would just consult the SAME stale local answer again and
 * never reach the network. This is why the retry always costs one real
 * transport operation, deliberately outside the counted budgets (D3, D5).
 *
 * Re-resolution failures are swallowed in favor of `null` (the caller's
 * original error is the truthful one to surface).
 */
export declare function recoverStaleVaultPin(options: {
    keystore: VaultKeystore;
    transport: VaultTransport;
    address: VaultRemoteAddress;
    repo_dir: string;
    /** The offline resolution the failing verb ran under. */
    resolution: VaultAddressResolution;
    /** The verb's failure. */
    error: unknown;
}): Promise<VaultAddressResolution | null>;
//# sourceMappingURL=vault-address.d.ts.map