Veefore docs

Secrets

Every place a secret could surface, and the specific mechanism that stops it.

Four categories of secret exist in a Veefore deployment. Each has a different containment story.

What it is Who holds it
Platform keys Data encryption, signing, session, audit chain The deployment's environment
Agent private keys One Ed25519 key per agent The agent's own host
Credential material Your downstream secrets The credential broker
Human credentials Passwords, session tokens, API keys People and your secret store

#Platform keys

ini
VEEFORE_DATA_ENCRYPTION_KEY=…    # seals credential material
VEEFORE_SIGNING_PRIVATE_KEY=…    # signs agent passports
VEEFORE_SESSION_SECRET=…         # signs human sessions
VEEFORE_AUDIT_CHAIN_SECRET=…     # keys the audit hash chain

`.env.example` ships development keys. They are not secret.

They exist so the stack boots out of the box, and they are shared with everyone who has ever cloned the repository. Replace all four before anything that matters.

Inject them from a secret manager, not from a file. And give each process only what it needs:

Control plane Gateway Worker
VEEFORE_DATA_ENCRYPTION_KEY yes yes yes
VEEFORE_SIGNING_PRIVATE_KEY yes yes —
VEEFORE_SESSION_SECRET yes no —
VEEFORE_AUDIT_CHAIN_SECRET yes yes yes

The gateway never issues a human session, so it does not need the session secret. A secret a process does not need is a secret that process should not have — it is one more place a compromise can read it from.

#Rotation

Key Consequence
VEEFORE_SESSION_SECRET Everyone re-authenticates. Safe
VEEFORE_SIGNING_PRIVATE_KEY Issued passports stop verifying. Issue new ones, let partners pick up the new published key, retire the old
VEEFORE_DATA_ENCRYPTION_KEY Every credential must be re-sealed. Plan as a migration
VEEFORE_AUDIT_CHAIN_SECRET Existing chain becomes unverifiable. Export and archive first

The last two are projects, not config changes.

#Agent private keys

Generated locally by veefore init and never sent to Veefore. Only the public half crosses the network, so there is no moment at which Veefore could have logged, cached or leaked the private one.

Written to .env.local at mode 0600, between managed markers:

ini
# Veefore MANAGED BEGIN — do not edit between the markers
VEEFORE_AGENT_PRIVATE_KEY=MC4CAQAwBQYDK2VwBCIEI…
# Veefore MANAGED END

The key is written once and is not recoverable

Veefore stores the public key and nothing else. Lose .env.local and you do not recover the key — you rotate to a new one with veefore agents rotate-key, which also invalidates every session the old key had open.

veefore doctor checks the file permissions. A key readable by another process on the host is a key that process can act with, and that is a real finding.

If you omit public_key at registration, Veefore generates the pair and returns the private half once. It is not stored and not recoverable. Use that path only when the agent runs somewhere that cannot generate a key.

#Credential material

The agent never holds it. → Credential broker

Five independent mechanisms keep it contained:

1. No endpoint returns it. GET /v1/credentials returns metadata only — key, name, type, provider, status, last rotated, lease count. The repository layer does not select the sealed column into API responses.

2. Redaction on ingest. Credential-shaped values, private keys, session tokens and anything listed in a tool's sensitive_parameters are redacted before a log line is constructed.

There is no code path where a secret is written and later filtered

Redaction happens on the way in, not on the way out. Which means log shipping, log retention and log backups cannot leak what was never written.

An output filter would be strictly weaker: it only protects the paths it covers, and a new log statement is a new path.

3. Audit by reference. Credential leases are recorded by id, never by value. Masked parameter paths are masked in audit too, so a MASK decision redacts the value in the trail as well as in the forwarded request.

4. Error messages never contain secret values. Nor key material, internal hostnames, or stack detail. When you need to know why a decision went a certain way, read the action record — behind authentication.

5. The quality audit. npm run quality:audit fails the build on a committed secret: private key blocks, high-entropy assignments to secret-named variables, and recognisable provider key formats. The CLI smoke test additionally asserts that no command prints a secret.

#Get the material keys right

Each credential type reads specific keys and discards the rest.

This used to fail two layers from its cause

Put the secret under a name the broker does not read and Veefore would seal it happily, permit the action happily, broker nothing usable, and your downstream would return 401. Nothing in the Veefore logs looked wrong, because from Veefore's point of view nothing was.

Now refused at registration and rotation with INVALID_CREDENTIAL_REFERENCE. BASIC_AUTH, MTLS_CERTIFICATE and SIGNING_KEY are exempt because their material is legitimately multi-field.

Full table

#Human credentials

Passwords are never stored in plaintext and never logged. The CLI reads them without echoing and stores only the resulting session token, in ~/.veefore/credentials.json at mode 0600.

Session tokens have a TTL and an idle timeout. High-impact operations need step-up regardless of session age, so a stolen session cannot revoke an agent.

API keys are shown exactly once; only a hash is stored. The field is token, not secret, and there is no endpoint that returns it again.

Step-up permissions are unavailable to API keys

Step-up requires a human re-authenticating, and an API key has no human. A key holding policy:activate still cannot activate a policy.

Which means CI cannot activate a policy on its own — deliberate, because activation moves the authorization boundary for every agent in scope. It is a decision, not a build step. → Gate your pipeline

#Files that contain secrets

File Mode Gitignored
.env yours to set yes
.env.local 0600 yes
~/.veefore/credentials.json 0600 n/a
.veefore-real.env 0600 yes
.veefore-demo-keys.env 0600 yes
veefore.config.json — no, and that is correct

veefore.config.json holds the agent id, the key id and the URLs. No secrets. Commit it.

#If a secret leaks

  1. Rotate in Veefore.
  2. Revoke at the source. Veefore rotating does not tell your provider to stop accepting the old value.
  3. Work out the exposure from the lease records.
  4. Open an incident with the window.
  5. Close the route it leaked through.

→ Credential leak runbook

#Checklist

  • [ ] All four platform keys replaced from .env.example defaults
  • [ ] Platform keys injected from a secret manager, not a file
  • [ ] Each process has only the keys it needs
  • [ ] All four backed up alongside the database, and a restore tested
  • [ ] .env, .env.local, .veefore-real.env gitignored
  • [ ] Agent keys generated locally; public_key supplied at registration
  • [ ] No agent holds a long-lived downstream key — all in the broker
  • [ ] sensitive_parameters set on every tool that handles PII
  • [ ] npm run quality:audit in CI
  • [ ] Rotation on a schedule for agent keys and credentials

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