ferro-cargo-registry-server 0.0.1

Cargo Alternative Registry Protocol server-side primitives — sparse index, /config.json, publish/yank/owners API. Backed by ferro-blob-store. Extracted from the Ferro ecosystem.
Documentation

ferro-cargo-registry-server

License Rust 1.88+

Server-side primitives for the Cargo Alternative Registry Protocol, sparse-index variant. As far as we can tell, this is the first crate on crates.io that publishes the server half of this protocol; existing crates implement the client (cargo itself) or git-index internals.

⚠️ Alpha (v0.0.1). API will shift before v0.1.

Part of the Ferro ecosystem. Extracted from FerroRepo, a private Rust artifact repository.

What this crate does

  • config/config.json response (registry API host, alternate registries list)
  • index — sparse-index format: line-per-version JSON entries (IndexEntry, IndexDep), entry_from_manifest / parse_lines / render_lines
  • name — canonical crate name validation (lowercase ASCII, hyphens, length cap)
  • publish — binary publish-request parser (length-prefixed metadata JSON + tarball bytes) per spec §"Publish"
  • version — semver validation
  • owners — owners API request / response types
  • yank — yank/unyank response
  • handlers / router — Axum router for /config.json, /index/{*path}, /api/v1/crates/**. Mounts a BlobStore from ferro-blob-store.

What this crate does not do

  • Git index format — sparse only. cargo 1.68+ defaults to sparse, controllable per-registry via CARGO_REGISTRIES_*_PROTOCOL=sparse. Git-index support is on the roadmap behind a separate feature once the in-tree git primitives stabilise.
  • Authentication — handlers are open. Layer your auth in the Axum middleware stack above this router.
  • TUF v2 metadata — the spec's TUF metadata layer is a separate crate (Phase 3).
  • crates.io federation / mirroring — this is for alternative registries (private registries / mirrors / corp internal). The server here does not pull from upstream crates.io.

Quick start

use std::sync::Arc;
use axum::Router;
use ferro_blob_store::FsBlobStore;
use ferro_cargo_registry_server::{router, CargoState};

# async fn run() -> Result<(), Box<dyn std::error::Error>> {
let store = Arc::new(FsBlobStore::new("/var/lib/cargo-registry")?);
let state = CargoState::new(store, "https://my-registry.example.com");
let app: Router = router(state);
let listener = tokio::net::TcpListener::bind("0.0.0.0:8082").await?;
axum::serve(listener, app).await?;
# Ok(()) }

Client-side: point cargo at it via your ~/.cargo/config.toml:

[registries.my-registry]
index = "sparse+https://my-registry.example.com/index/"

Status

Aspect Status
API stability alpha (v0.0.x)
Sparse index working
Git index not yet
Authentication scaffold only — wire your own middleware
TUF metadata not in this crate (Phase 3, separate)
MSRV rustc 1.88

Used in production by

  • FerroRepo (private) — Rust artifact repository.

License

Apache-2.0. See LICENSE.