Generic artifacts
Raw files that belong to no package ecosystem: firmware images, datasets, build outputs, signed installers, model weights.
These are the usual reason a team runs a second registry beside this one. The reason was rarely that the second registry was better — it was that there was nowhere here to put a file that is not an npm tarball or a Maven jar.
Enable with generic in ENABLED_ECOSYSTEMS.
Endpoints
PUT /generic/{scope}/{name}/{version}/{file}
GET /generic/{scope}/{name}/{version}/{file}
GET /generic/{scope}/{name}/{version} files in a version, with digests
GET /generic/{scope}/{name} versions, newest first
# Publish
curl -X PUT --data-binary @firmware.bin \
-H "Authorization: Bearer $PACKR_TOKEN" \
https://api.packr.blueforge.studio/generic/acme/router-fw/2.4.1/firmware.bin
# List what a version contains
curl https://api.packr.blueforge.studio/generic/acme/router-fw/2.4.1
{
"scope": "acme",
"name": "router-fw",
"version": "2.4.1",
"files": [
{ "file": "firmware.bin", "sha256": "…" },
{ "file": "manifest.json", "sha256": "…" }
]
}
It is not a separate registry
This is a naming convention over the same core the package adapters use, which means a firmware image is governed exactly like a crate:
- Publish authorization and per-scope token restrictions apply.
- Visibility applies. A private package's files, listings and versions all return 403 to a caller who may not read it.
- Yank and deprecate apply. A yanked version drops out of the version listing while staying downloadable by exact name.
- Provenance is recorded on publish, like any other artifact.
- The credential scan applies. Nothing about being a raw file makes it a safer place to leave an access key, and a publish carrying one is refused.
Several files per version
Firmware ships as an image plus a manifest plus release notes. Splitting those across versions would misrepresent them as separate releases, so a version holds as many files as you publish into it.
The first file published becomes the version's authoritative blob; the rest are stored beside it. That is why a version is created by its first upload rather than declared up front.
Rules
- Artifacts are immutable. Republishing a filename is a 409. A build that pinned it by digest keeps resolving to the same bytes.
- Downloads are opaque. Always
application/octet-stream, withnosniffand an attachment disposition. The registry does not know what your bytes are and will not guess — sniffing a content type here would let a publisher serve arbitrary HTML from the registry's own origin. - Filenames are validated, not sanitised. A filename becomes part of a storage key. Anything that could climb out of the package's own prefix is refused rather than quietly rewritten, because rewriting changes what you asked for without telling you.
.packr/is reserved for registry metadata such as provenance and SBOMs. A file published under that prefix would be invisible in its own listing, so it is refused instead.MAX_GENERIC_SIZEdefaults to 200 MB, deliberately larger than any package ecosystem's ceiling.