Security (RLS + scopes)#

Identities on the data API#

/data/* accepts two identities:

  1. Project API key (X-AFRIBASE-API-Key) - scoped to one project
  2. Project-user JWT (Authorization: Bearer) - issued by project auth (sign-in / OTP). This is the per-user identity RLS evaluates.

When both are present, the user JWT wins and the API key must belong to the same project.

API key scopes#

Keys are created with scopes (see Authentication). A key with any module scope is restricted to exactly those scopes; legacy keys keep full module access. Violations return 403 with an actionable message.

Row-level security (policies)#

Policies are configured per table + action (select / insert / update / delete) with a subject and effect (allow / deny).

Subject matching:

SubjectMatches
api_keyRequests authenticated with the project API key
authenticatedRequests with a valid project-user JWT (logged-in)
publicBoth
anyBoth

Rules:

  • No policies on a table: legacy allow-all (backward compatible)
  • Policies exist: a matching ALLOW is required; DENY always wins
  • The classic setup is an authenticated ALLOW per action, so only logged-in users can read/write

Example: only logged-in users can insert messages:

{ "action": "insert", "subject": "authenticated", "effect": "allow" }
JSON

Cross-project protection#

API keys are authorized only to their own project; requests to another project's routes return 403.

The users table#

The users table (auth users) is managed by the platform:

  • Cannot be created, renamed or deleted
  • Its columns cannot be added, updated or removed
  • Writes over the data API return 400
  • Data API reads are always scoped to the project

Secrets and env vars#

  • Stored encrypted at rest
  • Masked in list responses; revealed one at a time
  • Scoped keys: secrets:read/write, env:read/write