-
Notifications
You must be signed in to change notification settings - Fork 155
Multi-host dependency support: lockfile identity, token resolution consistency, error clarity #773
Copy link
Copy link
Open
Labels
area/cliCLI command surface, flags, help text (cross-cutting).CLI command surface, flags, help text (cross-cutting).area/lockfileLockfile schema, per-file provenance, integrity hashes, drift detection.Lockfile schema, per-file provenance, integrity hashes, drift detection.priority/highShips in current or next milestoneShips in current or next milestonestatus/acceptedDirection approved, safe to start work.Direction approved, safe to start work.status/triagedInitial agentic triage complete; pending maintainer ratification (silence = approval).Initial agentic triage complete; pending maintainer ratification (silence = approval).theme/securitySecure by default. Content scanning, lockfile integrity, MCP trust boundaries.Secure by default. Content scanning, lockfile integrity, MCP trust boundaries.type/architectureDesign-impacting change (new module, pattern, contract).Design-impacting change (new module, pattern, contract).
Milestone
Metadata
Metadata
Assignees
Labels
area/cliCLI command surface, flags, help text (cross-cutting).CLI command surface, flags, help text (cross-cutting).area/lockfileLockfile schema, per-file provenance, integrity hashes, drift detection.Lockfile schema, per-file provenance, integrity hashes, drift detection.priority/highShips in current or next milestoneShips in current or next milestonestatus/acceptedDirection approved, safe to start work.Direction approved, safe to start work.status/triagedInitial agentic triage complete; pending maintainer ratification (silence = approval).Initial agentic triage complete; pending maintainer ratification (silence = approval).theme/securitySecure by default. Content scanning, lockfile integrity, MCP trust boundaries.Secure by default. Content scanning, lockfile integrity, MCP trust boundaries.type/architectureDesign-impacting change (new module, pattern, contract).Design-impacting change (new module, pattern, contract).
Type
Projects
Status
Todo
Summary
PR #587 (generic git host / Gitea support) surfaces several pre-existing architectural and DX gaps in the dependency identity, token resolution, and error-reporting paths. None of these block #587 directly, but they should land before multi-host support is GA so we don't ship known sharp edges to users adopting Gitea / Bitbucket / self-hosted GitLab.
Items
1. Lockfile identity collision:
get_unique_key()omits hostDependencyReference.get_unique_key()andLockedDependency.get_unique_key()both return the barerepo_url(e.g.team/skills) without the host. Two dependencies with the sameowner/repoon different hosts collide silently inapm.lock:→ second entry overwrites the first; install order becomes load-bearing.
Severity: correctness / data-integrity. Becomes much more likely once #587 lands.
Files:
src/apm_cli/models/dependency/reference.py(lines ~176-190),src/apm_cli/deps/lockfile.py(lines ~43-49, ~196).Suggested fix: include host in
get_unique_key()for non-default hosts (preserve bareowner/repoforgithub.comto keep existing lockfiles stable).2. Asymmetric token resolution between download and clone paths
_download_github_filecallsauth_resolver.resolve()directly (line ~1207 ofgithub_downloader.py), while the clone path correctly routes through_resolve_dep_token()which returnsNonefor generic hosts. The asymmetry is not a security issue (HTTPS is the transport boundary percore/auth.py:377-379), but it produces misleading 401 errors when a GitHub PAT is sent to a Gitea / GitLab server that rejects it — instead of falling through to git-credential-helper as the clone path does.Severity: DX / error-message clarity.
Suggested fix: route
_download_github_filetoken resolution through_resolve_dep_token()for consistency.3.
is_gitlab_hostname()is convention-based and fragilestartswith("gitlab.")misses org-managed GitLab instances on bespoke hostnames (code.acme.com,git.team.org, etc.). The whole GitLab-vs-other-generic-host bifurcation in #587 falls back to a heuristic that doesn't hold.Severity: correctness on non-conformant hostnames.
Suggested fix: consider explicit user signaling (
type: gitlabinapm.yml) or capability-detection via API probe + cache, rather than relying on hostname conventions.4. Silent error swallowing in download fallback chain
_download_github_fileruns up to 7 attempts (raw + API × ref × API version), and currently swallows non-404 errors at each step — auth failures, 5xx, network errors all surface to the user as "file not found." There's also noverbose_callbackbreadcrumb per attempt, so--verbosedoesn't help users understand which endpoint was tried.Severity: DX / debuggability.
Suggested fix: classify exceptions, only swallow 404, surface 401/403/5xx with the host + endpoint context. Emit one
verbose_callbackline per attempt.5. Pre-existing GitHub-specific error strings reachable for generic hosts
Strings like
"GitHub API rate limit exceeded"are now reachable from Gitea / GitLab error paths via the shared download code. Should be parameterized onhost.Severity: polish.
Non-goals
Not changing the deliberate project stance that "HTTPS is the transport security boundary" (auth.py:377-379) — global PATs may be sent to user-configured hosts. This issue is about correctness, identity, and error-clarity, not transport gating.
Why now
PR #587 quadruples the surface area of the download fallback chain and introduces multi-host scenarios the lockfile identity model wasn't designed for. Tracking these explicitly so they don't get forgotten when #587 lands.