ensure-db.ts107 lines · main
1/**
2 * Ensure Doltgres database `briven_engine` exists (DOLTGRES-FIRST).
3 *
4 * Stock Postgres is forbidden for product Auth state. SuperTokens Core
5 * connects with a postgresql:// URI *to doltgres* (wire protocol only).
6 *
7 * NOTE: Creating the DB is not enough for a healthy Core today — Core still
8 * crashes on Doltgres with `SET SESSION CHARACTERISTICS is not yet supported`.
9 * See BRIVEN-ENGINE-DOLTGRES-GOTCHA.md. We still ensure the DB on Doltgres
10 * so we never drift back to stock Postgres.
11 *
12 * Safe to call at API boot; no-ops when already present or data-plane URL unset.
13 */
14
15import pg from 'pg';
16
17import { env } from '../../env.js';
18import { log } from '../../lib/logger.js';
19
20const ENGINE_DB = 'briven_engine';
21
22/**
23 * Create `briven_engine` on the Doltgres cluster if missing.
24 * Uses BRIVEN_DATA_PLANE_URL (admin) or BRIVEN_DATABASE_URL host.
25 */
26export async function ensureBrivenEngineDatabase(): Promise<{
27 ok: boolean;
28 engine: 'briven-engine';
29 db: typeof ENGINE_DB;
30 host: 'doltgres' | 'unknown';
31 created: boolean;
32 message?: string;
33}> {
34 const base = {
35 engine: 'briven-engine' as const,
36 db: ENGINE_DB,
37 host: 'doltgres' as const,
38 };
39
40 // Prefer data-plane admin URL (points at doltgres). Never invent stock postgres.
41 // BRIVEN_ENGINE_DATABASE_URL points at briven_engine — use its host for admin.
42 let adminUrl =
43 env.BRIVEN_DATA_PLANE_URL ??
44 env.BRIVEN_DATABASE_URL ??
45 null;
46 if (!adminUrl && env.BRIVEN_ENGINE_DATABASE_URL) {
47 try {
48 const u = new URL(env.BRIVEN_ENGINE_DATABASE_URL);
49 u.pathname = '/postgres';
50 adminUrl = u.toString();
51 } catch {
52 adminUrl = null;
53 }
54 }
55
56 if (!adminUrl) {
57 return {
58 ...base,
59 ok: false,
60 created: false,
61 message: 'no BRIVEN_DATA_PLANE_URL / BRIVEN_DATABASE_URL — cannot ensure Doltgres DB',
62 };
63 }
64
65 // Guard: refuse if URL clearly targets stock service name `postgres` without doltgres
66 // (compose product line must use host doltgres).
67 try {
68 const u = new URL(adminUrl);
69 if (u.hostname === 'postgres') {
70 log.error('briven_engine_db_refuses_stock_postgres', {
71 message: 'DOLTGRES-FIRST: briven_engine must not use stock postgres host',
72 });
73 return {
74 ...base,
75 ok: false,
76 created: false,
77 message: 'refusing stock postgres host — use doltgres',
78 };
79 }
80 } catch {
81 /* continue with raw URL */
82 }
83
84 const client = new pg.Client({ connectionString: adminUrl });
85 try {
86 await client.connect();
87 const found = await client.query(
88 `SELECT 1 AS ok FROM pg_database WHERE datname = $1`,
89 [ENGINE_DB],
90 );
91 if (found.rowCount && found.rowCount > 0) {
92 log.info('briven_engine_db_exists', { db: ENGINE_DB, host: 'doltgres' });
93 return { ...base, ok: true, created: false, message: 'already exists on Doltgres' };
94 }
95
96 // Doltgres: CREATE DATABASE outside a transaction; no reliable IF NOT EXISTS.
97 await client.query(`CREATE DATABASE "${ENGINE_DB}"`);
98 log.info('briven_engine_db_created', { db: ENGINE_DB, host: 'doltgres' });
99 return { ...base, ok: true, created: true, message: 'created on Doltgres' };
100 } catch (err) {
101 const message = err instanceof Error ? err.message : String(err);
102 log.warn('briven_engine_db_ensure_failed', { message });
103 return { ...base, ok: false, created: false, message };
104 } finally {
105 await client.end().catch(() => undefined);
106 }
107}