db-shell.ts32 lines · main
1import { dbNameFor, rotateProjectRolePassword } from '../db/data-plane.js';
2import { env } from '../env.js';
3
4/**
5 * Issue a short-lived DSN the user can pass to `psql`. The role's password is
6 * rotated on every call, so a leaked DSN is invalidated by the next issue —
7 * security relies on rotate-on-issue, not a SQL-side TTL (DoltGres rejects
8 * `VALID UNTIL`; `expiresAt` is app-side bookkeeping). No manual revocation
9 * required.
10 */
11export async function issueShellToken(projectId: string): Promise<{
12 dsn: string;
13 role: string;
14 expiresAt: Date;
15}> {
16 if (!env.BRIVEN_DATA_PLANE_URL) {
17 throw new Error('BRIVEN_DATA_PLANE_URL is not configured');
18 }
19 const { role, password, expiresAt } = await rotateProjectRolePassword(projectId, 15 * 60);
20 const dbName = dbNameFor(projectId);
21
22 const base = new URL(env.BRIVEN_DATA_PLANE_URL);
23 base.username = role;
24 base.password = password;
25 // why: database-per-project — point the DSN at the project's own DoltGres
26 // database so the user lands directly on their tables (in its `public`
27 // schema). No `search_path` option needed; platform tables are blocked by
28 // REVOKE at the grant layer.
29 base.pathname = `/${dbName}`;
30
31 return { dsn: base.toString(), role, expiresAt };
32}