Registries
A registry is a complete endpoint with its own packages, policy, and access rules. An organization can have many: one per team, one per product, a public storefront, a filtered mirror of crates.io, a bucket of release artifacts. Each is independent.
Three kinds
Section titled “Three kinds”The kind is chosen at creation and cannot be changed afterwards.
- Publish registry: a cargo registry whose crates arrive through
cargo publish. This is your private (or public) registry for first-party code. - Mirror registry: a cargo registry whose crates arrive from an upstream registry that Haven pulls through on demand. You never publish into a mirror. See Mirrors.
- Static file registry: plain versioned files uploaded over HTTP, for the artifacts that are not crates. See Publishing files and Consuming files.
All kinds share the same surfaces: the same policy engine, the same package pages and held view, the same tokens and audit log. The two cargo kinds additionally share the cargo registry protocol and rustdoc hosting.
Visibility
Section titled “Visibility”- Private (the default): readable only by your organization’s members and tokens, plus identities you explicitly grant.
- Public: any signed-in user can browse the registry and read promoted versions with a public-read token. Held versions stay invisible to the public; the gate applies to strangers exactly as it does to you.
Visibility can be flipped later from the registry settings. Making a private registry public exposes its promoted contents to everyone, so the UI asks for confirmation.
A public registry is also listed in the server’s public directory by default. Unlisting it (at creation or from settings) removes only the directory card: anyone who knows the registry’s name still reaches it, with exactly the read access public grants. Unlisting hides, it does not protect — use private visibility or grants for that.
Static file registries have one more setting there: version archives, which bundle each published version’s files into one downloadable archive.
Owners
Section titled “Owners”A registry has one or more owners. Owners change settings and policy, manage the allowlist of a mirror, approve promotions, vouch for publishers, and manage grants. Promotion approvals count distinct owner identities, so a registry with a promotion threshold above one needs at least that many owners to waive a hold; see Policy overview.
The registry’s owner list is registry wide: every subject on it can publish every crate in the registry, and introduce new crate names.
Package owners
Section titled “Package owners”A package can also carry owners of its own, scoped to that one package. This works the same on crate registries and on static file registries. A package owner can:
- publish new versions of the package (on files registries: upload and publish), and request its docs rebuilds — but never introduce a new package name, which stays registry-owner-gated,
- yank and unyank its versions (and, on files registries, set a draft’s license and request version archive builds),
- manage its per-package surfaces: grants, and on crates the publisher vouches, state trusts, and hold acceptances.
Writes always take an identity of the owning organization (an org token, a member’s session, or a CI identity via trusted publishing); a package owner from outside the organization gets the read side of their package, like a grant holder does.
An issuer#subject CI identity listed as a package owner can
exchange its OIDC id_token for a short-lived token through
trusted publishing,
bounded by this one package. Its grant carries a capability set
(publish alone is the form’s default; omitting the list via the API
grants all four) and re-adding the identity with an explicit list
edits the set in place. Capabilities attach to CI identities only: a
user’s or token’s power comes from its own credential.
A package owner touches nothing registry wide: no settings, no policy, no promotions or blocks (those override the registry’s compliance policy, which stays the registry owner’s lever). The package-owner list itself is managed by registry owners and org admins in the package’s Settings tab, never by package owners, so the role cannot widen itself. An empty list is the default and means what it always meant: registry owners only.
One naming subtlety: on crate registries foo-bar and foo_bar are
the same crate, and ownership follows that identity. On file
registries they are two distinct packages, owned separately.
This is the right tool for a shared registry where teams own their own packages: a subject trusted on one package can release it without being able to touch a neighboring team’s. The Settings tab on the registry is registry wide; the Settings tab on a package covers that package alone.
Create a package before its first publish
Section titled “Create a package before its first publish”A package normally comes into existence with its first publish, which
only a registry owner can perform for a new name. When the access
setup should come first, create the package ahead of time: the
registry’s Crates (or Packages) tab has a create form for owners, and
the API is PUT /api/v1/registries/{registry}/packages/{name}. The
same rule applies as for introducing a name via publish: registry
owners with publish rights only.
The created package has no versions. It is invisible to cargo and to readers — the index, downloads, search, and listings serve nothing, and only owners see its page — but owners and grants can be set on it immediately, so a package owner staged this way can perform the first publish themselves, and a grant holder can resolve the package the moment a version lands. The first publish fills in the description and versions as usual.
Creation is idempotent: re-creating an existing package changes
nothing. On crate registries a spelling that collides with an
existing crate’s identity (foo-bar vs foo_bar) is refused as a
conflict; on file registries the spellings are distinct packages,
matching the ownership rule above. A created-but-unpublished package
counts as registry content: a registry holding one refuses deletion
like any other non-empty registry.
Grants
Section titled “Grants”Grants share specific packages with identities outside the registry’s organization, without making anything public. A grant names:
- a subject: the identity being granted read access, and
- a version requirement: a semver range such as
^1.4limiting which versions the subject can resolve and download (*for all of them).
Grants are per package, on crates and on static files alike. They are the right tool for selling or licensing a package to a customer: the customer sees exactly the packages and version ranges you granted, nothing else in the registry.
Manage them on the package’s Settings tab, under Access. One
subject can hold several ranges at once, which is how a customer who
bought ^1 and later ^2 ends up reading both.
Withdrawing takes effect on the very next request, with no token to rotate on either side: withdraw one range, or withdraw every range a subject holds on the package in one step. Both directions are recorded in the audit log, naming the exact requirement that was granted or taken back.
Registry owners manage grants everywhere in the registry; package owners manage them on their own package.