Schema check: a unique key is matched by shape, not name; quiet fixture pools

The rule mutation that stopped checking a named unique index by its name
survived, and rightly: an index of the same table, key columns, predicate,
uniqueness and immediacy keeps R21.1 whatever it is called, and the named
index's existence is already required as a relation. The name condition
and REQUIRED_KEYS' index field are deleted.

The live block failed 5 of 10 repeated runs with unhandled 57P01 errors:
a test's own pool, already ended, still had connections closing when the
forced drop terminated them, and nothing listened. Every pool the tests
open now goes through fixturePool, which ignores those errors; the store's
own pool keeps its listener and is not a fixture.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-09-30 19:30:40 +02:00
commit 6c0c87669f
3 changed files with 29 additions and 26 deletions

View file

@ -234,13 +234,12 @@ describe("PostgresStore.checkSchema", () => {
expect(REQUIRED_KEYS).toHaveLength(12);
expect(REQUIRED_KEYS).toEqual(
expect.arrayContaining([
{ table: "linked_identities", columns: "provider,provider_user_id", index: "", predicate: "" },
{ table: "private_command_receipts", columns: "app_slug,idempotency_key", index: "", predicate: "" },
{ table: "entitlement_snapshots", columns: "account_id,provider,scope", index: "", predicate: "" },
{ table: "linked_identities", columns: "provider,provider_user_id", predicate: "" },
{ table: "private_command_receipts", columns: "app_slug,idempotency_key", predicate: "" },
{ table: "entitlement_snapshots", columns: "account_id,provider,scope", predicate: "" },
{
table: "auth_completions",
columns: "app_slug,attempt_id",
index: "auth_completions_attempt_unconsumed_unique_idx",
predicate: comparablePredicate("attempt_id IS NOT NULL AND consumed_at IS NULL"),
},
])
@ -360,6 +359,17 @@ describe.skipIf(!adminUrl)("startup against a live Postgres (HEIMDALL_TEST_PG_AD
const admin = adminUrl ? new Pool({ connectionString: adminUrl, max: 2 }) : undefined;
const cleanup: Array<() => Promise<void>> = [];
/**
* A pool the test itself uses. The forced drops end its connections,
* possibly while pg is still closing them after end() resolved; that is
* cleanup, not a finding, so it is not left to become an unhandled error.
*/
function fixturePool(connectionString: string): Pool {
const pool = new Pool({ connectionString, max: 2 });
pool.on("error", () => undefined);
return pool;
}
function urlFor(database: string, user?: string, password?: string): string {
const url = new URL(adminUrl!);
url.pathname = `/${database}`;
@ -370,7 +380,7 @@ describe.skipIf(!adminUrl)("startup against a live Postgres (HEIMDALL_TEST_PG_AD
beforeAll(async () => {
await admin!.query(`CREATE DATABASE ${template}`);
const pool = new Pool({ connectionString: urlFor(template) });
const pool = fixturePool(urlFor(template));
await new PostgresStore(pool).ensureSchema();
await pool.end();
await admin!.query(`CREATE ROLE ${role} LOGIN PASSWORD '${rolePassword}'`);
@ -390,10 +400,7 @@ describe.skipIf(!adminUrl)("startup against a live Postgres (HEIMDALL_TEST_PG_AD
async function appliedDatabase(): Promise<{ name: string; owner: Pool }> {
const name = `heimdall_check_${randomUUID().replace(/-/g, "")}`;
await admin!.query(`CREATE DATABASE ${name} TEMPLATE ${template}`);
const owner = new Pool({ connectionString: urlFor(name), max: 2 });
// The forced drop ends this fixture pool's connections, possibly while
// they are still closing; that is cleanup, not a finding.
owner.on("error", () => undefined);
const owner = fixturePool(urlFor(name));
cleanup.push(async () => {
await owner.end();
await admin!.query(`DROP DATABASE IF EXISTS ${name} WITH (FORCE)`);
@ -450,7 +457,7 @@ describe.skipIf(!adminUrl)("startup against a live Postgres (HEIMDALL_TEST_PG_AD
await grant(owner, STORE_TABLE_PRIVILEGES);
expect(await start(urlFor(name, role, rolePassword), false)).toBe("started");
const pool = new Pool({ connectionString: urlFor(name, role, rolePassword) });
const pool = fixturePool(urlFor(name, role, rolePassword));
cleanup.push(async () => {
await pool.end();
});
@ -474,7 +481,7 @@ describe.skipIf(!adminUrl)("startup against a live Postgres (HEIMDALL_TEST_PG_AD
expect(message, `${table} without ${privilege}`).toBe(refusal("SCHEMA_PRIVILEGES"));
expect(message).not.toContain("CANARY");
const pool = new Pool({ connectionString: urlFor(name, role, rolePassword) });
const pool = fixturePool(urlFor(name, role, rolePassword));
const failure = await exerciseStore(new PostgresStore(pool)).then(
() => undefined,
(error: unknown) => (error as { code?: string }).code