The storage layer serves three ecosystems but was named for one. Rename its
vocabulary so a Cargo index file and a Simple API page are documents and a
`.crate` and a wheel are blobs.
`pnpr-storage` now exposes `read_hosted_document`, `open_hosted_blob`,
`reserve_hosted_blob`, `finalize_blob_slot` and their peers on both the
filesystem and the S3 backend, and a publish write conflict is
`RegistryError::DocumentWriteConflict`, logged as `document_write_conflict`.
`PackageName` keeps its name: it holds a package's name and never a version,
and a name is what a crate and a Python project have too. The npm surfaces
keep their own packument and tarball vocabulary, which is accurate there.
Separately, a name now rejects `?`, `#`, `%`, whitespace, and control
characters. A request path is percent-decoded before a handler parses a name
from it, and a name is interpolated into the upstream URL, so `GET /foo%23bar`
was authorized and cached as `foo#bar` while fetching `foo` — a package rule
that named `foo` never ran.
The journal manifest's `packument_file` and `tarballs` aliases had no
coverage, so a sealed entry that spells its keys that way now has a recovery
test.
Related to pnpm/pnpm#14599.