Part 05 — Identity, Discovery, Onboarding and the Session ChannelLink to the section Part 05 — Identity, Discovery, Onboarding and the Session Channel

On this page

Maturity: Draft · Profiles: all

5.1 IdentityLink to the section 5.1 Identity

Every UNIVIP Device has:

Member Type Rule
device_id string Stable, globally unique, [A-Za-z0-9._~:-]{1,128}. RECOMMENDED form: urn:univip:<manufacturer>:<serial> or a UUID. MUST NOT change across firmware updates or re-onboarding. In a URL it is one path segment; : is a valid path character (RFC 3986 pchar) and is sent unencoded, and servers MUST also accept it percent-encoded (%3A).
manufacturer, model, serial_number, firmware_version string As for ONVIF GetDeviceInformation.
univip_version string Highest specification version implemented, e.g. 0.2.0.
remote_id object, optional { "serial": "...", "session_id": "..." } as broadcast under ASTM F3411 / EU Remote ID, if any, to let clients correlate with Remote ID receivers.
implementation_mode enum NATIVE, CONTROLLER, GATEWAY.
domain enum AIR, UNDERWATER, SURFACE, GROUND, MULTI. Selects which domain-specific members, commands and conformance groups apply.
gateway object, optional { "vendor": "...", "product": "...", "version": "...", "adapter": "mavlink" } when mode is GATEWAY.

Payloads carry payload_id unique within the device. Operations carry session_id (string), newly generated for each flight; see Part 07.

5.2 Discovery and onboardingLink to the section 5.2 Discovery and onboarding

A device learns its client endpoint by at least one of:

  1. Configured endpoint. The operator enters the client's UNIVIP endpoint URL and credentials into the device, dock, controller or gateway. REQUIRED for all devices.
  2. Claim code. The device displays or prints a short-lived claim code (or QR code) encoding univip://claim?endpoint=<url>&code=<code>; the client-side enrollment service exchanges it for device credentials (Part 13 §13.3). RECOMMENDED for consumer-friendly onboarding.
  3. DNS-SD on the local network. Devices on a LAN SHOULD advertise _univip._tcp with TXT records id=<device_id>, v=<univip_version>, profiles=S,C, path=/univip/v1. Clients MAY browse for this service and offer the operator a one-click onboarding that supplies the configured endpoint. A device MUST NOT grant access to anyone merely because they discovered it.

ONVIF WS-Discovery is NOT used by UNIVIP. A gateway that also acts as an ONVIF device MAY answer WS-Discovery for its ONVIF persona.

5.3 Session establishmentLink to the section 5.3 Session establishment

The device starts the connection

After an authenticated secure WebSocket is established, the Device sends hello and the Client sends welcome. The Device verifies the Client identity, sends capabilities, and begins telemetry and events. Video negotiation follows the media specification.

View Mermaid source
sequenceDiagram
    accTitle: The device starts the connection
    accDescr: After an authenticated secure WebSocket is established, the Device sends hello and the Client sends welcome. The Device verifies the Client identity, sends capabilities, and begins telemetry and events. Video negotiation follows the media specification.
    participant D as UNIVIP Device
    participant C as UNIVIP Client
    D->>C: Open authenticated WSS session over TLS 1.3
    D->>C: hello: device identity and version
    C-->>D: welcome: client identity and session settings
    Note over D: Verify configured client identity
    D->>C: capabilities: supported features
    D->>C: telemetry and events
    Note over D,C: Negotiate video using the advertised media capabilities

This is the successful connection path for one device. A gateway repeats hello, welcome and capabilities for each vehicle it presents. The steps below also define refusal, keepalive and reconnection behavior.

  1. Device performs TLS 1.3 to wss://<endpoint-host>/univip/v1/session.
  2. Device authenticates with one of the methods in Part 13 (mTLS client certificate, or OAuth 2.0 bearer token presented in the Authorization header of the WebSocket upgrade request).
  3. Device sends a hello envelope for each device it presents on the session (one for a native device; one per vehicle for a multiplexing gateway). The client answers each hello with a welcome carrying the same envelope device_id, or refuses that device with an error envelope carrying its device_id and code UNAUTHORIZED or FORBIDDEN_SCOPE.
  4. Device then sends capabilities (the full capability document) for each welcomed device before any other message for that device. ping, pong and error MAY precede it.
  5. Real-time traffic begins. A side that has neither sent nor received anything on the session for 30 s sends ping; the peer MUST answer with pong. A ping is unanswered when nothing at all arrives from the peer before the next ping is due; after three consecutive unanswered pings the side MUST close the connection with WebSocket close code 4000.
  6. On disconnect the device MUST reconnect with exponential backoff (initial 1 s, cap 60 s, full jitter) and resend hello and capabilities.

Refusing one device of a multiplexed session MUST NOT close the session or affect the other devices on it. The device MAY offer a refused device again with a new hello on the same session, not more often than once every 60 s; a later welcome attaches it. A welcome without a device_id (0.1 clients) answers every hello pending on the session.

5.3.1 Client identityLink to the section 5.3.1 Client identity

The device learns which client it is talking to from its own configuration of the endpoint, never from the welcome alone: at onboarding the operator configures the endpoint URL, the trust anchor (or pinned certificate) that authenticates it in TLS, and the client's client_id. A device MUST refuse a session whose welcome.client_id differs from the client_id configured for that endpoint (error with code UNAUTHORIZED, then close). The resulting verified client identity is used to route messages that belong to one client: command_status and lease envelopes for a command or lease submitted over the device's own REST listener go to the sessions whose verified client identity equals the client_id of the credential that submitted it, and those for a request received through the session proxy go to the session that carried the request (§5.5.1).

5.4 Envelope formatLink to the section 5.4 Envelope format

Every message on the session channel is one JSON text frame:

{
  "schema": "univip.envelope.v0.2",
  "type": "telemetry",
  "device_id": "urn:univip:acme:SN12345",
  "msg_id": "01J9ZC3V3Q6W1K9Z8Q0T6B4K7A",
  "timestamp": "2026-10-15T10:32:15.125Z",
  "payload": { }
}
Member Rule
type One of hello, welcome, capabilities, telemetry, event, command_status, signal, lease, request, response, ping, pong, error. Vendor types use reverse-DNS names.
device_id REQUIRED on every device-originated message (allows gateway multiplexing) and on client-originated messages addressed to one device (welcome, signal, request). Absent on ping and pong, which belong to the session. On error it is present when the error concerns one device and absent when it cannot be attributed (for example a frame that is not JSON).
msg_id REQUIRED; unique per sender per session; RECOMMENDED ULID.
timestamp Time the message was created, not the time of the data inside it.
payload An object validating against the schema for type (univip.telemetry.v0.2, univip.event.v0.2, univip.command_status.v0.2, univip.capabilities.v0.2, ...); the envelope schema defines the payloads of hello, welcome, signal, request, response, pong and error.

5.4.1 hello payloadLink to the section 5.4.1 hello payload

{ "univip_version": "0.2.0", "device_id": "urn:univip:acme:SN12345",
  "supported_schemas": ["univip.telemetry.v0.2", "univip.event.v0.2"],
  "resume_token": null }

5.4.2 welcome payloadLink to the section 5.4.2 welcome payload

{ "client_id": "vms-site-7", "univip_version": "0.2.0",
  "telemetry": { "requested_rate_hz": 5 },
  "server_time": "2026-10-15T10:32:14.990Z" }

The envelope carries the device_id of the hello it answers. A client MAY request a telemetry rate; the device MUST honor it if within the range advertised in capabilities and otherwise MUST clamp it to that range. Either way it reports the rate it applies in telemetry.applied_rate_hz of the next capabilities message. The rate is per device and shared by its sessions; when sessions request different rates the device applies one of them (the reference gateways apply the latest request) and every session's capabilities report the rate actually applied. The requested rate is an upper bound: a device never repeats a sample to reach it (Part 07 §7.11).

5.4.3 signal payloadLink to the section 5.4.3 signal payload

Carries WebRTC signaling (SDP offers and answers, ICE candidates, teardown) for the media plane; the payload is defined in Part 09 §9.3.

5.4.4 error payloadLink to the section 5.4.4 error payload

{ "code": "UNSUPPORTED_SCHEMA", "message": "...", "ref_msg_id": "..." }

Standard codes: UNAUTHORIZED, FORBIDDEN_SCOPE, UNSUPPORTED_SCHEMA, UNSUPPORTED_EXTENSION, MALFORMED (fails its schema or is not JSON), PROTOCOL_VIOLATION (valid but out of order, such as telemetry before capabilities), RATE_LIMITED, UNKNOWN_STREAM, CODEC_UNSUPPORTED, BUSY (for example a stream at its viewer limit), INTERNAL.

5.4.5 ping and pong payloadsLink to the section 5.4.5 ping and pong payloads

ping carries an empty object. pong carries { "ref_msg_id": "<msg_id of the ping>" }.

5.5 REST surfaceLink to the section 5.5 REST surface

The REST API (../api/univip-v1.openapi.yaml) exposes under /univip/v1/devices/{device_id}:

Resource Methods Purpose
/ GET Identity
/capabilities GET Capability document
/telemetry/latest GET Last telemetry sample (for clients that do not hold a session channel)
/events GET Recent events, filterable by topic and time
/media/streams GET Stream descriptors
/media/streams/{stream_id}/webrtc POST Alternative WebRTC signaling via HTTP (WHEP-style) for clients that prefer it; the Location of the response names the session resource
/media/streams/{stream_id}/webrtc/{resource_id} DELETE Tear down that WebRTC session (only its creator may; others receive 404)
/commands POST Submit a command (camera.* or vehicle.*)
/commands/{command_id} GET, DELETE Status; cancel
/leases GET, POST List the caller's own leases (all leases with univip.admin), acquire
/leases/{lease_id} GET, PATCH, DELETE Status, heartbeat/extend, release
/config GET, PATCH Device configuration subset exposed to clients (telemetry rate, stream defaults)

All responses are JSON except the SDP bodies of the WebRTC resources. Errors use RFC 9457 Problem Details with the type URIs registered in §5.5.2. HTTP 403 means only that the credential lacks the required scope; a command refused for a lease or safety reason is answered 422 with a REJECTED command status, so the client always receives a status it can show (Part 10 §10.1).

5.5.1 Session proxyLink to the section 5.5.1 Session proxy

A device declaring transports.rest.session_proxy: true serves its REST surface through request and response envelopes on the session channel, so that a client can reach a device that accepts no inbound connections.

{ "request_id": "req-0001", "method": "POST", "path": "/commands",
  "headers": { "content-type": "application/json" },
  "auth": { "client_id": "vms-site-7", "scopes": ["univip.view", "univip.camera"], "operator_user": "jdoe" },
  "body": { "schema": "univip.command.v0.2", "...": "..." } }
{ "request_id": "req-0001", "status": 202, "headers": { "content-type": "application/json" },
  "body": { "schema": "univip.command_status.v0.2", "state": "ACCEPTED", "...": "..." } }
  • path is relative to /univip/v1/devices/{device_id} (empty for the identity resource); query carries query parameters as strings; headers carries only content-type, if-none-match and if-match, in lower case. body is the JSON body, or a string for other media types (application/sdp).
  • The client-hosted endpoint authenticates and authorizes its own users and states the result in auth: the client_id (which MUST equal the session's verified client identity, §5.3.1), the UNIVIP scopes of the user's credential, and operator_user where known. The device MUST process the request exactly as if it had arrived on its own listener from a principal with those scopes, limited to the scopes the operator allowed for that endpoint at onboarding; by default univip.vehicle, univip.config and univip.admin are not allowed.
  • The device answers every request with exactly one response carrying the same request_id, the HTTP status it would have returned, the content-type, etag and location headers where applicable, and the body. Command status and lease envelopes for proxied commands and leases go to the session that carried the request. Requests on one session MAY be answered out of order.
  • A device MAY refuse request bodies larger than 1 MiB (status 413) and SHOULD answer within 10 s; the client-hosted endpoint answers its caller 504 when no response arrives within 30 s.

5.5.2 Problem typesLink to the section 5.5.2 Problem types

Problem type URIs are https://univip.org/problems/<slug>; vendor problems use a vendor URI. Where a UNIVIP code applies, the problem carries it as univip_code.

Slug Status univip_code Meaning
malformed 400 MALFORMED Body or parameters fail their schema; also used with HTTP 413 for a body over the size limit
unsupported-extension 400 UNSUPPORTED_EXTENSION Unknown must-understand member (Part 01 §1.4)
unauthorized 401 UNAUTHORIZED Missing or invalid credential
forbidden-scope 403 FORBIDDEN_SCOPE Credential lacks the scope, or a proxied request asserts a client other than the session's
lease-scope 403 LEASE_SCOPE Lease operation by a client that does not hold the lease, or a lease request whose client_id is not the caller's
unsupported 403 UNSUPPORTED_COMMAND The device does not offer the profile or feature (for example a vehicle lease without Profile N)
flight-control-disabled 403 FLIGHT_CONTROL_DISABLED Profile N is disabled by the operator
not-found 404 — Unknown device, stream, command, lease or resource
duplicate-command 409 — command_id already used
command-terminal 409 — Cancel of a command that already ended
command-not-cancellable 409 A command rejection reason, e.g. BUSY or LINK_LOST The adapter cannot confirm cancellation; the original command remains active and movement may continue
lease-conflict 409 — An active lease with this scope is held by another client
lease-state 409 — Operation not valid in the lease's state
stream-busy 409 BUSY Stream at its viewer limit
lease-gone 410 LEASE_EXPIRED Heartbeat or extension of a lease that has ended; the body is the lease
method-not-allowed 405 — Method not defined for the resource
unsupported-media-type 415 — Wrong Content-Type
rate-limited 429 RATE_LIMITED Too many requests
internal 500 INTERNAL Unexpected device error
device-error 502 — Client-hosted endpoint: the session to the device failed while the request was outstanding
device-unavailable 503 — Client-hosted endpoint: the device has no session, or offers no session proxy
device-timeout 504 — Client-hosted endpoint: no response within 30 s

Each URI resolves to a page on univip.org describing the problem.

5.6 MQTT alternativeLink to the section 5.6 MQTT alternative

A device that declares transports.realtime: ["WSS", "MQTT5"] MAY offer the real-time plane over MQTT 5 with the topic structure in Part 08 §8.7. The REST plane remains HTTPS. Conformance to the MQTT alternative is a separate optional test group.

Generated from spec/05-identity-and-connection.md.