Two pre-release fixes found during audit.
1) GroupKeyDistribute admin forgery (critical)
`group_key_distribution::try_apply_distribution_post` trusted the
`admin` field inside the decrypted payload without verifying it
matched the post's author. Exploit: any peer who learns a victim's
posting NodeId (public — appears as a recipient on any DM/group
post) and observes a target group_id in the wild could craft an
encrypted distribution post claiming to be from the legitimate
admin. The victim's storage uses INSERT OR REPLACE on group_keys,
so a successful forgery would overwrite the victim's legitimate
group key record and stored seed, breaking future rotations / key
distributions from the real admin.
Fix: reject the distribution post when `content.admin != post.author`.
Added test `forged_admin_is_rejected` that seeds a legitimate
record, attempts a forgery, and asserts the legitimate record is
untouched.
2) Cap concurrent port-scan hole punches at 1 (bandwidth)
`hole_punch_with_scanning` fires ~100 QUIC ClientHellos/sec for up
to SCAN_MAX_DURATION_SECS (300s), ~1 Mbps per active scanner. With
no cap, the growth loop / anchor referrals / replication paths
could spawn several scanners at once and drive sustained multi-Mbps
upload — particularly pathological on obfuscated VPNs where every
probe stalls at a proxy timeout, explaining the reported 10 Mbps
sustained upload after anchor connect.
Fix: module-level `tokio::sync::Semaphore(1)` guarding entry to the
scanning loop. Second-and-beyond callers fall back to the cheaper
`hole_punch_parallel` (standard punching, no 100/sec port walk)
instead of spawning another scanner. Permit is held for the scanner
lifetime and released on return. Added unit test
`scanner_semaphore_caps_concurrent_scans_at_one`.
Both changes leave the successful-call path untouched (single scanner
still runs; legitimate key distributions still apply). 120 / 120 core
tests pass.