Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions .github/workflows/build-binaries.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@
# `dign` alias (issue #548) for every supported OS/arch, and uploads them as run artifacts the
# caller's publish job attaches to a GitHub Release.
#
# DUAL ASSET NAMING (SPEC §11.2) — every per-OS/arch binary is published under TWO names so both
# downstream consumers resolve it with NO change on their side:
# * `dig-node-<ver>-<os>-<arch>[.exe]` ← the CANONICAL name the dig-installer thin-shim
# PREFERS (its dig-node Repo stem is `dig-node`).
# * `dig-companion-<ver>-<os>-<arch>[.exe]` ← the legacy name. apt.dig.net's packaging resolves
# the Linux binary by this exact template, and the installer keeps it as its pre-rename
# fallback. The binary itself is identical; only the filename differs.
# ASSET NAMING (SPEC §11.2) — every per-OS/arch binary is published under the CANONICAL name:
# * `dig-node-<ver>-<os>-<arch>[.exe]` ← the name every downstream consumer resolves: the
# dig-installer thin-shim (its dig-node Repo stem is `dig-node`) and apt.dig.net's packaging
# (whose Linux template is `dig-node-{ver}-linux-{arch}`).
# The duplicate legacy `dig-companion-*` copy is NO LONGER published (#585). dig-node was formerly
# dig-companion (#209); nothing resolves the legacy name from a dig-node RELEASE — the installer's
# pre-rename fallback targets the SEPARATE `DIG-Network/dig-companion` repo's own frozen historical
# releases, not this asset name — so the duplicate was pure release-noise.
# `dign` is a FIRST-CLASS alias binary (issue #548): a SEPARATE `[[bin]]` target sharing the SAME
# entrypoint, published alongside `dig-node` under its own stem `dign-<ver>-<os>-<arch>[.exe]`.
#
Expand Down Expand Up @@ -146,10 +147,9 @@ jobs:
SRC="target/${{ matrix.target }}/release/${{ matrix.bin }}"
test -f "$SRC" || { echo "binary not produced: $SRC"; exit 1; }
# On Windows out_name already ends in .exe; on unix there is no extension. Publish the
# SAME binary under both the canonical dig-node-* name and the legacy dig-companion-*
# name (apt's template + the installer's pre-rename fallback). See the header comment.
# binary under the canonical dig-node-* name every consumer resolves (#585 dropped the
# duplicate legacy dig-companion-* copy). See the header comment.
cp "$SRC" "dist/dig-node-${VER}-${{ matrix.out_name }}"
cp "$SRC" "dist/dig-companion-${VER}-${{ matrix.out_name }}"
# The `dign` first-class alias (issue #548): a SEPARATE binary that behaves byte-for-byte
# like `dig-node`, published under its own `dign-*` stem (same shape as `dig-node-*`) so
# the dig-installer resolves it via Repo::dign(). Its filename differs from `dig-node`
Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
# — nightly-release.yml — either from the midnight cron detecting a version bump or from a manual
# `workflow_dispatch`), this workflow builds the `dig-node` service binary + its `dign` alias for
# every OS/arch (via the reusable build workflow) and publishes them to a STABLE GitHub Release:
# `prerelease: false`, marked `latest`. Every per-OS/arch binary is published under BOTH the
# canonical `dig-node-*` and legacy `dig-companion-*` names (SPEC §11.2). The changelog is already
# `prerelease: false`, marked `latest`. Every per-OS/arch binary is published under the canonical
# `dig-node-*` name (+ the `dign-*` alias) — SPEC §11.2; the duplicate legacy `dig-companion-*`
# copy was dropped in #585. The changelog is already
# inside the tag (the orchestrator committed it before tagging), so the notes carry the changelog.
#
# This is intentionally tag-ONLY: merges to main no longer build or release here (dig_ecosystem
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ All notable changes to this project are documented here.
This project adheres to [Semantic Versioning](https://semver.org) and
[Conventional Commits](https://www.conventionalcommits.org).

## [0.36.0] - 2026-07-16

### Changed
- **status:** Consolidate the node-info/status contract to ONE canonical `version` field; remove the
ambiguous `dig_node_version` (the internal engine-library crate version) from `/version`,
`/.well-known/dig-node.json`, and `control.status` — `commit` already pins the in-repo engine
source (#586).
- **release:** Drop the duplicate legacy `dig-companion-*` release assets; ship only the canonical
`dig-node-*` binaries (+ the `dign` alias). No downstream consumer resolves the legacy name from a
dig-node release (#585).

## [0.35.0] - 2026-07-16

### Features
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ edition = "2021"
# the ROOT manifest (`[workspace.package].version`), so it MUST be set here for a
# release to fire (§3.6). The library crates (dig-node-core/dig-runtime/dig-wallet)
# keep their own independent versions — only the released binary tracks the workspace version.
version = "0.35.0"
version = "0.36.0"

# Release hardening, matching digstore: keep integer-overflow checks ON in release.
# The node parses untrusted serialized input and does offset/length arithmetic over
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ shipped as a **self-contained, cross-platform Rust binary** that installs as an
> **Naming.** The binary, crate, and service are all `dig-node` — the canonical, user-facing name
> for the local DIG node. Every machine-readable surface (`/health`, `/version`, `--json`) identifies
> itself as `dig-node`. The bind env-var names are `DIG_NODE_PORT` / `DIG_NODE_HOST` — the stable
> configuration contract (see the Environment section). For the legacy Linux package + the
> installer's pre-rename fallback, the GitHub release also publishes each binary under the old
> `dig-companion-*` filename (identical bytes). See [`USER_JOURNEY.md`](USER_JOURNEY.md).
> configuration contract (see the Environment section). Each GitHub release publishes every binary
> under the canonical `dig-node-*` name (the apt package + the installer both resolve it). See
> [`USER_JOURNEY.md`](USER_JOURNEY.md).
>
> **`dign` alias.** A shorter first-class alias binary, `dign`, ships alongside `dig-node` (mirroring
> `digs`↔`digstore`): `dign <args>` behaves identically to `dig-node <args>` — same subcommands,
Expand Down Expand Up @@ -230,7 +230,7 @@ capsule reference `storeId` or `storeId:rootHash` (each part lowercase 64-hex).

| Method | Params | Result |
|---|---|---|
| `control.status` | — | `{ running, service, version, commit, dig_node_version, protocol, uptime_secs, addr, upstream, cache:{cap_bytes,used_bytes,dir,shared}, hosted_store_count, cached_capsule_count, pinned_store_count, sync:{available} }` |
| `control.status` | — | `{ running, service, version, commit, protocol, uptime_secs, addr, upstream, cache:{cap_bytes,used_bytes,dir,shared}, hosted_store_count, cached_capsule_count, pinned_store_count, sync:{available} }` |
| `control.config.get` | — | `{ addr, port, upstream, upstream_override, cache_dir, cache_shared, config_path, sync_available }` |
| `control.config.setUpstream` | `{ upstream }` | `{ upstream, requires_restart:true }` — persisted; the running node captured its upstream at startup, so the change takes effect on the next start. A blank `upstream` clears the override. |
| `control.cache.get` | — | `{ cap_bytes, used_bytes, dir, shared }` |
Expand Down Expand Up @@ -264,7 +264,7 @@ A single fetch tells an agent what the node is, where it serves, and what it spe
| Endpoint | Returns |
|---|---|
| `GET /health` | `{ status, service:"dig-node", version, commit, mode, addr, upstream, cache:{ dir, cap_bytes, used_bytes, shared }, methods:[…] }` — extends the original health body (existing probes keep parsing `status`/`version`/`mode`/`upstream`/`cache`). `cache.shared` (#96) tells whether the cache is the dir shared with the DIG Browser. |
| `GET /version` | `{ service:"dig-node", version, commit, dig_node_version, protocol }` — the build fingerprint, to correlate a running node to an exact source revision. |
| `GET /version` | `{ service:"dig-node", version, commit, protocol }` — the build fingerprint (`version` is the one canonical version; `commit` correlates a running node to an exact source revision). |
| `GET /openrpc.json` | The OpenRPC document for the JSON-RPC surface (methods + error catalogue), generated from the method/error source so it cannot drift. |
| `GET /.well-known/dig-node.json` | The canonical discovery doc: identity, bound `addr`, cache (`dir`/`cap_bytes`/`used_bytes`/`shared`), the method catalogue, the error catalogue, and pointers to the OpenRPC/health/version endpoints. |

Expand Down
47 changes: 26 additions & 21 deletions SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,17 @@ The displayed program name is derived from arg0, so `dign --help`/`--version` re
`dig-node --help`/`--version` report `dig-node`. A release publishes `dign` alongside the primary
under the stem `dign-<ver>-<os>-<arch>[.exe]` (byte-identical shape to `dig-node-<ver>-<os>-<arch>`).

2.2. **Node library version.** The node is the first-party `dig-node-core` engine library crate in
this workspace. The constant `meta::DIG_NODE_VERSION` MUST equal the node library's crate version
(`dig_node_core::NODE_VERSION`, its `CARGO_PKG_VERSION`) and is surfaced in `/version`,
`/.well-known/dig-node.json`, and `control.status` as `dig_node_version`. When the node library
version changes, or when the digstore store-format git dependencies (`digstore-*`) are bumped to a
new rev, the method catalogue MUST be re-verified against the node's real dispatch (the drift
guard, §5.6, enforces this).
2.2. **One canonical version field (HARD RULE).** The node reports exactly ONE version — the
`version` field (the shipped `dig-node` binary / workspace release version, `meta::VERSION`) —
across `/version`, `/.well-known/dig-node.json`, and `control.status`; `commit` (`meta::GIT_SHA`)
pins the exact source revision beside it. There is NO second version key: the former
`dig_node_version` (the internal engine-library crate version, `dig_node_core::NODE_VERSION`) was
removed in #585/#586 because it named a *different* value under a second key — ambiguous ("which
version?") — and `commit` already fingerprints the now-in-repo engine. The node engine
(`dig-node-core`) is a first-party sibling crate in this workspace; when its crate version changes,
or when the digstore store-format git dependencies (`digstore-*`) are bumped to a new rev, the
method catalogue MUST be re-verified against the node's real dispatch (the drift guard, §5.6,
enforces this).

2.3. **Protocol tag.** `meta::PROTOCOL` is the DIG read-protocol identifier (`"21"`, the
rpc.dig.net §21 JSON-RPC read contract). It MUST be bumped only when the wire contract changes.
Expand Down Expand Up @@ -798,7 +802,7 @@ canonical one (`true`) or a process-private fallback (`false`), from the read pa

### 6.2. `GET /version`

Returns `{ service, version, commit, dig_node_version, protocol }` (§2).
Returns `{ service, version, commit, protocol }` (§2; `version` is the one canonical version).

### 6.3. `GET /openrpc.json` and `rpc.discover`

Expand Down Expand Up @@ -986,7 +990,7 @@ lowercase 64-hex; a capsule reference is `storeId:rootHash`. Malformed refs yiel

| Method | Params | Result (essentials) |
|---|---|---|
| `control.status` | — | `running`, `service`, `version`, `commit`, `dig_node_version`, `protocol`, `uptime_secs`, `addr`, `upstream`, `cache`, `hosted_store_count`, `cached_capsule_count`, `pinned_store_count`, `sync.available` |
| `control.status` | — | `running`, `service`, `version`, `commit`, `protocol`, `uptime_secs`, `addr`, `upstream`, `cache`, `hosted_store_count`, `cached_capsule_count`, `pinned_store_count`, `sync.available` |
| `control.config.get` | — | `addr`, `port`, `upstream`, `upstream_override`, `cache_dir`, `cache_shared`, `config_path`, `sync_available` |
| `control.config.setUpstream` | `upstream` (URL string; blank clears) | `upstream` (normalized), `requires_restart: true` — persisted, effective on next start (§3.4) |
| `control.cache.get` | — | `cap_bytes`, `used_bytes`, `dir`, `shared` |
Expand Down Expand Up @@ -1531,17 +1535,18 @@ boolean, default `false`). It MUST NOT trigger on `push` to `main`.
job is a no-op). The manual-dispatch `workflow_dispatch` on `release.yml` is a build-only "does main
still build?" canary — it never publishes (publish is gated on a tag ref).

11.2. **Dual asset naming (HARD RULE).** Every per-OS/arch binary MUST be published under TWO
filenames containing identical bytes:
11.2. **Asset naming (HARD RULE).** Every per-OS/arch binary MUST be published under the canonical
name:

- **`dig-node-<ver>-<os>-<arch>[.exe]`** — the canonical name; the dig-installer thin-shim's
preferred stem.
- **`dig-companion-<ver>-<os>-<arch>[.exe]`** — the legacy name; apt.dig.net's Linux packaging
resolves by exactly this template (`dig-companion-{ver}-linux-x64`, bare binary), and the
installer keeps it as its pre-rename fallback.
- **`dig-node-<ver>-<os>-<arch>[.exe]`** — the canonical name every downstream consumer resolves:
the dig-installer thin-shim's preferred stem AND apt.dig.net's Linux packaging template
(`dig-node-{ver}-linux-{arch}`, bare binary).

`<ver>` is the tag without the leading `v`. Removing the legacy asset is a breaking change for
those consumers and MUST NOT be done while either still resolves it.
`<ver>` is the tag without the leading `v`. The duplicate legacy `dig-companion-*` copy (dig-node
was formerly dig-companion, #209) is NO LONGER published (#585): no consumer resolves that name from
a dig-node release — the installer's pre-rename fallback targets the SEPARATE
`DIG-Network/dig-companion` repo's own frozen historical releases, not this asset name — so it was
pure release-noise.

11.3. **Matrix.** `windows-x64` (x86_64-pc-windows-msvc), `linux-x64` (x86_64-unknown-linux-gnu),
`macos-arm64` (aarch64-apple-darwin), `macos-x64` (x86_64-apple-darwin, cross-compiled on
Expand All @@ -1564,8 +1569,8 @@ tags/releases and the rolling `nightly` are NEVER pruned. Neither `nightly-*` no

11.6. **Reusable build.** The cross-OS build lives once in `.github/workflows/build-binaries.yml`
(`on: workflow_call`, inputs `version` + `ref`). Both `release.yml` (stable) and the nightly channel
call it, so the two paths can never diverge on HOW a binary is produced — including the dual
`dig-node-*`/`dig-companion-*` naming (§11.2) and the `dign` alias.
call it, so the two paths can never diverge on HOW a binary is produced — including the canonical
`dig-node-*` naming (§11.2) and the `dign` alias.

11.7. **RELEASE_TOKEN posture + 60-day cron caveat.** Releasing uses the `RELEASE_TOKEN` org PAT,
not `GITHUB_TOKEN` (a tag pushed by `GITHUB_TOKEN` does not trigger downstream workflows, and it
Expand Down Expand Up @@ -1615,7 +1620,7 @@ ONLY automatic release trigger, a quiet repo can silently stop releasing. Detect
| 7 | Error codes | Table §10 — stable numbers + UPPER_SNAKE names + origins | §10; `src/meta.rs` |
| 8 | CLI exit codes + `--json` envelopes | Table §8.4; one JSON object on stdout | §8; `src/cli.rs`, `tests/cli.rs` |
| 9 | Service label | `net.dignetwork.dig-node` across install/uninstall/start/stop/SCM dispatcher | §2.4, §9.4 |
| 10 | Release assets | Dual-named `dig-node-*` + legacy `dig-companion-*`, identical bytes, per §11.3 matrix | §11; `.github/workflows/release.yml` |
| 10 | Release assets | Canonical `dig-node-*` (+ `dign-*` alias), per §11.3 matrix | §11; `.github/workflows/release.yml` |
| 11 | Control-token scheme | `<state_dir>/control-token` (machine-wide, ACL-restricted, §7.3a), 64-hex, `X-Dig-Control-Token` / `params._control_token`, constant-time | §7.2–7.3a |
| 12 | Health/version/well-known shapes | §6 fields; additions additive only | §6; `src/meta.rs`, `src/server.rs` |
| 13 | Subscription persistence | `<cache>/subscriptions.json` schema-versioned, atomic, cross-process-locked | §14.1; `subscription.rs` |
Expand Down
6 changes: 3 additions & 3 deletions USER_JOURNEY.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
> for the local DIG node (per `SYSTEM.md` → *Canonical terminology & branding*). Everything the user
> sees and every machine-readable surface identifies itself as `dig-node`. The bind env-var names
> are `DIG_NODE_PORT` / `DIG_NODE_HOST` — the stable configuration contract, and the GitHub
> release also publishes each binary under the legacy `dig-companion-*` filename (identical bytes) for
> the apt package + the installer's pre-rename fallback.
> release publishes each binary under the canonical `dig-node-*` name (the apt package + the
> installer both resolve it).

`dig-node` is the **localhost DIG node** that the [DIG Chrome extension](https://github.com/DIG-Network/dig-chrome-extension)
(and any DIG client) resolves `chia://` content through, so retrieval happens **on the user's own
Expand Down Expand Up @@ -153,7 +153,7 @@ every subcommand (machine output to stdout, prose to stderr).
|---|---|
| `POST /` | JSON-RPC 2.0 — the read path (`dig.getContent`, `dig.getAnchoredRoot`, `cache.*`, passthrough, `rpc.discover`) **and** the gated `control.*` admin surface. |
| `GET /health` | Liveness + mode + cache stats, plus `service`, `commit`, bound `addr`, cache `dir`, and the `methods` catalogue. |
| `GET /version` | Build fingerprint: `{ service, version, commit, dig_node_version, protocol }`. |
| `GET /version` | Build fingerprint: `{ service, version, commit, protocol }`. |
| `GET /openrpc.json` | The OpenRPC document for the JSON-RPC surface (methods + error catalogue). |
| `GET /.well-known/dig-node.json` | Canonical discovery doc: identity, addr, cache, methods, errors, spec pointers. |

Expand Down
10 changes: 6 additions & 4 deletions crates/dig-node-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,12 @@ pub mod subscription;
/// read-only on the loopback browser surface (`GET /verify/...`).
pub mod verification_ledger;

/// The node library's crate version (its `Cargo.toml` `version`). Host shells (the
/// OS-service `dig-node-service`, the DIG Browser's `dig_runtime`) surface this as the
/// running node's `dig_node_version` in status/discovery documents, so a deployed node
/// reports exactly which node implementation it runs.
/// The node engine library's own crate version (its `Cargo.toml` `version`), for
/// programmatic use by host shells. Host shells report the SHIPPED node version to
/// consumers as the single canonical `version` field, and pin the exact engine source
/// via the build `commit` (this engine is an in-repo sibling crate), so this crate
/// version is NOT surfaced under a second status key (#586 removed the former
/// `dig_node_version`).
pub const NODE_VERSION: &str = env!("CARGO_PKG_VERSION");

/// JSON-RPC error code: the served/requested root is NOT the store's
Expand Down
1 change: 0 additions & 1 deletion crates/dig-node-service/src/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,6 @@ async fn status(ctx: &ControlCtx) -> Value {
"service": crate::meta::SERVICE_NAME,
"version": crate::meta::VERSION,
"commit": crate::meta::GIT_SHA,
"dig_node_version": crate::meta::DIG_NODE_VERSION,
"protocol": crate::meta::PROTOCOL,
"uptime_secs": ctx.started.elapsed().as_secs(),
"addr": ctx.addr,
Expand Down
Loading
Loading