/** * The one seam both authentication choices go through. * * WHY AN INTERFACE. "Paste a key" and "sign in with PKCE" differ only in how a credential is * ACQUIRED. Everything after that -- the Bearer header, the base URL, model discovery, the 401 * recovery path -- is identical, and it has to stay identical or the two paths drift. So acquisition * is two adapters behind this interface and nothing downstream can tell which one produced the key: * * ApiKeyCredentialAdapter user pastes an sk-orca-… key * PkceCredentialAdapter browser consent issues one * * `CredentialResult` carries no `source`-dependent behaviour, which is asserted by test rather than * left as a convention -- a provider request built from an API-key result and one built from a PKCE * result are byte-identical. * * THE DASHBOARD IS A SEPARATE PROCESS FROM THE PROVIDER CALLS, and it is a browser. So the adapter * that runs in the dashboard never holds a key: it posts the secret to the loopback server, which * owns the store, and reads back a redacted status. `BrowserCredentialClient` below is that half. */ import { type OrcaCredentialSource, type ResolvedOrcaCredential } from './credential-store.js'; /** What both adapters produce. Nothing downstream may branch on `source`. */ export interface CredentialResult { readonly key: string; readonly source: OrcaCredentialSource; readonly accountId: string; readonly generation: number; readonly scope: string | null; } export declare function toCredentialResult(credential: ResolvedOrcaCredential): CredentialResult; export interface CredentialAdapter { readonly id: 'orcarouter' | 'orcarouter-oauth'; readonly source: OrcaCredentialSource; /** The label a user sees. Distinct per adapter, everywhere both can appear. */ readonly label: string; /** Is a usable credential currently held for this adapter? */ status(env?: NodeJS.ProcessEnv): Promise; /** Discard this adapter's stored credential. */ clear(env?: NodeJS.ProcessEnv): Promise; } export interface CredentialStatus { readonly configured: boolean; readonly masked: string; readonly accountId: string | null; readonly scope: string | null; readonly needsReauth: boolean; readonly reauthReason: string | null; readonly source: OrcaCredentialSource | null; /** True when this adapter's credential is the one inference would actually use. */ readonly active: boolean; /** Where a user goes to manage or revoke the key this app holds. */ readonly dashboardUrl: string; } export declare const ORCA_KEY_DASHBOARD_URL = "https://www.orcarouter.ai/console/authorized-apps"; export declare class CredentialInputError extends Error { constructor(message: string); } /** * Adapter one: a key the user already has. * * This path is never removed in favour of PKCE. A user who already holds a key, or who is working on * a machine where a browser flow is not appropriate, must keep a working route to inference. */ export declare class ApiKeyCredentialAdapter implements CredentialAdapter { readonly id: "orcarouter"; readonly source: "api-key"; readonly label = "OrcaRouter - API"; /** * Store a pasted key. * * The shape check is a typo catcher, not validation: an `sk-orca-` prefix proves nothing about * whether the credential is live, and this package has no non-billing endpoint to check it * against. Validity is established by the first real request. */ save(rawKey: string, env?: NodeJS.ProcessEnv): Promise; status(env?: NodeJS.ProcessEnv): Promise; clear(env?: NodeJS.ProcessEnv): Promise; } /** * Adapter two: consent in a browser, exchanged for a key. * * The exchange itself lives in `connect.ts` because it needs a listener and a lifecycle; this class * is the store-facing half, so both adapters present the same three operations. */ export declare class PkceCredentialAdapter implements CredentialAdapter { readonly id: "orcarouter-oauth"; readonly source: "oauth-pkce"; readonly label = "OrcaRouter - Auth"; /** * Persist the key the exchange returned. * * A PKCE-issued key is durable, not refreshable: it is stored exactly like a pasted one and reused * until OrcaRouter revokes it. Re-authorizing on every launch would hit the account's * 10-keys-per-24-hours cap and lock the user out, which is why nothing here is called at startup. */ save(key: string, options: { accountId: string; scope: string | null; }, env?: NodeJS.ProcessEnv): Promise; status(env?: NodeJS.ProcessEnv): Promise; clear(env?: NodeJS.ProcessEnv): Promise; } export declare const apiKeyAdapter: ApiKeyCredentialAdapter; export declare const pkceAdapter: PkceCredentialAdapter; export declare const CREDENTIAL_ADAPTERS: readonly CredentialAdapter[]; /** * Resolve the credential inference will use, from whichever adapter holds one. * * This is the function a provider request calls. It takes no adapter argument on purpose: a caller * that could name an adapter could branch on the answer, and the whole point of the seam is that the * request path cannot tell the difference. */ export declare function credentialForInference(env?: NodeJS.ProcessEnv): Promise; /** * Record that the relay rejected a request with 401. * * Delegates to the generation-scoped transition, so a late failure from a request issued before the * user reauthorized cannot mark the new credential as broken. */ export declare function recordRejection(credential: CredentialResult, env?: NodeJS.ProcessEnv): Promise<'marked' | 'stale-generation' | 'unknown-account' | 'ephemeral'>; //# sourceMappingURL=credentials.d.ts.map