Fifth section of #23: the start-up check. Before any migration runs, on
both connections, the console refuses when the two strings log in as one
user or reach different databases, when the runtime user is a superuser
or a member of a superuser role, when it owns or is a member of the
owner of the database, when the database is owned by neither the
migration user nor a superuser, when the runtime user can create objects
in the database, in public or in a console schema, or when it owns an
object in those schemas that a name lookup could resolve (relations,
functions, operators, types, and operator classes, families and
extensions database-wide). After the migrations and the boot grant, on
the runtime connection, it refuses when console_runtime is missing, when
the runtime user does not inherit it or holds it with SET, when the
schema is behind the code, when the runtime user reaches an owner role,
owns an object, holds any direct membership but console_runtime, or
holds a privilege an enclosure withholds. Each refusal names the
statement that fixes it, with names quoted by the database; a check
query that fails refuses too. migrate up, down and status refuse a
database whose owner is neither user before goose runs.
The boot grant is now WITH INHERIT TRUE, SET FALSE: the runtime user
needs only to inherit console_runtime, and without SET on that first
membership no SET ROLE reaches a role through it. Granting again
updates an existing membership in place; this worktree's runtime user
held SET from the previous section and lost it at the suite's boot.
Every check runs in a read-only REPEATABLE READ transaction that begins
with SET LOCAL search_path = pg_catalog, pg_temp, and names every
function and catalog relation with pg_catalog., so nothing the runtime
user planted (a function such as public.quote_ident(name), or an
operator such as public.=(oid, integer), which qualified function names
alone did not exclude) runs in the migration user's session or writes a
statement the console prints. TestCheckQueriesQualifyEveryName scans
the query constants and fails on an unqualified function call or catalog
relation.
Full suite on reset databases: 4370 pass, 15 skip, none failed. The
console booted on the test stack and logged "runtime database user
checked" with the runtime and migration users. make lint passes. Break
runs that disable an early refusal or a test's cleanup can leave a role
or a membership in the shared test cluster; those were removed after
the run.
Deliberate breaks, scripts/mutation-check -side new, all CAUGHT (76):
checks 3a to 3c run before checks 1 to 3
checks 1 to 4 run after the migrations
the boot grant runs before the superuser check
the database-ownership check removed (TestCheckBeforeMigrating)
the database-ownership check removed (TestOpenRuntimeDatabase)
check 4 tests datdba = current_user in place of MEMBER
check 4 reads the first database in pg_database
check 4 without its datname = current_database() filter
the migration identity read outside the pinned read-only transaction, with an unqualified quote_ident
the runtime identity read outside the pinned read-only transaction, with an unqualified quote_ident
the migration pool opened without role=none (owner set its own role)
check 12 reads has_schema_privilege in place of the ACL entries
check 12's schema CREATE query removed (TestCheckBeforeMigrating)
check 12's schema CREATE query removed (TestOpenRuntimeDatabase)
check 12's ownership query removed (TestCheckBeforeMigrating)
check 12's ownership query removed (TestOpenRuntimeDatabase)
check 12 runs after the migrations
the boot grant's pg_catalog.format written format
check 12's queries read outside the pinned read-only transaction (TestCheckBeforeMigrating)
check 12's queries read outside the pinned read-only transaction (TestOpenRuntimeDatabase)
CheckRuntimeUser's transaction without the search-path pin
the second query of checks 9 and 12 casts the login with regrole
CheckMigrationDatabaseOwner removed from dbMigration
dbMigration checks before up only
CheckMigrationDatabaseOwner removed from dbRuntime
the owner half refuses a superuser-owned database
copy 3d prints the database name unquoted
check 11 without the four-privilege read
copy 9 prints the user in place of the grantee
check 11's grantee filter dropped
check 11's predefined-role query removed
copy 3c prints the direct role unquoted
copy 6 prints the direct role unquoted
check 6 tests MEMBER in place of USAGE
check 8 tests USAGE in place of MEMBER
check 9 without functions
check 9 without public
check 9 tests owner = current_user in place of MEMBER
the direct-membership check removed (TestCheckRuntimeUser)
the direct-membership check removed (TestOpenRuntimeDatabase)
the direct-membership check counts console_runtime
the direct-membership check runs before check 8
check 11 removed
check 3 without its membership half
copy 5 quotes the name in Go (%q)
an exemption when env is development
a failed check query passes
the scratch database is dropped after the login that owns it (test-side)
an unqualified quote_ident( in the identity query
an unqualified pg_roles in the owner check
PendingMigrations calls to_regclass without pg_catalog.
the query constants renamed so none begins query (test-side)
the search-path pin removed from the pinned read-only transaction
the search-path pin removed from the savepoint a test runs a check in
check 5 removed
check 6 does not read the SET option
check 6 does not read the SET option (separate-step start)
the boot grant leaves the SET option (TestGrantRuntimeRole)
the boot grant leaves the SET option (TestOpenRuntimeDatabase)
the database CREATE query removed (TestCheckBeforeMigrating)
the database CREATE query removed (TestOpenRuntimeDatabase)
the database CREATE query reads has_database_privilege in place of the ACL entries
check 12's ownership query reads public only
check 12's ownership query reads public only (TestOpenRuntimeDatabase)
check 9 without operators
check 9 without types
check 9 without operator classes
check 9 without operator families
check 9 without extensions
start's refusal log lacks the owner refusal
the scan folds no case (test-side)
the scan reads a quoted call as no call (test-side)
the scan reads no line comment (test-side)
the scan skips a concatenated constant (test-side)
the scan passes a query constant without a value (test-side)
copy 5a prints only the GRANT, not the REVOKE by the grantor