OPAL Permissions

Security and access control for Plans

OPAL Permissions

Reference for the OPAL permission system that controls what Plans can access and modify.

Security Note

OPAL's capability-based permission model means Plans must explicitly request the resources they need, and users review these requests before approval. This "principle of least privilege" protects your robot from malicious or buggy Plans - a Plan that only requests sensors.distance can never accidentally (or intentionally) spin your motors.


Permission model

OPAL uses a capability-based security model:

  1. Plans declare required permissions
  2. User reviews and approves permissions
  3. Runtime enforces permission checks
    ┌─────────────────┐
    │     Plan        │
    │  (requests      │
    │   permissions)  │
    └────────┬────────┘
             │
             ▼
    ┌─────────────────┐
    │   Permission    │
    │   Checker       │
    │ (grants/denies) │
    └────────┬────────┘
             │
             ▼
    ┌─────────────────┐
    │   Hardware/     │
    │   Resources     │
    └─────────────────┘

Permission categories

Category Prefix Description
Sensors sensors.* Read sensor data
Actuators actuators.* Control motors, servos
Communication comms.* Send/receive messages
Storage storage.* Persist data
System system.* System operations
Network network.* Network access

Sensor permissions

sensors.read

Read any sensor value.

// Requires: sensors.read
var dist = sensors.distance.front
var heading = sensors.imu.heading

sensors.distance

Read distance sensors only.

// Requires: sensors.distance
var dist = sensors.distance.front
var left = sensors.distance.left

sensors.imu

Read IMU (orientation) sensors.

// Requires: sensors.imu
var heading = sensors.imu.heading
var pitch = sensors.imu.pitch

sensors.line

Read line following sensors.

// Requires: sensors.line
var on_line = sensors.line.center

sensors.camera

Access camera feed.

// Requires: sensors.camera
var frame = camera.capture()

sensors.gps

Access GPS location.

// Requires: sensors.gps
var lat = gps.latitude
var lon = gps.longitude

Actuator permissions

actuators.control

Control any actuator.

// Requires: actuators.control
drive(50, 50)
set_servo("arm", 90)

actuators.motors

Control DC motors only.

// Requires: actuators.motors
drive(50, 50)
set_motor("left", 60)

actuators.servos

Control servos only.

// Requires: actuators.servos
set_servo("head.pan", 90)
set_servo("head.tilt", 45)

actuators.relays

Control relay outputs.

// Requires: actuators.relays
set_relay("lights", true)

actuators.emergency_stop

Access emergency stop function.

// Requires: actuators.emergency_stop
emergency_stop()

Note: Emergency stop is always allowed regardless of other permissions for safety.


Communication permissions

comms.broadcast

Send broadcast messages.

// Requires: comms.broadcast
broadcast("status", {state: "idle"})

comms.send

Send direct messages to peers.

// Requires: comms.send
send_to("Worker A", "command", {action: "start"})

comms.receive

Receive messages from peers.

// Requires: comms.receive
on_message("task") { data ->
    execute(data)
}

comms.peers

Access peer information.

// Requires: comms.peers
var peer_list = peers.list()
var status = peers["Worker A"].status

Storage permissions

storage.read

Read stored data.

// Requires: storage.read
var config = storage.get("config")
var history = storage.get("patrol_history")

storage.write

Write data to storage.

// Requires: storage.write
storage.set("last_patrol", now())
storage.set("config", {speed: 50})

storage.delete

Delete stored data.

// Requires: storage.delete
storage.delete("old_data")
storage.clear()

System permissions

system.info

Access system information.

// Requires: system.info
var version = system.version
var uptime = system.uptime
var name = system.personality_name

system.battery

Access battery status.

// Requires: system.battery
var level = battery.level
var voltage = battery.voltage

system.time

Access time functions.

// Requires: system.time
var now = now()
var hour = time.hour

system.plans

Control other plans.

// Requires: system.plans
activate("PatrolPlan")
deactivate("OldPlan")
pause("BackgroundTask")

system.config

Modify system configuration.

// Requires: system.config
// Very restricted - rarely granted
config.set("network.port", 8125)

Network permissions

network.local

Access local network.

// Requires: network.local
// Used for LAN discovery and communication

network.internet

Access external internet.

// Requires: network.internet
// Rarely granted - for cloud services
http.get("https://api.example.com/data")

Declaring permissions

In plan header

#!octomy-plan v1.0
# @permissions sensors.distance, actuators.motors
# @permissions comms.broadcast

plan MyPlan {
    // Plan code
}

In metadata.json

{
    "name": "My Plan",
    "permissions": [
        "sensors.distance",
        "actuators.motors",
        "comms.broadcast"
    ]
}

Permission groups

Common permission bundles:

basic

Minimal permissions for simple plans.

sensors.read
system.time

mobile

Permissions for mobile robots.

sensors.read
actuators.motors
system.battery

autonomous

Full autonomous operation.

sensors.read
actuators.control
comms.broadcast
storage.read
storage.write
system.info

admin

Administrative access (rarely used).

sensors.read
actuators.control
comms.*
storage.*
system.*

Permission UI

When importing a plan:

┌─────────────────────────────────────────────┐
│  Permission Review                           │
├─────────────────────────────────────────────┤
│                                              │
│  Plan: Obstacle Avoider                      │
│  Author: RobotBuilder42                      │
│                                              │
│  This plan requests:                         │
│                                              │
│  ✓ sensors.distance                          │
│    Read distance sensor values               │
│                                              │
│  ✓ actuators.motors                          │
│    Control drive motors                      │
│                                              │
│  ✓ system.battery                            │
│    Check battery level                       │
│                                              │
│  ⚠ Risk Level: LOW                          │
│    Only accesses sensors and motors          │
│                                              │
│  [Approve] [Deny] [Review Code]              │
│                                              │
└─────────────────────────────────────────────┘

Risk levels

Level Description
LOW Read-only sensors, no network
MEDIUM Motor control, local storage
HIGH Network access, all actuators
CRITICAL System config, internet access

Runtime enforcement

Permission check

At runtime, each operation checks permissions:

Plan calls: drive(50, 50)
    ↓
Permission check: actuators.motors
    ↓
Granted? → Execute
    ↓
Denied? → Throw E501 Permission Denied

Error handling

try {
    drive(50, 50)
} catch error {
    if error.code == "E501" {
        log_error("No motor permission!")
        // Fallback behavior
    }
}

Trust levels and permissions

Permissions interact with trust levels:

Trust Level Max Permissions
Block None
Ignore None
Meet sensors.read
Handshake sensors.read, comms.receive
Trust All except system.config
Depend All

Remote control from a peer is limited by:

  1. Plan's declared permissions
  2. Peer's trust level
  3. User's approval

Best practices

Principle of least privilege

Request only what you need:

// Bad - requests everything
# @permissions actuators.control

// Good - requests only motors
# @permissions actuators.motors

Explain why

Document permission use:

# @permissions sensors.distance
#   Used for obstacle detection
# @permissions actuators.motors
#   Used for driving and avoidance

Handle denials gracefully

try {
    var dist = sensors.distance.front
} catch error {
    if error.code == "E501" {
        // Fall back to simpler behavior
        use_bump_sensors_only()
    }
}

Avoid permission: network.internet

Internet access should rarely be needed. Consider:

  • Local processing instead of cloud
  • Hub-mediated cloud access
  • Offline-first design

Security considerations

Plan signing

Plans from trusted sources can be signed:

# @signature sha256:abc123...
# @author verified:RobotBuilder42

Signed plans show verified author in permission dialog.

Sandboxing

Plans run in a sandbox:

  • Cannot access filesystem directly
  • Cannot execute system commands
  • Limited memory and CPU
  • Network access controlled

Audit logging

All permission-controlled actions are logged:

[12:34:56] Plan "Patrol" used sensors.distance
[12:34:56] Plan "Patrol" used actuators.motors

In this section
Topics
reference OPAL permissions security access-control
See also