The security model
What Veefore guarantees, what it does not, and where each guarantee is enforced.
Veefore is security infrastructure, so the honest thing to do is state the guarantees precisely — including their limits — rather than list features.
#The four guarantees
1. The gateway is the authorization boundary
Every protected action is decided server-side, in a process the agent does not control, on every call. No decision is cached and no permission is carried forward.
The LLM is not the boundary. The SDK is not the boundary. The browser is not the boundary. → The boundary
2. It fails closed
When a dependency enforcement relies on is unavailable, protected actions are refused. There is no mode, flag or environment variable in which an error becomes an allow. → Fail closed
3. The agent never holds the secret
Credentials live in the broker. The agent asks Veefore to act; Veefore decides, then leases a short-lived, scoped credential to the tool runtime. A leaked prompt leaks nothing usable. → Secrets
4. Tenants are isolated by two independent layers
Application-level scoping that refuses a query with no tenant scope, plus PostgreSQL row-level security underneath it. Either alone would be sufficient. → Tenant isolation
#Where each guarantee is enforced
| Guarantee | Enforced by | Verified by |
|---|---|---|
| Agent identity | Ed25519 signature, nonce, timestamp, audience, generation | tests/security, gateway smoke |
| Authority bounds | Delegation intersection at stage 6 | tests/unit, tests/integration |
| Policy determinism | Closed field set, total operators | tests/policy — 31 cases |
| Fail-closed | Explicit refusal on dependency loss | tests/chaos — 13 cases |
| Tenant isolation | Repository scope guard + RLS | tests/security, tests/integration |
| Secret containment | Broker, redaction on ingest, quality audit | tests/security, CLI smoke |
| Audit integrity | Keyed hash chain | veefore audit verify, tests/integration |
Every row is a suite you can run. npm run verify runs all of them.
#What Veefore does not guarantee
Being clear about this is more useful than implying completeness.
It does not make a bad agent good. If an agent is authorized to issue refunds and policy permits a refund, Veefore permits it. The value is that the authority is bounded, the decision is recorded, and the blast radius is known.
It does not prevent prompt injection. It makes injection much less rewarding: the agent has no credential to steal, and anything it is talked into attempting still goes through the full pipeline.
It does not secure your downstream. If your API accepts unauthenticated requests, Veefore brokering a credential does not change that.
It does not prove audit completeness against a database-level attacker. The hash chain detects tampering within the stored sequence. An attacker with database write access and the chain secret could rewrite it consistently. → Audit integrity
It does not hold money. Not a wallet, a processor, a ledger or a settlement
system. amount is a policy input. → Scope
#The threat model
Written as attacker goals with the mechanism that refuses each one: → Threat model
Every case in it has a corresponding test in tests/security — 49 of them. A
threat model without tests is a wish list.
#Access control
Roles, permissions, high-impact grants, custom roles.
Re-authentication for irreversible operations.
Identity provider integration and lifecycle.
IP restrictions and the egress guards.
#Assurance
What the chain proves and what it does not.
Control mapping, populated from live state.
How to report a vulnerability.
#The design principle underneath all of it
Prefer a guarantee that is structural over one that is configured.
A few examples of the same instinct:
- An agent belongs to one environment, so a staging identity cannot act in production. Not because a rule forbids it — because the agent is not there.
- The credential broker runs at stage 10, after everything that can refuse. So
BLOCKmeans the secret did not go out, rather than meaning it did but the response was discarded. - Revocation is terminal. A revocation that can be undone by whoever caused the incident is not a revocation.
- The scope audit asserts no table has a
balancecolumn. A wallet could be written without the word "wallet"; it could not be written without somewhere to put a balance.
Configuration drifts. Structure does not.