All three run in CI on every push, in a dedicated
native-protocol job separate
from the TypeScript test job (see .github/workflows/ci.yml).
What each baseline implements
Each SDK exposes the same small surface, matching the TypeScriptProtocolAdapter used by conformance:
- Canonical JSON — deterministic serialization with sorted object keys and no insignificant whitespace, so two implementations produce byte-identical output for the same logical value.
- CLX1 framing — a 4-byte big-endian length prefix followed by the
canonical JSON payload (
sdks/rust/src/lib.rs::encode_frame,CrosslinkProtocol.encodeFramein Kotlin/Swift). - Incremental frame decoding — a decoder that can be fed partial byte chunks (as they arrive off a socket) and yields complete messages once a full frame is buffered, enforcing the max-frame-size limit before allocating.
- Protocol version checks — rejecting a frame whose
vfield isn’t the supported CLX1 version. - Shared fixtures — the same
messages-v1.jsonandinvalid-v1.jsoncorpus every language SDK is checked against.
CrosslinkValue hierarchy,
Swift walks Any/NSNumber/NSNull, Rust uses serde_json::Value. Only the
serialized bytes need to match, not the in-memory representation.
What they deliberately do not implement yet
These packages are protocol foundations, not feature-parity clients. They do not currently include:- Transport selection — no WebSocket/WebRTC client, no LAN vs. relay candidate racing (see Networking)
- The CLX1 handshake — no X25519/Ed25519 key exchange, no hybrid PQ support (see Encryption and Hybrid post-quantum exchange)
- Pairing UI — no QR/code entry flow, no SAS verification
- Persistent identity — no keychain/keystore-backed device identity across restarts
- Reconnect policy — no backoff, no session resumption
Adding a language
- Implement canonical JSON and the 4-byte big-endian frame length prefix.
- Enforce frame-size and protocol-version limits before allocating memory for the payload — the negative fixtures include an oversized-frame case specifically to catch implementations that decode first and check second.
- Port every fixture from
packages/protocol/fixtures/messages-v1.jsonandpackages/conformance/fixtures/invalid-v1.jsonwithout changing them — fixtures are generated from (and only ever edited alongside) the TypeScript reference inpackages/protocol. - Assert the exact stable error code (
parse_error,version_unsupported,invalid_message, …) for every negative fixture, not just “an error was thrown.” - Add the SDK’s test command to
.github/workflows/ci.yml’snative-protocoljob before implementing transports or crypto, so conformance regressions are caught from the first commit.