Skip to content

Establish exact PostgreSQL identities and notification lifecycle - #1754

Draft
Zetazzz wants to merge 5 commits into
agent/pg-checkout-sanitationfrom
feat/exact-pg-identity-notification-broker
Draft

Establish exact PostgreSQL identities and notification lifecycle#1754
Zetazzz wants to merge 5 commits into
agent/pg-checkout-sanitationfrom
feat/exact-pg-identity-notification-broker

Conversation

@Zetazzz

@Zetazzz Zetazzz commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements planning items F01 and F12 as one PostgreSQL trust-boundary change:

  • derives process-local, keyed identities from the complete connection reuse contract;
  • adds lease-aware pool ownership, capacity admission, deterministic teardown, and opaque diagnostics;
  • adds optional runtime/control credential separation without changing unconfigured deployments;
  • adds a dedicated notification listener role attestation contract;
  • adds an exact-topic, bounded-queue PostgreSQL notification broker with awaited teardown.

F12 is included with F01 because the notification broker is the first long-lived consumer of exact pool identity and leases. This PR is stacked on #1752 and preserves its default TCP checkout sanitation contract.

Planning issue: https://github.com/constructive-io/constructive-planning/issues/1693

Architecture and behavior

Exact identities and leases

Pool identity includes driver generation, host, port, database, login credential, complete serializable TLS contract, pool policy, connection purpose, and checkout contract. The identity is an opaque process-local HMAC, so cache keys and diagnostics do not expose connection URLs or provide a portable password verifier.

acquirePgPool returns an exact identity, pool, and idempotent release claim. Leased pools are not eligible for LRU/TTL eviction. Admission fails closed when capacity cannot be reclaimed safely, and teardown waits for all detached pool disposal work.

The compatibility getPgPool API remains available. Database-name cleanup aliases are retained for existing code-generation and Graphile cleanup callers during the migration to opaque identities.

Optional runtime credentials

The configuration contract now supports a static runtime login bound to an exact route identity, or a resolver that receives only frozen, credential-free route facts. Returned credentials must explicitly include database, user, and password; the database must match the routed physical database. Resolver/configuration failures never fall back to the control credential.

When neither runtime path is configured, the existing single-login behavior remains unchanged. Request-owned runtime and control pool leases are released idempotently on finish, close, abort, and partial acquisition failure.

Notification role and broker

The notification broker exposes exact broker and physical database target identities, frozen exact topic allowlists, per-topic subscription, an observed terminated promise, role revalidation, and idempotent awaited release.

Topic validation rejects empty, NUL-containing, malformed surrogate, and over-63-byte PostgreSQL identifiers without Unicode normalization. Subscriber queues are bounded; an overflow terminates only the slow subscriber. Fatal listener failures are latched and delivered to all owners without silent reconnect.

The dedicated listener login is audited on the same pinned client before LISTEN. The audit checks exact session/current user/database identity, login and NOINHERIT posture, prohibited role attributes and memberships, database ownership/privileges, and application schema/relation/function/sequence privileges. Audit results are frozen and credential-free.

Topic ownership is reference counted. Final release waits for UNLISTEN, destroys uncertain clients, releases the pool lease, and aggregates cleanup failures while still attempting remaining cleanup.

#1752 compatibility

  • The default node-postgres factory still installs the existing DISCARD ALL checkout sanitizer exactly once.
  • No sanitation option or opt-out is introduced.
  • Registered custom factories retain their existing factory-owned checkout semantics and receive a distinct driver identity.
  • The production notification listener is acquired through the default sanitized pool path.
  • The Sanitize reused PostgreSQL connections at checkout #1752 sanitation regression suite and real PostgreSQL request-boundary test pass.

Explicit exclusions

This is lower-level infrastructure only. It does not enable shared realtime or wire notification credentials into GraphQL/server middleware. It excludes F05, F18, F21, F22, F24, F25, F26, and F44, plus scoped introspection, build-state retirement, Graphile cache governance, and pg-many-to-many changes.

Validation

  • pnpm install --frozen-lockfile
  • pg-env: 5 tests; CJS/ESM build; lint
  • pg-cache: 108 unit tests passed, 4 integration tests gated in the normal unit run; CJS/ESM build; lint
  • dedicated real PostgreSQL notification run: 2 suites / 4 tests passed, including safe/unsafe role audit, real LISTEN/NOTIFY, shared listener ownership, UNLISTEN/teardown, and clean next-generation PID/topic state
  • graphql-types: no package tests present; CJS/ESM build; lint
  • graphql-env: 12 tests / 2 suites; CJS/ESM build; lint
  • express-context: 47 tests / 5 suites; CJS/ESM build; lint
  • pg-query-context: 13 tests / 2 suites, including real checkout sanitation regression; CJS/ESM build
  • graphql-server: 151 tests / 14 suites; CJS/ESM build
  • Prettier checks for all new files and git diff --check

Lint has one pre-existing unrelated warning in packages/express-context/src/loaders/identity-providers.ts (moduleName is unused); there are no lint errors.

pnpm policy:check is currently blocked only by repository-wide expired exceptions unrelated to this diff: @typescript-eslint/eslint-plugin and @typescript-eslint/parser (2026-08-17), and @types/semver (2026-08-16). This PR does not change those dependencies.

Remaining integration and risk

  • F24 must consume this broker and define realtime generation wiring; this PR deliberately leaves it inactive.
  • F18 must add the production runtime privilege gate; this PR defines credential separation but does not claim runtime role attestation.
  • Listener role provisioning must satisfy the strict role contract before the broker admits a lease.
  • The identity HMAC is intentionally process-local; identities are diagnostic/cache handles, not durable cross-process identifiers.

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