Expand description
The PostgreSQL wire protocol, served over a program’s read models.
docs/05-tier-lowering.md §5.3 asks for “pgwire access
for the outside world: psql, BI tools, DBeaver see materialized views as ordinary tables — the
single cheapest trust-builder for adopting teams”, and
07 §7.2 files it under external-tool compatibility
with no alternative listed. [beck_core::read] is what the tables are; this is the socket.
§Why it is written here rather than taken
There are crates that implement this protocol server-side. What they carry is the rest of a
database — a type registry, an extended-protocol state machine over prepared statements with
parameters, portals that suspend — and a read model has none of those to expose. What is
actually needed is the startup exchange, the simple query, the extended query with no
parameters, and four type OIDs a driver already knows. That is this file, and it adds no
dependency to a workspace whose §7.9 pins everything
(adr/0020).
§What it deliberately does not do
- No authentication. It answers
AuthenticationOkto everyone, which is whyserverefuses to bind anywhere but the loopback interface. An unauthenticated read of an application’s whole state must not be reachable from another host, and a flag that turns that off is a decision with an ADR rather than a convenience. - No TLS. The same reason and the same bound.
- No writes. The log is the only way state changes; a read model that accepted an
insertwould be a second way, which is the property01§1.1 is about.
§pg_catalog, and why it is not here either
psql’s \d sends a join against four catalogue relations, and those relations are read
models: [beck_core::pg] derives pg_class, pg_namespace, pg_attribute and the rest from
the same [Schema] this file serves, and they are scanned, filtered and joined by the
operators every other query goes through. Nothing in this file knows what a backslash command
is. A catalogue answered by matching the query text would be a second query path — one that
could drift from the schema, and one no select could reach — where this one cannot disagree
with the schema because it is the schema under another set of column names.
\d, \d <table>, \dt, \dn and \l are what that answers. Anything else asks for an
object a read model does not have — a function, a role, an index — and is refused by the name
of the relation it asked for ([beck_core::pg::Rel::missing]) rather than by an empty answer.
[beck_core::read::Schema::CATALOGUE] is still the table that says what a read model is
derived from, which is the question pg_catalog has no column for.