aim/.plans/007-source-provider-expansion/2026-03-20-source-provider-expansion-design.md

7.2 KiB

Source And Provider Expansion Design

Goal

Expand install-source coverage beyond the current GitHub-centric path without collapsing providers, exact artifact sources, and update metadata into one abstraction.

Problem Statement

The current codebase has a real mismatch between what the domain and adapter layers suggest is possible and what the end-to-end install pipeline actually treats as first-class:

  • the domain source model already includes GitHub, GitLab, direct URL, and file
  • the adapter layer also advertises SourceForge and zsync shapes
  • the public source pipeline and most end-to-end behavior are still effectively GitHub-shaped

That creates two problems:

  • adding new install origins risks becoming a copy of the GitHub path with provider-specific exceptions bolted on later
  • zsync is at risk of being modeled as a provider even though the current code treats it primarily as update metadata

Design Goals

  • make GitLab a real repository-backed install source
  • make SourceForge a real repository-backed install source
  • preserve direct-url as a first-class exact-resolution source
  • keep install origin semantics truthful in the registry
  • allow provider-native update re-resolution where it fits naturally
  • keep zsync as update metadata rather than forcing it into the install-source model

Non-Goals

  • generic search UX across all providers
  • full behavioral parity across every provider in the first slice
  • rewriting the CLI presentation layer
  • promoting zsync into a first-class install source
  • inventing a universal provider abstraction that erases real capability differences

Architectural Decision

Separate three concerns explicitly:

  • source kind: how the user identified the install origin
  • resolution strategy: how the system turns that origin into a concrete installable artifact
  • update channel: how an installed application later discovers newer payloads

Under this model:

  • GitHub, GitLab, and SourceForge are repository-backed source kinds
  • direct-url is an exact artifact source kind
  • file remains a local artifact source kind
  • zsync remains an update-channel and metadata mechanism

This keeps install and update semantics aligned without pretending every source type has provider-like behavior.

Source Taxonomy

The input classification layer should classify user queries into a small, stable taxonomy:

  • repository-backed sources
    • GitHub
    • GitLab
    • SourceForge
  • exact artifact sources
    • direct URL
  • local artifact sources
    • file

Classification should answer only:

  • what kind of source the user provided
  • what canonical locator can be derived
  • whether release or asset hints are present
  • whether the origin is inherently trackable

Classification should not try to encode provider-specific release discovery beyond those normalized hints.

Resolution Model

After classification, a resolver layer should convert a SourceRef into an installable release candidate.

Repository-backed sources

Repository-backed resolution should:

  • accept a canonical repository or project locator
  • discover release or download candidates using provider-specific logic
  • select a concrete AppImage payload when confidence is sufficient
  • return explicit structured failures when the repository exists but no installable AppImage is available

This applies to:

  • GitHub
  • GitLab
  • SourceForge

Exact artifact sources

Exact-resolution sources should:

  • treat the user-provided locator as the concrete payload origin
  • derive best-effort metadata without pretending release discovery exists
  • remain installable even when rich update tracking is unavailable

This applies to:

  • direct URL
  • file

Registry Semantics

Registry persistence should preserve the truth about where the install came from.

Each installed record should continue to store:

  • original source kind
  • original source locator
  • canonical locator when one exists
  • installed version
  • installed file metadata

The key rule is:

  • install origin remains the origin the user chose
  • update mechanisms are additive metadata, not a replacement source identity

That means a direct URL install remains a direct URL install even if metadata later yields a richer update channel. A GitLab install remains a GitLab install even if update planning later uses provider-specific release rediscovery.

Update Strategy

Update planning should use the install origin as the primary re-entry point.

For repository-backed sources:

  • prefer provider-native re-resolution using the canonical locator
  • attach update channels discovered during metadata inspection as additional evidence

For exact-resolution sources:

  • keep update support weak by default unless post-install metadata offers something stronger

For zsync:

  • keep it as discovered metadata and update-channel input
  • do not rewrite the install source as zsync
  • do not require zsync install-source tests in this phase

This preserves a clean distinction between install origin and update mechanism.

Error Handling

The design should distinguish unsupported semantics from runtime failure.

Unsupported source semantics

Examples:

  • malformed provider URL shapes
  • a project URL form we do not support yet
  • a provider source kind sent to the wrong resolver

These should fail early during classification or resolver selection with provider-aware messages.

Resolvable source, but no installable artifact

Examples:

  • repository exists but has no AppImage asset
  • release metadata is present but incomplete
  • multiple assets exist but none match install heuristics confidently

These should be structured resolution failures rather than generic unsupported errors.

Transport or integration failure

Examples:

  • HTTP download failures
  • metadata fetch failures
  • local staging or desktop integration failures

These remain operational failures in the existing install and update flow.

Testing Strategy

Testing should expand along capability lines rather than provider-specific copy-paste.

Classification tests

Add coverage for:

  • GitLab source forms
  • SourceForge source forms
  • direct URL edge cases
  • unsupported or malformed provider inputs

Resolver contract tests

Each resolver should satisfy a shared contract:

  • accepts valid source refs for its own kind
  • rejects source refs for other kinds
  • returns a concrete install candidate or a structured no-artifact result

End-to-end flow tests

Add focused flow coverage for:

  • install from GitLab source
  • install from direct URL
  • install from SourceForge source
  • truthful registry origin persistence
  • update planning that uses install origin plus additive metadata

Non-goal tests

Do not force zsync into install-source tests for this phase.

Rollout

Recommended rollout order:

  1. normalize the source taxonomy and resolver interfaces
  2. wire GitLab and direct URL cleanly through install and registry persistence
  3. add SourceForge using the same resolver contract, limited to supported URL and project forms
  4. extend update planning only where the source kind supports provider-native re-resolution naturally
  5. leave zsync unchanged except to ensure it remains additive update metadata

This keeps the product honest: each added source gets explicit semantics instead of being forced through a renamed GitHub pathway.