{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreiacs4nhzatyadxp3nvvvacb657eugggv6w2nknyg7j2qk2cuzdz2e",
    "uri": "at://did:plc:ivbknywyskln22er3nkssdhl/app.bsky.feed.post/3mkcfibhbepd2"
  },
  "path": "/t/pre-rfc-dns-domains-as-package-namespaces/24202#post_1",
  "publishedAt": "2026-04-25T05:23:57.000Z",
  "site": "https://internals.rust-lang.org",
  "tags": [
    "GitHub - jmillikin/upstream__cargo at domain-namespaces-raw-llm-output · GitHub",
    "crates.io",
    "GitHub - jmillikin/upstream__crates.io at domain-namespaces-raw-llm-output · GitHub"
  ],
  "textContent": "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.\n\nThe 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.\n\nCargo branch (raw LLM output): GitHub - jmillikin/upstream__cargo at domain-namespaces-raw-llm-output · GitHub\n\ncrates.io branch (raw LLM output): GitHub - jmillikin/upstream__crates.io at domain-namespaces-raw-llm-output · GitHub\n\nI 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.\n\n  * 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`?\").\n  * But also opinions may currently be different than they were a year or two ago.\n\n\n\nRough outline of the design:\n\n  * 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`.\n  * This is designed to address name squatting (\"I want to publish my `wasm` crate but there's already an empty crate named `wasm`\").\n    * 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.\n    * 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.\n  * Cargo strips off the namespace prefix before passing the crate name to `rustc`, so `example.com/base64` is `base64` to the compiler.\n    * 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.\n  * 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.\n    * The URL of the file is `https://{namespace}/.well-known/rust-lang.org/package-namespace.json`.\n    * This file contains a list of keys that identify who is allowed to create packages in that namespace.\n    * 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.\n  * 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.\n    * Specifically they can put something on `{username}.github.io`.\n  * Domain verification only happens when a crate is first created. Subsequent uploads use the existing permissions (either a crate owner, or a TrustedPub key).\n    * 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.\n  * Whenever the crate name needs to be encoded somewhere that a `/` is semantically meaningful (URLs, file paths) it gets encoded to `%2F`.\n    * This includes the paths in source archives.\n    * Yes this means the crates.io URLs for namespaced crates are kinda ugly. I think this doesn't matter.\n\n\n\nScreenshots:\n\nExample `package-namespace.json`:\n\n\n    {\n    \t\"authorized_keys\": [\n    \t\t\"sha256-kdRCstHTc6I8OxwyuW+QC8gFkn4tT8/g4a0M//cvCXk=\"\n    \t]\n    }\n\n\nExample `Cargo.toml`:\n\n\n    cargo-features = [\"domain-namespaces\"]\n\n    [package]\n    name = \"example.com/hello\"\n    version = \"0.1.0\"\n    edition = \"2024\"\n\n    description = \"Hello, world!\"\n    license = \"0BSD\"\n    repository = \"https://github.com/example/hello\"\n    homepage = \"https://example.com/hello\"\n    documentation = \"https://example.com/hello-docs\"\n",
  "title": "[Pre-RFC] DNS domains as package namespaces"
}