import type { Client } from "../kernel.js"; import { GITVAULT_MIRROR_KEYSTORE_STILL_REQUIRED_STATEMENT, GITVAULT_MIRROR_VALIDITY_NOT_FRESHNESS_STATEMENT } from "../namespaces/gitvault.crypto.js"; import { GitvaultKeystore } from "./gitvault-keystore.js"; import { type GitvaultMirrorBackend } from "./gitvault-mirror-backend.js"; /** * REPO-RELATIVE — the `source//` prefix has already been stripped * (see the module doc's mirror-layout mapping). This is the shape every * OTHER function in this module, `gitvault-recover.ts`, and the mirror * backend interface all consume; nothing here ever sees the raw wire key * except `listGitvaultObjectsAll` itself. * * `size_bytes` is an exact decimal string for EVERY kind, including the two * generation-addressed chain kinds (`head`/`vault_genesis` at generation * zero, `admission_record`) — never `null`. */ export interface GitvaultObjectEntry { key: string; object_kind: string; sha256: string; size_bytes: string; } /** Page through `GET /gitvault/v1/vaults/:vault_id/objects`, collecting every entry, stripped to repo-relative keys. Store-and-echo cursor per D3a — never parsed here either. */ export declare function listGitvaultObjectsAll(client: Client, repoId: string): Promise; /** Read one object's bytes by key, using the same wire identity every stored kind already carries (§3 layout). `null` when the gateway reports the object absent. */ export declare function readGitvaultObjectBytes(client: Client, repoId: string, entry: GitvaultObjectEntry): Promise; /** Exported for the key-shape conformance test (`gitvault-mirror-recover.test.ts`) — never called for its own sake outside this module. */ export declare function generationRouteForKey(key: string): { route: "heads" | "admissions"; generation: string; } | null; /** * `key_envelope` is path-addressed by `(epoch, recipient_fingerprint)`, not a * plain object_id — every other kind uses its object_id, read straight from * the key's own filename via an ANCHORED, kind-specific pattern (never a * loose, unanchored fallback — see {@link NON_GENERATION_KEY_SPECS}). * Exported for the key-shape conformance test. */ export declare function objectReadRequestForEntry(entry: GitvaultObjectEntry): { object_kind: string; object_id?: string; epoch?: string; recipient_fingerprint?: string; }; export interface GitvaultMirrorWritePlan { /** Every non-head, non-admission entry, in listing order — write these FIRST, in any order among themselves. */ objects: GitvaultObjectEntry[]; /** Then admission records and heads, interleaved, strictly ascending by generation (admission before its own head). */ admissionsAndHeads: GitvaultObjectEntry[]; } /** Sort a flat listing into the admission-order write plan (module doc above). */ export declare function planMirrorWrite(entries: readonly GitvaultObjectEntry[]): GitvaultMirrorWritePlan; export interface GitvaultMirrorCopyResult { key: string; outcome: "copied" | "already_present" | "skipped_foreign_recipient" | "failed"; size_bytes?: string; error?: string; } export interface GitvaultMirrorSyncSummary { repo_id: string; destination: string; /** Faithful counts of what ACTUALLY happened this call — never an estimate (design D3a rider (e)). */ objects_listed: number; objects_copied: number; objects_already_present: number; /** * Task 5.3 follow-up: a `key_envelope` wrapped for a DIFFERENT recipient * than this machine's own identity — EXPECTED, not a problem. The * recipient-only read gate means a mirror can only ever hold envelopes * addressed to the local identity; a multi-recipient vault * (gitvault-human-envelopes) makes this the norm. Never counted toward * `objects_failed`, and never causes `mirror sync` to report anything but * success — named per-key in `skipped_foreign_recipient_keys` so a reader * can tell "expected skip" from "silent gap" without cross-referencing. */ objects_skipped_foreign_recipient: number; skipped_foreign_recipient_keys: string[]; objects_failed: number; bytes_copied: string; errors: Array<{ key: string; error: string; }>; validity_not_freshness: typeof GITVAULT_MIRROR_VALIDITY_NOT_FRESHNESS_STATEMENT; keystore_still_required: typeof GITVAULT_MIRROR_KEYSTORE_STILL_REQUIRED_STATEMENT; } export interface GitvaultMirrorSyncOptions { keystore?: GitvaultKeystore; /** Test/advanced hook: an already-opened backend, bypassing config resolution. */ backend?: GitvaultMirrorBackend; } /** * `run402 gitvault mirror sync` (task 2.3): list the vault's stored objects, * diff against the mirror by key+size, fetch and hash-verify what's missing, * write it in admission order. Resumable and idempotent — running it twice in * a row with nothing new copies nothing the second time. */ export declare function mirrorSync(client: Client, repoId: string, options?: GitvaultMirrorSyncOptions): Promise; export interface GitvaultMirrorPushResult { attempted: boolean; outcome: "pushed" | "skipped_no_mirror" | "failed"; summary?: GitvaultMirrorSyncSummary; error?: string; } /** * Fires after an ordinary vault push/deploy produces a new generation. NEVER * throws and NEVER alters the caller's deploy/push outcome (design D6) — a * mirror is strictly extra durability, and its failure is reported BESIDE the * vault result as a distinct line, not folded into it. Fires only when a * mirror is configured for this vault; a vault with no mirror gets * `skipped_no_mirror` (not an error) so callers can log it uniformly without * branching on whether mirroring was ever opted into. * * Implemented as a full (but INCREMENTAL, idempotent) sync rather than a * push-scoped upload: the objects listing + diff-by-size machinery already * makes an all-caught-up sync cheap (one listing page, zero copies), and this * keeps the admission-order write discipline in exactly one place instead of * a second, push-scoped code path that could drift from it. */ export declare function mirrorPushForGeneration(client: Client, repoId: string, options?: GitvaultMirrorSyncOptions): Promise; /** * `run402 repos create --byo`'s every-push dual-write (task 3.3, design * D1): list the vault's stored objects, restrict to the signed CHAIN * (never the payload kinds, which THIS SAME push already wrote directly to * the destination — task 3.2), diff against the destination by key+size, * fetch (from run402 — the chain stays run402-authoritative) and * hash-verify what's missing, write it in admission order. Resumable and * idempotent, reusing the SAME `reconcileOne` copy primitive and * admission-order discipline the opt-in mirror uses — one implementation, * not a second ordering to prove. */ export declare function byoChainCopySync(client: Client, repoId: string, options?: GitvaultMirrorSyncOptions): Promise; /** * Fires after an ordinary vault push produces a new generation, mirroring * {@link mirrorPushForGeneration}'s exact contract (NEVER throws, NEVER * alters the caller's push outcome — the chain-copy is reported BESIDE it). * Gated on a LOCAL BYO write config existing for this repo — a managed * vault (the common case) pays zero extra network calls, `skipped_no_byo`. */ export declare function byoChainCopyPushForGeneration(client: Client, repoId: string, options?: GitvaultMirrorSyncOptions): Promise; export interface GitvaultByoMissingObject { key: string; object_kind: string; } export interface GitvaultByoPresenceReport { repo_id: string; destination: string; checked: number; missing: GitvaultByoMissingObject[]; } /** * Adjudicates the BYO destination against run402's signed chain (task 3.3's * read half, D6): HEAD-checks (cheap, no data transfer) every object the * vault's OWN listing names — payload AND chain alike, since for a BYO * vault the destination is supposed to hold BOTH (payload via task 3.2's * direct write, chain via this file's dual-write above) — against the * destination, by key + size. Never throws on an absence; it REPORTS every * missing object by name so the caller (`repos fsck`) can refuse with * `GITVAULT_BYO_OBJECT_MISSING` naming exactly what the chain says should * exist and does not. */ export declare function verifyByoObjectsPresent(client: Client, repoId: string, options?: GitvaultMirrorSyncOptions): Promise; //# sourceMappingURL=gitvault-mirror.d.ts.map