import type { ReducedBody } from "./hubServer.ts"; /** The local actor key used to authenticate a write to a hub (SSH-style transport auth, * see transportAuth.ts). Optional: omit against a read-public/ungated hub that requires * no transport credential. The same keypair already used to sign objects is reused. */ export interface HubSigner { keyId: string; privateKey: string; } /** * The token a keyless reader may present, from the environment. * * Named after what it is rather than who uses it: any process that can read a private * hub without holding a signing key wants this — a CI job, a short-lived container, a * sandbox. Empty or whitespace means "unset" (that is how an unset shell variable * arrives), and a value carrying a line break is refused outright: it lands in an HTTP * header, and the environment it comes from is not necessarily the caller's own. */ export declare const HUB_TOKEN_ENV = "AVCS_HUB_TOKEN"; /** * Build fetch headers for a hub write. An AVCS-Sig signature is the ONLY credential a * write accepts, and there is deliberately **no token parameter**: the absence is the * enforcement. A parameter that took a token and ignored it would invite a later reader * to "finish" it. * * A token reaches a process through its environment, which is exactly the channel an * ephemeral, less-trusted reader has. Letting it mutate would mean a leaked env var can * push objects, finalize a view, or rewrite policy — none of which a signature-covered * request allows without the actor's key. * * `path` must equal the server's pathname or the signature won't verify. */ export declare function writeAuthHeaders(signer: HubSigner | undefined, method: string, path: string, body: string, scope?: string): Record; /** * Headers for a hub READ (issue #50). * * The reference hub is read-public (D2), so reads went out bare and the omission was * invisible against it. It stops being invisible for an embedder with per-repo access * control, which necessarily gates reads — and the failure there is total rather than * partial, because `pushToHub` opens with GET /have, so a 401 on reads breaks push too. * * Best-effort by design: no signer, no header, and a read-public hub is unaffected. The * signature covers the method, so a captured GET credential cannot be replayed as a write. */ export declare function readAuthHeaders(signer: HubSigner | undefined, path: string, scope?: string, token?: string | undefined, method?: string, body?: string): Record; /** Bound on the exponential backoff for a throttled request. */ export interface RetryOptions { /** Extra attempts after the first, on 429 only. Default 6. */ attempts?: number; /** First backoff step, doubled per attempt. Default 250 ms. */ baseMs?: number; /** Ceiling for a single wait, `Retry-After` included. Default 30 s. */ maxMs?: number; /** Ceiling for the TOTAL time spent waiting on one request. Default 60 s. Without it a hub * answering `Retry-After: 60` to every attempt would stall a push for minutes; with it the * client waits a bounded amount and then reports the throttle. */ budgetMs?: number; } /** Tuning for a push/pull. Every field has a default; callers normally pass nothing. */ export interface TransferOptions { /** Cap on the JSON bytes of one batched push request. Default 4 MiB, lowered to whatever * smaller `batchMaxBytes` the hub advertises. */ maxBatchBytes?: number; /** Cap on how many oids one batched fetch asks for. Default 512. */ maxFetchOids?: number; retry?: RetryOptions; } /** * `GET /reduced` (docs/27 §3.1) — the derived state a replica would compute, read without * replicating. `null` when the server does not serve it (no advertisement, 404/405/501, * unreachable) or the view does not exist: the caller falls back to replicate + reduce, * which is exactly what it did before. Pass the previous `etag` to get `unchanged` (a 304) * instead of a body. The answer is NOT an authority — a replica prefers its own reduce. */ export declare function hubReduced(base: string, view?: string, opts?: { signer?: HubSigner; etag?: string; retry?: RetryOptions; }): Promise<{ status: "ok"; etag: string; body: ReducedBody; } | { status: "unchanged"; etag: string; } | null>; /** * `GET /reduced/blob/:oid` (docs/27 §3.2) — bytes of a synthetic blob named in a `/reduced` * answer's `synth` list. `stale` (412) means the reduction moved since `etag`: re-read * `/reduced`. `null` for a stored blob (use `/objects/:oid`), an unknown view, or a server * without the capability. */ export declare function hubReducedBlob(base: string, view: string, oid: string, opts?: { signer?: HubSigner; etag?: string; retry?: RetryOptions; }): Promise<{ status: "ok"; bytes: Uint8Array; } | { status: "stale"; etag: string; } | null>; export declare function pushToHub(localRepoDir: string, hubUrl: string, signWith?: HubSigner, opts?: TransferOptions): Promise<{ pushed: number; rejected: number; }>; /** * Pull objects the local store lacks: discover what the hub has, then fetch the wanted set * and put it locally (idempotent, content-addressed) — batched via POST /objects/fetch when * the hub advertises it, else the original GET per oid. Returns how many were pulled, * plus the highest Lamport timestamp among the imported operations (0 when none) so * the caller can advance its clock past the imported history (Phase 13.2 * observe-on-import — subsequently issued lamports sort after what was pulled). */ export declare function pullFromHub(localRepoDir: string, hubUrl: string, signWith?: HubSigner, opts?: TransferOptions): Promise<{ pulled: number; maxLamport: number; }>; /** * Submit a draft checkpoint to the hub's integration queue (Phase 14, docs/17 §14.4): * push the local delta, POST /integrate, and on `needs_evidence` pull ONLY the * `missingLocally` oids the hub says are needed to reproduce the integrated tree. * NO retry loop, NO re-proposal, NO redo — the caller's next action is at most "run * validation once against exactly the integrated tree → attach evidence → resubmit the * same ticket". Returns the hub's structured verdict plus the HTTP status. */ export declare function integrateWithHub(localRepoDir: string, hubUrl: string, args: { view: string; checkpoint: string; by: string; ticketId?: string; signWith?: HubSigner; }): Promise<{ status: number; verdict: string; } & Record>; /** * Request a finalize (= PR merge) on the hub (E6): POST /finalize with the view, the new * checkpoint, the parent head being compare-and-swapped, and the finalizer. The hub runs * the authoritative CAS+lock+gates. When `signWith` is given the request is signed so a * gated hub can authenticate the finalizer. Returns the HTTP status + the hub's verdict. */ export declare function finalizeOnHub(hubUrl: string, args: { view: string; newCheckpoint: string; parentHead: string | null; by: string; signWith?: { keyId: string; privateKey: string; }; }): Promise<{ status: number; finalized: boolean; head?: string; reason?: string; }>; //# sourceMappingURL=hubClient.d.ts.map