Credential broker
The credential broker turns a provider connection into scoped, short-lived credentials on demand. Instead of pasting a broad provider token into a stored secret, you bind a secret to a connection plus a scope template; the actual credential is minted at resolve time, TTL-bounded, and never stored — each resolve gets a fresh value derived from the connection's parent credential.
Brokered vs. rotated
| Rotated (static) secret | Brokered secret | |
|---|---|---|
| What is stored | The encrypted value | A pointer: connection + template — no value exists at rest |
| Lifetime | Until you rotate it | TTL-bounded per mint |
| Blast radius of a leak | The stored value, until rotated | One short-lived mint |
| Revocation | Rotate the secret | Revoke or suspend the connection — nothing else to chase |
Brokered secrets surface in listings with source: "brokered" and display-only binding facts (provider, connection id, template) — never template parameters, never credential material. Every mint is ledgered and audited: what was minted, from which connection, under which template, for which resolve.
Scope templates
A template declares what shape of credential a mint produces. Two populations exist:
- Provider-declared catalog — templates shipped by each provider's manifest (e.g. Cloudflare
workers-deploy,pages-deploy,account-read,hyperdrive-edit; Supabase equivalents). - Org custom templates — templates your workspace authors on top of a declared base.
Custom template authoring
| Method | Path | Description |
|---|---|---|
GET / POST | /v1/organizations/{orgId}/integrations/providers/{provider}/scope-templates | List (declared first, then every custom — retired included) / create |
PATCH | …/scope-templates/{templateId} | Update — displayName, description, status |
Template ids match [a-z0-9-]+. The console's create dialog takes an id, a base (declared template), and a display name. Retirement is soft and happens through PATCH (status: "active" | "retired"): a retired template disappears from create flows but stays in the manage view so it can be reactivated. No hard delete exists — a template can never be deleted out from under a live binding.
Connection-fact templates
Some templates mint no credential at all. A template with factKind: "connection-anchor" serves the custody row's provider-side anchor as its "minted" value:
| Provider | Template | Serves |
|---|---|---|
| Cloudflare | account-id | The connection's Cloudflare account id |
| Supabase | org-id | The connection's Supabase organization id |
The value is not a credential — there is no decrypt, no provider call, and nothing to revoke — but it is still ledgered like any mint, so provenance is uniform. Use these to bind values like CLOUDFLARE_ACCOUNT_ID or TF_VAR_supabaseOrgId as brokered secrets instead of hand-copying them into stored CI secrets: they follow the connection, and a re-pointed connection re-points them. A connection with no custody row fails the mint with parent_credential_missing.
The hyperdrive-edit caveat
Cloudflare's hyperdrive-edit template requires the provider permission groups "Hyperdrive Write" and "Account Settings Read". Mints are parent-grant deny-by-default: a template can never mint beyond what the connection's parent token actually holds.
An existing Cloudflare connection whose parent token was created before you needed Hyperdrive must have the Hyperdrive group added to the parent token (provider-side) before hyperdrive-edit can mint. The OAuth connect path cannot provision this group — only the token-paste path derives the required groups from the template grammar. If mints fail after adding the template, re-paste an upgraded token (a re-authorization, which preserves existing bindings).