Skip to main content

RCAN v1.6: Four Hard Problems in Robot Communication

4 min read By Craig Merry
rcan opencastor robotics federation lora security

Earlier today we shipped RCAN v1.5. This is v1.6, which followed about two hours later.

Four gaps were deferred from v1.5 as “large-complexity, non-blocking.” We finished them today anyway.

The core question: Robot A (on your registry) wants to command Robot B (on my registry). Who decides?

Before v1.6, RCAN mentioned federation (“registries federate like email”) but provided no protocol. The FEDERATION_SYNC message type existed but had no payload spec.

v1.6 defines §18 — Registry Federation Protocol:

  • Trust tiers: Root (manages trust anchors) → Authoritative (annual audit, can issue LoA 2/3) → Community (self-signed, LoA 1 only)
  • Trust anchor discovery: _rcan.<domain> DNSSEC TXT record → registry public key fingerprint
  • Cross-registry JWT trust chains: Registry A signs a JWT that Registry B can verify by fetching Registry A’s public key from DNS
  • FEDERATION_SYNC wire format: {source_registry, target_registry, sync_type: consent|revocation|key, payload, signature}
  • 12-step federated consent flow: Alice (reg-1) → request → Robot B’s owner (reg-2) → grant → propagated back

Protocol 66 invariant preserved: local safety always wins regardless of federation status. A robot on reg-2 will always enforce its own consent records — it trusts incoming commands only after local verification.

GAP-17: Bandwidth-Constrained Transports

A typical RCAN message with JWT auth and Ed25519 signature is 400–800 bytes before payload. An ESTOP on LoRa SF12 at ~250 bps would take 25 seconds to transmit. That’s not a safety system.

v1.6 defines three transport tiers:

RCAN-HTTP (existing): full JSON, up to 64MB. For WiFi/LTE.

RCAN-Compact: abbreviated field names (t=msg_type, i=msg_id, f=from_rrn, etc.), CBOR/msgpack encoding. Target: <200 bytes for ESTOP, <512 bytes for STATUS. For constrained WiFi.

RCAN-Minimal: exactly 32 bytes. ESTOP-only.

[2B type][8B from_hash][8B to_hash][4B unix32][8B sig_truncated][2B checksum]

SHA-256 of RRN string → first 8 bytes as address. HMAC-SHA256 → first 8 bytes as truncated signature. XOR checksum. At LoRa SF12: 32 bytes = ~1 second transmit time. That’s a safety system.

BLE L2CAP framing is also specified: MTU 251 bytes, multi-packet fragmentation for larger RCAN messages over BLE.

Transport negotiation happens in DISCOVER responses: supported_transports: ["http", "compact", "minimal", "ble"].

GAP-18: Multi-Modal Payloads

RCAN payloads were JSON-only. SENSOR_DATA and TRAINING_DATA implied data transfer but had no binary standard. Images sent outside the RCAN envelope are outside the trust boundary — unverifiable, unauditable.

v1.6 adds media_chunks[] to every RCAN message:

{
  "chunk_id": "uuid",
  "mime_type": "image/jpeg",
  "encoding": "base64",
  "hash_sha256": "abc123...",
  "data_b64": "...",
  "size_bytes": 42800
}

Two modes: inline (base64, <64KB) and reference (URL + hash, robot serves at GET /api/v1/media/{chunk_id}, HMAC-signed URL with 5-minute TTL).

The SHA-256 hash is included in the RCAN message’s CommitmentRecord. The signed message proves what data was transmitted — even if the actual image is stored elsewhere. The audit trail covers the data, not just the metadata.

Streaming mode for video: SENSOR_DATA messages with stream_id, chunk_index, is_final fields. TRAINING_DATA now requires multi-modal payloads — JSON-only TRAINING_DATA is deprecated in v1.6.

GAP-14: Human Identity Verification

Before v1.6: JWT sub identifies the human. But who verified them before issuing the JWT?

v1.6 adds Level of Assurance (LoA) as a required JWT claim:

  • LoA 1 (Anonymous/pseudonymous): email not verified. Issued by any registry including community tier.
  • LoA 2 (Email verified): registry verified email ownership. Authoritative tier minimum.
  • LoA 3 (Hardware token): FIDO2/WebAuthn binding. Only root or authoritative registries.

Recommended enforcement: control scope requires LoA ≥ 2. safety scope requires LoA ≥ 3.

loa_enforcement: false by default — all existing deployments are backward compatible. Opt-in enforcement when you’re ready.

For the factory floor: set min_loa_for_control: 2 in your Protocol 66 manifest. Workers must use email-verified accounts. ESTOP still works from any LoA — you can always stop the robot.

What’s in each release

rcan-specrcan-pyrcan-tsOpenCastorRRF
v1.5v1.5.0v0.5.0 (430 tests)v0.5.0 (311 tests)v2026.3.17.0v1.5.0
v1.6v1.6.0v0.6.0 (587 tests)v0.6.0 (405 tests)v2026.3.17.1v1.6.0

All 22 gaps from the original audit addressed.

pip install opencastor==2026.3.17.1
pip install rcan==0.6.0
npm install @continuonai/[email protected]

Spec: rcan.dev/spec — now has 19 sections.