From c25e709cd1daca6d022f13f32f8f674377a1153a Mon Sep 17 00:00:00 2001 From: Kristof Siket Date: Mon, 2 Mar 2026 12:13:10 +0100 Subject: [PATCH 1/6] Migrate `prisma init --db` from deprecated connection fields to new connection model Read the connection string from `connections[0].endpoints.direct.connectionString` instead of manually constructing a DSN from `database.directConnection` fields. Falls back to the legacy `directConnection` path when `connections` is absent or endpoints lack a `connectionString`, for backward compatibility with older API versions. Also bumps `@prisma/management-api-sdk` from 0.2.0 to 1.12.0, which includes the new connection model types and renames the SDK exports: - `ManagementAPI` -> `ManagementApiSdk` - `createManagementAPI` -> `createManagementApiSdk` Closes TML-1927 --- packages/cli/package.json | 2 +- packages/cli/src/Init.ts | 16 +++++++++------- packages/cli/src/management-api/auth-client.ts | 10 +++++----- packages/cli/src/management-api/auth.ts | 8 ++++---- pnpm-lock.yaml | 10 +++++----- 5 files changed, 24 insertions(+), 22 deletions(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index 588b36f7dce6..c8525995fb7b 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -124,7 +124,7 @@ "@prisma/generator": "workspace:*", "@prisma/get-platform": "workspace:*", "@prisma/internals": "workspace:*", - "@prisma/management-api-sdk": "0.2.0", + "@prisma/management-api-sdk": "1.12.0", "@prisma/migrate": "workspace:*", "@swc/core": "1.11.5", "@swc/jest": "0.2.37", diff --git a/packages/cli/src/Init.ts b/packages/cli/src/Init.ts index d594c58305eb..4e9e2bd60042 100644 --- a/packages/cli/src/Init.ts +++ b/packages/cli/src/Init.ts @@ -544,16 +544,18 @@ export class Init implements Command { throw new Error('Missing database info in response') } - if (!project.database.directConnection) { - // This should never happen: OpenAPI types are not entirely correct, - // `directConnection` is not independently nullable and must always - // be present if `database` is in the response body. + const connection = project.database.connections?.[0] + const directEndpoint = connection?.endpoints?.direct + + if (directEndpoint?.connectionString) { + prismaPostgresDatabaseUrl = directEndpoint.connectionString + } else if (project.database.directConnection) { + const { host, user, pass } = project.database.directConnection + prismaPostgresDatabaseUrl = `postgres://${user}:${pass}@${host}/postgres?sslmode=require` + } else { throw new Error('Missing connection string in response') } - const { host, user, pass } = project.database.directConnection - prismaPostgresDatabaseUrl = `postgres://${user}:${pass}@${host}/postgres?sslmode=require` - workspaceId = project.workspace.id.replace(/^wksp_/, '') projectId = project.id.replace(/^proj_/, '') environmentId = project.database.id.replace(/^db_/, '') diff --git a/packages/cli/src/management-api/auth-client.ts b/packages/cli/src/management-api/auth-client.ts index b829caccb58f..8511f064c634 100644 --- a/packages/cli/src/management-api/auth-client.ts +++ b/packages/cli/src/management-api/auth-client.ts @@ -1,16 +1,16 @@ -import type { ManagementAPI } from '@prisma/management-api-sdk' -import { createManagementAPI } from '@prisma/management-api-sdk' +import type { ManagementApiSdk } from '@prisma/management-api-sdk' +import { createManagementApiSdk } from '@prisma/management-api-sdk' import { FileTokenStorage } from './token-storage' const CLIENT_ID = 'cmi4ttoor03pv2wco4526rnin' -export function createAuthenticatedManagementAPI(): ManagementAPI { +export function createAuthenticatedManagementAPI(): ManagementApiSdk { const tokenStorage = new FileTokenStorage() - return createManagementAPI({ + return createManagementApiSdk({ clientId: CLIENT_ID, - redirectUri: 'http://localhost:0/auth/callback', // Not used when tokens already exist + redirectUri: 'http://localhost:0/auth/callback', tokenStorage, }) } diff --git a/packages/cli/src/management-api/auth.ts b/packages/cli/src/management-api/auth.ts index 099359b5bc01..94fdf19d26cf 100644 --- a/packages/cli/src/management-api/auth.ts +++ b/packages/cli/src/management-api/auth.ts @@ -2,8 +2,8 @@ import events from 'node:events' import http from 'node:http' import { AddressInfo } from 'node:net' -import type { ManagementAPI } from '@prisma/management-api-sdk' -import { AuthError as SDKAuthError, createManagementAPI } from '@prisma/management-api-sdk' +import type { ManagementApiSdk } from '@prisma/management-api-sdk' +import { AuthError as SDKAuthError, createManagementApiSdk } from '@prisma/management-api-sdk' import open from 'open' import { FileTokenStorage } from './token-storage' @@ -71,7 +71,7 @@ export async function login(options: LoginOptions): Promise { export class LoginState { private latestVerifier?: string private latestState?: string - private managementAPI: ManagementAPI + private managementAPI: ManagementApiSdk private tokenStorage: FileTokenStorage constructor( @@ -80,7 +80,7 @@ export class LoginState { private utmMedium: string, ) { this.tokenStorage = new FileTokenStorage() - this.managementAPI = createManagementAPI({ + this.managementAPI = createManagementApiSdk({ clientId: CLIENT_ID, redirectUri: `http://${hostname}:${port}/auth/callback`, tokenStorage: this.tokenStorage, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fe4f12147dad..e8dcbb75dfd4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -495,8 +495,8 @@ importers: specifier: workspace:* version: link:../internals '@prisma/management-api-sdk': - specifier: 0.2.0 - version: 0.2.0 + specifier: 1.12.0 + version: 1.12.0 '@prisma/migrate': specifier: workspace:* version: link:../migrate @@ -3602,8 +3602,8 @@ packages: '@prisma/get-platform@7.2.0': resolution: {integrity: sha512-k1V0l0Td1732EHpAfi2eySTezyllok9dXb6UQanajkJQzPUGi3vO2z7jdkz67SypFTdmbnyGYxvEvYZdZsMAVA==} - '@prisma/management-api-sdk@0.2.0': - resolution: {integrity: sha512-ZFY5v3r2l4cx05zMNO4Wpu5ihW811xa9TytTS76Tal8oYHAPAUkSgNJZcRIPu5iYfs9LqOFegoonX1vIG0YVfw==} + '@prisma/management-api-sdk@1.12.0': + resolution: {integrity: sha512-fe9rOdWBx5u4N4q2brBWHZCMg+S8pHb6lBRWuINzwVAjyJqTdOhDG5RiGCPB0V8EQQ/HfQtIFrot9HDPfEJkOg==} '@prisma/ppg@1.0.1': resolution: {integrity: sha512-rRRXuPPerXwNWjSA3OE0e/bqXSTfsE82EsMvoiluc0fN0DizQSe3937/Tnl5+DPbxY5rdAOlYjWXG0A2wwTbKA==} @@ -10094,7 +10094,7 @@ snapshots: dependencies: '@prisma/debug': 7.2.0 - '@prisma/management-api-sdk@0.2.0': + '@prisma/management-api-sdk@1.12.0': dependencies: openapi-fetch: 0.14.0 From c67ff336394cc8fce5d069481d91c772a93eca26 Mon Sep 17 00:00:00 2001 From: Kristof Siket Date: Mon, 2 Mar 2026 12:22:39 +0100 Subject: [PATCH 2/6] Use .find() to select a connection with a usable connectionString The API doesn't guarantee ordering of connections[], so the first entry might be an accelerate connection without direct/pooled endpoints. Use .find() to locate a connection that has a connectionString available, and also try pooled endpoint before falling back to legacy directConnection. --- packages/cli/src/Init.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/cli/src/Init.ts b/packages/cli/src/Init.ts index 4e9e2bd60042..7093fd69b973 100644 --- a/packages/cli/src/Init.ts +++ b/packages/cli/src/Init.ts @@ -544,11 +544,17 @@ export class Init implements Command { throw new Error('Missing database info in response') } - const connection = project.database.connections?.[0] + const connection = project.database.connections?.find( + (c) => + Boolean(c.endpoints?.direct?.connectionString) || + Boolean(c.endpoints?.pooled?.connectionString), + ) const directEndpoint = connection?.endpoints?.direct if (directEndpoint?.connectionString) { prismaPostgresDatabaseUrl = directEndpoint.connectionString + } else if (connection?.endpoints?.pooled?.connectionString) { + prismaPostgresDatabaseUrl = connection.endpoints.pooled.connectionString } else if (project.database.directConnection) { const { host, user, pass } = project.database.directConnection prismaPostgresDatabaseUrl = `postgres://${user}:${pass}@${host}/postgres?sslmode=require` From 58d9e31ca8c8742310686e93676e2a6d6a60bd18 Mon Sep 17 00:00:00 2001 From: Kristof Siket Date: Mon, 2 Mar 2026 13:17:52 +0100 Subject: [PATCH 3/6] Fix prettier formatting --- packages/cli/src/Init.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/cli/src/Init.ts b/packages/cli/src/Init.ts index 7093fd69b973..1aa657167525 100644 --- a/packages/cli/src/Init.ts +++ b/packages/cli/src/Init.ts @@ -545,9 +545,7 @@ export class Init implements Command { } const connection = project.database.connections?.find( - (c) => - Boolean(c.endpoints?.direct?.connectionString) || - Boolean(c.endpoints?.pooled?.connectionString), + (c) => Boolean(c.endpoints?.direct?.connectionString) || Boolean(c.endpoints?.pooled?.connectionString), ) const directEndpoint = connection?.endpoints?.direct From be53d81e77302be9c9d42c48e659a0bbdca29459 Mon Sep 17 00:00:00 2001 From: Kristof Siket Date: Mon, 2 Mar 2026 14:59:35 +0100 Subject: [PATCH 4/6] refactor: remove legacy connection string fallback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use connectionString directly from the connections endpoint array. Drop the directConnection fallback — the API always returns the connections array with connectionString populated. --- packages/cli/src/Init.ts | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/packages/cli/src/Init.ts b/packages/cli/src/Init.ts index 1aa657167525..f10907f14f9b 100644 --- a/packages/cli/src/Init.ts +++ b/packages/cli/src/Init.ts @@ -547,19 +547,16 @@ export class Init implements Command { const connection = project.database.connections?.find( (c) => Boolean(c.endpoints?.direct?.connectionString) || Boolean(c.endpoints?.pooled?.connectionString), ) - const directEndpoint = connection?.endpoints?.direct - - if (directEndpoint?.connectionString) { - prismaPostgresDatabaseUrl = directEndpoint.connectionString - } else if (connection?.endpoints?.pooled?.connectionString) { - prismaPostgresDatabaseUrl = connection.endpoints.pooled.connectionString - } else if (project.database.directConnection) { - const { host, user, pass } = project.database.directConnection - prismaPostgresDatabaseUrl = `postgres://${user}:${pass}@${host}/postgres?sslmode=require` - } else { + + const connectionString = + connection?.endpoints?.direct?.connectionString ?? connection?.endpoints?.pooled?.connectionString + + if (!connectionString) { throw new Error('Missing connection string in response') } + prismaPostgresDatabaseUrl = connectionString + workspaceId = project.workspace.id.replace(/^wksp_/, '') projectId = project.id.replace(/^proj_/, '') environmentId = project.database.id.replace(/^db_/, '') From 079b771a043965396756af6f321de1cc1b334040 Mon Sep 17 00:00:00 2001 From: Kristof Siket Date: Mon, 2 Mar 2026 15:57:03 +0100 Subject: [PATCH 5/6] chore: bump hono from 4.11.7 to 4.12.3 Fixes IP spoofing authentication bypass vulnerability (GHSA-xxxxx). --- packages/cli/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index c8525995fb7b..ca79486f1a5d 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -143,7 +143,7 @@ "fs-extra": "11.3.0", "get-port-please": "3.2.0", "get-tsconfig": "4.10.0", - "hono": "4.11.7", + "hono": "4.12.3", "jest": "29.7.0", "jest-junit": "16.0.0", "kleur": "4.1.5", From 87e8626a26820897d6b864db712e94bb2fc59faf Mon Sep 17 00:00:00 2001 From: Kristof Siket Date: Mon, 2 Mar 2026 16:18:01 +0100 Subject: [PATCH 6/6] fix: tighten hono override to >=4.12.2 to fix audit vulnerability The previous override (>=4.11.10) allowed 4.12.0-4.12.1 which are vulnerable to authentication bypass by IP spoofing (GHSA-xh87-mx6m-69f3). The transitive dependency @prisma/dev>hono resolved to a version in that range. --- package.json | 2 +- pnpm-lock.yaml | 46 +++++++++++++++++++++++----------------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index 42c5398f8e9c..1574efab49c8 100644 --- a/package.json +++ b/package.json @@ -162,7 +162,7 @@ "pnpm": { "overrides": { "form-data": ">=4.0.4", - "hono": ">=4.11.10", + "hono": ">=4.12.2", "jws": ">=4.0.1", "tar-fs": ">=2.1.4", "lodash": ">=4.17.23" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bdc8cb8e58c9..6da299595636 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,7 +6,7 @@ settings: overrides: form-data: '>=4.0.4' - hono: '>=4.11.10' + hono: '>=4.12.2' jws: '>=4.0.1' tar-fs: '>=2.1.4' lodash: '>=4.17.23' @@ -442,7 +442,7 @@ importers: devDependencies: '@hono/node-server': specifier: 1.19.9 - version: 1.19.9(hono@4.12.0) + version: 1.19.9(hono@4.12.3) '@inquirer/prompts': specifier: 7.3.3 version: 7.3.3(@types/node@20.19.25) @@ -552,8 +552,8 @@ importers: specifier: 4.10.0 version: 4.10.0 hono: - specifier: '>=4.11.10' - version: 4.12.0 + specifier: '>=4.12.2' + version: 4.12.3 jest: specifier: 29.7.0 version: 29.7.0(@types/node@20.19.25)(ts-node@10.9.2(@swc/core@1.11.5)(@types/node@20.19.25)(typescript@5.4.5)) @@ -638,7 +638,7 @@ importers: version: 2.0.3(@jest/expect@29.7.0)(@jest/globals@29.7.0) '@hono/node-server': specifier: 1.19.0 - version: 1.19.0(hono@4.12.0) + version: 1.19.0(hono@4.12.3) '@inquirer/prompts': specifier: 7.3.3 version: 7.3.3(@types/node@20.19.25) @@ -1781,10 +1781,10 @@ importers: devDependencies: '@hono/node-server': specifier: 1.19.0 - version: 1.19.0(hono@4.12.0) + version: 1.19.0(hono@4.12.3) '@hono/zod-validator': specifier: 0.7.2 - version: 0.7.2(hono@4.12.0)(zod@4.1.3) + version: 0.7.2(hono@4.12.3)(zod@4.1.3) '@opentelemetry/api': specifier: 1.9.0 version: 1.9.0 @@ -1810,8 +1810,8 @@ importers: specifier: workspace:* version: link:../driver-adapter-utils hono: - specifier: '>=4.11.10' - version: 4.12.0 + specifier: '>=4.12.2' + version: 4.12.3 temporal-polyfill: specifier: 0.3.0 version: 0.3.0 @@ -2811,18 +2811,18 @@ packages: resolution: {integrity: sha512-1k8/8OHf5VIymJEcJyVksFpT+AQ5euY0VA5hUkCnlKpD4mr8FSbvXaHblxeTTEr90OaqWzAkQaqD80qHZQKxBA==} engines: {node: '>=18.14.1'} peerDependencies: - hono: '>=4.11.10' + hono: '>=4.12.2' '@hono/node-server@1.19.9': resolution: {integrity: sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==} engines: {node: '>=18.14.1'} peerDependencies: - hono: '>=4.11.10' + hono: '>=4.12.2' '@hono/zod-validator@0.7.2': resolution: {integrity: sha512-ub5eL/NeZ4eLZawu78JpW/J+dugDAYhwqUIdp9KYScI6PZECij4Hx4UsrthlEUutqDDhPwRI0MscUfNkvn/mqQ==} peerDependencies: - hono: '>=4.11.10' + hono: '>=4.12.2' zod: ^3.25.0 || ^4.0.0 '@humanfs/core@0.19.1': @@ -5650,8 +5650,8 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} - hono@4.12.0: - resolution: {integrity: sha512-NekXntS5M94pUfiVZ8oXXK/kkri+5WpX2/Ik+LVsl+uvw+soj4roXIsPqO+XsWrAw20mOzaXOZf3Q7PfB9A/IA==} + hono@4.12.3: + resolution: {integrity: sha512-SFsVSjp8sj5UumXOOFlkZOG6XS9SJDKw0TbwFeV+AJ8xlST8kxK5Z/5EYa111UY8732lK2S/xB653ceuaoGwpg==} engines: {node: '>=16.9.0'} hosted-git-info@2.8.9: @@ -9193,17 +9193,17 @@ snapshots: '@gar/promisify@1.1.3': optional: true - '@hono/node-server@1.19.0(hono@4.12.0)': + '@hono/node-server@1.19.0(hono@4.12.3)': dependencies: - hono: 4.12.0 + hono: 4.12.3 - '@hono/node-server@1.19.9(hono@4.12.0)': + '@hono/node-server@1.19.9(hono@4.12.3)': dependencies: - hono: 4.12.0 + hono: 4.12.3 - '@hono/zod-validator@0.7.2(hono@4.12.0)(zod@4.1.3)': + '@hono/zod-validator@0.7.2(hono@4.12.3)(zod@4.1.3)': dependencies: - hono: 4.12.0 + hono: 4.12.3 zod: 4.1.3 '@humanfs/core@0.19.1': {} @@ -10056,13 +10056,13 @@ snapshots: '@electric-sql/pglite': 0.3.15 '@electric-sql/pglite-socket': 0.0.20(@electric-sql/pglite@0.3.15) '@electric-sql/pglite-tools': 0.2.20(@electric-sql/pglite@0.3.15) - '@hono/node-server': 1.19.9(hono@4.12.0) + '@hono/node-server': 1.19.9(hono@4.12.3) '@mrleebo/prisma-ast': 0.13.1 '@prisma/get-platform': 7.2.0 '@prisma/query-plan-executor': 7.2.0 foreground-child: 3.3.1 get-port-please: 3.2.0 - hono: 4.12.0 + hono: 4.12.3 http-status-codes: 2.3.0 pathe: 2.0.3 proper-lockfile: 4.1.2 @@ -12348,7 +12348,7 @@ snapshots: dependencies: function-bind: 1.1.2 - hono@4.12.0: {} + hono@4.12.3: {} hosted-git-info@2.8.9: {}