Skip to content

Registry Conventions

Reference for every ecosystem pkgprobe scans: what config files exist at each precedence level, what syntax declares a registry URL or credentials, and what pkgprobe currently parses.

This document is the spec for implementing new languages/<lang>/registry.rs modules and for verifying completeness of the existing ones.


Every ecosystem follows roughly the same four-level hierarchy, highest precedence first:

LevelDescriptionTypical location
EnvironmentEnv vars and CLI flags at runtime$PIP_INDEX_URL, $CARGO_REGISTRIES_X_TOKEN
ProjectConfig file adjacent to the manifest/lockfile.npmrc, auth.json, .cargo/config.toml
UserPer-user config in the home directory~/.npmrc, ~/.m2/settings.xml, ~/.pypirc
MachineSystem-wide config (rare)/etc/pip/pip.conf, /etc/NuGet/NuGet.Config

pkgprobe reads project and user levels for all implemented ecosystems. Environment-level detection is implemented for Node, Python, and Rust.


Implementation: app/core/src/languages/node/registry.rsComplete

FileFields
.npmrcregistry=<url>, @scope:registry=<url>, _authToken, _password, _auth
.yarnrc.ymlnpmRegistryServer, npmAuthToken, npmScopes.<scope>.npmRegistryServer
FileFields
~/.npmrcSame as project .npmrc
~/.yarnrc.ymlSame as project .yarnrc.yml
~/.config/pnpm/rcSame as .npmrc
Variablepkgprobe
NPM_TOKENDetected: token hashed, auth_status set

Implementation: app/core/src/languages/php/registry.rsComplete

FileFields
composer.jsonrepositories[].type, repositories[].url
auth.jsonhttp-basic, bearer, github-oauth, gitlab-token
FileFields
~/.composer/auth.jsonSame as project auth.json

Implementation: app/core/src/languages/dotnet/registry.rsComplete

FileFields
NuGet.Config (walks up directory tree)<packageSources>, <packageSourceCredentials>
FileFields
~/.nuget/NuGet/NuGet.ConfigSame
FileFields
/etc/NuGet/NuGet.Config (macOS/Linux)Same

Implementation: app/core/src/languages/python/registry.rsComplete

LevelFileFields
Projectpyproject.toml[tool.pip] index-url, extra-index-url
User~/.pip/pip.conf[global] index-url, extra-index-url
User~/.pypirc[distutils] index-servers, [<server>] repository, username, password
Env$PIP_INDEX_URL, $PIP_EXTRA_INDEX_URLOverride index URLs
LevelFileFields
Projectpyproject.toml[[tool.poetry.source]] name, url
User~/Library/Caches/pypoetry/auth.tomlhttp-basic, http-bearer
LevelFileFields
Projectpyproject.toml[[tool.uv.index]] name, url
User~/.config/uv/uv.tomlSame
Env$UV_INDEX_URL, $UV_EXTRA_INDEX_URLOverride

Implementation: app/core/src/languages/rust_lang/registry.rsComplete

LevelFileFields
Project.cargo/config.toml[registries.<name>] index, token
User~/.cargo/config.tomlSame
User~/.cargo/credentials.toml[registries.<name>] token
Env$CARGO_REGISTRIES_<NAME>_TOKENPer-registry token

Implementation: app/core/src/languages/go/registry.rsComplete

LevelFileFields
Project/User~/.netrcmachine <host> login <user> password <token>
Env$GOPROXYModule proxy list
Env$GOPRIVATEModule prefixes that bypass proxy

Implementation: app/core/src/languages/ruby/registry.rsComplete

LevelFileFields
ProjectGemfilesource "<url>"
Project.bundle/configBUNDLE_GEMS__<HOST>
User~/.gemrc:sources: [...]
User~/.gem/credentials<url>: <api-key>

Implementation: app/core/src/languages/java/registry.rsComplete

LevelFileFields
Projectpom.xml<repositories>, <pluginRepositories>
User~/.m2/settings.xml<servers>, <profiles>
LevelFileFields
Projectgradle.propertiesartifactory_user, artifactory_password
User~/.gradle/gradle.propertiesSame

Implementation: app/core/src/languages/swift/registry.rsComplete

LevelFileFields
ProjectPackage.swift.package(url: "https://...", from: "1.0.0")
User~/.netrcCredentials matched by host

Implementation: app/core/src/languages/dart/registry.rsComplete

LevelFileFields
Projectpubspec.yamldependencies.<pkg>.hosted.url
User~/.pub-cache/pub-credentials.jsonhosted[].url, hosted[].token

Implementation: app/core/src/languages/cocoapods/registry.rsComplete

LevelFileFields
ProjectPodfilesource 'https://...'
User~/.cocoapods/repos/*/.git/config remote URLs
User~/.netrcCredentials by host

For each ecosystem, the registry parser should:

  1. Read project-level config adjacent to the manifest/lockfile.
  2. Read user-level config from the home directory.
  3. Read machine-level config from the system directory (when it exists).
  4. Hash all credential values via utils::hash_secret before storing.
  5. Emit one RegistryConfig per registry URL with level, config_file, username, password_hash, and valid (always true until policy runs).
  6. Be callable from attach_ecosystem_registries regardless of PM.
  7. Short-circuit quickly when the config file is absent.
  8. Include unit tests using tempfile fixtures.