{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://gmr.github.io/pglifecycle/schemata/role.json",
  "title": "Role",
  "description": "A role is an entity that can own database objects and have database privileges.\n",
  "type": "object",
  "properties": {
    "name": {
      "title": "Role Name",
      "type": "string"
    },
    "comment": {
      "title": "Comment",
      "description": "An optional comment about the role",
      "type": "string"
    },
    "create": {
      "title": "Create Role",
      "description": "Used in special cases where a role should be definied, but not created, such as \"PUBLIC\".\n",
      "type": "boolean",
      "default": true
    },
    "environments": {
      "title": "Environments",
      "description": "Used to limit the environments the role is created in. The default value is all environments.\n",
      "type": "array",
      "items": {
        "enum": [
          "DEVELOPMENT",
          "STAGING",
          "TESTING",
          "PRODUCTION"
        ]
      },
      "uniqueItems": true
    },
    "grants": {
      "description": "Privileges on database objects, grouped by the kind of object they are on. Written under `grants:` or `revocations:` on the role, user, or group they apply to, so a role file is the whole story of what that role can do.\n`ALL` stands for every privilege the object type has. Append ` WITH GRANT OPTION` to a privilege to let the grantee grant it onward.\n",
      "title": "ACLs",
      "type": "object",
      "properties": {
        "columns": {
          "description": "Privileges on individual columns, keyed by `schema.table.column`.\n",
          "type": "object",
          "propertyNames": {
            "pattern": "^([A-Za-z0-9_\\-]+)\\.([A-Za-z0-9_\\-]+)\\.([A-Za-z0-9_\\-]+)$"
          },
          "patternProperties": {
            "^.*$": {
              "type": "array",
              "items": {
                "pattern": "^(SELECT|INSERT|UPDATE|REFERENCES|ALL)( WITH GRANT OPTION)?$"
              }
            }
          }
        },
        "databases": {
          "description": "Privileges on databases, keyed by database name.\n",
          "type": "object",
          "propertyNames": {
            "pattern": "^([A-Za-z_\\-\\.])+$"
          },
          "patternProperties": {
            "^.*$": {
              "type": "array",
              "items": {
                "pattern": "^(CREATE|CONNECT|TEMP|TEMPORARY|ALL)( WITH GRANT OPTION)?$"
              }
            }
          }
        },
        "domains": {
          "description": "Privileges on domains, keyed by `schema.domain`.\n",
          "type": "object",
          "propertyNames": {
            "pattern": "^([A-Za-z0-9_\\-]+)\\.([A-Za-z0-9_\\-]+)$"
          },
          "patternProperties": {
            "^.*$": {
              "type": "array",
              "items": {
                "pattern": "^(USAGE|ALL)( WITH GRANT OPTION)?$"
              }
            }
          }
        },
        "foreign_data_wrappers": {
          "description": "Privileges on foreign data wrappers, keyed by wrapper name.\n",
          "type": "object",
          "propertyNames": {
            "pattern": "^([A-Za-z0-9_\\-\\.]+)$"
          },
          "patternProperties": {
            "^.*$": {
              "type": "array",
              "items": {
                "pattern": "^(USAGE|ALL)( WITH GRANT OPTION)?$"
              }
            }
          }
        },
        "foreign_servers": {
          "description": "Privileges on foreign servers, keyed by server name.\n",
          "type": "object",
          "propertyNames": {
            "pattern": "^([A-Za-z0-9_\\-\\.]+)$"
          },
          "patternProperties": {
            "^.*$": {
              "type": "array",
              "items": {
                "pattern": "^(USAGE|ALL)( WITH GRANT OPTION)?$"
              }
            }
          }
        },
        "functions": {
          "description": "Privileges on functions and procedures, keyed by `schema.function(argument types)`: the signature, since the name alone is ambiguous across overloads.\n",
          "type": "object",
          "propertyNames": {
            "pattern": "^([A-Za-z0-9_\\-]+)\\.([A-Za-z0-9_\\-]+)\\((.*)\\)$"
          },
          "patternProperties": {
            "^.*$": {
              "type": "array",
              "items": {
                "pattern": "^(EXECUTE|ALL)( WITH GRANT OPTION)?$"
              }
            }
          }
        },
        "groups": {
          "title": "Role Memberships",
          "description": "Memberships in other roles. Each entry is the role name on its own when the membership behaves the way `GRANT <role> TO <member>` grants it, or a mapping when it does not.\n`admin: true` writes WITH ADMIN OPTION. `inherit` and `set` write the per-membership WITH INHERIT / WITH SET options, which need PostgreSQL 16 or later; omit `inherit` to defer to the member role's own `inherit` option, which is what PostgreSQL does.\nThe grantor (`GRANTED BY`) is not carried: it records who granted the membership in one cluster, not what the schema is.\n",
          "type": "array",
          "items": {
            "oneOf": [
              {
                "title": "Role Name",
                "type": "string"
              },
              {
                "title": "Membership With Options",
                "type": "object",
                "properties": {
                  "role": {
                    "title": "Role Name",
                    "type": "string"
                  },
                  "admin": {
                    "title": "WITH ADMIN OPTION",
                    "description": "Whether the member may in turn grant this role to others.\n",
                    "type": "boolean"
                  },
                  "inherit": {
                    "title": "WITH INHERIT",
                    "description": "Whether the member automatically uses this role's privileges. Omit to defer to the member role's own `inherit` option.\n",
                    "type": "boolean"
                  },
                  "set": {
                    "title": "WITH SET",
                    "description": "Whether the member may SET ROLE to this role.\n",
                    "type": "boolean"
                  }
                },
                "required": [
                  "role"
                ],
                "additionalProperties": false
              }
            ]
          },
          "uniqueItems": true
        },
        "languages": {
          "description": "Privileges on procedural languages, keyed by language name.\n",
          "type": "object",
          "propertyNames": {
            "pattern": "^([A-Za-z0-9_\\-\\.]+)$"
          },
          "patternProperties": {
            "^.*$": {
              "type": "array",
              "items": {
                "pattern": "^(USAGE|ALL)( WITH GRANT OPTION)?$"
              }
            }
          }
        },
        "large_objects": {
          "description": "Privileges on large objects, keyed by OID.\n",
          "type": "object",
          "propertyNames": {
            "pattern": "^[0-9]+$"
          },
          "patternProperties": {
            "^.*$": {
              "type": "array",
              "items": {
                "pattern": "^(SELECT|UPDATE|ALL)( WITH GRANT OPTION)?$"
              }
            }
          }
        },
        "roles": {
          "title": "Role Memberships",
          "description": "Memberships in other roles. Each entry is the role name on its own when the membership behaves the way `GRANT <role> TO <member>` grants it, or a mapping when it does not.\n`admin: true` writes WITH ADMIN OPTION. `inherit` and `set` write the per-membership WITH INHERIT / WITH SET options, which need PostgreSQL 16 or later; omit `inherit` to defer to the member role's own `inherit` option, which is what PostgreSQL does.\nThe grantor (`GRANTED BY`) is not carried: it records who granted the membership in one cluster, not what the schema is.\n",
          "type": "array",
          "items": {
            "oneOf": [
              {
                "title": "Role Name",
                "type": "string"
              },
              {
                "title": "Membership With Options",
                "type": "object",
                "properties": {
                  "role": {
                    "title": "Role Name",
                    "type": "string"
                  },
                  "admin": {
                    "title": "WITH ADMIN OPTION",
                    "description": "Whether the member may in turn grant this role to others.\n",
                    "type": "boolean"
                  },
                  "inherit": {
                    "title": "WITH INHERIT",
                    "description": "Whether the member automatically uses this role's privileges. Omit to defer to the member role's own `inherit` option.\n",
                    "type": "boolean"
                  },
                  "set": {
                    "title": "WITH SET",
                    "description": "Whether the member may SET ROLE to this role.\n",
                    "type": "boolean"
                  }
                },
                "required": [
                  "role"
                ],
                "additionalProperties": false
              }
            ]
          },
          "uniqueItems": true
        },
        "schemata": {
          "description": "Privileges on schemas, keyed by schema name.\n",
          "type": "object",
          "propertyNames": {
            "pattern": "^([A-Za-z0-9_\\-]+)$"
          },
          "patternProperties": {
            "^.*$": {
              "type": "array",
              "items": {
                "pattern": "^(CREATE|USAGE|ALL)( WITH GRANT OPTION)?$"
              }
            }
          }
        },
        "sequences": {
          "description": "Privileges on sequences, keyed by `schema.sequence`.\n",
          "type": "object",
          "propertyNames": {
            "pattern": "^([A-Za-z0-9_\\-]+)\\.([A-Za-z0-9_\\-]+)$"
          },
          "patternProperties": {
            "^.*$": {
              "type": "array",
              "items": {
                "pattern": "^(SELECT|UPDATE|USAGE|ALL)( WITH GRANT OPTION)?$"
              }
            }
          }
        },
        "tables": {
          "description": "Privileges on tables, keyed by `schema.table`. Privileges on a view may be written here or under `views`: PostgreSQL grants on a view with TABLE syntax, so both emit `GRANT ... ON TABLE`.\n",
          "type": "object",
          "propertyNames": {
            "pattern": "^([A-Za-z0-9_\\-]+)\\.([A-Za-z0-9_\\-]+)$"
          },
          "patternProperties": {
            "^.*$": {
              "type": "array",
              "items": {
                "pattern": "^(SELECT|INSERT|UPDATE|DELETE|TRUNCATE|REFERENCES|TRIGGER|MAINTAIN|ALL)( WITH GRANT OPTION)?$"
              }
            }
          }
        },
        "tablespaces": {
          "description": "Privileges on tablespaces, keyed by tablespace name.\n",
          "type": "object",
          "propertyNames": {
            "pattern": "^([A-Za-z0-9_\\-]+)$"
          },
          "patternProperties": {
            "^.*$": {
              "type": "array",
              "items": {
                "pattern": "^(CREATE|USAGE|ALL)( WITH GRANT OPTION)?$"
              }
            }
          }
        },
        "types": {
          "description": "Privileges on types, keyed by `schema.type`.\n",
          "type": "object",
          "propertyNames": {
            "pattern": "^([A-Za-z0-9_\\-]+)\\.([A-Za-z0-9_\\-]+)$"
          },
          "patternProperties": {
            "^.*$": {
              "type": "array",
              "items": {
                "pattern": "^(USAGE|ALL)( WITH GRANT OPTION)?$"
              }
            }
          }
        },
        "views": {
          "description": "Privileges on views, keyed by `schema.view`. Emitted as `GRANT ... ON TABLE`, as PostgreSQL requires.\n",
          "type": "object",
          "propertyNames": {
            "pattern": "^([A-Za-z0-9_\\-]+)\\.([A-Za-z0-9_\\-]+)$"
          },
          "patternProperties": {
            "^.*$": {
              "type": "array",
              "items": {
                "pattern": "^(SELECT|ALL)( WITH GRANT OPTION)?$"
              }
            }
          }
        }
      },
      "additionalProperties": false
    },
    "revocations": {
      "description": "Privileges on database objects, grouped by the kind of object they are on. Written under `grants:` or `revocations:` on the role, user, or group they apply to, so a role file is the whole story of what that role can do.\n`ALL` stands for every privilege the object type has. Append ` WITH GRANT OPTION` to a privilege to let the grantee grant it onward.\n",
      "title": "ACLs",
      "type": "object",
      "properties": {
        "columns": {
          "description": "Privileges on individual columns, keyed by `schema.table.column`.\n",
          "type": "object",
          "propertyNames": {
            "pattern": "^([A-Za-z0-9_\\-]+)\\.([A-Za-z0-9_\\-]+)\\.([A-Za-z0-9_\\-]+)$"
          },
          "patternProperties": {
            "^.*$": {
              "type": "array",
              "items": {
                "pattern": "^(SELECT|INSERT|UPDATE|REFERENCES|ALL)( WITH GRANT OPTION)?$"
              }
            }
          }
        },
        "databases": {
          "description": "Privileges on databases, keyed by database name.\n",
          "type": "object",
          "propertyNames": {
            "pattern": "^([A-Za-z_\\-\\.])+$"
          },
          "patternProperties": {
            "^.*$": {
              "type": "array",
              "items": {
                "pattern": "^(CREATE|CONNECT|TEMP|TEMPORARY|ALL)( WITH GRANT OPTION)?$"
              }
            }
          }
        },
        "domains": {
          "description": "Privileges on domains, keyed by `schema.domain`.\n",
          "type": "object",
          "propertyNames": {
            "pattern": "^([A-Za-z0-9_\\-]+)\\.([A-Za-z0-9_\\-]+)$"
          },
          "patternProperties": {
            "^.*$": {
              "type": "array",
              "items": {
                "pattern": "^(USAGE|ALL)( WITH GRANT OPTION)?$"
              }
            }
          }
        },
        "foreign_data_wrappers": {
          "description": "Privileges on foreign data wrappers, keyed by wrapper name.\n",
          "type": "object",
          "propertyNames": {
            "pattern": "^([A-Za-z0-9_\\-\\.]+)$"
          },
          "patternProperties": {
            "^.*$": {
              "type": "array",
              "items": {
                "pattern": "^(USAGE|ALL)( WITH GRANT OPTION)?$"
              }
            }
          }
        },
        "foreign_servers": {
          "description": "Privileges on foreign servers, keyed by server name.\n",
          "type": "object",
          "propertyNames": {
            "pattern": "^([A-Za-z0-9_\\-\\.]+)$"
          },
          "patternProperties": {
            "^.*$": {
              "type": "array",
              "items": {
                "pattern": "^(USAGE|ALL)( WITH GRANT OPTION)?$"
              }
            }
          }
        },
        "functions": {
          "description": "Privileges on functions and procedures, keyed by `schema.function(argument types)`: the signature, since the name alone is ambiguous across overloads.\n",
          "type": "object",
          "propertyNames": {
            "pattern": "^([A-Za-z0-9_\\-]+)\\.([A-Za-z0-9_\\-]+)\\((.*)\\)$"
          },
          "patternProperties": {
            "^.*$": {
              "type": "array",
              "items": {
                "pattern": "^(EXECUTE|ALL)( WITH GRANT OPTION)?$"
              }
            }
          }
        },
        "groups": {
          "title": "Role Memberships",
          "description": "Memberships in other roles. Each entry is the role name on its own when the membership behaves the way `GRANT <role> TO <member>` grants it, or a mapping when it does not.\n`admin: true` writes WITH ADMIN OPTION. `inherit` and `set` write the per-membership WITH INHERIT / WITH SET options, which need PostgreSQL 16 or later; omit `inherit` to defer to the member role's own `inherit` option, which is what PostgreSQL does.\nThe grantor (`GRANTED BY`) is not carried: it records who granted the membership in one cluster, not what the schema is.\n",
          "type": "array",
          "items": {
            "oneOf": [
              {
                "title": "Role Name",
                "type": "string"
              },
              {
                "title": "Membership With Options",
                "type": "object",
                "properties": {
                  "role": {
                    "title": "Role Name",
                    "type": "string"
                  },
                  "admin": {
                    "title": "WITH ADMIN OPTION",
                    "description": "Whether the member may in turn grant this role to others.\n",
                    "type": "boolean"
                  },
                  "inherit": {
                    "title": "WITH INHERIT",
                    "description": "Whether the member automatically uses this role's privileges. Omit to defer to the member role's own `inherit` option.\n",
                    "type": "boolean"
                  },
                  "set": {
                    "title": "WITH SET",
                    "description": "Whether the member may SET ROLE to this role.\n",
                    "type": "boolean"
                  }
                },
                "required": [
                  "role"
                ],
                "additionalProperties": false
              }
            ]
          },
          "uniqueItems": true
        },
        "languages": {
          "description": "Privileges on procedural languages, keyed by language name.\n",
          "type": "object",
          "propertyNames": {
            "pattern": "^([A-Za-z0-9_\\-\\.]+)$"
          },
          "patternProperties": {
            "^.*$": {
              "type": "array",
              "items": {
                "pattern": "^(USAGE|ALL)( WITH GRANT OPTION)?$"
              }
            }
          }
        },
        "large_objects": {
          "description": "Privileges on large objects, keyed by OID.\n",
          "type": "object",
          "propertyNames": {
            "pattern": "^[0-9]+$"
          },
          "patternProperties": {
            "^.*$": {
              "type": "array",
              "items": {
                "pattern": "^(SELECT|UPDATE|ALL)( WITH GRANT OPTION)?$"
              }
            }
          }
        },
        "roles": {
          "title": "Role Memberships",
          "description": "Memberships in other roles. Each entry is the role name on its own when the membership behaves the way `GRANT <role> TO <member>` grants it, or a mapping when it does not.\n`admin: true` writes WITH ADMIN OPTION. `inherit` and `set` write the per-membership WITH INHERIT / WITH SET options, which need PostgreSQL 16 or later; omit `inherit` to defer to the member role's own `inherit` option, which is what PostgreSQL does.\nThe grantor (`GRANTED BY`) is not carried: it records who granted the membership in one cluster, not what the schema is.\n",
          "type": "array",
          "items": {
            "oneOf": [
              {
                "title": "Role Name",
                "type": "string"
              },
              {
                "title": "Membership With Options",
                "type": "object",
                "properties": {
                  "role": {
                    "title": "Role Name",
                    "type": "string"
                  },
                  "admin": {
                    "title": "WITH ADMIN OPTION",
                    "description": "Whether the member may in turn grant this role to others.\n",
                    "type": "boolean"
                  },
                  "inherit": {
                    "title": "WITH INHERIT",
                    "description": "Whether the member automatically uses this role's privileges. Omit to defer to the member role's own `inherit` option.\n",
                    "type": "boolean"
                  },
                  "set": {
                    "title": "WITH SET",
                    "description": "Whether the member may SET ROLE to this role.\n",
                    "type": "boolean"
                  }
                },
                "required": [
                  "role"
                ],
                "additionalProperties": false
              }
            ]
          },
          "uniqueItems": true
        },
        "schemata": {
          "description": "Privileges on schemas, keyed by schema name.\n",
          "type": "object",
          "propertyNames": {
            "pattern": "^([A-Za-z0-9_\\-]+)$"
          },
          "patternProperties": {
            "^.*$": {
              "type": "array",
              "items": {
                "pattern": "^(CREATE|USAGE|ALL)( WITH GRANT OPTION)?$"
              }
            }
          }
        },
        "sequences": {
          "description": "Privileges on sequences, keyed by `schema.sequence`.\n",
          "type": "object",
          "propertyNames": {
            "pattern": "^([A-Za-z0-9_\\-]+)\\.([A-Za-z0-9_\\-]+)$"
          },
          "patternProperties": {
            "^.*$": {
              "type": "array",
              "items": {
                "pattern": "^(SELECT|UPDATE|USAGE|ALL)( WITH GRANT OPTION)?$"
              }
            }
          }
        },
        "tables": {
          "description": "Privileges on tables, keyed by `schema.table`. Privileges on a view may be written here or under `views`: PostgreSQL grants on a view with TABLE syntax, so both emit `GRANT ... ON TABLE`.\n",
          "type": "object",
          "propertyNames": {
            "pattern": "^([A-Za-z0-9_\\-]+)\\.([A-Za-z0-9_\\-]+)$"
          },
          "patternProperties": {
            "^.*$": {
              "type": "array",
              "items": {
                "pattern": "^(SELECT|INSERT|UPDATE|DELETE|TRUNCATE|REFERENCES|TRIGGER|MAINTAIN|ALL)( WITH GRANT OPTION)?$"
              }
            }
          }
        },
        "tablespaces": {
          "description": "Privileges on tablespaces, keyed by tablespace name.\n",
          "type": "object",
          "propertyNames": {
            "pattern": "^([A-Za-z0-9_\\-]+)$"
          },
          "patternProperties": {
            "^.*$": {
              "type": "array",
              "items": {
                "pattern": "^(CREATE|USAGE|ALL)( WITH GRANT OPTION)?$"
              }
            }
          }
        },
        "types": {
          "description": "Privileges on types, keyed by `schema.type`.\n",
          "type": "object",
          "propertyNames": {
            "pattern": "^([A-Za-z0-9_\\-]+)\\.([A-Za-z0-9_\\-]+)$"
          },
          "patternProperties": {
            "^.*$": {
              "type": "array",
              "items": {
                "pattern": "^(USAGE|ALL)( WITH GRANT OPTION)?$"
              }
            }
          }
        },
        "views": {
          "description": "Privileges on views, keyed by `schema.view`. Emitted as `GRANT ... ON TABLE`, as PostgreSQL requires.\n",
          "type": "object",
          "propertyNames": {
            "pattern": "^([A-Za-z0-9_\\-]+)\\.([A-Za-z0-9_\\-]+)$"
          },
          "patternProperties": {
            "^.*$": {
              "type": "array",
              "items": {
                "pattern": "^(SELECT|ALL)( WITH GRANT OPTION)?$"
              }
            }
          }
        }
      },
      "additionalProperties": false
    },
    "options": {
      "titles": "Role Options",
      "type": "object",
      "properties": {
        "bypass_rls": {
          "title": "Bypass Role Level Security",
          "description": "These clauses determine whether a role bypasses every row-level security (RLS) policy.\n",
          "type": "boolean",
          "default": false
        },
        "connection_limit": {
          "title": "Connection Limit",
          "description": "If role can log in, this specifies how many concurrent connections the role can make. -1 (the default) means no limit.\n",
          "type": "integer",
          "default": -1
        },
        "create_db": {
          "title": "Create Database",
          "description": "Determines if the role is allowed to create databases.",
          "type": "boolean",
          "default": false
        },
        "create_role": {
          "title": "Create Role",
          "description": "These clauses determine whether a role will be permitted to create a new group, role or user.\n",
          "type": "boolean",
          "default": false
        },
        "inherit": {
          "title": "Inherits Role Privileges",
          "description": "These clauses determine whether a role \"inherits\" the privileges of roles it is a member of.\n",
          "type": "boolean",
          "default": false
        },
        "login": {
          "title": "Login Allowed",
          "description": "These clauses determine whether a role is allowed to log in; that is, whether the role can be given as the initial session authorization name during client connection.\n",
          "type": "boolean",
          "default": false
        },
        "replication": {
          "title": "Replication Enabled",
          "description": "These clauses determine whether a role is allowed to initiate streaming replication or put the system in and out of backup mode. A role having the REPLICATION attribute is a very highly privileged role, and should only be used on roles actually used for replication.\n",
          "type": "boolean",
          "default": false
        },
        "superuser": {
          "title": "Super User",
          "description": "These clauses determine whether the new role is a \"superuser\", who can override all access restrictions within the database. Superuser status is dangerous and should be used only when really needed.\n",
          "type": "boolean",
          "default": false
        }
      },
      "additionalProperties": false
    },
    "settings": {
      "type": "array",
      "items": {
        "type": "object",
        "propertyNames": {
          "pattern": "^[A-Za-z_][A-Za-z0-9_\\.]*$"
        }
      }
    }
  },
  "additionalProperties": false
}