/** * `credentials` namespace — TWO surfaces that must not be confused. * * r.credentials. the GATEWAY's project credentials * r.credentials.projectKeys. the LOCAL key cache on this machine * * A **project credential** (`r402_…`) is a ROW on the gateway: named, listable, * expiring, individually revocable, and several may be live per kind at once — * that overlap IS zero-downtime rotation. It is the replacement for the legacy * `anon_key` / `service_key`, which are DERIVED from the platform signing key, * never expire, and cannot be revoked one at a time. The signing key behind the * legacy pair is being retired. * * These methods existed on the gateway and in the OpenAPI document with no * client at all, so an agent that wanted off the legacy keys had to hand-roll a * SIWX-signed request — which is exactly the "hidden manual step" the project * exists to remove. `r.credentials.status()` is the one to poll; it answers * "am I still on the retiring key" without any privileged role. * * The secret is returned EXACTLY ONCE, from `issue()` / `rotate()` / * `mintToken()`. There is no read that returns it. Never write one of these * responses to a result cache, tmp file, or expansion handle. */ import type { ProjectCredentialCacheInfo, ProjectKeys } from "../credentials.js"; import type { Client } from "../kernel.js"; import type { IssueProjectCredentialInput, ProjectCredentialIssued, ProjectCredentialListResult, ProjectCredentialRevoked, ProjectCredentialStatus, ProjectTokenIssued, ProjectCredentialKind } from "./credentials.types.js"; export interface ProjectKeyCacheStatus extends ProjectCredentialCacheInfo { project_id: string; configured: boolean; has_anon_key: boolean; has_service_key: boolean; anon_key_prefix: string | null; service_key_prefix: string | null; anon_key_fingerprint: string | null; service_key_fingerprint: string | null; site_url: string | null; cached_at: string | null; } export interface ProjectKeyCacheListResult extends ProjectCredentialCacheInfo { projects: ProjectKeyCacheStatus[]; } export interface ProjectKeyCacheExportOptions { /** Required to emit secret key material. */ reveal?: boolean; } export interface ProjectKeyCacheExportResult extends ProjectCredentialCacheInfo, ProjectKeys { project_id: string; revealed: true; } export interface ProjectKeyCacheImportOptions { anonKey?: string; serviceKey: string; siteUrl?: string; } export interface ProjectKeyCacheMutationResult extends ProjectKeyCacheStatus { imported?: boolean; removed?: boolean; } export declare class Credentials { private readonly client; /** The LOCAL key cache on this machine. Not project inventory. */ readonly projectKeys: ProjectKeysCache; constructor(client: Client); /** * Issue a named project credential * (`POST /projects/v1/:project_id/credentials`). * * Requires owner membership on the project's owning org PLUS a fresh * step-up, and a delegate can never satisfy it — a scoped agent credential * must not be able to escalate itself into a permanent root. If you are * running unattended and hold only a delegate, use {@link mintToken}. * * The returned `secret` is shown ONCE. Persist it before doing anything * else; there is no read that returns it, only `rotate()` for a new one. */ issue(projectId: string, input: IssueProjectCredentialInput): Promise; /** * List a project's credentials (`GET /projects/v1/:project_id/credentials`). * Metadata only — never a secret or a secret hash. `project.read` is enough. */ list(projectId: string, opts?: { includeRevoked?: boolean; }): Promise; /** * Rotation posture (`GET /projects/v1/:project_id/credential-status`) — the * surface to poll deliberately, rather than waiting to notice the * `X-Run402-Key-Rotation` advisory header. * * `state: "legacy"` means the project still depends on the derived * anon/service keys signed by the retiring platform key. Only `project.read` * is required: knowing you should rotate is not a privileged act, and gating * it behind the owner role would hide the warning from the automation that * most needs it. */ status(projectId: string): Promise; /** * Rotate a credential * (`POST /projects/v1/:project_id/credentials/:credential_id/rotate`) — mint * a replacement and revoke the old one in a single transaction, keeping the * name and recording `replacement_of`. * * For a rotation with NO downtime window, prefer `issue()` a second live * credential, deploy it, then `revoke()` the first: several credentials may * be live per kind at once, and that overlap is the whole point. `rotate()` * is the right call when the old secret is already compromised. */ rotate(projectId: string, credentialId: string): Promise; /** * Revoke a credential immediately * (`DELETE /projects/v1/:project_id/credentials/:credential_id`). Frees the * name for reuse. Owner + step-up, same as `issue()`. */ revoke(projectId: string, credentialId: string, opts?: { reason?: string; }): Promise; /** * Mint a SHORT-LIVED project token (`POST /projects/v1/:project_id/tokens`). * * This is the cold-restart recovery path, and the one credential call a * delegate CAN make with no human present: an agent that lost its local * state but still holds a delegate gets back to work unattended. There is no * step-up, because there is nobody to prompt; what it hands back expires, so * it cannot become a durable root. * * Defaults to `service` — the kind an agent needs to deploy. */ mintToken(projectId: string, opts?: { kind?: ProjectCredentialKind; }): Promise; } export declare class ProjectKeysCache { private readonly client; constructor(client: Client); list(): Promise; status(projectId: string): Promise; import(projectId: string, opts: ProjectKeyCacheImportOptions): Promise; export(projectId: string, opts?: ProjectKeyCacheExportOptions): Promise; remove(projectId: string): Promise; } //# sourceMappingURL=credentials.d.ts.map