Skip to content

feat: typed table reads for CORS, pubkey, webauthn, database_settings + Graphile feature flag wiring#1091

Merged
pyramation merged 1 commit intomainfrom
feat/phase3-typed-settings-reads
May 10, 2026
Merged

feat: typed table reads for CORS, pubkey, webauthn, database_settings + Graphile feature flag wiring#1091
pyramation merged 1 commit intomainfrom
feat/phase3-typed-settings-reads

Conversation

@pyramation
Copy link
Copy Markdown
Contributor

Summary

Continues the unified settings architecture (Phases 3–4, per constructive-planning#812). Builds on the RLS pattern from PR #1086 to read from all remaining typed settings tables with backwards-compatible fallback to api_modules.

Server-side reads (Phase 3 continued):

  • CORS — queries cors_settings (per-API, then db-default), falls back to api_modules legacy cors module
  • Pubkey challenge — queries pubkey_settings (with LEFT JOINs to metaschema_public.schema / function), falls back to api_modules legacy pubkey_challenge module
  • WebAuthn — queries webauthn_settings (with LEFT JOINs to 4 schema FKs), no legacy fallback needed
  • Database settings — queries database_settings with api_settings cascade via COALESCE

All queries use the same try/catch → undefined fallback pattern so deployments without the new tables continue working.

Graphile feature flag wiring (Phase 4):

  • buildPreset() now accepts databaseSettings and conditionally includes PgAggregatesPreset when enableAggregates is true
  • Other feature flags (postgis, search, uploads, etc.) are stored on ApiStructure but do not yet disable their corresponding plugins — deferred to a follow-up that maps each flag to specific disablePlugins entries

Other changes:

  • Refactored toApiStructure from positional args to a ResolvedSettings object
  • Both resolveApiNameHeader and resolveDomainLookup now run all 6 settings queries in parallel via Promise.all
  • cors.ts reads api.corsOrigins (typed) and merges with legacy api_modules CORS data
  • Re-exports PgAggregatesPreset from graphile-settings so the server doesn't need a direct dependency

Review & Testing Checklist for Human

  • SQL column names match actual table schemas — Verify the column names in PUBKEY_SETTINGS_SQL, WEBAUTHN_SETTINGS_SQL, DATABASE_SETTINGS_SQL, and CORS_SETTINGS_SQL match the table definitions from constructive-db PRs feat(node-type-registry): add DataLimitCounter, DataFeatureFlag, AuthzAppMembership #1060/fix(presigned-url): match files→buckets by table name prefix instead of schema name #1075. Mismatches would be silently swallowed by the try/catch.
  • CORS fallback asymmetryqueryCorsSettings introduces a db-default cascade (api_id IS NULL) that queryCorsModuleLegacy does not have. Confirm this is desired new behavior, not an unintentional divergence.
  • queryCorsModuleLegacy lacks try/catch — Unlike all other legacy fallback functions, the CORS legacy query will throw on DB errors rather than returning undefined. Verify this is acceptable or should be wrapped.
  • Feature flags are read but mostly not enforced — Only enableAggregates actually gates a plugin. The other 8 flags are carried on ApiStructure but don't disable anything yet. Confirm this partial wiring is acceptable for now.
  • Deploy with pgpm deploy — Test against a real database to verify the typed table queries return correct data and the api_modules fallback works when typed tables are empty.

Notes

  • No new tests are included — test coverage for typed settings reads is tracked in constructive-planning#823.
  • All pre-existing TS errors (ConstructivePreset, makePgService, streamToStorage not found) are confirmed present on main — they require building graphile-settings first.
  • The svcCache LRU cache (1-year TTL) means the additional queries only fire on cold starts / cache misses.

Link to Devin session: https://app.devin.ai/sessions/94a2728a9c414500bead29cbbc829c15
Requested by: @pyramation

… + Graphile feature flag wiring

Phase 3 (continued) + Phase 4 of the unified settings architecture:

- Add DatabaseSettings, PubkeyChallengeSettings, WebauthnSettings interfaces to types.ts
- Add corsOrigins, databaseSettings, pubkeyChallengeSettings, webauthnSettings to ApiStructure
- Implement SQL queries for cors_settings, pubkey_settings, webauthn_settings, database_settings
  with LEFT JOINs to metaschema_public.schema and metaschema_public.function
- Add try/catch fallback pattern: typed table first, then legacy api_modules
- Update cors.ts to read from api.corsOrigins (typed table) with api_modules fallback
- Wire database_settings feature flags into Graphile preset (enable_aggregates adds PgAggregatesPreset)
- Re-export PgAggregatesPreset from graphile-settings for server consumption
- All new queries run in parallel via Promise.all in both resolveApiNameHeader and resolveDomainLookup
@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

@pyramation pyramation merged commit a9d0191 into main May 10, 2026
54 checks passed
@pyramation pyramation deleted the feat/phase3-typed-settings-reads branch May 10, 2026 00:24
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