{"record":{"id":"fbc461593c3ba05d","repo":"JuliusBrussee/caveman","slug":"postgres-resolver-isolation-incomplete-s","errorCode":null,"errorMessage":"postgres: resolver isolation incomplete: %s","messagePattern":"postgres: resolver isolation incomplete: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"shared/platform/postgresconfig/postgresconfig.go","lineNumber":756,"sourceCode":"\t\t\tJOIN pg_attribute org_col ON org_col.attrelid=c.oid\n\t\t\t  AND org_col.attname='organization_id' AND NOT org_col.attisdropped\n\t\t\tWHERE n.nspname='public' AND c.relkind IN ('r','p')\n\t\t\t  AND has_table_privilege(rr.role_name, c.oid, 'SELECT,INSERT,UPDATE,DELETE')\n\t\t\t  AND NOT EXISTS (\n\t\t\t    SELECT 1 FROM pg_policy policy\n\t\t\t    WHERE policy.polrelid=c.oid\n\t\t\t      AND role.oid=ANY(policy.polroles)\n\t\t\t      AND policy.polqual IS NOT NULL\n\t\t\t      AND policy.polwithcheck IS NOT NULL\n\t\t\t  )\n\t\t)\n\t\tSELECT coalesce(string_agg(violation, '; ' ORDER BY violation), '') FROM violations\n\t`).Scan(&violations)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"postgres: inspect resolver schema: %w\", err)\n\t}\n\tif violations != \"\" {\n\t\treturn fmt.Errorf(\"postgres: resolver isolation incomplete: %s\", violations)\n\t}\n\treturn nil\n}\n\n// WithOrg runs fn inside a transaction whose tenant GUC is transaction-local.\n// Empty scopes are rejected: tenant work must never degrade to an unscoped\n// query when RLS is the hard boundary.\nfunc WithOrg(ctx context.Context, pool *pgxpool.Pool, orgID string, fn func(pgx.Tx) error) error {\n\torgID = strings.TrimSpace(orgID)\n\tif orgID == \"\" {\n\t\treturn errors.New(\"postgres: organization scope is required\")\n\t}\n\ttx, err := pool.Begin(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer func() { _ = tx.Rollback(ctx) }()\n\tif _, err := tx.Exec(ctx, `SELECT set_config('app.current_organization_id', $1, true)`, orgID); err != nil {","sourceCodeStart":738,"sourceCodeEnd":774,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/shared/platform/postgresconfig/postgresconfig.go#L738-L774","documentation":"validateResolverSchema aggregates a list of resolver-isolation violations from a catalog query (SQL-level RLS policy checks, e.g. policies lacking polwithcheck). If the aggregated violation string is non-empty, the schema fails validation with the violation list embedded in the message. Like its tenant-schema sibling, this is a deliberate guard ensuring row-level security is correctly configured before the pool starts.","triggerScenarios":"NewRuntimePool → ValidateTenantSchema → validateResolverSchema: the SQL finds resolver tables whose RLS policies are missing, not FORCE, or missing WITH CHECK clauses — the violations string is non-empty.","commonSituations":"Migrations applied but RLS policies created incompletely (e.g. CREATE POLICY without WITH CHECK); someone dropped or altered a policy; enabling RLS manually on a new resolver table without the full policy set; restoring a dump that lost policy definitions.","solutions":["Parse the semicolon-joined violations in the message to see which tables/policies are deficient","Recreate the policies per the library's requirements, including WITH CHECK clauses (e.g. ALTER TABLE ... ENABLE ROW LEVEL SECURITY; CREATE POLICY ... WITH CHECK ...)","Re-run the project's schema migrations to restore canonical policies","Confirm the policies are applied for the role the pool connects as, then retry NewRuntimePool"],"exampleFix":"// before: policy without WITH CHECK -> violation reported\nCREATE POLICY resolver_isolation ON resolver.t FOR SELECT USING (org_id = current_setting('app.current_organization_id')::uuid);\n// after: include WITH CHECK\nCREATE POLICY resolver_isolation ON resolver.t FOR ALL USING (org_id = current_setting('app.current_organization_id')::uuid) WITH CHECK (org_id = current_setting('app.current_organization_id')::uuid);","handlingStrategy":"validation","validationCode":"// detect policies missing WITH CHECK before startup\nSELECT schemaname, tablename, policyname FROM pg_policies WHERE schemaname='resolver' AND (polwithcheck IS NULL OR polroles IS NULL);","typeGuard":null,"tryCatchPattern":"if err := NewRuntimePool(ctx, cfg); err != nil {\n    if strings.Contains(err.Error(), \"resolver isolation incomplete\") {\n        log.Fatalf(\"RLS policy drift on resolver schema, re-run migrations: %v\", err)\n    }\n    return err\n}","preventionTips":["Create every RLS policy with both USING and WITH CHECK clauses","Manage policies only through migrations; audit pg_policies after restores","Add an integration test asserting resolver policy definitions post-migrate"],"tags":["postgres","row-level-security","tenant-isolation","policy"],"backgroundTag":"schema-validation-failed","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}