# Publishing a release A release moves a package from a working directory to an installable, content-hashed artifact that other packages can pin. The registry is a directory layout, an address and not an authority: descriptors promise bytes, and after download the bytes prove the promise by hash. Environment: the public `law-v0.1.1` release, run from the root of the [lab bundle](/corpus/lab/#before-you-start). The example continues the lab's [versions exercise](/corpus/lab/solutions/#versions-exercise), which has already published the five lab packages to `/tmp/lab-work/registry` and authored revision `0.2.0` of `labparcels.registry` in `/tmp/lab-work/reg02`. Status letters follow the [legend on the topic index](/corpus/#how-this-topic-marks-confidence). ## Example: pack, publish, and pin one revision One package, three steps. All commands and outputs below are verbatim from the [versions exercise](/corpus/lab/solutions/#versions-exercise). **1. Pack and 2. publish** revision `0.2.0` of `labparcels.registry` into the existing lab registry: ```shell law pack --out /tmp/lab-work/artifacts/registry-0.2.0 --project /tmp/lab-work/reg02 law publish /tmp/lab-work/artifacts/registry-0.2.0 --registry lab=/tmp/lab-work/registry ``` ```text labparcels.registry@0.2.0 → /tmp/lab-work/artifacts/registry-0.2.0: contentHash sha256:fc69df17896dd8c60a4a4889e2313fd3228b234444bf0e36d98a94372ab96ce2, worldHash sha256:b3056c550cfaf9c58fa84befda4557d3b6c5020fdfc8c324086335343998e597, 3 files labparcels.registry@0.2.0 → lab (/tmp/lab-work/registry): contentHash sha256:fc69df17896dd8c60a4a4889e2313fd3228b234444bf0e36d98a94372ab96ce2, worldHash sha256:b3056c550cfaf9c58fa84befda4557d3b6c5020fdfc8c324086335343998e597 versions labparcels.registry: 0.1.0, 0.2.0 changed: p/labparcels.registry/0.2.0/package.lawir.json changed: p/labparcels.registry/0.2.0/world.lawir.json changed: p/labparcels.registry/0.2.0.json ``` The first line is `pack`: it names the artifact directory and two hashes. The content hash pins the package bytes; the world hash pins the package together with its closure. The remaining lines are `publish`: the same two hashes now stand in the registry, the registry lists both known versions, and the `changed:` lines name the descriptor (`0.2.0.json`) and the two blobs it wrote. What this result means: any project that can read the `lab` registry can now pin `labparcels.registry@0.2.0`, and the install will verify the downloaded bytes against `sha256:fc69df17…`. Nothing in an existing consumer changed yet. **3. Pin** the new revision from a consumer, here a scratch copy of the fees package at `/tmp/lab-work/fees-upd`: ```shell law update 'labparcels.registry@0.2.0' --project /tmp/lab-work/fees-upd --registry lab=/tmp/lab-work/registry ``` ```text lab ← /tmp/lab-work/registry (--registry) ~ labparcels.registry 0.1.0 -> 0.2.0 changed: .law/transport.json changed: deps/labparcels.registry.lawir.json changed: law.lock changed: law.toml changed: package.law ``` The consumer's manifest, lock, pinned bytes, and import line now name `0.2.0`. In the lab run its five scenarios still pass after the move, so the consumer can commit the new pin. Previewing the move first and checking currency afterwards are covered on [**Upgrades and replay**](/corpus/releases/replay-and-upgrades/). ## The three steps in general First `pack` builds the release artifact: a directory or a portable `.arxo` container. Then `publish` places it into a registry directory, or prepares a signed candidate from a manifest plus a bytes directory. Downstream packages then pin the exact version with `add` or `update`. The directory flow is **available in the public release** (S). The command catalog records these usage strings for the first two steps: ```text law pack --out