-
Notifications
You must be signed in to change notification settings - Fork 0
BYOK Secrets
Coop is bring-your-own-key (BYOK): you supply the model API key, Coop never
ships one. A Hen's brain.provider_id chooses where that key is read from.
| Scheme | Backend | Key on disk? |
|---|---|---|
vault:<secret> |
Local sealed file vault | Yes β sealed at rest |
azure-kv://<vault>/<secret>[/<version>] |
Azure Key Vault | No β fetched at run time |
Both can coexist; different hens on the same farm can use different backends.
A single xchacha20poly1305 file, sealed with a key derived from your
passphrase via Argon2id. File mode is 0600; the passphrase never touches disk.
export COOP_PASSPHRASE='change-me'
coop vault init ~/.coop/vault.json
COOP_SECRET_VALUE='sk-ant-...' coop vault put ~/.coop/vault.json byok-anthropic
coop vault list ~/.coop/vault.jsonAuto-unlock the vault at daemon startup:
COOP_VAULT=~/.coop/vault.json COOP_PASSPHRASE='change-me' coopd serveOr unlock a running daemon over the API:
curl -X POST http://127.0.0.1:9700/api/v1/vault/unlock \
-H 'content-type: application/json' \
-d '{"path":"~/.coop/vault.json","passphrase":"change-me"}'Reference it from a manifest:
brain:
provider_id: vault:byok-anthropic
model: claude-sonnet-4-5-20250929For teams who already centralize secrets in Azure. The key is fetched over HTTPS each time a brain is built and held only in zeroized memory β it is never written to the local vault file or disk.
azure-kv://<vault-name>/<secret-name>
azure-kv://<vault-name>/<secret-name>/<version>
brain:
provider_id: azure-kv://my-coop-kv/byok-anthropic
model: claude-sonnet-4-5-20250929The optional /<version> pins a specific secret version; omit it for the
latest enabled one.
Credentials come from the environment (the standard Azure
EnvironmentCredential model), resolved in this order:
1. Static bearer token β bring your own already-acquired AAD token:
export AZURE_KEYVAULT_TOKEN="$(az account get-access-token \
--resource https://vault.azure.net --query accessToken -o tsv)"Coop does not refresh it β supply a fresh one if it expires (useful with a managed identity that mints tokens out-of-band).
2. Service principal (client credentials) β Coop performs the OAuth2 client-credentials flow against AAD and caches the token until just before expiry:
export AZURE_TENANT_ID=<tenant-guid>
export AZURE_CLIENT_ID=<app-registration-client-id>
export AZURE_CLIENT_SECRET=<client-secret>| Variable | Default | Example override |
|---|---|---|
AZURE_KEYVAULT_DNS_SUFFIX |
vault.azure.net |
vault.azure.cn, vault.usgovcloudapi.net
|
AZURE_AUTHORITY_HOST |
https://login.microsoftonline.com |
https://login.chinacloudapi.cn |
The token / service principal needs the Get secret permission on the target
vault β the Key Vault Secrets User role under RBAC, or a get secrets access
policy.
# create a vault + secret
az keyvault create --name my-coop-kv --resource-group my-rg --location eastus
az keyvault secret set --vault-name my-coop-kv \
--name byok-anthropic --value 'sk-ant-...'
# create a service principal and grant Get on secrets
az ad sp create-for-rbac --name coop-byok
az role assignment create --assignee <appId> \
--role "Key Vault Secrets User" \
--scope $(az keyvault show --name my-coop-kv --query id -o tsv)Then export AZURE_TENANT_ID / AZURE_CLIENT_ID / AZURE_CLIENT_SECRET and
point a manifest at azure-kv://my-coop-kv/byok-anthropic.
- Secret values are wrapped in
Zeroizingand wiped from memory on drop. - AAD tokens and client secrets are redacted in
Debugoutput and never logged. - Azure Key Vault error bodies are truncated to 512 bytes and contain no secret values.
- All Azure traffic is HTTPS-only (
https_only). - See the Security Model hardening table (M1, M2).
Coop is Apache-2.0 Β· pre-alpha (v0.1). Authoritative docs live in the repo.
Get started
Operate
Reference