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.

FieldRequiredWhat it sets
migrationyesRuns 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.
appyesReceives the grants in the first table. After the plan, SELECT on okm_meta.
reportingnoThe grants in the second table.
managednoRoles the plan creates. See managed.
columnsnoColumn SELECT or UPDATE. See columns.

Grants are on managed objects.

Objectapp
tableSELECT, INSERT, UPDATE, DELETE
viewSELECT, INSERT, UPDATE, DELETE
materialized viewSELECT
sequenceUSAGE, SELECT
functionEXECUTE

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.

ObjectPrivileges
tablesSELECT, INSERT, UPDATE, DELETE
functionsEXECUTE
sequencesUSAGE, 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.

Objectreporting
tableSELECT
viewSELECT
materialized viewSELECT
schemaUSAGE

reporting also receives a default SELECT on later tables, for the migration role.

okmodel.config.ts
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.

FieldDefaultResult
name—The role name.
loginNOLOGINLOGIN when true.
inheritINHERITNOINHERIT 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.

FieldRequiredWhat it sets
roleyesThe role that receives the privilege.
onyesThe table, view, or materialized view.
selectnoColumns granted SELECT.
updatenoColumns 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.

okmodel.config.ts
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"] }], 
  },
});
CaseResult
An empty migration, app, reporting, managed name, or column roleRefused. roles.migration needs a name. The label is migration, app, reporting, managed role, or column grant role.
reporting is migration or appRefused. Role okm_app cannot be the reporting role and also migration or app.
update on the reporting roleRefused. Role okm_read is the reporting role and cannot be granted update.
on names an ignored tableRefused. Column grant on users targets an ignored table.
An external migration, app, or reporting role is absentokm 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 objectOKM1020.
A privilege is missing on an object that existsOKM1825. 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.

On this page