Task
cargo test -p dig-app-core --lib cannot complete on a Windows dev machine. One test hangs
indefinitely and takes the whole harness process down with it, so a developer or lane running the
local suite gets no result at all — not a failure, a hang. Make the local suite terminate on Windows.
Context
crates/dig-app-core/src/control.rs:1160, a_user_configured_host_off_loopback_still_receives_the_token:
let listener = std::net::TcpListener::bind(("0.0.0.0", 0)).expect("bind");
let port = listener.local_addr().expect("addr").port();
let _ = post_json_to("0.0.0.0", port, b"{}", Some("super-secret-control-token"),
Duration::from_millis(300), EndpointTrust::UserConfigured);
let (mut stream, _) = listener.accept().expect("the configured node must be dialled");
let mut request = Vec::new();
stream.read_to_end(&mut request).expect("read the request");
Neither accept() nor read_to_end() carries a timeout, and read_to_end returns only at EOF —
i.e. only once the client end is fully closed. The 300ms budget passed to post_json_to bounds the
client's wait, not the server side's. Dialling the wildcard address 0.0.0.0 is also
platform-dependent: Linux routes it to localhost, Windows does not treat it the same way.
Measured on Windows 11, on a tree whose control.rs blob is byte-identical to main
(a13aa3033042ae0f4954282b252c4a53ab595140), so this is pre-existing and not introduced by any
branch:
- In a full
--lib run: has been running for over 60 seconds, then
test exited abnormally and cargo test exits 1 with no test result: line.
- In isolation with
timeout 300: exit 124 — still hung after five minutes.
CI is unaffected — Test + coverage (>=80% lines, gated) is SUCCESS on the same commit, because the
runner is Linux. That asymmetry is what makes this worth fixing rather than tolerating: the gate is
green while the local suite is unrunnable, so the failure only ever appears on a developer's machine.
Why this is worth a ticket rather than a shrug
A hang is indistinguishable from a dead lane. Three lanes on this repo died silently in one session
and the first hypothesis each time was a cap or a watchdog; a suite that hangs on the same machine
adds a second indistinguishable cause. It also means no Windows lane can use the local suite as
evidence — it must defer to CI for every claim.
Scope
The deliverable is a suite that terminates on Windows with a correct verdict. The likely fix is to
bound the server side — set_read_timeout on the accepted stream, and read to the end of the request
head rather than to EOF, since the assertion only inspects headers — and to dial 127.0.0.1 while
keeping the test's actual subject intact. The subject must be preserved: its whole point
(control.rs:1153-1158) is that an explicitly user-configured non-loopback node still receives the
token, which is the §5.3 direction where an over-strict fix would be a worse regression than the bug.
Its control test immediately above must keep failing if that guarantee is broken. Do not simply
#[cfg(not(windows))] it away — that would delete Windows coverage of a §5.3 guarantee.
Evidence required
A full cargo test -p dig-app-core --lib completing on Windows with a test result: line, plus the
mutation check that the preserved subject still fails when the token is withheld from a
UserConfigured endpoint.
Re-measured 2026-08-19 at sweep time — PARTIAL: the hang is MITIGATED, the ask is NOT satisfied
Carried into the body because a move to this repo does not bring comment history.
dig-app origin/main @ 8a146c1. The test is now at
crates/dig-app-core/src/control.rs:1184 and carries:
#[test]
#[cfg_attr(
windows,
ignore = "hangs on Windows: untimed accept()/read_to_end() on a 0.0.0.0 dial (dig_ecosystem#2705)"
)]
fn a_user_configured_host_off_loopback_still_receives_the_token() {
So the local suite now terminates on Windows — the acute symptom is gone. What has NOT been done
is the deliverable: the test body at :1185-1216 is unchanged, still
TcpListener::bind(("0.0.0.0", 0)), still an untimed accept(), still read_to_end() to EOF, still
dialling "0.0.0.0".
The mitigation's own doc comment (:1173-1178) states the remaining work verbatim:
"ignore rather than cfg(not(windows)) on purpose: the test still COMPILES on Windows, so it
cannot rot behind a cfg while the code it covers changes, and it can still be run there
deliberately with -- --ignored once the fix lands. … Un-skip by bounding THIS side —
set_read_timeout on the accepted stream, and read the request head rather than to EOF, since only
headers are asserted — and dialling 127.0.0.1."
A worse consequence than the ticket originally recorded also surfaced and is now fixed by the same
mitigation (:1169-1171): the wedged harness "ran the Native confirmer (windows-latest) job into
GitHub's six-hour ceiling on every merge to main after it landed." So this was not local-only.
What is left, and why it is not "just delete the ignore"
Windows coverage of a §5.3 guarantee is currently absent. The subject — an explicitly
user-configured non-loopback node still receives the control token — is the direction where an
over-strict fix is a worse regression than the bug. Its control test
(an_auto_discovered_host_off_loopback_is_refused_without_dialling, :1226) must keep failing if
that guarantee is broken.
Done condition: cargo test -p dig-app-core --lib completes on Windows with a test result: line
and this test runs there (no ignore), plus the mutation check that the preserved subject still
fails when the token is withheld from a UserConfigured endpoint.
Parent epic
https://github.com/DIG-Network/dig_ecosystem/issues/1533 (EPIC: drive the full dig-node/dig-app
system home).
kind:maintenance — a user cannot perceive the outcome. It is not blocking a named business
ticket today: the acute form (a six-hour CI job on every merge, and an unrunnable local suite) is
already mitigated, so what remains is restoring platform coverage rather than unblocking shipping.
Orchestrator ticket: https://github.com/DIG-Network/dig_ecosystem/issues/1533
Moved from DIG-Network/dig_ecosystem#2705 so this repo's own PR can close it with Closes (CLAUDE.md §1.3).
GitHub refuses a private-to-public issue transfer, so the body was copied and comment history
stayed on the original.
Task
cargo test -p dig-app-core --libcannot complete on a Windows dev machine. One test hangsindefinitely and takes the whole harness process down with it, so a developer or lane running the
local suite gets no result at all — not a failure, a hang. Make the local suite terminate on Windows.
Context
crates/dig-app-core/src/control.rs:1160,a_user_configured_host_off_loopback_still_receives_the_token:Neither
accept()norread_to_end()carries a timeout, andread_to_endreturns only at EOF —i.e. only once the client end is fully closed. The 300ms budget passed to
post_json_tobounds theclient's wait, not the server side's. Dialling the wildcard address
0.0.0.0is alsoplatform-dependent: Linux routes it to localhost, Windows does not treat it the same way.
Measured on Windows 11, on a tree whose
control.rsblob is byte-identical tomain(
a13aa3033042ae0f4954282b252c4a53ab595140), so this is pre-existing and not introduced by anybranch:
--librun:has been running for over 60 seconds, thentest exited abnormallyandcargo testexits 1 with notest result:line.timeout 300: exit 124 — still hung after five minutes.CI is unaffected —
Test + coverage (>=80% lines, gated)is SUCCESS on the same commit, because therunner is Linux. That asymmetry is what makes this worth fixing rather than tolerating: the gate is
green while the local suite is unrunnable, so the failure only ever appears on a developer's machine.
Why this is worth a ticket rather than a shrug
A hang is indistinguishable from a dead lane. Three lanes on this repo died silently in one session
and the first hypothesis each time was a cap or a watchdog; a suite that hangs on the same machine
adds a second indistinguishable cause. It also means no Windows lane can use the local suite as
evidence — it must defer to CI for every claim.
Scope
The deliverable is a suite that terminates on Windows with a correct verdict. The likely fix is to
bound the server side —
set_read_timeouton the accepted stream, and read to the end of the requesthead rather than to EOF, since the assertion only inspects headers — and to dial
127.0.0.1whilekeeping the test's actual subject intact. The subject must be preserved: its whole point
(
control.rs:1153-1158) is that an explicitly user-configured non-loopback node still receives thetoken, which is the §5.3 direction where an over-strict fix would be a worse regression than the bug.
Its control test immediately above must keep failing if that guarantee is broken. Do not simply
#[cfg(not(windows))]it away — that would delete Windows coverage of a §5.3 guarantee.Evidence required
A full
cargo test -p dig-app-core --libcompleting on Windows with atest result:line, plus themutation check that the preserved subject still fails when the token is withheld from a
UserConfiguredendpoint.Re-measured 2026-08-19 at sweep time — PARTIAL: the hang is MITIGATED, the ask is NOT satisfied
Carried into the body because a move to this repo does not bring comment history.
dig-app
origin/main@8a146c1. The test is now atcrates/dig-app-core/src/control.rs:1184and carries:So the local suite now terminates on Windows — the acute symptom is gone. What has NOT been done
is the deliverable: the test body at
:1185-1216is unchanged, stillTcpListener::bind(("0.0.0.0", 0)), still an untimedaccept(), stillread_to_end()to EOF, stilldialling
"0.0.0.0".The mitigation's own doc comment (
:1173-1178) states the remaining work verbatim:A worse consequence than the ticket originally recorded also surfaced and is now fixed by the same
mitigation (
:1169-1171): the wedged harness "ran theNative confirmer (windows-latest)job intoGitHub's six-hour ceiling on every merge to
mainafter it landed." So this was not local-only.What is left, and why it is not "just delete the ignore"
Windows coverage of a §5.3 guarantee is currently absent. The subject — an explicitly
user-configured non-loopback node still receives the control token — is the direction where an
over-strict fix is a worse regression than the bug. Its control test
(
an_auto_discovered_host_off_loopback_is_refused_without_dialling,:1226) must keep failing ifthat guarantee is broken.
Done condition:
cargo test -p dig-app-core --libcompletes on Windows with atest result:lineand this test runs there (no
ignore), plus the mutation check that the preserved subject stillfails when the token is withheld from a
UserConfiguredendpoint.Parent epic
https://github.com/DIG-Network/dig_ecosystem/issues/1533 (EPIC: drive the full dig-node/dig-app
system home).
kind:maintenance— a user cannot perceive the outcome. It is not blocking a named businessticket today: the acute form (a six-hour CI job on every merge, and an unrunnable local suite) is
already mitigated, so what remains is restoring platform coverage rather than unblocking shipping.
Orchestrator ticket: https://github.com/DIG-Network/dig_ecosystem/issues/1533
Moved from DIG-Network/dig_ecosystem#2705 so this repo's own PR can close it with
Closes(CLAUDE.md §1.3).GitHub refuses a private-to-public issue transfer, so the body was copied and comment history
stayed on the original.