feat(edge): route PACKAGES requests to the per-R-minor slot

- add edge/rpkgs-router.ts, which redirects PACKAGES, PACKAGES.gz and
  PACKAGES.rds into …/src/contrib/<x.y>/ for slots listed in UNION_SLOTS
- leave tarballs alone: R keeps the pre-redirect contrib URL, so the union
  index steers per-minor tarballs with a Path field instead
- stop resolving an unidentifiable distro to a phantom linux-gnu/linux-musl
  slot and send those clients to CRAN
- mark every redirect no-store, since the target depends on the User-Agent
- cover the routing matrix in edge/rpkgs-router.test.ts, run by just edge-test
- correct the spec and plan: the union index carries Path: <x.y> on per-minor
  records, not Path: .. on flat ones
This commit is contained in:
Patrick Schratz 2026-08-07 14:00:14 +00:00
commit 628d19d650
No known key found for this signature in database
GPG key ID: 62050D5BC68AB6DC

View file

@ -10,7 +10,7 @@ Spec: `specs/2026-08-07-per-minor-edge-routing-design.md`
## Global constraints
- Redirect only `PACKAGES`, `PACKAGES.gz` and `PACKAGES.rds`; never a tarball, because `Path: ..` entries arrive already normalised to the flat path.
- Redirect only `PACKAGES`, `PACKAGES.gz` and `PACKAGES.rds`; never a tarball, because the union index already carries the correct tarball URL for both classes of package.
- Every redirect carries `Cache-Control: no-store`; redirect targets stay UA-independent.
- `UNION_SLOTS` is empty by default, so deploying the script is a no-op until a slot is backfilled.
- A slot is `<arch>/<os>`, e.g. `amd64/alpine324`.
@ -138,9 +138,9 @@ git commit -m "feat(cdn): manage the edge middleware script from this repo"
- [ ] **Step 1: write the failing tests**
- a package present in both slots keeps the per-minor record and gains no `Path`
- a package only in the flat slot survives with `Path = ".."`
- a package only in the per-minor slot survives unchanged
- a package present in both slots keeps the per-minor record, with `Path = "4.5"`
- a package only in the flat slot survives with no `Path`
- a package only in the per-minor slot survives with `Path = "4.5"`
- a union smaller than the flat input raises an error rather than returning
- [ ] **Step 2: run them and watch them fail**
@ -149,7 +149,7 @@ git commit -m "feat(cdn): manage the edge middleware script from this repo"
- [ ] **Step 3: implement `write_union_index()` and call it from `upload_package_index()`**
After `update_PACKAGES()` has written the per-minor index, read the flat slot's `PACKAGES.rds`, drop packages already in the per-minor index, set `Path = ".."` on the rest, and rewrite `PACKAGES`, `PACKAGES.gz` and `PACKAGES.rds` in the per-minor slot.
After `update_PACKAGES()` has written the per-minor index, read the flat slot's `PACKAGES.rds`, set `Path = <r_minor>` on the per-minor records, drop the flat records for packages the per-minor slot already has, and rewrite `PACKAGES`, `PACKAGES.gz` and `PACKAGES.rds` in the per-minor slot.
- [ ] **Step 4: run the tests until they pass**
@ -159,7 +159,7 @@ After `update_PACKAGES()` has written the per-minor index, read the flat slot's
## Task 4: Roll out slot by slot
- [ ] Re-index one slot (`amd64/alpine324`, R 4.5) and confirm the union index lists both `curl` (per-minor) and `jsonlite` (flat, `Path: ..`).
- [ ] Re-index one slot (`amd64/alpine324`, R 4.5) and confirm the union index lists both `curl` (per-minor, `Path: 4.5`) and `jsonlite` (flat, no `Path`).
- [ ] Set `UNION_SLOTS = "amd64/alpine324"` and confirm in `reg.devxy.io/r/r-alpine:4.5-3.24` that `available.packages()` returns the union count and `"curl" %in% rownames(...)`.
- [ ] Add `arm64/alpine324`, then the remaining slots.