PostgreSQL libpq dependency review¶
This note records the dependency review for adding PostgreSQL support through
libpq, the PostgreSQL project-owned C client library.
Decision¶
libpq is accepted as the PostgreSQL client dependency for Merovingian. It is
wrapped inside the database module and must not leak PGconn, PGresult, or
other libpq-specific types into homeserver services.
Why it is needed¶
PostgreSQL is the intended production database backend. Speaking the PostgreSQL
wire protocol directly would be high-risk, unauditable project code. libpq is
the native PostgreSQL client API, is packaged by supported Linux and BSD
distributions, and gives the project a stable interface for connection
management, parameterized execution, and PostgreSQL error reporting.
Security boundary¶
- Connection strings are accepted only in explicit PostgreSQL URI or libpq key/value form.
- Connection-opening diagnostics use a fixed redacted identity and generic parser/connection-status refusal reasons, not a reconstructed option summary or forwarded library error text. Host/database values are suppressed too. Actual DEBUG-console and returned-diagnostic confidentiality checks cover malformed quoted input and policy-admitted private missing-socket failures; they do not establish general SQL-result error or live authentication/TLS confidentiality. See ADR-0139.
PGconnownership is RAII-managed withPQfinish.PGresultownership is RAII-managed withPQclear.- Statement execution uses
PQexecParamsso parameter values stay separate from SQL command text. - Existing project statement-name, SQL-shape, and placeholder validation still runs before libpq execution.
- Runtime startup uses PostgreSQL only when a URI file is explicitly present; otherwise existing in-memory test flows remain isolated from ambient databases.
- Runtime startup requires
database.role=runtime; offline migration planning requiresdatabase.role=migration.
Maintenance and platform posture¶
libpq is resolved from the operating-system PostgreSQL client package and
linked dynamically. The top-level Meson dependency sets allow_fallback: false,
so clean builds must provide libpq.pc through the host package manager even
when the wrapper scripts use Meson's forcefallback mode for other
dependencies. There is no subprojects/libpq.wrap
(ADR-0218).
Supported development paths install the OS development package explicitly:
Debian-family hosts use libpq-dev, Fedora-family hosts use libpq-devel,
FreeBSD uses postgresql17-client, OpenBSD uses postgresql-client, and
NetBSD/pkgsrc uses postgresql17-client.
License¶
PostgreSQL libpq is released under the PostgreSQL license (SPDX: PostgreSQL).
It is compatible with Merovingian's GPL-3.0-or-later distribution and is
resolved from the operating-system PostgreSQL client package.
Current limitations¶
- Live integration tests against a temporary PostgreSQL server are gated by
MEROVINGIAN_TEST_POSTGRESQL_URI. - Separate PostgreSQL users/grants for runtime and migration roles are enforced
at connection time:
open_postgresql_persistent_store()(src/database/postgresql_store.cpp) runsSET ROLEto the configured migration role before applying any DDL and to the runtime role before serving traffic, refusing to open the store if either role cannot be assumed. This depends on the two roles existing and owning the schema objects — provision them withpackaging/postgresql/provision-roles.sqlbefore pointingdatabase.migration_role/database.runtime_roleat a deployment.
Source references¶
- PostgreSQL libpq connection control documentation.
- PostgreSQL libpq command execution documentation.