Skip to content

fix: start the Noise handshake on a hivemind-core 5.x parameter message - #22

Merged
JarbasAl merged 1 commit into
devfrom
fix/accept-core5-shake-without-handshake-flag
Sep 13, 2026
Merged

JarbasAl merged 1 commit into
devfrom
fix/accept-core5-shake-without-handshake-flag

Conversation

@openvoiceos-bot

@openvoiceos-bot openvoiceos-bot commented Sep 13, 2026 •

Copy link
Copy Markdown
Contributor

🤖 Auto-generated by Claude Opus 5 (claude-opus-5) via Claude Code — NOT human-reviewed. Verify before acting.

Against hivemind-core 5.x the client never started the Noise handshake. It waited after HELLO until the caller timed out. This is the hivemind-test-harness micropython-e2e failure "Client did not reach STATE_READY within 10s (stuck in state 2)".

Governing clauses

JarbasHiveMind/architecture dev 56f5f9e, hivemind-crypto-1.md.

§3:

It is the single key-exchange
mechanism: a connection that cannot complete the Noise handshake is
rejected, and there is no unencrypted-session fallback and no
alternative key derivation.

§3.3, step 2:

  1. Server states connection parameters — HANDSHAKE, unencrypted:
    the server advertises its supported Noise patterns and
    suites (preference-ordered, §3.1), the encodings it offers and
    whether it supports binary framing (binarize;
    HIVEMIND-WIRE-1 §2–§3). This step also carries
    max_protocol_version, a capability hint a version-aware node reads
    to decide whether the peer supports the Noise handshake at all

The step names no handshake flag.

The defect

hivemind-core 5.1.3a1 sends this step-2 message, captured from a real hub:

{"max_protocol_version": 3, "binarize": false,
 "encodings": ["JSON-B64", "JSON-URLSAFE-B64", "JSON-B91", "JSON-Z85B", "JSON-Z85P", "JSON-B32", "JSON-HEX"],
 "ciphers": ["CHACHA20-POLY1305", "AES-GCM"],
 "noise": {"patterns": ["XXpsk2"], "suites": ["25519_ChaChaPoly_SHA256", "25519_AESGCM_SHA256"]}}

In _handle_handshake, the STATE_HELLO_RECEIVED branch began with if not payload.get("handshake"): return. That message has no handshake key, so the client returned before _should_use_noise ran. It sent nothing, recorded no error, and stayed in state 2. A spy on the live client confirmed this: _should_use_noise was never called, and last_error was None.

The change

  • hivemind/client.py: the guard now accepts a shake that carries the legacy handshake flag or a noise parameter dict. A shake with neither is still ignored. What happens next is unchanged: the client uses Noise when it holds a provisioned PSK and a mutual pattern and suite exist, and otherwise it refuses the hub unless legacy_hub=True.
  • README.md: the feature line said the key comes from the password through PBKDF2. That is only the legacy_hub path. It now describes the v3 Noise handshake with a provisioned PSK and links the existing Protocol v3 section.

Evidence

test/test_core5_shake.py feeds a HELLO and core 5.1.3a1's exact shake payload to a client with a provisioned PSK.

test on dev 1a015be here
test_a_core5_shake_starts_the_noise_handshake fails: client ignored the hub's shake (state 2) passes: it sends Noise message 1 (XXpsk2) and reaches STATE_HANDSHAKE_SENT
test_a_shake_without_noise_or_flag_is_still_ignored passes passes

Client suite, CPython 3.11: 92 passed.

Against a real hivemind-core 5.1.3a1 hub (hivescope 0.8.5a2), running the harness's tests/test_micropython_e2e.py and tests/test_embedded_clients.py:

  • this branch, with the harness change that provisions the PSK: 15 passed;
  • dev, with the PSK provisioned: 4 failed, stuck in state 2;
  • this branch, without a PSK: 4 failed, and the client logs refusing to fall back to the pre-v3 password handshake (HIVEMIND-CRYPTO-1 §3, §5). That refusal is correct.

The companion harness PR, JarbasHiveMind/hivemind-test-harness#56, provisions the PSK. The harness job checks out this repo's dev, so that job turns green once this PR merges.

Lint: hivemind/client.py has the same flake8 and ruff findings as on dev, and the new test file is clean.

🤖 Generated with Claude Code

hivemind-core 5.x sends its step-2 parameter HANDSHAKE with
max_protocol_version, binarize, encodings, ciphers and noise
{patterns, suites}, and no legacy "handshake" flag. HIVEMIND-CRYPTO-1 §3.3
step 2 defines that message by those parameters. The client returned early
unless payload["handshake"] was truthy, so it ignored the message, never
started the Noise handshake and stayed in STATE_HELLO_RECEIVED (2) until
the caller timed out. That is the hivemind-test-harness micropython-e2e
failure "stuck in state 2".

The guard now accepts a shake that carries the legacy flag or a noise
parameter dict. A shake with neither is still ignored.

The README feature line said the key comes from the password through
PBKDF2; that is only the legacy_hub path. It now describes the v3 Noise
handshake with a provisioned PSK.

test/test_core5_shake.py feeds a HELLO and core 5.1.3a1's exact shake
payload to a client with a provisioned PSK: on dev the client stays in
state 2; here it sends Noise message 1 (XXpsk2) and reaches
STATE_HANDSHAKE_SENT. Client suite: 92 passed. With this change and a
provisioned PSK, the harness micropython e2e and embedded tests pass
against a real hivemind-core 5.1.3a1 hub (15 passed).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 13, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

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 marked this pull request as ready for review September 13, 2026 06:58
@JarbasAl
JarbasAl merged commit b8a3966 into dev Sep 13, 2026
4 checks passed
@JarbasAl
JarbasAl deleted the fix/accept-core5-shake-without-handshake-flag branch September 13, 2026 06:58
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