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
4 changes: 2 additions & 2 deletions 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.47.7"
version = "0.47.8"

# 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
2 changes: 1 addition & 1 deletion crates/dig-node-core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "dig-node-core"
version = "0.13.7"
version = "0.13.8"
edition = "2021"
license = "GPL-2.0-only"
description = "The canonical DIG node ENGINE library (crate `dig_node_core`): the JSON-RPC dispatch (`handle_rpc`, the same contract as rpc.dig.net), local-first content serve/fetch/redirect from LOCAL .dig store modules (via digstore_host::serve_blind), chain-anchored-root resolution, chain-watch + subscriptions + generation gap-fill, the LRU cache, and the full P2P stack. Shared UNCHANGED by both host shells: the `dig-node` OS-service binary (dig-node-service) and the DIG Browser's in-process cdylib (dig-runtime). Native Rust so the compiled-module serve path works."
Expand Down
37 changes: 4 additions & 33 deletions crates/dig-node-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ pub use seams::dig_peer::{address_book, dht, net, pex, session, PeerNetwork};
/// `handle_rpc`/`handle_rpc_json` free functions delegate to it; most callers keep using those
/// stable entry points and never need this trait in scope directly.
pub use seams::dig_rpc::RpcDispatch;
/// The `KeyManager` trait is seam 7's public surface (#1285 W1b-6) — bring it into scope to call
/// `peer_id_hex`/`identity_seed_for_peer`/`peer_cert_dir`/`node_cert_dir` on a `Node`. #908
/// boundary: this seam holds ONLY the node's machine identity — never a user key.
pub use seams::key_mgmt::KeyManager;
/// Cross-seam shared vocabulary (#1285 W1a) — the ONLY types the node's seams (peer, wallet, rpc,
/// local-content, capsule, chain, key-management) are allowed to share; see the module doc.
pub mod shared;
Expand Down Expand Up @@ -1724,17 +1728,6 @@ impl Node {
// learns what this node already holds. Every byte a peer fetches carries its own merkle proof
// (verified by the caller against the chain-anchored root), so the node is never the trust anchor.

/// The node's own `peer_id` (64-hex) = SHA-256(SPKI DER) of its PERSISTENT, CA-signed
/// [`NodeCert`](dig_nat::NodeCert), or `None` if no identity seed is configured. This is the mTLS
/// identity the node presents on every peer path (loaded from — or minted into — the node's cert
/// dir, so it is stable across restarts; see [`peer::load_or_generate_node_cert`]).
pub fn peer_id_hex(&self) -> Option<String> {
let seed = self.identity_seed?;
peer::load_or_generate_node_cert(self.node_cert_dir(), &seed)
.ok()
.map(|cert| cert.peer_id().to_hex())
}

/// `dig.getAvailability` — answer one queried item against the local inventory, enriching the
/// pure presence answer (`peer::availability_presence`) with the per-resource `total_length` +
/// `chunk_count` when the item is at resource granularity (`store_id` + `root` + `retrieval_key`)
Expand Down Expand Up @@ -2143,28 +2136,6 @@ impl Node {
})
}

/// The node's persistent identity seed, if configured — the source of the STABLE mTLS `peer_id`
/// for the L7 peer network (see [`peer::load_or_generate_node_cert`]). `None` disables the peer network
/// (the node still serves the HTTP read path).
pub fn identity_seed_for_peer(&self) -> Option<[u8; 32]> {
self.identity_seed
}

/// The directory the L7 peer network keeps its TLS cert/key + peer address book under (a
/// `peer-net/` subdir of the cache dir, so it shares the node's data root + writability handling).
pub fn peer_cert_dir(&self) -> PathBuf {
self.cache_dir.join("peer-net")
}

/// The directory the node's PERSISTENT, CA-signed [`NodeCert`](dig_nat::NodeCert) identity
/// (`node.crt` + `node.key`, 0600) lives under — an `identity/` subdir of [`Self::peer_cert_dir`],
/// kept SEPARATE from dig-gossip's own `node.key` in `peer-net/` so the two never clobber each
/// other. This is the node's stable machine transport identity (#908, #1280); its `peer_id`
/// survives restarts because the cert is loaded back from here.
pub fn node_cert_dir(&self) -> PathBuf {
self.peer_cert_dir().join("identity")
}

/// The node's cache dir root — the data root the P2P content engine's download staging
/// (`<cache>/downloads`) + `.download.tmp` GC live under (shares the node's writability handling).
pub fn cache_dir_path(&self) -> &Path {
Expand Down
2 changes: 1 addition & 1 deletion crates/dig-node-core/src/peer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ use std::sync::Arc;
use serde_json::{json, Value};
use tokio::io::{AsyncReadExt, AsyncWriteExt};

use crate::{CachedCapsule, CapsuleStore, PeerNetwork};
use crate::{CachedCapsule, CapsuleStore, KeyManager, PeerNetwork};

// -- Constants ---------------------------------------------------------------------------------------

Expand Down
66 changes: 66 additions & 0 deletions crates/dig-node-core/src/seams/key_mgmt/key_manager.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//! Seam 7's public surface (#1285/#1303) — the node's MACHINE-key lifecycle: the persistent
//! §21.9 identity seed, the derived stable mTLS `peer_id`, and the on-disk cert directories the
//! L7 peer network's [`dig_nat::NodeCert`] lives under.
//!
//! **#908 boundary (foundational, preserved exactly by this carve):** this seam holds ONLY the
//! node's own MACHINE identity — never a user's DID/wallet signing key. A dig-app proves
//! possession of a profile's identity key over the IPC session (`crate::session`); that key never
//! crosses into the engine. `KeyManager` does not add, and must never grow, a user-key path.
//!
//! `KeyManager` is implemented by [`Node`] with the EXISTING method bodies (carved unchanged
//! from `lib.rs`, #1285 W1b-6) — a behaviour-preserving trait extraction, not a new
//! implementation, and NOT a `dig-keystore` crate adoption (a later wave, coordinated with the
//! key-management family). Plain `Send + Sync` (no async methods) but kept trait-shaped to match
//! the other seams' pattern, so it stays dyn-compatible for the future `Arc<dyn KeyManager>`
//! handle (W1c).

use std::path::PathBuf;

use crate::Node;

/// Seam 7 (key management) — the node's machine identity_seed/NodeCert lifecycle. See the module
/// doc for the #908 boundary this seam enforces.
pub trait KeyManager: Send + Sync {
/// The node's own `peer_id` (64-hex) = SHA-256(SPKI DER) of its PERSISTENT, CA-signed
/// [`NodeCert`](dig_nat::NodeCert), or `None` if no identity seed is configured. This is the mTLS
/// identity the node presents on every peer path (loaded from — or minted into — the node's cert
/// dir, so it is stable across restarts; see [`crate::peer::load_or_generate_node_cert`]).
fn peer_id_hex(&self) -> Option<String>;

/// The node's persistent identity seed, if configured — the source of the STABLE mTLS `peer_id`
/// for the L7 peer network (see [`crate::peer::load_or_generate_node_cert`]). `None` disables the
/// peer network (the node still serves the HTTP read path).
fn identity_seed_for_peer(&self) -> Option<[u8; 32]>;

/// The directory the L7 peer network keeps its TLS cert/key + peer address book under (a
/// `peer-net/` subdir of the cache dir, so it shares the node's data root + writability handling).
fn peer_cert_dir(&self) -> PathBuf;

/// The directory the node's PERSISTENT, CA-signed [`NodeCert`](dig_nat::NodeCert) identity
/// (`node.crt` + `node.key`, 0600) lives under — an `identity/` subdir of [`Self::peer_cert_dir`],
/// kept SEPARATE from dig-gossip's own `node.key` in `peer-net/` so the two never clobber each
/// other. This is the node's stable machine transport identity (#908, #1280); its `peer_id`
/// survives restarts because the cert is loaded back from here.
fn node_cert_dir(&self) -> PathBuf;
}

impl KeyManager for Node {
fn peer_id_hex(&self) -> Option<String> {
let seed = self.identity_seed?;
crate::peer::load_or_generate_node_cert(self.node_cert_dir(), &seed)
.ok()
.map(|cert| cert.peer_id().to_hex())
}

fn identity_seed_for_peer(&self) -> Option<[u8; 32]> {
self.identity_seed
}

fn peer_cert_dir(&self) -> PathBuf {
self.cache_dir.join("peer-net")
}

fn node_cert_dir(&self) -> PathBuf {
self.peer_cert_dir().join("identity")
}
}
11 changes: 11 additions & 0 deletions crates/dig-node-core/src/seams/key_mgmt/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//! Seam 7 — key management (#1285/#1303). Houses the [`KeyManager`] trait (the seam's public
//! surface — the node's MACHINE identity_seed/NodeCert lifecycle, carved unchanged from
//! `lib.rs`, #1285 W1b-6). The `dig-keystore` crate ADOPTION (the canonical keystore, #1024) is
//! a later wave, coordinated with the key-management family — out of scope here.
//!
//! **#908 boundary:** this seam is the machine-key/user-key boundary point. It NEVER holds a
//! user's DID/wallet signing key — see the module doc on [`key_manager::KeyManager`].

mod key_manager;

pub use key_manager::KeyManager;
1 change: 1 addition & 0 deletions crates/dig-node-core/src/seams/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ pub mod chia_peer;
pub mod content;
pub mod dig_peer;
pub mod dig_rpc;
pub mod key_mgmt;
Loading