3-RRC: Wire Encoding, Constants, and Numeric Assignments

Version: 0.1.1

This document exists so that two people, writing two separate RRC implementations, do not accidentally invent two different protocols while both claiming success.

1-RRC explained what the system is. 2-RRC explained what messages exist and how sessions behave. This document locks down the numbers, field keys, and expectations that appear on the wire so that CBOR blobs mean the same thing everywhere.

If you skip this document, your implementation will still work, but only with itself. That is not a victory.

Canonical Encoding Rules

All RRC messages are encoded as CBOR maps. The map keys are unsigned integers. String keys are not allowed. This is not because strings are evil, but because numeric keys are smaller, faster to parse, and harder to misspell.

All integer values are encoded as unsigned integers unless explicitly stated otherwise. Binary values are encoded as CBOR byte strings. Human-readable text is encoded as CBOR text strings using UTF-8.

Ordering of keys in the CBOR map does not matter. Receivers must not assume any specific ordering and must not reject messages solely because the sender arranged keys differently.

Unknown keys must be ignored. This is not optional. If your implementation explodes because it saw a field it did not understand, that is your fault.

Envelope Structure

Every RRC message shares the same top-level envelope. This envelope is a CBOR map containing the following fields.

Field 0 - Protocol Version

This value identifies the RRC protocol version used to encode the message. For this specification, the value must be 1. Messages with other versions may be ignored or rejected.

Field 1 - Message Type

This is an unsigned integer identifying what kind of message this is. The numeric values for message types are defined later in this document.

Field 2 - Message Identifier

This is a byte string chosen by the sender. It must be unique within the scope of the sender’s current session. It does not need to be globally unique, cryptographically strong, or persistent across reconnects. It exists so implementations can correlate messages if they care to.

Field 3 - Timestamp

This is an unsigned integer representing milliseconds since the Unix epoch, according to the sender’s clock. It is advisory only. No one is expected to agree on time.

Field 4 - Sender Identity

This is a byte string containing the Reticulum identity hash of the sender. This field is mandatory even though the Link already authenticates the peer, because forwarded messages need an explicit source identifier.

Field 5 - Room Name

This is a text string identifying the room the message applies to. If a message does not apply to a room, this field may be omitted.

Field 6 - Body

This field contains the payload of the message. Its structure and meaning depend entirely on the message type.

Field 7 - Nickname

This is an optional text string containing a human-readable nickname for the sender.

It is advisory only. It may be omitted, empty, ridiculous, or all three. The hub may ignore it, sanitize it, replace it, or drop it on the floor entirely. Clients may display it if present, or may choose to rely on identity hashes, locally cached labels, or whatever else they think is a good idea.

If both sides send this field, they are not negotiating. They are making suggestions.

No other top-level fields are defined by this document.

Envelope field keys 0 through 39 are reserved for core protocol use. Extensions may define additional top-level fields using keys 40 through 63. Keys 64 and above are reserved for future specifications, which is a polite way of saying “don’t squat there unless you enjoy avoidable pain.”

Message Type Assignments

Message type values are fixed. They are not suggestions.

Type

Name

1

HELLO

2

WELCOME

10

JOIN

11

JOINED

12

PART

13

PARTED

20

MSG

21

NOTICE

30

PING

31

PONG

40

ERROR

10 - 19: Room Membership Messages

Type 10 - JOIN

The JOIN message uses type 10. This message is sent by the client to request entry into a room.

Type 11 - JOINED

The JOINED message uses type 11. This message is sent by the hub to confirm room membership.

Type 12 - PART

The PART message uses type 12. This message is sent by the client to leave a room.

Type 13 - PARTED

The PARTED message uses type 13. This message is sent by the hub to confirm that a client has left a room.

20 - 29: Messages Intended for Rooms and People

Type 20 - MSG

The MSG message uses type 20. This message carries chat content intended for a room.

Type 21 - NOTICE

The NOTICE message uses type 21. This message carries informational or non-conversational content.

40 and Up: Error and Status Messages

Type 40 - ERROR

The ERROR message uses type 40. This message reports a failure or refusal.

Values from 0 to 63 are reserved for core protocol use. Values from 64 upward are available for extensions, experiments, and future specifications. If you collide with yourself there, that is your own adventure.

Message Body Definitions

The body field exists so message-specific data does not leak into the envelope and turn everything into a special case.

For HELLO, the body is a CBOR map with unsigned integer keys. It may contain session-specific data used for exchanging version information or program capabilities, as well as human-facing metadata.

All body fields are advisory and optional. Any human-facing metadata is considered an extension of the protocol and is outside the scope of this specification.

HELLO body key assignments:

Key

Name

Type

Description

0

Client Name

text string

Client software name (optional)

1

Client Version

text string

Client version string (optional)

2

Capabilities

map/array

Capability hints (optional)

For WELCOME, the body is also a CBOR map with unsigned integer keys. It may contain session-specific data used for exchanging version information or program capabilities, as well as human-facing metadata.

All body fields are advisory and optional. Any human-facing metadata is considered an extension of the protocol and is outside the scope of this specification.

WELCOME body key assignments:

Key

Name

Type

Description

0

Hub Name

text string

Human-friendly hub name

1

Hub Version

text string

Hub version string (optional)

2

Capabilities

map/array

Capability hints (optional)

Unknown body keys must be ignored. Keys 0 through 63 are reserved for core body fields defined by this document. Keys 64 and above may be used for extensions.

For JOIN, the body is empty or omitted. The room name is taken from the envelope field.

For JOINED, the body may contain a list of current members. If present, this list is advisory and not guaranteed to be complete or current.

For PART, the body is empty or omitted.

For PARTED, the body may be empty, omitted, or may contain a list of remaining members. If you are hoping for perfect presence, you are in the wrong document.

For MSG, the body contains the message payload. The simplest and most common form is a text string. Implementations may choose to use structured payloads, but hubs must treat the body as opaque data and forward it unchanged.

For NOTICE, the body follows the same rules as MSG but carries a different semantic meaning.

For PING and PONG, the body may be omitted or may contain arbitrary data to allow round-trip correlation. Receivers must echo the body back unchanged in the corresponding response if it is present.

For ERROR, the body should be a text string describing the error in plain language. It may optionally be a CBOR map if structured error information is desired, but clients must handle simple text at minimum.

Room Name Normalization

Room names are encoded as text strings. Hubs should normalize room names internally, typically by converting them to lowercase. The exact normalization method is an implementation detail, but the observable behavior should be case-insensitive room matching.

Clients should not assume that room names preserve original casing.

Identity Encoding

The sender identity field contains the Reticulum identity hash encoded as a CBOR byte string. No additional structure is imposed by RRC.

Clients and hubs must not reinterpret, truncate, or re-encode this value. It is passed through as-is and treated as opaque data.

Error Handling on the Wire

Malformed messages may be ignored. Messages with unknown message types must be ignored. Messages with missing required envelope fields may be ignored or may trigger an ERROR, at the receiver’s discretion.

If a hub sends an ERROR and then closes the Link, that is considered valid behavior. Clients should not attempt to argue with a closed socket.

Forward Compatibility Rules

Implementations must follow three simple rules to remain compatible over time.

They must ignore unknown envelope keys. They must ignore unknown message types. They must not repurpose existing numeric assignments.

Breaking any of these rules means you are no longer speaking RRC, regardless of how confident you feel.

Tabular Examples

The following table summarizes the structure of RRC messages.

Field Number

Field Name

Description

0

Protocol Version

Unsigned integer identifying the protocol version

1

Message Type

Unsigned integer identifying the message type

2

Message ID

Byte string chosen by the sender

3

Timestamp

Unsigned integer representing milliseconds since the Unix epoch

4

Sender Identity

Byte string containing the Reticulum identity hash

5

Room Name

Text string identifying the room (optional)

6

Body

Message-specific payload (structure depends on message type)

7

Nickname

Optional, advisory human-readable sender nickname


The following table summarizes the message type assignments (Field 1).

Type

Name

Description

0

RESERVED

Reserved; must not be used

1

HELLO

Client announces itself to the hub

2

WELCOME

Hub acknowledges and accepts the session

10

JOIN

Client requests entry into a room

11

JOINED

Hub confirms room membership

12

PART

Client leaves a room

13

PARTED

Hub confirms room departure

20

MSG

Chat message intended for a room

21

NOTICE

Informational message

30

PING

Check whether the peer is responsive

31

PONG

Response to a PING

40

ERROR

Report a failure or refusal


The following table is an example of a client sending a chat message to a room.

Field Number

Field Name

Value

0

Protocol Version

1

1

Message Type

20 (MSG)

2

Message ID

b”\x01\x02\x03\x04”

3

Timestamp

1700000000000

4

Sender Identity

b”\xAA\xBB\xCC\xDD\xEE\xFF”

5

Room Name

“#general”

6

Body

“Hello, world!”

7

Nickname

“alice”