Silicon DM Docs
DM / Contracts and compatibility
DM 0.6 adds groups. Release status

Contracts and compatibility

Package versions, HTTP versions, WebSocket frame versions, and the shared transport version are separate. Negotiate the contract your consumer implements.

Discover and negotiate

GET /api/v1/contracts returns service version, contract lifecycle state, and the compatibility matrix. Client::contracts() and dm contracts expose the same information. In a sandbox, supply its app secret; lifecycle counters are isolated.

Consumer HTTP contract Standalone frames Shared transport
DM client / CLI 0.5.x 1 3 1
DM client / CLI 0.4.x 1 3 Not used; standalone connection retained

HTTP clients send X-DM-Contract-Version: 1. Standalone WebSocket clients may send X-DM-Protocol-Version: 3; shared clients use version 1. Omitting a version retains the existing default. Unsupported or repeated version headers are rejected with 406 and compatibility information. Responses identify the selected versions.

Shared WebSocket v1

Open /api/v1/ws/shared once per backend. The server immediately sends:

{"type":"prewarmed","data":{"protocol_version":1,"max_subscriptions":64}}

Authenticate each subscription inside the encrypted connection, never in a URL:

{"type":"subscribe","data":{"subscription_id":"local-profile-id","token":"ACCESS-TOKEN","organization_id":"tos","actor_id":"cos:tos","device_id":"stable-device","testing_key":null,"testing_generation":null}}

For a sandbox, testing_key is its test app secret. Only that authenticated actor can use the subscription. Responses and commands use:

{"type":"channel","data":{"subscription_id":"local-profile-id","frame":{"type":"pong","data":{"ping_id":"PING-ID"}}}}

The inner frame is an unchanged WebSocket v3 frame. Each subscription receives its own ready, cursors, and generation. The outer transport also has its own ping/pong. Respond immediately at the same layer as the incoming ping. unsubscribe removes one subscription. Authentication failures do not confer access to any other subscription. The connection is bounded to 64 subscriptions; slow or overflowing clients disconnect and recover through durable replay.

Backward compatibility

Existing HTTP v1 and standalone WebSocket v3 consumers keep their shapes. Shared transport is an additive endpoint. Optional discovery fields do not change existing mandatory fields. Breaking changes require a new contract, explicit compatibility documentation, and consumer-driven tests; package SemVer alone is not a protocol negotiation mechanism.

The common HTTP and v3 envelope has exactly type and data, with message metadata inside data. Local callbacks intentionally have type, data, and metadata, as specified in the relay guide.

Deprecation and sunset

The contract_versions table exists separately in each plane. It tracks state, request count, last request, deprecation time, and sunset time. This is local contract lifecycle bookkeeping, not Space Station telemetry.

An operator first marks a supported predecessor deprecated and sets deprecated_at, after publishing a tested replacement. A deprecated contract is sunset after seven complete days with no requests, measured from the later of deprecation and last use. Never-used deprecated contracts use their introduction time and deprecation date. Active contracts are never retired just because a new deployment has no traffic. Open streams refresh last-use during heartbeats. The delivery worker performs retirement each minute; admission and discovery also check retirement. A sunset contract returns 410 and is never revived by late traffic. Keep its compatibility record for consumers.

Use a migration or operator database procedure to deprecate a release. This control is deliberately not an unauthenticated application endpoint. Example:

UPDATE contract_versions
SET status = 'deprecated', deprecated_at = clock_timestamp()
WHERE family = 'http' AND version = <REPLACED-VERSION> AND status = 'active';

Consumer-driven tests

tests/wire_contract.rs sends SDK-generated bytes to backend extractors and round-trips realtime frames independently. Contract tests cover unsupported and duplicate headers; integration tests exercise lifecycle and multiplexed routing. Run cargo test --workspace --all-targets --all-features before release.

Team of Silicons · Edit this page

Usage guides first. Protocol details when you need them.