# dwarves — the CI/CD forge of the nordisk constellation.
#
# The smith crates (Brokkr, Sindri) move in here as the forge grows (the
# EXTRACTION — a separate, larger task). For now the workspace carries the
# forge's own `dwarves` CLI: the entrypoint every pipeline is reached through,
# with `dwarves doctor` as the self-check the smoke test drives.
# The `dwarves-gui` crate is the live web + native demo (an INTERIM facett render of
# the CI/CD forge view on the reusable `facett-wasm-demo` harness — pipeline roster +
# run listing), and `xtask` builds/publishes it to Codeberg Pages. Both are their OWN
# crates (`publish = false`): nothing else in the workspace depends on them, so the
# `dwarves` CLI's minimal-dependency footprint is untouched — they only ever compile
# when explicitly targeted (`cargo build -p dwarves-gui` / `cargo xtask …`).
[workspace]
resolver = "2"
members = ["crates/dwarves", "crates/dwarves-embed", "crates/dwarves-slsa", "crates/dwarves-web-client", "crates/nornir-funnel-embed", "crates/nornir-warehouse-embed", "crates/nornir-warehouse-nav", "dwarves-gui", "xtask"]
[workspace.package]
version = "0.2.0"
edition = "2021"
license = "MIT OR Apache-2.0"
repository = "https://git.gunnar.rs/nordisk/dwarves"
# LOCAL DEV ONLY (mirrors holger/nornir): when the OPTIONAL `holger` feature is built,
# dwarves consumes holger-server-lib in-process for the artifact store, which pulls
# znippy transitively. crates.io znippy-common still trails the local API, so redirect
# the znippy crates to the sibling checkout (the documented side-by-side dev layout).
# These patches are STRIPPED by `cargo publish` and are inert for the DEFAULT build
# (the `holger` feature is off, so nothing here is resolved). REMOVE before any publish
# of a holger-enabled dwarves. Paths are RELATIVE to the sibling convention.
#
# ── ⚠ EVERY CONDITION BELOW HAS EXPIRED. MEASURED 2026-08-24. ────────────────────
#
# NOT, as it turns out, a release blocker — and that correction is the useful part.
# `release_doctor::fork_scope` treats a `[patch.crates-io]` entry whose target this repo
# does not itself produce as a FOREIGN FORK and blocks the closure above it, per its own
# rule table:
#
# publishable + local version ALREADY on crates.io -> Held (reported, run proceeds)
# publishable + UNPUBLISHED / ahead / desync -> Veto (whole run refuses)
#
# Read cold, that predicts a Veto here: `dwarves-embed`, `dwarves-web-client` and
# `nornir-warehouse-nav` are all `RegistryState::Unpublished`. MEASURED, it does not
# happen — `dwarves crate-release . --bump keep --only <the six>` on 2026-08-24 reported
# no fork hold and no veto at all, and went green through graph-precheck, the dirty sweep
# and Gate B (6/6 rehearsed into the served /sparring). So this block is NOT why the
# 2026-08-23 cascade's tail stalled; the package-boundary defects fixed in the same commit
# as this comment are. Written down because the cold reading is plausible, wrong, and
# would otherwise get re-derived by the next lane that walks fork_scope.rs.
#
# The lines are still expired, and that is worth recording on its own. Per line —
# published max_version vs the local checkout this patch points at, and a byte compare of
# the two `src/` trees:
#
# | patch target | crates.io | local | src/ diff |
# |----------------------|-----------|--------|------------------------|
# | nornir-git | 0.1.7 | 0.1.7 | IDENTICAL (0 files) |
# | znippy-common | 0.9.14 | 0.9.14 | IDENTICAL (0 files) |
# | znippy-compress | 0.9.13 | 0.9.13 | IDENTICAL (0 files) |
# | znippy-decompress | 0.9.11 | 0.9.11 | IDENTICAL (0 files) |
# | znippy-plugin-python | 0.9.9 | 0.9.9 | IDENTICAL (0 files) |
# | znippy-plugin-maven | 0.9.10 | 0.9.10 | IDENTICAL (0 files) |
# | znippy-zoomies | 0.1.24 | 0.1.24 | IDENTICAL (0 files) |
#
# Not "close enough" — the registry has caught up EXACTLY, at every one of the seven, to
# the byte. So "crates.io znippy-common still trails the local API" (above) and
# "`znippy_zoomies::gatling_bfs` exists only in the local `../znippy-zoomies`, not in the
# 0.1.13 on crates.io" (below) are both simply no longer true: 0.1.13 became 0.1.24, and
# 0.1.24 is the local tree. Corroborated end to end rather than only by version string —
# the isolated published-shape `cargo package` runs of `nornir-warehouse-nav` and
# `dwarves-embed` (2026-08-24) compiled `znippy-zoomies 0.1.24` and `nornir-git 0.1.7`
# FROM THE REGISTRY, with no patch block in effect at all, and both packaged green.
#
# WHY THEY ARE STILL HERE, then: removing them cannot be VERIFIED on this box today. The
# dwarves workspace does not resolve at all —
#
# error: failed to select a version for the requirement `funnel-core = "^0.1.4"`
# candidate versions found which didn't match: 0.1.3
# location searched: /home/rickard/git/funnel-core
# required by package `nornir v0.5.6 (/home/rickard/git/nornir)`
#
# — because the `funnel-core` sibling CHECKOUT is one commit behind its own origin/main
# (d55cde4, "funnel-core 0.1.4: drifted"). `nornir/Cargo.toml:522` names funnel-core by
# PATH, and `[patch.crates-io]` cannot override a path dep, so nothing inside dwarves can
# route around it.
#
# Note WHICH things that breaks, because it is not everything: `cargo metadata`, `cargo
# check`, `cargo test` and a plain in-workspace `cargo package` all fail on it. The RELEASE
# path does not — it operates on stripped, path-free manifests, which is why
# `crate-release` runs green through Gate B while `cargo check --workspace` cannot start.
# So the gates are reachable and the local FAT `embed-nornir` build is not, and removing
# these seven lines is exactly a change to the resolve that only the unreachable half
# exercises. That is the whole reason they are still here: not a measured risk, an
# UNMEASURABLE one, and shared main is the wrong place to find out.
#
# So the expiry is recorded rather than acted on. `git merge --ff-only origin/main` in
# ../funnel-core, then `cargo check --workspace`, is the whole remaining gate on deleting
# this block.
#
# (`bench/Cargo.toml` carries the same five znippy lines with the same expired reasoning.
# It is a SEPARATE workspace and `publish = false`, so it holds up no release; it should
# come off in the same pass, for tidiness rather than for the gate.)
[patch.crates-io]
# `gunnar-client` (the constellation's pure-Rust send-pack, linked by the release
# doctor's finalize push) names `nornir-git` by VERSION; dwarves names it by PATH. One
# copy, not two russh/gix stacks: point the registry name at the sibling edda checkout.
nornir-git = { path = "../edda/crates/nornir-git" }
# -- holger's version-only sibling crates (2026-10-22), mirrored from nornir 4db6b941 --
# holger main (cbf89f0e) names these by version only and they are not on crates.io yet,
# so `embed-holger` (holger-server-lib) does not resolve without them. DROP each line
# once that crate is published.
appliance-grow = { path = "../edda/crates/appliance-grow" }
nordisk-estate-svg = { path = "../monetize/crates/estate-svg" }
nordisk-twin = { path = "../Skidbladnir/crates/installer/nordisk-twin" }
nornir-auth-policy = { path = "../edda/crates/nornir-auth-policy" }
# One copy each: holger names these by version only too, while this workspace builds
# them from the same siblings by path.
draupnir = { path = "../draupnir" }
jera = { path = "../edda/crates/jera" }
modgunn = { path = "../modgunn" }
nornir-appshell = { path = "../edda/crates/nornir-appshell" }
nornir-auth-webauthn = { path = "../edda/crates/nornir-auth-webauthn" }
nornir-escape = { path = "../edda/crates/nornir-escape" }
nornir-humanize = { path = "../edda/crates/nornir-humanize" }
nornir-service = { path = "../edda/crates/nornir-service" }
nornir-zone = { path = "../edda/crates/nornir-zone" }
# TEMPORARY (the release-3 merge, 2026-10-03), until gunnar publishes gunnar-client on
# russh 0.63 / gix 0.88. release-3 takes gunnar-client from crates.io (678fe68: a holger
# constellation has no ../gunnar checkout), and that is what crates/dwarves/Cargo.toml
# still names. But crates.io's newest, 1.1.4, rides russh 0.61, which pins ecdsa
# =0.17.0-rc.18 / ed25519-dalek =3.0.0-rc.0 — it cannot share a lock with main's W3
# crypto (korp-installer's p256 0.14 / ecdsa 0.17.0) — and main's lock already had
# gunnar-client 1.4.0 (the sibling's). So the registry name points at the sibling
# gunnar checkout while this lasts; the line goes when gunnar-client is published.
gunnar-client = { path = "../gunnar/crates/gunnar-client" }
# ...and, for the same while, the edda git crates it is built on, exactly as gunnar's own
# root patches them (gunnar 71b968e): crates.io's gunnar-pack/-delta/-pktline/-sendpack
# are on the gix 0.86 set, and the sibling gunnar-client on gix 0.88 cannot take their
# ObjectId (two gix-hash majors). Only the entries this graph uses; they go with the
# line above when edda and gunnar publish.
# 2026-10-05 (merge to main): gunnar-pack/-delta/-pktline/-sendpack 2.0.0 / 1.1.0 are on
# crates.io (published 2026-10-04 on gix 0.88, byte-identical to the merged edda), so
# their lines went; so did znippy-compress / -plugin-python / -plugin-maven /
# -decompress and znippy-zoomies (published identical, or unused). znippy-common stays:
# the merged znippy carries the W3 sign bump that 0.9.17 on crates.io does not.
znippy-common = { path = "../znippy/znippy-common" }
# ── the FAT-build patch set, mirrored from nornir/Cargo.toml ────────────────
# `embed-nornir` compiles the `nornir` umbrella IN, so this workspace must resolve
# nornir's dep graph the SAME way nornir's own workspace does. Without these,
# `cargo check -p dwarves --features embed-nornir` fails inside nornir's sources on
# APIs the published crates do not have yet — e.g. `znippy_zoomies::gatling_bfs`
# (the frontier-parallel BFS that drives the change-radius walk) exists only in the
# local `../znippy-zoomies`, not in the 0.1.13 on crates.io.
#
# Keep this list in sync with nornir's `[patch.crates-io]`. A patch that drifts
# between the two workspaces means the fat node builds a DIFFERENT nornir than the
# standalone `nornir-server` does, which is worse than not building it at all.
#
# `nornir-testmatrix` is NOT listed: this workspace already path-deps it directly, so a
# patch entry would be redundant (and cargo would warn it went unused).
#
# `nornir-build-thing` IS listed, since 2026-08-29 (oden): modgunn 98ec031 names it by
# VERSION (`nornir-build-thing = "0.1"`, behind `provenance-verify`) and reads
# `Attestation::dsse` / `BuildProvenance::slsa_statement_bytes` — the local edda API
# (0.1.11 + DSSE) — while modgunn's own `[patch.crates-io]` does not reach into THIS
# workspace (patches are root-only). Without this line cargo resolved a SECOND copy,
# registry 0.1.10, and the forge build died in modgunn/src/provenance.rs:756 with
# `E0609: no field dsse`. One nornir-build-thing, the sibling checkout, like nornir-git.
nornir-build-thing = { path = "../edda/crates/nornir-build-thing" }
# `dwarves-runa` IS listed, since 2026-09-26 (loki): facett-pipeline (path dep, feature
# `runa-adapter`) names it by VERSION (`0.2.0`), while dwarves, dwarves-embed and
# dwarves-gui name the edda sibling by PATH. Two packages, same 0.2.3, and
# `cargo test -p dwarves-gui --tests` died in dwarves-embed/src/cicdwizard.rs with
# `E0308: expected dwarves_runa::pipeline::Pipeline, found dwarves_runa::Pipeline`.
# One dwarves-runa, the sibling checkout, like nornir-git and nornir-build-thing.
dwarves-runa = { path = "../edda/crates/dwarves-runa" }
# Rickard, 2026-09-05: test artifacts carry line tables only — full DWARF in every test
# binary and its deps was the bulk of a target dir (gunnar/target 271 GB, korp/target 852 GB
# on the day the disks filled); backtraces still show file:line.
[profile.test]
debug = "line-tables-only"