Access & audit
The data editor hands out direct database access, so it’s deliberately fenced with RBAC, auditing and a server-side-only connection model.
RBAC — read vs. write
Section titled “RBAC — read vs. write”Access is enforced per resource by Pier’s role-based access control:
| Action | Minimum role |
|---|---|
| Browse databases / schemas / tables / collections / keys | Viewer |
| View structure, rows, documents, key values | Viewer |
| SQL Runner (any statement) | Editor |
| Mongo Shell (any script) | Editor |
| Redis command (any command) | Editor |
The split is intentional: a teammate can be given read-only insight into production data without the ability to mutate it. Anything that could write — every runner, regardless of whether the specific statement happens to be a SELECT — requires Editor.
Audit log
Section titled “Audit log”Every runner execution is recorded in the db_query_log table, whether it succeeds or fails. Each row captures:
- Who — user id and username.
- Where — the service and the target database.
- What — the SQL / command / script text, and its kind (
read,write,redis,mongo). - Outcome — status (
ok/error), row count, duration, and the error message on failure.
Logging is best-effort and never blocks a query — an audit-write failure won’t mask a successful (or failed) statement. Browsing reads aren’t logged; the audit trail focuses on the runners, which are the actions that can change data.
Credentials
Section titled “Credentials”Connection credentials come from the service’s encrypted environment (env_json, AES-256-GCM at rest) and are decrypted in memory only at request time. They are:
- never displayed in the UI,
- never written to logs,
- read from the standard image variables —
POSTGRES_USER/POSTGRES_PASSWORD,MYSQL_ROOT_PASSWORD(orMARIADB_ROOT_PASSWORD),MONGO_INITDB_ROOT_USERNAME/MONGO_INITDB_ROOT_PASSWORD,REDIS_PASSWORD.
Connection model
Section titled “Connection model”Pier core runs on the host and reaches each database over the pier-net Docker network — the container’s internal IP and port — falling back to 127.0.0.1:{host_port} only when a port is published. This means:
- A private database never has to be exposed to the internet for you to inspect it.
- The traffic stays on the internal Docker bridge between the host process and the container.
Injection safety (SQL)
Section titled “Injection safety (SQL)”For the SQL browser, identifiers (schema/table/column names) arrive as parameters but are never trusted blindly:
- the
(schema, table)pair is confirmed to exist viainformation_schemabefore any string-built SQL touches it, - every identifier and literal is engine-quoted,
- column names always come from the catalog, never from the client.
The SQL Runner itself executes the operator’s statement as-is — that’s the point of a runner — which is exactly why it’s gated behind Editor and fully audited.
Next steps
Section titled “Next steps”- Overview — supported engines and where to find the Data tab.
- SQL Runner — limits and behavior of the SQL runner.