Authorization
PlotPress’s authorization model is per-dashboard. Each dashboard folder declares its own users and its own connections. There is no workspace-wide “everyone can read X.”
| Noun | Defined in | Stored in |
|---|---|---|
| User | OIDC provider (or Email OTP for self-hosted demos) | SQLite (id, email, last seen) |
| Role | dashboards/<name>/users.yaml | parsed at boot |
| Connection | dashboards/<name>/connections.yaml | parsed at boot, never persisted |
users.yaml defines named roles (e.g. analysts, exec) and how a user qualifies for each — by static email list or OIDC claim.
The rule
Section titled “The rule”A query runs if and only if the requesting user holds at least one role listed in the target connection’s allowed_users, and that connection lives in the same dashboard folder as the page making the request.
flowchart LR
U[User<br/>email] -->|OIDC| S[Session]
S --> R{users.yaml<br/>role resolution}
R -->|claim match| R1[role: analysts]
R -->|email list| R2[role: exec]
Q[Query] --> C[(connection: warehouse)]
C -->|allowed_users| R1
R1 -.->|allowed| Q
What this is not
Section titled “What this is not”- Not row-level security. PlotPress controls which connections a viewer can hit. Push row filtering down into the database (RLS or per-role views).
- Not a query builder. The backend executes against database views (the primary path) or pre-registered SQL files (the fallback — see Authoring → Queries as fallback).
- Not a secret manager. Connection DSNs read from environment variables; PlotPress never writes them to disk.
Every query execution writes one row to audit_log in SQLite: timestamp, user, dashboard, view (or query name), parameters, connection, duration, row count, error. Backups of the SQLite file are the audit backup.