Skip to content

[cpp-RCP-FS-05] Message.id uses a bespoke stream_key:byte_bus_id encoding instead of the canonical decimal scheme #88

Closed

Description

@SoundMatt

Location: include/rcp/adapt.hpp — endpoint_id_to_relay_id/relay_id_to_endpoint_id (~lines 73-111).

Finding: relay::Message.id is encoded here as "<stream_key as 16 lowercase hex digits>:<byte_bus_id as decimal>". Per this project's own tracked understanding of the relevant RELAY spec section, Message.id is supposed to be just the endpoint address (a decimal 0-255 string) on its own, with the stream/server identity carried separately, out-of-band from the ID field — the stream key isn't supposed to be folded into the ID string at all. The header's own comment already flags this as "this implementation's own encoding, not something the ... RELAY spec mandates a shape for," which lines up with the audit's read. Prepending the stream key changes the shape of every Message.id this library produces, which would break interoperability with anything (a golden-oracle test harness, another language port, etc.) expecting the spec's plain decimal-string form.

Recommendation: Encode Message.id as just the decimal byte_bus_id string per the spec, and carry the per-connection stream key out-of-band (e.g. in Message.meta, or scoped to the Caller/connection object) instead of folding it into the ID.

Verification: Independently re-read include/rcp/adapt.hpp against current HEAD (commit 4b9449a, 2026-07-29). Confirmed endpoint_id_to_relay_id builds exactly the "<16 hex>:<decimal>" string described, and relay_id_to_endpoint_id requires that exact shape to decode. This is a RELAY-spec-conformance claim (not a TC18 claim) that I'm relying on the project's own established understanding of §15.7.5/§8.5 for, since I did not re-derive it from a fresh read of the RELAY spec text in this pass — flagging this specific angle as worth a second look if there's any doubt about that section's current wording.

Filed from the 2026-07-29 ecosystem audit register; independently re-verified against current HEAD before filing.

Activity

  1. SoundMatt commented on Jul 30, 2026

    @SoundMatt
    OwnerAuthor

    Correction / likely REFUTED — please review before acting on this issue.

    After filing this, I got access to the actual RELAY spec text (§15.7.5) and re-read it more carefully. It turns out this finding is probably wrong, and I want to flag that rather than let it sit uncorrected.

    §15.7.5 says the plain-decimal ByteBusID encoding applies to the common case of adapting a single-stream client Controller. But it also has an explicit carve-out immediately after that table:

    An implementation whose Adapt-wrapped type can itself receive requests from more than one StreamID concurrently (e.g. adapting an RC Server rather than a single-stream client Controller) MUST extend ID's encoding to disambiguate the stream — this section does not mandate one fixed multi-stream ID format ... a conformant multi-stream encoding MUST be unambiguous, round-trip losslessly through ID, and be documented in the implementation's own Adapt doc comment.

    rcp/adapt.hpp's own doc comment states its Adapt() is explicitly built so "one adapter can address any number of distinct endpoints through the same underlying RequestFn" — i.e. it's the multi-stream case the spec is describing, not the single-stream case the plain-decimal table row covers. Checking cpp-RCP's "<16-hex stream_key>:<decimal byte_bus_id>" encoding against the three requirements the spec places on a multi-stream encoding:

    • Unambiguous: yes (fixed-width 16-hex-digit prefix + : + decimal digits, and relay_id_to_endpoint_id rejects anything not matching that shape).
    • Round-trips losslessly through ID: yes (endpoint_id_to_relay_id/relay_id_to_endpoint_id are inverses).
    • Documented in the Adapt doc comment: yes (the header comment describes exactly this scheme).

    So this looks like a case where the audit register I was working from (and I, in filing this) missed the multi-stream carve-out and treated the single-stream table row as the whole rule. I'd suggest closing this issue unless a maintainer disagrees with this reading of §15.7.5.

    (Unrelated to the above, while re-reading adapt.hpp I did notice RcpCallerAdapter::send/call decode stream_key from the message ID but never actually pass it to the wrapped RequestFn — only response_to_message on the return path uses it. That may be worth a separate look, but it's a different question from the ID-encoding-shape question this issue was originally about, and I haven't verified how big a problem it is, so I'm just flagging it here rather than filing a new issue for it.)

  2. SoundMatt commented on Jul 30, 2026

    @SoundMatt
    OwnerAuthor

    Fixed by #93 (merged), which was not auto-linked because the PR description's bold markdown around the issue numbers broke GitHub's closing-keyword parser.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions