/** * The saved-key inventory behind Settings › API keys: every stored row the * credential resolver can use for the caller, with what uses it and what the * caller may do with it. Values are never read into the result; `masked` * carries only the last four characters. */ import { type AgentProviderId } from "../client/agent-provider-catalog.js"; import { type SecretManagedBy, type SecretScope, type SecretUsage } from "./register.js"; /** Whose key a row is: the caller's own, or the organization's. */ export type ApiKeyOwnerScope = "user" | "org"; export interface ApiKeyEntry { /** Stored key name, e.g. `OPENAI_API_KEY` or an ad-hoc `STRIPE_SECRET_KEY`. */ name: string; /** Registered label, e.g. "OpenAI API key". Absent for ad-hoc keys. */ label?: string; scope: ApiKeyOwnerScope; /** * The stored row's own scope. A `workspace` row is the organization's * shared row (owner `org`) or, for owner `user`, the caller's solo row. */ storedScope: SecretScope; /** "••••1234". Absent on managed keys, which only say they exist. */ masked?: string; updatedAt: number | null; /** Synced from the Dispatch Vault and managed there. */ vault?: true; registered: boolean; docsUrl?: string; /** The model provider this key (or endpoint) adds. Manage it in Model. */ provider?: AgentProviderId; /** What uses the key, per app and feature. Empty when nothing is known to. */ usedFor: SecretUsage[]; /** Present when another Settings page creates and rotates the key. */ managedBy?: SecretManagedBy; /** Saving a new value writes this same row. */ canReplace: boolean; canDelete: boolean; /** A registered validator can check the stored value. */ canTest: boolean; } export interface AddableApiKey { name: string; label: string; description?: string; docsUrl?: string; /** Where a save lands: `user` for the caller, otherwise shared. */ scope: SecretScope; } export interface ApiKeysListing { /** The caller's keys, then (owners and admins) the organization's. */ keys: ApiKeyEntry[]; /** Keys another Settings page owns, read-only here. */ managed: ApiKeyEntry[]; /** Registered keys nobody has saved yet that the caller may add. */ addable: AddableApiKey[]; hasOrganization: boolean; /** Owner or admin: sees and manages the organization's keys. */ canManageOrg: boolean; } export interface ApiKeyCaller { email: string; orgId: string | null; } /** The row id an owner scope and stored scope name for this caller. */ export declare function apiKeyRowScopeId(caller: ApiKeyCaller, owner: ApiKeyOwnerScope, storedScope: SecretScope): string | null; /** * Every saved key the caller can use. Members get their own keys plus the * names of managed organization keys (never their masks); owners and admins * also get the organization's keys. */ export declare function listApiKeys(caller: ApiKeyCaller): Promise; export type DeleteApiKeyRefusal = { status: "not-found"; } | { status: "forbidden"; error: string; } | { status: "managed"; managedBy: SecretManagedBy; } | { status: "vault"; }; export type DeleteApiKeyResult = { status: "deleted"; removed: string[]; } | DeleteApiKeyRefusal; /** * Delete one saved key row. A provider key also takes its endpoint and older * key names at the same row, so the provider stops rather than half-working. */ export declare function deleteApiKey(caller: ApiKeyCaller, input: { name: string; scope: ApiKeyOwnerScope; storedScope?: SecretScope; }): Promise;