Problem
DependencyReference.port is parsed and threaded through URL construction (#665), but is never propagated into the credential resolution path. git credential fill supports a port= field, but APM always sends bare hostname only:
# token_manager.py:111
input=f"protocol=https\nhost={host}\n\n" # no port= line
Affected code path:
| Layer |
File |
Gap |
| Auth resolver |
core/auth.py:210 |
resolve_for_dep() reads dep_ref.host, ignores dep_ref.port |
| Cache key |
core/auth.py:183 |
(host.lower(), org.lower()) — no port dimension |
| Host model |
core/auth.py:56 |
HostInfo has no port field |
| Credential fill |
core/token_manager.py:111 |
git credential fill input omits port= |
Impact
When a user has the same hostname serving git on different ports with different credentials (e.g. bitbucket.corp.com:7999 for SSH and bitbucket.corp.com:7990 for HTTPS, each requiring distinct PATs), APM's pre-resolved token path (Method 1: authenticated HTTPS) may resolve the wrong credential.
Mitigating factor: for non-GitHub hosts, APM's token resolution typically returns None, and git's own clone process queries credential helpers with the full URL including port — so the direct clone path handles this correctly. The gap only affects the pre-resolved token path in _resolve_token.
Suggested fix
1. HostInfo — add port
@dataclass(frozen=True)
class HostInfo:
host: str
port: Optional[int] = None # Non-standard git port
kind: str
has_public_repos: bool
api_base: str
2. AuthResolver — port-aware cache key
key = (host.lower(), port, org.lower() if org else "")
3. resolve_for_dep — thread port
def resolve_for_dep(self, dep_ref):
host = dep_ref.host or default_host()
port = dep_ref.port
org = dep_ref.repo_url.split("/")[0] if dep_ref.repo_url else None
return self.resolve(host, org, port=port)
4. resolve_credential_from_git — pass port to git credential protocol
input_str = f"protocol=https\nhost={host}\n"
if port:
input_str += f"port={port}\n"
input_str += "\n"
All new parameters default to None — fully backward compatible.
Limitation worth documenting
Not all credential helpers honor the port field. OS keychains and gh auth typically store credentials per-hostname. APM can pass the information correctly, but per-port discrimination ultimately depends on the helper implementation. A one-line note in docs/getting-started/authentication.md under "Git credential helper not found" would set expectations.
Context
Follow-up from PR #665 review (auth-expert panel finding). The port field was introduced on DependencyReference and LockedDependency but was only wired into URL construction, not credential resolution.
Refs: #661, #665
Problem
DependencyReference.portis parsed and threaded through URL construction (#665), but is never propagated into the credential resolution path.git credential fillsupports aport=field, but APM always sends bare hostname only:Affected code path:
core/auth.py:210resolve_for_dep()readsdep_ref.host, ignoresdep_ref.portcore/auth.py:183(host.lower(), org.lower())— no port dimensioncore/auth.py:56HostInfohas noportfieldcore/token_manager.py:111git credential fillinput omitsport=Impact
When a user has the same hostname serving git on different ports with different credentials (e.g.
bitbucket.corp.com:7999for SSH andbitbucket.corp.com:7990for HTTPS, each requiring distinct PATs), APM's pre-resolved token path (Method 1: authenticated HTTPS) may resolve the wrong credential.Mitigating factor: for non-GitHub hosts, APM's token resolution typically returns
None, and git's own clone process queries credential helpers with the full URL including port — so the direct clone path handles this correctly. The gap only affects the pre-resolved token path in_resolve_token.Suggested fix
1.
HostInfo— add port2.
AuthResolver— port-aware cache key3.
resolve_for_dep— thread port4.
resolve_credential_from_git— pass port to git credential protocolAll new parameters default to
None— fully backward compatible.Limitation worth documenting
Not all credential helpers honor the
portfield. OS keychains andgh authtypically store credentials per-hostname. APM can pass the information correctly, but per-port discrimination ultimately depends on the helper implementation. A one-line note indocs/getting-started/authentication.mdunder "Git credential helper not found" would set expectations.Context
Follow-up from PR #665 review (auth-expert panel finding). The port field was introduced on
DependencyReferenceandLockedDependencybut was only wired into URL construction, not credential resolution.Refs: #661, #665