Skip to content

fix: switch RLS module query from metaschema table to services_public.api_modules#767

Merged
pyramation merged 4 commits intomainfrom
rls/rls-module-fix
Mar 4, 2026
Merged

fix: switch RLS module query from metaschema table to services_public.api_modules#767
pyramation merged 4 commits intomainfrom
rls/rls-module-fix

Conversation

@pyramation
Copy link
Copy Markdown
Contributor

@pyramation pyramation commented Mar 2, 2026

fix: switch RLS module query from metaschema table to services_public.api_modules

Summary

The server's RLS module resolution queried metaschema_modules_public.rls_module, which only contains a single row for the public API. This caused all other authenticated APIs (admin, auth, app, objects) to resolve rlsModule=undefined and skip authentication entirely.

This PR switches both api.ts and upload.ts to query services_public.api_modules WHERE name = 'rls_module', which has entries for all authenticated APIs. The RlsModule TypeScript type is expanded from 3 optional fields to 8 required fields, parsed from the JSONB data column.

Updates since last revision

Simplified api.ts to read schema names directly from JSONB — the JOIN workaround through metaschema_modules_public.rls_modulemetaschema_public.schema has been removed from api.ts. The query is now a simple SELECT data FROM services_public.api_modules WHERE api_id = $1 AND name = 'rls_module', and toRlsModule reads d.authenticate_schema and d.role_schema directly.

⚠️ Requires companion DB fix: This simplification depends on constructive-db#554, which fixes the api_modules.sql migration to derive schema names from metaschema_public.schema (the single source of truth) instead of hardcoding dashed names in JSONB. Without that DB fix deployed first, api.ts will read dashed schema names from JSONB and fail.

Note: upload.ts still uses the JOIN workaround to resolve correct PG schema names independently of the DB fix. This inconsistency between api.ts (direct JSONB read) and upload.ts (JOIN-based resolution) should be reconciled — ideally by simplifying upload.ts to match api.ts once the DB fix is deployed.

Key changes:

  • api.ts: RLS_MODULE_SQL is now a simple query against services_public.api_modules; toRlsModule reads schema names directly from JSONB data
  • upload.ts: All three fallback queries (BY_DATABASE_ID, BY_API_ID, BY_DBNAME) query services_public.api_modules with JOINs to resolve PG schema names
  • types.ts: RlsModule fields are now required; added publicSchema, currentRole, currentRoleId, currentIpAddress, currentUserAgent
  • upload.ts: Removed SAFE_IDENTIFIER regex check (redundant with escapeIdentifier() already used in the query)

Review & Testing Checklist for Human

  • Deploy ordering: constructive-db#554 must be deployed before this PR. api.ts reads d.authenticate_schema and d.role_schema directly from JSONB. The current JSONB has dashed names (constructive-auth-private); the DB fix changes them to underscored names (constructive_auth_private) matching actual PG schemas. Deploying this server PR first will break authentication on api.ts codepath.
  • Inconsistency: api.ts vs upload.ts schema resolution. api.ts reads schema names from JSONB directly (simple, assumes DB fix deployed). upload.ts JOINs to metaschema_public.schema to resolve schema names (defensive, works pre-DB-fix). Consider simplifying upload.ts to match api.ts once DB fix is confirmed deployed.
  • Brittle fallback in upload.ts. Line 259: publicSchema: { schemaName: row.public_schema_name ?? d.role_schema } — if public_schema_name is NULL, falls back to JSONB value with dashes. Verify whether publicSchema.schemaName is used in downstream SQL (if so, fallback would break).
  • End-to-end test against the hub. The unit tests pass (all 11), but the original failure was in the constructive-hub Playwright integration tests (login.spec.ts — "new user can create account" / Organizations heading not visible after signup). Run the hub tests to confirm authentication works on auth.localhost, admin.localhost, app.localhost, and objects.localhost.
  • Verify api_modules.data JSONB always has all 8 fields populated. The TypeScript types declare them as required string, but there is no runtime validation. Query a representative sample: SELECT data FROM services_public.api_modules WHERE name = 'rls_module' and verify all 8 keys are present in every row.

Notes

  • Test assertions in upload.test.ts were loosened from specific WHERE clause checks to generic expect.stringContaining('WHERE') — not ideal but acceptable since the queries are simple.
  • The new fields (publicSchema, currentRole, etc.) are exposed on the type but not yet consumed by downstream code (auth.ts, graphile.ts). They are forward-compatible additions.
  • Devin Session
  • Requested by @pyramation

….api_modules

- RLS_MODULE_SQL in api.ts now queries services_public.api_modules
  WHERE name='rls_module' instead of metaschema_modules_public.rls_module
  (which only had 1 row for the public API)
- RlsModule type enriched with all 8 required fields from JSONB data:
  authenticate, authenticateStrict, privateSchema, publicSchema,
  currentRole, currentRoleId, currentIpAddress, currentUserAgent
- upload.ts RLS module queries also switched to services_public.api_modules
- Removed SAFE_IDENTIFIER regex (redundant with escapeIdentifier)
- Updated upload tests to match new JSONB data shape
@devin-ai-integration
Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

…vs-underscores mismatch

The api_modules JSONB data stores schema names with dashes (e.g. constructive-auth-private)
but the actual PostgreSQL schemas use underscores (constructive_auth_private). The old query
got the correct PG name via a direct JOIN on metaschema_public.schema.schema_name.

This fix JOINs api_modules with metaschema_modules_public.rls_module and metaschema_public.schema
to resolve the correct PG schema names, while still using api_modules for API-level resolution
so all authenticated APIs (not just public) get their rls_module config.
@devin-ai-integration devin-ai-integration Bot changed the title fix: switch RLS module query from metaschema table to services_public.api_modules fix: switch RLS module query to api_modules with schema name resolution via JOIN Mar 2, 2026
Now that constructive-db derives api_modules JSONB schema names from
metaschema_public.schema (the single source of truth), the server can
read authenticate_schema and role_schema directly from the JSONB data
without needing a JOIN workaround to resolve the correct PG schema names.
@devin-ai-integration devin-ai-integration Bot changed the title fix: switch RLS module query to api_modules with schema name resolution via JOIN fix: switch RLS module query from metaschema table to services_public.api_modules Mar 3, 2026
… JSONB

Consistent with api.ts: remove JOIN workaround from all three upload
fallback queries (BY_DATABASE_ID, BY_API_ID, BY_DBNAME). Both api.ts
and upload.ts now read authenticate_schema and role_schema directly
from the JSONB data column.
@pyramation pyramation merged commit e42311e into main Mar 4, 2026
43 checks passed
@pyramation pyramation deleted the rls/rls-module-fix branch March 4, 2026 11:30
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