mirror of
https://relay.ngit.dev/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit-grasp.git
synced 2026-10-05 15:08:24 +00:00
Production traffic containing unparseable client messages tore down the entire WebSocket connection. A single bad message - most visibly requests carrying invalid event IDs, failing deserialization with `Invalid input length 64` - propagated out of the relay's read loop and closed the session, so every affected client had to reconnect and re-subscribe. One malformed frame cost a client all of its live subscriptions, and clients that retried the same payload produced sustained connection churn. The defect was upstream in rust-nostr's local relay, not in ngit-grasp, and was reported as nostr:nevent1qqsqmmfv6fxk995yr5858eev7z6zmchchgmk90d4rffuuwe6ewcvx0cpz3mhxue69uhhyetvv9ujumn8d96zuer9wckedd82 and fixed by nostr:nevent1qqs24l0rv6qw3mdqdaj8nj4wlds2gy8a9wrqs3gj5kcmz27c8gm7kagpz3mhxue69uhhyetvv9ujumn8d96zuer9wc7gp6cp Deserialization failures are now contained inside the WebSocket loop and answered with a `NOTICE`, leaving the session and its subscriptions intact. Upgrade the NostrDevKit crates from 0.45.0-alpha.3 to 0.45.0-alpha.8, the first published release containing the fix. Inclusion was verified three ways rather than by release notes: upstream commit 7c0f3aa2cf2fbeb9f0067cb2349579754919eabd is an ancestor of the `Bump to v0.45.0-alpha.8` commit on upstream master; the alpha.8 crate downloaded from crates.io contains the repaired match arm in `src/local_relay/local/inner.rs`; and it also ships the upstream regression test `test_malformed_client_message_does_not_close_connection`, which drives a real WebSocket with a short-author REQ and asserts a subsequent valid REQ still reaches EOSE on the same socket. That upstream test covers the behaviour directly, so no equivalent test is duplicated here. All four rust-nostr crates move together to keep the tree off a mixture of alpha versions. `nostr-relay-builder` is gone: upstream merged it into `nostr-sdk` at alpha.4, so its imports become `nostr_sdk::local_relay` and `nostr_sdk::prelude`, and `nostr-sdk` now enables the `local-relay` feature. Three further alpha-to-alpha API removals are absorbed: `nostr::hashes` is no longer re-exported, so the `Sec-WebSocket-Accept` derivation depends on `bitcoin_hashes` directly - the same crate `nostr` still uses internally, so no second hash implementation enters the tree; `BoxedFuture` became crate-private, so `WritePolicy::admit_event` spells out its `Pin<Box<dyn Future<...>>>` return type; and `EventBuilder::text_note` was removed in favour of `EventBuilder::new(Kind::TextNote, ..)`, which affects test code only. These requirements are pinned exactly as `=0.45.0-alpha.n` rather than left as caret requirements. Cargo reads `"0.45.0-alpha.3"` as `^0.45.0-alpha.3`, which admits *any* later prerelease of 0.45.0 even though prereleases promise no compatibility - exactly the surprise reported against ngit in nostr:nevent1qqs0yvj4z302cjsnqx9jpp78jrfujhse0w47adjncwkxr922rjltk8spz3mhxue69uhhyetvv9ujumn8d96zuer9wcr42j8n where a declared alpha.2 resolved to alpha.7. This upgrade is direct evidence that the risk is real: alpha.4 deleted a whole crate this project depended on, which a caret requirement would have accepted silently. Pinning is safe because it only narrows resolution, and the committed `Cargo.lock` already selects these versions; what it adds is protection for builds that do not honour the lockfile - `cargo install`, and downstream consumers of the `ngit_grasp` library. The pins should be relaxed to caret requirements once 0.45.0 is released. Validated in the project Nix development shell with `CARGO_BUILD_JOBS=2`: `cargo fmt --all --check` clean, `cargo clippy --workspace --all-targets -D warnings` clean, and `cargo test --workspace --no-fail-fast` at 1937 passed / 32 failed. The 32 failures were confirmed pre-existing by running the identical suite on unmodified master in this environment: the same 1937/32 split and a byte-identical set of failing test names, so this upgrade introduces no regressions. All dependencies remain crates.io sources, so no `flake.nix` or `nix/module.nix` hashes required updating.