Veefore docs

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.

The agent never holds the credentialThree columns: the agent with no credential, the gateway containing the pipeline and the broker, and the downstream service. The credential flows only from the broker to the tool runtime.Credentials flow to the runtime, not the agentAgent processholds: identity keyholds: no credentialprompt context isnot a secret storeGatewayStages 1–9everything that can refuseCredential brokerunseal · lease · recordstage 10, after every refusalYour servicereceives the leasedcredential, scoped toone permitted actionsignedleasedan agent calling your service directly has no credential to call with
The credential reaches the tool runtime inside the gateway. It never reaches the agent.
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

  1. You register a credential reference with its material. Veefore seals the material with VEEFORE_DATA_ENCRYPTION_KEY.
  2. You attach the credential to a tool.
  3. An agent requests an action on that tool.
  4. The pipeline runs. Stage 10 is the first stage with an external side effect — every refusal has already happened.
  5. The broker issues a lease: a short-lived credential, scoped to this action.
  6. 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

bash
curl -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:audit fails 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

bash
curl -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

bash
curl -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.

Identity, authority, policy and enforcement for autonomous AI agents.