Skip to content
Unverified: This page has not yet been anchored to automated code tests.

Publishing crates to crates.io

Vox uses cargo-hakari for workspace build optimization. Publishing external crates requires a few extra steps to satisfy crates.io closure requirements.

  1. Mark the crate publishable in docs/src/architecture/layers.toml:

    my-crate = { layer = 1, publishable = true }
  2. Run the publishability gate:

    Terminal window
    cargo run -p vox-arch-check

    Rule 18 must pass — no publish = false deps in the workspace-crate closure. If it fires, either mark each flagged dep publishable (and add it to this pipeline) or remove it from the crate’s dependencies.

  3. Remove workspace-hack from the crate’s Cargo.toml:

    # Remove this line from crates intended for external publishing:
    # workspace-hack = { workspace = true }

    workspace-hack is a build-optimization-only dep managed by hakari. It has no code — only feature flags. cargo publish cannot resolve it (our repo version is 0.6.0; no matching version on crates.io). Removing it has no effect on crate behaviour.

  4. Add a version to each workspace path-dep that is in this crate’s closure (in the root Cargo.toml [workspace.dependencies] section):

    my-dep = { path = "crates/my-dep", version = "0.6.0" }
  5. Verify name availability:

    Terminal window
    cargo search my-crate --limit 5

    crates.io has no namespaces — use a vox- prefix to avoid collisions. Record the decision in contracts/reports/crates-io-names.v1.json.

  6. Add publish metadata to the crate’s Cargo.toml:

    readme = "README.md"
    keywords = ["..."] # max 5, snake_case
    categories = ["..."] # must match https://crates.io/category_slugs

    license, repository, version, authors are inherited from the workspace. Add a README.md (becomes the crates.io front page).

  7. Dry-run:

    Terminal window
    cargo publish -p my-crate --dry-run

    If this fails with “no matching package named X”, the dep X is not yet on crates.io. Publish it first (leaf-first ordering).

  8. Publish leaf-first — each crate must be on crates.io before its dependents can publish:

    Terminal window
    cargo publish -p my-leaf-crate # publish deps first
    cargo publish -p my-crate # then the crate

    Every cargo publish (without --dry-run) is irreversible — crates.io allows yanking but not deletion. Requires cargo login with a maintainer token. Never run from CI.

Current publishable crates (leaf-first order)

Section titled “Current publishable crates (leaf-first order)”
CrateStatusNotes
vox-cryptoprepared, ready to publishno workspace deps
vox-mesh-typespreparedno workspace deps
vox-scaling-policypreparedrequires vox-mesh-types live
vox-bounded-fspreparedrequires vox-scaling-policy live
vox-secretspreparedrequires vox-crypto + vox-bounded-fs live
  • contracts/reports/crates-io-names.v1.json — approved published names
  • contracts/reports/closure-budgets.v1.json — Rule 19 dep-closure budgets
  • docs/src/architecture/layers.toml — publishable = true registry