Skip to content

fix: migrate aiosendspin adapters to Noise identity/pairing SDK API - #110

Closed
chrisuthe wants to merge 2 commits into
Sendspin:mainfrom
chrisuthe:pr2-aiosendspin-pairing-migration
Closed

fix: migrate aiosendspin adapters to Noise identity/pairing SDK API#110
chrisuthe wants to merge 2 commits into
Sendspin:mainfrom
chrisuthe:pr2-aiosendspin-pairing-migration

Conversation

@chrisuthe

Copy link
Copy Markdown
Member

Depends on #109

This PR is stacked on #109 (protocol-evidence verification foundation) and includes its commit in the diff until that one merges. Please review/merge #109 first; the diff here will shrink to just this PR'"'"'s changes once it does.

Why

The aiosendspin SDK dependency introduced a breaking change: it now requires a static X25519 Identity plus a pairing store of pre-established long-term PSK records, instead of the old server_id=/client_id= constructor kwargs. Without this fix, every aiosendspin-involving conformance case fails at connection time.

What

  • src/conformance/adapters/_aiosendspin_pairing.py (new): since conformance cases launch server and client as independent OS processes with no out-of-band pairing channel, this shared helper derives a deterministic (not cryptographically meaningful — documented in the module) Identity/PSK pair from the CLI-shared server_id/client_id so both sides agree on a pre-paired credential without a real pairing exchange.
  • aiosendspin_server.py:
    • Builds identity/pairing_store via the new helper; adds --client-id CLI arg.
    • Fixes negotiated_rolesnegotiated_role_ids SDK rename.
    • Bounds server.close() with a 5s timeout. Root cause: aiohttp'"'"'s AppRunner.cleanup() can block up to its 60s keep-alive shutdown_timeout for inbound (server-hosted) WebSocket connections — this only manifests in client-initiated scenarios, where the server holds the inbound socket. The case'"'"'s summary JSON has already been written successfully by that point, so a slow/timed-out close no longer fails the case.
  • aiosendspin_client.py: builds identity/pairing_store via the same helper; replaces the removed add_server_hello_listener callback with reading client.server_info directly for the peer_hello summary field.
  • runner.py: passes client_id to the server role'"'"'s CLI args so it can build the expected client'"'"'s pairing record.

Testing

  • python -m compileall src scripts
  • Verified via run_case() smoke tests (default 40s timeout): server-initiated-flac, server-initiated-pcm, server-initiated-metadata, server-initiated-controller, server-initiated-artwork, and client-initiated-pcm (previously hanging until the harness timeout due to the AppRunner.cleanup() issue above) all pass end-to-end, with client-initiated-pcm now completing in ~13s.

chrisuthe and others added 2 commits September 4, 2026 13:33
Introduce a protocol-evidence-based verification mode for conformance
scenarios so we can assert on Sendspin protocol compliance (hello
negotiation, role capability advertisement, stream setup handshake,
etc.) rather than only on rendered audio/media correctness.

- src/conformance/protocol.py: defines protocol assertion IDs and
  protocol_evidence_failure() to check adapter summaries against them.
- src/conformance/models.py: ScenarioSpec gains verification_mode
  support for 'protocol' and a protocol_assertions field.
- src/conformance/scenarios.py: registers the new baseline protocol
  scenario.
- src/conformance/runner.py: wires the 'protocol' verification_mode
  into _compare_summaries().
- README.md / adapters/README.md: document the protocol-evidence
  contract adapters must uphold.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The aiosendspin SDK now requires a static X25519 Identity plus a
pairing store of pre-established long-term PSK records instead of the
old server_id=/client_id= constructor kwargs. Since conformance cases
launch server and client as independent OS processes with no
out-of-band pairing channel, add a shared helper that derives a
deterministic (not cryptographically meaningful) Identity/PSK pair
from the CLI-shared server_id/client_id so both sides agree on a
pre-paired credential.

- src/conformance/adapters/_aiosendspin_pairing.py (new): shared
  identity/pairing_store derivation for both adapter roles.
- aiosendspin_server.py: build identity/pairing_store via the new
  helper, add --client-id CLI arg, fix negotiated_role_ids rename,
  bound server.close() with a timeout since aiohttp's AppRunner
  cleanup can block up to its 60s keep-alive shutdown_timeout in
  client-initiated scenarios even though the case summary was already
  written successfully.
- aiosendspin_client.py: build identity/pairing_store via the new
  helper, replace the removed add_server_hello_listener callback with
  reading client.server_info directly for the peer_hello summary
  field.
- runner.py: pass client_id to the server role's CLI args so it can
  build the expected client's pairing record.

Verified server-initiated-flac/pcm/metadata/controller/artwork and
client-initiated-pcm all pass end-to-end via run_case().

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@chrisuthe

Copy link
Copy Markdown
Member Author

Superseded: this exact fix (Identity/pairing_store migration + allow_unencrypted=True + bounded server.close() timeout) was already merged upstream in #94 and #96 (same root cause independently discovered/fixed). Closing as redundant; PR #109 (protocol-evidence foundation) does not depend on this.

@chrisuthe chrisuthe closed this Sep 4, 2026
@chrisuthe
chrisuthe deleted the pr2-aiosendspin-pairing-migration branch September 4, 2026 18:41
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.

1 participant