Skip to content

Establish complete PostgreSQL request context across Graphile execution - #1744

Draft
Zetazzz wants to merge 2 commits into
test/performance-harness-corefrom
feat/complete-graphile-request-context
Draft

Establish complete PostgreSQL request context across Graphile execution#1744
Zetazzz wants to merge 2 commits into
test/performance-harness-corefrom
feat/complete-graphile-request-context

Conversation

@Zetazzz

@Zetazzz Zetazzz commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Summary

This combines planning items F02, F13, and F16 into one atomic request-context correction on top of #1716.

  • F02: @constructive-io/express-context now owns a canonical, complete pgSettings contract; pg-query-context applies all settings in one parameterized PostgreSQL round trip with transaction-local semantics.
  • F13: Graphile i18n and LLM request-lane SQL now consume the existing complete Grafast request context and fail closed when it is missing. Bulk mutation SQL uses the native @dataplan/pg query-config contract.
  • F16: PublicKeySignature derives a fresh anonymous execution context by copying the complete request settings and replacing only role with the configured anonymous role.
  • The GraphQL server consumes req.constructive.pgSettings instead of reconstructing a second, incomplete settings object. Unauthenticated identity-bearing private headers remain inert until a separate authenticated internal-ingress boundary owns their translation.
  • Ordered graphile.introspectionDependencySchemas are wired into the canonical request search_path alongside the resolved API schemas.

Planning: constructive-io/constructive-planning#1693

Ownership and security contract

packages/express-context owns 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 explicit role, request.id, transaction_read_only, search_path, and row_security values.

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-context owns application to PostgreSQL. Non-empty pooled context cannot be combined with skipTransaction; settings and callback failures roll back and release without replacing the original error. The direct algorithmic change is:

N per-setting SQL round trips -> 1 parameterized settings round trip

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: request withPgClient + complete pgSettings, 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 native PgClient queries.
  • 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

  • Public GraphQL SDL is unchanged.
  • A real schema introspection contract verifies the three existing PublicKey mutation names, arguments, and return types.
  • Signature verification remains behind its existing feature flag; this PR does not enable it or change that behavior.
  • The active PublicKey signup/challenge paths use the common anonymous helper. Disabled verification/failure-recording behavior is intentionally not activated here.

Validation

Passed:

  • pnpm install --frozen-lockfile
  • CJS and ESM builds for the affected GraphQL server dependency closure, including:
    • @constructive-io/graphql-types
    • @constructive-io/graphql-env
    • @constructive-io/express-context
    • pg-query-context
    • graphile-test
    • graphile-bulk-mutations
    • graphile-i18n
    • graphile-llm
    • graphile-settings
    • @constructive-io/graphql-server
  • targeted lint: 0 errors (the existing unused-variable warning in graphile.ts remains)
  • git diff --check
  • @constructive-io/graphql-env: 9 tests / 1 snapshot
  • @constructive-io/express-context: 38 tests
  • pg-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 tests
  • graphile-settings real Graphile/PostgreSQL request-context integration: 2 tests
  • previously validated owner/integration suites retained by this branch:
    • graphile-test: 21 tests / 12 snapshots
    • graphile-bulk-mutations native PgClient owner tests: 2 tests
    • graphile-i18n: 10 tests, including real PostgreSQL/Graphile behavior
    • graphile-llm request-context owner tests: 8 tests
    • graphile-settings PublicKey owner + real Graphile/PostgreSQL integration: 21 tests

The 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:

  • The legacy bulk mutation integration fixture currently reaches PostgreSQL but fails because anonymous lacks usage on its bulk_test schema. This PR does not change fixture/application grants; the changed native client contract is covered by owner tests and the combined real Graphile integration.
  • The complete LLM integration suite requires its external Ollama model. Request-context owner tests, CJS/ESM builds, and lint pass without treating that external dependency as a successful test.

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.

@Zetazzz
Zetazzz force-pushed the feat/complete-graphile-request-context branch from f0b8184 to d9eb179 Compare August 16, 2026 14:02
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