Credential broker
The agent never holds the secret. Veefore seals material on the way in and leases short-lived, scoped credentials on the way out.
An agent that holds an API key is an agent whose API key is in its prompt context, in its logs, and in whatever the model decides to say next. Prompt injection becomes credential theft, and the blast radius is whatever that key can do.
The credential broker removes the key from the agent entirely. The agent asks Veefore to perform an action. Veefore decides. Only after the action is permitted does the broker issue a short-lived, scoped credential — to the tool runtime, not to the agent.
The agent never sees it
A leaked prompt leaks nothing usable. A compromised agent can only ask for actions, and every ask runs the full pipeline. There is no key to exfiltrate, because the agent was never given one.
This is also what makes the SDK genuinely non-load-bearing: an agent that bypasses the SDK and calls your API directly has no credential to call it with.
Described in text
The agent holds only its own identity key. The gateway runs stages one to nine, and only after the action is permitted does the broker unseal the stored material and lease it — scoped to that one action — to the tool runtime. An agent calling your service directly has no credential to call with, which is what makes the SDK genuinely non-load-bearing.
#The flow
- You register a credential reference with its material. Veefore seals the material with
VEEFORE_DATA_ENCRYPTION_KEY. - You attach the credential to a tool.
- An agent requests an action on that tool.
- The pipeline runs. Stage 10 is the first stage with an external side effect — every refusal has already happened.
- The broker issues a lease: a short-lived credential, scoped to this action.
- The tool runtime uses it. The lease is recorded by reference and expires.
Default lease lifetime is CREDENTIAL_DEFAULT_TTL_SECONDS, 600 seconds. Lease
statuses are ISSUED, USED, EXPIRED, REVOKED.
#Registering one
bashcurl -X POST https://veefore.example.com/v1/credentials \
-H "Authorization: Bearer $VEEFORE_API_KEY" \
-H 'content-type: application/json' \
-d '{
"key": "payments-api-key",
"name": "Payments service API key",
"type": "API_KEY",
"provider": "local",
"material": {
"api_key": "…",
"header": "x-api-key"
}
}'
Supported types: API_KEY, BEARER_TOKEN, BASIC_AUTH, DATABASE_DSN,
OAUTH_CLIENT, MTLS_CERTIFICATE, SIGNING_KEY.
Use the right key names in `material`
Each credential type reads specific keys and discards the rest. API_KEY
accepts api_key, apiKey, key or value, plus optional header and
prefix. Put the secret under a name the broker does not read and you get a
failure two layers away from the cause: Veefore seals and stores it happily,
permits the action happily, brokers nothing, and your downstream returns 401.
Veefore now refuses this at registration and at rotation with
INVALID_CREDENTIAL_REFERENCE rather than letting you find out in production.
BASIC_AUTH, MTLS_CERTIFICATE and SIGNING_KEY are exempt from the check
because their material is legitimately multi-field.
| Type | Reads |
|---|---|
API_KEY |
api_key / apiKey / key / value, plus header, prefix |
BEARER_TOKEN |
token / access_token / value |
BASIC_AUTH |
username and password |
DATABASE_DSN |
dsn / url / connection_string |
OAUTH_CLIENT |
client_id and client_secret |
MTLS_CERTIFICATE |
certificate and private_key |
SIGNING_KEY |
private_key and algorithm |
#Secrets never come back out
No endpoint returns credential material. GET /v1/credentials returns metadata
only: key, name, type, provider, status, created, last rotated, lease count.
The guarantee is enforced in several places at once, deliberately:
- The repository layer does not select the sealed column into API responses.
- Log redaction strips credential-shaped values from every log line.
- Audit events record the credential by id, never by value.
npm run quality:auditfails the build on a committed secret.- The CLI smoke test asserts no command prints a secret.
If you lose the material, you rotate. You do not read it back. That is the intended one-way door.
#Rotation
bashcurl -X POST https://veefore.example.com/v1/credentials/cred_01ABC/rotate \
-H "Authorization: Bearer $VEEFORE_API_KEY" \
-H 'content-type: application/json' \
-d '{ "material": { "api_key": "…", "header": "x-api-key" } }'
Rotation seals the new material and invalidates every outstanding lease. An in-flight action holding an old lease fails rather than continuing with a credential you have decided to retire.
credential:rotate requires step-up authentication. The status moves through
ROTATING while it happens, so the transition is observable.
Rotate on a schedule. veefore doctor reports credentials that are overdue, and
CREDENTIAL_ANOMALY is a risk signal that fires on unusual credential use.
#Revocation
bashcurl -X POST https://veefore.example.com/v1/credentials/cred_01ABC/revoke \
-H "Authorization: Bearer $VEEFORE_API_KEY" \
-H 'content-type: application/json' \
-d '{ "reason": "Key published in a support ticket" }'
Immediate. Every lease dies, and every tool depending on the credential starts
failing at stage 10 with INVALID_CREDENTIAL_REFERENCE. credential:revoke is
high impact and step-up gated.
#Providers
CREDENTIAL_BROKER_PROVIDER selects the backend. local seals material in
PostgreSQL with VEEFORE_DATA_ENCRYPTION_KEY, which is correct for development
and for deployments where Veefore's database is already your trust boundary.
For production, point it at your existing secret manager so the material lives where the rest of your secrets live and inherits that system's rotation, auditing and access control. The broker's behaviour is identical either way.
Rotating the data encryption key needs re-sealing
VEEFORE_DATA_ENCRYPTION_KEY is what seals stored material under the local
provider. Changing it without re-sealing makes every stored credential
unreadable, and the symptom is every tool failing at once. Plan it as a
migration, not a config change.
#Why stage 10 and not earlier
Brokering is the first irreversible step. Everything before it — authentication, identity, lifecycle, capability, delegation, policy, risk, approval — can refuse with no trace outside Veefore.
Putting the broker after all of them is what makes BLOCK mean blocked.
Brokering earlier, say for performance, would mean a blocked action had already
caused a credential to be issued. Then "we blocked it" and "the secret did not
go out" would be two different claims, and only one of them would be true.