Prechádzať zdrojové kódy

Document DCBA artifact repository support

The README now describes the mixed layout: .dcbar repositories discovered
beside .usmr ones under the same parent (a directory holding both
descriptors is a configuration error; the legacy single-repo fallback stays
.usmr-only), the three new routes (verbatim ARTIFACTS.usml, url-rewritten
repo.dcbar, artifact detail) and the kind-guarded .usmc/.dcba download
endpoint. The serves table states the home/usmc split (DCBA repos as cards,
package table, hero counts and search stay source-package-only), and a new
"DCBA repositories" subsection explains what a .dcba is, the
"sudo usm dcba add-repo" verb and the exact name+version matching that
drives the pre-built artifacts section on package pages and the
one-directional source-package link on artifact pages. Layout table updated
with the new endpoints/entrypoints/artifact page.
saddle-Clanker-Saddle 1 mesiac pred
rodič
commit
f57ab28fcd
1 zmenil súbory, kde vykonal 72 pridanie a 23 odobranie
  1. 72 23
      README.md

+ 72 - 23
README.md

@@ -4,25 +4,31 @@ A Statum + Spry application that browses **and serves** any number of USM
 repositories: human-facing pages for exploring packages (an all-repository
 overview plus per-repository browse views), plus the exact HTTP endpoints a
 real USM client (`usm repository list` / `verify` / `install`) expects to
-fetch from a repository host.
+fetch from a repository host. Alongside USM source repositories it also
+serves **DCBA artifact repositories** — repositories of pre-built build
+artifacts (`.dcba`) that `usm install` fetches instead of building a package
+from source (`usm dcba add-repo` / `usm dcba repository list`).
 
 ## What it serves
 
 | Endpoint | Purpose |
 |---|---|
-| `GET /` | Overview: every repository (name, summary, package count, total size), per-repo add-repository instructions (`sudo usm add-repo <repo.usmr URL>`), the global install-USM block, and a combined package table with repo badges + server-side search across all repositories |
-| `GET /repo/{name}` | Single-repo browse: that repository's overview card, instructions and package table, search scoped to it |
-| `GET /repo/{name}/package/{file}` | Package detail: manifest fields read out of the `.usmc` (licences, flags, provides/depends tables), sha512, on-disk size/mtime, download button |
-| `GET /repo/{name}/PACKAGES.usml` | That repository's listing streamed **verbatim** (`application/json`) |
+| `GET /` | Overview: every repository of both kinds as a card (name, summary, chip, kind-appropriate counts and `sudo usm add-repo` / `sudo usm dcba add-repo` instructions), the global install-USM block, and a **source-package-only** combined table (usmc rows from USM repositories, repo badges) with server-side search across them — DCBA repositories appear as cards, never as package rows |
+| `GET /repo/{name}` | Single-repo browse: that repository's overview card and instructions. A USM repository renders its package table with search scoped to it; a DCBA repository renders an artifacts table (name, version, size, download) instead — search stays source-package-only |
+| `GET /repo/{name}/package/{file}` | Package detail: manifest fields read out of the `.usmc` (licences, flags, provides/depends tables), sha512, on-disk size/mtime, download button, plus a "Pre-built artifacts" section listing every DCBA repository carrying an artifact for this exact name + version |
+| `GET /repo/{name}/artifact/{file}` | Artifact detail (DCBA repositories): listing-derived name/version, sha512, on-disk size/mtime, download button, the `usm dcba add-repo` instruction and — on an exact name+version match — a one-directional link to the source package's detail page |
+| `GET /repo/{name}/PACKAGES.usml` | That USM repository's listing streamed **verbatim** (`application/json`); a DCBA repository has none and answers 404 |
+| `GET /repo/{name}/ARTIFACTS.usml` | That DCBA repository's artifact listing streamed **verbatim** (`application/json`) so signatures and checksums stay valid; a USM repository answers 404 |
 | `GET /repo/{name}/repo.usmr` | A rewritten copy of the `.usmr` with its embedded `url` replaced by the derived base + `repo/{name}/` — the URL `sudo usm add-repo` consumes |
-| `GET /repo/{name}/{file}.usmc` | Package archives streamed from that repository's `public/` (`application/octet-stream`, exact content-length) |
+| `GET /repo/{name}/repo.dcbar` | The rewritten DCBA counterpart: a copy of the `.dcbar` with its `url` replaced by the derived base + `repo/{name}/` — the URL `sudo usm dcba add-repo` consumes (the route name is canonical regardless of the on-disk descriptor's filename) |
+| `GET /repo/{name}/{file}.usmc` / `GET /repo/{name}/{file}.dcba` | Package archives / pre-built artifacts streamed from that repository's `public/` (`application/octet-stream`, exact content-length); the suffix selects the repository kind, so the wrong kind (or a listing the other kind owns) answers 404 |
 | `GET /install-usm.sh` | The configured installer script (`installer.path` mode only), served by the root-level catch-all |
 
 The derived base is `base_url` from the config when set, else
 `X-Forwarded-Proto`/`X-Forwarded-Host`, else the request's own scheme/host —
 so clients behind a reverse proxy resolve against the public name. Each
-repository is addressed by the `name` in its `.usmr`, which is also its
-routing segment.
+repository is addressed by the `name` in its `.usmr` or `.dcbar`, which is
+also its routing segment.
 
 ## Configuration
 
@@ -44,8 +50,8 @@ carries the static Statum keys plus an optional `"usm-web"` section:
 
 | Key | Meaning |
 |---|---|
-| `repo` | The parent directory holding the repositories (each a subdirectory with a `.usmr` and `public/`); relative paths resolve against the config file's directory |
-| `repositories` | Optional explicit list of repository subdirectories to serve (in that order); when absent or empty every subdirectory containing a `.usmr` is discovered by scanning |
+| `repo` | The parent directory holding the repositories (each a subdirectory with a `.usmr` **or** a `.dcbar` plus `public/`); relative paths resolve against the config file's directory |
+| `repositories` | Optional explicit list of repository subdirectories to serve, of either kind, in that order; when absent or empty every subdirectory containing a `.usmr` or a `.dcbar` is discovered by scanning |
 | `installer.url` | External installer location; the homepage links out and shows `curl -fsSL <url> \| sh` |
 | `installer.path` | Installer script this app serves at `/install-usm.sh`; relative paths resolve against the config file's directory |
 | `base_url` | Optional override of the request-derived repository base (normalised to a trailing slash) |
@@ -67,17 +73,60 @@ the `USM_WEB_REPO_DIR` environment variable, the config's `repo` key, or the
 │   └── public/
 │       ├── PACKAGES.usml
 │       └── <name>-<version>.usmc
+├── prebuilt/
+│   ├── prebuilt.dcbar   (same JSON shape as a .usmr)
+│   ├── keys/
+│   └── public/
+│       ├── ARTIFACTS.usml
+│       └── <name>-<version>.dcba
 └── extra/
     └── …
 ```
 
+USM source repositories and DCBA artifact repositories live side by side
+under the same parent — there is no separate configuration for the second
+kind. A subdirectory is classified by its descriptor: `.usmr` makes it a
+USM source repository (`.usmc` packages in `public/PACKAGES.usml`), `.dcbar`
+a DCBA artifact repository (`.dcba` artifacts in `public/ARTIFACTS.usml`).
+A directory holding **both** descriptors is a configuration error; split it
+into two subdirectories instead.
+
 A legacy single-repository layout with the `.usmr` directly inside the
-configured directory is still served as one repository. Discovery re-runs on
+configured directory is still served as one repository (this fallback stays
+`.usmr`-only; a bare `.dcbar` in the parent is not discovered). Discovery re-runs on
 every request, so repositories added or removed on disk are picked up without
-a restart, and each repository's `.usmr` and `PACKAGES.usml` re-read when
-their mtimes change — one repository can be rebuilt without disturbing the
-others. There is **no database and no authentication**; all Statum state is
-stateless PAGE slots.
+a restart, and each repository's descriptor (`.usmr`/`.dcbar`) and listing
+(`PACKAGES.usml`/`ARTIFACTS.usml`) re-read when their own mtimes change —
+one repository can be rebuilt without disturbing the others. There is **no
+database and no authentication**; all Statum state is stateless PAGE slots.
+
+### DCBA repositories
+
+A DCBA repository distributes **pre-built build artifacts**: one `.dcba`
+archive per package name + version (built and published upstream with
+`usm dcba repository init` / `add` / `publish`), described by a `.dcbar`
+(the same JSON shape as a `.usmr`) and listed in a signed
+`public/ARTIFACTS.usml`. With such a repository configured, `usm install`
+fetches the artifact instead of building the package from source.
+
+Two things differ from the usmc flow when pointing a client at one:
+
+- the verb carries the `dcba` subcommand: `sudo usm dcba add-repo <url>`
+  (not `sudo usm add-repo`), where `<url>` is the served
+  `.../repo/<name>/repo.dcbar` rewrite;
+- clients match artifacts by **plain name + version string comparison**, so
+  the package detail pages surface pre-built artifacts only when a DCBA
+  repository carries that exact version — a newer or older artifact version
+  never shows up as "for" that package.
+
+The views keep the two kinds apart: the home page lists DCBA repositories
+as cards (with artifact counts and their own add-repo instruction) but the
+package table, the Packages/Total-size hero counts and search stay
+usmc-only; a DCBA repository's browse page shows its artifacts table, and
+each artifact has a detail page with its sha512 and a one-directional link
+to the matching source package (a package page then lists every DCBA
+repository carrying its pre-built artifacts, so the pair is discoverable
+from both sides).
 
 ## Development
 
@@ -107,8 +156,8 @@ ninja -C builddir
 
 `--repo` points at the parent directory holding the repositories (see the
 layout above). Repo parsing uses libusm (`Usm.Repository`,
-`Usm.RepositoryListing`, `Usm.Manifest.from_package`) — no hand-rolled
-usml/usmr mappers.
+`Usm.RepositoryListing`, `Usm.DcbaListing`, `Usm.Manifest.from_package`) —
+no hand-rolled usml/usmr/dcbar mappers.
 
 ## Layout
 
@@ -116,13 +165,13 @@ usml/usmr mappers.
 |---|---|
 | `src/main.vala` | application wiring: modules, config, pages, action, endpoints |
 | `src/UsmWebConfig.vala` | the `"usm-web"` config section (repo parent, repositories, installer url\|path, base_url, name) |
-| `src/RepositoryService.vala` | multi-repository discovery + libusm-backed read side with per-repo mtime reload |
+| `src/RepositoryService.vala` | multi-repository discovery (`.usmr` and `.dcbar` subdirectories, kind-guarded members) + libusm-backed read side with per-repo mtime reload |
 | `src/DerivedBase.vala` | base-URI derivation from config/forwarded headers |
-| `src/PackagesState.vala` | shared `packages` slot-state builder (overview + repo-scoped) and size/fingerprint formatting |
-| `src/entrypoints/` | `HomeEntrypoint` (/), `RepoBrowseEntrypoint` (/repo/{name}) and `PackageDetailEntrypoint` (/repo/{name}/package/{file}) |
+| `src/PackagesState.vala` | shared `packages` slot-state builder (overview + repo-scoped, both repository kinds, DCBA artifact rows) and size/fingerprint formatting |
+| `src/entrypoints/` | `HomeEntrypoint` (/), `RepoBrowseEntrypoint` (/repo/{name}), `PackageDetailEntrypoint` (/repo/{name}/package/{file}) and `ArtifactDetailEntrypoint` (/repo/{name}/artifact/{file}) |
 | `src/actions/` | `SearchPackagesAction` — server-side table filtering (all repositories or one) |
-| `src/endpoints/` | the USM-facing endpoints listed above |
-| `src/pages/*.html` | Statum pages, compiled by `statum-mkpstm` at build time |
+| `src/endpoints/` | the USM/DCBA-facing endpoints listed above (`PackagesListingEndpoint`, `RepositoryDefinitionEndpoint`, `ArtifactsListingEndpoint`, `DcbaDefinitionEndpoint`, `PackageDownloadEndpoint`, `InstallerScriptEndpoint`) |
+| `src/pages/*.html` | Statum pages (`home`, `repo`, `package`, `artifact`), compiled by `statum-mkpstm` at build time |
 | `src/Static/main.css` | stylesheet embedded by `statum-mkres` |
 | `MANIFEST.usm` | USM package manifest: `provides bin:usm-web`, build/runtime/manage deps |
 | `usm-scripts/` | USM build + install scripts (meson staging) |
@@ -174,4 +223,4 @@ podman run -d -p 8080:8080 \
 ```
 
 `/repo` inside the container is the repositories **parent** directory: every
-subdirectory holding a `.usmr` is served at `/repo/<name>/…`.
+subdirectory holding a `.usmr` or a `.dcbar` is served at `/repo/<name>/…`.