Skip to content

fix: never fall back to the legacy handshake unless the operator sets legacy_hub - #20

Merged
JarbasAl merged 1 commit into
devfrom
fix/no-automatic-legacy-handshake
Sep 10, 2026
Merged

JarbasAl merged 1 commit into
devfrom
fix/no-automatic-legacy-handshake

Conversation

@openvoiceos-bot

Copy link
Copy Markdown
Contributor

🤖 Auto-generated by Claude Fable 5.1 (claude-fable-5-1) via Claude Code — NOT human-reviewed. Verify before acting.

Stacked on #19.

The client used to pick the pre-v3 password handshake on its own whenever the hub could not offer Noise: no PSK provisioned, a v2-capped hub, max_protocol_version set below 3, or no mutual pattern/suite. This PR removes that automatic choice. A hub that cannot complete Noise is now rejected outright — no shake response is ever sent for it — and the legacy handshake is reachable only through a new legacy_hub constructor option, off by default, that prints a loud, removal-dated warning at connect time. max_protocol_version below 3 now requires legacy_hub=True at construction, since it can only ever reach a hub through that same legacy path.

HIVEMIND-CRYPTO-1 §3: "The handshake is mandatory on every connection: there is no cleartext, pre-shared-key, or password alternative and no protocol-version ladder to negotiate down." §5: "A node MUST run the mandatory Noise handshake on every connection and reject any peer that cannot complete it, with no cleartext or legacy fallback (§3)."

The removal version is computed from hivemind/version.py's VERSION tuple as the next major (VERSION[0] + 1, currently 1.0.0), never hard-coded as a string.

Fail-before / green-after (.venv/bin/python -m pytest test -q -W default -p no:cacheprovider, run against this branch's own venv):

# source reverted, rewritten tests kept:
6 failed, 5 passed in 0.23s
  TestNoAutomaticLegacyFallback::test_no_psk_is_rejected            FAILED
  TestNoAutomaticLegacyFallback::test_v2_server_is_rejected         FAILED
  TestNoAutomaticLegacyFallback::test_client_capped_at_v2_requires_legacy_hub FAILED
  TestNoAutomaticLegacyFallback::test_no_mutual_suite_is_rejected   FAILED
  TestLegacyHubOptIn::test_legacy_hub_true_uses_legacy_path_regardless_of_hub_offer FAILED
  TestLegacyHubOptIn::test_legacy_hub_warning_names_removal_version FAILED

# fix restored:
87 passed, 5 warnings, 24 subtests passed in 14.20-14.88s

test/test_integration.py's existing handshake/bus/ping round-trip tests exercise a v0-v2-only mock hub, so they now pass legacy_hub=True explicitly rather than relying on the removed automatic fallback; nothing else in that suite changed. Baseline at the #19 head was 85 passed; this branch nets 87 (six legacy-fallback tests were rewritten as four rejection tests plus two opt-in tests).

Verified by execution: the fail-before/green-after transition above, the full suite pass count, and that no shake envelope is ever sent for a rejected hub (asserted directly in TestNoAutomaticLegacyFallback._assert_rejected). Verified by reading source: the exact clause text, quoted from JarbasHiveMind/architecture's hivemind-crypto-1.md §3 and its §5 conformance bullet list.

@coderabbitai

coderabbitai Bot commented Sep 10, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: cf78afcf-34d5-4be3-930d-11be3f630d1c


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@JarbasAl
JarbasAl force-pushed the fix/no-automatic-legacy-handshake branch from 6515a37 to 2ced00b Compare September 10, 2026 20:26
@JarbasAl
JarbasAl changed the base branch from fix/reject-malformed-frames to dev September 10, 2026 20:33
… legacy_hub

The client chose the pre-v3 password handshake automatically whenever the
hub could not offer Noise (no PSK, a v2-capped hub, max_protocol_version=2,
or no mutual pattern/suite), violating HIVEMIND-CRYPTO-1 §3 ("The handshake
is mandatory on every connection: there is no cleartext, pre-shared-key, or
password alternative and no protocol-version ladder to negotiate down") and
§5 ("A node MUST run the mandatory Noise handshake on every connection and
reject any peer that cannot complete it, with no cleartext or legacy
fallback").

A hub that cannot complete Noise is now rejected: no shake response is sent
and last_error names the violated clause. legacy_hub (default False) is the
only way to reach a legacy hub; setting it prints a loud warning at connect
time naming the pre-v3 handshake's lack of PAKE/forward secrecy and the
computed next-major removal version. max_protocol_version below 3 now
requires legacy_hub=True at construction time, since it can only ever reach
a hub through that same legacy path.

Fail-before: reverting the source (keeping the new tests) failed 6 of 6
rewritten tests, including a TypeError on the missing legacy_hub kwarg and
an AssertionError expecting rejection where the client instead sent a
plaintext shake. Restoring the fix: full suite 87 passed (baseline 85 at
PR #19's head, +2 net across replaced/added legacy-handshake tests).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@JarbasAl
JarbasAl force-pushed the fix/no-automatic-legacy-handshake branch from 2ced00b to e0ce20b Compare September 10, 2026 20:53
@JarbasAl
JarbasAl marked this pull request as ready for review September 10, 2026 21:05
@JarbasAl
JarbasAl merged commit 298ef53 into dev Sep 10, 2026
4 checks passed
@JarbasAl
JarbasAl deleted the fix/no-automatic-legacy-handshake branch September 10, 2026 21:05
Sign up for free to 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.

2 participants