# 0030: Package repo on a CDN

> The package repo sits behind a CDN with the release host as fallback; the x86-64-v3 repos are reached by redirect, not copied.

Source: https://wolos.pages.dev/manual/adr-0030

## Context

ADR 0019 republished the x86-64-v3 builds of CachyOS as `[wolos-cachy]`: a release-time copy (about 1 GiB, 536 packages) selected by version match, re-signed, uploaded as GitHub release assets and mirrored by a token-protected CDN that accepted files under 99 MB. That was a second package pipeline to run and verify at every release, a 1000-asset limit to watch, and a repo whose contents nobody chose (whatever matched that day). `[wolos]` itself went through the same CDN by hand-rolled PUTs. WolOS now has one build path (0029) and an AWS account; the repo needs one plain, cacheable home.

## Decision

- `[wolos]` is served by CloudFront in front of the S3 bucket `wolos-repo` (OAC, private). Object layout `<tag>/<file>` (`wolos-2026-10-31/<pkg>`, `wolos-testing/<pkg>`): the same paths as the release assets, so `Server = https://<domain>/$repo-<date>` works on both. Publish is `aws s3 sync` (packages and signatures first, databases last; `Cache-Control: public, max-age=31536000, immutable` for packages and signatures, `public, max-age=60` for `.db`, `.files` and `revision`) plus an invalidation. The distribution's `wolos*` behaviour is an origin group: S3 first, the GitHub release assets (`github.com/wonderlandos/wolos-packages/releases/download`) on 403/404/5xx. `wolos-mirrorlist` lists the CloudFront domain first and GitHub second; the squareweb CDN and the bearer-token push are gone.
- The CachyOS x86-64-v3 repos are **not republished**. `pacman.conf` carries three gated sections `[cachyos-v3]`, `[cachyos-core-v3]`, `[cachyos-extra-v3]` (CachyOS's own names and order, between `[wolos]` and Arch) that include `/etc/pacman.d/wolos-cachy-mirrorlist`: one line, `Server = https://<domain>/cachy/$repo`. The distribution's `cachy/*` behaviour is a CloudFront Function (viewer-request) that answers `302` to `https://<mirror>/repo/x86_64_v3/<repo>/<file>` on a mirror ranked for the viewer's region; nothing is fetched or cached by CloudFront. pacman follows redirects (libcurl `FOLLOWLOCATION`), so does `curl -L` in `wol mirror rank`. A Lambda (python 3.12, EventBridge every 30 min) seeds its list from the `cachyos-v3-mirrorlist` package, HEADs `cachyos-v3.db` on every mirror, keeps the fresh ones (database within a day of the newest) ordered by latency, groups them by region, writes the result into the function's source (`function.js` is the template in the repo, with a marker for the inlined list) and publishes the function (`UpdateFunction` + `PublishFunction`; Terraform ignores the code afterwards). No KeyValueStore: its API needs SigV4A signing, which the Lambda runtime's boto3 cannot do without an extra wheel.
- `Architecture = x86_64 x86_64_v3` in both `pacman.conf` copies: CachyOS v3 packages carry `arch = x86_64_v3` in `.PKGINFO` (checked on `gcc-libs` from `cachyos-v3`, 2026-11-01); `$arch` in Server lines stays `x86_64`.
- `wol mirror gate` turns the three sections on together, only on x86-64-v3 CPUs (`wol_core::mirror::CACHY_REPOS`); a partial set counts as off and is completed. `wol mirror rank` reorders `[wolos]` only. `release.json` has no `cachy` field (the `Manifest` field stays, defaulting to empty, for older readers).
- The CachyOS signing key stays pinned in `wolos-pkgbuilds/wolos-keyring/cachy-trusted` and shipped fully trusted in `wolos-keyring`; packages and databases keep their upstream signatures and pacman checks them (`SigLevel = Required DatabaseOptional`).

Caveat, stated on purpose: **the CachyOS repos roll while Arch is pinned.** `[wolos]` and the Arch repos sit at one archive date per release; `cachyos-*-v3` has no archive and moves daily. On a v3 machine with the sections on, `pacman -Syu` can take a newer CachyOS build of a library than the pinned Arch date has, a partial upgrade in the Arch sense (a dependency that Arch at the snapshot does not satisfy, or an soname Arch's pinned consumers were not built against). ADR 0019's copy avoided this by version matching at release time. Options weighed: (a) keep republishing (what is removed here); (b) a pull-through cache of CachyOS files on CloudFront, frozen per release (needs the lead's OK to host their packages, and a selection step again); (c) a redirect only, and watch. **Decision: (c), the redirect only, for one release.** After it, measure on real v3 installs: how often the sections are on, pacman errors from version mismatches, and anything `wol update` could not reconcile; then decide between staying, (b) with a pinned selection, or dropping the v3 repos. Mitigations now: the sections are off by default and off on every CPU below v3; `HoldPkg`, `SigLevel` and the slot-based update (0016) still apply; `wol update` moves only `[wolos]` and Arch, so a rollback to the other slot undoes a bad CachyOS pull.

## Consequences

one less pipeline at release and no 2 GiB / 1000-asset ceiling; `[wolos]` downloads come from an edge, cached a year by content (databases 60 s). The CloudFront domain is a `*.cloudfront.net` name for now (no custom domain or certificate yet); it is written into `wolos-mirrorlist` and `wolos-cachy-mirrorlist` once, after `terraform apply` (`terraform output repo_domain`), with a pkgrel bump: until then the placeholder `REPO_DOMAIN` fails over to GitHub for `[wolos]`, and the CachyOS sections must stay off. A CachyOS mirror outage costs a redirect to the next ranked mirror, not a WolOS release. `wolos-build/infra/cdn.tf` describes everything; `wolos-build/cdn/` holds the function and the ranking Lambda with their tests.
