/**
 * BlobInboxClient.ts — minimal Vercel Blob REST client for the feedback inbox.
 *
 * Why hand-rolled instead of `@vercel/blob`: the canonical front (feedback-front/)
 * deploys with NO install step (`installCommand: "true"` in vercel.json) and bundles
 * its function from ../../src at dev time — a runtime dependency would break that
 * zero-install contract. The drainer (server side) shares this same client so the
 * two ends of the inbox speak one protocol with zero drift.
 *
 * Protocol pinned against @vercel/blob 0.27.3 source (dist/chunk-*.js):
 *   - base `https://blob.vercel-storage.com`, headers `authorization: Bearer <token>`
 *     + `x-api-version: 7` (this client speaks the v7-era request shape — pathname in
 *       the URL path, simple PUT body. The live Blob API rejects that shape with
 *       `400 bad_request "Invalid pathname"` once `x-api-version` is declared as 9+
 *       (newer protocol versions expect a different request format). `7` is the
 *       declared version whose wire contract matches the request this client builds;
 *       verified live against PUT/LIST/DELETE. Adopting the @vercel/blob 2.x v12
 *       protocol would be a larger rewrite, tracked as receiver hardening.)
 *   - PUT  /<pathname>            (body = content; `x-content-type`; `x-add-random-suffix: 1`)
 *   - GET  /?prefix=&limit=&cursor=  → { blobs: [{url, pathname, size, uploadedAt}], cursor, hasMore }
 *   - POST /delete                (JSON { urls: [...] })
 *   - blob CONTENT is read by GETting the blob's own `url` (random-suffixed → unguessable).
 *
 * `addRandomSuffix` is deliberately ON for inbox writes: blob URLs are public-but-
 * unguessable, and a predictable `inbox/<feedbackId>.json` pathname would make report
 * bodies enumerable by anyone who learns the store's host. The drainer never needs to
 * predict a pathname — it lists by prefix and reads the returned URLs.
 *
 * Everything is injected (token, base URL, fetch) so unit tests stub the wire and the
 * integration tier runs against a local fake Blob server.
 */
export interface BlobEntry {
    url: string;
    pathname: string;
    size: number;
    uploadedAt: string;
}
export interface BlobListResult {
    blobs: BlobEntry[];
    cursor?: string;
    hasMore: boolean;
}
export interface BlobInboxClientOptions {
    token: string;
    /** Override the API base (tests / fake server). Default: the real Blob API. */
    apiBase?: string;
    fetchImpl?: typeof fetch;
}
export declare class BlobApiError extends Error {
    readonly status: number;
    readonly operation: string;
    constructor(status: number, operation: string, detail: string);
}
export declare class BlobInboxClient {
    private readonly token;
    private readonly apiBase;
    private readonly fetchImpl;
    constructor(opts: BlobInboxClientOptions);
    private headers;
    /** Durably store one inbox object. Returns the blob's (random-suffixed) URL + pathname. */
    put(pathname: string, content: string): Promise<{
        url: string;
        pathname: string;
    }>;
    /** List one page of blobs under a prefix (oldest pagination order is the API's). */
    list(prefix: string, opts?: {
        limit?: number;
        cursor?: string;
    }): Promise<BlobListResult>;
    /** Read a blob's content by its URL (the URL came from put/list — never predicted). */
    fetchContent(url: string): Promise<string>;
    /** Delete blobs by URL. Idempotent server-side (deleting a gone blob is not an error). */
    del(urls: string[]): Promise<void>;
}
//# sourceMappingURL=BlobInboxClient.d.ts.map