Skip to content

Channel layout

The estate's channel is served from https://artifacts.phpboyscout.uk: the signed index at the root, and every artefact-version beneath it. This page documents what the package expects, so a mirror can reproduce it.

The signed index

https://artifacts.phpboyscout.uk/index.txt
https://artifacts.phpboyscout.uk/index.txt.sig

The index URL is compiled in as artifacts.DefaultIndexURL; its signature is the same URL with .sig appended. Override it with artifacts.WithIndexURL(url) to point a client at a mirror of the whole channel, or at a test server.

The index is the only location the package carries. It names, for each approved artefact-version, the digest of its manifest and up to eight download locations:

phpboyscout-artifact-index-v1
namespace: phpboyscout
generation: <n>
issued: <RFC 3339>
expires: <RFC 3339>
complete: true
approved onnxruntime 1.28.0 <manifest sha256> https://artifacts.phpboyscout.uk

Every location must be https. There is no compiled-in download location and no option to set one: a location that could only be corrected by a release would be a second answer to a question the signed index already answers.

Asset path

<location>/<artefact>/<version>/<file>

<location> is a base URL from the index, with any trailing slash trimmed. The other three components are percent-escaped. <version> is the artefact's own upstream version (1.28.0 for ONNX Runtime 1.28.0), never a version of the channel, which does not have one.

Example:

https://artifacts.phpboyscout.uk/onnxruntime/1.28.0/onnxruntime-linux-x64-1.28.0.tgz

When an entry names more than one location, they are tried in order and the first that answers is used. Every file is checked against the signed manifest before it is used, so a broken or hostile location can deny service but cannot substitute anything.

The channel is public: these paths resolve without a token.

Files in every artefact-version

File Constant Purpose
checksums.txt artifacts.ManifestFile digests of every asset in this version
checksums.txt.sig artifacts.SignatureFile detached OpenPGP signature over checksums.txt

The channel also publishes the signing key as release.asc. This package never fetches it. Trust comes from the key embedded in the calling binary and the key served over WKD. A key downloaded from the same place as the signature it validates proves nothing, which is why there is no constant for it.

Manifest format

A signed envelope: a magic line, three headers in a fixed order, then one line per asset giving its SHA-256, its length in bytes and its filename, separated by single spaces.

phpboyscout-artifact-manifest-v1
namespace: phpboyscout
name: onnxruntime
version: 1.28.0
e15ff8b5d85afe6c144d97c6fd432254bf76a219daaf17658087d6ecb3e8f0bb 8116278 onnxruntime-linux-aarch64-1.28.0.tgz
a3e1b79d7bb1bf09696ce675f49e4064e6c81f6202b8225624fff0e93f8d6407 9125960 onnxruntime-linux-x64-1.28.0.tgz

Parsing is strict throughout, because every byte is signed data. The file is LF-only and ends with a newline. The digest is exactly 64 lowercase hex characters; the length is a non-negative decimal with no leading zero, at most 1 GiB; a filename may appear once. A header out of order, an unknown header, a blank line or any other malformed line rejects the whole manifest with ErrMalformedManifest, because a parser that skipped bad lines would silently accept a manifest with entries removed. A manifest listing no files is likewise rejected.

The headers are checked against the request: a manifest signed for a different namespace, artefact or version is ErrIdentityMismatch, however valid its signature.

The manifest is authoritative for what a version contains. A file absent from it is ErrNotFound regardless of how the URL responds.

Signature format

A detached, ASCII-armored OpenPGP signature over the exact bytes of checksums.txt. This is what gtb's signing backend emits.

The signing key for the estate channel:

Identity artifacts-release@phpboyscout.uk (trust.ReleaseEmail)
Fingerprint 544E64F3B87561D56739333634A711C4B9EAA99A
WKD openpgpkey.phpboyscout.uk

go/signing enforces a minimum key strength: Ed25519, or RSA at 3072 bits or above. It also requires the key returned by WKD to carry a UID matching the address requested, because a key published under a different identity is a different key.

Verification order

  1. index.txt and index.txt.sig are fetched and the signature verified, then the index is parsed and checked for namespace, expiry and generation. The artefact-version must be listed as approved.
  2. checksums.txt is fetched, and its SHA-256 must equal the digest the index names for it.
  3. checksums.txt.sig is fetched and verified against the trust anchors, before the manifest is parsed, because the parser is the first thing an attacker reaches.
  4. The manifest is parsed and its headers matched against the request.
  5. A cache entry whose digest matches the manifest is returned here.
  6. Otherwise the requested asset is fetched, and its length and SHA-256 are checked against the manifest entry as it streams.
  7. The verified bytes are written to the cache and the path returned.

A cache hit saves the download, not the checks: steps 1 to 4 run on every resolution, so a withdrawal reaches a consumer holding a warm cache.