No description
Find a file
2025-11-05 22:48:58 +00:00
dev-services update dev services for apple containers 2025-10-09 08:01:01 +00:00
interim-models reordering fields 2025-11-05 22:48:58 +00:00
interim-namegen add ability to create new workspaces through the ui 2025-10-09 08:01:01 +00:00
interim-pgtypes add scaffolding for clusters and service creds 2025-11-01 00:17:45 +00:00
interim-server reordering fields 2025-11-05 22:48:58 +00:00
sass fix table keyboard nav 2025-11-05 18:40:00 +00:00
static switch from hero icons to tabler icons 2025-10-24 18:27:26 +00:00
svelte reordering fields 2025-11-05 22:48:58 +00:00
.dockerignore initial commit 2025-05-02 23:48:54 -07:00
.gitignore exclude .helix files from version control 2025-10-09 08:01:01 +00:00
Cargo.lock add scaffolding for clusters and service creds 2025-11-01 00:17:45 +00:00
Cargo.toml add ability to create new workspaces through the ui 2025-10-09 08:01:01 +00:00
deno.json insert rows from viewer 2025-08-15 00:16:36 -07:00
deno.lock misc cleanup 2025-09-14 16:22:42 -04:00
Dockerfile refactor db clients 2025-08-04 13:59:50 -07:00
mise.toml fix mise watch sources 2025-10-14 05:14:04 +00:00
package.json misc cleanup 2025-09-14 16:22:42 -04:00
README.md add scaffolding for clusters and service creds 2025-11-01 00:17:45 +00:00

Phonograph (FKA Interim)

A friendly, collaborative PostgreSQL derivative for nerds of all stripes.

The Phonograph Authorization Model

Postgres provides a sophisticated role based access control (RBAC) system, which Phonograph leverages to apply permissions consistently across the web UI and inbound PostgreSQL1 connections.

In order to efficiently pool database connections from the application server, most actions initiated via the web UI are run as the corresponding database user role using the SET ROLE command. SET ROLE does not provide great insulation against privilege escalation. Queries which are not thoroughly validated and escaped must only be run via a dedicated connection initiated with the user-level role's credentials.

Given complete freedom it is possible, in fact easy, to configure a Postgres table into what would be considered an "invalid" state by Phonograph, so table creation and ownership is restricted to the "root" Phonograph role, which acts on the behalf of the user in order to facilitate schema updates via the web interface.

Permissions Granted via User Roles

Accessing workspace databases

GRANT CONNECT ON <database> TO <role>;

This permission is granted when initially creating the workspace, as well as when accepting an invitation to a table.

Access to workspaces is controlled via the CONNECT ON DATABASE permission. However, it is unreasonable to query every backing database to compute the set of workspaces to which a user has access, so Phonograph caches workspace-level "connect" permissions in its own centralized table (workspace_memberships).

workspace_memberships rows are added whenever the GRANT CONNECT command is run, and are deleted after a REVOKE CONNECT command is run.

It is possible that an error occurs after REVOKE CONNECT but before the membership record is deleted. Therefore for authorization purposes, membership of a workspace is not a guarantee that the user has CONNECT privileges, just that they might. In cases where the root Postgres user is fetching potentially sensitive data on behalf of a user, the user's actual ability to connect to the database should always be confirmed.

Accessing the phono schema

GRANT USAGE ON <schema> TO <role>;

This permission is granted when initially creating the workspace, as well as when accepting an invitation to a table.

Creating, updating, and deleting columns

GRANT <table owner role> TO <role>;

This permission is granted when initially creating the table, as well as when accepting an invitation to a table, if the invitation includes "owner" permissions.

This permission is only used via the web UI and must not be granted to service credentials, lest users alter table structure in unsupported ways.

Reading table data

GRANT SELECT ON <table> TO <role>;

This permission is granted when initially creating the table, as well as when accepting an invitation to the table.

Phonograph uses SELECT permissions to infer whether a table should be accessible to a user via the web UI.

Inserting rows

GRANT INSERT (<columns>) ON <table> TO <role>;

Write-protected columns (_id, etc.) are excluded.

This permission is granted when initially creating the table, as well as when accepting an invitation to the table, if the invitation includes "edit" permissions.

These permissions must be updated for each relevant user role whenever a column is added; this is simplified by maintaining a single "writer" role per table.

Updating rows

GRANT UPDATE (<columns>) ON <table> TO <role>;

Write-protected columns (_id, etc.) are excluded.

This permission is granted when initially creating the table, as well as when accepting an invitation to the table, if the invitation includes "edit" permissions.

These permissions must be updated for each relevant user role whenever a column is added; this is simplified by maintaining a single "writer" role per table.

Actions Facilitated by Root

  • Creating tables

Service Credentials

Direct user PostgreSQL connections are performed using secondary LOGIN roles created by the user's primary workspace role (where the primary workspace role is e.g. usr_{user_id}). The credentials for these secondary roles are referred to as "service credentials" or "PostgreSQL credentials". Service credentials are created and assigned permissions by users in the web UI, and their permissions are revoked manually in the web UI and/or by cascading REVOKE commands targeting the primary workspace role.

Service credential role names have the format svc_{user_id}_{8 chars (4 bytes) of random hex}. With the user ID consuming 32 characters, this balances name length with an ample space for possible names.

Footnotes


  1. Barring historical pedantry, "Postgres" and "PostgreSQL" are essentially synonymous and are often used interchangeably. As a matter of convention throughout Phonograph docs, "Postgres" is largely used to refer to the database software, while "PostgreSQL" is typically used to refer to the query language and/or wire protocol. ↩︎