[Pre-RFC] DNS domains as package namespaces

Package namespacing is one of those perennial topics that seems to attract designs but not much implementation. I took my own preferred approach (DNS domains) and got some robots to implement a proof-of-concept.

The code isn't great (and the robots hallucinate various minor details) but overall it's enough to get a feel for how DNS-based namespacing would work.

Cargo branch (raw LLM output): GitHub - jmillikin/upstream__cargo at domain-namespaces-raw-llm-output · GitHub

crates.io branch (raw LLM output): GitHub - jmillikin/upstream__crates.io at domain-namespaces-raw-llm-output · GitHub

I want to get a feeling for how the Cargo / crates.io team feel about the overall concept before I put any effort into cleaning up the proof-of-concept code.

  • My impression from past discussions is that those teams have historically objected to namespaces for aesthetic reasons ("why name your crate boring.com/base64 when you could just name it base64inator9000?").
  • But also opinions may currently be different than they were a year or two ago.

Rough outline of the design:

  • Package names are allowed (not required) to start with a {namespace}/ prefix, where the namespace is a DNS-style dotted name like example.com or jdoe.github.io.
  • This is designed to address name squatting ("I want to publish my wasm crate but there's already an empty crate named wasm").
    • Control over subsets of the global namespace ("My project is named cool so I want to prevent someone else from publishing a crate named cool-wasm) is out of scope.
    • You can use your own domain as a namespace if you care about this, but it doesn't prevent someone else from registering packages with a given prefix either in the global namespace or their own domain.
  • Cargo strips off the namespace prefix before passing the crate name to rustc, so example.com/base64 is base64 to the compiler.
    • If you want to depend on base64 and example.com/base64 in the same crate then you'll need to use existing Cargo mechanisms to rename one in the local compilation context.
  • When a crate is first created on crates.io, if it has a namespace then that namespace will be interpreted as a DNS name and verified by fetching a list of authorized user keys.
    • The URL of the file is https://{namespace}/.well-known/rust-lang.org/package-namespace.json.
    • This file contains a list of keys that identify who is allowed to create packages in that namespace.
    • The key format is determined by the registry. In the case of crates.io it's computed as approximately sha256((namespace, user_id)) -- see gen-auth-key.py for details. Note that user_id part of existing API responses, so no part of this key is secret.
  • The use of https://{namespace}/.well-known/ as opposed to DNS TXT records (etc) is to enable users to publish namespaced crates without having to first pay for a domain.
    • Specifically they can put something on {username}.github.io.
  • Domain verification only happens when a crate is first created. Subsequent uploads use the existing permissions (either a crate owner, or a TrustedPub key).
    • This means that if control of a domain is lost then the new owner can't use that access to publish new versions of existing crates.
  • Whenever the crate name needs to be encoded somewhere that a / is semantically meaningful (URLs, file paths) it gets encoded to %2F.
    • This includes the paths in source archives.
    • Yes this means the crates.io URLs for namespaced crates are kinda ugly. I think this doesn't matter.

Screenshots:

Example package-namespace.json:

{
	"authorized_keys": [
		"sha256-kdRCstHTc6I8OxwyuW+QC8gFkn4tT8/g4a0M//cvCXk="
	]
}

Example Cargo.toml:

cargo-features = ["domain-namespaces"]

[package]
name = "example.com/hello"
version = "0.1.0"
edition = "2024"

description = "Hello, world!"
license = "0BSD"
repository = "https://github.com/example/hello"
homepage = "https://example.com/hello"
documentation = "https://example.com/hello-docs"

Please review Survey of organizational ownership and registry namespace designs for Cargo and Crates.io and the sub-threads

I've read those thoroughly, both when they were originally posted and before posting this thread. As you may remember, the thread I posted in 2020 asking for the same feature (Pre-RFC: User namespaces on crates.io) was one of the "past discussions" linked in your survey.

Is there anything in particular you'd like to draw my attention to?

If so, it would be good to acknowledge the prior discussions and highlight what is different. Besides how the namespaces are verified, this looked like someone just retreading existing ground, including vague references to requirements when they are clearly written out.

I think it would be premature to write up the "alternatives considered" section of the RFC before knowing whether the Cargo and crates.io teams are OK with the concept of namespaces.

After all, the entire thread would just end if someone from one of those teams posts "no we still don't want namespaces, ask again in five years".

The bullet points in the first post are faster to read than lengthy prose, and certainly faster to write.

If the relevant teams are interested in proceeding to a full RFC then don't worry, you'll have plenty of reading material. My Obsidian tag on this topic (collecting known namespacing designs + considering their applicability to Rust) runs to several tens of thousands of lines.

I think there is a misunderstanding. We are not blocked on an implementation. We are not short on ideas. What is needed is someone to have an idea and explain how it solves the problems that have previously uncovered or making a convincing case why we should flex on some of them.

I'm not looking for an RFC or full alternatives section. Long prose documents can be easy to lose people. What I would find helpful to see this worth bringing to other's attention is an analysis of this against the requirements and a contrast with the DNS case and its analysis.

From my own work on writing all of that up, I have strong doubts about DNS namespacing. I'm personally split between a simple identifier namespace or organizational tagging.

Augmenting my analysis with this or doing your own would also be a great help for this effort.