From 34b6f68883ad73bf3663f2d0186fa3b82a10aa2d Mon Sep 17 00:00:00 2001 From: 7ttp <117663341+7ttp@users.noreply.github.com> Date: Wed, 29 Jul 2026 04:28:09 +0530 Subject: [PATCH 1/6] fix --- apps/cli-go/internal/debug/postgres.go | 49 ++++++++++++++++++- apps/cli-go/internal/debug/postgres_test.go | 34 +++++++++++++ apps/cli-go/internal/utils/connect.go | 2 - apps/cli-go/internal/utils/connect_test.go | 4 +- .../legacy/shared/legacy-connect-errors.ts | 6 --- .../shared/legacy-connect-errors.unit.test.ts | 7 +-- .../legacy-db-config.integration.test.ts | 5 -- .../legacy/shared/legacy-db-config.layer.ts | 3 +- 8 files changed, 88 insertions(+), 22 deletions(-) diff --git a/apps/cli-go/internal/debug/postgres.go b/apps/cli-go/internal/debug/postgres.go index 6e0929e238..79254ed282 100644 --- a/apps/cli-go/internal/debug/postgres.go +++ b/apps/cli-go/internal/debug/postgres.go @@ -2,6 +2,8 @@ package debug import ( "context" + "crypto/tls" + "encoding/binary" "encoding/json" "errors" "io" @@ -16,7 +18,10 @@ import ( type Proxy struct { dialContext func(ctx context.Context, network, addr string) (net.Conn, error) - errChan chan error + // tlsConfig is what pgx resolved from sslmode. DialFunc completes the + // handshake itself, so logged frames are plaintext in memory but not on the wire. + tlsConfig *tls.Config + errChan chan error } func NewProxy() Proxy { @@ -30,10 +35,19 @@ func NewProxy() Proxy { func SetupPGX(config *pgx.ConnConfig) { proxy := Proxy{ dialContext: config.DialFunc, + tlsConfig: config.TLSConfig, errChan: make(chan error, 1), } config.DialFunc = proxy.DialFunc + // pgx must not negotiate TLS again over the in-memory pipe; clearing these + // *without* DialFunc's handshake is what downgraded sslmode=require (#5872). + // Every attempt then reuses the primary's config, which pgconn only leaves + // plaintext for sslmode=disable and =allow (config.go:772-780), so a required + // connection stays encrypted; =allow loses its opportunistic TLS retry. config.TLSConfig = nil + for _, fallback := range config.Fallbacks { + fallback.TLSConfig = nil + } } func (p *Proxy) DialFunc(ctx context.Context, network, addr string) (net.Conn, error) { @@ -41,6 +55,11 @@ func (p *Proxy) DialFunc(ctx context.Context, network, addr string) (net.Conn, e if err != nil { return nil, err } + if p.tlsConfig != nil { + if serverConn, err = startTLS(ctx, serverConn, p.tlsConfig); err != nil { + return nil, err + } + } const bufSize = 1024 * 1024 ln := bufconn.Listen(bufSize) @@ -73,6 +92,34 @@ func (p *Proxy) DialFunc(ctx context.Context, network, addr string) (net.Conn, e return ln.DialContext(ctx) } +// libpq's SSLRequest message code, PG_PROTOCOL(1234,5679). +const sslRequestCode = 80877103 + +// startTLS mirrors pgconn's own startTLS (pgconn@v1.14.3/pgconn.go:406-419), but +// handshakes eagerly so a refusal or bad certificate fails the dial rather than +// surfacing as a parse error inside the forwarding goroutines. +func startTLS(ctx context.Context, conn net.Conn, tlsConfig *tls.Config) (net.Conn, error) { + if err := binary.Write(conn, binary.BigEndian, []int32{8, sslRequestCode}); err != nil { + conn.Close() + return nil, err + } + response := make([]byte, 1) + if _, err := io.ReadFull(conn, response); err != nil { + conn.Close() + return nil, err + } + if response[0] != 'S' { + conn.Close() + return nil, errors.New("server refused TLS connection") + } + tlsConn := tls.Client(conn, tlsConfig) + if err := tlsConn.HandshakeContext(ctx); err != nil { + conn.Close() + return nil, err + } + return tlsConn, nil +} + type Backend struct { *pgproto3.Backend logger *log.Logger diff --git a/apps/cli-go/internal/debug/postgres_test.go b/apps/cli-go/internal/debug/postgres_test.go index 9f46fd6b84..40a3083cb7 100644 --- a/apps/cli-go/internal/debug/postgres_test.go +++ b/apps/cli-go/internal/debug/postgres_test.go @@ -2,6 +2,9 @@ package debug import ( "context" + "encoding/binary" + "io" + "net" "testing" "github.com/jackc/pgx/v4" @@ -28,4 +31,35 @@ func TestPostgresProxy(t *testing.T) { assert.NoError(t, err) assert.NoError(t, proxy.Close(ctx)) }) + + t.Run("negotiates TLS itself instead of downgrading", func(t *testing.T) { + config, err := pgx.ParseConfig(postgresUrl + "?sslmode=require") + require.NoError(t, err) + require.NotNil(t, config.TLSConfig) + // Run test + SetupPGX(config) + assert.Nil(t, config.TLSConfig) + for _, fallback := range config.Fallbacks { + assert.Nil(t, fallback.TLSConfig) + } + // A server refusing TLS must fail the dial, not continue in plaintext. + ln, err := net.Listen("tcp", "127.0.0.1:0") + require.NoError(t, err) + defer ln.Close() + go func() { + conn, err := ln.Accept() + if err != nil { + return + } + defer conn.Close() + request := make([]byte, 8) + if _, err := io.ReadFull(conn, request); err != nil { + return + } + assert.Equal(t, int32(sslRequestCode), int32(binary.BigEndian.Uint32(request[4:]))) + _, _ = conn.Write([]byte("N")) + }() + _, err = config.DialFunc(context.Background(), "tcp", ln.Addr().String()) + assert.ErrorContains(t, err, "server refused TLS connection") + }) } diff --git a/apps/cli-go/internal/utils/connect.go b/apps/cli-go/internal/utils/connect.go index e19aaaf523..cd9080de05 100644 --- a/apps/cli-go/internal/utils/connect.go +++ b/apps/cli-go/internal/utils/connect.go @@ -321,8 +321,6 @@ func SetConnectSuggestion(err error) { "Make sure your local IP is allowed in Network Restrictions and Network Bans.\n%s/project/_/database/settings", CurrentProfile.DashboardURL, ) - } else if strings.Contains(msg, "SSL connection is required") && viper.GetBool("DEBUG") { - CmdSuggestion = "SSL connection is not supported with --debug flag" } else if strings.Contains(msg, "SCRAM exchange: Wrong password") || strings.Contains(msg, "failed SASL auth") { // password authentication failed for user / invalid SCRAM server-final-message received from server CmdSuggestion = SuggestEnvVar diff --git a/apps/cli-go/internal/utils/connect_test.go b/apps/cli-go/internal/utils/connect_test.go index a7b772d70f..064546b456 100644 --- a/apps/cli-go/internal/utils/connect_test.go +++ b/apps/cli-go/internal/utils/connect_test.go @@ -208,10 +208,12 @@ func TestSetConnectSuggestion(t *testing.T) { suggestion: "", }, { + // The debug proxy negotiates TLS itself, so --debug is no longer the + // reason a server rejects an unencrypted connection (#5872). name: "ssl required with debug flag", err: errors.New("SSL connection is required"), debug: true, - suggestion: "SSL connection is not supported with --debug flag", + suggestion: "", }, { name: "wrong password via SCRAM", diff --git a/apps/cli/src/legacy/shared/legacy-connect-errors.ts b/apps/cli/src/legacy/shared/legacy-connect-errors.ts index 58e6338538..442c1bee73 100644 --- a/apps/cli/src/legacy/shared/legacy-connect-errors.ts +++ b/apps/cli/src/legacy/shared/legacy-connect-errors.ts @@ -70,8 +70,6 @@ export interface LegacyConnectSuggestionContext { readonly dashboardUrl: string; /** Active profile name (Go's `CurrentProfile.Name`). */ readonly profileName: string; - /** Whether `--debug` is set (Go's `viper.GetBool("DEBUG")`). */ - readonly debug: boolean; } /** @@ -366,10 +364,6 @@ export function legacyConnectSuggestion( ) { return `Make sure your local IP is allowed in Network Restrictions and Network Bans.\n${ctx.dashboardUrl}/project/_/database/settings`; } - // SSL connection is required (only under --debug, which disables TLS). - if (text.includes("SSL connection is required") && ctx.debug) { - return "SSL connection is not supported with --debug flag"; - } // Wrong password (Go: "SCRAM exchange: Wrong password" / "failed SASL auth"; // node-postgres surfaces the server's `28P01` "password authentication failed"). if ( diff --git a/apps/cli/src/legacy/shared/legacy-connect-errors.unit.test.ts b/apps/cli/src/legacy/shared/legacy-connect-errors.unit.test.ts index 41867f4df8..dec18f832b 100644 --- a/apps/cli/src/legacy/shared/legacy-connect-errors.unit.test.ts +++ b/apps/cli/src/legacy/shared/legacy-connect-errors.unit.test.ts @@ -276,7 +276,6 @@ describe("legacyConnectSuggestion", () => { const ctx = { dashboardUrl: "https://supabase.com/dashboard", profileName: "supabase", - debug: false, } as const; // The @effect/sql SqlError wraps the node driver error on `.cause`; a multi-address @@ -318,12 +317,10 @@ describe("legacyConnectSuggestion", () => { expect(legacyConnectSuggestion(err, ctx)).toBe(LEGACY_SUGGEST_ENV_VAR); }); - it("suggests the --debug SSL note only under --debug", () => { + // `ssl` comes from the DSN alone, so a server demanding it blames the DSN, not the flag. + it("does not blame --debug when the server demands SSL", () => { const err = sqlError(new Error("SSL connection is required")); expect(legacyConnectSuggestion(err, ctx)).toBeUndefined(); - expect(legacyConnectSuggestion(err, { ...ctx, debug: true })).toBe( - "SSL connection is not supported with --debug flag", - ); }); it("maps an IPv6-only connectivity failure to the IPv6 pooler suggestion", () => { diff --git a/apps/cli/src/legacy/shared/legacy-db-config.integration.test.ts b/apps/cli/src/legacy/shared/legacy-db-config.integration.test.ts index c277d2930e..83c414b3b6 100644 --- a/apps/cli/src/legacy/shared/legacy-db-config.integration.test.ts +++ b/apps/cli/src/legacy/shared/legacy-db-config.integration.test.ts @@ -163,7 +163,6 @@ describe("legacyDbConfigResolver (local + db-url)", () => { suggestionContext: { dashboardUrl: "https://supabase.com/dashboard", profileName: "supabase", - debug: false, }, }); expect(r.isLocal).toBe(true); @@ -216,7 +215,6 @@ describe("legacyDbConfigResolver (local + db-url)", () => { suggestionContext: { dashboardUrl: "https://supabase.com/dashboard", profileName: "supabase", - debug: false, }, }); expect(r.isLocal).toBe(false); @@ -510,7 +508,6 @@ describe("legacyDbConfigResolver (linked config ordering)", () => { suggestionContext: { dashboardUrl: "https://supabase.com/dashboard", profileName: "supabase", - debug: false, }, }); expect(r.ref).toEqual(Option.some(adHocRef)); @@ -668,7 +665,6 @@ describe("legacyDbConfigResolver (linked config ordering)", () => { suggestionContext: { dashboardUrl: "https://supabase.com/dashboard", profileName: "supabase", - debug: false, }, }); } @@ -810,7 +806,6 @@ describe("legacyDbConfigResolver (linked config ordering)", () => { suggestionContext: { dashboardUrl: "https://supabase.com/dashboard", profileName: "supabase", - debug: false, }, }); } diff --git a/apps/cli/src/legacy/shared/legacy-db-config.layer.ts b/apps/cli/src/legacy/shared/legacy-db-config.layer.ts index 45714feb97..b4de96d26b 100644 --- a/apps/cli/src/legacy/shared/legacy-db-config.layer.ts +++ b/apps/cli/src/legacy/shared/legacy-db-config.layer.ts @@ -108,13 +108,12 @@ export const legacyDbConfigLayer = Layer.effect( const path = yield* Path.Path; // Profile context for the connect-failure suggestion (Go's `SetConnectSuggestion` - // reads the ambient `CurrentProfile` + `viper.GetBool("DEBUG")`). Snapshot it once + // reads the ambient `CurrentProfile`). Snapshot it once // and attach it to every resolved connection so the driver layer can render Go's // hint on a refused/auth/IPv6 connect error. const suggestionContext: LegacyConnectSuggestionContext = { dashboardUrl: cliConfig.dashboardUrl, profileName: cliConfig.profile, - debug: yield* LegacyDebugFlag, }; // Capture the ambient services the Management API stack needs, so the From 064c0d896c83326b07edd3a1e85fccb905a786a9 Mon Sep 17 00:00:00 2001 From: 7ttp <117663341+7ttp@users.noreply.github.com> Date: Wed, 29 Jul 2026 05:27:46 +0530 Subject: [PATCH 2/6] lint --- apps/cli-go/internal/debug/postgres_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/cli-go/internal/debug/postgres_test.go b/apps/cli-go/internal/debug/postgres_test.go index 40a3083cb7..87a29c3dbe 100644 --- a/apps/cli-go/internal/debug/postgres_test.go +++ b/apps/cli-go/internal/debug/postgres_test.go @@ -56,7 +56,7 @@ func TestPostgresProxy(t *testing.T) { if _, err := io.ReadFull(conn, request); err != nil { return } - assert.Equal(t, int32(sslRequestCode), int32(binary.BigEndian.Uint32(request[4:]))) + assert.Equal(t, uint32(sslRequestCode), binary.BigEndian.Uint32(request[4:])) _, _ = conn.Write([]byte("N")) }() _, err = config.DialFunc(context.Background(), "tcp", ln.Addr().String()) From e0ba3275007dbce2ca24552621ab72d60127b4dc Mon Sep 17 00:00:00 2001 From: 7ttp <117663341+7ttp@users.noreply.github.com> Date: Wed, 29 Jul 2026 05:38:08 +0530 Subject: [PATCH 3/6] fix --- apps/cli-go/internal/debug/postgres.go | 10 ++++++++++ apps/cli-go/internal/gen/types/types.go | 7 ++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/apps/cli-go/internal/debug/postgres.go b/apps/cli-go/internal/debug/postgres.go index 79254ed282..9558494c93 100644 --- a/apps/cli-go/internal/debug/postgres.go +++ b/apps/cli-go/internal/debug/postgres.go @@ -10,6 +10,7 @@ import ( "log" "net" "os" + "time" "github.com/jackc/pgproto3/v2" "github.com/jackc/pgx/v4" @@ -99,6 +100,15 @@ const sslRequestCode = 80877103 // handshakes eagerly so a refusal or bad certificate fails the dial rather than // surfacing as a parse error inside the forwarding goroutines. func startTLS(ctx context.Context, conn net.Conn, tlsConfig *tls.Config) (net.Conn, error) { + // pgconn only watches ctx once DialFunc returns, so bound the negotiation here + // or an endpoint that accepts TCP and never replies hangs the read forever. + if deadline, ok := ctx.Deadline(); ok { + if err := conn.SetDeadline(deadline); err != nil { + conn.Close() + return nil, err + } + defer func() { _ = conn.SetDeadline(time.Time{}) }() + } if err := binary.Write(conn, binary.BigEndian, []int32{8, sslRequestCode}); err != nil { conn.Close() return nil, err diff --git a/apps/cli-go/internal/gen/types/types.go b/apps/cli-go/internal/gen/types/types.go index c12a7b58eb..688ab6302f 100644 --- a/apps/cli-go/internal/gen/types/types.go +++ b/apps/cli-go/internal/gen/types/types.go @@ -16,7 +16,6 @@ import ( "github.com/jackc/pgconn" "github.com/jackc/pgx/v4" "github.com/spf13/afero" - "github.com/spf13/viper" "github.com/supabase/cli/internal/utils" "github.com/supabase/cli/pkg/api" ) @@ -192,10 +191,8 @@ func isRequireSSL(ctx context.Context, dbUrl string, options ...func(*pgx.ConnCo } return false, err } - // SSL is not supported in debug mode - require := !viper.GetBool("DEBUG") - debugf("isRequireSSL result require_ssl=%t debug_mode=%t", require, viper.GetBool("DEBUG")) - return require, conn.Close(ctx) + debugf("isRequireSSL result require_ssl=true") + return true, conn.Close(ctx) } func IsSSLDebugEnabled() bool { From 99bbeea9571740ed6b9921181b5ba49779e20120 Mon Sep 17 00:00:00 2001 From: 7ttp <117663341+7ttp@users.noreply.github.com> Date: Wed, 29 Jul 2026 05:53:03 +0530 Subject: [PATCH 4/6] fix: preserve sslmode=allow tls fallback under debug --- apps/cli-go/internal/debug/postgres.go | 44 ++++++++++++++++++++------ 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/apps/cli-go/internal/debug/postgres.go b/apps/cli-go/internal/debug/postgres.go index 9558494c93..aef7cb76b0 100644 --- a/apps/cli-go/internal/debug/postgres.go +++ b/apps/cli-go/internal/debug/postgres.go @@ -19,45 +19,69 @@ import ( type Proxy struct { dialContext func(ctx context.Context, network, addr string) (net.Conn, error) - // tlsConfig is what pgx resolved from sslmode. DialFunc completes the - // handshake itself, so logged frames are plaintext in memory but not on the wire. - tlsConfig *tls.Config - errChan chan error + // tlsPlan is pgconn's TLS config per attempt, primary first. DialFunc walks it + // so sslmode=allow keeps its plaintext-then-TLS retry, and completes the + // handshake itself, leaving logged frames plaintext in memory but not on the wire. + tlsPlan []*tls.Config + attempts map[string]int + errChan chan error } func NewProxy() Proxy { dialer := net.Dialer{} return Proxy{ dialContext: dialer.DialContext, + attempts: map[string]int{}, errChan: make(chan error, 1), } } func SetupPGX(config *pgx.ConnConfig) { + tlsPlan := []*tls.Config{config.TLSConfig} + for _, fallback := range config.Fallbacks { + if fallback.Host != config.Host { + break + } + tlsPlan = append(tlsPlan, fallback.TLSConfig) + } proxy := Proxy{ dialContext: config.DialFunc, - tlsConfig: config.TLSConfig, + tlsPlan: tlsPlan, + attempts: map[string]int{}, errChan: make(chan error, 1), } config.DialFunc = proxy.DialFunc // pgx must not negotiate TLS again over the in-memory pipe; clearing these // *without* DialFunc's handshake is what downgraded sslmode=require (#5872). - // Every attempt then reuses the primary's config, which pgconn only leaves - // plaintext for sslmode=disable and =allow (config.go:772-780), so a required - // connection stays encrypted; =allow loses its opportunistic TLS retry. config.TLSConfig = nil for _, fallback := range config.Fallbacks { fallback.TLSConfig = nil } } +// nextTLSConfig returns the TLS config for this attempt against addr. pgconn dials +// each plan entry once per resolved address, in plan order, so a per-address +// counter replays the same TLS/plaintext sequence it would have used itself. +func (p *Proxy) nextTLSConfig(addr string) *tls.Config { + if p.attempts == nil { + p.attempts = map[string]int{} + } + i := p.attempts[addr] + p.attempts[addr]++ + if i < len(p.tlsPlan) { + return p.tlsPlan[i] + } + return nil +} + func (p *Proxy) DialFunc(ctx context.Context, network, addr string) (net.Conn, error) { + tlsConfig := p.nextTLSConfig(addr) serverConn, err := p.dialContext(ctx, network, addr) if err != nil { return nil, err } - if p.tlsConfig != nil { - if serverConn, err = startTLS(ctx, serverConn, p.tlsConfig); err != nil { + if tlsConfig != nil { + if serverConn, err = startTLS(ctx, serverConn, tlsConfig); err != nil { return nil, err } } From e9d8a40861222ab8f5f0561d8505a679416cd243 Mon Sep 17 00:00:00 2001 From: 7ttp <117663341+7ttp@users.noreply.github.com> Date: Wed, 29 Jul 2026 06:12:00 +0530 Subject: [PATCH 5/6] fix: keep the no-plaintext fallback rule inside the debug tls plan --- apps/cli-go/internal/debug/postgres.go | 16 +++++++++++++--- .../shared/legacy-pgdelta-ssl-probe.layer.ts | 8 ++------ 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/apps/cli-go/internal/debug/postgres.go b/apps/cli-go/internal/debug/postgres.go index aef7cb76b0..c0ace9d57a 100644 --- a/apps/cli-go/internal/debug/postgres.go +++ b/apps/cli-go/internal/debug/postgres.go @@ -42,6 +42,11 @@ func SetupPGX(config *pgx.ConnConfig) { if fallback.Host != config.Host { break } + // ConnectByUrl drops plaintext fallbacks once the primary is TLS, and it + // runs after this, so apply the same rule here or --debug reinstates them. + if config.TLSConfig != nil && fallback.TLSConfig == nil { + continue + } tlsPlan = append(tlsPlan, fallback.TLSConfig) } proxy := Proxy{ @@ -66,12 +71,17 @@ func (p *Proxy) nextTLSConfig(addr string) *tls.Config { if p.attempts == nil { p.attempts = map[string]int{} } + if len(p.tlsPlan) == 0 { + return nil + } i := p.attempts[addr] p.attempts[addr]++ - if i < len(p.tlsPlan) { - return p.tlsPlan[i] + // pgconn redials an addr for the target_session_attrs retry, so clamp rather + // than fall off the plan into plaintext. + if i >= len(p.tlsPlan) { + i = len(p.tlsPlan) - 1 } - return nil + return p.tlsPlan[i] } func (p *Proxy) DialFunc(ctx context.Context, network, addr string) (net.Conn, error) { diff --git a/apps/cli/src/legacy/shared/legacy-pgdelta-ssl-probe.layer.ts b/apps/cli/src/legacy/shared/legacy-pgdelta-ssl-probe.layer.ts index 4d2e0f02b5..965d83e21c 100644 --- a/apps/cli/src/legacy/shared/legacy-pgdelta-ssl-probe.layer.ts +++ b/apps/cli/src/legacy/shared/legacy-pgdelta-ssl-probe.layer.ts @@ -1,7 +1,6 @@ import { Effect, Layer } from "effect"; import * as net from "node:net"; -import { LegacyDebugFlag } from "../../shared/legacy/global-flags.ts"; import { LegacyPgDeltaSslProbe, LegacyPgDeltaSslProbeError, @@ -76,10 +75,7 @@ export function legacyInterpretSslProbeByte(byte: number | undefined): "tls" | " */ export const legacyPgDeltaSslProbeLayer = Layer.effect( LegacyPgDeltaSslProbe, - Effect.gen(function* () { - // Go disables SSL in debug mode (`require := !viper.GetBool("DEBUG")`), so a - // server that speaks TLS still reports "not required" under `--debug`. - const debug = yield* LegacyDebugFlag; + Effect.sync(() => { const probeTarget = (target: LegacySslProbeTarget) => Effect.gen(function* () { const outcome = yield* Effect.callback<"tls" | "refused", LegacyPgDeltaSslProbeError>( @@ -136,7 +132,7 @@ export const legacyPgDeltaSslProbeLayer = Layer.effect( }, ); if (outcome === "refused") return false; - return !debug; + return true; }); return LegacyPgDeltaSslProbe.of({ requireSsl: (dbUrl) => From 613b1862ae4cc6641915955c78b93562a0068094 Mon Sep 17 00:00:00 2001 From: 7ttp <117663341+7ttp@users.noreply.github.com> Date: Wed, 29 Jul 2026 16:17:06 +0530 Subject: [PATCH 6/6] fix: pass the pgmeta ca bundle under --debug in gen types --- apps/cli/src/legacy/commands/gen/types/types.handler.ts | 4 +--- .../legacy/commands/gen/types/types.integration.test.ts | 7 +++++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/apps/cli/src/legacy/commands/gen/types/types.handler.ts b/apps/cli/src/legacy/commands/gen/types/types.handler.ts index 3f090e6090..5f4caa1dbf 100644 --- a/apps/cli/src/legacy/commands/gen/types/types.handler.ts +++ b/apps/cli/src/legacy/commands/gen/types/types.handler.ts @@ -2,7 +2,6 @@ import { loadProjectConfig } from "@supabase/config"; import { ChildProcessSpawner } from "effect/unstable/process"; import { Effect, FileSystem, Option, Path, Stdio, Stream } from "effect"; import { - LegacyDebugFlag, LegacyDnsResolverFlag, LegacyNetworkIdFlag, } from "../../../../shared/legacy/global-flags.ts"; @@ -192,7 +191,6 @@ export const legacyGenTypes = Effect.fn("legacy.gen.types")(function* (flags: Le const stdio = yield* Stdio.Stdio; const networkId = yield* LegacyNetworkIdFlag; const dnsResolver = yield* LegacyDnsResolverFlag; - const debug = yield* LegacyDebugFlag; const spawner = yield* ChildProcessSpawner.ChildProcessSpawner; const rawArgs = yield* stdio.args; const platformApi = yield* LegacyPlatformApiFactory; @@ -426,7 +424,7 @@ export const legacyGenTypes = Effect.fn("legacy.gen.types")(function* (flags: Le } const useTls = yield* sslProbe.requireSslForHost(target.probeHost, target.probePort); - if (useTls && !debug) { + if (useTls) { env.push(`PG_META_DB_SSL_ROOT_CERT=${legacyRootCaBundle()}`); } diff --git a/apps/cli/src/legacy/commands/gen/types/types.integration.test.ts b/apps/cli/src/legacy/commands/gen/types/types.integration.test.ts index 5d75f2caa9..4488a603c6 100644 --- a/apps/cli/src/legacy/commands/gen/types/types.integration.test.ts +++ b/apps/cli/src/legacy/commands/gen/types/types.integration.test.ts @@ -2883,7 +2883,10 @@ describe("legacy gen types", () => { }), ); - it.live("omits the CA bundle env var in --debug mode even when TLS is supported", () => + // Go's `GetRootCA` no longer special-cases `--debug`: `isRequireSSL` returns true + // on any successful probe (`types.go:194-195`), so the bundle is passed to pgmeta + // regardless of the flag. + it.live("passes the CA bundle env var in --debug mode when TLS is supported", () => Effect.tryPromise({ try: () => withSslProbeServer(async (port) => { @@ -2903,7 +2906,7 @@ describe("legacy gen types", () => { ).pipe(Effect.provide(layer)), ); - expect(docker.env.startsWith("PG_META_DB_SSL_ROOT_CERT=")).toBe(false); + expect(docker.env.startsWith("PG_META_DB_SSL_ROOT_CERT=")).toBe(true); }, "S"), catch: (cause) => (cause instanceof Error ? cause : new Error(String(cause))), }),