Files
nora/COMPAT.md
DevITWay | Pavel Volkov e4168b7ee4 chore: add workspace clippy lints, release profiles, COMPAT.md, diff-registry.sh (#119)
- Workspace clippy lints: or_fun_call, redundant_clone, collection_is_never_read,
  naive_bytecount, stable_sort_primitive, large_types_passed_by_value, assigning_clones
- Fix or_fun_call in cargo_registry.rs (unwrap_or -> unwrap_or_else)
- Release profiles: release (thin LTO) + release-official (full LTO, codegen-units=1)
- COMPAT.md: protocol compatibility matrix for all 7 registries (40 endpoints)
- scripts/diff-registry.sh: differential smoke tests (Docker/npm/Cargo/PyPI/Go/Raw)
2026-04-09 12:38:59 +03:00

6.3 KiB

NORA Registry Protocol Compatibility

This document describes which parts of each registry protocol are implemented in NORA.

Legend: Full = complete implementation, Partial = basic support with limitations, Stub = placeholder, — = not implemented

Docker (OCI Distribution Spec 1.1)

Endpoint Method Status Notes
/v2/ GET Full API version check
/v2/_catalog GET Full List all repositories
/v2/{name}/tags/list GET Full List image tags
/v2/{name}/manifests/{ref} GET Full By tag or digest
/v2/{name}/manifests/{ref} HEAD Full Check manifest exists
/v2/{name}/manifests/{ref} PUT Full Push manifest
/v2/{name}/manifests/{ref} DELETE Full Delete manifest
/v2/{name}/blobs/{digest} GET Full Download layer/config
/v2/{name}/blobs/{digest} HEAD Full Check blob exists
/v2/{name}/blobs/{digest} DELETE Full Delete blob
/v2/{name}/blobs/uploads/ POST Full Start chunked upload
/v2/{name}/blobs/uploads/{uuid} PATCH Full Upload chunk
/v2/{name}/blobs/uploads/{uuid} PUT Full Complete upload
Namespaced {ns}/{name} * Full Two-level paths
Deep paths a/b/c/name * Max 2-level (org/image)
Token auth (Bearer) Full WWW-Authenticate challenge
Cross-repo blob mount POST Not implemented
Referrers API GET OCI 1.1 referrers

Known Limitations

  • Max 2-level image path: org/image:tag works, org/sub/path/image:tag returns 404
  • Large monolithic blob PUT (>~500MB) may fail even with high body limit
  • No cross-repository blob mounting

npm

Feature Status Notes
Package metadata (GET) Full JSON with all versions
Scoped packages @scope/name Full URL-encoded path
Tarball download Full SHA256 verified
Tarball URL rewriting Full Points to NORA, not upstream
Publish (npm publish) Full Immutable versions
Unpublish Not implemented
Dist-tags (latest, next) Partial Read from metadata, no explicit management
Search (/-/v1/search) Not implemented
Audit (/-/npm/v1/security/advisories) Not implemented
Upstream proxy Full Configurable TTL

Maven

Feature Status Notes
Artifact download (GET) Full JAR, POM, checksums
Artifact upload (PUT) Full Any file type
GroupId path layout Full Dots → slashes
SHA1/MD5 checksums Full Stored alongside artifacts
maven-metadata.xml Partial Stored as-is, no auto-generation
SNAPSHOT versions No SNAPSHOT resolution
Multi-proxy fallback Full Tries proxies in order
Content-Type by extension Full .jar, .pom, .xml, .sha1, .md5

Known Limitations

  • maven-metadata.xml not auto-generated on publish (must be uploaded explicitly)
  • No SNAPSHOT version management (-SNAPSHOT → latest timestamp)

Cargo (Sparse Index, RFC 2789)

Feature Status Notes
config.json Full dl and api fields
Sparse index lookup Full Prefix rules (1/2/3/ab/cd)
Crate download Full .crate files by version
cargo publish Full Length-prefixed JSON + .crate
Dependency metadata Full req, package transforms
SHA256 verification Full On publish
Cache-Control headers Full immutable for downloads, max-age=300 for index
Yank/unyank Not implemented
Owner management Not implemented
Categories/keywords Partial Stored but not searchable

PyPI (PEP 503/691)

Feature Status Notes
Simple index (HTML) Full PEP 503
Simple index (JSON) Full PEP 691, via Accept header
Package versions page Full HTML + JSON
File download Full Wheel, sdist, egg
twine upload Full Multipart form-data
SHA256 hashes Full In metadata links
Case normalization Full My-Packagemy-package
Upstream proxy Full Configurable TTL
JSON API metadata Full application/vnd.pypi.simple.v1+json
Yanking Not implemented
Upload signatures (PGP) Not implemented

Go Module Proxy (GOPROXY)

Feature Status Notes
/@v/list Full List known versions
/@v/{version}.info Full Version metadata JSON
/@v/{version}.mod Full go.mod file
/@v/{version}.zip Full Module zip archive
/@latest Full Latest version info
Module path escaping Full !xX per spec
Immutability Full .info, .mod, .zip immutable after first write
Size limit for .zip Full Configurable
$GONOSUMDB / $GONOSUMCHECK Not relevant (client-side)
Upstream proxy Direct storage only

Raw File Storage

Feature Status Notes
Upload (PUT) Full Any file type
Download (GET) Full Content-Type by extension
Delete (DELETE) Full
Exists check (HEAD) Full Returns size + Content-Type
Max file size Full Configurable (default 1MB)
Directory listing Not implemented
Versioning Overwrite-only

Helm OCI

Helm charts are stored as OCI artifacts via the Docker registry endpoints. helm push and helm pull work through the standard /v2/ API.

Feature Status Notes
helm push (OCI) Full Via Docker PUT manifest/blob
helm pull (OCI) Full Via Docker GET manifest/blob
Helm repo index (index.yaml) Not implemented (OCI only)

Cross-Cutting Features

Feature Status Notes
Authentication (Bearer/Basic) Full Per-request token validation
Anonymous read Full NORA_AUTH_ANONYMOUS_READ=true
Rate limiting Full tower_governor, per-IP
Prometheus metrics Full /metrics endpoint
Health check Full /health
Swagger/OpenAPI Full /swagger-ui/
S3 backend Full AWS, MinIO, any S3-compatible
Local filesystem backend Full Default, content-addressable
Activity log Full Recent push/pull in dashboard
Backup/restore Full CLI commands
Mirror CLI Full nora mirror for npm/pip/cargo/maven/docker