Skip to content

Security Overview

Security in AnvilBase is on by default and layered. The design goal is strong tenant isolation — no project can read or write another project’s data — backed by defense in depth so no single failure leaks data.

Principles

  • Default deny at every boundary (network, API, database, storage, runtime).
  • Tenant isolation first — cryptographic and physical separation between projects.
  • Least privilege — scoped API keys, short-lived tokens, role-gated operators.
  • Defense in depth — RLS and routing isolation and encryption and audit.
  • Self-hostable — every control works without an external SaaS dependency.
  • Verifiable — immutable audit logs and a testable RLS sandbox.

Trust boundaries

Public Internet
│ (1) TLS terminates here
Traefik
│ (2) only the gateway is exposed
Control Plane ──(3)──► Internal services (Postgres, Valkey, MinIO, Realtime, Deno)
│ ▲
│ (5) tenant config │ (4) edge functions egress boundary
▼ │
Secrets vault (pgcrypto) ──(7)┘
Database ──(6)──► RLS & schema isolation (the primary data line)
  1. Internet → Traefik (edge TLS)
  2. Traefik → control-plane APIs
  3. Gateway → internal services
  4. Edge functions → outbound networks (egress/SSRF control)
  5. Tenant code/config → control plane (provisioning, secrets)
  6. Database → RLS & schema boundaries (the main data-isolation line)
  7. Secrets vault → services (key material boundary)

The defaults that protect you

ControlDefaultPage
Row Level Securityenabled on every created table (fail-closed)RLS
Encryption at restLUKS (Postgres), SSE-S3 (storage), pgcrypto (secrets)Encryption
Encryption in transitTLS at the edge; optional internal mTLSNetwork Security
API key scopesanon/authenticated/service_role, RLS-awareAPI Keys & Scopes
Cache isolationper-project Valkey ACL user proj_<pid> physically confined to the <project_id>:* keyspaceCache / KV
Edge function authverify_jwt: true by defaultFunctions
Management planefail-closed (401 without a valid credential)Concepts
Webhook targetsSSRF guard (no loopback/RFC1918/metadata)Webhooks
Destructive DDLrequires name-echo confirmationTables & Schema
Audit loggingevery administrative action recordedAudit Logs

How isolation is enforced (twice)

  1. At the routing layer — the control plane resolves the project from the credential and only ever routes to that project’s database, bucket, cache namespace, and queue namespace. A credential for project A cannot address project B. Cross-tenant id guessing returns 404 (IDOR-safe).
  2. Inside Postgres — RLS evaluates policies against the injected user/role context, so even within a project a user only sees permitted rows.

See Multi-Tenancy for the full isolation matrix.

Two credential systems

  • Management plane (/api/v1) — admin token or Personal Access Token; for operators/console/CLI. Fail-closed.
  • Data plane (/v1) — per-project API keys and user JWTs; for applications.

They’re not interchangeable. Concepts → The two API planes.