| 1 |
# Seeded font bases |
| 2 |
|
| 3 |
The image cuts its two house faces from pinned upstream bases (`quasi-type`, |
| 4 |
wiki `typography-standard`). The pins name files on raw.githubusercontent.com, |
| 5 |
which rate-limits by IP, and a 429 there fails the whole build an hour in, |
| 6 |
behind every expensive layer. Alloy's only install path is building the image |
| 7 |
yourself, so a fetch that cannot run is an install that cannot run. |
| 8 |
|
| 9 |
Anything dropped in this directory is copied into the `quasi-type` checkout's |
| 10 |
own `bases/cache/` before the cut runs, which is the directory the tool reads |
| 11 |
before it fetches anything. This `README.md` is skipped, and is what keeps the |
| 12 |
directory in git. |
| 13 |
|
| 14 |
## What the seed covers |
| 15 |
|
| 16 |
The two cuts the image runs, and nothing else. A build makes three requests to |
| 17 |
that host: these two, and a third from shop's own build script, which cuts the |
| 18 |
terminal's bundled face while `cargo install shop` runs. This directory |
| 19 |
does not cover that third one: shop's build script passes its own `OUT_DIR` as |
| 20 |
the cache directory, so there is no path for the image build to point at a |
| 21 |
carried copy. Covering it with a seed needs a change in shop (read the cache |
| 22 |
directory and the offline flag from the environment). |
| 23 |
|
| 24 |
What covers all three without that change is the mirror. `QUASI_TYPE_MIRROR`, |
| 25 |
set in the Containerfile to `https://makenot.work/static/bases`, is read inside |
| 26 |
`quasi-type` itself, so it reaches the fetch this directory cannot. It is a |
| 27 |
second source and not a carried copy: files are addressed by the sha256 the pin |
| 28 |
already carries and verified against it, upstream stays the fallback, and |
| 29 |
`sealed` still means the two cuts. A warm cargo target directory is what covers |
| 30 |
the terminal's fetch on a host that has built once. |
| 31 |
|
| 32 |
The rest of the build is not offline either, in any mode: it clones two |
| 33 |
repositories, resolves crates.io, and installs packages. |
| 34 |
|
| 35 |
## The four files |
| 36 |
|
| 37 |
Named exactly as `quasi-type` caches them: |
| 38 |
|
| 39 |
atkinson-mono-2.001-AtkinsonHyperlegibleMono%5Bwght%5D.ttf |
| 40 |
atkinson-mono-2.001-LICENSE.txt |
| 41 |
atkinson-next-2.001-AtkinsonHyperlegibleNext%5Bwght%5D.ttf |
| 42 |
atkinson-next-2.001-LICENSE.txt |
| 43 |
|
| 44 |
Copy them from a warm checkout, `~/Code/Libraries/quasi-type/bases/cache/`, or |
| 45 |
from any machine that has built the image once. Do not commit them: a font in a |
| 46 |
repo is a second source of truth that nothing rebuilds, which is the same |
| 47 |
reason the built faces are not committed either. `.gitignore` here says so. |
| 48 |
|
| 49 |
The list above is what the pins name today. The build does not read it: it |
| 50 |
derives the names from the pinned checkout's own `bases/pins.toml`, so a |
| 51 |
`QUASI_TYPE_REV` bump that moves to a new base version asks for the new names |
| 52 |
and this list is what goes stale. |
| 53 |
|
| 54 |
Seeding cannot forge a base. Every cached file is checked against the pin's |
| 55 |
sha256 exactly as a downloaded one is, so a wrong or tampered copy fails the |
| 56 |
cut rather than shipping. |
| 57 |
|
| 58 |
## Using it |
| 59 |
|
| 60 |
build/build-iso.sh --build-arg QUASI_BASES=sealed |
| 61 |
|
| 62 |
`sealed` passes `--offline` to the cut, so the cut may not reach the network. If |
| 63 |
the seed is short of a file the pins name, the build says which files before the |
| 64 |
tool is compiled, rather than at the cut. Use it on a build host with a |
| 65 |
warm cache. The default, `fetch`, uses whatever is seeded and downloads the |
| 66 |
rest, which is what a stranger with an empty directory gets. |
| 67 |
|
| 68 |
Keeping the bases outside the repo is possible with |
| 69 |
|
| 70 |
podman build -v ~/Code/Libraries/quasi-type/bases/cache:/base-cache:ro . |
| 71 |
|
| 72 |
The mount shadows this directory for the length of the build. Note what that |
| 73 |
costs: `build/build-iso.sh` and `build/build-image.sh` forward `--build-arg` and |
| 74 |
nothing else, so this route means driving `podman build` yourself, and a build |
| 75 |
started that way carries no build stamp and reports its version as |
| 76 |
`0.1 (Fedora 43)` (docs/IMAGE.md). Copying the files in here is the route that |
| 77 |
works with the scripts. |
| 78 |
|
| 79 |
## What none of this is |
| 80 |
|
| 81 |
A fix. It is a carried copy of two files and it goes stale the first time |
| 82 |
`QUASI_TYPE_REV` moves. The durable answer is the mirror above: the same files |
| 83 |
on infrastructure we own, addressed by the same sha256, so an unseeded build has |
| 84 |
somewhere to reach that is not somebody else's rate limiter, and reached from |
| 85 |
inside `quasi-type` so it covers shop's fetch too. |
| 86 |
|
| 87 |
What the seed buys on top of the mirror is `sealed`: a cut that reaches no |
| 88 |
network at all, which is the only way to prove the two faces came from the bytes |
| 89 |
the pins name and nothing else. |
| 90 |
|