Skip to content

feat(dig-node): canonical node-control contract + uncommon default port 9778 - #5

Merged
MichaelTaylor3d merged 1 commit into
mainfrom
feat/node-control-contract-uncommon-port
Jul 6, 2026
Merged

feat(dig-node): canonical node-control contract + uncommon default port 9778#5
MichaelTaylor3d merged 1 commit into
mainfrom
feat/node-control-contract-uncommon-port

Conversation

@MichaelTaylor3d

Copy link
Copy Markdown
Contributor

What

Two coordinated changes to the dig-node OS-service shell:

  1. Canonical node-control contract (fix(peer): keep a later source's novel reach-hint when an earlier source fills the cap #130). Establishes SPEC.md §7 as the ONE node-control interface every controller speaks (the dig-chrome-extension node UI, the DIG Browser "My Node" surface, the CLI, any local tool) — the cross-repo source of truth the extension conforms to (mirrored in the superproject SYSTEM.md).
  2. Uncommon default port (docs(spec): correct the dig-node-core P2P dependency list to match Cargo.toml #132). Moves the default localhost port off the collision-prone 8080 to the uncommon high port 9778.

Why

  • The extension and dig-node must speak ONE control interface (parity). Audit found they already agree — this PR pins that agreement so a one-sided dig-node change can't silently break the extension, and documents it authoritatively.
  • 80/8080 are the most collision-prone ports on a dev machine; 9778 is clear of the common-dev set, is the dig-wallet API's 9777 sibling, and matches the local-node port the digstore §5.3 resolver already expects (DEFAULT_LOCAL_NODE_PORT) — turning a known cross-repo drift into alignment.

Changes

Control contract (#130):

  • SPEC §7 reframed as the canonical cross-repo interface; new §7.7 consumer conformance (open status/discovery surface vs token-gated control.*; the MV3 token-reachability constraint; lifecycle is CLI/OS-service, not RPC; control.status field names are a stable contract) and §7.8 integration-test launch surface (clean dig-node run a consumer e2e can spawn → poll /health → drive control → stop).
  • New integration tests (crates/dig-node-service/tests/server.rs) pin the exact extension-consumed shape: control.status emits hosted_store_count/pinned_store_count/cached_capsule_count/cache.used_bytes/sync.available/upstream; control.* w/o token → -32030 UNAUTHORIZED; GET /health carries the open probe contract.

Uncommon port (#132):

  • DEFAULT_PORT 8080 → 9778 (DIG_NODE_PORT override preserved; dig.local:80 unaffected). Updated across config.rs/meta.rs/server.rs/cli.rs + SPEC/README/USER_JOURNEY.
  • Consumers that must follow (routed separately by the orchestrator): extension server.host default + §5.3 localhost tier, dig-installer, DIG Browser in-process.

Release wiring: set root [workspace.package].version (which the tag-on-merge + version-increment CI read) and make dig-node-service inherit it, so the released binary version, the tag, and the gate read one version. This repo's changelog-tag.yml/ensure-version-increment.yml read [workspace.package].version from the root manifest, which was previously unset (tag-on-merge would no-op); this populates it.

Blast radius

Confined to dig-node-service (the shell). dig-node-core/dig-runtime/dig-wallet untouched. The port default is consumed by the §5.3 ladder in sibling repos (extension/installer/browser) — coherence-completed there on their lanes. No public API removed/renamed.

Version bump

0.4.1 → 0.5.0 (minor). Pre-1.0: a changed default (the port) is a behavior change → minor in 0.x semver; also carries the new SPEC contract + conformance tests. No public API break.

Verified

  • cargo fmt --all -- --check clean
  • cargo clippy -p dig-node-service --all-targets --locked -- -D warnings clean
  • cargo test green — 28 server integration tests (incl. 3 new conformance guards) + all unit tests

Refs #130 (dig-node half; extension side conforms on its lane), #132 (dig-node side; consumers follow).

…rt 9778
Establish §7 of SPEC.md as the ONE canonical node-control interface every
controller speaks (the dig-chrome-extension node UI, the DIG Browser "My Node"
surface, the CLI) and pin the extension-consumed shape so the two repos stay in
parity (#130); move the default localhost port off the collision-prone 8080 to
the uncommon high port 9778 (#132).
Control contract (#130):
- SPEC §7 reframed as the canonical cross-repo control interface + a new §7.7
(consumer conformance) and §7.8 (integration-test launch surface): the OPEN
status/discovery surface (GET /health + read methods, no token) vs the
token-gated control.* management plane; the token-reachability constraint (a
sandboxed MV3 extension cannot read <config_dir>/control-token, so it is
limited to status + gets UNAUTHORIZED on control.* and defers management to a
same-host process controller); lifecycle (start/stop/restart) is the CLI/
OS-service contract, NOT an RPC; and control.status field names are a stable
consumer contract.
- New integration tests pin the exact shape the extension consumes:
control.status emits hosted_store_count/pinned_store_count/
cached_capsule_count/cache.used_bytes/sync.available/upstream;
control.* without a token returns -32030 UNAUTHORIZED; GET /health carries the
open status probe contract. A one-sided dig-node change now fails these guards.
Uncommon port (#132):
- DEFAULT_PORT 8080 -> 9778 (DIG_NODE_PORT override preserved; dig.local :80
unaffected). 9778 is clear of the common-dev set (80/443/3000/5000/8000/8080/
8888/9000), is the dig-wallet API's 9777 sibling, and matches the local-node
port the digstore §5.3 resolver already expects (DEFAULT_LOCAL_NODE_PORT).
Updated the default across config/meta/server/cli + SPEC/README/USER_JOURNEY.
Consumers that must follow (routed separately): extension server.host default
+ §5.3 localhost tier, dig-installer, DIG Browser in-process.
Release wiring: set root [workspace.package].version (which the tag-on-merge +
version-increment CI read) and make dig-node-service inherit it, so the released
binary version, the tag, and the gate all read one version. Bumped 0.4.1 -> 0.5.0
(minor, pre-1.0: a changed default is a behavior change; also carries the new
SPEC contract + conformance tests; no public API removed).
Verified: cargo fmt --all --check clean; clippy -p dig-node-service
--all-targets -D warnings clean; cargo test green (28 server integration + unit).
@MichaelTaylor3d
MichaelTaylor3d merged commit fa7c55a into mainJul 6, 2026
9 checks passed
@MichaelTaylor3d
MichaelTaylor3d deleted the feat/node-control-contract-uncommon-port branch July 6, 2026 17:19
MichaelTaylor3d added a commit that referenced this pull request Jul 10, 2026
…rt 9778 (#5)
Establish §7 of SPEC.md as the ONE canonical node-control interface every
controller speaks (the dig-chrome-extension node UI, the DIG Browser "My Node"
surface, the CLI) and pin the extension-consumed shape so the two repos stay in
parity (#130); move the default localhost port off the collision-prone 8080 to
the uncommon high port 9778 (#132).
Control contract (#130):
- SPEC §7 reframed as the canonical cross-repo control interface + a new §7.7
(consumer conformance) and §7.8 (integration-test launch surface): the OPEN
status/discovery surface (GET /health + read methods, no token) vs the
token-gated control.* management plane; the token-reachability constraint (a
sandboxed MV3 extension cannot read <config_dir>/control-token, so it is
limited to status + gets UNAUTHORIZED on control.* and defers management to a
same-host process controller); lifecycle (start/stop/restart) is the CLI/
OS-service contract, NOT an RPC; and control.status field names are a stable
consumer contract.
- New integration tests pin the exact shape the extension consumes:
control.status emits hosted_store_count/pinned_store_count/
cached_capsule_count/cache.used_bytes/sync.available/upstream;
control.* without a token returns -32030 UNAUTHORIZED; GET /health carries the
open status probe contract. A one-sided dig-node change now fails these guards.
Uncommon port (#132):
- DEFAULT_PORT 8080 -> 9778 (DIG_NODE_PORT override preserved; dig.local :80
unaffected). 9778 is clear of the common-dev set (80/443/3000/5000/8000/8080/
8888/9000), is the dig-wallet API's 9777 sibling, and matches the local-node
port the digstore §5.3 resolver already expects (DEFAULT_LOCAL_NODE_PORT).
Updated the default across config/meta/server/cli + SPEC/README/USER_JOURNEY.
Consumers that must follow (routed separately): extension server.host default
+ §5.3 localhost tier, dig-installer, DIG Browser in-process.
Release wiring: set root [workspace.package].version (which the tag-on-merge +
version-increment CI read) and make dig-node-service inherit it, so the released
binary version, the tag, and the gate all read one version. Bumped 0.4.1 -> 0.5.0
(minor, pre-1.0: a changed default is a behavior change; also carries the new
SPEC contract + conformance tests; no public API removed).
Verified: cargo fmt --all --check clean; clippy -p dig-node-service
--all-targets -D warnings clean; cargo test green (28 server integration + unit).
Co-Authored-By: Claude <noreply@anthropic.com>
MichaelTaylor3d added a commit that referenced this pull request Jul 10, 2026
…rt 9778 (#5)
Establish §7 of SPEC.md as the ONE canonical node-control interface every
controller speaks (the dig-chrome-extension node UI, the DIG Browser "My Node"
surface, the CLI) and pin the extension-consumed shape so the two repos stay in
parity (#130); move the default localhost port off the collision-prone 8080 to
the uncommon high port 9778 (#132).
Control contract (#130):
- SPEC §7 reframed as the canonical cross-repo control interface + a new §7.7
(consumer conformance) and §7.8 (integration-test launch surface): the OPEN
status/discovery surface (GET /health + read methods, no token) vs the
token-gated control.* management plane; the token-reachability constraint (a
sandboxed MV3 extension cannot read <config_dir>/control-token, so it is
limited to status + gets UNAUTHORIZED on control.* and defers management to a
same-host process controller); lifecycle (start/stop/restart) is the CLI/
OS-service contract, NOT an RPC; and control.status field names are a stable
consumer contract.
- New integration tests pin the exact shape the extension consumes:
control.status emits hosted_store_count/pinned_store_count/
cached_capsule_count/cache.used_bytes/sync.available/upstream;
control.* without a token returns -32030 UNAUTHORIZED; GET /health carries the
open status probe contract. A one-sided dig-node change now fails these guards.
Uncommon port (#132):
- DEFAULT_PORT 8080 -> 9778 (DIG_NODE_PORT override preserved; dig.local :80
unaffected). 9778 is clear of the common-dev set (80/443/3000/5000/8000/8080/
8888/9000), is the dig-wallet API's 9777 sibling, and matches the local-node
port the digstore §5.3 resolver already expects (DEFAULT_LOCAL_NODE_PORT).
Updated the default across config/meta/server/cli + SPEC/README/USER_JOURNEY.
Consumers that must follow (routed separately): extension server.host default
+ §5.3 localhost tier, dig-installer, DIG Browser in-process.
Release wiring: set root [workspace.package].version (which the tag-on-merge +
version-increment CI read) and make dig-node-service inherit it, so the released
binary version, the tag, and the gate all read one version. Bumped 0.4.1 -> 0.5.0
(minor, pre-1.0: a changed default is a behavior change; also carries the new
SPEC contract + conformance tests; no public API removed).
Verified: cargo fmt --all --check clean; clippy -p dig-node-service
--all-targets -D warnings clean; cargo test green (28 server integration + unit).
Co-Authored-By: Claude <noreply@anthropic.com>
MichaelTaylor3d added a commit that referenced this pull request Jul 13, 2026
…sts, 3-OS smoke CI
- install now clean-reinstalls (stop -> delete -> wait -> create) instead of a bare
create, so re-running it against an already-registered service no longer hits
Windows CreateService error 1073. It deliberately never auto-starts (unlike the
dig-dns pattern this mirrors) since the dig-installer issues its own start
afterward and treats a start failure as fatal.
- Windows: sc config sets the SCM display name to "DIG NETWORK: NODE" after create,
then sc qc reads it back to confirm the override actually took
(result.display_name_verified in --json).
- macOS postinstall now calls the binary's own idempotent `ensure-hosts` so
dig.local -> 127.0.0.2 is registered on .pkg install (Windows/.deb already did
this).
- New service-smoke CI job (windows-latest/macos-14/ubuntu-latest): build, install,
start, poll for serving, assert the Windows display name, install a second time to
prove no 1073, stop, uninstall, and assert the registration is gone.
- config::DEFAULT_PORT now sources dig_constants::DIG_NODE_PORT (single-sourced
#5.3 default) via a rev-pinned dig-constants 0.3.0 dependency, kept a cargo-
distinct source from dig-node-core's bare-git 0.2.x pin so the P2P crate chain
(dig-nat/dig-gossip/dig-dht/dig-onion) does not need to move in this PR.
- SPEC.md: document the display-name + clean-reinstall contract (#494), and the
previously-undocumented 9444 DIG_PEER_PORT P2P listener default.
Closes #494, refs #502.
Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@MichaelTaylor3d