Safety Conformance
OpenCastor implements a layered safety model grounded in RCAN §6 (Safety Invariants) and §16 (Protocol 66). These invariants are non-negotiable — they cannot be overridden by AI-generated commands, remote operators, or runtime configuration changes.
Protocol 66
Protocol 66 is RCAN's safety manifest protocol. Any RCAN-compliant robot must expose its safety capabilities and invariant status via a well-known endpoint so operators, fleets, and registries can verify the robot's safety posture at runtime.
Safety Manifest Endpoint
GET /api/safety/manifest Returns a JSON document describing:
- Which of the 5 safety invariants are active
- Hardware safety capabilities (physical e-stop, watchdog MCU, SIL level, etc.)
- Current safety envelope values (max speed, estop distance, watchdog timeout)
- Audit trail status and last event timestamp
{
"protocol": 66,
"rcan_version": "1.4",
"invariants": {
"local_safety_wins": true,
"safety_messages_bypass_queues": true,
"estop_requires_explicit_clear": true,
"ai_cannot_override_safety": true,
"audit_trail_complete": true
},
"hardware_safety": {
"physical_estop": false,
"hardware_watchdog_mcu": false,
"sil_level": "none",
"human_proximity_sensors": "none"
},
"envelope": {
"max_linear_speed_mps": 1.0,
"max_angular_speed_radps": 2.0,
"emergency_stop_distance": 0.3
}
} The 5 Safety Invariants (RCAN §6)
All RCAN-compliant robots must implement these invariants. They are enforced at the runtime layer and cannot be overridden by any AI brain, remote command, or configuration update.
local_safety_wins Required Local sensor-based safety decisions always override any network command. If a proximity sensor detects an obstacle within the emergency stop distance, the robot stops — regardless of what the AI brain or a remote operator commanded.
safety_messages_bypass_queues ESTOP and SAFETY_HALT messages skip the normal command queue and are processed immediately. A safety command can never be delayed by a backlogged navigation or action queue.
estop_requires_explicit_clear Once an emergency stop is triggered, the robot remains stopped until an operator explicitly clears it via an authenticated ESTOP_CLEAR command. Automatic recovery is not permitted.
ai_cannot_override_safety The AI brain operates within a sandboxed action space. It can never issue commands that modify safety envelope parameters, disable proximity monitoring, or alter ESTOP state. Safety constraints are enforced below the AI layer.
audit_trail_complete Every safety event — ESTOP triggers, limit violations, watchdog resets, and ESTOP clears — is written to a tamper-evident audit log with a UTC timestamp and the initiating source (sensor, operator, AI, watchdog).
Minimum Required Configuration
Every RCAN config must include a safety block with at minimum local_safety_wins: true. The full recommended safety block is:
safety:
local_safety_wins: true # REQUIRED — RCAN §6 invariant
max_linear_speed_mps: 1.0 # m/s hard cap
max_angular_speed_radps: 2.0 # rad/s hard cap
emergency_stop_distance: 0.3 # metres — auto ESTOP trigger distance
watchdog:
timeout_s: 10 # Heartbeat timeout before safe stop
brain:
confidence_gates:
- scope: control
min_confidence: 0.75
on_fail: block # Block command if AI confidence < 0.75
- scope: config
min_confidence: 0.65
on_fail: block local_safety_wins is a required field in the safety object. Configs without it will fail validation.
Field Reference
| Field | Required | Description |
|---|---|---|
safety.local_safety_wins | ✅ Yes | Enables RCAN §6 local safety invariant. Must be true. |
safety.emergency_stop_distance | Recommended | Distance in metres triggering automatic ESTOP (e.g. 0.3) |
watchdog.timeout_s | Recommended | Seconds without heartbeat before safe stop is triggered |
brain.confidence_gates | Recommended | Per-scope AI confidence thresholds. Block or escalate low-confidence commands. |
Hardware Safety Capabilities
The hardware_safety block declares physical safety hardware present on the robot. This is reported via Protocol 66 and stored in the Robot Registry Foundation so operators know the actual hardware safety posture of each robot.
hardware_safety:
physical_estop: false # Physical e-stop button (cuts actuator power)
hardware_watchdog_mcu: false # Dedicated watchdog MCU (e.g. STM32 safety core)
force_torque_sensors: false # F/T sensors for contact force limiting (ISO/TS 15066)
human_proximity_sensors: none # none | lidar | depth_camera | uwb | combined
sil_level: none # none | SIL1 | SIL2 | SIL3 | PLc | PLd | PLe
voltage_monitoring: false # Hardware voltage monitoring with auto power cutoff SIL / Performance Level Reference
| Level | Standard | Typical Application |
|---|---|---|
none | — | Dev/research robots with software-only safety (OpenCastor Bob, Alex) |
PLc | ISO 13849 | Consumer/research robots with basic hardware safety (Unitree Go2) |
PLd | ISO 13849 | Industrial collaborative robots (Boston Dynamics Spot) |
PLe | ISO 13849 | Safety-critical industrial machinery |
SIL1–3 | IEC 61508 | Functional safety systems (medical, process industry) |
hardware_safety block should accurately reflect the robot's actual hardware. A dev robot like OpenCastor Bob correctly reports sil_level: none — this helps operators make informed deployment decisions rather than creating false confidence.
Brain Watchdog (watchdog.timeout_s)
The brain watchdog implements invariant SOFTWARE_001: if the AI brain becomes unresponsive for timeout_s seconds, the RCAN runtime performs a controlled stop — all motors halt and the robot enters a safe idle state until the brain reconnects and sends an explicit ESTOP_CLEAR.
How It Works
The runtime expects a heartbeat from the AI brain at least once every timeout_s seconds. If no heartbeat arrives within the window:
- The runtime logs a
WATCHDOG_TIMEOUTsafety event to the audit trail. - All actuator outputs are set to their safe/zero state.
- The robot transitions to
ESTOPstate, blocking further commands. - An operator must issue an authenticated
ESTOP_CLEARbefore motion resumes.
Configuration
Add a watchdog block to your .rcan.yaml:
watchdog:
timeout_s: 10 # Default: 10s. Max recommended: 30s.
enabled: true # Set to false only for local development (not recommended in production) Field Reference
| Field | Default | Description |
|---|---|---|
watchdog.timeout_s | 10 | Seconds without brain heartbeat before controlled stop is triggered. |
watchdog.enabled | true | Enable/disable the watchdog. Disabling is strongly discouraged for production deployments. |
See the full rcan-config.json schema for the complete watchdog object definition.
EU AI Act Compliance (Article 13)
EU AI Act Article 13 requires AI systems to disclose their AI nature, capabilities, and operator identity to persons they interact with. Robots using RCAN that incorporate foundation models or LLM capabilities must implement MessageType 18 (TRANSPARENCY).
Deadline: August 2, 2026 (General Purpose AI provisions in force).
MessageType.TRANSPARENCY (type: 18)
Purpose: Robots disclose AI nature, capabilities, and operator to humans they interact with.
Trigger: On first human interaction, on request, or periodically in human-occupied spaces.
Payload Schema
{
"ai_system": true, // Required — always true per Art. 13
"model_family": "claude-sonnet", // AI model family (not version)
"operator": "example-company", // Deploying operator name
"capabilities": ["navigation", "speech"], // What the robot can do
"limitations": ["cannot lift > 2kg"], // Known limitations
"contact": "safety@example.com", // Who to contact
"rcan_version": "1.4",
"p66_conformance_pct": 87, // Protocol 66 conformance level
"audit_enabled": true // Whether actions are audited
} When to Send
- A robot enters a human-occupied space
- A human directly interacts with the robot
- Requested via voice command or button
- On startup in any public-facing deployment
Python Implementation
from rcan.safety import make_transparency_message
msg = make_transparency_message(
source_ruri="rcan://rcan.dev/acme/arm/v1/unit-001",
target_ruri="rcan://local/human-display",
operator="Acme Robotics",
capabilities=["navigation", "speech"],
model_family="claude-sonnet",
limitations=["cannot lift > 5 kg"],
contact="safety@acme.example",
p66_conformance_pct=87.0,
audit_enabled=True,
) Applicability
Robots using RCAN that incorporate LLM/AI capabilities fall under EU AI Act as:
- High-risk AI systems (Annex III, §3 — safety components of machinery)
- General Purpose AI (if using foundation models like Claude/GPT)
See the EU AI Act Compliance Guide for full implementation details and the Article 9/17 requirements.
§8.4 — Clock Synchronization Requirements v1.5
Gap: GAP-04 — Replay attack prevention (§8.3) depends on timestamp comparison. Unsynced clocks cause valid commands to be rejected or create replay windows.
Requirements
- All RCAN-compliant robots MUST synchronize their system clocks using NTP or Network Time Security (NTS, RFC 8915) before entering operational mode.
- Recommended time source:
pool.ntp.org - Maximum drift tolerance: ±5 seconds
- Embedded hardware without RTC SHOULD use NTP at boot and maintain drift within tolerance.
Protocol 66 Manifest — New Fields
Robots MUST expose the following new fields in GET /api/safety/manifest:
{
"protocol": 66,
"rcan_version": "1.5",
...
"clock_synchronized": true, // false if NTP not confirmed
"clock_source": "ntp", // "ntp" | "nts" | "gps" | "manual" | "none"
"clock_drift_ms": 12.4, // Last known drift in milliseconds
"offline_mode": false, // true when registry unreachable
"offline_since_s": 0 // Seconds since entering offline mode
} Restricted Mode
When clock_synchronized: false, the robot MUST enter restricted mode:
- Only accept commands from same-network, same-owner sources
- Log a WARNING-level audit event every 60 seconds
- Cross-owner consent requests are blocked until sync is restored
- ESTOP is always accepted regardless of clock sync state (P66 invariant)
§20 — Audit Trail Export Protocol v1.5 SHOULD
Gap: GAP-21 — HMAC-chained audit exists locally; no standard export API for compliance audits. EU AI Act Article 17 requires accessible audit records.
Export Endpoint
GET /api/v1/audit?from=<unix_ts>&to=<unix_ts>&format=jsonl|csv
// Response headers
Content-Type: application/x-ndjson (format=jsonl)
Content-Type: text/csv (format=csv)
X-Audit-Chain-Root: sha256:abc123 // Root hash of the exported chain
X-Audit-Issuer-Sig: ed25519:... // Ed25519 signature over root hash JSONL Export Format
The first line is a signed header; subsequent lines are NDJSON commitment records:
// Line 1: header
{"type":"audit_export","from":1741000000,"to":1741086400,"count":142,"chain_root":"sha256:abc...","issuer_sig":"ed25519:xyz...","rcan_version":"1.5"}
// Lines 2-N: commitment records
{"id":"...","timestamp":1741000001,"cmd":"move_forward","operator":"...","commitment_hash":"..."}
... Verification
Recipients can verify the export by:
- Computing the chain root hash over all commitment records in order
- Verifying the
issuer_sigagainst the robot's public key (from JWKS or registry) - Comparing computed root to
chain_rootin the header
Protocol 66 Manifest — Audit Fields
{
"audit_enabled": true,
"audit_retention_days": 90,
"audit_count": 1423,
"audit_last_event": 1741000001.0
} Protocol 66 Manifest — v1.6 Fields v1.6
Three new fields are added to GET /api/safety/manifest in v1.6, covering identity assurance, federation, and constrained transport support.
{
"protocol": 66,
"rcan_version": "1.6",
...
"min_loa_for_control": 2, // NEW v1.6 — default 1 (backward compat). See §8.7.
"federation_enabled": false, // NEW v1.6 — default false. See §18.
"trusted_registries": [], // NEW v1.6 — federation allowlist; [] = trust all authoritative
"supported_transports": ["http"], // NEW v1.6 — constrained transport tiers. See §19.
...
} min_loa_for_control
- Type:
integer— values 1, 2, or 3 (Level of Assurance — see §8.7) - Default:
1(backward compatible — existing v1.5 deployments are unaffected) - Robots MUST reject
control-scope commands from JWTs whoseloafield is below this value - Recommended production setting:
2(email-verified identity minimum) - ESTOP is always exempt from LoA enforcement (P66 invariant)
federation_enabled
- Type:
boolean— defaultfalse - When
false: the robot rejects all cross-registry commands and ignoresFEDERATION_SYNCmessages - When
true: the robot participates in the §18 federation protocol - The optional
trusted_registriesarray, when non-empty, acts as an explicit federation allowlist
supported_transports
- Type:
string[]— values from["http", "compact", "minimal", "ble"] - Default:
["http"](unchanged v1.5 behaviour) - Senders use this field during transport negotiation (see §19)
- A robot advertising
"minimal"MUST support the 32-byte RCAN-Minimal ESTOP frame
Complete v1.6 Manifest Example
{
"protocol": 66,
"rcan_version": "1.6",
"invariants": {
"local_safety_wins": true,
"safety_messages_bypass_queues": true,
"estop_requires_explicit_clear": true,
"ai_cannot_override_safety": true,
"audit_trail_complete": true
},
"hardware_safety": { "physical_estop": false, "sil_level": "none" },
"envelope": {
"max_linear_speed_mps": 1.0,
"emergency_stop_distance": 0.3
},
"clock_synchronized": true,
"clock_source": "ntp",
"clock_drift_ms": 8.2,
"offline_mode": false,
"offline_since_s": 0,
"audit_enabled": true,
"audit_retention_days": 90,
"audit_count": 1847,
"audit_last_event": 1741050001.0,
"min_loa_for_control": 2,
"federation_enabled": false,
"trusted_registries": [],
"supported_transports": ["http", "compact"]
} Conformance Badges
RCAN-compliant robots can display conformance badges to signal their safety posture. Badges are available for:
- RCAN Compliant — passes schema validation and implements all 5 invariants
- Protocol 66 — exposes
GET /api/safety/manifest - Verified — independently verified by the Robot Registry Foundation
See the Conformance Badges page for embed codes and SVG assets.