227 lines
No EOL
7.2 KiB
Markdown
227 lines
No EOL
7.2 KiB
Markdown
# 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. |