proto-socket/VERSIONING.md

6.7 KiB

Versioning

Proto Socket tracks protocol compatibility separately from language package versions.

Current Versions

  • Protocol version: 0.1
  • Dart package version: see dart/pubspec.yaml
  • Go module version: repository tag based

0.1 is the current compatibility contract for the checked-in available implementations. The wire format does not carry a protocol version field yet; compatibility is verified by shared proto definitions, unit tests, and cross-language tests.

Protocol 0.1 also allows optional application-level convention messages for capability announcement and request error reporting. These conventions do not change the required handshake or the PacketBase wire fields unless they are promoted in a later protocol version.

Protocol Version

The protocol version describes the wire-format and behavior contract that every language implementation must satisfy:

  • TCP uses a 4-byte big-endian payload length followed by one PacketBase protobuf payload.
  • WebSocket and WSS use one binary frame per PacketBase protobuf payload.
  • PacketBase.typeName routes the inner message by canonical protobuf full message name.
  • nonce increments for every outbound packet on a connection.
  • responseNonce links a response packet to the request nonce.
  • Heartbeat behavior follows PROTOCOL.md.

Breaking protocol changes require a new major protocol version. Backward-compatible additions keep the same major protocol version but must include updated tests before release.

Proto Package and Wire Identity

Proto package names are part of the wire identity because they prefix protobuf full message names. Package names must use lowercase snake_case segments joined by dots, for example proto_socket or example_chat.v1.

The canonical package for the shared packet schema is proto_socket. Common message identities therefore use values such as proto_socket.PacketBase, proto_socket.HeartBeat, and proto_socket.TestData; PacketBase.typeName carries the inner message identity.

Language-specific namespace options such as Go go_package or Java/Kotlin package names are package-generation details. They do not change the protocol package or wire typeName.

Git Release Standard

Current consumption and release flow is Git ref/tag based. Package registry publication is optional future work, not the current release standard.

Git releases must identify the repository ref/tag being consumed and use the full local validation matrix as the compatibility gate.

Package Version

Each language implementation may publish on its own package cadence if registry releases are later introduced. Package versions communicate implementation releases, bug fixes, and language-specific API changes.

A package release must state which protocol version it implements. A package version bump does not imply a protocol version bump unless the wire-format or required behavior changes.

Breaking Protocol Changes

Examples of breaking protocol changes:

  • Renaming or removing PacketBase fields.
  • Changing the canonical proto package or typeName derivation without a compatibility path.
  • Changing nonce or responseNonce semantics.
  • Changing heartbeat request/response timing or echo behavior in a way that disconnects older peers.
  • Changing TCP framing, byte order, max packet handling, or WebSocket binary-frame rules.

Non-breaking Protocol Changes

Examples of non-breaking changes:

  • Adding a new protobuf message type.
  • Adding optional fields to application messages when older peers can ignore them.
  • Adding a new language implementation that passes the existing protocol and cross-language tests.
  • Tightening tests or documentation without changing wire behavior.
  • Adding an optional hello/capability message that peers may ignore and that is not required before normal traffic.
  • Adding an optional standard error response convention, provided older peers can still fail by timeout or existing response type-mismatch behavior.

Backward-compatible message additions require updated parser maps and cross-language tests before release.

Optional Capability Announcement

ProtoSocketHello, or an equivalent project-specific message, is a candidate convention for announcing:

  • protocolVersion
  • stable capabilities tokens
  • optional implementation metadata

In protocol 0.1, this message is not a required handshake. A peer must be able to send and receive normal messages without first receiving a hello/capability message. Making a hello message mandatory, changing connection readiness semantics, or disconnecting older peers that do not send it requires a protocol-version review.

Standard Error Response Convention

ProtoSocketError, or an equivalent project-specific message, is a candidate convention for request handler failures. A supported error response should carry the original request nonce in responseNonce, a stable error code, a safe message, and optional detail/debug fields.

In protocol 0.1, implementations may continue to report handler failure as timeout, response type mismatch, or implementation-specific errors. Requiring all handlers to emit a shared error response, or requiring every requester to treat a particular error message type specially, requires parser map updates, cross-language tests, and compatibility review.

nonce Overflow

nonce and responseNonce fields are protobuf int32 values (signed 32-bit). The maximum emitted nonce is 2,147,483,647 (int32 max).

Current policy:

  • Implementations start at 1 and increment by 1 on every send call, including requests and responses.
  • After issuing 2,147,483,647, implementations reset the internal counter to 0; the next emitted PacketBase.nonce is 1.
  • 0 is reserved and must not be emitted as PacketBase.nonce, because responseNonce == 0 means "not a response".

Changing this wrap behavior or the reserved meaning of responseNonce == 0 changes nonce semantics and requires compatibility review and cross-language boundary tests.

New Language Compatibility

A new language implementation must target the current protocol version unless its README explicitly says otherwise. Before it is listed as available, it must:

  • Generate protobuf bindings from the canonical schema.
  • Use the same canonical protobuf full message name typeName values as the available implementations.
  • Keep language namespace/package options separate from the protobuf package used for wire identity.
  • Implement TCP, TLS+TCP, WS, and WSS framing consistently where the language runtime supports them.
  • Implement request-response correlation with nonce and responseNonce.
  • Handle heartbeat automatically inside the client/server core.
  • Pass same-language tests and cross-language tests against at least one available implementation.