Skip to content

feat: zero-connection startup with PostgreSQL SSL support#20

Merged
KIvanow merged 10 commits intomasterfrom
cloud-version
Feb 11, 2026
Merged

feat: zero-connection startup with PostgreSQL SSL support#20
KIvanow merged 10 commits intomasterfrom
cloud-version

Conversation

@KIvanow
Copy link
Collaborator

@KIvanow KIvanow commented Feb 9, 2026

Enable graceful application startup without pre-configured database connections and add SSL support for cloud PostgreSQL deployments.

Features

  • Zero-Connection Startup: App starts without DB_HOST set, users add connections via UI
  • PostgreSQL SSL: New STORAGE_SSL_CA env var supports file paths or URLs (AWS RDS, GCP, Azure)
  • Server Startup Guard: Frontend waits for backend initialization to prevent race conditions
  • SPA Routing: Fixed client-side routing on page refresh with proper NestJS architecture
  • Enhanced UX: Loading states, error boundaries, and helpful guidance for first-time setup

Technical Changes

  • New waiting status in health endpoints when no connections configured
  • SpaFallbackModule with type-safe Fastify handlers and static file whitelist
  • ServerStartupGuard component with progress indicators and timeout handling
  • NoConnectionsGuard shows arrow pointing to sidebar connection selector
  • Proper timeout cleanup to prevent memory leaks
  • SSL certificate fetching with domain whitelist and 10s timeout

Migration

  • Fully backwards compatible - existing DB_HOST configurations work unchanged
  • Optional: Set STORAGE_SSL_CA for cloud PostgreSQL requiring SSL
  • API docs now at /docs instead of /api/docs

Fixes

  • SPA routing on page refresh in production
  • Race condition on server startup
  • Memory leak in polling component
  • Inconsistent error messaging

Note

Medium Risk
Touches startup/health behavior, production routing, and PostgreSQL connection initialization (including remote CA fetch), which could impact boot and request handling if misconfigured or if allowlisting blocks existing SSL setups.

Overview
Enables graceful “zero-connection” startup: when no saved connections exist and DB_HOST is not set, the backend now reports a waiting health state (with message) instead of failing/creating a default, and the UI guides users to add a first connection.

Adds PostgreSQL SSL CA support for storage via STORAGE_SSL_CA (file path or trusted HTTPS URL) with domain allowlisting, redirect blocking, and fetch timeout, plus clearer logging.

Hardens production SPA routing/static serving by registering a Fastify-level catch-all SPA fallback ahead of Nest routes, and standardizes API docs to /docs (CLI banner and server logs updated). Versions are bumped to 0.5.0, and Docker no longer sets default DB env vars.

Written by Cursor Bugbot for commit 9e02f14. This will update automatically on new commits. Configure here.

Enable graceful application startup without pre-configured database connections
and add SSL support for cloud PostgreSQL deployments.

## Features

- **Zero-Connection Startup**: App starts without DB_HOST set, users add connections via UI
- **PostgreSQL SSL**: New STORAGE_SSL_CA env var supports file paths or URLs (AWS RDS, GCP, Azure)
- **Server Startup Guard**: Frontend waits for backend initialization to prevent race conditions
- **SPA Routing**: Fixed client-side routing on page refresh with proper NestJS architecture
- **Enhanced UX**: Loading states, error boundaries, and helpful guidance for first-time setup

## Technical Changes

- New `waiting` status in health endpoints when no connections configured
- SpaFallbackModule with type-safe Fastify handlers and static file whitelist
- ServerStartupGuard component with progress indicators and timeout handling
- NoConnectionsGuard shows arrow pointing to sidebar connection selector
- Proper timeout cleanup to prevent memory leaks
- SSL certificate fetching with domain whitelist and 10s timeout

## Migration

- Fully backwards compatible - existing DB_HOST configurations work unchanged
- Optional: Set STORAGE_SSL_CA for cloud PostgreSQL requiring SSL
- API docs now at /docs instead of /api/docs

## Fixes

- SPA routing on page refresh in production
- Race condition on server startup
- Memory leak in polling component
- Inconsistent error messaging
@BetterDB-inc BetterDB-inc deleted a comment from cursor bot Feb 9, 2026
Fix SPA fallback broken by global API prefix, prevent subdomain spoofing in SSL CA domain whitelist, and block insecure HTTP URLs for certificate fetching.
Move SPA fallback to Fastify setNotFoundHandler to avoid global prefix conflict, ensure API 404s return JSON not HTML, prevent subdomain spoofing in SSL CA domain validation, and block insecure HTTP URLs for certificate fetching.
Register SPA fallback at Fastify level before NestJS to avoid global prefix conflicts, ensure API 404s return JSON, block insecure HTTP for SSL certificates, prevent subdomain spoofing with proper domain validation, restrict SPA fallback to GET requests only, and update DTOs with 'waiting' status.
Register SPA fallback at Fastify level before NestJS to handle client-side routes correctly, ensure missing API routes return JSON 404, block HTTP for SSL certificates and validate only official CA distribution endpoints (AWS RDS PKI, GCP Cloud SQL, DigiCert), prevent subdomain spoofing with proper domain validation, restrict SPA fallback to GET requests only, exclude HEAD from catch-all to preserve Docker healthchecks, and update DTOs with 'waiting' status.
@KIvanow
Copy link
Collaborator Author

KIvanow commented Feb 10, 2026

bugbot run

Register SPA fallback at Fastify level before NestJS to handle client-side routes, ensure missing API routes return JSON 404, block HTTP for SSL certificates and validate only official CA endpoints with proper path boundaries (AWS RDS PKI, GCP Cloud SQL with trailing slash, DigiCert), prevent subdomain spoofing, exclude HEAD from catch-all for Docker healthchecks, consolidate publicPath computation to prevent divergence, and update DTOs with 'waiting' status.
{retryCount > 5 && (
<p className="text-sm text-muted-foreground mt-4">
Still starting... ({retryCount} seconds elapsed)
</p>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Retry counter inaccurately displays as seconds elapsed

Low Severity

The UI displays retryCount as "seconds elapsed," but each retry cycle includes the variable fetch duration plus the 1-second RETRY_INTERVAL. A slow or timing-out server response makes each cycle significantly longer than 1 second, so the displayed count undercounts actual elapsed time, potentially confusing users during long startup waits.

Fix in Cursor Fix in Web

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

// Serve index.html for SPA client-side routes
reply.type('text/html').send(indexHtml);
}
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SPA catch-all returns 404 for all static assets

High Severity

The SPA catch-all wildcard route explicitly sends a 404 JSON response for any URL matching STATIC_EXTENSIONS (.js, .css, .png, .woff2, etc.). Meanwhile, @fastify/static is registered with both wildcard: false and decorateReply: false, making it a complete no-op — it registers no routes, no hooks, and no reply decorators. There is no remaining mechanism to serve frontend assets (JS bundles, CSS, fonts, images) from the public directory. In production, the browser loads index.html but all <script> and <link> tags for hashed build assets like /assets/index-abc123.js will receive 404s, rendering the SPA non-functional.

Additional Locations (1)

Fix in Cursor Fix in Web

@KIvanow KIvanow merged commit 41ff73f into master Feb 11, 2026
2 checks passed
@KIvanow KIvanow deleted the cloud-version branch February 11, 2026 12:39
@KIvanow KIvanow restored the cloud-version branch February 11, 2026 12:39
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