Survey of organizational ownership and registry namespace designs for Cargo and Crates.io

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:

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 extern name) 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 2 or -next suffix.
    • 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/derive instead of project::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:

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 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:

Past discussions

10 Likes

I've added an open question about "What does ownership meant to convey?".

I've made explicit that changing the forced transfer of ownership is out of scope for this.

Cross-posting as this ties into the use cases:

2 Likes