This guide is the operator contract for libdictenstein's 4.0.0-rc.5 source,
native, and language-binding artifacts. The family-wide dependency order,
registry spellings, and credential matrix remain normative in
liblevenshtein's release guide.
release/version.json is the version authority. The root crate, package
manifests, native metadata, and language facades must agree with it before a
tag is created. The release tag is v4.0.0-rc.5; Go later receives the
additional subdirectory tag bindings/go/v4.0.0-rc.5.
The source validation graph consumes exact v4.0.0-rc.5 tags for
vinary-tree-interop and liblevenshtein plus v0.1.0 for llattice.
liblevenshtein is a cross-project validation consumer, not a registry
prerequisite: public libdictenstein packages are published after interop and
before liblevenshtein.
Before tagging, require a clean worktree and run:
python3 scripts/sync-release-version.py
python3 scripts/check-bindings.py
python3 scripts/check-binding-docs.py
RUST_BACKTRACE=1 cargo nextest run --release --no-fail-fast --workspace --all-features
cargo clippy --all-features --all-targets -- -D warnings
The synchronizer writes and validates the libdictenstein and interop package
entries in the primary Cargo.lock. Locked builds must leave that file
byte-for-byte unchanged; a stale lock is a source defect, not something a
publication workflow may regenerate.
The repository CI additionally proves the feature matrix, Rocq models, sanitizers, documentation, diagrams, and all language conformance suites.
Pushing the tag creates only the immutable source ref. A manual
validate-only dispatch at the tag validates and stages artifacts and creates
the checksummed GitHub prerelease. Later publication dispatches must choose one
registry value; branch dispatches fail the contract job.
gh workflow run release-bindings.yml \
--repo vinary-tree/libdictenstein \
--ref v4.0.0-rc.5 \
-f registry=validate-only
gh workflow run release-bindings.yml \
--repo vinary-tree/libdictenstein \
--ref v4.0.0-rc.5 \
-f registry=npm
validate-only enables no registry uploader. The other choices—npm,
crates-io, pypi, maven-central, clojars, nuget, rubygems,
go-module, luarocks, and opam—each authorize only their matching
protected job. There is deliberately no publish-all option.
The crates.io job uses OpenID Connect (OIDC) trusted publishing rather than a
stored Cargo token. In the libdictenstein crate settings on crates.io,
register repository vinary-tree/libdictenstein, workflow
release-bindings.yml, and environment crates-io. The job grants
id-token: write only to the uploader, obtains a temporary token with
rust-lang/crates-io-auth-action@v1, and passes that value to
cargo publish --locked.
npm uses the corresponding package-level publisher for
@vinary-tree/libdictenstein: repository vinary-tree/libdictenstein,
workflow release-bindings.yml, environment npm, and direct npm publish
authority. After the first successful keyless publications, require trusted
publishing on crates.io, disallow npm tokens in the package settings, and
revoke the superseded long-lived credentials. The family-wide guide contains
the complete publisher matrix and recovery order.
RubyGems is keyless as well. Because libdictenstein is a new global gem
coordinate, register a pending trusted publisher with repository owner
vinary-tree, repository libdictenstein, workflow release-bindings.yml,
and environment rubygems; leave reusable-workflow fields empty. The uploader
alone receives id-token: write, exchanges that identity through the official
RubyGems credential action pinned to release v2.1.0's immutable commit, and
pushes the exact .gem produced by the unprivileged package job. No
RUBYGEMS_API_KEY is stored.
Clojars does not offer a GitHub OIDC exchange. Verify io.vinarytree in
Clojars using the vinarytree.io DNS proof, store the public account name as
the organization variable CLOJARS_USERNAME, and store only
CLOJARS_DEPLOY_TOKEN in this repository's protected clojars environment.
The first io.vinarytree/libdictenstein-clojure upload requires an unscoped,
single-use bootstrap token because Clojars cannot scope a token to a nonexistent
artifact. After registry read-back succeeds, disable it and replace it with a
finite-expiration token scoped only to that artifact.
LuaRocks has no OIDC trusted-publisher exchange. Create an API key dedicated to
vinary-tree/libdictenstein and store it only as LUAROCKS_API_KEY in this
repository's protected luarocks environment; do not share the
liblevenshtein-rust key or place either key at organization scope. The upload
job uses --temp-key, which authenticates this invocation without persisting
the secret in the runner's LuaRocks configuration. Required-reviewer protection
remains the human authorization boundary for each upload.
The source rock deliberately treats the native SDK as an external dependency.
Its module paths use LIBDICTENSTEIN_INCDIR and
LIBDICTENSTEIN_LIBDIR, followed by the source package's generated shared-ABI
headers; never replace them with a checkout-local target/release path. Before
upload, the release job downloads the exact Linux native SDK, builds the rock
into an isolated tree through those two variables, and runs the public Lua
conformance program from that installed tree. luarocks lint alone is
insufficient because it does not invoke the linker or load the resulting
module.
opam publication targets the fixed organization fork
vinary-tree/opam-repository and opens an upstream pull request against
ocaml/opam-repository:master. Store a short-lived classic GitHub token with
only public_repo as OPAM_GITHUB_TOKEN in this repository's protected
opam environment. The job checks out the release model, reads the opam-native
4.0.0~rc5 version for the package directory, uses the canonical version only
in its Git-safe branch name, and configures Git authentication without placing
the token in a remote URL. Submit vinary-tree-interop.4.0.0~rc5 first; only
after that upstream package is merged and publicly resolvable should this job
submit libdictenstein.4.0.0~rc5. Revoke the release token after the complete
three-package submission sequence.
The validate-only graph does not mutate a package registry, but its terminal
job writes the checksummed GitHub prerelease. Protect that job with the
github-release environment and a required reviewer. It needs no stored
secret; approval gates the job-scoped GITHUB_TOKEN used for the release.
The renamed global-distribution metadata first appeared in append-only source
v4.0.0-rc.4-release.1. Its validate-only graph passed every package lane
except the numeric fpm candidate: fpm correctly rejected the intentional public
module vinary_tree_libdictenstein while optional package-name enforcement was
enabled for package libdictenstein. No registry publication job ran.
Append-only source v4.0.0-rc.4-release.2 preserves that idiomatic namespaced
Fortran module and disables only fpm's optional module-name convention in both
development and staged manifests. Publisher-environment corrections are
preserved by releases 3 and 4. Public read-back of the revision-1 Lua rock then
proved that its hard-coded source-tree library path was not installable from a
registry archive. Append-only source v4.0.0-rc.4-release.5 replaces that path
with LuaRocks' external-dependency variables and publishes packaging revision
4.0.0rc4-2. The Rust RC, ABI, and Lua API remain unchanged. The synchronizer
and binding contract treat the semantic version, Lua packaging revision, and
source tag as independent release invariants. The opam staging job derives its
own exact corrective source ref from GITHUB_REF_NAME.
RC.5 also restores the JavaScript package graph to the repositories' existing,
public names. The libdictenstein facade remains
@vinary-tree/libdictenstein; its only runtime dependencies are
@vinary-tree/vinary-tree-interop and @vinary-tree/javascript-runtime at
the same exact candidate. The mistakenly shortened @vinary-tree/interop and
mistaken umbrella @vinary-tree/vinary-tree coordinates are historical
artifacts, not aliases to use in manifests. Publish and verify the canonical
packages before deprecating the mistaken coordinates. The same release model
owns the product description used verbatim by the Maven POM, JReleaser, and
Clojars so their public summaries cannot drift.
The GitHub prerelease retains portable native archives, Python wheels, the npm
tarball, Maven and Clojure staging files, NuGet and Ruby packages, the
LuaRocks and opam metadata, the Hackage numeric candidate, and one
SHA256SUMS manifest. Hackage and fpm remain candidate-only for the RC
because their numeric 4.0.0 spellings cannot distinguish it from the final
release.
For npm, the protected job publishes
@vinary-tree/libdictenstein@4.0.0-rc.5 with provenance under next.
Install the public tarball in a clean directory, exercise dictionary
construction, mutation, iteration, snapshot stability, and deterministic
close, then move the new scoped package's latest tag to the RC, remove
bootstrap, and deprecate the immutable 0.0.0 reservation artifact.
Tags and published versions are immutable. A failed validation run may be
rerun with registry=validate-only; a failed registry lane may be retried only
when the registry confirms that version was not accepted. If public bytes are
wrong, repair the source and issue the next unused candidate. Never move the
source tag, overwrite a package version, or authorize an unrelated registry
to compensate for a failed lane.
Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |