issue-281: use the DATABASE_URL password for postgres connections #284
No reviewers
Labels
No labels
bug
chore
documentation
enhancement
feature
ready
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
david/pi-extensions-and-skills!284
Loading…
Reference in a new issue
No description provided.
Delete branch "bug/issue-281/database-url-password-silently-ignored"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Fixes the postgres extension silently ignoring the password in
DATABASE_URL, which made every connection fail with the misleadingSASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a stringwhenever~/.pgpasshad no matching entry.Root cause
parseConnUrl()returned only{host, port, database, user}— the URL's password was dropped.passwordProvideroption, whichpgdoes not support, so it was silently dropped.pg's own deprecated~/.pgpasslookup (removed inpg@9), which yieldsundefinedon a miss → SCRAM throwsclient password must be a string.A second latent bug: the
pgpasscall used a 2-arg(err, password)callback, butpgpasscalls its callback with a single argument — so a found password would be treated as an error and a miss would resolve to"".The fix
env.ts—ConnInfogainspassword?: string;parseConnUrl()returnspassword: parsed.password || undefined(a password-less URL normalises toundefinedso it still triggers the.pgpassfallback).index.ts— two small, injectable, exported helpers:resolvePassword(conn, pgpassFn?)— the URL's password is authoritative; a password-less URL does an explicit~/.pgpasslookup; a miss resolves toundefined(never"").buildPoolConfig(conn, pgpassFn?)— builds thepg.Poolconfig withpasswordas a function (the formpg's deprecation notice recommends). Because it's a function,pgnever touches its deprecated built-inpgpasspath.new pg.Pool(buildPoolConfig(connInfo)).Acceptance criteria (issue-281)
DATABASE_URL, no matching~/.pgpass→ all tools connect (URL password is a real string reaching SCRAM).DATABASE_URL+ matching~/.pgpass→ unchanged (explicit lookup).password authentication failed, notclient password must be a string.pg's deprecated built-inpgpasspath (thepasswordis always a function, sopguses thetypeof this.password === 'function'branch and never its internalrequire('pgpass')fallback).Verification
bun test→ 53 pass, 0 fail (21 new assertions acrossenv.test.tsandindex.test.ts, with a fake injectablepgpass).tsc --noEmit --strictintroduces no new type errors vs. the original (only the 3 pre-existing ones: untypedpg/pgpassimports and the pre-existingdb_query_onesignature).pg.Poolconstructed frombuildPoolConfig()output accepts the function-valuedpasswordwithout throwing (connects lazily, sopgpassis only invoked at connect time).Files
extensions/postgres/env.tsConnInfo.password?: string;parseConnUrl()carriesparsed.password || undefinedextensions/postgres/index.tsPgpassLookup,resolvePassword(),buildPoolConfig(); factory nownew pg.Pool(buildPoolConfig(connInfo)); removed the invalidpasswordProviderextensions/postgres/env.test.tsparseConnUrland preserved inextractConnInfoextensions/postgres/index.test.tsresolvePassword(URL authoritative, pgpass fallback, miss→undefined, no user/db skip) andbuildPoolConfig(config handed topg)extensions/postgres/README.mdCloses #281