Every once in a while, namespacing support on crates.io comes up among many different use cases. This is an attempt to collect the information on this topic to reduce the conversations from falling into spinning in circles over the same points.
The focus for this topic is clarifying and discussing the background context for namespaces. The following threads are for exploring prior art and proposals though they assume understanding and agreement on this thread:
- Child Thread: Survey of organizational ownership designs for Cargo and Crates.io
- Child Thread: Survey of alternative identifier designs for Cargo and Crates.io
- Child Thread: Survey of registry namespace designs for Cargo and Crates.io
Debating which proposal Cargo and Crates.io should go with is off-topic for this thread. Please create your own thread.
Glossary
- Registry namespace: a private scope for naming packages on a registry and specifying them as a dependency, typically oriented around the owning organization
- Rust namespace: how you reference a package in Rust code (aka
externname) and the public modules underneath it - Public registry namespaces: anyone can publish to this namespace
- Private registry namespaces: restricted who can publish to this namespace
- Open namespaces: within a programming language, you can extend a namespace with any content. For example, in C++, you can add your own type to
std(despite the language spec saying not to) - Partially open namespaces: within a programming language, you are limited in how you can extend another namespace, typically limited to nesting other namespaces underneath.
- Closed namespaces: within a programming language, the the root namespace and any child namespaces / modules are not open to extension. For example, Rust namespaces are currently closed to extension.
Use cases
User experimentation:
- I would like my own sandbox to publish packages to for trying out ideas without distracting others, taking up finite resources, or worrying about naming
- This is particularly important for users who don't feel confident in what the norms are. For example, I (epage) was hesitant on my first publish and was thinking "can I really just do this?". For others, they might just decide not to publish, avoiding engaging with the ecosystem.
Organizations:
- We want users to be able to easily identify packages as coming from us so that their trust in us can extend to our packages
Reducing squatting, abandonware impact:
- I would like to use a name without consideration for what has been taken (and possibly abandoned)
- As a company, we're late to the Rust game and someone already provides their own API for our product under the product's name and we don't want to disrupt the community that has developed around it by asserting our trademark
Reducing typo squatting:
- I don't want to mistype a dependency and accidentally run a bitcoin miner or exfiltrate secrets
Forks:
- I would like to develop a fork without a pesty
2or-nextsuffix.- Ideally, it would be easy to replace the original with my fork without everyone having to patch it in (assuming Cargo had same-source patching)
References:
Related use cases
Renames:
- As an organization or a user, I would like the ability to change my name without breaking users
Ownership transfers:
- I'm no longer able to maintain this package and wish to hand it off to someone else without breaking users
- I'd like to promote my package from being for me to being generally useful without breaking users
- If I depend on a package that transfers owners, I need to vet the new owner
Assumptions
People will not arbitrarily jump on the same name but people will most likely want to reuse names with
- existing name is squatted
- existing package is abandonware
- intentional forks
- treating an organizational name as a Rust namespace (
project/deriveinstead ofproject::derive)
Open questions
- What do organizations want conveyed with ownership?
- Rust project has: Rust crate ownership policy
- Google has employees put their unofficial work (marked as such) under Google · GitHub
- Will organizations want to represent a specific policy? Or would they benefit from an additional way of specifying the polocy?
References:
Out of scope
Evaluating more fundamental registry design changes, like a form of federation.
Changing policies around forced transfer of ownership.
Requirements
Proposals should be backwards compatible with the current environment, including:
- Packages currently exist without namespaces
- New packages will likely need to be used without namespaces for consistency
- Emergent pattern of plugin or related packages being named
<otherpkg>-<plugin> - Package names impact
- crates.io urls
- docs.rs urls
- feature activations (
dep:pkgname,pkgname/feature) - PackageID Specs
- As parameters on the CLI which makes common shell control characters unlikely to be useful (e.g.
>)
The registry is stable and immutable, including:
- No deletions except in some very limited cases
- No renames
- Ownership transfers are an explicit operation by the current owners
A design should strive to be approachable, usable, and ergonomic, including:
- Users should interact with meaningful package names (not randomly generated strings or indexes)
- Users should be able to understand how to reference a package inside of Rust code
- There should be a good story if the way to reference two packages inside of Rust code collide
Fairness for participating in the feature
- The more generally aimed the feature is, the fewer barriers to use the feature should have (e.g. owning a domain)
Github-dependence by crates.io is not an inherent requirement and there is a desire to support other identity providers
We need to be mindful of the load put on the crates.io team to handle governance of policy
References:
- comment on RFC 2978
- comment on Internals: Namespacing on Crates.io
- comment on Internals: Pre-RFC: Packages as Namespaces
- comment on Internals: Pre-RFC: Packages as Namespaces
Developments related to these use cases
crates.io has started monitoring for typosquatting in 2023 (crates.io#7206), leveraging the work that went into TypoGard.
Crates.io policy for allowed content, deletion, and transfers has evolved over time, offering more flexibility
- RFC 3463: crates.io Policy Update (2023)
- RFC 3646: Change crates.io policy to not offer crate transfer mediation (2024)
- RFC 3660: crates.io: Crate Deletions (2024)
RFC 3452: Nested packages and RFC 3826: Procedural macros in same package as app are not approved but could help reduce the number of package names people use.
Partially-open Rust namespaces
RFC 3243: Partially-open Rust namespaces has been approved as of 2024 but not fully implemented and has some overlap in use cases.
Partially-open Rust namespaces means that you can have multiple packages that contribute to the same namespace used to access them in Rust. Unlike C++ with its fully-open namespaces, arbitrary items may not be injected, only other namespaces.
To ensure maintainer's control over their API, crates.io will restrict publishing to a namespace to those who have publish rights to the root package. The owners are allowed to delegate publish permissions for child packages to other people.
Examples:
| existing name | potential name | notes |
|---|---|---|
| clap | clap | |
| clap_derive | clap::derive | |
| clap_complete | clap::complete | |
| clap_mangen | clap::man | |
| clap_lex | clap_lex | first-party but a private dependency of clap |
| clap-cargo | clap-cargo | third-party though an extension of clap's API |
This was originally called "Packages as (optional) namespaces" but the name was not updated as the RFC evolved and is unclear in its intent; many people mistake this for organizational registry namespaces.
Future possibilities:
- Relaxing the orphan rules within a namespace (comment on Internals: Pre-RFC: Packages as Namespaces)
Past discussions
- Internals: Crates.io package policies (2014)
- Users: Cargo problems - namespacing (2015)
- crates.io#624 (2017)
- Internals: Crates.io squatting (2018)
- Internals: Namespacing on Crates.io (2018)
- Internals: Pre-RFC: Packages as Namespaces (2018)
- Internals: Pre-RFC Domains as namespaces (2018)
- Internals: Pre-RFC: unique crate names (2019)
- Internals: Scoped packages (like in npm)? (2019)
- Internals: Pre-RFC: Formal squatting policy on crates.io (2019)
- Internals: Pre-RFC Cratespaces (crates as namespace, take 2… or 3?) (2019)
- Internals: Pre-RFC: Author Attached Crates-io Names (2020)
- Internals: Pre-RFC: User namespaces on crates.io (2020)
- Internals: Blog Post: No Namespaces in Rust is a Feature (2020)
- Internals: Pre-RFC: (hyper)minimalist namespaces on crates.io (2020)
- crates.io#2750 (2020)
- Internals: Pre-RFC: Packages as Optional Namespaces (2020)
- RFC 2978: Proposal for user namespaces on crates.io (2020) (rendered)
- blog: Why Namespacing Matters in Public Open Source Repositories (2021)
- RFC 3243: Packages as (optional) namespaces (2022)
- RFC 3384: uri crates (2023) (rendered)
- Zulip: crate namespacing (2023)
- Internals: Crates.io “first-come, first-served” for plain crate names - why and how should it be changed? (2023)
- PackagingCon: What's in a name(space)? – Adam Harvey (2023)
- Internals: Organizations in crates.io (2023)
- blog: A namespace system, if you can keep it (2024)
- Internals: Verified organization on Crates.io (2024)
- blog: Package Management Namespaces (2026)