Skip to content

feat(api): add RLS module support to API resolution for PostGraphile v5#684

Merged
pyramation merged 6 commits intodevelop-v5from
devin/rls-module-authentication-upgrade
Feb 5, 2026
Merged

feat(api): add RLS module support to API resolution for PostGraphile v5#684
pyramation merged 6 commits intodevelop-v5from
devin/rls-module-authentication-upgrade

Conversation

@pyramation
Copy link
Contributor

@pyramation pyramation commented Feb 5, 2026

Summary

The develop-v5 branch rewrote API resolution to use direct SQL queries instead of the GraphQL ORM approach. However, the RLS module data (needed for authentication) was missing from the new implementation, and the grafast context was accessing the Express request incorrectly. This PR fixes both issues to restore bearer token authentication.

Changes in api.ts:

  • Added RLS_MODULE_SQL query to fetch RLS module data from metaschema_modules_public.rls_module with private schema name
  • Added api_id to DOMAIN_LOOKUP_SQL and API_NAME_LOOKUP_SQL queries
  • Added queryRlsModule function and toRlsModule helper for type conversion
  • Updated resolveApiNameHeader and resolveDomainLookup to fetch and include RLS module in the ApiStructure
  • Removed silent error swallowing - query functions now let errors propagate instead of catching "does not exist" errors and returning null

Changes in graphile.ts:

  • Fixed grafast.context callback to use correct request path: requestContext.expressv4.req instead of ctx.node.req
  • This was causing bearer token authentication to silently fail (always using anonRole instead of roleName)

Changes in auth.ts:

  • Added comprehensive INFO-level logging throughout the authentication middleware
  • Logs RLS module presence, auth function selection, authorization header parsing, query execution, and results
  • This helps diagnose why authentication may not be working as expected

Updates since last revision

  • Fixed the RLS module SQL query to use the correct schema: metaschema_modules_public.rls_module instead of services_public.rls_module
  • Removed all silent error swallowing from query functions - errors now propagate properly instead of being hidden. If a table doesn't exist, you'll get an actual error instead of silent null returns.

Review & Testing Checklist for Human

  • Test bearer token authentication end-to-end: Log in, get a token, make an authenticated GraphQL request, and verify the correct role is applied (not anonRole). This is the most critical test.
  • Verify the requestContext path is correct: The path requestContext.expressv4.req is a type assertion - confirm this is correct for grafserv/express/v4 by checking grafserv source code
  • Verify SQL query correctness: Confirm that metaschema_modules_public.rls_module and metaschema_public.schema tables exist with the expected columns (api_id, authenticate, authenticate_strict, private_schema_id)
  • Test error propagation: With the error swallowing removed, verify the server handles missing tables appropriately (should throw, not silently fail)
  • Consider log verbosity: The new auth logs are at INFO level - decide if this is appropriate for production or should be DEBUG

Recommended test plan:

  1. Start the server locally and observe the new [auth] logs
  2. Verify logs now show rlsModule=present (not missing)
  3. Make an unauthenticated GraphQL request - check logs show "No bearer token provided"
  4. Authenticate and get a bearer token
  5. Make an authenticated request with Authorization: Bearer <token> header
  6. Check logs show the auth query being executed and the result
  7. Verify the request uses roleName (not anonRole)

Notes

  • The Grafast.RequestContext type is used but cast to access expressv4 property - this type assertion should be verified against grafserv source
  • Query functions no longer swallow "does not exist" errors - they will throw if tables are missing
  • Build has pre-existing issues in develop-v5 branch (missing workspace dependencies), so full build verification was not possible locally

Link to Devin run: https://app.devin.ai/sessions/c0c4671ef1dd48199e62c4bd403dd3c5
Requested by: Dan Lynch (@pyramation)

- Add RLS_MODULE_SQL query to fetch RLS module data with private schema name
- Add api_id to DOMAIN_LOOKUP_SQL and API_NAME_LOOKUP_SQL queries
- Add RlsModuleRow interface for type safety
- Add queryRlsModule function to fetch RLS module by API ID
- Add toRlsModule helper to convert database row to RlsModule interface
- Update toApiStructure to accept and include RLS module data
- Update resolveApiNameHeader and resolveDomainLookup to fetch RLS module

This enables the authentication middleware (auth.ts) to access the
rlsModule data (authenticate, authenticateStrict, privateSchema) which
is required for PostGraphile v5 authentication flow.
@devin-ai-integration
Copy link
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

…Graphile v5

The grafast.context callback receives a RequestContext object, not a generic
context. In grafserv/express/v4, the Express request is available at
requestContext.expressv4.req, not ctx.node.req.

This was preventing the authentication middleware from properly passing
the token to the GraphQL context, causing bearer token authentication
to fail silently (always using anonRole instead of roleName).
…ture

The grafast.context callback expects Partial<Grafast.RequestContext>, not
the full Grafast.RequestContext type.
Added INFO-level logging throughout the auth middleware to help debug
authentication issues:
- Log when middleware is called and whether api is present
- Log RLS module details (authenticate, authenticateStrict, privateSchema)
- Log authFn selection and strictAuth setting
- Log authorization header parsing
- Log the actual auth query being executed
- Log query results and success/failure
- Log when skipping auth due to missing config
The RLS module table is in metaschema_modules_public.rls_module, not
services_public.rls_module. This was causing the RLS module query to
return null, which made authentication skip entirely.
Simplified query functions to just call pool.query() directly without
try/catch blocks that silently swallow 'does not exist' errors. Errors
should propagate so issues are visible, not hidden.
@pyramation pyramation merged commit f9885f1 into develop-v5 Feb 5, 2026
13 checks passed
@pyramation pyramation deleted the devin/rls-module-authentication-upgrade branch February 5, 2026 03:44
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