/**
 * Thin tRPC client for the public catalog BFF (`bff.extenshi.io`).
 *
 * The BFF tRPC server is configured WITHOUT a data transformer (no superjson),
 * so this client must match — plain JSON over the wire. We type the proxy as
 * `any` on purpose: catalog-api emits no `.d.ts`, so the BFF↔API type chain
 * can't be imported reliably across a published-package boundary. The runtime
 * proxy builds the procedure path from property access regardless of types.
 *
 * Every call carries `Authorization: Bearer <ek_…>`. Today the BFF read
 * procedures are anonymous, but they are moving to mandatory key-enforcement
 * (no anonymous data access) — sending the key now is forward-compatible and
 * needs no client change when enforcement lands.
 */
import { type PayBff } from './pay.js';
/** One credit pool as reported by `getApiCallerBalance`. */
export interface CreditPool {
    /** Total calls this pool can still fund (free grant + purchased) — the single number that gates a call. */
    remaining: number;
    /** The slice of `remaining` still coming from the one-time signup grant (always ≤ remaining). */
    freeRemaining: number;
    freeGranted: number;
    freeUsed: number;
}
/** Read/scan/icon/inventory balances for the `ek_` key or remote-MCP identity. */
export interface ApiCallerBalance {
    read: CreditPool;
    scan: CreditPool;
    icon: CreditPool;
    inventory: CreditPool;
    billingUrl: string;
}
/** A resolved store→catalog reference (`resolveExtensionRef`). */
export interface ExtensionRef {
    id: number;
    store: 'CHROME' | 'FIREFOX' | 'EDGE';
}
export interface Bff extends PayBff {
    /**
     * Create a project owned by this identity — the same service as the Dojo
     * wizard. Idempotent per `idempotencyKey`. Requires project.write.
     */
    createProject(input: import('@extenshi/contracts').AgentCreateProject): Promise<unknown>;
    /** Owner decisions with status, suggested defaults and what each blocks. */
    getDecisions(input: {
        projectId: string;
    }): Promise<unknown>;
    /** Record a PROPOSAL; only the owner decides, in Dojo. Requires project.write. */
    proposeDecision(input: import('@extenshi/contracts').ProposeDecision): Promise<unknown>;
    importManifest(input: import('@extenshi/contracts').ManifestImport): Promise<unknown>;
    getProjectWorkspace(input: {
        projectId: string;
    }): Promise<unknown>;
    diffProjectWorkspace(input: import('@extenshi/contracts').WorkspacePatch): Promise<unknown>;
    patchProjectWorkspace(input: import('@extenshi/contracts').WorkspacePatch): Promise<unknown>;
    recordProjectEvidence(input: Omit<import('@extenshi/contracts').Evidence, 'id' | 'recordedAt'>): Promise<unknown>;
    getReleaseReadiness(input: {
        projectId: string;
        browser?: 'chrome' | 'firefox' | 'edge';
        artifactDigest?: string;
    }): Promise<unknown>;
    connectionDiagnostics(): Promise<unknown>;
    searchExtensions(input: Record<string, unknown>): Promise<unknown>;
    getExtensionById(id: number): Promise<unknown>;
    /** Paginated store user reviews for an extension (PII-free projection). */
    getReviews(input: Record<string, unknown>): Promise<unknown>;
    getSecurityData(extensionId: number): Promise<unknown>;
    getRiskSummary(extensionId: number): Promise<unknown>;
    getSearchFacets(input: Record<string, unknown>): Promise<unknown>;
    getStats(): Promise<unknown>;
    /** Catalog-wide extended facets (manifest / permissions / risk / freshness …), cached server-side. */
    getExtendedFilterFacets(): Promise<unknown>;
    /** Catalog-wide category tree with per-category counts. */
    getCategoryTree(): Promise<unknown>;
    /** This caller's credit balances across all pools. FREE — never spends a read credit. */
    getApiCallerBalance(): Promise<ApiCallerBalance>;
    /**
     * Resolve a public STORE extension id (from the store URL) to the numeric
     * catalog id the read tools take. FREE — the read that follows is what's
     * metered. Returns null when no catalog listing exists for it yet.
     */
    resolveExtensionRef(input: {
        storeId: string;
        store?: 'CHROME' | 'FIREFOX' | 'EDGE';
    }): Promise<ExtensionRef | null>;
    /**
     * Risk for MANY extensions addressed by store id, in ONE metered read.
     * Cluster-resolved server-side, so each row describes the same listing the
     * extension page renders. Capped at 40 extensions per call for metered
     * callers — the BFF rejects a larger batch with a message naming the limit.
     */
    getSecuritySummaryBatch(input: {
        extensions: Array<{
            storeId: string;
            store: 'CHROME' | 'FIREFOX' | 'EDGE';
        }>;
    }): Promise<unknown>;
    /**
     * The caller's OWN extension projects. FREE — credits pay for catalog data
     * about other people's extensions, never for reading your own work.
     */
    listMyProjects(): Promise<unknown>;
    /**
     * One own project as state an agent can act on: chosen extension types, the
     * manifest.json that project produces per browser, live hosted URLs, and an
     * index of saved tool state. FREE, same reasoning. `includeToolStates` inlines
     * named payloads; without it the response lists what exists and how big.
     */
    getMyProjectState(input: {
        projectId: string;
        includeToolStates?: string[];
    }): Promise<unknown>;
    /**
     * The starter extension one own project produces, as files — the same set the
     * site commits and packs into its download. FREE, same reasoning. One browser
     * per call: the manifests differ between them and the rest does not.
     */
    getMyProjectScaffold(input: {
        projectId: string;
        browser?: string;
    }): Promise<unknown>;
    listPrivacyPolicyVersions(input: {
        projectId: string;
    }): Promise<unknown>;
    getPrivacyPolicyVersion(input: {
        projectId: string;
        versionNumber: number;
    }): Promise<unknown>;
    publishPrivacyPolicy(input: {
        projectId: string;
        bodyMarkdown?: string;
        kind?: string;
    }): Promise<unknown>;
    updatePrivacyPolicyWithAi(input: {
        projectId: string;
    }): Promise<unknown>;
    /**
     * Create (or ROTATE) the per-project CI evidence ingest secret. The
     * plaintext is shown once and belongs in the repository's Actions secrets.
     */
    createCiIngestSecret(input: {
        projectId: string;
    }): Promise<unknown>;
    revokeCiIngestSecret(input: {
        projectId: string;
    }): Promise<unknown>;
    /** Register a project's homepage/support URL (HTTPS, reachable, hashed). */
    upsertHostedPage(input: {
        projectId: string;
        kind: string;
        url: string;
    }): Promise<unknown>;
    /** Re-fetch and compare: verified | changed | unreachable per kind. */
    verifyHostedArtifact(input: {
        projectId: string;
        kind: string;
    }): Promise<unknown>;
    /** Forget a registration (a project moving off a URL needs a real delete). */
    removeHostedPage(input: {
        projectId: string;
        kind: string;
    }): Promise<unknown>;
    listHostedPages(input: {
        projectId: string;
    }): Promise<unknown>;
    /** Publish (create or update) the project's landing page on page.extenshi.io. */
    publishLandingPage(input: {
        projectId: string;
        form: Record<string, unknown>;
        registerAsHomepage?: boolean;
    }): Promise<unknown>;
    getLandingPage(input: {
        projectId: string;
    }): Promise<unknown>;
    unpublishLandingPage(input: {
        projectId: string;
    }): Promise<unknown>;
    /** Schema-v2 homepage drafted from project state: {form, sources, todos, problems, previewUrl}. Writes nothing. */
    draftLandingPage(input: {
        projectId: string;
        storeUrls?: {
            chrome?: string;
            firefox?: string;
            edge?: string;
        };
    }): Promise<unknown>;
    /** Render exactly as publish would (validation, Pay offers, canonical) without writing. */
    previewLandingPage(input: {
        projectId: string;
        form: Record<string, unknown>;
        locale?: string;
    }): Promise<unknown>;
    listLandingVersions(input: {
        projectId: string;
    }): Promise<unknown>;
    /** Publish an earlier version's form as a new version. */
    rollbackLandingPage(input: {
        projectId: string;
        versionNumber: number;
        registerAsHomepage?: boolean;
    }): Promise<unknown>;
    /** Custom domain: records to set, verification state, next step. */
    getCustomDomain(input: {
        projectId: string;
    }): Promise<unknown>;
    setCustomDomain(input: {
        projectId: string;
        hostname: string;
    }): Promise<unknown>;
    verifyCustomDomain(input: {
        projectId: string;
    }): Promise<unknown>;
    removeCustomDomain(input: {
        projectId: string;
    }): Promise<unknown>;
    /** The hosted install instructions page (it. 10 T8): state, URL and the saved form. */
    getInstructionsPage(input: {
        projectId: string;
    }): Promise<unknown>;
    /** Publish the install instructions (the saved form when `input` is omitted). */
    publishInstructions(input: {
        projectId: string;
        input?: Record<string, unknown>;
    }): Promise<unknown>;
    setInstructionsEnabled(input: {
        projectId: string;
        enabled: boolean;
    }): Promise<unknown>;
    /** Every uninstall form and welcome page of the project: translatable fields and per-language status. */
    getPageTranslations(input: {
        projectId: string;
    }): Promise<unknown>;
    /** Save one language of one page (text by field path; the server records the source text). */
    setPageTranslations(input: {
        projectId: string;
        surface: 'uninstall' | 'welcome' | 'instructions';
        publicCode: string;
        locale: string;
        translations: Record<string, string>;
    }): Promise<unknown>;
    /**
     * Translated copies of the hosted privacy policy / license terms (it. 13 T10
     * L3): what the developer can translate (edited sections, own answers),
     * languages, status per language and the translation URLs. The English
     * version stays the binding text.
     */
    getPrivacyPolicyTranslations(input: {
        projectId: string;
    }): Promise<unknown>;
    setPrivacyPolicyTranslations(input: {
        projectId: string;
        locale: string;
        translations: Record<string, string>;
        sources?: Record<string, string>;
    }): Promise<unknown>;
    getLicenseTermsTranslations(input: {
        projectId: string;
    }): Promise<unknown>;
    setLicenseTermsTranslations(input: {
        projectId: string;
        locale: string;
        translations: Record<string, string>;
        sources?: Record<string, string>;
    }): Promise<unknown>;
    /**
     * Upload one PNG/JPEG/WebP to the project's PUBLIC media store (the same one
     * Dojo uploads use). The BFF re-checks magic bytes, strips metadata, enforces
     * size/dimension/quota limits and returns a stable content-addressed URL.
     */
    uploadProjectMedia(input: {
        projectId: string;
        mime: 'image/png' | 'image/jpeg' | 'image/webp';
        dataBase64: string;
    }): Promise<unknown>;
}
/** Build a BFF client from a static `ek_…` key (stdio path). */
export declare function makeBff(bffUrl: string, apiKey: string): Bff;
/**
 * Build a BFF client whose Authorization header is produced per request by
 * `authHeader` (may be async). The remote OAuth server uses this to mint a
 * fresh, short-lived genkan JWT for each call instead of holding a static key.
 * The provider returns the FULL header value (e.g. `Bearer eyJ…`).
 */
export declare function makeBffWithAuth(bffUrl: string, authHeader: () => string | Promise<string>): Bff;
//# sourceMappingURL=bff.d.ts.map