Skip to content

fix(antseed): parse a libpq kv-conninfo DATABASE_URL in the node writers#39

Closed
jmlago wants to merge 1 commit into
mainfrom
fix-antseed-pg-conninfo
Closed

fix(antseed): parse a libpq kv-conninfo DATABASE_URL in the node writers#39
jmlago wants to merge 1 commit into
mainfrom
fix-antseed-pg-conninfo

Conversation

@jmlago

@jmlago jmlago commented Jun 29, 2026

Copy link
Copy Markdown
Member

The bug (live in prod after #38)

After the host-store flip, the antseed sidecar can't reach Postgres:

write-market: getaddrinfo ENOTFOUND base
write-status: getaddrinfo ENOTFOUND base

peer_offers / buyer_status stay empty → antseed marketplace degraded (fail-soft to other providers).

Root cause: the prod DATABASE_URL secret is a libpq keyword/value conninfo (host=… port=… dbname=… user=… password='…' sslmode=require) — chosen in the infra wiring (#165) to dodge password percent-encoding, and the form psycopg uses on the router/ingress. But the sidecar is node-postgres, whose connectionString only parses a postgres:// URL — it mis-reads the conninfo and resolves host base.

The fix

store.pgConfig(): pass a URL through untouched (dev/compose), otherwise parse the kv conninfo into a node-postgres config object (dbnamedatabase, sslmodessl). write-market.js / write-status.js / control.js use it.

Verified: pgConfig() parses the prod-shaped conninfo correctly and passes URLs through; write-market.js with a kv-conninfo DATABASE_URL writes peer_offers against the compose Postgres. Node-only change (router/ingress psycopg path unaffected).

Follow-up to #38.

Summary by CodeRabbit

  • Bug Fixes
    • Improved database connection handling so tools can work with a wider range of PostgreSQL connection settings.
    • Status and marketplace data writes now use the same connection configuration path, reducing connection-related failures.
    • Added more robust validation and error reporting when processing incoming marketplace data.

The prod secret hands DATABASE_URL as a libpq KEYWORD/VALUE conninfo
(host=… port=… dbname=… user=… password='…' sslmode=require) — the form psycopg
uses on the router/ingress. node-postgres's `connectionString` only parses a
postgres:// URL, so the sidecar resolved host "base" and died with ENOTFOUND,
leaving peer_offers / buyer_status empty after the host-store flip (#38).

Add store.pgConfig(): pass a URL through (dev/compose), otherwise parse the kv
conninfo into a pg config object (sslmode -> ssl). write-market.js, write-status.js
and control.js use it. Verified: write-market.js writes peer_offers against a
kv-conninfo DATABASE_URL pointed at the compose Postgres.
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

antseed/store.js adds and exports a pgConfig() function that reads DATABASE_URL and returns either a connectionString object (for URL-form values) or a parsed libpq key=value conninfo object. Three scripts—control.js, write-market.js, and write-status.js—replace their inline DATABASE_URL Pool/Client construction with pgConfig().

Changes

pgConfig helper and adoption

Layer / File(s) Summary
pgConfig implementation and export
antseed/store.js
Adds pgConfig() that reads process.env.DATABASE_URL, passes URL-form values through as { connectionString }, and parses libpq key=value conninfo strings into a pg config object with sslmode translation. Exports it alongside existing exports.
Adopt pgConfig in all antseed scripts
antseed/control.js, antseed/write-market.js, antseed/write-status.js
Each script adds pgConfig to its ./store.js import and passes pgConfig() to new Pool()/new Client() instead of { connectionString: process.env.DATABASE_URL }.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • genlayerlabs/unhardcoded#38: Directly touches the same antseed/control.js and antseed/write-status.js DB connection setup that this PR refactors.

Poem

A bunny dug through conninfo ground,
Where KEY=VALUE pairs were found.
No more raw URLs alone—
pgConfig makes the settings known.
🐇 One helper, three scripts, all aligned!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main fix: parsing libpq-style DATABASE_URL handling in the node writers.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-antseed-pg-conninfo

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Biome (2.5.0)
antseed/control.js

File contains syntax errors that prevent linting: Line 30: Illegal return statement outside of a function


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@antseed/store.js`:
- Line 27: The DSN check currently uses a generic substring test, which can
misclassify libpq conninfo strings when a quoted value contains “://”. Update
the DSN normalization logic in the store helper to detect URLs by anchoring on
the actual scheme at the start of the string, and only return {
connectionString: dsn } for real URI-style DSNs while leaving key/value conninfo
untouched.
- Line 40: The pgConfig() sslmode handling in store.js is too permissive because
every value other than "disable" is downgraded to { rejectUnauthorized: false },
which breaks stricter modes. Update the sslmode branch in pgConfig() to either
map each supported mode explicitly (including verify-ca and verify-full with
proper certificate verification behavior) or throw/reject unsupported values
instead of silently disabling verification.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e5bdb976-1253-4e73-8e32-6cae3a43aa84

📥 Commits

Reviewing files that changed from the base of the PR and between 9d576f5 and dd9b183.

📒 Files selected for processing (4)
  • antseed/control.js
  • antseed/store.js
  • antseed/write-market.js
  • antseed/write-status.js

Comment thread antseed/store.js
// dies with ENOTFOUND, leaving peer_offers/buyer_status empty.
function pgConfig() {
const dsn = process.env.DATABASE_URL || "";
if (!dsn || dsn.includes("://")) return { connectionString: dsn };

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Anchor URL detection to the DSN scheme.

dsn.includes("://") misclassifies valid libpq conninfo if a quoted value contains ://, such as a generated password. That would send the whole key/value string back through connectionString and reintroduce the connection failure this helper is meant to avoid.

Proposed fix
-  if (!dsn || dsn.includes("://")) return { connectionString: dsn };
+  if (!dsn || /^[a-z][a-z0-9+.-]*:\/\//i.test(dsn.trimStart())) {
+    return { connectionString: dsn };
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!dsn || dsn.includes("://")) return { connectionString: dsn };
if (!dsn || /^[a-z][a-z0-9+.-]*:\/\//i.test(dsn.trimStart())) {
return { connectionString: dsn };
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@antseed/store.js` at line 27, The DSN check currently uses a generic
substring test, which can misclassify libpq conninfo strings when a quoted value
contains “://”. Update the DSN normalization logic in the store helper to detect
URLs by anchoring on the actual scheme at the start of the string, and only
return { connectionString: dsn } for real URI-style DSNs while leaving key/value
conninfo untouched.

Comment thread antseed/store.js
else if (key === "dbname") cfg.database = val;
else if (key === "user") cfg.user = val;
else if (key === "password") cfg.password = val;
else if (key === "sslmode") cfg.ssl = val === "disable" ? false : { rejectUnauthorized: false };

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check whether repository-managed DATABASE_URL examples or manifests use stricter sslmode values.
rg -n "sslmode=(verify-ca|verify-full|require|disable|prefer|allow)" .

Repository: genlayerlabs/unhardcoded

Length of output: 263


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== antseed/store.js (relevant section) ==\n'
cat -n antseed/store.js | sed -n '1,140p'

printf '\n== Search for sslmode handling and postgres URL usage ==\n'
rg -n "sslmode|DATABASE_URL|postgres://|postgresql://" antseed -g '!**/node_modules/**' || true

printf '\n== Search for any code paths that distinguish verify-ca / verify-full ==\n'
rg -n "verify-ca|verify-full|rejectUnauthorized|ssl\s*=" antseed -g '!**/node_modules/**' || true

Repository: genlayerlabs/unhardcoded

Length of output: 3717


Fail closed for stricter sslmode values. pgConfig() maps every non-disable value to { rejectUnauthorized: false }, so verify-ca and verify-full would silently lose certificate verification. Either preserve those modes or reject unsupported values instead of downgrading them.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@antseed/store.js` at line 40, The pgConfig() sslmode handling in store.js is
too permissive because every value other than "disable" is downgraded to {
rejectUnauthorized: false }, which breaks stricter modes. Update the sslmode
branch in pgConfig() to either map each supported mode explicitly (including
verify-ca and verify-full with proper certificate verification behavior) or
throw/reject unsupported values instead of silently disabling verification.

@jmlago

jmlago commented Jun 29, 2026

Copy link
Copy Markdown
Member Author

superseded by #40

@jmlago jmlago closed this Jun 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant