Repository: dagger/dagger
Pull request #10248: feat: move http auth methods to top-level git
Author: login: jedevc
Created: 2025-04-23T14:10:35Z | Merged: 2025-04-29T10:08:32Z

...and deprecate the standalone `WithAuthToken` and `WithAuthHeader` methods.
    
Originally, this started as just an attempt to configure HTTP and SSH authentication similarly - we wanted to standardize on doing it all in the top-level constructor, or all using `With` helpers. I have a preference for keeping at the top-level, so that a user can't mistakenly do `Directory.AsGit().WithAuthToken()`, which wouldn't be used. Additionally, we're currently relying on the fact that `dag.Git` doesn't *actually* query anything in the git repository, all operations are deferred till later - but we very well may want to change that in the future (especially as we get more caching enhancements). However, as I refactored the `git` implementation, I realized there's a bigger inconsistency here.

Prior to this refactor, we were loading credentials entirely inconsistently. While for SSH, we would avoid a potentially expensive request to the client for credentials if we were already provided them, for HTTP, we were unconditionally just fetching them. This resulted in a ton of code sprawl, which, if we move everything to the constructor, is vastly simplified.

TODO:
- [x] Design consensus (see :thread: https://discord.com/channels/707636530424053791/1346856793074307202)
	> @shykes
	> I think constructor as you suggested is good
	> I just wanted to make sure you didn't take inspiration from `Container.withRegistryAuth` in your quest for consistency
	>
	> @jedevc
	> happy to rework that one as a separate pr? 
	>
	> @shykes
	> That would be amazing, it's been on my list for ages but I keep not getting around to it
- [x] Implementation
- [x] Tests


Diff:
diff --git a/core/git.go b/core/git.go
index 044cead8505..b582faad872 100644
--- a/core/git.go
+++ b/core/git.go
@@ -271,7 +271,7 @@ func (repo *RemoteGitRepository) setup(ctx context.Context) (_ *gitutil.GitCLI,
 		})
 	}
 
-	netConf, err := repo.dnsConfig(ctx)
+	netConf, err := DNSConfig(ctx, repo.Query)
 	if err != nil {
 		return nil, nil, err
 	}
@@ -291,7 +291,7 @@ func (repo *RemoteGitRepository) setup(ctx context.Context) (_ *gitutil.GitCLI,
 	return gitutil.NewGitCLI(opts...), cleanups.Run, nil
 }
 
-func (repo *RemoteGitRepository) dnsConfig(ctx context.Context) (*oci.DNSConfig, error) {
+func DNSConfig(ctx context.Context, query *Query) (*oci.DNSConfig, error) {
 	clientMetadata, err := engine.ClientMetadataFromContext(ctx)
 	if err != nil {
 		return nil, err
@@ -301,7 +301,7 @@ func (repo *RemoteGitRepository) dnsConfig(ctx context.Context) (*oci.DNSConfig,
 	clientDomains := []string{}
 	clientDomains = append(clientDomains, network.SessionDomain(namespace))
 
-	dns := *repo.Query.DNS()
+	dns := *query.DNS()
 	dns.SearchDomains = append(clientDomains, dns.SearchDomains...)
 	return &dns, nil
 }
diff --git a/core/integration/git_test.go b/core/integration/git_test.go
index 00d8a8d2b5a..9e726eece7d 100644
--- a/core/integration/git_test.go
+++ b/core/integration/git_test.go
@@ -431,8 +431,9 @@ func (GitSuite) TestAuthProviders(ctx context.Context, t *testctx.T) {
 		token, err := decodeAndTrimPAT(pat)
 		require.NoError(t, err)
 
-		_, err = c.Git("https://github.com/grouville/daggerverse-private.git").
-			WithAuthToken(c.SetSecret("github_pat", token)).
+		_, err = c.Git("https://github.com/grouville/daggerverse-private.git", dagger.GitOpts{
+			HTTPAuthToken: c.SetSecret("github_pat", token),
+		}).
 			Branch("main").
 			Tree().
 			File("LICENSE").
@@ -446,8 +447,9 @@ func (GitSuite) TestAuthProviders(ctx context.Context, t *testctx.T) {
 		token, err := decodeAndTrimPAT(pat)
 		require.NoError(t, err)
 
-		_, err = c.Git("https://bitbucket.org/dagger-modules/private-modules-test.git").
-			WithAuthToken(c.SetSecret("bitbucket_pat", token)).
+		_, err = c.Git("https://bitbucket.org/dagger-modules/private-modules-test.git", dagger.GitOpts{
+			HTTPAuthToken: c.SetSecret("bitbucket_pat", token),
+		}).
 			Branch("main").
 			Tree().
 			File("README.md").
@@ -461,8 +463,9 @@ func (GitSuite) TestAuthProviders(ctx context.Context, t *testctx.T) {
 		token, err := decodeAndTrimPAT(pat)
 		require.NoError(t, err)
 
-		_, err = c.Git("https://gitlab.com/dagger-modules/private/test/more/dagger-test-modules-private.git").
-			WithAuthToken(c.SetSecret("gitlab_pat", token)).
+		_, err = c.Git("https://gitlab.com/dagger-modules/private/test/more/dagger-test-modules-private.git", dagger.GitOpts{
+			HTTPAuthToken: c.SetSecret("gitlab_pat", token),
+		}).
 			Branch("main").
 			Tree().
 			File("README.md").
@@ -507,8 +510,10 @@ func (GitSuite) TestAuth(ctx context.Context, t *testctx.T) {
 	})
 
 	t.Run("incorrect auth", func(ctx context.Context, t *testctx.T) {
-		_, err := c.Git(repoURL, dagger.GitOpts{ExperimentalServiceHost: gitDaemon}).
-			WithAuthToken(c.SetSecret("token-wrong", "wrong")).
+		_, err := c.Git(repoURL, dagger.GitOpts{
+			ExperimentalServiceHost: gitDaemon,
+			HTTPAuthToken:           c.SetSecret("token-wrong", "wrong"),
+		}).
 			Branch("main").
 			Tree().
 			File("README.md").
@@ -518,8 +523,43 @@ func (GitSuite) TestAuth(ctx context.Context, t *testctx.T) {
 	})
 
 	t.Run("token auth", func(ctx context.Context, t *testctx.T) {
-		dt, err := c.Git(repoURL, dagger.GitOpts{ExperimentalServiceHost: gitDaemon}).
-			WithAuthToken(c.SetSecret("token", "foobar")).
+		dt, err := c.Git(repoURL, dagger.GitOpts{
+			ExperimentalServiceHost: gitDaemon,
+			HTTPAuthToken:           c.SetSecret("token", "foobar"),
+		}).
+			Branch("main").
+			Tree().
+			File("README.md").
+			Contents(ctx)
+		require.NoError(t, err)
+		require.Equal(t, "Hello, world!", dt)
+	})
+
+	t.Run("header auth", func(ctx context.Context, t *testctx.T) {
+		dt, err := c.Git(repoURL, dagger.GitOpts{
+			ExperimentalServiceHost: gitDaemon,
+			HTTPAuthHeader:          c.SetSecret("header", "basic "+base64.StdEncoding.EncodeToString([]byte("x-access-token:foobar"))),
+		}).
+			Branch("main").
+			Tree().
+			File("README.md").
+			Contents(ctx)
+		require.NoError(t, err)
+		require.Equal(t, "Hello, world!", dt)
+	})
+}
+
+func (GitSuite) TestWithAuth(ctx context.Context, t *testctx.T) {
+	// these were deprecated in dagger/dagger#10248
+
+	c := connect(ctx, t)
+	gitDaemon, repoURL := gitServiceHTTPWithBranch(ctx, t, c, c.Directory().WithNewFile("README.md", "Hello, world!"), "main", c.SetSecret("target", "foobar"))
+
+	t.Run("token auth", func(ctx context.Context, t *testctx.T) {
+		git := c.Git(repoURL, dagger.GitOpts{ExperimentalServiceHost: gitDaemon})
+		//nolint:staticcheck // SA1019 deprecated
+		git = git.WithAuthToken(c.SetSecret("token", "foobar"))
+		dt, err := git.
 			Branch("main").
 			Tree().
 			File("README.md").
@@ -529,8 +569,10 @@ func (GitSuite) TestAuth(ctx context.Context, t *testctx.T) {
 	})
 
 	t.Run("header auth", func(ctx context.Context, t *testctx.T) {
-		dt, err := c.Git(repoURL, dagger.GitOpts{ExperimentalServiceHost: gitDaemon}).
-			WithAuthHeader(c.SetSecret("header", "basic "+base64.StdEncoding.EncodeToString([]byte("x-access-token:foobar")))).
+		git := c.Git(repoURL, dagger.GitOpts{ExperimentalServiceHost: gitDaemon})
+		//nolint:staticcheck // SA1019 deprecated
+		git = git.WithAuthHeader(c.SetSecret("header", "basic "+base64.StdEncoding.EncodeToString([]byte("x-access-token:foobar"))))
+		dt, err := git.
 			Branch("main").
 			Tree().
 			File("README.md").
diff --git a/core/schema/git.go b/core/schema/git.go
index 9d741a893ab..440aef1e0e6 100644
--- a/core/schema/git.go
+++ b/core/schema/git.go
@@ -6,6 +6,7 @@ import (
 	"encoding/hex"
 	"errors"
 	"fmt"
+	"net/http"
 	"net/url"
 	"strconv"
 
@@ -14,14 +15,27 @@ import (
 	"github.com/dagger/dagger/engine"
 	"github.com/dagger/dagger/engine/server/resource"
 	"github.com/dagger/dagger/engine/slog"
+	"github.com/dagger/dagger/engine/sources/netconfhttp"
+	"github.com/moby/buildkit/executor/oci"
 
 	"github.com/dagger/dagger/util/gitutil"
 	"github.com/go-git/go-git/v5"
 	"github.com/go-git/go-git/v5/config"
 	"github.com/go-git/go-git/v5/plumbing/transport"
+	"github.com/go-git/go-git/v5/plumbing/transport/client"
+	githttp "github.com/go-git/go-git/v5/plumbing/transport/http"
 	"github.com/go-git/go-git/v5/storage/memory"
 )
 
+func init() {
+	// allow injection of custom dns resolver for go-git
+	customClient := &http.Client{
+		Transport: netconfhttp.NewInjectableTransport(&http.Transport{}),
+	}
+	client.InstallProtocol("http", githttp.NewClient(customClient))
+	client.InstallProtocol("https", githttp.NewClient(customClient))
+}
+
 var _ SchemaResolvers = &gitSchema{}
 
 type gitSchema struct {
@@ -40,6 +54,8 @@ func (s *gitSchema) Install() {
 			ArgDeprecated("keepGitDir", `Set to true to keep .git directory.`).
 			ArgDoc("sshKnownHosts", `Set SSH known hosts`).
 			ArgDoc("sshAuthSocket", `Set SSH auth socket`).
+			ArgDoc("httpAuthToken", `Secret used to populate the password during basic HTTP Authorization`).
+			ArgDoc("httpAuthHeader", `Secret used to populate the Authorization HTTP header`).
 			ArgDoc("experimentalServiceHost", `A service which must be started before the repo is fetched.`),
 		dagql.NodeFuncWithCacheKey("git", s.gitLegacy, dagql.CachePerClient).
 			View(BeforeVersion("v0.13.4")).
@@ -75,9 +91,11 @@ func (s *gitSchema) Install() {
 			ArgDoc("patterns", `Glob patterns (e.g., "refs/tags/v*").`),
 		dagql.Func("withAuthToken", s.withAuthToken).
 			Doc(`Token to authenticate the remote with.`).
+			Deprecated(`Use "httpAuthToken" in the constructor instead.`).
 			ArgDoc("token", `Secret used to populate the password during basic HTTP Authorization`),
 		dagql.Func("withAuthHeader", s.withAuthHeader).
 			Doc(`Header to authenticate the remote with.`).
+			Deprecated(`Use "httpAuthHeader" in the constructor instead.`).
 			ArgDoc("header", `Secret used to populate the Authorization HTTP header`),
 	}.Install(s.srv)
 
@@ -108,12 +126,27 @@ type gitArgs struct {
 
 	SSHKnownHosts string                        `name:"sshKnownHosts" default:""`
 	SSHAuthSocket dagql.Optional[core.SocketID] `name:"sshAuthSocket"`
+
+	HTTPAuthToken  dagql.Optional[core.SecretID] `name:"httpAuthToken"`
+	HTTPAuthHeader dagql.Optional[core.SecretID] `name:"httpAuthHeader"`
 }
 
 //nolint:gocyclo
 func (s *gitSchema) git(ctx context.Context, parent dagql.Instance[*core.Query], args gitArgs) (inst dagql.Instance[*core.GitRepository], _ error) {
-	// 1. Setup experimental service host
-	var svcs core.ServiceBindings
+	remote, err := gitutil.ParseURL(args.URL)
+	if errors.Is(err, gitutil.ErrUnknownProtocol) {
+		remote, err = gitutil.ParseURL("https://" + args.URL)
+	}
+	if err != nil {
+		return inst, fmt.Errorf("failed to parse Git URL: %w", err)
+	}
+
+	clientMetadata, err := engine.ClientMetadataFromContext(ctx)
+	if err != nil {
+		return inst, fmt.Errorf("failed to get client metadata from context: %w", err)
+	}
+
+	var gitServices core.ServiceBindings
 	if args.ExperimentalServiceHost.Valid {
 		svc, err := args.ExperimentalServiceHost.Value.Load(ctx, s.srv)
 		if err != nil {
@@ -123,191 +156,201 @@ func (s *gitSchema) git(ctx context.Context, parent dagql.Instance[*core.Query],
 		if err != nil {
 			return inst, err
 		}
-		svcs = append(svcs, core.ServiceBinding{
+		gitServices = append(gitServices, core.ServiceBinding{
 			ID:       svc.ID(),
 			Service:  svc.Self,
 			Hostname: host,
 		})
 	}
 
-	// 2. Get client metadata
-	clientMetadata, err := engine.ClientMetadataFromContext(ctx)
-	if err != nil {
-		return inst, fmt.Errorf("failed to get client metadata from context: %w", err)
-	}
+	var (
+		sshAuthSock    dagql.Instance[*core.Socket]
+		httpAuthToken  dagql.Instance[*core.Secret]
+		httpAuthHeader dagql.Instance[*core.Secret]
+	)
 
-	// 3. Setup authentication
-	var authSock dagql.Instance[*core.Socket]
-	var authToken dagql.Instance[*core.Secret]
-
-	// First parse the ref scheme to determine auth strategy
-	remote, err := gitutil.ParseURL(args.URL)
-	if errors.Is(err, gitutil.ErrUnknownProtocol) {
-		remote, err = gitutil.ParseURL("https://" + args.URL)
-	}
-	if err != nil {
-		return inst, fmt.Errorf("failed to parse Git URL: %w", err)
-	}
-	if remote.Scheme == "ssh" && (remote.User == nil || remote.User.Username() == "") {
-		// default to git user for SSH, otherwise weird incorrect defaults like "root" can get
-		// applied in various places. This matches the git module source implementation.
+	switch remote.Scheme {
+	case gitutil.SSHProtocol:
 		if remote.User == nil {
+			// default to git user for SSH, otherwise weird incorrect defaults
+			// like "root" can get applied in various places. This matches the
+			// git module source implementation.
 			remote.User = url.User("git")
 		}
-		pass, ok := remote.User.Password()
-		if ok {
-			remote.User = url.UserPassword(remote.User.Username(), pass)
-		}
-		fixedURL := &url.URL{
-			Scheme: remote.Scheme,
-			User:   remote.User,
-			Host:   remote.Host,
-			Path:   remote.Path,
-		}
-		if remote.Fragment != nil {
-			fixedURL.Fragment = remote.Fragment.Ref
-			if remote.Fragment.Subdir != "" {
-				fixedURL.Fragment += ":" + remote.Fragment.Subdir
-			}
-		}
-		args.URL = fixedURL.String()
-	}
 
-	// Handle explicit SSH socket if provided
-	switch {
-	case args.SSHAuthSocket.Valid:
-		sock, err := args.SSHAuthSocket.Value.Load(ctx, s.srv)
-		if err != nil {
-			return inst, err
-		}
-		authSock = sock
-
-	case remote.Scheme == "ssh" && clientMetadata != nil && clientMetadata.SSHAuthSocketPath != "":
-		// For SSH refs, try to load client's SSH socket if no explicit socket was provided
-		var sockInst dagql.Instance[*core.Socket]
-		if err := s.srv.Select(ctx, s.srv.Root(), &sockInst,
-			dagql.Selector{
-				Field: "host",
-			},
-			dagql.Selector{
-				Field: "unixSocket",
-				Args: []dagql.NamedInput{
-					{
-						Name:  "path",
-						Value: dagql.NewString(clientMetadata.SSHAuthSocketPath),
+		if args.SSHAuthSocket.Valid {
+			sshAuthSock, err = args.SSHAuthSocket.Value.Load(ctx, s.srv)
+			if err != nil {
+				return inst, err
+			}
+		} else if clientMetadata.SSHAuthSocketPath != "" {
+			// For SSH refs, try to load client's SSH socket if no explicit socket was provided
+			var sockInst dagql.Instance[*core.Socket]
+			if err := s.srv.Select(ctx, s.srv.Root(), &sockInst,
+				dagql.Selector{
+					Field: "host",
+				},
+				dagql.Selector{
+					Field: "unixSocket",
+					Args: []dagql.NamedInput{
+						{
+							Name:  "path",
+							Value: dagql.NewString(clientMetadata.SSHAuthSocketPath),
+						},
 					},
 				},
-			},
-		); err != nil {
-			return inst, fmt.Errorf("failed to select unix socket: %w", err)
-		}
+			); err != nil {
+				return inst, fmt.Errorf("failed to select unix socket: %w", err)
+			}
 
-		// reinvoke this API with the socket as an explicit arg so it shows up in the DAG
-		selectArgs := []dagql.NamedInput{
-			{
-				Name:  "url",
-				Value: dagql.NewString(args.URL),
-			},
-			{
-				Name:  "sshAuthSocket",
-				Value: dagql.Opt(dagql.NewID[*core.Socket](sockInst.ID())),
-			},
-		}
-		if args.KeepGitDir.Valid {
-			selectArgs = append(selectArgs, dagql.NamedInput{
-				Name:  "keepGitDir",
-				Value: dagql.Opt(args.KeepGitDir.Value),
-			})
-		}
-		if args.ExperimentalServiceHost.Valid {
-			selectArgs = append(selectArgs, dagql.NamedInput{
-				Name:  "experimentalServiceHost",
-				Value: dagql.Opt(dagql.NewID[*core.Service](args.ExperimentalServiceHost.Value.ID())),
-			})
+			// reinvoke this API with the socket as an explicit arg so it shows up in the DAG
+			selectArgs := []dagql.NamedInput{
+				{
+					Name:  "url",
+					Value: dagql.NewString(remote.String()),
+				},
+				{
+					Name:  "sshAuthSocket",
+					Value: dagql.Opt(dagql.NewID[*core.Socket](sockInst.ID())),
+				},
+			}
+			if args.KeepGitDir.Valid {
+				selectArgs = append(selectArgs, dagql.NamedInput{
+					Name:  "keepGitDir",
+					Value: dagql.Opt(args.KeepGitDir.Value),
+				})
+			}
+			if args.ExperimentalServiceHost.Valid {
+				selectArgs = append(selectArgs, dagql.NamedInput{
+					Name:  "experimentalServiceHost",
+					Value: dagql.Opt(dagql.NewID[*core.Service](args.ExperimentalServiceHost.Value.ID())),
+				})
+			}
+			if args.SSHKnownHosts != "" {
+				selectArgs = append(selectArgs, dagql.NamedInput{
+					Name:  "sshKnownHosts",
+					Value: dagql.Opt(dagql.NewString(args.SSHKnownHosts)),
+				})
+			}
+			err = s.srv.Select(ctx, parent, &inst, dagql.Selector{Field: "git", Args: selectArgs})
+			return inst, err
+		} else {
+			return inst, fmt.Errorf("SSH URLs are not supported without an SSH socket")
 		}
-		if args.SSHKnownHosts != "" {
-			selectArgs = append(selectArgs, dagql.NamedInput{
-				Name:  "sshKnownHosts",
-				Value: dagql.Opt(dagql.NewString(args.SSHKnownHosts)),
-			})
+	case gitutil.HTTPProtocol, gitutil.HTTPSProtocol:
+		if args.HTTPAuthToken.Valid {
+			httpAuthToken, err = args.HTTPAuthToken.Value.Load(ctx, s.srv)
+			if err != nil {
+				return inst, err
+			}
 		}
-		err = s.srv.Select(ctx, parent, &inst, dagql.Selector{Field: "git", Args: selectArgs})
-		return inst, err
-
-	case remote.Scheme == "ssh":
-		return inst, fmt.Errorf("SSH URLs are not supported without an SSH socket")
-	}
-
-	// For HTTP(S) refs, handle PAT auth if we're the main client
-	if (remote.Scheme == "https" || remote.Scheme == "http") && clientMetadata != nil {
-		parentClientMetadata, err := parent.Self.NonModuleParentClientMetadata(ctx)
-		if err != nil {
-			return inst, fmt.Errorf("failed to retrieve non-module parent client metadata: %w", err)
+		if args.HTTPAuthHeader.Valid {
+			httpAuthHeader, err = args.HTTPAuthHeader.Value.Load(ctx, s.srv)
+			if err != nil {
+				return inst, err
+			}
 		}
+		if httpAuthToken.Self == nil && httpAuthHeader.Self == nil {
+			// For HTTP refs, try to load client credentials from the git helper
+			parentClientMetadata, err := parent.Self.NonModuleParentClientMetadata(ctx)
+			if err != nil {
+				return inst, fmt.Errorf("failed to retrieve non-module parent client metadata: %w", err)
+			}
+			if clientMetadata.ClientID != parentClientMetadata.ClientID {
+				// only handle PAT auth if we're the main client
+				break
+			}
 
-		if clientMetadata.ClientID == parentClientMetadata.ClientID {
-			// Check if repo is public
-			repo := git.NewRemote(memory.NewStorage(), &config.RemoteConfig{
-				Name: "origin",
-				URLs: []string{remote.Remote()},
-			})
-
-			_, err := repo.ListContext(ctx, &git.ListOptions{Auth: nil})
-			switch {
-			case err == nil:
-				// no auth needed
-
-			case errors.Is(err, transport.ErrAuthenticationRequired):
-				// Only proceed with auth if repo requires authentication
-				authCtx := engine.ContextWithClientMetadata(ctx, parentClientMetadata)
-
-				bk, err := parent.Self.Buildkit(authCtx)
+			// start services if needed, before checking for auth
+			var dnsConfig *oci.DNSConfig
+			if len(gitServices) > 0 {
+				svcs, err := parent.Self.Services(ctx)
 				if err != nil {
-					return inst, fmt.Errorf("failed to get buildkit: %w", err)
+					return inst, fmt.Errorf("failed to get services: %w", err)
 				}
+				detach, _, err := svcs.StartBindings(ctx, gitServices)
+				if err != nil {
+					return inst, err
+				}
+				defer detach()
 
-				// Retrieve credential from host
-				credentials, err := bk.GetCredential(authCtx, remote.Scheme, remote.Host, remote.Path)
-				switch {
-				case err != nil || credentials == nil || credentials.Password == "":
-					// it's possible to provide auth tokens via chained API calls, so warn now but
-					// don't fail. Auth will be checked again before relevant operations later.
-					slog.Warn("Failed to retrieve git credentials: %v", err)
-
-				default:
-					// Credentials found, create and set auth token
-					hash := sha256.Sum256([]byte(credentials.Password))
-					secretName := hex.EncodeToString(hash[:])
-					var secretAuthToken dagql.Instance[*core.Secret]
-					if err := s.srv.Select(authCtx, s.srv.Root(), &secretAuthToken,
-						dagql.Selector{
-							Field: "setSecret",
-							Args: []dagql.NamedInput{
-								{
-									Name:  "name",
-									Value: dagql.NewString(secretName),
-								},
-								{
-									Name:  "plaintext",
-									Value: dagql.NewString(credentials.Password),
-								},
-							},
-						},
-					); err != nil {
-						return inst, fmt.Errorf("failed to create a new secret with the git auth token: %w", err)
-					}
-					authToken = secretAuthToken
+				dnsConfig, err = core.DNSConfig(ctx, parent.Self)
+				if err != nil {
+					return inst, err
 				}
+			}
 
-			default:
+			public, err := isRemotePublic(netconfhttp.WithDNSConfig(ctx, dnsConfig), remote)
+			if err != nil {
+				return inst, err
+			}
+			if public {
+				break
+			}
+
+			// Retrieve credential from host
+			authCtx := engine.ContextWithClientMetadata(ctx, parentClientMetadata)
+			bk, err := parent.Self.Buildkit(authCtx)
+			if err != nil {
+				return inst, fmt.Errorf("failed to get buildkit: %w", err)
+			}
+			credentials, err := bk.GetCredential(authCtx, remote.Scheme, remote.Host, remote.Path)
+			if err != nil {
 				// it's possible to provide auth tokens via chained API calls, so warn now but
 				// don't fail. Auth will be checked again before relevant operations later.
-				slog.Warn("failed to list remote refs: %v", err)
+				slog.Warn("Failed to retrieve git credentials: %v", err)
+				break
 			}
+
+			hash := sha256.Sum256([]byte(credentials.Password))
+			secretName := hex.EncodeToString(hash[:])
+			var authToken dagql.Instance[*core.Secret]
+			if err := s.srv.Select(authCtx, s.srv.Root(), &authToken,
+				dagql.Selector{
+					Field: "setSecret",
+					Args: []dagql.NamedInput{
+						{
+							Name:  "name",
+							Value: dagql.NewString(secretName),
+						},
+						{
+							Name:  "plaintext",
+							Value: dagql.NewString(credentials.Password),
+						},
+					},
+				},
+			); err != nil {
+				return inst, fmt.Errorf("failed to create a new secret with the git auth token: %w", err)
+			}
+
+			// reinvoke this API with the socket as an explicit arg so it shows up in the DAG
+			selectArgs := []dagql.NamedInput{
+				{
+					Name:  "url",
+					Value: dagql.NewString(remote.String()),
+				},
+				{
+					Name:  "httpAuthToken",
+					Value: dagql.Opt(dagql.NewID[*core.Secret](authToken.ID())),
+				},
+			}
+			if args.KeepGitDir.Valid {
+				selectArgs = append(selectArgs, dagql.NamedInput{
+					Name:  "keepGitDir",
+					Value: dagql.Opt(args.KeepGitDir.Value),
+				})
+			}
+			if args.ExperimentalServiceHost.Valid {
+				selectArgs = append(selectArgs, dagql.NamedInput{
+					Name:  "experimentalServiceHost",
+					Value: dagql.Opt(dagql.NewID[*core.Service](args.ExperimentalServiceHost.Value.ID())),
+				})
+			}
+			err = s.srv.Select(ctx, parent, &inst, dagql.Selector{Field: "git", Args: selectArgs})
+			return inst, err
 		}
 	}
 
-	// 4. Handle git directory configuration
 	discardGitDir := false
 	if args.KeepGitDir.Valid {
 		slog.Warn("The 'keepGitDir' argument is deprecated. Use `tree`'s `discardGitDir' instead.")
@@ -320,8 +363,10 @@ func (s *gitSchema) git(ctx context.Context, parent dagql.Instance[*core.Query],
 			Query:         parent.Self,
 			URL:           remote,
 			SSHKnownHosts: args.SSHKnownHosts,
-			SSHAuthSocket: authSock.Self,
-			Services:      svcs,
+			SSHAuthSocket: sshAuthSock.Self,
+			AuthToken:     httpAuthToken,
+			AuthHeader:    httpAuthHeader,
+			Services:      gitServices,
 			Platform:      parent.Self.Platform(),
 		},
 		DiscardGitDir: discardGitDir,
@@ -330,33 +375,15 @@ func (s *gitSchema) git(ctx context.Context, parent dagql.Instance[*core.Query],
 		return inst, fmt.Errorf("failed to create GitRepository instance: %w", err)
 	}
 
-	// set the auth token by selecting withAuthToken so that it shows up in the dagql call
-	// as a secret and can thus be passed to functions
-	if authToken.Self != nil {
-		var instWithToken dagql.Instance[*core.GitRepository]
-		err := s.srv.Select(ctx, inst, &instWithToken,
-			dagql.Selector{
-				Field: "withAuthToken",
-				Args: []dagql.NamedInput{
-					{
-						Name:  "token",
-						Value: dagql.NewID[*core.Secret](authToken.ID()),
-					},
-				},
-			},
-		)
-		if err != nil {
-			return inst, fmt.Errorf("failed to set auth token: %w", err)
-		}
-		inst = instWithToken
-	}
-
 	var resourceIDs []*resource.ID
-	if authToken.Self != nil {
-		resourceIDs = append(resourceIDs, &resource.ID{ID: *authToken.ID()})
+	if sshAuthSock.Self != nil {
+		resourceIDs = append(resourceIDs, &resource.ID{ID: *sshAuthSock.ID()})
+	}
+	if httpAuthToken.Self != nil {
+		resourceIDs = append(resourceIDs, &resource.ID{ID: *httpAuthToken.ID()})
 	}
-	if authSock.Self != nil {
-		resourceIDs = append(resourceIDs, &resource.ID{ID: *authSock.ID()})
+	if httpAuthHeader.Self != nil {
+		resourceIDs = append(resourceIDs, &resource.ID{ID: *httpAuthHeader.ID()})
 	}
 	if len(resourceIDs) > 0 {
 		postCall, err := core.ResourceTransferPostCall(ctx, parent.Self, clientMetadata.ClientID, resourceIDs...)
@@ -366,9 +393,26 @@ func (s *gitSchema) git(ctx context.Context, parent dagql.Instance[*core.Query],
 
 		inst = inst.WithPostCall(postCall)
 	}
+
 	return inst, nil
 }
 
+func isRemotePublic(ctx context.Context, remote *gitutil.GitURL) (bool, error) {
+	// check if repo is public
+	repo := git.NewRemote(memory.NewStorage(), &config.RemoteConfig{
+		Name: "origin",
+		URLs: []string{remote.Remote()},
+	})
+	_, err := repo.ListContext(ctx, &git.ListOptions{Auth: nil})
+	if err != nil {
+		if errors.Is(err, transport.ErrAuthenticationRequired) {
+			return false, nil
+		}
+		return false, err
+	}
+	return true, nil
+}
+
 type gitArgsLegacy struct {
 	URL                     string
 	KeepGitDir              bool `default:"false"`
diff --git a/docs/docs-graphql/schema.graphqls b/docs/docs-graphql/schema.graphqls
index 7bde9d1583f..28b98213e56 100644
--- a/docs/docs-graphql/schema.graphqls
+++ b/docs/docs-graphql/schema.graphqls
@@ -2454,13 +2454,13 @@ type GitRepository {
   withAuthHeader(
     """Secret used to populate the Authorization HTTP header"""
     header: SecretID!
-  ): GitRepository!
+  ): GitRepository! @deprecated(reason: "Use \"httpAuthHeader\" in the constructor instead.")
 
   """Token to authenticate the remote with."""
   withAuthToken(
     """Secret used to populate the password during basic HTTP Authorization"""
     token: SecretID!
-  ): GitRepository!
+  ): GitRepository! @deprecated(reason: "Use \"httpAuthToken\" in the constructor instead.")
 }
 
 """
@@ -3250,6 +3250,12 @@ type Query {
 
     """Set SSH auth socket"""
     sshAuthSocket: SocketID
+
+    """Secret used to populate the password during basic HTTP Authorization"""
+    httpAuthToken: SecretID
+
+    """Secret used to populate the Authorization HTTP header"""
+    httpAuthHeader: SecretID
   ): GitRepository!
 
   """Queries the host environment."""
diff --git a/docs/static/api/reference/index.html b/docs/static/api/reference/index.html
index 3d61fc7fa2c..296ef5af6cb 100644
--- a/docs/static/api/reference/index.html
+++ b/docs/static/api/reference/index.html
@@ -854,6 +854,18 @@ <h5>Arguments</h5>
                         </td>
                         <td> Set SSH auth socket </td>
                       </tr>
+                      <tr>
+                        <td>
+                          <span class="property-name"><code>httpAuthToken</code></span> - <span class="property-type"><a href="#definition-SecretID"><code>SecretID</code></a></span>
+                        </td>
+                        <td> Secret used to populate the password during basic HTTP Authorization </td>
+                      </tr>
+                      <tr>
+                        <td>
+                          <span class="property-name"><code>httpAuthHeader</code></span> - <span class="property-type"><a href="#definition-SecretID"><code>SecretID</code></a></span>
+                        </td>
+                        <td> Secret used to populate the Authorization HTTP header </td>
+                      </tr>
                     </tbody>
                   </table>
                 </div>
@@ -8233,8 +8245,9 @@ <h6 class="field-argument-name"><span class="property-name"><code>patterns</code
                         </td>
                       </tr>
                       <tr class="row-has-field-arguments">
-                        <td data-property-name=""><a class="property-name" id="GitRepository-withAuthHeader" href="#GitRepository-withAuthHeader"><code>withAuthHeader</code></a> - <span class="property-type"><a href="#definition-GitRepository"><code>GitRepository!</code></a></span> </td>
-                        <td> Header to authenticate the remote with. </td>
+                        <td data-property-name="" class="definition-deprecated"><a class="property-name" id="GitRepository-withAuthHeader" href="#GitRepository-withAuthHeader"><code>withAuthHeader</code></a> - <span class="property-type"><a href="#definition-GitRepository"><code>GitRepository!</code></a></span> </td>
+                        <td> Header to authenticate the remote with. <span class="deprecation-reason">Use "httpAuthHeader" in the constructor instead.</span>
+                        </td>
                       </tr>
                       <tr class="row-field-arguments">
                         <td colspan="2">
@@ -8250,8 +8263,9 @@ <h6 class="field-argument-name"><span class="property-name"><code>header</code><
                         </td>
                       </tr>
                       <tr class="row-has-field-arguments">
-                        <td data-property-name=""><a class="property-name" id="GitRepository-withAuthToken" href="#GitRepository-withAuthToken"><code>withAuthToken</code></a> - <span class="property-type"><a href="#definition-GitRepository"><code>GitRepository!</code></a></span> </td>
-                        <td> Token to authenticate the remote with. </td>
+                        <td data-property-name="" class="definition-deprecated"><a class="property-name" id="GitRepository-withAuthToken" href="#GitRepository-withAuthToken"><code>withAuthToken</code></a> - <span class="property-type"><a href="#definition-GitRepository"><code>GitRepository!</code></a></span> </td>
+                        <td> Token to authenticate the remote with. <span class="deprecation-reason">Use "httpAuthToken" in the constructor instead.</span>
+                        </td>
                       </tr>
                       <tr class="row-field-arguments">
                         <td colspan="2">
diff --git a/docs/static/reference/php/Dagger/Client.html b/docs/static/reference/php/Dagger/Client.html
index 171bdaa42a2..569d041ea61 100644
--- a/docs/static/reference/php/Dagger/Client.html
+++ b/docs/static/reference/php/Dagger/Client.html
@@ -288,7 +288,7 @@ <h2>Methods</h2>
                     <a href="../Dagger/GitRepository.html"><abbr title="Dagger\GitRepository">GitRepository</abbr></a>
                 </div>
                 <div class="col-md-8">
-                    <a href="#method_git">git</a>(string $url, bool|null $keepGitDir = true, <abbr title="Dagger\Dagger\ServiceId|Dagger\Service|null">Service|null</abbr> $experimentalServiceHost = null, string|null $sshKnownHosts = &#039;&#039;, <abbr title="Dagger\Dagger\SocketId|Dagger\Socket|null">Socket|null</abbr> $sshAuthSocket = null)
+                    <a href="#method_git">git</a>(string $url, bool|null $keepGitDir = true, <abbr title="Dagger\Dagger\ServiceId|Dagger\Service|null">Service|null</abbr> $experimentalServiceHost = null, string|null $sshKnownHosts = &#039;&#039;, <abbr title="Dagger\Dagger\SocketId|Dagger\Socket|null">Socket|null</abbr> $sshAuthSocket = null, <abbr title="Dagger\Dagger\SecretId|Dagger\Secret|null">Secret|null</abbr> $httpAuthToken = null, <abbr title="Dagger\Dagger\SecretId|Dagger\Secret|null">Secret|null</abbr> $httpAuthHeader = null)
         
                                             <p><p>Queries a Git repository.</p></p>                </div>
                 <div class="col-md-2"></div>
@@ -1435,7 +1435,7 @@ <h4>Return Value</h4>
                     <h3 id="method_git">
         <div class="location">at line 148</div>
         <code>                    <a href="../Dagger/GitRepository.html"><abbr title="Dagger\GitRepository">GitRepository</abbr></a>
-    <strong>git</strong>(string $url, bool|null $keepGitDir = true, <abbr title="Dagger\Dagger\ServiceId|Dagger\Service|null">Service|null</abbr> $experimentalServiceHost = null, string|null $sshKnownHosts = &#039;&#039;, <abbr title="Dagger\Dagger\SocketId|Dagger\Socket|null">Socket|null</abbr> $sshAuthSocket = null)
+    <strong>git</strong>(string $url, bool|null $keepGitDir = true, <abbr title="Dagger\Dagger\ServiceId|Dagger\Service|null">Service|null</abbr> $experimentalServiceHost = null, string|null $sshKnownHosts = &#039;&#039;, <abbr title="Dagger\Dagger\SocketId|Dagger\Socket|null">Socket|null</abbr> $sshAuthSocket = null, <abbr title="Dagger\Dagger\SecretId|Dagger\Secret|null">Secret|null</abbr> $httpAuthToken = null, <abbr title="Dagger\Dagger\SecretId|Dagger\Secret|null">Secret|null</abbr> $httpAuthHeader = null)
         </code>
     </h3>
     <div class="details">    
@@ -1473,6 +1473,16 @@ <h4>Parameters</h4>
                 <td><abbr title="Dagger\Dagger\SocketId|Dagger\Socket|null">Socket|null</abbr></td>
                 <td>$sshAuthSocket</td>
                 <td></td>
+            </tr>
+                    <tr>
+                <td><abbr title="Dagger\Dagger\SecretId|Dagger\Secret|null">Secret|null</abbr></td>
+                <td>$httpAuthToken</td>
+                <td></td>
+            </tr>
+                    <tr>
+                <td><abbr title="Dagger\Dagger\SecretId|Dagger\Secret|null">Secret|null</abbr></td>
+                <td>$httpAuthHeader</td>
+                <td></td>
             </tr>
             </table>
 
@@ -1495,7 +1505,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_host">
-        <div class="location">at line 175</div>
+        <div class="location">at line 183</div>
         <code>                    <a href="../Dagger/Host.html"><abbr title="Dagger\Host">Host</abbr></a>
     <strong>host</strong>()
         </code>
@@ -1527,7 +1537,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_http">
-        <div class="location">at line 184</div>
+        <div class="location">at line 192</div>
         <code>                    <a href="../Dagger/File.html"><abbr title="Dagger\File">File</abbr></a>
     <strong>http</strong>(string $url, <abbr title="Dagger\Dagger\ServiceId|Dagger\Service|null">Service|null</abbr> $experimentalServiceHost = null)
         </code>
@@ -1574,7 +1584,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_llm">
-        <div class="location">at line 197</div>
+        <div class="location">at line 205</div>
         <code>                    <a href="../Dagger/LLM.html"><abbr title="Dagger\LLM">LLM</abbr></a>
     <strong>llm</strong>(string|null $model = null, int|null $maxAPICalls = null)
         </code>
@@ -1621,7 +1631,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadBindingFromID">
-        <div class="location">at line 212</div>
+        <div class="location">at line 220</div>
         <code>                    <a href="../Dagger/Binding.html"><abbr title="Dagger\Binding">Binding</abbr></a>
     <strong>loadBindingFromID</strong>(<abbr title="Dagger\BindingId|Dagger\Binding">Binding</abbr> $id)
         </code>
@@ -1663,7 +1673,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadCacheVolumeFromID">
-        <div class="location">at line 222</div>
+        <div class="location">at line 230</div>
         <code>                    <a href="../Dagger/CacheVolume.html"><abbr title="Dagger\CacheVolume">CacheVolume</abbr></a>
     <strong>loadCacheVolumeFromID</strong>(<abbr title="Dagger\CacheVolumeId|Dagger\CacheVolume">CacheVolume</abbr> $id)
         </code>
@@ -1705,7 +1715,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadContainerFromID">
-        <div class="location">at line 232</div>
+        <div class="location">at line 240</div>
         <code>                    <a href="../Dagger/Container.html"><abbr title="Dagger\Container">Container</abbr></a>
     <strong>loadContainerFromID</strong>(<abbr title="Dagger\ContainerId|Dagger\Container">Container</abbr> $id)
         </code>
@@ -1747,7 +1757,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadCurrentModuleFromID">
-        <div class="location">at line 242</div>
+        <div class="location">at line 250</div>
         <code>                    <a href="../Dagger/CurrentModule.html"><abbr title="Dagger\CurrentModule">CurrentModule</abbr></a>
     <strong>loadCurrentModuleFromID</strong>(<abbr title="Dagger\CurrentModuleId|Dagger\CurrentModule">CurrentModule</abbr> $id)
         </code>
@@ -1789,7 +1799,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadDirectoryFromID">
-        <div class="location">at line 252</div>
+        <div class="location">at line 260</div>
         <code>                    <a href="../Dagger/Directory.html"><abbr title="Dagger\Directory">Directory</abbr></a>
     <strong>loadDirectoryFromID</strong>(<abbr title="Dagger\DirectoryId|Dagger\Directory">Directory</abbr> $id)
         </code>
@@ -1831,7 +1841,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadEngineCacheEntryFromID">
-        <div class="location">at line 262</div>
+        <div class="location">at line 270</div>
         <code>                    <a href="../Dagger/EngineCacheEntry.html"><abbr title="Dagger\EngineCacheEntry">EngineCacheEntry</abbr></a>
     <strong>loadEngineCacheEntryFromID</strong>(<abbr title="Dagger\EngineCacheEntryId|Dagger\EngineCacheEntry">EngineCacheEntry</abbr> $id)
         </code>
@@ -1873,7 +1883,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadEngineCacheEntrySetFromID">
-        <div class="location">at line 272</div>
+        <div class="location">at line 280</div>
         <code>                    <a href="../Dagger/EngineCacheEntrySet.html"><abbr title="Dagger\EngineCacheEntrySet">EngineCacheEntrySet</abbr></a>
     <strong>loadEngineCacheEntrySetFromID</strong>(<abbr title="Dagger\EngineCacheEntrySetId|Dagger\EngineCacheEntrySet">EngineCacheEntrySet</abbr> $id)
         </code>
@@ -1915,7 +1925,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadEngineCacheFromID">
-        <div class="location">at line 282</div>
+        <div class="location">at line 290</div>
         <code>                    <a href="../Dagger/EngineCache.html"><abbr title="Dagger\EngineCache">EngineCache</abbr></a>
     <strong>loadEngineCacheFromID</strong>(<abbr title="Dagger\EngineCacheId|Dagger\EngineCache">EngineCache</abbr> $id)
         </code>
@@ -1957,7 +1967,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadEngineFromID">
-        <div class="location">at line 292</div>
+        <div class="location">at line 300</div>
         <code>                    <a href="../Dagger/Engine.html"><abbr title="Dagger\Engine">Engine</abbr></a>
     <strong>loadEngineFromID</strong>(<abbr title="Dagger\EngineId|Dagger\Engine">Engine</abbr> $id)
         </code>
@@ -1999,7 +2009,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadEnumTypeDefFromID">
-        <div class="location">at line 302</div>
+        <div class="location">at line 310</div>
         <code>                    <a href="../Dagger/EnumTypeDef.html"><abbr title="Dagger\EnumTypeDef">EnumTypeDef</abbr></a>
     <strong>loadEnumTypeDefFromID</strong>(<abbr title="Dagger\EnumTypeDefId|Dagger\EnumTypeDef">EnumTypeDef</abbr> $id)
         </code>
@@ -2041,7 +2051,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadEnumValueTypeDefFromID">
-        <div class="location">at line 312</div>
+        <div class="location">at line 320</div>
         <code>                    <a href="../Dagger/EnumValueTypeDef.html"><abbr title="Dagger\EnumValueTypeDef">EnumValueTypeDef</abbr></a>
     <strong>loadEnumValueTypeDefFromID</strong>(<abbr title="Dagger\EnumValueTypeDefId|Dagger\EnumValueTypeDef">EnumValueTypeDef</abbr> $id)
         </code>
@@ -2083,7 +2093,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadEnvFromID">
-        <div class="location">at line 322</div>
+        <div class="location">at line 330</div>
         <code>                    <a href="../Dagger/Env.html"><abbr title="Dagger\Env">Env</abbr></a>
     <strong>loadEnvFromID</strong>(<abbr title="Dagger\EnvId|Dagger\Env">Env</abbr> $id)
         </code>
@@ -2125,7 +2135,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadEnvVariableFromID">
-        <div class="location">at line 332</div>
+        <div class="location">at line 340</div>
         <code>                    <a href="../Dagger/EnvVariable.html"><abbr title="Dagger\EnvVariable">EnvVariable</abbr></a>
     <strong>loadEnvVariableFromID</strong>(<abbr title="Dagger\EnvVariableId|Dagger\EnvVariable">EnvVariable</abbr> $id)
         </code>
@@ -2167,7 +2177,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadErrorFromID">
-        <div class="location">at line 342</div>
+        <div class="location">at line 350</div>
         <code>                    <a href="../Dagger/Error.html"><abbr title="Dagger\Error">Error</abbr></a>
     <strong>loadErrorFromID</strong>(<abbr title="Dagger\ErrorId|Dagger\Error">Error</abbr> $id)
         </code>
@@ -2209,7 +2219,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadErrorValueFromID">
-        <div class="location">at line 352</div>
+        <div class="location">at line 360</div>
         <code>                    <a href="../Dagger/ErrorValue.html"><abbr title="Dagger\ErrorValue">ErrorValue</abbr></a>
     <strong>loadErrorValueFromID</strong>(<abbr title="Dagger\ErrorValueId|Dagger\ErrorValue">ErrorValue</abbr> $id)
         </code>
@@ -2251,7 +2261,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadFieldTypeDefFromID">
-        <div class="location">at line 362</div>
+        <div class="location">at line 370</div>
         <code>                    <a href="../Dagger/FieldTypeDef.html"><abbr title="Dagger\FieldTypeDef">FieldTypeDef</abbr></a>
     <strong>loadFieldTypeDefFromID</strong>(<abbr title="Dagger\FieldTypeDefId|Dagger\FieldTypeDef">FieldTypeDef</abbr> $id)
         </code>
@@ -2293,7 +2303,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadFileFromID">
-        <div class="location">at line 372</div>
+        <div class="location">at line 380</div>
         <code>                    <a href="../Dagger/File.html"><abbr title="Dagger\File">File</abbr></a>
     <strong>loadFileFromID</strong>(<abbr title="Dagger\FileId|Dagger\File">File</abbr> $id)
         </code>
@@ -2335,7 +2345,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadFunctionArgFromID">
-        <div class="location">at line 382</div>
+        <div class="location">at line 390</div>
         <code>                    <a href="../Dagger/FunctionArg.html"><abbr title="Dagger\FunctionArg">FunctionArg</abbr></a>
     <strong>loadFunctionArgFromID</strong>(<abbr title="Dagger\FunctionArgId|Dagger\FunctionArg">FunctionArg</abbr> $id)
         </code>
@@ -2377,7 +2387,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadFunctionCallArgValueFromID">
-        <div class="location">at line 392</div>
+        <div class="location">at line 400</div>
         <code>                    <a href="../Dagger/FunctionCallArgValue.html"><abbr title="Dagger\FunctionCallArgValue">FunctionCallArgValue</abbr></a>
     <strong>loadFunctionCallArgValueFromID</strong>(<abbr title="Dagger\FunctionCallArgValueId|Dagger\FunctionCallArgValue">FunctionCallArgValue</abbr> $id)
         </code>
@@ -2419,7 +2429,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadFunctionCallFromID">
-        <div class="location">at line 403</div>
+        <div class="location">at line 411</div>
         <code>                    <a href="../Dagger/FunctionCall.html"><abbr title="Dagger\FunctionCall">FunctionCall</abbr></a>
     <strong>loadFunctionCallFromID</strong>(<abbr title="Dagger\FunctionCallId|Dagger\FunctionCall">FunctionCall</abbr> $id)
         </code>
@@ -2461,7 +2471,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadFunctionFromID">
-        <div class="location">at line 413</div>
+        <div class="location">at line 421</div>
         <code>                    <a href="../Dagger/Function_.html"><abbr title="Dagger\Function_">Function_</abbr></a>
     <strong>loadFunctionFromID</strong>(<abbr title="Dagger\FunctionId|Dagger\Function_">Function_</abbr> $id)
         </code>
@@ -2503,7 +2513,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadGeneratedCodeFromID">
-        <div class="location">at line 423</div>
+        <div class="location">at line 431</div>
         <code>                    <a href="../Dagger/GeneratedCode.html"><abbr title="Dagger\GeneratedCode">GeneratedCode</abbr></a>
     <strong>loadGeneratedCodeFromID</strong>(<abbr title="Dagger\GeneratedCodeId|Dagger\GeneratedCode">GeneratedCode</abbr> $id)
         </code>
@@ -2545,7 +2555,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadGitRefFromID">
-        <div class="location">at line 433</div>
+        <div class="location">at line 441</div>
         <code>                    <a href="../Dagger/GitRef.html"><abbr title="Dagger\GitRef">GitRef</abbr></a>
     <strong>loadGitRefFromID</strong>(<abbr title="Dagger\GitRefId|Dagger\GitRef">GitRef</abbr> $id)
         </code>
@@ -2587,7 +2597,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadGitRepositoryFromID">
-        <div class="location">at line 443</div>
+        <div class="location">at line 451</div>
         <code>                    <a href="../Dagger/GitRepository.html"><abbr title="Dagger\GitRepository">GitRepository</abbr></a>
     <strong>loadGitRepositoryFromID</strong>(<abbr title="Dagger\GitRepositoryId|Dagger\GitRepository">GitRepository</abbr> $id)
         </code>
@@ -2629,7 +2639,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadHostFromID">
-        <div class="location">at line 453</div>
+        <div class="location">at line 461</div>
         <code>                    <a href="../Dagger/Host.html"><abbr title="Dagger\Host">Host</abbr></a>
     <strong>loadHostFromID</strong>(<abbr title="Dagger\HostId|Dagger\Host">Host</abbr> $id)
         </code>
@@ -2671,7 +2681,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadInputTypeDefFromID">
-        <div class="location">at line 463</div>
+        <div class="location">at line 471</div>
         <code>                    <a href="../Dagger/InputTypeDef.html"><abbr title="Dagger\InputTypeDef">InputTypeDef</abbr></a>
     <strong>loadInputTypeDefFromID</strong>(<abbr title="Dagger\InputTypeDefId|Dagger\InputTypeDef">InputTypeDef</abbr> $id)
         </code>
@@ -2713,7 +2723,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadInterfaceTypeDefFromID">
-        <div class="location">at line 473</div>
+        <div class="location">at line 481</div>
         <code>                    <a href="../Dagger/InterfaceTypeDef.html"><abbr title="Dagger\InterfaceTypeDef">InterfaceTypeDef</abbr></a>
     <strong>loadInterfaceTypeDefFromID</strong>(<abbr title="Dagger\InterfaceTypeDefId|Dagger\InterfaceTypeDef">InterfaceTypeDef</abbr> $id)
         </code>
@@ -2755,7 +2765,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadLLMFromID">
-        <div class="location">at line 483</div>
+        <div class="location">at line 491</div>
         <code>                    <a href="../Dagger/LLM.html"><abbr title="Dagger\LLM">LLM</abbr></a>
     <strong>loadLLMFromID</strong>(<abbr title="Dagger\LLMId|Dagger\LLM">LLM</abbr> $id)
         </code>
@@ -2797,7 +2807,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadLLMTokenUsageFromID">
-        <div class="location">at line 493</div>
+        <div class="location">at line 501</div>
         <code>                    <a href="../Dagger/LLMTokenUsage.html"><abbr title="Dagger\LLMTokenUsage">LLMTokenUsage</abbr></a>
     <strong>loadLLMTokenUsageFromID</strong>(<abbr title="Dagger\LLMTokenUsageId|Dagger\LLMTokenUsage">LLMTokenUsage</abbr> $id)
         </code>
@@ -2839,7 +2849,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadLabelFromID">
-        <div class="location">at line 503</div>
+        <div class="location">at line 511</div>
         <code>                    <a href="../Dagger/Label.html"><abbr title="Dagger\Label">Label</abbr></a>
     <strong>loadLabelFromID</strong>(<abbr title="Dagger\LabelId|Dagger\Label">Label</abbr> $id)
         </code>
@@ -2881,7 +2891,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadListTypeDefFromID">
-        <div class="location">at line 513</div>
+        <div class="location">at line 521</div>
         <code>                    <a href="../Dagger/ListTypeDef.html"><abbr title="Dagger\ListTypeDef">ListTypeDef</abbr></a>
     <strong>loadListTypeDefFromID</strong>(<abbr title="Dagger\ListTypeDefId|Dagger\ListTypeDef">ListTypeDef</abbr> $id)
         </code>
@@ -2923,7 +2933,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadModuleConfigClientFromID">
-        <div class="location">at line 523</div>
+        <div class="location">at line 531</div>
         <code>                    <a href="../Dagger/ModuleConfigClient.html"><abbr title="Dagger\ModuleConfigClient">ModuleConfigClient</abbr></a>
     <strong>loadModuleConfigClientFromID</strong>(<abbr title="Dagger\ModuleConfigClientId|Dagger\ModuleConfigClient">ModuleConfigClient</abbr> $id)
         </code>
@@ -2965,7 +2975,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadModuleFromID">
-        <div class="location">at line 533</div>
+        <div class="location">at line 541</div>
         <code>                    <a href="../Dagger/Module.html"><abbr title="Dagger\Module">Module</abbr></a>
     <strong>loadModuleFromID</strong>(<abbr title="Dagger\ModuleId|Dagger\Module">Module</abbr> $id)
         </code>
@@ -3007,7 +3017,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadModuleSourceFromID">
-        <div class="location">at line 543</div>
+        <div class="location">at line 551</div>
         <code>                    <a href="../Dagger/ModuleSource.html"><abbr title="Dagger\ModuleSource">ModuleSource</abbr></a>
     <strong>loadModuleSourceFromID</strong>(<abbr title="Dagger\ModuleSourceId|Dagger\ModuleSource">ModuleSource</abbr> $id)
         </code>
@@ -3049,7 +3059,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadObjectTypeDefFromID">
-        <div class="location">at line 553</div>
+        <div class="location">at line 561</div>
         <code>                    <a href="../Dagger/ObjectTypeDef.html"><abbr title="Dagger\ObjectTypeDef">ObjectTypeDef</abbr></a>
     <strong>loadObjectTypeDefFromID</strong>(<abbr title="Dagger\ObjectTypeDefId|Dagger\ObjectTypeDef">ObjectTypeDef</abbr> $id)
         </code>
@@ -3091,7 +3101,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadPortFromID">
-        <div class="location">at line 563</div>
+        <div class="location">at line 571</div>
         <code>                    <a href="../Dagger/Port.html"><abbr title="Dagger\Port">Port</abbr></a>
     <strong>loadPortFromID</strong>(<abbr title="Dagger\PortId|Dagger\Port">Port</abbr> $id)
         </code>
@@ -3133,7 +3143,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadSDKConfigFromID">
-        <div class="location">at line 573</div>
+        <div class="location">at line 581</div>
         <code>                    <a href="../Dagger/SDKConfig.html"><abbr title="Dagger\SDKConfig">SDKConfig</abbr></a>
     <strong>loadSDKConfigFromID</strong>(<abbr title="Dagger\SDKConfigId|Dagger\SDKConfig">SDKConfig</abbr> $id)
         </code>
@@ -3175,7 +3185,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadScalarTypeDefFromID">
-        <div class="location">at line 583</div>
+        <div class="location">at line 591</div>
         <code>                    <a href="../Dagger/ScalarTypeDef.html"><abbr title="Dagger\ScalarTypeDef">ScalarTypeDef</abbr></a>
     <strong>loadScalarTypeDefFromID</strong>(<abbr title="Dagger\ScalarTypeDefId|Dagger\ScalarTypeDef">ScalarTypeDef</abbr> $id)
         </code>
@@ -3217,7 +3227,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadSecretFromID">
-        <div class="location">at line 593</div>
+        <div class="location">at line 601</div>
         <code>                    <a href="../Dagger/Secret.html"><abbr title="Dagger\Secret">Secret</abbr></a>
     <strong>loadSecretFromID</strong>(<abbr title="Dagger\SecretId|Dagger\Secret">Secret</abbr> $id)
         </code>
@@ -3259,7 +3269,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadServiceFromID">
-        <div class="location">at line 603</div>
+        <div class="location">at line 611</div>
         <code>                    <a href="../Dagger/Service.html"><abbr title="Dagger\Service">Service</abbr></a>
     <strong>loadServiceFromID</strong>(<abbr title="Dagger\ServiceId|Dagger\Service">Service</abbr> $id)
         </code>
@@ -3301,7 +3311,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadSocketFromID">
-        <div class="location">at line 613</div>
+        <div class="location">at line 621</div>
         <code>                    <a href="../Dagger/Socket.html"><abbr title="Dagger\Socket">Socket</abbr></a>
     <strong>loadSocketFromID</strong>(<abbr title="Dagger\SocketId|Dagger\Socket">Socket</abbr> $id)
         </code>
@@ -3343,7 +3353,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadSourceMapFromID">
-        <div class="location">at line 623</div>
+        <div class="location">at line 631</div>
         <code>                    <a href="../Dagger/SourceMap.html"><abbr title="Dagger\SourceMap">SourceMap</abbr></a>
     <strong>loadSourceMapFromID</strong>(<abbr title="Dagger\SourceMapId|Dagger\SourceMap">SourceMap</abbr> $id)
         </code>
@@ -3385,7 +3395,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadTerminalFromID">
-        <div class="location">at line 633</div>
+        <div class="location">at line 641</div>
         <code>                    <a href="../Dagger/Terminal.html"><abbr title="Dagger\Terminal">Terminal</abbr></a>
     <strong>loadTerminalFromID</strong>(<abbr title="Dagger\TerminalId|Dagger\Terminal">Terminal</abbr> $id)
         </code>
@@ -3427,7 +3437,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_loadTypeDefFromID">
-        <div class="location">at line 643</div>
+        <div class="location">at line 651</div>
         <code>                    <a href="../Dagger/TypeDef.html"><abbr title="Dagger\TypeDef">TypeDef</abbr></a>
     <strong>loadTypeDefFromID</strong>(<abbr title="Dagger\TypeDefId|Dagger\TypeDef">TypeDef</abbr> $id)
         </code>
@@ -3469,7 +3479,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_module">
-        <div class="location">at line 653</div>
+        <div class="location">at line 661</div>
         <code>                    <a href="../Dagger/Module.html"><abbr title="Dagger\Module">Module</abbr></a>
     <strong>module</strong>()
         </code>
@@ -3501,7 +3511,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_moduleSource">
-        <div class="location">at line 662</div>
+        <div class="location">at line 670</div>
         <code>                    <a href="../Dagger/ModuleSource.html"><abbr title="Dagger\ModuleSource">ModuleSource</abbr></a>
     <strong>moduleSource</strong>(string $refString, string|null $refPin = &#039;&#039;, bool|null $disableFindUp = false, bool|null $allowNotExists = false, <abbr title="Dagger\Dagger\ModuleSourceKind">ModuleSourceKind</abbr>|null $requireKind = null)
         </code>
@@ -3563,7 +3573,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_secret">
-        <div class="location">at line 689</div>
+        <div class="location">at line 697</div>
         <code>                    <a href="../Dagger/Secret.html"><abbr title="Dagger\Secret">Secret</abbr></a>
     <strong>secret</strong>(string $uri)
         </code>
@@ -3605,7 +3615,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_setSecret">
-        <div class="location">at line 701</div>
+        <div class="location">at line 709</div>
         <code>                    <a href="../Dagger/Secret.html"><abbr title="Dagger\Secret">Secret</abbr></a>
     <strong>setSecret</strong>(string $name, string $plaintext)
         </code>
@@ -3652,7 +3662,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_sourceMap">
-        <div class="location">at line 712</div>
+        <div class="location">at line 720</div>
         <code>                    <a href="../Dagger/SourceMap.html"><abbr title="Dagger\SourceMap">SourceMap</abbr></a>
     <strong>sourceMap</strong>(string $filename, int $line, int $column)
         </code>
@@ -3704,7 +3714,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_typeDef">
-        <div class="location">at line 724</div>
+        <div class="location">at line 732</div>
         <code>                    <a href="../Dagger/TypeDef.html"><abbr title="Dagger\TypeDef">TypeDef</abbr></a>
     <strong>typeDef</strong>()
         </code>
@@ -3736,7 +3746,7 @@ <h4>Return Value</h4>
             </div>
                     <div class="method-item">
                     <h3 id="method_version">
-        <div class="location">at line 733</div>
+        <div class="location">at line 741</div>
         <code>                    string
     <strong>version</strong>()
         </code>
diff --git a/docs/static/reference/php/renderer.index b/docs/static/reference/php/renderer.index
index 99d973f174d..ad3cd1110e5 100644
--- a/docs/static/reference/php/renderer.index
+++ b/docs/static/reference/php/renderer.index
@@ -1 +1 @@
-O:21:"Doctum\Renderer\Index":3:{i:0;a:111:{s:25:"Dagger\Attribute\Argument";s:40:"599c918d890fda25d981b222243917a54c4f5d7d";s:31:"Dagger\Attribute\DaggerFunction";s:40:"e6f41c556e9485df2b9e1c6b97c0757407cbc97a";s:29:"Dagger\Attribute\DaggerObject";s:40:"2930fe9bbcb95a159d0450891d7e88740dea5ab5";s:28:"Dagger\Attribute\DefaultPath";s:40:"9da24512063fd39d4ea2b49e882f51a96e0162a1";s:20:"Dagger\Attribute\Doc";s:40:"f61f0845119200f4399d5ea63e088aa4a6feccee";s:23:"Dagger\Attribute\Ignore";s:40:"1a502cd8f1d878f701b57a1825fa6b7d18215e4e";s:27:"Dagger\Attribute\ListOfType";s:40:"16aca4763d19d5f49262111dfa0adf4e4a511636";s:34:"Dagger\Attribute\ReturnsListOfType";s:40:"ed3f5a7aa079776c1aa0a06f6d0611f21d6c1b30";s:14:"Dagger\Binding";s:40:"b8325948594f101e5eed270f2599709b73545e7f";s:16:"Dagger\BindingId";s:40:"72e8ed4f39bbbf4fa023ea39b0b35db0378c1fd4";s:15:"Dagger\BuildArg";s:40:"c2c16c6bdf746c6e98a001ec142c80a234147fa3";s:18:"Dagger\CacheVolume";s:40:"b0d870b4bb424bea79f396785769189404385d5c";s:20:"Dagger\CacheVolumeId";s:40:"485f0589b8adfc28f44c509a3d42181507381fa4";s:13:"Dagger\Client";s:40:"c7c5bbb17b309a9158382d3a857e88ec5337508c";s:28:"Dagger\Client\AbstractClient";s:40:"b415ffaea530d9db597b4dcd8c58b4c5967f10cd";s:24:"Dagger\Client\AbstractId";s:40:"d2abe25a67e7b39798969380b4e0e5b3015a0159";s:33:"Dagger\Client\AbstractInputObject";s:40:"d32535748b3bef110dd2dbfebae058dc1dd041ed";s:28:"Dagger\Client\AbstractObject";s:40:"b6cd3b134e5e892f9c84c00cc683941bcfc34f47";s:28:"Dagger\Client\AbstractScalar";s:40:"da89fca18da2a9d9dc8b100130fad5e82c3d5be8";s:20:"Dagger\Client\IdAble";s:40:"4ef86778b2b8f364e9b6e6e0d28f4eaebe234b93";s:26:"Dagger\Client\QueryBuilder";s:40:"3221784340af8a60f6f9a2f96df131dd2eed7821";s:17:"Dagger\Connection";s:40:"351e42733e9aa7a0faeef78f65a68b58db915747";s:16:"Dagger\Container";s:40:"9007e37813a5ec5fa035684ac70c68946d3e6593";s:18:"Dagger\ContainerId";s:40:"540fe0360b08d511b290e2ff1699a59968be2a1e";s:20:"Dagger\CurrentModule";s:40:"9b73292daedf0e8e873d4753ad28040c0dfb6495";s:22:"Dagger\CurrentModuleId";s:40:"3696f40ec2bdbaa58f72b0d7ac0e833f77338aa8";s:13:"Dagger\Dagger";s:40:"f57a0d4cadf14639192b5393f21130e696996809";s:16:"Dagger\Directory";s:40:"a44b6ac73bd6a00140aa2060fddc0a87ce589d5d";s:18:"Dagger\DirectoryId";s:40:"6fb4d22efa55b392dd52780ae0072ddf72a7f0ee";s:13:"Dagger\Engine";s:40:"ae016c517e90bc5d363308394dc9328812d30ddc";s:18:"Dagger\EngineCache";s:40:"a3fcf096662dc346b8e0ab4cbf7c2198bd3254c7";s:23:"Dagger\EngineCacheEntry";s:40:"44de6debf36dfe5eac5a4ba531d48a5a1ecbc4d5";s:25:"Dagger\EngineCacheEntryId";s:40:"5738fccc09f155e8290227cc2b9684173b8a22ed";s:26:"Dagger\EngineCacheEntrySet";s:40:"b184c91ec3641e6c60f6f4d729734b44b9f55b05";s:28:"Dagger\EngineCacheEntrySetId";s:40:"0c9ac7fe17e8b8bb853193f514a38b05c1add407";s:20:"Dagger\EngineCacheId";s:40:"3f12cd6f6972cd392cf9634f5b385f6be957a9fb";s:15:"Dagger\EngineId";s:40:"40062b717291a1f36398fd02412db24faea447fe";s:18:"Dagger\EnumTypeDef";s:40:"0b9117b04754f1c25b08be15b6954b7bb6060b58";s:20:"Dagger\EnumTypeDefId";s:40:"ba173fe6e430ec78d71df4fc399e4cb85bd73d37";s:23:"Dagger\EnumValueTypeDef";s:40:"32f36bce731899f624384a63a89565f56f9a105b";s:25:"Dagger\EnumValueTypeDefId";s:40:"e803ead0700211f9673bd575bc43a577d598bdab";s:10:"Dagger\Env";s:40:"fabf3c6b49c3fc4fc0a40b17ef6ef03734fa948a";s:12:"Dagger\EnvId";s:40:"2149564e700691ecddbb842e6e4be0bfcad09dba";s:18:"Dagger\EnvVariable";s:40:"1b9189bc5234d007fb8b600756fddf5639ba61a6";s:20:"Dagger\EnvVariableId";s:40:"269f94488bdb08c0060978893bf8a6dff945c86e";s:12:"Dagger\Error";s:40:"4a5e84c68b100203a67764b640dbda068e1f915c";s:14:"Dagger\ErrorId";s:40:"ef37180163c8dddeee5f0f3fb1c0b179e37b9d1c";s:17:"Dagger\ErrorValue";s:40:"b9c627a7e99f41a5fa2e8be4204bb204572936c0";s:19:"Dagger\ErrorValueId";s:40:"4918314f16e28ac94f6960d807488b0b3854fc6a";s:19:"Dagger\FieldTypeDef";s:40:"2606cce48ed7b818a05341d0d9e6c3e2bfaa70ce";s:21:"Dagger\FieldTypeDefId";s:40:"122879e85337e457ade164e8fea00d80a6f28285";s:11:"Dagger\File";s:40:"cc9ef28e43d46229efba91336a6e583179a11676";s:13:"Dagger\FileId";s:40:"bc85863444247ea841f7b5581d1388f60d360a8d";s:18:"Dagger\FunctionArg";s:40:"29e8453fd63dff44e8f314eab44165498cb4f2e2";s:20:"Dagger\FunctionArgId";s:40:"4474816604297943d7e035f04662b2baf7d7a0a6";s:19:"Dagger\FunctionCall";s:40:"03a4a45a8c317057e5dfb31532fb43ea0f9c8f5f";s:27:"Dagger\FunctionCallArgValue";s:40:"adda1fcd6373559126d3378bc6053c81dbd416d3";s:29:"Dagger\FunctionCallArgValueId";s:40:"30238fdb304a915b1fadff52a1b76cd6362d7ee5";s:21:"Dagger\FunctionCallId";s:40:"e33b22b4114cc0d3d1f1cacafb28837532cf8323";s:17:"Dagger\FunctionId";s:40:"57a3eae77dadf9c7d9131fc323340cbe830e6852";s:16:"Dagger\Function_";s:40:"4d7ebbd125aad5b143ae42af80b3fa230c4ae007";s:20:"Dagger\GeneratedCode";s:40:"fa8ec2c94c3356defabb156bb1fbd221666170b3";s:22:"Dagger\GeneratedCodeId";s:40:"078b50726e514b4f4b87103cb2789e305b343e29";s:13:"Dagger\GitRef";s:40:"2612a7864977c2a034e88d2bedb4e7ac3b8e75fd";s:15:"Dagger\GitRefId";s:40:"b227492b8af6417b862679e9d9e03254c6e81e33";s:20:"Dagger\GitRepository";s:40:"8514065d24fb4fd08532181e0149fa88a2d0c3f2";s:22:"Dagger\GitRepositoryId";s:40:"b1cde824233bf04aa2b05a140dd16ecfe7728684";s:11:"Dagger\Host";s:40:"5418a1aa2b1b32ede2a325fe3babd48d28bfbd48";s:13:"Dagger\HostId";s:40:"267333be0e4463cf17adfcc016889bfaaa6488eb";s:19:"Dagger\InputTypeDef";s:40:"a95a958913d050ff4bd12d2f4dc0638885325d27";s:21:"Dagger\InputTypeDefId";s:40:"36014536fe74fa1621f991fd81caa748b1bc259b";s:23:"Dagger\InterfaceTypeDef";s:40:"e90e3650c114a7744810e6f344149828a3a54967";s:25:"Dagger\InterfaceTypeDefId";s:40:"389f4ba6599668a38aa6a474b4fa2293f9fb3fe3";s:11:"Dagger\Json";s:40:"6e52f55cbaec3227fb566937a3125e1e4372342e";s:10:"Dagger\LLM";s:40:"91debfa95d1a2d7302c86d66f5c77011d933a7a3";s:12:"Dagger\LLMId";s:40:"8276d5be767664cddf85d8b2b380e43ecc975d5c";s:20:"Dagger\LLMTokenUsage";s:40:"4a7473eb4b8e94f85be6e5f0a5efd4979a763600";s:22:"Dagger\LLMTokenUsageId";s:40:"9a888ea6e08c4facc8c9bcf3a8b90f919f3ab575";s:12:"Dagger\Label";s:40:"7d08dc0f0cce1fc0a015263e740721d80eba259b";s:14:"Dagger\LabelId";s:40:"3dc472658ff734743971535ad954dc7903fd0469";s:18:"Dagger\ListTypeDef";s:40:"a045a67134f2930bc4097e389c4d50b3db62e15a";s:20:"Dagger\ListTypeDefId";s:40:"61ad34c3ed73445042e6f40fa93434c3825c0d02";s:13:"Dagger\Module";s:40:"717dd5b0043c23032ecdb954beca6a40b0fa52f8";s:25:"Dagger\ModuleConfigClient";s:40:"141d0e1267ec444b5d4d10abea48822250dda423";s:27:"Dagger\ModuleConfigClientId";s:40:"bfa70ca8951238848ec381b58277cd3686f88c64";s:15:"Dagger\ModuleId";s:40:"eae2161e7344840a16f0a115c587ecd84729f779";s:19:"Dagger\ModuleSource";s:40:"500c8e185c770d3e0b2bc3ccc0fe5cd82781af24";s:21:"Dagger\ModuleSourceId";s:40:"e42b13465b1dc6019b5657c07e9ec4d0b69d8102";s:20:"Dagger\ObjectTypeDef";s:40:"c8e8f590236bd7c7a4fabf949e30fe032204a478";s:22:"Dagger\ObjectTypeDefId";s:40:"68efd4f65fb4320692c555c65bf0cae88ae59d43";s:20:"Dagger\PipelineLabel";s:40:"7ecd4805b71e92e9436cb2c77152ca362347d953";s:15:"Dagger\Platform";s:40:"bf145c3bbb4d105a1ed182233a525dc74448bb39";s:11:"Dagger\Port";s:40:"230147d5022892945405c47e001226201ac6f329";s:18:"Dagger\PortForward";s:40:"d043b91a6aeddc222f98dc3da99d0192aed00f69";s:13:"Dagger\PortId";s:40:"4337a4444768f04d0a8c4ea5bd9fa46bae6019ef";s:16:"Dagger\SDKConfig";s:40:"9bbb25c5525248dcb21b2aac7e0211639c13978e";s:18:"Dagger\SDKConfigId";s:40:"d821c0833382a7346b5a9d9d466400be8b50ff53";s:20:"Dagger\ScalarTypeDef";s:40:"d6d1e31d44b46cf458482edef303987a54859c14";s:22:"Dagger\ScalarTypeDefId";s:40:"2ede70846fda4c2424b8662f25c0d0fa92d0af4a";s:13:"Dagger\Secret";s:40:"bd4c10576c8efc5a8fbf7a45b4dc2f701db53167";s:15:"Dagger\SecretId";s:40:"d1ab3e44242471724daeedb9f40d2af3919f7aaa";s:14:"Dagger\Service";s:40:"d1cac79daee3143260b1da2fcfcf2a72db271da6";s:16:"Dagger\ServiceId";s:40:"ef33c82eb8d5f95b6007db7bc5dcbec84c4b5103";s:13:"Dagger\Socket";s:40:"c6f797d5bfd84890fe67b0b7377b790026edac25";s:15:"Dagger\SocketId";s:40:"63a510e5c175aa5bc88c5efb9de9acc20c6203fa";s:16:"Dagger\SourceMap";s:40:"97ac4c1c3d2472a5352b6b3fcc3ba382e448bff0";s:18:"Dagger\SourceMapId";s:40:"316469285d33887e2c708dedf4f5542dba2d7614";s:15:"Dagger\Terminal";s:40:"130ea9d9953fff5c7740b70f46aaf91e367ad3cd";s:17:"Dagger\TerminalId";s:40:"b742dd1fbd01daea8c49f17be3458e05f9d9b404";s:14:"Dagger\TypeDef";s:40:"9e98ca7a53a88dc6eec1ed8bdf8878d2e3a1d415";s:16:"Dagger\TypeDefId";s:40:"fefe81a49d75e7ba6376ec76563143cd999ca8c1";}i:1;a:1:{i:0;s:4:"main";}i:2;a:3:{i:0;s:6:"Dagger";i:1;s:16:"Dagger\Attribute";i:2;s:13:"Dagger\Client";}}
\ No newline at end of file
+O:21:"Doctum\Renderer\Index":3:{i:0;a:111:{s:25:"Dagger\Attribute\Argument";s:40:"599c918d890fda25d981b222243917a54c4f5d7d";s:31:"Dagger\Attribute\DaggerFunction";s:40:"e6f41c556e9485df2b9e1c6b97c0757407cbc97a";s:29:"Dagger\Attribute\DaggerObject";s:40:"2930fe9bbcb95a159d0450891d7e88740dea5ab5";s:28:"Dagger\Attribute\DefaultPath";s:40:"9da24512063fd39d4ea2b49e882f51a96e0162a1";s:20:"Dagger\Attribute\Doc";s:40:"f61f0845119200f4399d5ea63e088aa4a6feccee";s:23:"Dagger\Attribute\Ignore";s:40:"1a502cd8f1d878f701b57a1825fa6b7d18215e4e";s:27:"Dagger\Attribute\ListOfType";s:40:"16aca4763d19d5f49262111dfa0adf4e4a511636";s:34:"Dagger\Attribute\ReturnsListOfType";s:40:"ed3f5a7aa079776c1aa0a06f6d0611f21d6c1b30";s:14:"Dagger\Binding";s:40:"b8325948594f101e5eed270f2599709b73545e7f";s:16:"Dagger\BindingId";s:40:"72e8ed4f39bbbf4fa023ea39b0b35db0378c1fd4";s:15:"Dagger\BuildArg";s:40:"c2c16c6bdf746c6e98a001ec142c80a234147fa3";s:18:"Dagger\CacheVolume";s:40:"b0d870b4bb424bea79f396785769189404385d5c";s:20:"Dagger\CacheVolumeId";s:40:"485f0589b8adfc28f44c509a3d42181507381fa4";s:13:"Dagger\Client";s:40:"549fb90d81745f9559f7c8a2057658fcb0d97ddc";s:28:"Dagger\Client\AbstractClient";s:40:"b415ffaea530d9db597b4dcd8c58b4c5967f10cd";s:24:"Dagger\Client\AbstractId";s:40:"d2abe25a67e7b39798969380b4e0e5b3015a0159";s:33:"Dagger\Client\AbstractInputObject";s:40:"d32535748b3bef110dd2dbfebae058dc1dd041ed";s:28:"Dagger\Client\AbstractObject";s:40:"b6cd3b134e5e892f9c84c00cc683941bcfc34f47";s:28:"Dagger\Client\AbstractScalar";s:40:"da89fca18da2a9d9dc8b100130fad5e82c3d5be8";s:20:"Dagger\Client\IdAble";s:40:"4ef86778b2b8f364e9b6e6e0d28f4eaebe234b93";s:26:"Dagger\Client\QueryBuilder";s:40:"3221784340af8a60f6f9a2f96df131dd2eed7821";s:17:"Dagger\Connection";s:40:"351e42733e9aa7a0faeef78f65a68b58db915747";s:16:"Dagger\Container";s:40:"9007e37813a5ec5fa035684ac70c68946d3e6593";s:18:"Dagger\ContainerId";s:40:"540fe0360b08d511b290e2ff1699a59968be2a1e";s:20:"Dagger\CurrentModule";s:40:"9b73292daedf0e8e873d4753ad28040c0dfb6495";s:22:"Dagger\CurrentModuleId";s:40:"3696f40ec2bdbaa58f72b0d7ac0e833f77338aa8";s:13:"Dagger\Dagger";s:40:"f57a0d4cadf14639192b5393f21130e696996809";s:16:"Dagger\Directory";s:40:"a44b6ac73bd6a00140aa2060fddc0a87ce589d5d";s:18:"Dagger\DirectoryId";s:40:"6fb4d22efa55b392dd52780ae0072ddf72a7f0ee";s:13:"Dagger\Engine";s:40:"ae016c517e90bc5d363308394dc9328812d30ddc";s:18:"Dagger\EngineCache";s:40:"a3fcf096662dc346b8e0ab4cbf7c2198bd3254c7";s:23:"Dagger\EngineCacheEntry";s:40:"44de6debf36dfe5eac5a4ba531d48a5a1ecbc4d5";s:25:"Dagger\EngineCacheEntryId";s:40:"5738fccc09f155e8290227cc2b9684173b8a22ed";s:26:"Dagger\EngineCacheEntrySet";s:40:"b184c91ec3641e6c60f6f4d729734b44b9f55b05";s:28:"Dagger\EngineCacheEntrySetId";s:40:"0c9ac7fe17e8b8bb853193f514a38b05c1add407";s:20:"Dagger\EngineCacheId";s:40:"3f12cd6f6972cd392cf9634f5b385f6be957a9fb";s:15:"Dagger\EngineId";s:40:"40062b717291a1f36398fd02412db24faea447fe";s:18:"Dagger\EnumTypeDef";s:40:"0b9117b04754f1c25b08be15b6954b7bb6060b58";s:20:"Dagger\EnumTypeDefId";s:40:"ba173fe6e430ec78d71df4fc399e4cb85bd73d37";s:23:"Dagger\EnumValueTypeDef";s:40:"32f36bce731899f624384a63a89565f56f9a105b";s:25:"Dagger\EnumValueTypeDefId";s:40:"e803ead0700211f9673bd575bc43a577d598bdab";s:10:"Dagger\Env";s:40:"fabf3c6b49c3fc4fc0a40b17ef6ef03734fa948a";s:12:"Dagger\EnvId";s:40:"2149564e700691ecddbb842e6e4be0bfcad09dba";s:18:"Dagger\EnvVariable";s:40:"1b9189bc5234d007fb8b600756fddf5639ba61a6";s:20:"Dagger\EnvVariableId";s:40:"269f94488bdb08c0060978893bf8a6dff945c86e";s:12:"Dagger\Error";s:40:"4a5e84c68b100203a67764b640dbda068e1f915c";s:14:"Dagger\ErrorId";s:40:"ef37180163c8dddeee5f0f3fb1c0b179e37b9d1c";s:17:"Dagger\ErrorValue";s:40:"b9c627a7e99f41a5fa2e8be4204bb204572936c0";s:19:"Dagger\ErrorValueId";s:40:"4918314f16e28ac94f6960d807488b0b3854fc6a";s:19:"Dagger\FieldTypeDef";s:40:"2606cce48ed7b818a05341d0d9e6c3e2bfaa70ce";s:21:"Dagger\FieldTypeDefId";s:40:"122879e85337e457ade164e8fea00d80a6f28285";s:11:"Dagger\File";s:40:"cc9ef28e43d46229efba91336a6e583179a11676";s:13:"Dagger\FileId";s:40:"bc85863444247ea841f7b5581d1388f60d360a8d";s:18:"Dagger\FunctionArg";s:40:"29e8453fd63dff44e8f314eab44165498cb4f2e2";s:20:"Dagger\FunctionArgId";s:40:"4474816604297943d7e035f04662b2baf7d7a0a6";s:19:"Dagger\FunctionCall";s:40:"03a4a45a8c317057e5dfb31532fb43ea0f9c8f5f";s:27:"Dagger\FunctionCallArgValue";s:40:"adda1fcd6373559126d3378bc6053c81dbd416d3";s:29:"Dagger\FunctionCallArgValueId";s:40:"30238fdb304a915b1fadff52a1b76cd6362d7ee5";s:21:"Dagger\FunctionCallId";s:40:"e33b22b4114cc0d3d1f1cacafb28837532cf8323";s:17:"Dagger\FunctionId";s:40:"57a3eae77dadf9c7d9131fc323340cbe830e6852";s:16:"Dagger\Function_";s:40:"4d7ebbd125aad5b143ae42af80b3fa230c4ae007";s:20:"Dagger\GeneratedCode";s:40:"fa8ec2c94c3356defabb156bb1fbd221666170b3";s:22:"Dagger\GeneratedCodeId";s:40:"078b50726e514b4f4b87103cb2789e305b343e29";s:13:"Dagger\GitRef";s:40:"2612a7864977c2a034e88d2bedb4e7ac3b8e75fd";s:15:"Dagger\GitRefId";s:40:"b227492b8af6417b862679e9d9e03254c6e81e33";s:20:"Dagger\GitRepository";s:40:"8514065d24fb4fd08532181e0149fa88a2d0c3f2";s:22:"Dagger\GitRepositoryId";s:40:"b1cde824233bf04aa2b05a140dd16ecfe7728684";s:11:"Dagger\Host";s:40:"5418a1aa2b1b32ede2a325fe3babd48d28bfbd48";s:13:"Dagger\HostId";s:40:"267333be0e4463cf17adfcc016889bfaaa6488eb";s:19:"Dagger\InputTypeDef";s:40:"a95a958913d050ff4bd12d2f4dc0638885325d27";s:21:"Dagger\InputTypeDefId";s:40:"36014536fe74fa1621f991fd81caa748b1bc259b";s:23:"Dagger\InterfaceTypeDef";s:40:"e90e3650c114a7744810e6f344149828a3a54967";s:25:"Dagger\InterfaceTypeDefId";s:40:"389f4ba6599668a38aa6a474b4fa2293f9fb3fe3";s:11:"Dagger\Json";s:40:"6e52f55cbaec3227fb566937a3125e1e4372342e";s:10:"Dagger\LLM";s:40:"91debfa95d1a2d7302c86d66f5c77011d933a7a3";s:12:"Dagger\LLMId";s:40:"8276d5be767664cddf85d8b2b380e43ecc975d5c";s:20:"Dagger\LLMTokenUsage";s:40:"4a7473eb4b8e94f85be6e5f0a5efd4979a763600";s:22:"Dagger\LLMTokenUsageId";s:40:"9a888ea6e08c4facc8c9bcf3a8b90f919f3ab575";s:12:"Dagger\Label";s:40:"7d08dc0f0cce1fc0a015263e740721d80eba259b";s:14:"Dagger\LabelId";s:40:"3dc472658ff734743971535ad954dc7903fd0469";s:18:"Dagger\ListTypeDef";s:40:"a045a67134f2930bc4097e389c4d50b3db62e15a";s:20:"Dagger\ListTypeDefId";s:40:"61ad34c3ed73445042e6f40fa93434c3825c0d02";s:13:"Dagger\Module";s:40:"717dd5b0043c23032ecdb954beca6a40b0fa52f8";s:25:"Dagger\ModuleConfigClient";s:40:"141d0e1267ec444b5d4d10abea48822250dda423";s:27:"Dagger\ModuleConfigClientId";s:40:"bfa70ca8951238848ec381b58277cd3686f88c64";s:15:"Dagger\ModuleId";s:40:"eae2161e7344840a16f0a115c587ecd84729f779";s:19:"Dagger\ModuleSource";s:40:"500c8e185c770d3e0b2bc3ccc0fe5cd82781af24";s:21:"Dagger\ModuleSourceId";s:40:"e42b13465b1dc6019b5657c07e9ec4d0b69d8102";s:20:"Dagger\ObjectTypeDef";s:40:"c8e8f590236bd7c7a4fabf949e30fe032204a478";s:22:"Dagger\ObjectTypeDefId";s:40:"68efd4f65fb4320692c555c65bf0cae88ae59d43";s:20:"Dagger\PipelineLabel";s:40:"7ecd4805b71e92e9436cb2c77152ca362347d953";s:15:"Dagger\Platform";s:40:"bf145c3bbb4d105a1ed182233a525dc74448bb39";s:11:"Dagger\Port";s:40:"230147d5022892945405c47e001226201ac6f329";s:18:"Dagger\PortForward";s:40:"d043b91a6aeddc222f98dc3da99d0192aed00f69";s:13:"Dagger\PortId";s:40:"4337a4444768f04d0a8c4ea5bd9fa46bae6019ef";s:16:"Dagger\SDKConfig";s:40:"9bbb25c5525248dcb21b2aac7e0211639c13978e";s:18:"Dagger\SDKConfigId";s:40:"d821c0833382a7346b5a9d9d466400be8b50ff53";s:20:"Dagger\ScalarTypeDef";s:40:"d6d1e31d44b46cf458482edef303987a54859c14";s:22:"Dagger\ScalarTypeDefId";s:40:"2ede70846fda4c2424b8662f25c0d0fa92d0af4a";s:13:"Dagger\Secret";s:40:"bd4c10576c8efc5a8fbf7a45b4dc2f701db53167";s:15:"Dagger\SecretId";s:40:"d1ab3e44242471724daeedb9f40d2af3919f7aaa";s:14:"Dagger\Service";s:40:"d1cac79daee3143260b1da2fcfcf2a72db271da6";s:16:"Dagger\ServiceId";s:40:"ef33c82eb8d5f95b6007db7bc5dcbec84c4b5103";s:13:"Dagger\Socket";s:40:"c6f797d5bfd84890fe67b0b7377b790026edac25";s:15:"Dagger\SocketId";s:40:"63a510e5c175aa5bc88c5efb9de9acc20c6203fa";s:16:"Dagger\SourceMap";s:40:"97ac4c1c3d2472a5352b6b3fcc3ba382e448bff0";s:18:"Dagger\SourceMapId";s:40:"316469285d33887e2c708dedf4f5542dba2d7614";s:15:"Dagger\Terminal";s:40:"130ea9d9953fff5c7740b70f46aaf91e367ad3cd";s:17:"Dagger\TerminalId";s:40:"b742dd1fbd01daea8c49f17be3458e05f9d9b404";s:14:"Dagger\TypeDef";s:40:"9e98ca7a53a88dc6eec1ed8bdf8878d2e3a1d415";s:16:"Dagger\TypeDefId";s:40:"fefe81a49d75e7ba6376ec76563143cd999ca8c1";}i:1;a:1:{i:0;s:4:"main";}i:2;a:3:{i:0;s:6:"Dagger";i:1;s:16:"Dagger\Attribute";i:2;s:13:"Dagger\Client";}}
\ No newline at end of file
diff --git a/engine/sources/netconfhttp/common.go b/engine/sources/netconfhttp/common.go
new file mode 100644
index 00000000000..618cade5f6a
--- /dev/null
+++ b/engine/sources/netconfhttp/common.go
@@ -0,0 +1,83 @@
+package netconfhttp
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"net"
+
+	"github.com/moby/buildkit/executor/oci"
+)
+
+func createResolver(dns *oci.DNSConfig) (*net.Resolver, []string) {
+	if dns == nil {
+		return net.DefaultResolver, nil
+	}
+	dialer := net.Dialer{}
+	resolver := &net.Resolver{
+		PreferGo: true,
+		Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
+			return dialNameservers(ctx, network, dns.Nameservers, &dialer)
+		},
+	}
+	return resolver, dns.SearchDomains
+}
+
+func dialNameservers(ctx context.Context, network string, nameservers []string, dialer *net.Dialer) (net.Conn, error) {
+	if len(nameservers) == 0 {
+		return nil, errors.New("no nameservers configured")
+	}
+
+	var errs []error
+	for _, ns := range nameservers {
+		conn, err := dialer.DialContext(ctx, network, net.JoinHostPort(ns, "53"))
+		if err != nil {
+			errs = append(errs, err)
+			continue
+		}
+		return conn, nil
+	}
+
+	return nil, errors.Join(errs...)
+}
+
+func resolveHost(ctx context.Context, target string, resolver *net.Resolver, searchDomains []string) (string, error) {
+	if host, port, err := net.SplitHostPort(target); err == nil {
+		ip, err := lookup(ctx, host, resolver, searchDomains)
+		if err != nil {
+			return "", err
+		}
+		return net.JoinHostPort(ip.String(), port), nil
+	} else {
+		ip, err := lookup(ctx, target, resolver, searchDomains)
+		if err != nil {
+			return "", err
+		}
+		return ip.String(), nil
+	}
+}
+
+func lookup(ctx context.Context, target string, resolver *net.Resolver, searchDomains []string) (net.IP, error) {
+	var errs []error
+	for _, domain := range append([]string{""}, searchDomains...) {
+		qualified := target
+		if domain != "" {
+			qualified += "." + domain
+		}
+
+		ips, err := resolver.LookupIPAddr(ctx, qualified)
+		if err != nil {
+			errs = append(errs, err)
+			continue
+		}
+
+		if len(ips) > 0 {
+			return ips[0].IP, nil
+		}
+	}
+	if len(errs) > 0 {
+		return nil, errors.Join(errs...)
+	}
+
+	return nil, fmt.Errorf("no IPs found for %s", target)
+}
diff --git a/engine/sources/netconfhttp/transport.go b/engine/sources/netconfhttp/transport.go
index 1fdef33debc..ec2e2078223 100644
--- a/engine/sources/netconfhttp/transport.go
+++ b/engine/sources/netconfhttp/transport.go
@@ -1,9 +1,6 @@
 package netconfhttp
 
 import (
-	"context"
-	"errors"
-	"fmt"
 	"net"
 	"net/http"
 	"strings"
@@ -15,37 +12,7 @@ import (
 // the given network configuration as a logical override to the host's
 // /etc/hosts and/or /etc/resolv.conf.
 func NewTransport(rt http.RoundTripper, dns *oci.DNSConfig) http.RoundTripper {
-	var domains []string
-	var resolver *net.Resolver
-	if dns == nil {
-		resolver = net.DefaultResolver
-	} else {
-		domains = dns.SearchDomains
-
-		dialer := net.Dialer{}
-		resolver = &net.Resolver{
-			PreferGo: true,
-			Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
-				if len(dns.Nameservers) == 0 {
-					return nil, errors.New("no nameservers configured")
-				}
-
-				var errs []error
-				for _, ns := range dns.Nameservers {
-					conn, err := dialer.DialContext(ctx, network, net.JoinHostPort(ns, "53"))
-					if err != nil {
-						errs = append(errs, err)
-						continue
-					}
-
-					return conn, nil
-				}
-
-				return nil, errors.Join(errs...)
-			},
-		}
-	}
-
+	resolver, domains := createResolver(dns)
 	return &transport{
 		rt:            rt,
 		resolver:      resolver,
@@ -61,49 +28,13 @@ type transport struct {
 }
 
 func (h *transport) RoundTrip(req *http.Request) (*http.Response, error) {
+	req = req.Clone(req.Context())
 	if strings.Count(req.URL.Host, ".") == 0 && len(h.searchDomains) > 0 {
-		if host, port, err := net.SplitHostPort(req.URL.Host); err == nil {
-			ip, err := h.lookup(req.Context(), host)
-			if err != nil {
-				return nil, err
-			}
-
-			req.URL.Host = net.JoinHostPort(ip.String(), port)
-		} else {
-			ip, err := h.lookup(req.Context(), req.URL.Host)
-			if err != nil {
-				return nil, err
-			}
-
-			req.URL.Host = ip.String()
-		}
-	}
-
-	return h.rt.RoundTrip(req)
-}
-
-func (h *transport) lookup(ctx context.Context, target string) (net.IP, error) {
-	var errs []error
-	for _, domain := range append([]string{""}, h.searchDomains...) {
-		qualified := target
-
-		if domain != "" {
-			qualified += "." + domain
-		}
-
-		ips, err := h.resolver.LookupIPAddr(ctx, qualified)
+		var err error
+		req.URL.Host, err = resolveHost(req.Context(), req.URL.Host, h.resolver, h.searchDomains)
 		if err != nil {
-			errs = append(errs, err)
-			continue
+			return nil, err
 		}
-
-		if len(ips) > 0 {
-			return ips[0].IP, nil
-		}
-	}
-	if len(errs) > 0 {
-		return nil, errors.Join(errs...)
 	}
-
-	return nil, fmt.Errorf("no IPs found for %s", target)
+	return h.rt.RoundTrip(req)
 }
diff --git a/engine/sources/netconfhttp/transport_inject.go b/engine/sources/netconfhttp/transport_inject.go
new file mode 100644
index 00000000000..2efa710532f
--- /dev/null
+++ b/engine/sources/netconfhttp/transport_inject.go
@@ -0,0 +1,50 @@
+package netconfhttp
+
+import (
+	"context"
+	"net/http"
+	"strings"
+
+	"github.com/moby/buildkit/executor/oci"
+)
+
+type dnsConfigKey struct{}
+
+// WithDNSConfig adds DNS configuration to a context
+func WithDNSConfig(ctx context.Context, dns *oci.DNSConfig) context.Context {
+	if dns == nil {
+		return ctx
+	}
+	return context.WithValue(ctx, dnsConfigKey{}, dns)
+}
+
+// NewInjectableTransport returns a http.RoundTripper that extracts DNS configuration
+// from each request's context to determine the appropriate resolver.
+func NewInjectableTransport(rt http.RoundTripper) http.RoundTripper {
+	return &injectableTransport{
+		rt: rt,
+	}
+}
+
+type injectableTransport struct {
+	rt http.RoundTripper
+}
+
+func (t *injectableTransport) RoundTrip(req *http.Request) (*http.Response, error) {
+	var dnsConfig *oci.DNSConfig
+	if v := req.Context().Value(dnsConfigKey{}); v != nil {
+		dnsConfig = v.(*oci.DNSConfig)
+	}
+	resolver, searchDomains := createResolver(dnsConfig)
+
+	if strings.Count(req.URL.Host, ".") == 0 && len(searchDomains) > 0 {
+		var err error
+		req = req.Clone(req.Context())
+		req.URL.Host, err = resolveHost(req.Context(), req.URL.Host, resolver, searchDomains)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	return t.rt.RoundTrip(req)
+}
diff --git a/go.mod b/go.mod
index 68a12368c3b..cd76c62e137 100644
--- a/go.mod
+++ b/go.mod
@@ -52,7 +52,7 @@ require (
 	github.com/docker/docker v28.0.4+incompatible
 	github.com/dschmidt/go-layerfs v0.2.0
 	github.com/dustin/go-humanize v1.0.1
-	github.com/go-git/go-git/v5 v5.14.0
+	github.com/go-git/go-git/v5 v5.16.0
 	github.com/gofrs/flock v0.12.1
 	github.com/gogo/protobuf v1.3.2
 	github.com/google/generative-ai-go v0.19.0
@@ -128,15 +128,15 @@ require (
 	go.opentelemetry.io/otel/sdk/metric v1.34.0
 	go.opentelemetry.io/otel/trace v1.34.0
 	go.opentelemetry.io/proto/otlp v1.4.0
-	golang.org/x/crypto v0.36.0
+	golang.org/x/crypto v0.37.0
 	golang.org/x/exp v0.0.0-20250305212735-054e65f0b394
 	golang.org/x/mod v0.24.0
-	golang.org/x/net v0.38.0
+	golang.org/x/net v0.39.0
 	golang.org/x/oauth2 v0.28.0
-	golang.org/x/sync v0.12.0
-	golang.org/x/sys v0.31.0
-	golang.org/x/term v0.30.0
-	golang.org/x/text v0.23.0
+	golang.org/x/sync v0.13.0
+	golang.org/x/sys v0.32.0
+	golang.org/x/term v0.31.0
+	golang.org/x/text v0.24.0
 	golang.org/x/tools v0.31.0
 	google.golang.org/api v0.228.0
 	google.golang.org/grpc v1.71.0
@@ -165,7 +165,7 @@ require (
 	github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
 	github.com/Microsoft/go-winio v0.6.2 // indirect
 	github.com/Microsoft/hcsshim v0.12.9 // indirect
-	github.com/ProtonMail/go-crypto v1.1.5 // indirect
+	github.com/ProtonMail/go-crypto v1.1.6 // indirect
 	github.com/agext/levenshtein v1.2.3 // indirect
 	github.com/agnivade/levenshtein v1.2.1 // indirect
 	github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect
@@ -199,7 +199,7 @@ require (
 	github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
 	github.com/charmbracelet/x/ansi v0.8.0 // indirect
 	github.com/charmbracelet/x/term v0.2.1 // indirect
-	github.com/cloudflare/circl v1.6.0 // indirect
+	github.com/cloudflare/circl v1.6.1 // indirect
 	github.com/containerd/cgroups/v3 v3.0.3 // indirect
 	github.com/containerd/errdefs/pkg v0.3.0 // indirect
 	github.com/containerd/fifo v1.1.0 // indirect
diff --git a/go.sum b/go.sum
index b1734b37c79..3d3db5db288 100644
--- a/go.sum
+++ b/go.sum
@@ -44,8 +44,8 @@ github.com/Microsoft/hcsshim v0.12.9 h1:2zJy5KA+l0loz1HzEGqyNnjd3fyZA31ZBCGKacp6
 github.com/Microsoft/hcsshim v0.12.9/go.mod h1:fJ0gkFAna6ukt0bLdKB8djt4XIJhF/vEPuoIWYVvZ8Y=
 github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
 github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
-github.com/ProtonMail/go-crypto v1.1.5 h1:eoAQfK2dwL+tFSFpr7TbOaPNUbPiJj4fLYwwGE1FQO4=
-github.com/ProtonMail/go-crypto v1.1.5/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
+github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw=
+github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
 github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78=
 github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ=
 github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
@@ -157,8 +157,8 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR
 github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
 github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
-github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk=
-github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
+github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
+github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
 github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
 github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA=
 github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU=
@@ -294,8 +294,8 @@ github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UN
 github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
 github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
 github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
-github.com/go-git/go-git/v5 v5.14.0 h1:/MD3lCrGjCen5WfEAzKg00MJJffKhC8gzS80ycmCi60=
-github.com/go-git/go-git/v5 v5.14.0/go.mod h1:Z5Xhoia5PcWA3NF8vRLURn9E5FRhSl7dGj9ItW3Wk5k=
+github.com/go-git/go-git/v5 v5.16.0 h1:k3kuOEpkc0DeY7xlL6NaaNg39xdgQbtH5mwCafHO9AQ=
+github.com/go-git/go-git/v5 v5.16.0/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8=
 github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E=
 github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc=
 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
@@ -804,8 +804,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
-golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
+golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
+golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw=
 golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM=
@@ -836,8 +836,8 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
-golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
-golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
+golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
+golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc=
 golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
@@ -849,8 +849,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
-golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
+golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
+golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -879,22 +879,22 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
-golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
+golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
 golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
-golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
-golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
+golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
+golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
-golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
-golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
+golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
+golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
 golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
 golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
diff --git a/sdk/dotnet/sdk/Dagger.SDK.SourceGenerator/Code/CodeRenderer.cs b/sdk/dotnet/sdk/Dagger.SDK.SourceGenerator/Code/CodeRenderer.cs
index 8f9f24393f0..8fb76d99752 100644
--- a/sdk/dotnet/sdk/Dagger.SDK.SourceGenerator/Code/CodeRenderer.cs
+++ b/sdk/dotnet/sdk/Dagger.SDK.SourceGenerator/Code/CodeRenderer.cs
@@ -162,7 +162,10 @@ public string Format(string source)
 
     private static string RenderObsolete(Field field)
     {
-        return !field.IsDeprecated ? "" : $"[Obsolete(\"{field.DeprecationReason}\")]";
+        if (!field.IsDeprecated)
+            return "";
+        string escapedReason = SymbolDisplay.FormatLiteral(field.DeprecationReason, true);
+        return $"[Obsolete({escapedReason})]";
     }
 
     private static string RenderDocComment(Type type)
diff --git a/sdk/elixir/lib/dagger/gen/client.ex b/sdk/elixir/lib/dagger/gen/client.ex
index f362ddc49d8..cd6e041ef6a 100644
--- a/sdk/elixir/lib/dagger/gen/client.ex
+++ b/sdk/elixir/lib/dagger/gen/client.ex
@@ -212,7 +212,9 @@ defmodule Dagger.Client do
           {:keep_git_dir, boolean() | nil},
           {:experimental_service_host, Dagger.ServiceID.t() | nil},
           {:ssh_known_hosts, String.t() | nil},
-          {:ssh_auth_socket, Dagger.SocketID.t() | nil}
+          {:ssh_auth_socket, Dagger.SocketID.t() | nil},
+          {:http_auth_token, Dagger.SecretID.t() | nil},
+          {:http_auth_header, Dagger.SecretID.t() | nil}
         ]) :: Dagger.GitRepository.t()
   def git(%__MODULE__{} = client, url, optional_args \\ []) do
     query_builder =
@@ -223,6 +225,8 @@ defmodule Dagger.Client do
       |> QB.maybe_put_arg("experimentalServiceHost", optional_args[:experimental_service_host])
       |> QB.maybe_put_arg("sshKnownHosts", optional_args[:ssh_known_hosts])
       |> QB.maybe_put_arg("sshAuthSocket", optional_args[:ssh_auth_socket])
+      |> QB.maybe_put_arg("httpAuthToken", optional_args[:http_auth_token])
+      |> QB.maybe_put_arg("httpAuthHeader", optional_args[:http_auth_header])
 
     %Dagger.GitRepository{
       query_builder: query_builder,
diff --git a/sdk/elixir/lib/dagger/gen/git_repository.ex b/sdk/elixir/lib/dagger/gen/git_repository.ex
index ecf70c86ee1..3eb207de65a 100644
--- a/sdk/elixir/lib/dagger/gen/git_repository.ex
+++ b/sdk/elixir/lib/dagger/gen/git_repository.ex
@@ -107,6 +107,9 @@ defmodule Dagger.GitRepository do
     Client.execute(git_repository.client, query_builder)
   end
 
+  @deprecated """
+  Use \\"httpAuthHeader\\" in the constructor instead.
+  """
   @doc """
   Header to authenticate the remote with.
   """
@@ -123,6 +126,9 @@ defmodule Dagger.GitRepository do
     }
   end
 
+  @deprecated """
+  Use \\"httpAuthToken\\" in the constructor instead.
+  """
   @doc """
   Token to authenticate the remote with.
   """
diff --git a/sdk/go/dagger.gen.go b/sdk/go/dagger.gen.go
index 20f4efca0fa..e34b1315042 100644
--- a/sdk/go/dagger.gen.go
+++ b/sdk/go/dagger.gen.go
@@ -5666,6 +5666,8 @@ func (r *GitRepository) Tags(ctx context.Context, opts ...GitRepositoryTagsOpts)
 }
 
 // Header to authenticate the remote with.
+//
+// Deprecated: Use "httpAuthHeader" in the constructor instead.
 func (r *GitRepository) WithAuthHeader(header *Secret) *GitRepository {
 	assertNotNil("header", header)
 	q := r.query.Select("withAuthHeader")
@@ -5677,6 +5679,8 @@ func (r *GitRepository) WithAuthHeader(header *Secret) *GitRepository {
 }
 
 // Token to authenticate the remote with.
+//
+// Deprecated: Use "httpAuthToken" in the constructor instead.
 func (r *GitRepository) WithAuthToken(token *Secret) *GitRepository {
 	assertNotNil("token", token)
 	q := r.query.Select("withAuthToken")
@@ -8068,6 +8072,10 @@ type GitOpts struct {
 	SSHKnownHosts string
 	// Set SSH auth socket
 	SSHAuthSocket *Socket
+	// Secret used to populate the password during basic HTTP Authorization
+	HTTPAuthToken *Secret
+	// Secret used to populate the Authorization HTTP header
+	HTTPAuthHeader *Secret
 }
 
 // Queries a Git repository.
@@ -8090,6 +8098,14 @@ func (r *Client) Git(url string, opts ...GitOpts) *GitRepository {
 		if !querybuilder.IsZeroValue(opts[i].SSHAuthSocket) {
 			q = q.Arg("sshAuthSocket", opts[i].SSHAuthSocket)
 		}
+		// `httpAuthToken` optional argument
+		if !querybuilder.IsZeroValue(opts[i].HTTPAuthToken) {
+			q = q.Arg("httpAuthToken", opts[i].HTTPAuthToken)
+		}
+		// `httpAuthHeader` optional argument
+		if !querybuilder.IsZeroValue(opts[i].HTTPAuthHeader) {
+			q = q.Arg("httpAuthHeader", opts[i].HTTPAuthHeader)
+		}
 	}
 	q = q.Arg("url", url)
 
diff --git a/sdk/php/generated/Client.php b/sdk/php/generated/Client.php
index 4f9b21f2f78..61da199ebd5 100644
--- a/sdk/php/generated/Client.php
+++ b/sdk/php/generated/Client.php
@@ -151,6 +151,8 @@ public function git(
         ServiceId|Service|null $experimentalServiceHost = null,
         ?string $sshKnownHosts = '',
         SocketId|Socket|null $sshAuthSocket = null,
+        SecretId|Secret|null $httpAuthToken = null,
+        SecretId|Secret|null $httpAuthHeader = null,
     ): GitRepository {
         $innerQueryBuilder = new \Dagger\Client\QueryBuilder('git');
         $innerQueryBuilder->setArgument('url', $url);
@@ -166,6 +168,12 @@ public function git(
         if (null !== $sshAuthSocket) {
         $innerQueryBuilder->setArgument('sshAuthSocket', $sshAuthSocket);
         }
+        if (null !== $httpAuthToken) {
+        $innerQueryBuilder->setArgument('httpAuthToken', $httpAuthToken);
+        }
+        if (null !== $httpAuthHeader) {
+        $innerQueryBuilder->setArgument('httpAuthHeader', $httpAuthHeader);
+        }
         return new \Dagger\GitRepository($this->client, $this->queryBuilderChain->chain($innerQueryBuilder));
     }
 
diff --git a/sdk/python/src/dagger/client/gen.py b/sdk/python/src/dagger/client/gen.py
index 0e192f982ea..935beb0427d 100644
--- a/sdk/python/src/dagger/client/gen.py
+++ b/sdk/python/src/dagger/client/gen.py
@@ -5879,11 +5879,19 @@ async def tags(
     def with_auth_header(self, header: "Secret") -> Self:
         """Header to authenticate the remote with.
 
+        .. deprecated::
+            Use "httpAuthHeader" in the constructor instead.
+
         Parameters
         ----------
         header:
             Secret used to populate the Authorization HTTP header
         """
+        warnings.warn(
+            'Method "with_auth_header" is deprecated: Use "httpAuthHeader" in the constructor instead.',
+            DeprecationWarning,
+            stacklevel=4,
+        )
         _args = [
             Arg("header", header),
         ]
@@ -5893,12 +5901,20 @@ def with_auth_header(self, header: "Secret") -> Self:
     def with_auth_token(self, token: "Secret") -> Self:
         """Token to authenticate the remote with.
 
+        .. deprecated::
+            Use "httpAuthToken" in the constructor instead.
+
         Parameters
         ----------
         token:
             Secret used to populate the password during basic HTTP
             Authorization
         """
+        warnings.warn(
+            'Method "with_auth_token" is deprecated: Use "httpAuthToken" in the constructor instead.',
+            DeprecationWarning,
+            stacklevel=4,
+        )
         _args = [
             Arg("token", token),
         ]
@@ -8079,6 +8095,8 @@ def git(
         experimental_service_host: "Service | None" = None,
         ssh_known_hosts: str | None = "",
         ssh_auth_socket: "Socket | None" = None,
+        http_auth_token: "Secret | None" = None,
+        http_auth_header: "Secret | None" = None,
     ) -> GitRepository:
         """Queries a Git repository.
 
@@ -8097,6 +8115,11 @@ def git(
             Set SSH known hosts
         ssh_auth_socket:
             Set SSH auth socket
+        http_auth_token:
+            Secret used to populate the password during basic HTTP
+            Authorization
+        http_auth_header:
+            Secret used to populate the Authorization HTTP header
         """
         _args = [
             Arg("url", url),
@@ -8104,6 +8127,8 @@ def git(
             Arg("experimentalServiceHost", experimental_service_host, None),
             Arg("sshKnownHosts", ssh_known_hosts, ""),
             Arg("sshAuthSocket", ssh_auth_socket, None),
+            Arg("httpAuthToken", http_auth_token, None),
+            Arg("httpAuthHeader", http_auth_header, None),
         ]
         _ctx = self._select("git", _args)
         return GitRepository(_ctx)
diff --git a/sdk/rust/crates/dagger-sdk/src/gen.rs b/sdk/rust/crates/dagger-sdk/src/gen.rs
index 9b8816c67cf..31d04f429bb 100644
--- a/sdk/rust/crates/dagger-sdk/src/gen.rs
+++ b/sdk/rust/crates/dagger-sdk/src/gen.rs
@@ -8071,6 +8071,12 @@ pub struct QueryGitOpts<'a> {
     /// A service which must be started before the repo is fetched.
     #[builder(setter(into, strip_option), default)]
     pub experimental_service_host: Option<ServiceId>,
+    /// Secret used to populate the Authorization HTTP header
+    #[builder(setter(into, strip_option), default)]
+    pub http_auth_header: Option<SecretId>,
+    /// Secret used to populate the password during basic HTTP Authorization
+    #[builder(setter(into, strip_option), default)]
+    pub http_auth_token: Option<SecretId>,
     /// DEPRECATED: Set to true to keep .git directory.
     #[builder(setter(into, strip_option), default)]
     pub keep_git_dir: Option<bool>,
@@ -8363,6 +8369,12 @@ impl Query {
         if let Some(ssh_auth_socket) = opts.ssh_auth_socket {
             query = query.arg("sshAuthSocket", ssh_auth_socket);
         }
+        if let Some(http_auth_token) = opts.http_auth_token {
+            query = query.arg("httpAuthToken", http_auth_token);
+        }
+        if let Some(http_auth_header) = opts.http_auth_header {
+            query = query.arg("httpAuthHeader", http_auth_header);
+        }
         GitRepository {
             proc: self.proc.clone(),
             selection: query,
diff --git a/sdk/typescript/src/api/client.gen.ts b/sdk/typescript/src/api/client.gen.ts
index 3288883eb91..ced70c70442 100644
--- a/sdk/typescript/src/api/client.gen.ts
+++ b/sdk/typescript/src/api/client.gen.ts
@@ -1193,6 +1193,16 @@ export type ClientGitOpts = {
    * Set SSH auth socket
    */
   sshAuthSocket?: Socket
+
+  /**
+   * Secret used to populate the password during basic HTTP Authorization
+   */
+  httpAuthToken?: Secret
+
+  /**
+   * Secret used to populate the Authorization HTTP header
+   */
+  httpAuthHeader?: Secret
 }
 
 export type ClientHttpOpts = {
@@ -5600,6 +5610,7 @@ export class GitRepository extends BaseClient {
   /**
    * Header to authenticate the remote with.
    * @param header Secret used to populate the Authorization HTTP header
+   * @deprecated Use "httpAuthHeader" in the constructor instead.
    */
   withAuthHeader = (header: Secret): GitRepository => {
     const ctx = this._ctx.select("withAuthHeader", { header })
@@ -5609,6 +5620,7 @@ export class GitRepository extends BaseClient {
   /**
    * Token to authenticate the remote with.
    * @param token Secret used to populate the password during basic HTTP Authorization
+   * @deprecated Use "httpAuthToken" in the constructor instead.
    */
   withAuthToken = (token: Secret): GitRepository => {
     const ctx = this._ctx.select("withAuthToken", { token })
@@ -7613,6 +7625,8 @@ export class Client extends BaseClient {
    * @param opts.experimentalServiceHost A service which must be started before the repo is fetched.
    * @param opts.sshKnownHosts Set SSH known hosts
    * @param opts.sshAuthSocket Set SSH auth socket
+   * @param opts.httpAuthToken Secret used to populate the password during basic HTTP Authorization
+   * @param opts.httpAuthHeader Secret used to populate the Authorization HTTP header
    */
   git = (url: string, opts?: ClientGitOpts): GitRepository => {
     const ctx = this._ctx.select("git", { url, ...opts })


Reviews:
user: login: jedevc
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T14:13:15Z
user: login: jedevc
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T14:19:26Z
user: login: sipsma
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T20:11:23Z
user: login: helderco
body: lgtm
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-28T16:21:37Z
user: login: jedevc
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-28T16:31:55Z

Review comments:
diff_hunk: @@ -123,191 +156,202 @@ func (s *gitSchema) git(ctx context.Context, parent dagql.Instance[*core.Query],
 		if err != nil {
 			return inst, err
 		}
-		svcs = append(svcs, core.ServiceBinding{
+		gitServices = append(gitServices, core.ServiceBinding{
 			ID:       svc.ID(),
 			Service:  svc.Self,
 			Hostname: host,
 		})
 	}
 
-	// 2. Get client metadata
-	clientMetadata, err := engine.ClientMetadataFromContext(ctx)
-	if err != nil {
-		return inst, fmt.Errorf("failed to get client metadata from context: %w", err)
-	}
+	var (
+		sshAuthSock    dagql.Instance[*core.Socket]
+		httpAuthToken  dagql.Instance[*core.Secret]
+		httpAuthHeader dagql.Instance[*core.Secret]
+	)
 
-	// 3. Setup authentication
-	var authSock dagql.Instance[*core.Socket]
-	var authToken dagql.Instance[*core.Secret]
-
-	// First parse the ref scheme to determine auth strategy
-	remote, err := gitutil.ParseURL(args.URL)
-	if errors.Is(err, gitutil.ErrUnknownProtocol) {
-		remote, err = gitutil.ParseURL("https://" + args.URL)
-	}
-	if err != nil {
-		return inst, fmt.Errorf("failed to parse Git URL: %w", err)
-	}
-	if remote.Scheme == "ssh" && (remote.User == nil || remote.User.Username() == "") {
-		// default to git user for SSH, otherwise weird incorrect defaults like "root" can get
-		// applied in various places. This matches the git module source implementation.
+	switch remote.Scheme {
+	case gitutil.SSHProtocol:
 		if remote.User == nil {
+			// default to git user for SSH, otherwise weird incorrect defaults
+			// like "root" can get applied in various places. This matches the
+			// git module source implementation.
 			remote.User = url.User("git")
 		}
-		pass, ok := remote.User.Password()
-		if ok {
-			remote.User = url.UserPassword(remote.User.Username(), pass)
-		}
path: core/schema/git.go
user: login: jedevc
body: @sipsma so this was part of a git fix you did in [`68b2782` (#9682)](https://github.com/dagger/dagger/pull/9682/commits/68b2782cc3dd5ca2bf7a08a8ea34b01d22e3b35f)

But, I'll be honest, I can't quite tell what this bit is for? It seems to just add the password... which is already in there? Just wanted to check.

This whole URL manipulation actually gets so much neater with the forked `gitutil` package, since now there's `remote.String()`, which allows us to manipulate any of those URL fields inline.
created_at: 2025-04-23T14:13:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -123,191 +156,202 @@ func (s *gitSchema) git(ctx context.Context, parent dagql.Instance[*core.Query],
 		if err != nil {
 			return inst, err
 		}
-		svcs = append(svcs, core.ServiceBinding{
+		gitServices = append(gitServices, core.ServiceBinding{
 			ID:       svc.ID(),
 			Service:  svc.Self,
 			Hostname: host,
 		})
 	}
 
-	// 2. Get client metadata
-	clientMetadata, err := engine.ClientMetadataFromContext(ctx)
-	if err != nil {
-		return inst, fmt.Errorf("failed to get client metadata from context: %w", err)
-	}
+	var (
+		sshAuthSock    dagql.Instance[*core.Socket]
+		httpAuthToken  dagql.Instance[*core.Secret]
+		httpAuthHeader dagql.Instance[*core.Secret]
+	)
 
-	// 3. Setup authentication
-	var authSock dagql.Instance[*core.Socket]
-	var authToken dagql.Instance[*core.Secret]
-
-	// First parse the ref scheme to determine auth strategy
-	remote, err := gitutil.ParseURL(args.URL)
-	if errors.Is(err, gitutil.ErrUnknownProtocol) {
-		remote, err = gitutil.ParseURL("https://" + args.URL)
-	}
-	if err != nil {
-		return inst, fmt.Errorf("failed to parse Git URL: %w", err)
-	}
-	if remote.Scheme == "ssh" && (remote.User == nil || remote.User.Username() == "") {
-		// default to git user for SSH, otherwise weird incorrect defaults like "root" can get
-		// applied in various places. This matches the git module source implementation.
+	switch remote.Scheme {
+	case gitutil.SSHProtocol:
 		if remote.User == nil {
+			// default to git user for SSH, otherwise weird incorrect defaults
+			// like "root" can get applied in various places. This matches the
+			// git module source implementation.
 			remote.User = url.User("git")
 		}
-		pass, ok := remote.User.Password()
-		if ok {
-			remote.User = url.UserPassword(remote.User.Username(), pass)
-		}
-		fixedURL := &url.URL{
-			Scheme: remote.Scheme,
-			User:   remote.User,
-			Host:   remote.Host,
-			Path:   remote.Path,
-		}
-		if remote.Fragment != nil {
-			fixedURL.Fragment = remote.Fragment.Ref
-			if remote.Fragment.Subdir != "" {
-				fixedURL.Fragment += ":" + remote.Fragment.Subdir
-			}
-		}
-		args.URL = fixedURL.String()
-	}
 
-	// Handle explicit SSH socket if provided
-	switch {
-	case args.SSHAuthSocket.Valid:
-		sock, err := args.SSHAuthSocket.Value.Load(ctx, s.srv)
-		if err != nil {
-			return inst, err
-		}
-		authSock = sock
-
-	case remote.Scheme == "ssh" && clientMetadata != nil && clientMetadata.SSHAuthSocketPath != "":
-		// For SSH refs, try to load client's SSH socket if no explicit socket was provided
-		var sockInst dagql.Instance[*core.Socket]
-		if err := s.srv.Select(ctx, s.srv.Root(), &sockInst,
-			dagql.Selector{
-				Field: "host",
-			},
-			dagql.Selector{
-				Field: "unixSocket",
-				Args: []dagql.NamedInput{
-					{
-						Name:  "path",
-						Value: dagql.NewString(clientMetadata.SSHAuthSocketPath),
+		if args.SSHAuthSocket.Valid {
+			sshAuthSock, err = args.SSHAuthSocket.Value.Load(ctx, s.srv)
+			if err != nil {
+				return inst, err
+			}
+		} else if clientMetadata.SSHAuthSocketPath != "" {
+			// For SSH refs, try to load client's SSH socket if no explicit socket was provided
+			var sockInst dagql.Instance[*core.Socket]
+			if err := s.srv.Select(ctx, s.srv.Root(), &sockInst,
+				dagql.Selector{
+					Field: "host",
+				},
+				dagql.Selector{
+					Field: "unixSocket",
+					Args: []dagql.NamedInput{
+						{
+							Name:  "path",
+							Value: dagql.NewString(clientMetadata.SSHAuthSocketPath),
+						},
 					},
 				},
-			},
-		); err != nil {
-			return inst, fmt.Errorf("failed to select unix socket: %w", err)
-		}
+			); err != nil {
+				return inst, fmt.Errorf("failed to select unix socket: %w", err)
+			}
 
-		// reinvoke this API with the socket as an explicit arg so it shows up in the DAG
-		selectArgs := []dagql.NamedInput{
-			{
-				Name:  "url",
-				Value: dagql.NewString(args.URL),
-			},
-			{
-				Name:  "sshAuthSocket",
-				Value: dagql.Opt(dagql.NewID[*core.Socket](sockInst.ID())),
-			},
-		}
-		if args.KeepGitDir.Valid {
-			selectArgs = append(selectArgs, dagql.NamedInput{
-				Name:  "keepGitDir",
-				Value: dagql.Opt(args.KeepGitDir.Value),
-			})
-		}
-		if args.ExperimentalServiceHost.Valid {
-			selectArgs = append(selectArgs, dagql.NamedInput{
-				Name:  "experimentalServiceHost",
-				Value: dagql.Opt(dagql.NewID[*core.Service](args.ExperimentalServiceHost.Value.ID())),
-			})
+			// reinvoke this API with the socket as an explicit arg so it shows up in the DAG
+			selectArgs := []dagql.NamedInput{
+				{
+					Name:  "url",
+					Value: dagql.NewString(remote.String()),
+				},
+				{
+					Name:  "sshAuthSocket",
+					Value: dagql.Opt(dagql.NewID[*core.Socket](sockInst.ID())),
+				},
+			}
+			if args.KeepGitDir.Valid {
+				selectArgs = append(selectArgs, dagql.NamedInput{
+					Name:  "keepGitDir",
+					Value: dagql.Opt(args.KeepGitDir.Value),
+				})
+			}
+			if args.ExperimentalServiceHost.Valid {
+				selectArgs = append(selectArgs, dagql.NamedInput{
+					Name:  "experimentalServiceHost",
+					Value: dagql.Opt(dagql.NewID[*core.Service](args.ExperimentalServiceHost.Value.ID())),
+				})
+			}
+			if args.SSHKnownHosts != "" {
+				selectArgs = append(selectArgs, dagql.NamedInput{
+					Name:  "sshKnownHosts",
+					Value: dagql.Opt(dagql.NewString(args.SSHKnownHosts)),
+				})
+			}
+			err = s.srv.Select(ctx, parent, &inst, dagql.Selector{Field: "git", Args: selectArgs})
+			return inst, err
+		} else {
+			return inst, fmt.Errorf("SSH URLs are not supported without an SSH socket")
 		}
-		if args.SSHKnownHosts != "" {
-			selectArgs = append(selectArgs, dagql.NamedInput{
-				Name:  "sshKnownHosts",
-				Value: dagql.Opt(dagql.NewString(args.SSHKnownHosts)),
-			})
+	case gitutil.HTTPProtocol, gitutil.HTTPSProtocol:
+		if args.HTTPAuthToken.Valid {
+			httpAuthToken, err = args.HTTPAuthToken.Value.Load(ctx, s.srv)
+			if err != nil {
+				return inst, err
+			}
 		}
-		err = s.srv.Select(ctx, parent, &inst, dagql.Selector{Field: "git", Args: selectArgs})
-		return inst, err
-
-	case remote.Scheme == "ssh":
-		return inst, fmt.Errorf("SSH URLs are not supported without an SSH socket")
-	}
-
-	// For HTTP(S) refs, handle PAT auth if we're the main client
-	if (remote.Scheme == "https" || remote.Scheme == "http") && clientMetadata != nil {
-		parentClientMetadata, err := parent.Self.NonModuleParentClientMetadata(ctx)
-		if err != nil {
-			return inst, fmt.Errorf("failed to retrieve non-module parent client metadata: %w", err)
+		if args.HTTPAuthHeader.Valid {
+			httpAuthHeader, err = args.HTTPAuthHeader.Value.Load(ctx, s.srv)
+			if err != nil {
+				return inst, err
+			}
 		}
+		if httpAuthToken.Self == nil && httpAuthHeader.Self == nil {
+			// For HTTP refs, try to load client credentials from the git helper
+			parentClientMetadata, err := parent.Self.NonModuleParentClientMetadata(ctx)
+			if err != nil {
+				return inst, fmt.Errorf("failed to retrieve non-module parent client metadata: %w", err)
+			}
+			if clientMetadata.ClientID != parentClientMetadata.ClientID {
+				// only handle PAT auth if we're the main client
+				break
+			}
 
-		if clientMetadata.ClientID == parentClientMetadata.ClientID {
-			// Check if repo is public
-			repo := git.NewRemote(memory.NewStorage(), &config.RemoteConfig{
-				Name: "origin",
-				URLs: []string{remote.Remote()},
-			})
-
-			_, err := repo.ListContext(ctx, &git.ListOptions{Auth: nil})
-			switch {
-			case err == nil:
-				// no auth needed
-
-			case errors.Is(err, transport.ErrAuthenticationRequired):
-				// Only proceed with auth if repo requires authentication
-				authCtx := engine.ContextWithClientMetadata(ctx, parentClientMetadata)
-
-				bk, err := parent.Self.Buildkit(authCtx)
+			// start services if needed, before checking for auth
+			// XXX: does this even make sense?
path: core/schema/git.go
user: login: jedevc
body: :thinking: so previously, this didn't work, so I did a bit of hackery to get it working. Essentially, we would never use the client credential helper on `experimentalServiceHost`, since we'd hit a DNS resolution error immediately, and just not attach any creds.

This felt kind of inconsistent, but I'm also unsure of whether this is desirable behavior. I can imagine it both ways:
- The `Service` comes from `container.AsService` - in that case, it's all dagger internal, so it's weird to talk to the end-client for creds.
- The `Service` comes from an end-client tunnel - in that case, maybe it makes sense, the user might have configured this all deliberately.

I'm leaning towards keeping it? It won't do an extra harm IMO.
created_at: 2025-04-23T14:19:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -123,191 +156,202 @@ func (s *gitSchema) git(ctx context.Context, parent dagql.Instance[*core.Query],
 		if err != nil {
 			return inst, err
 		}
-		svcs = append(svcs, core.ServiceBinding{
+		gitServices = append(gitServices, core.ServiceBinding{
 			ID:       svc.ID(),
 			Service:  svc.Self,
 			Hostname: host,
 		})
 	}
 
-	// 2. Get client metadata
-	clientMetadata, err := engine.ClientMetadataFromContext(ctx)
-	if err != nil {
-		return inst, fmt.Errorf("failed to get client metadata from context: %w", err)
-	}
+	var (
+		sshAuthSock    dagql.Instance[*core.Socket]
+		httpAuthToken  dagql.Instance[*core.Secret]
+		httpAuthHeader dagql.Instance[*core.Secret]
+	)
 
-	// 3. Setup authentication
-	var authSock dagql.Instance[*core.Socket]
-	var authToken dagql.Instance[*core.Secret]
-
-	// First parse the ref scheme to determine auth strategy
-	remote, err := gitutil.ParseURL(args.URL)
-	if errors.Is(err, gitutil.ErrUnknownProtocol) {
-		remote, err = gitutil.ParseURL("https://" + args.URL)
-	}
-	if err != nil {
-		return inst, fmt.Errorf("failed to parse Git URL: %w", err)
-	}
-	if remote.Scheme == "ssh" && (remote.User == nil || remote.User.Username() == "") {
-		// default to git user for SSH, otherwise weird incorrect defaults like "root" can get
-		// applied in various places. This matches the git module source implementation.
+	switch remote.Scheme {
+	case gitutil.SSHProtocol:
 		if remote.User == nil {
+			// default to git user for SSH, otherwise weird incorrect defaults
+			// like "root" can get applied in various places. This matches the
+			// git module source implementation.
 			remote.User = url.User("git")
 		}
-		pass, ok := remote.User.Password()
-		if ok {
-			remote.User = url.UserPassword(remote.User.Username(), pass)
-		}
path: core/schema/git.go
user: login: sipsma
body: Believe there was an intention here to handle a case of `username == "" && userpassword != ""`, but it's off obviously. I was in the midst of trying to make all the pre-existing git integ tests pass when I added this code so I probably just moved on after they passed and didn't notice this bit was no-op. So nothing significant, thanks for cleaning up
created_at: 2025-04-24T20:11:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -2454,13 +2454,13 @@ type GitRepository {
   withAuthHeader(
     """Secret used to populate the Authorization HTTP header"""
     header: SecretID!
-  ): GitRepository!
+  ): GitRepository! @deprecated(reason: "Use \"httpAuthHeader\" instead.")
path: docs/docs-graphql/schema.graphqls
user: login: helderco
body: Maybe add "in the constructor" (or similar) to clarify?
created_at: 2025-04-28T16:04:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -2454,13 +2454,13 @@ type GitRepository {
   withAuthHeader(
     """Secret used to populate the Authorization HTTP header"""
     header: SecretID!
-  ): GitRepository!
+  ): GitRepository! @deprecated(reason: "Use \"httpAuthHeader\" instead.")
path: docs/docs-graphql/schema.graphqls
user: login: jedevc
body: :tada: yup agreed! Thanks :pray: 
created_at: 2025-04-28T16:31:55Z
author_association: CONTRIBUTOR

PR comments:
user: login: jed
created_at: 2025-04-24T10:45:48Z
body: what do i need to do not to get mentioned in this repo any more?
author_association: NONE
user: login: jedevc
created_at: 2025-04-24T10:53:41Z
body: @jed apologies there's a confusion when copy-pasting from our discord, where I go by `jed`. I've updated my username there in the hope that should stop the tagging confusion. Genuinely really sorry for the inconvenience :cry:
author_association: CONTRIBUTOR
user: login: jed
created_at: 2025-04-24T11:03:51Z
body: i appreciate that. github clearly needs a little more friction for @ mentions...
author_association: NONE
user: login: grouville
created_at: 2025-04-29T17:48:29Z
body: Coming in a bit late, but it's very neat 😍 
author_association: MEMBER
user: login: gerhard
created_at: 2025-04-29T19:23:29Z
body: I didn't go through all the code, but this started failing after we merged this PR: https://v3.dagger.cloud/dagger/traces/2fd74b07d6984b17ffefd842765a87c0?span=5df1ac3b414b9694

![image](https://github.com/user-attachments/assets/790d392d-02ef-4993-b8c9-43ca4bbe4661)

Do you see the problem @grouville @sipsma ?
author_association: CONTRIBUTOR
user: login: sipsma
created_at: 2025-04-29T21:39:01Z
body: > I didn't go through all the code, but this started failing after we merged this PR: https://v3.dagger.cloud/dagger/traces/2fd74b07d6984b17ffefd842765a87c0?span=5df1ac3b414b9694
> 
> ![image](https://private-user-images.githubusercontent.com/3342/438943064-790d392d-02ef-4993-b8c9-43ca4bbe4661.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NDU5NjI5MDQsIm5iZiI6MTc0NTk2MjYwNCwicGF0aCI6Ii8zMzQyLzQzODk0MzA2NC03OTBkMzkyZC0wMmVmLTQ5OTMtYjhjOS00M2NhNGJiZTQ2NjEucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDQyOSUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTA0MjlUMjEzNjQ0WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZWQyNWQyOWFjZjM3M2QxMzAwOWU0N2Q3Y2UwMWYyYTlkNzFiYmQzNjUxOTdjY2JkMzlkMTY4YzNkOGYzMjBjYiZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.2Ua7XYuAonrHBTXaOBwksmtW1Z4RcVlvC_2VY3pzOWI)
> 
> Do you see the problem @grouville @sipsma ?

@jedevc sent out a follow up to this PR w/ a fix for that: https://github.com/dagger/dagger/pull/10297
author_association: CONTRIBUTOR