---
title: The security model
description: What Veefore guarantees, what it does not, and where each guarantee is enforced.
label: Overview
---

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

:::security 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](/secure/boundary)
:::

:::security 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](/secure/fail-closed)
:::

:::security 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](/secure/secrets)
:::

:::security 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](/secure/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](/secure/audit-integrity)

**It does not hold money.** Not a wallet, a processor, a ledger or a settlement
system. `amount` is a policy input. [→ Scope](/scope)

## The threat model

Written as attacker goals with the mechanism that refuses each one:
[→ Threat model](/secure/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

:::cards

:::card RBAC | /secure/rbac
Roles, permissions, high-impact grants, custom roles.
:::

:::card Step-up | /secure/step-up
Re-authentication for irreversible operations.
:::

:::card SSO and SCIM | /secure/sso-and-scim
Identity provider integration and lifecycle.
:::

:::card Network | /secure/network
IP restrictions and the egress guards.
:::

:::

## Assurance

:::cards

:::card Audit integrity | /secure/audit-integrity
What the chain proves and what it does not.
:::

:::card Compliance | /secure/compliance
Control mapping, populated from live state.
:::

:::card Responsible disclosure | /secure/disclosure
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 `BLOCK` means 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 `balance` column. 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.
