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
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"
# (`[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.26.0"
version = "0.27.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
166 changes: 149 additions & 17 deletions SPEC.md

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions crates/dig-node-service/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ impl ExitCode {
match e.kind() {
PermissionDenied => ExitCode::PermissionDenied,
AddrInUse | AddrNotAvailable => ExitCode::BindFailed,
// A bad argument surfaced as `InvalidInput` (e.g. `dig-node open` rejecting a
// non-DIG/malformed link) is a USAGE error, not a generic I/O failure.
InvalidInput => ExitCode::Usage,
_ => ExitCode::IoError,
}
}
Expand All @@ -118,6 +121,7 @@ impl ExitCode {
/// stderr in the default mode) and a machine `result` object (folded into the
/// `--json` success envelope). Service functions return this instead of printing
/// directly, so main.rs renders ONE consistent surface for both audiences.
#[derive(Debug)]
pub struct Outcome {
/// Human-readable, possibly multi-line, summary lines.
pub summary: String,
Expand Down Expand Up @@ -204,6 +208,8 @@ mod tests {
assert_eq!(ExitCode::from_io_error(&bind), ExitCode::BindFailed);
let other = std::io::Error::other("x");
assert_eq!(ExitCode::from_io_error(&other), ExitCode::IoError);
let usage = std::io::Error::new(std::io::ErrorKind::InvalidInput, "bad link");
assert_eq!(ExitCode::from_io_error(&usage), ExitCode::Usage);
}

#[test]
Expand Down
273 changes: 237 additions & 36 deletions crates/dig-node-service/src/control.rs

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions crates/dig-node-service/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,19 @@ pub mod config;
pub mod content;
pub mod control;
pub mod meta;
/// `dig-node open <chia://… | urn:dig:chia:…>` (#389): the OS scheme-handler target the
/// installer registers for `chia://` + `urn:dig:chia:`. Strictly validates the untrusted
/// handler argument, then opens the user's default browser at the resolving URL. See [`open`].
pub mod open;
pub mod pair;
pub mod pairing;
pub mod rpc;
pub mod server;
pub mod service;
/// The machine-wide, identity-independent daemon STATE dir (#501): where the control token +
/// paired-token store live so the daemon (which may run as a service under a different OS
/// account) and the operator CLI resolve the SAME files. See [`state`].
pub mod state;
pub mod wallet_authz;

/// Windows Service Control Protocol entrypoint — only meaningful on Windows, where
Expand Down
10 changes: 10 additions & 0 deletions crates/dig-node-service/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
use clap::{Parser, Subcommand};
use dig_node_service::cli::{error_envelope, success_envelope, ExitCode, Outcome};
use dig_node_service::config::Config;
use dig_node_service::open;
use dig_node_service::pair::{self, PairAction};
use dig_node_service::{serve, service, VERSION};

Expand Down Expand Up @@ -70,6 +71,13 @@ enum Command {
#[command(subcommand)]
action: Option<PairCommand>,
},
/// Open a DIG link in the default browser (#389). The OS scheme-handler target the
/// installer registers for `chia://` + `urn:dig:chia:`. Accepts ONLY those two schemes,
/// resolves via the local node's serve URL, and never invokes a shell.
Open {
/// The DIG link (`chia://<storeId>[:<root>]/<path>` or `urn:dig:chia:<…>`).
link: String,
},
}

/// `dig-node pair` sub-actions. With none, lists pending requests + issued tokens.
Expand Down Expand Up @@ -100,6 +108,7 @@ impl Command {
Command::Stop => "stop",
Command::Status => "status",
Command::Pair { .. } => "pair",
Command::Open { .. } => "open",
}
}
}
Expand Down Expand Up @@ -129,6 +138,7 @@ fn main() -> std::process::ExitCode {
};
render(pair::run(&config, pair_action), action, json)
}
Command::Open { link } => render(open::run(&config, &link), action, json),
};
std::process::ExitCode::from(exit.code())
}
Expand Down
7 changes: 4 additions & 3 deletions crates/dig-node-service/src/meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -452,8 +452,8 @@ pub enum ErrorCode {
/// `-32030` — a `control.*` (CONTROL/admin) method was called without a valid
/// local control token. The control surface is loopback-only AND locally
/// authorized: a same-host controller (the DIG Browser "My Node" UI) must read
/// the node's control token from its config dir and present it. Read methods
/// are NOT gated; only the mutating/management control namespace is. Shell error.
/// the node's control token from the machine-wide state dir and present it. Read
/// methods are NOT gated; only the mutating/management control namespace is. Shell error.
/// (Canonical dig-rpc-types §10 code; `-32020` is RESERVED for onion routing.)
Unauthorized,
/// `-32031` — a control operation the embedded dig-node cannot perform on this
Expand Down Expand Up @@ -710,7 +710,8 @@ pub fn openrpc_document() -> Value {
let auth_note = if m.requires_auth {
" CONTROL method: requires the local control token (loopback-only + \
locally authorized — present it as the X-Dig-Control-Token header or \
params._control_token; read it from <config_dir>/control-token)."
params._control_token; read it from the machine-wide state dir's \
control-token file, e.g. via `dig-node pair`)."
} else {
""
};
Expand Down
Loading
Loading