import type { Clock, GitHubInstallationRepository, InstallationPermissions } from '@cat-factory/kernel';
/**
 * A failed installation-token mint, carrying the HTTP `status` as a STRUCTURED FIELD so the
 * stale-installation reconcile classifies by `instanceof` (via {@link installationTokenMintStatusOf})
 * instead of parsing the message (error-message coverage I7). This is where the mint failure ENTERS
 * the system (the App JWT → `/access_tokens` call is not a `VcsClient` request, so it never routes
 * through `describeVcsApiError`), so the code is attached exactly once here and nothing downstream
 * re-parses it — the first-wrap-point rule (I6).
 *
 * The message is the elaborated {@link explainInstallationTokenMintFailure} text; the reconcile
 * reads the `status` field, so the wording is free to change without affecting classification.
 */
export declare class InstallationTokenMintError extends Error {
    readonly installationId: number;
    readonly status: number;
    constructor(installationId: number, status: number);
}
/**
 * The HTTP status of an installation-token MINT failure, or undefined for any other error. Reads
 * the status ONLY off a real {@link InstallationTokenMintError}, so a repo-level 404 `GitHubApiError`
 * — which also carries a `status` — is NOT mistaken for a gone installation (the reconcile must
 * tombstone only on a mint 404/410, never a single deleted repo). The mint always throws in-process
 * to the reconcile catch, so `instanceof` is authoritative.
 */
export declare function installationTokenMintStatusOf(error: unknown): number | undefined;
/**
 * Turn a failed installation-token mint into an actionable message (error-message coverage C3).
 * The App JWT → `/access_tokens` call is not a `VcsClient` request, so it doesn't route through
 * `describeVcsApiError`; this is the local equivalent for that one endpoint.
 *
 * The wording is purely for humans: the stale-installation reconcile classifies off the structured
 * {@link InstallationTokenMintError} `status` field, not this text, so the cause/remedy prose is
 * free to change. Exported for unit testing, mirroring `explainMigrationFailure`.
 */
export declare function explainInstallationTokenMintFailure(installationId: number, status: number): string;
export interface GitHubAppAuthDependencies {
    appId: string;
    /** App private key in PKCS#8 PEM (`-----BEGIN PRIVATE KEY-----`). */
    privateKeyPem: string;
    installationRepository: GitHubInstallationRepository;
    clock: Clock;
    apiBase: string;
}
export declare class GitHubAppAuth {
    private readonly deps;
    private keyPromise?;
    constructor(deps: GitHubAppAuthDependencies);
    /** A short-lived RS256 JWT authenticating as the App. */
    appJwt(): Promise<string>;
    /**
     * A valid installation access token, minting + caching one if needed. Pass
     * `forceRefresh` to bypass the in-memory cache and mint a fresh token: a token
     * bakes in its repo set + permission scopes at mint time, so one minted before
     * the user granted the App access keeps reporting the old (no-write) grant for up
     * to ~1h. The fresh mint replaces the cached entry, so subsequent calls (and the
     * bootstrap push token, which reads the same cache) pick up the new grant too.
     */
    installationToken(installationId: number, opts?: {
        forceRefresh?: boolean;
        repositoryIds?: number[];
    }): Promise<string>;
    /**
     * The permissions the installation token actually carries (App ∩ what the
     * install approved) — the source of truth for capability checks. Comes free
     * with the mint response and is cached alongside the token, so a warm process
     * answers without a network call. Used by the provisioner to guard privileged
     * actions (e.g. repo creation) before attempting them.
     */
    installationPermissions(installationId: number): Promise<InstallationPermissions>;
    private cachedToken;
    private mintInstallationToken;
    private importKey;
}
//# sourceMappingURL=GitHubAppAuth.d.ts.map