/** * Per-organization credential payloads, shared between server and UI. * * A credential row is canonically identified by the * `(role, backend, auth_method)` tuple; the schema stores the tuple, * not a dotted-string discriminator. The dotted form * `..` clients see in `type` is a derived * label projected from the tuple at DTO-build time. Always 3 segments * — even when a backend has a single canonical auth method, it's * recorded explicitly so the wire format and the schema stay in * lockstep without a per-backend special case. * * Each row carries `{ secrets, metadata }`. The database enforces the * split at the column level: `secrets` is encrypted, `metadata` is * plaintext jsonb. The union below forces every new field to pick a * side at authoring time — a future column cannot accidentally stuff * a secret into `metadata` without the TS compiler flagging it, * because the keys in each variant's `metadata` are fixed. * * The registry (`packages/server/src/db/repository/credential/registry.ts`) * owns the matching zod validators, the runtime-plaintext-location * pin, and the cardinality (`'singleton' | 'multi' | 'per-user'`). * This file only expresses the shape both sides of the wire agree on. * * - `provisioning.*` — admin credentials a worker uses to create * per-app logical databases in a customer's cloud. * - `inference.*` — credentials used to call a managed inference API * (Snowflake Cortex REST API, Databricks AI Gateway). Non-singleton * so an org can keep separate dev/prod rows. * - reserved: `authoring.*`, `runtime.*`, `connection.*`, `pat.*`, * `trust.*`, `generator.*`. * * Trust and generator payload variants don't appear in the union yet — * those land in the followup PR alongside their registry entries. The * schema (and the CHECK constraint allowing `class IN ('stored', 'trust', * 'generator')`) already supports them so the followup is registry-only. */ /** * Secrets shape for `provisioning.snowflake.pat` and * `inference.snowflake-cortex.pat`. Snowflake accepts either a * programmatic access token (used as the `password` for `snowflake-sdk`, * or as a bearer token against the REST API) or an RSA private key used * to sign a short-lived JWT. Consumers branch on which shape is present. * * Note that the dotted label says `pat` even when the keypair branch is * used; `pat` here is the identifier of the auth-method *family*, * because Snowflake exposes both as a single endpoint that consumes a * bearer token (the keypair JWT and the literal PAT are interchangeable * at the request level). When a true second auth method lands (e.g. * OAuth M2M) it gets its own tuple with a distinct auth_method segment. */ export type SnowflakeSecrets = { pat: string; } | { privateKey: string; privateKeyPassphrase?: string; }; export type ProvisioningLakebasePayload = { type: 'provisioning.lakebase.pat'; secrets: { pat: string; }; metadata: { workspaceUrl?: string; adminHost?: string; adminPort?: number; adminUsername?: string; sslMode?: string; }; }; export type ProvisioningSnowflakePayload = { type: 'provisioning.snowflake.pat'; secrets: SnowflakeSecrets; metadata: { account: string; username: string; warehouse?: string; role?: string; schema?: string; databasePrefix?: string; }; }; /** * Credentials used to call the Snowflake Cortex REST API. Same secret * shapes as `provisioning.snowflake.pat` — the REST API accepts either * a long-lived PAT as a bearer token or a short-lived JWT signed with * an RSA private key. `cardinality: 'multi'` in the registry because * orgs will plausibly want separate dev / prod Cortex identities. */ export type InferenceSnowflakeCortexPayload = { type: 'inference.snowflake-cortex.pat'; secrets: SnowflakeSecrets; metadata: { /** Snowflake account identifier, e.g. `xy12345.us-east-1`. */ account: string; /** Service user whose PAT or public key is installed on the Snowflake side. */ username: string; /** Role the PAT is scoped to / the JWT should assume at call time. */ role?: string; }; }; /** * Databricks AI Gateway credential. AI Gateway only accepts Programmatic * Access Tokens (PATs) as bearer credentials — there is no keypair or * OAuth path comparable to Snowflake Cortex. `gatewayHost` is either the * Anthropic-compatible AI Gateway origin or a workspace AI Gateway * Anthropic messages URL, both validated at the registry. */ export type InferenceDatabricksAiGatewayPayload = { type: 'inference.databricks-ai-gateway.pat'; secrets: { pat: string; }; metadata: { /** * AI Gateway origin, e.g. `https://.ai-gateway.cloud.databricks.com`, * or workspace Anthropic messages URL, e.g. * `https:///ai-gateway/anthropic/v1/messages`. */ gatewayHost: string; }; }; export type CredentialPayload = ProvisioningLakebasePayload | ProvisioningSnowflakePayload | InferenceSnowflakeCortexPayload | InferenceDatabricksAiGatewayPayload; export type CredentialType = CredentialPayload['type']; /** * All known `` prefixes. Used by callers to filter credentials by * role (e.g. "list all provisioning credentials for this org"). Includes * reserved-but-unused roles so adding a new one later is a registry + * union change rather than a cross-cutting rename. * * `trust` and `generator` are reserved for the credential-class taxonomy * (see `CredentialClass` below): trust-config rows like * `trust.aws.iam-role-assume` will claim `role: 'trust'`, generator rows * like `generator.snowflake.keypair-jwt` will claim `role: 'generator'`. * They are not yet populated in the registry — these reserved values * just keep the `(class, role, backend, auth_method)` tuple consistent * so the followup PR's registrations are a code-only change. */ export declare const CREDENTIAL_ROLES: readonly ["provisioning", "authoring", "runtime", "connection", "inference", "pat", "trust", "generator"]; export type CredentialRole = (typeof CREDENTIAL_ROLES)[number]; /** * Three credential classes, recorded on every row of the `credential` * table: * - `stored` — encrypted secret bytes are the credential * (PATs, RSA private keys held for JWT signing). * - `trust` — the credential is a trust assertion held in * `metadata`; `encrypted_secrets` is NULL. The DB's * `chk_credential_secrets_class` CHECK constraint * enforces this. * - `generator` — encrypted bytes are *generator material* (OAuth * client_id+secret, RSA keypair) used to mint a * short-lived runtime token. The minted token is * never persisted; only the cache key tuple * (orgId, credentialId, fingerprint, derivationKey) * is. * * The class is denormalized onto the row so query paths can branch on * it without joining the registry, and so the schema CHECK constraint * can enforce the secrets-vs-no-secrets invariant. Only `'stored'` * entries are registered today; `'trust'` and `'generator'` are * reserved by the schema and the type system, awaiting their registry * additions in the followup PR. */ export declare const CREDENTIAL_CLASSES: readonly ["stored", "trust", "generator"]; export type CredentialClass = (typeof CREDENTIAL_CLASSES)[number]; /** * The process where a credential's plaintext (or its derived runtime * token, for generator credentials) may legitimately exist. * * - `server` — the Superblocks control plane. * - `orchestrator` — the customer's On-Premise Agent. * - `worker` — the orchestrator's per-language sandboxed * worker process (Go/JS/Python). * - `customer-sm` — held in the customer's own secret manager * (AWS Secrets Manager, GCP Secret Manager, * Vault); the Superblocks control plane never * touches it. Reserved. * * The repository's `assertProcessCanHandle` guard reads a process-level * `PROCESS_LOCATION` constant and rejects with * `WrongProcessForCredentialError` if a row's * `runtimePlaintextLocation` excludes the current process. Replaces * the implicit "this code path lives server-side, so the secret must * be decryptable here" convention with a typed check. */ export declare const RUNTIME_PLAINTEXT_LOCATIONS: readonly ["server", "orchestrator", "worker", "customer-sm"]; export type RuntimePlaintextLocation = (typeof RUNTIME_PLAINTEXT_LOCATIONS)[number]; /** * Format a `(role, backend, authMethod)` tuple into the dotted * `CredentialType` label that clients see on the wire. The schema * stores the tuple; this is the canonical projection for DTOs and * registry-by-label lookups. Always 3 segments. */ export declare function formatCredentialType(role: string, backend: string, authMethod: string): CredentialType; /** * Inverse of `formatCredentialType`. Returns `null` when the input * doesn't have exactly three dotted segments — the caller decides * whether that's a hard error or a soft signal. Backend and auth-method * identifiers may contain hyphens but never dots, so a length-3 split * is unambiguous. */ export declare function parseCredentialType(type: string): { role: string; backend: string; authMethod: string; } | null; /** * Convenience: extract the role segment of a `CredentialType`. The * full tuple round-trip is `parseCredentialType`. */ export declare function credentialRole(type: CredentialType): CredentialRole; /** * Non-secret projection returned from list / GET endpoints. Never contains * `secrets`. `metadata` is the same shape the client POSTed under that key. * * `class`, `role`, `backend`, `authMethod`, and `runtimePlaintextLocation` * come from columns on the row (the canonical tuple plus the registry- * pinned class and process-location). `type` is the dotted label * projected from `(role, backend, authMethod)` — kept on the DTO as * an API-stable identifier so existing clients don't have to assemble * it themselves. */ export interface CredentialDto { id: string; organizationId: string; /** Derived label `${role}.${backend}.${authMethod}`; not stored. */ type: CredentialType; /** `null` when the registry marks the tuple as a singleton. */ name: string | null; metadata: CredentialPayload['metadata']; /** First 8 hex of SHA-256 over the decrypted secrets object at write time. */ fingerprint: string; /** See `CredentialClass`. Pinned by the registry on write. */ class: CredentialClass; /** See `CREDENTIAL_ROLES`. First segment of the canonical tuple. */ role: CredentialRole; /** Short backend identifier, e.g. `lakebase`, `snowflake`, `aws`. */ backend: string; /** Short auth-method identifier, e.g. `pat`, `keypair`, `oauth-m2m`. */ authMethod: string; /** See `RuntimePlaintextLocation`. Pinned by the registry on write. */ runtimePlaintextLocation: RuntimePlaintextLocation; createdAt: string; updatedAt: string; createdBy: string | null; } export interface UpsertCredentialRequest { type: CredentialType; name?: string | null; secrets: CredentialPayload['secrets']; metadata: CredentialPayload['metadata']; } //# sourceMappingURL=index.d.ts.map