Party GUCs leak across pooled database connections in the service layer

Table of Contents

This page is a capture in the inbox bucket of the product backlog — a pre-sprint idea, not yet pulled into a sprint as a story.

1. What

The service layer sets the RLS session GUCs (app.current_tenant_id, app.visible_party_ids, app.current_party_id) per request on its pooled database connections. A request whose authenticated context carries no party does not reset the GUCs an earlier party-context request left on the pooled connection it lands on, so a party-scoped-row read (list, history, count) returns different results depending on which pooled connection serves it - pool roulette.

Observed 2026-09-08 during the synthetic bind's live CRUD system test: the same ores.shell session (same JWT) listed 26 party-scoped fx_spot_generation_config rows through one pooled connection and 0 through another minutes later; the RLS policies and data were verified correct by running the same read as the service role with the explicit GUCs (11 folders / 26 fx spot rows returned).

2. Why

Read visibility under the party-isolation RLS policies becomes non-deterministic for any caller whose requests mix party and non-party contexts on the service pool: the qt client switching parties, the shell (which has no party context at all), and the services themselves. Rows written without a party context (stamped with the nil uuid) are also permanently invisible to every party-restricted session. The fix belongs in the per-request context application (ores.service make_request_context / the ores.database connection layer): reset or locally scope all three GUCs on every checkout (e.g. set_config(..., true) inside the request transaction) instead of leaving them stuck to the pooled connection.

3. References

  • projects/ores.service/src/service/request_context.cpp (party context from JWT claims)
  • projects/ores.sql/create/synthetic/synthetic_rls_policies_create.sql (the policies whose select visibility flapped)
  • The synthetic bind task's live system test record (entity-classification-drift-synthetic/task_bind-synthetic-entities-to-profiles.org)

4. See also

Emacs 29.3 (Org mode 9.6.15)