test(marmot): refresh interop harness for restructured whitenoise-rs

whitenoise-rs became a workspace (core `whitenoise` crate at root, wn/wnd moved to
crates/whitenoise-cli) and grew native --discovery-relays / --default-account-relays
flags, which broke the headless harness's patch/build assumptions.

- Repath the mock-keyring patch to crates/whitenoise-cli/src/bin/wnd.rs and match the
  new main() (env-gated Whitenoise::initialize_mock_keyring_store(); the fn is pub
  under the integration-tests feature).
- Drop the discovery-env / defaults-env patches: start_daemon now passes the native
  --discovery-relays / --default-account-relays flags instead.
- Build wn/wnd via `cargo build -p whitenoise-cli --features whitenoise/integration-tests`
  (the binaries left the root crate; integration-tests brings in the mock keyring).
- The skip-unprocessable-retry patch still applies (root crate, 19-line offset).

Enables the end-to-end test_17_group_image_commit (amy sets a group icon -> whitenoise
must still process the commit) added in the previous commit to actually run.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JL3GXW1fmHa3xWfQjLLqfp
This commit is contained in:
Claude
2026-07-15 01:21:40 +00:00
parent 22582d6a97
commit e4c52a5553
4 changed files with 40 additions and 92 deletions
@@ -1,24 +0,0 @@
--- a/src/whitenoise/relays.rs
+++ b/src/whitenoise/relays.rs
@@ -98,6 +98,21 @@
}
pub(crate) fn defaults() -> Vec<Relay> {
+ // marmot-interop-headless patch: honour $WHITENOISE_DISCOVERY_RELAYS
+ // (comma-separated list) when present so newly created accounts only
+ // ever get our loopback relay baked into their NIP-65 / inbox /
+ // key-package lists. Without this override, `create-identity` stamps
+ // the hard-coded public set into the account's relay lists, and every
+ // later activate / publish burns connection budget on unreachable
+ // sockets — enough to break inbox-plane activation and drop kind:1059.
+ if let Ok(from_env) = std::env::var("WHITENOISE_DISCOVERY_RELAYS") {
+ let parsed: Vec<Relay> = from_env
+ .split(',').map(str::trim).filter(|s| !s.is_empty())
+ .filter_map(|u| RelayUrl::parse(u).ok())
+ .map(|url| Relay::new(&url))
+ .collect();
+ if !parsed.is_empty() { return parsed; }
+ }
let urls: &[&str] = if cfg!(debug_assertions) {
&["ws://localhost:8080", "ws://localhost:7777"]
} else {
@@ -1,23 +0,0 @@
--- a/src/relay_control/discovery.rs
+++ b/src/relay_control/discovery.rs
@@ -87,6 +87,20 @@
/// Initial curated relay set from the planning doc.
pub(crate) fn curated_default_relays() -> Vec<RelayUrl> {
+ // marmot-interop-headless patch: honour $WHITENOISE_DISCOVERY_RELAYS
+ // (comma-separated list) when present, so the harness can force wnd
+ // to use a loopback relay instead of the baked-in public set.
+ if let Ok(from_env) = std::env::var("WHITENOISE_DISCOVERY_RELAYS") {
+ let parsed: Vec<RelayUrl> = from_env
+ .split(',')
+ .map(str::trim)
+ .filter(|s| !s.is_empty())
+ .filter_map(|u| RelayUrl::parse(u).ok())
+ .collect();
+ if !parsed.is_empty() {
+ return parsed;
+ }
+ }
[
"wss://index.hzrd149.com",
"wss://indexer.coracle.social",
@@ -1,18 +1,17 @@
--- a/src/bin/wnd.rs
+++ b/src/bin/wnd.rs
@@ -22,6 +22,15 @@
--- a/crates/whitenoise-cli/src/bin/wnd.rs
+++ b/crates/whitenoise-cli/src/bin/wnd.rs
@@ -44,6 +44,14 @@ async fn main() -> whitenoise_cli::Result<()> {
let args = Args::parse();
let config = Config::resolve(args.data_dir.as_ref(), args.logs_dir.as_ref());
+ // marmot-interop-headless patch: allow sandboxes/CI without a real
+ // kernel keyring to fall back to the integration-tests mock keyring
+ // by setting $WHITENOISE_MOCK_KEYRING=1. Requires the daemon to be
+ // built with --features cli,integration-tests. No effect otherwise.
+ #[cfg(feature = "integration-tests")]
+ // marmot-interop-headless patch: allow sandboxes / CI without a real kernel
+ // keyring to fall back to the integration-tests mock keyring store by setting
+ // $WHITENOISE_MOCK_KEYRING=1. Requires building the binaries with
+ // `--features whitenoise/integration-tests` (the harness does).
+ if std::env::var("WHITENOISE_MOCK_KEYRING").is_ok() {
+ Whitenoise::initialize_mock_keyring_store();
+ }
+
let wn_config = WhitenoiseConfig::new(&config.data_dir, &config.logs_dir, KEYRING_SERVICE_ID);
Whitenoise::initialize_whitenoise(wn_config).await?;
let mut wn_config =
WhitenoiseConfig::new(&config.data_dir, &config.logs_dir, KEYRING_SERVICE_ID);
if !args.discovery_relays.is_empty() {
+30 -34
View File
@@ -52,32 +52,27 @@ preflight() {
2>&1 | tee -a "$LOG_FILE"
fi
# Four harness-only patches to wnd so it runs fully offline / in
# sandboxes that block outbound + kernel keyring:
# 1. discovery-env: honour $WHITENOISE_DISCOVERY_RELAYS so we can
# point wnd at our loopback relay instead of the baked-in public
# set. Without it wnd exits with NoRelayConnections.
# 2. mock-keyring: honour $WHITENOISE_MOCK_KEYRING so wnd uses the
# Two harness-only patches to whitenoise-rs so it runs in sandboxes that
# block the kernel keyring:
# 1. mock-keyring: honour $WHITENOISE_MOCK_KEYRING so wnd uses the
# integration-tests mock keyring store when the kernel keyutils
# syscalls are blocked (common in containers / CI).
# 3. defaults-env: reuse the same env var so `Relay::defaults()`
# (what `create-identity` stamps into the new account's NIP-65 /
# inbox / key-package lists) points at the loopback relay too.
# Without it every account wnd creates carries damus.io /
# primal.net / nos.lol, and every later activate / publish burns
# connection budget on unreachable sockets — enough to break the
# account-inbox subscription plane and drop kind:1059 delivery.
# 4. skip-unprocessable-retry: when mdk-core returns
# `MlsMessageUnprocessable` (pre-membership commit, too-old epoch)
# the message is provably undecryptable — retrying it ten times
# with exponential backoff (total ~17 min) just blocks later
# decryptable commits behind a queue of doomed retries, which in
# the harness manifests as "A already left" / "name unchanged"
# timeouts. The patch treats that error as terminal.
# syscalls are blocked (common in containers / CI). Compiled in via
# `--features whitenoise/integration-tests` on the build below.
# 2. skip-unprocessable-retry: when mdk-core returns a terminal MLS
# error (MlsMessageUnprocessable / PreviouslyFailed / MdkCoreError)
# the message is provably undecryptable — retrying it ten times with
# exponential backoff (~17 min) just blocks later decryptable commits
# behind a queue of doomed retries, which in the harness manifests as
# "A already left" / "name unchanged" timeouts. The patch treats those
# errors as terminal.
#
# The relay-override patches this harness used to carry (discovery-env /
# defaults-env) are gone: upstream wnd now takes native --discovery-relays
# and --default-account-relays flags (passed in start_daemon), which do the
# same job without patching. wn/wnd also moved into the crates/whitenoise-cli
# workspace member — the mock-keyring patch targets that path.
local -a patches=(
"whitenoise-discovery-env.patch"
"whitenoise-mock-keyring.patch"
"whitenoise-defaults-env.patch"
"whitenoise-skip-unprocessable-retry.patch"
)
# Apply each patch with a real exit-code check. The previous version
@@ -114,7 +109,8 @@ preflight() {
for attempt in $(seq 1 $max); do
step "building wn + wnd (attempt $attempt/$max, ~5 min first run)"
( cd "$WN_REPO" && \
cargo build --release --features cli,integration-tests --bin wn --bin wnd ) \
cargo build --release -p whitenoise-cli \
--features whitenoise/integration-tests --bin wn --bin wnd ) \
2>&1 | tee -a "$LOG_FILE"
[[ -x "$WN_BIN" && -x "$WND_BIN" ]] && break
[[ "$attempt" -lt "$max" ]] && warn "wn/wnd build failed (likely transient 503 from rustup or crates.io) — retrying"
@@ -243,17 +239,17 @@ start_daemon() {
-exec rm -rf {} + 2>/dev/null || true
fi
mkdir -p "$data_dir/logs" "$data_dir/release"
# Env vars consumed by the two harness-only wnd patches applied in
# preflight:
# WHITENOISE_DISCOVERY_RELAYS — forces the discovery plane at our
# loopback relay (kills the "can't reach nos.lol" exit path).
# WHITENOISE_MOCK_KEYRING — swaps in the integration-tests mock
# secret store so wnd doesn't fall over when the kernel blocks
# keyutils syscalls.
# Both are harmless on a real host with connectivity + a real keyring.
WHITENOISE_DISCOVERY_RELAYS="$RELAY_URL" \
WHITENOISE_MOCK_KEYRING=1 \
# --discovery-relays / --default-account-relays are native wnd flags that
# force both the discovery plane and freshly-created accounts' NIP-65 / inbox
# / key-package lists onto our loopback relay (kills the "can't reach nos.lol"
# exit path and stops accounts from carrying unreachable public relays).
#
# WHITENOISE_MOCK_KEYRING=1 is consumed by the mock-keyring patch: it swaps in
# the integration-tests mock secret store so wnd doesn't fall over when the
# kernel blocks keyutils syscalls. Harmless on a real host with a real keyring.
WHITENOISE_MOCK_KEYRING=1 \
nohup "$WND_BIN" --data-dir "$data_dir" --logs-dir "$data_dir/logs" \
--discovery-relays "$RELAY_URL" --default-account-relays "$RELAY_URL" \
>"$data_dir/logs/stdout.log" 2>"$data_dir/logs/stderr.log" &
local pid=$!
echo "$pid" > "$data_dir/pid"