Establish complete PostgreSQL request context across Graphile execution - #1744
Draft
Zetazzz wants to merge 2 commits into
Draft
Establish complete PostgreSQL request context across Graphile execution#1744Zetazzz wants to merge 2 commits into
Zetazzz wants to merge 2 commits into
Conversation
Zetazzz
force-pushed
the
feat/complete-graphile-request-context
branch
from
August 16, 2026 14:02
f0b8184 to
d9eb179
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This combines planning items F02, F13, and F16 into one atomic request-context correction on top of #1716.
@constructive-io/express-contextnow owns a canonical, completepgSettingscontract;pg-query-contextapplies all settings in one parameterized PostgreSQL round trip with transaction-local semantics.@dataplan/pgquery-config contract.PublicKeySignaturederives a fresh anonymous execution context by copying the complete request settings and replacing onlyrolewith the configured anonymous role.req.constructive.pgSettingsinstead of reconstructing a second, incomplete settings object. Unauthenticated identity-bearing private headers remain inert until a separate authenticated internal-ingress boundary owns their translation.graphile.introspectionDependencySchemasare wired into the canonical requestsearch_pathalongside the resolved API schemas.Planning: constructive-io/constructive-planning#1693
Ownership and security contract
packages/express-contextowns the request facts and canonical builder. Every request gets a fresh object containing all supported security GUCs, with absent claims represented by empty strings, plus explicitrole,request.id,transaction_read_only,search_path, androw_securityvalues.Trusted overrides are restricted to the declared security-GUC allowlist and reject accessors, symbols, arrays, nulls, non-string values, and PostgreSQL session controls such as role/search path/read-only/RLS. This PR does not translate caller-controlled identity headers into trusted claims; that requires the separately authenticated internal-ingress boundary excluded below.
postgres/pg-query-contextowns application to PostgreSQL. Non-empty pooled context cannot be combined withskipTransaction; settings and callback failures roll back and release without replacing the original error. The direct algorithmic change is:Ordinary Graphile lanes use the exact canonical object. The PublicKey lane creates a copy and changes only
role; API/database/request identity, search path, RLS, read-only state, and empty-claim clearing are retained.F13 package changes
graphile-i18n: requestwithPgClient+ completepgSettings, native query-config execution, deterministic fail-closed behavior.graphile-llm: RAG and metering request lanes use the complete context; metadata queries use native query configs and preserve database errors while treating only absent optional module relations as unprovisioned.graphile-bulk-mutations: insert/upsert/update/delete callbacks use typed nativePgClientqueries.graphile-test: applies derivative settings in the existing test transaction and restores the primary request context, enabling behavior-level role isolation tests.No storage plugins were changed.
Schema and behavior
Validation
Passed:
pnpm install --frozen-lockfile@constructive-io/graphql-types@constructive-io/graphql-env@constructive-io/express-contextpg-query-contextgraphile-testgraphile-bulk-mutationsgraphile-i18ngraphile-llmgraphile-settings@constructive-io/graphql-servergraphile.tsremains)git diff --check@constructive-io/graphql-env: 9 tests / 1 snapshot@constructive-io/express-context: 38 testspg-query-context: 10 tests, including real PostgreSQL transaction-local restoration plus COMMIT and ROLLBACK restoration of a non-empty baseline on one reused backend@constructive-io/graphql-server: 151 testsgraphile-settingsreal Graphile/PostgreSQL request-context integration: 2 testsgraphile-test: 21 tests / 12 snapshotsgraphile-bulk-mutationsnative PgClient owner tests: 2 testsgraphile-i18n: 10 tests, including real PostgreSQL/Graphile behaviorgraphile-llmrequest-context owner tests: 8 testsgraphile-settingsPublicKey owner + real Graphile/PostgreSQL integration: 21 testsThe real integration executes, in sequence, authenticated and anonymous GraphQL requests, an i18n plugin query, a PublicKey anonymous-role query, a forced rollback, and a post-rollback request. It verifies
current_user, user/API/database/request GUCs, read-only state, RLS, search path, no authenticated-to-anonymous leakage, anonymous role derivation, and rollback isolation.Not counted as passed:
anonymouslacks usage on itsbulk_testschema. This PR does not change fixture/application grants; the changed native client contract is covered by owner tests and the combined real Graphile integration.Explicit exclusions
This does not include F01 runtime identity, F10 checkout sanitation, F14 storage snapshots/isolation, F07 SQL qualification, F08 cache ownership, F15 storage wiring, F17 build contracts, F18 admission or authenticated internal-ingress claims, scoped introspection behavior, build-state retirement, notification broker, pg-many-to-many, pnpm patches, Crystal/upstream changes, or performance-harness extensions.