/** * Typed TS client for the BYOK admin REST surface exposed by * `app.MapRichTextBoxAiKeyVaultAdmin()` on the ASP.NET Core * `RichTextBox.AspNetCore` package. * * Tenant-settings UIs (e.g. an admin dashboard where customers paste their * OpenAI / Anthropic / Azure OpenAI key) call into this client instead of * hand-rolling fetch + JSON. The endpoints are off by default on the * server; the host explicitly maps them and wraps in their own auth * middleware. * * @example * ```ts * import { createAdminClient } from "@richscripts/richtexteditor/admin"; * * const admin = createAdminClient({ * baseUrl: "/richtextbox/ai/vault/keys", * fetch: (url, init) => fetch(url, { * ...init, * headers: { ...init?.headers, "Authorization": "Bearer " + adminJwt }, * }), * }); * * await admin.upsert({ tenantId: "acme", provider: "OpenAI", apiKey: "sk-..." }); * const keys = await admin.list("acme"); * await admin.delete(keys[0].keyId); * ``` */ export type AiKeyVaultProvider = "OpenAI" | "Anthropic" | "AzureOpenAI" | string; export interface AiKeyVaultEntry { keyId: string; tenantId: string; provider: AiKeyVaultProvider; createdUtc: string; lastRotatedUtc?: string; azureEndpoint?: string; azureDeploymentName?: string; azureApiVersion?: string; } export interface AiKeyVaultUpsertRequest { tenantId: string; provider: AiKeyVaultProvider; apiKey: string; keyId?: string; azureEndpoint?: string; azureDeploymentName?: string; azureApiVersion?: string; } export interface AiKeyVaultAdminClientOptions { /** * Base URL the admin endpoints are mapped at on the server. Default * `"/richtextbox/ai/vault/keys"` matches the server-side default. */ baseUrl?: string; /** * Custom fetch impl. Use this to inject auth headers, retry policies, * or a polyfilled fetch in older runtimes. Defaults to `globalThis.fetch`. */ fetch?: typeof fetch; } export interface AiKeyVaultAdminClient { /** * Create or rotate a key. Returns the stored entry's metadata; the * `apiKey` field is never echoed back in the response. */ upsert(request: AiKeyVaultUpsertRequest): Promise; /** * List keys for a tenant. Pass `undefined` to list across tenants * (admin views). */ list(tenantId?: string): Promise; /** * Revoke a key by id. Resolves to `true` when a key was removed, * `false` when the id was unknown (idempotent). */ delete(keyId: string): Promise; } /** * Build an admin client configured for one server. Multiple clients with * different `baseUrl` / auth headers can coexist (e.g. one per tenant). */ export function createAdminClient(options?: AiKeyVaultAdminClientOptions): AiKeyVaultAdminClient; export class AiKeyVaultAdminError extends Error { /** * HTTP status code returned by the server. `0` for network failures. */ status: number; /** * Body of the error response, if any. Usually `{ error: "..." }`. */ body?: unknown; constructor(message: string, status: number, body?: unknown); }