/** * Shared FILE_TOMBSTONE fetch used by BOTH the pull planner (`sync.ts`) and the * push planner (`share.ts`). * * A FILE_TOMBSTONE is the authoritative record of an intentional, scoped delete * (`hq files delete ` → `POST /v1/files/delete` → `recordDeletions`). * Both sync legs consult it so a deleted key is neither re-downloaded (pull) nor * re-uploaded (push) and therefore cannot be resurrected by a behind peer. * * Lives in its own module so `share.ts` can use the fetch without importing from * `sync.ts` — `sync.ts` already imports values from `share.ts` * (`isEphemeralPath`, `isMalformedVaultKey`), so the reverse value-import would * create a runtime ESM cycle. */ import type { VaultServiceConfig } from "../types.js"; /** * Per-attempt deadline from request start until the response headers arrive. * A vault can contain hundreds of thousands of tracked objects, so the old * five-second whole request budget was shorter than a healthy API * scan/serialization under normal load. * * This deadline covers only time-to-headers. A tombstone page can be several * megabytes, so the body is bounded separately by an idle timeout (see * `FETCH_TOMBSTONES_BODY_IDLE_TIMEOUT_MS`): a slow link that keeps delivering * bytes must be able to finish a page, while a stalled socket still fails. */ export declare const FETCH_TOMBSTONES_TIMEOUT_MS = 60000; /** * Longest gap allowed between two body chunks of one tombstone page. The timer * resets every time bytes arrive, so total download time is not limited by it. */ export declare const FETCH_TOMBSTONES_BODY_IDLE_TIMEOUT_MS = 60000; /** * Backstop for one page body that keeps trickling bytes but never finishes. * Ten minutes covers a ~3 MB page at ~5 KB/s; anything slower is treated as a * failed attempt so a sync pass cannot hang forever on one request. */ export declare const FETCH_TOMBSTONES_BODY_MAX_MS: number; /** * Extra attempts for vault 429/502/503/504 so a few-second throttle can * clear. Other non-ok statuses and network errors still use * `FETCH_TOMBSTONES_MAX_ATTEMPTS`. */ export declare const FETCH_TOMBSTONES_TRANSIENT_MAX_ATTEMPTS = 5; /** * The planners must not continue without a deletion-authority snapshot. This * error deliberately retains the last transport/status cause so the runner can * classify a temporary network failure and retry the pass on its normal loop. */ export declare class TombstoneFetchError extends Error { readonly attempts: number; constructor(message: string, attempts: number, cause?: unknown); } export type TombstoneTimeoutPhase = "headers" | "body-stalled" | "body-ceiling"; /** * One attempt hit a tombstone deadline. Named `TimeoutError` so the runner's * transient-network classifier (which walks `TombstoneFetchError.cause`) keeps * treating it as a retryable transport failure, the same as the AbortError it * replaces. `phase` tells a headers timeout apart from a stalled body. */ export declare class TombstoneTimeoutError extends Error { readonly phase: TombstoneTimeoutPhase; constructor(phase: TombstoneTimeoutPhase, message: string); } /** * A FILE_TOMBSTONE as the planners need it: the deleted key + when it was * deleted. The `deletedAt` timestamp is the decisive precedence signal on the * pull side — a remote object newer than it is a genuine re-create (sync it), an * object at or older than it is a stale resurrection of a deleted key (suppress * it). */ export interface CompanyTombstone { deletedAt: string; } /** * Selects the vault whose tombstones should be returned. Personal scope is a * server-resolved ownership selector: the client must never pass a `prs_*` UID * through the company selector because that route requires company membership. */ export type TombstoneScope = ({ companyUid: string; } | { personal: true; }) & { prefix?: string; }; /** * Fetch one vault's FILE_TOMBSTONE rows from hq-pro * (GET /v1/files/tombstones) and return them as a POSIX-keyed map the planners * consult to avoid resurrecting an intentionally-deleted object * (delete-resync). The endpoint is ACL-filtered server-side, so the map only * ever contains keys this caller can read — exactly the keys that can appear in * the (STS-scoped) remote LIST. * * This is a deletion-authority read, not an optional optimization. A failed * read must block the affected sync leg: proceeding with an empty map permits * a stale peer to preserve or re-upload a file that was deliberately deleted. * The request therefore gets a volume-appropriate deadline and bounded retries; * exhausted attempts throw so the runner reports an aborted/partial pass. */ export declare function fetchFileTombstones(vaultConfig: VaultServiceConfig, scope: TombstoneScope): Promise>; //# sourceMappingURL=tombstones.d.ts.map