Roles
roles names migration, app, and optional reporting grants.
roles names migration, app, and optional reporting grants.
A name in managed is a role the plan creates. A name outside that list is external and has to exist already. schema() has no roles field. The grants are added when the config sets roles.
| Field | Required | What it sets |
|---|---|---|
migration | yes | Runs the files. When this role already exists and is not the session user, apply issues SET ROLE before the statements. Default privileges are for this role. |
app | yes | Receives the grants in the first table. After the plan, SELECT on okm_meta. |
reporting | no | The grants in the second table. |
managed | no | Roles the plan creates. See managed. |
columns | no | Column SELECT or UPDATE. See columns. |
Grants are on managed objects.
| Object | app |
|---|---|
| table | SELECT, INSERT, UPDATE, DELETE |
| view | SELECT, INSERT, UPDATE, DELETE |
| materialized view | SELECT |
| sequence | USAGE, SELECT |
| function | EXECUTE |
Default privileges are ALTER DEFAULT PRIVILEGES for the migration role, in each schema those objects use. With no such schema, they are issued in public.
| Object | Privileges |
|---|---|
| tables | SELECT, INSERT, UPDATE, DELETE |
| functions | EXECUTE |
| sequences | USAGE, SELECT |
The plan revokes INSERT, UPDATE, and DELETE on a materialized view granted to app. After the plan, app receives SELECT on okm_meta. When this run creates the migration role, that role receives USAGE and CREATE on the schema, and SELECT, INSERT, and UPDATE on okm_meta, okm_history, and okm_backfill. Apply then issues SET ROLE.
| Object | reporting |
|---|---|
| table | SELECT |
| view | SELECT |
| materialized view | SELECT |
| schema | USAGE |
reporting also receives a default SELECT on later tables, for the migration role.
import { defineConfig } from "okmodel/migrate";
export default defineConfig({
schema: "./schema.ts",
database: process.env.DATABASE_URL!,
roles: {
migration: "okm_migrate",
app: "okm_app",
reporting: "okm_read",
},
});Managed
managed lists roles the plan creates and alters. A role is never dropped. The statement is NOSUPERUSER NOCREATEDB NOCREATEROLE. An external role emits no CREATE ROLE and no ALTER ROLE. login and inherit are altered only when the role is already managed.
| Field | Default | Result |
|---|---|---|
name | — | The role name. |
login | NOLOGIN | LOGIN when true. |
inherit | INHERIT | NOINHERIT when false. |
A managed role that pg_roles does not have is created. okm doctor skips that absence. The role that applies a CREATE ROLE or ALTER ROLE needs CREATEROLE. A superuser passes the same check. The message names that role: Role postgres lacks CREATEROLE. Nothing was changed. A role another session created first does not fail the create.
Columns
columns grants SELECT or UPDATE on named columns. on is the SQL name of one table, view, or materialized view. A column may be the field name or the SQL name. An empty list adds no grant. A role named only here receives those column grants.
| Field | Required | What it sets |
|---|---|---|
role | yes | The role that receives the privilege. |
on | yes | The table, view, or materialized view. |
select | no | Columns granted SELECT. |
update | no | Columns granted UPDATE. |
On a table with a hidden column, reporting receives SELECT on the visible columns. hidden({ filterable: true }) stays in that hidden set. A select list for reporting adds those columns, including a hidden one. On a table with no hidden column, reporting receives SELECT on the table. On a view or a materialized view, a select list for reporting is the SELECT grant for those columns.
import { defineConfig } from "okmodel/migrate";
export default defineConfig({
schema: "./schema.ts",
database: process.env.DATABASE_URL!,
roles: {
migration: "okm_migrate",
app: "okm_app",
reporting: "okm_read",
managed: [{ name: "okm_app", login: true }],
columns: [{ role: "okm_app", on: "users", select: ["email"] }],
},
});| Case | Result |
|---|---|
An empty migration, app, reporting, managed name, or column role | Refused. roles.migration needs a name. The label is migration, app, reporting, managed role, or column grant role. |
reporting is migration or app | Refused. Role okm_app cannot be the reporting role and also migration or app. |
update on the reporting role | Refused. Role okm_read is the reporting role and cannot be granted update. |
on names an ignored table | Refused. Column grant on users targets an ignored table. |
An external migration, app, or reporting role is absent | okm doctor refuses. Role okm_app is named in roles and does not exist. |
on or a column is missing, or on matches more than one object | OKM1020. |
| A privilege is missing on an object that exists | OKM1825. An object absent from the database is skipped. |
connect() | Leaves roles unchecked. |
OKM1020
Column grant names missing, which is not in the schema. Column users.missing is not in the schema. Column grant on users matches more than one object.
OKM1825
Role okm_read lacks SELECT(email) on public.users.email. okm doctor names the role, the privilege, and the object.
OKM1122
A reserved word is role user is a reserved word. A name past 63 bytes includes the count, as in is 64 bytes. The limit is 63.