docs: document content verification and typed errors
CI / Check (push) Successful in 2m34s
CI / Format (push) Successful in 17s
CI / Clippy (push) Successful in 2m38s
CI / Test (push) Successful in 3m7s

Describe what downloads are verified against (registry digests for
OCI, published checksums for distro CDNs) and the degradation policy;
document the ecr::Error variants and the Result alias for library
consumers.
This commit is contained in:
2026-10-04 21:21:04 +02:00
parent 593ce20f4f
commit 8f67b362b4
2 changed files with 41 additions and 2 deletions
+39
View File
@@ -20,6 +20,28 @@ spinners (indicatif) — is owned by `crates/ecr-cli`.
## Library API
### Errors (`ecr::error`)
Public functions return `Result<T, ecr::Error>` so consumers can match on
the failure modes that call for different handling. anyhow remains the
internal error type; semantic variants are raised at the sites that detect
the conditions, everything else converts to:
- `Error::Other` — any other failure, transparently wrapping the anyhow
context chain (`source()` walks it; `Display` shows the top message).
- `Error::UserNamespacesUnavailable` — unprivileged user namespaces are
disabled; `remediation` names the sysctl to set.
- `Error::BinfmtNotRegistered` — binfmt_misc missing for the target
architecture (foreign-arch namespace mode).
- `Error::ArchNotAvailable` — the registry serves no linux manifest for
the requested architecture; `available` lists what it does serve.
- `Error::MissingSubidRange` — `/etc/subuid` or `/etc/subgid` has no
usable entry for the user.
Errors raised inside the namespace child (mount setup, resolv.conf,
chroot exec) cross the process boundary as formatted chains and surface
as `Error::Other`.
### Rootfs lifecycle (`ecr::rootfs`)
- `RootfsCache::new(dir)` / `RootfsCache::default_dir()` — the image tarball
@@ -195,6 +217,23 @@ If architecture is not available in manifest list, error with available architec
Error: No manifest found for architecture 'riscv64'. Available: amd64, arm64, ppc64le, s390x
```
### Content Verification
Downloaded content is hashed (sha256 and sha512 in parallel) while
streaming, and verified before it enters the cache — a mismatch fails the
download and nothing partial is kept:
- OCI architecture manifests requested by digest are checked against that
digest (the layer digests read from them are trusted next).
- OCI layer blobs are checked against the digest the manifest names. A
digest algorithm other than sha256/sha512 cannot be checked: warn and
accept.
- Direct distro tarballs are checked against the checksum each distro
publishes next to them (Alpine: per-file `.sha256`; Ubuntu: `SHA256SUMS`
in the release directory). A missing or unfetchable checksum artifact
degrades to an unverified download with a warning, mirroring the
freshness-check policy; a checksum mismatch always fails.
### Layer Extraction
`extract::extract_tarball` handles plain rootfs tarballs and OCI layer