xsp

The XAP Stream Protocol frame codec — a self-describing, self-delimiting frame [version · type · stream-id · principal-DID · flags · len · payload] that carries XAP over any transport. The payload is opaque bytes and the canonical binary encoding dogfoods CX `data-bin`. Identity is orthogonal to transport: the `principal` field names a DID, while verification and authorization remain separate concerns.

xsp:encode

[$xsp:encode] -> bytes — Encode a [frame …] element into wire bytes, data-bin-encoding the payload by default or UTF-8-encoding it when binary=false.

xsp:decode

[$xsp:decode] -> element — Decode one frame at offset 0 into a [frame …] element whose `consumed` attr is the total frame length so a reader can advance to the next frame.

xsp:decode-all

[$xsp:decode-all] -> element — Decode a buffer of concatenated frames into a [frames …] element whose children are the parsed [frame …] elements, with any trailing partial frame as a [remainder …] child.

xsp:auth-hello

[$xsp:auth-hello] -> element — Build the XSP-AUTH M1 hello from injected randomness (nonce, ephemeral X25519 public key), the dialed endpoint, and an optional initiator DID (absent = anonymous).

xsp:auth-challenge

[$xsp:auth-challenge] -> element — Responder side: validate M1 and build M2, signing the role-pinned transcript with the responder's Ed25519 seed — there is no anonymous responder.

xsp:auth-prove

[$xsp:auth-prove] -> element — Initiator side: verify M2 (selected version, channel-binding equality, responder transcript signature), derive the key schedule, and build M3 with the key-confirmation tag, the attach request, and — when a DID is claimed — the initiator transcript signature.

xsp:auth-confirm

[$xsp:auth-confirm] -> element — Responder side: verify M3 (initiator tag; transcript signature when a DID is claimed; anonymous refused under require-mutual), then build M4 carrying the responder key-confirmation tag and the attach result session.

xsp:auth-finish

[$xsp:auth-finish] -> element — Initiator side: verify M4's responder key-confirmation tag and return the [xsp-auth-established …] report with the responder DID, channel id, and bound session.

xsp:auth-transcript

[$xsp:auth-transcript] -> element — Assemble the signed transcript element — M1 verbatim plus M2 with its [sig] child stripped — the exact subject of both handshake signatures.

xsp:auth-keys

[$xsp:auth-keys] -> element — Derive the HKDF key schedule (confirmation tags, per-direction proof keys, channel id) from the ephemeral X25519 shared secret salted by both nonces; both sides derive identical values.

xsp:auth-verify

[$xsp:auth-verify] -> bool — Low-level transcript-signature check for one role; the initiator role additionally covers the responder's signature (transcript closure).

xsp:auth-rotate

[$xsp:auth-rotate] -> element — Produce a §6.3 rotation continuity proof: the outgoing key signs the incoming DID bound to the prior channel id, attesting the new key's holder held the old.

xsp:auth-rotate-verify

[$xsp:auth-rotate-verify] -> bool — Verify a rotation continuity proof against the outgoing key (offline-recovered from a did:key/did:peer old DID, or supplied for did:web).

xsp:auth-frame-check

[$xsp:auth-frame-check] -> string — Enforce the §4.8 post-handshake binding: an empty-principal frame inherits the session principal; a non-empty principal must equal it or the frame is rejected — the rule that makes the XSP principal field a checked label, never an identity source.

xsp:auth-proof

[$xsp:auth-proof] -> bytes — Compute the per-request possession proof for request/response transports: HMAC(key, counter-be8 concatenated with sha256(frame-bytes)).

xsp:auth-proof-verify

[$xsp:auth-proof-verify] -> bool — Verify a per-request possession proof in constant time; a counter below 1 never verifies.