role and access say which organisation role may use what a robot exposes.
Both are optional, and both are the cloud’s alone: the robot is sent them and
ignores them. The ideas, and what a role is, are on
Roles and Rights; this page is the format.
fleetless: 1
access:
assets: operate
job_history: [operate]
rules:
- match: /arm/**
role: admin
- match: /diagnostics/*
kinds: [read]
role: maintenance
datapoints:
battery_soc:
topic: /battery
type: sensor_msgs/msg/BatteryState
field: percentage
raw_diagnostics:
topic: /diagnostics/raw
type: diagnostic_msgs/msg/DiagnosticArray
role: [maintenance, admin]
services:
arm_home:
ros_name: /arm/home
type: std_srvs/srv/Trigger
role: admin
Here battery_soc follows the organisation’s default for read, arm_home
and everything else under /arm needs admin, and a datapoint under
/diagnostics/ needs maintenance unless it names its own role, as
raw_diagnostics does.
role on an entry
An optional field on every entry of datapoints, actions, services,
publishers and cameras.
| field | type | bounds | absent means |
|---|---|---|---|
role |
a role key, or a list of keys | a key is lower-case, letter-initial, letters, digits and underscores, at most 63 characters, and not defaults; a list names 1 to 50 |
the first rule of access.rules that fits, then the organisation’s default for the entry’s kind |
A list means any of them: holding one of the roles, or inheriting from one, is enough. An empty list is refused, because it would say nobody, which is already what a kind without a default means.
The kind an entry needs follows from its section:
| section | kind |
|---|---|
datapoints, cameras |
read |
actions, services |
invoke |
publishers |
publish |
An entry’s own role wins outright. The rules are not consulted for it.
access.rules
An ordered list that gives a role to every entry whose ROS name fits a
pattern, so a namespace takes one line instead of one role per entry.
| field | type | bounds | absent means |
|---|---|---|---|
match |
glob over a ROS name | absolute, at most 255 characters | required |
kinds |
list | one to three of read, invoke and publish |
the rule fits every kind |
role |
a role key, or a list of keys | as on an entry | required |
At most 100 rules. The glob works on whole name segments:
| pattern | fits | does not fit |
|---|---|---|
/arm/home |
/arm/home |
/arm, /arm/homing |
/diagnostics/* |
/diagnostics/raw |
/diagnostics, /diagnostics/raw/left |
/arm/** |
/arm, /arm/home, /arm/gripper/open |
/armature |
/**/state |
/state, /arm/state, /arm/gripper/state |
/arm/state/raw |
/joint_* |
/joint_1, /joint_left |
/joint, /arm/joint_1 |
*stands for one segment, and inside a segment for any characters (/joint_*).**stands for any number of whole segments, none included, so/arm/**fits/armas well as everything below it. It stands alone as a segment:/ar**is refused.- A pattern is absolute, like every ROS name. A relative pattern or a trailing slash is refused as a schema error, not read as a warning.
The name an entry is matched by depends on its section:
| section | matched by |
|---|---|
datapoints, publishers |
topic |
actions, services |
ros_name |
cameras |
source.topic, when source.kind is ros |
A camera whose source is rtsp, mjpeg or v4l2 has no ROS name, so no rule
fits it: give it a role, or the default decides. The built-in datapoint
bridge_state has none either, and follows the default for read.
The first rule that fits decides. Put the narrow rule above the wide one:
access:
rules:
- match: /arm/gripper/**
role: operate
- match: /arm/**
role: admin
/arm/gripper/open needs operate; the rest of /arm needs admin. Written
the other way round, the second rule would never be reached.
kinds narrows a rule to the entries of those kinds: read is datapoints and
cameras, invoke is services and actions, publish is publishers. A rule
never touches assets or job_history.
access.assets and access.job_history
The two capabilities that belong to the robot as a whole. They have no ROS name, so rules cannot reach them.
| field | type | bounds | absent means |
|---|---|---|---|
assets |
a role key, or a list of keys | as on an entry | the organisation’s default for assets |
job_history |
a role key, or a list of keys | as on an entry | the organisation’s default for job_history |
assets is the asset store, the URDF and the meshes, which give away the
machine’s build. job_history is the past job runs; a run names the person who
started it, so whoever reads it learns who else has been driving the robot. A
caller whose role lacks either is refused with 403 capability_required.
Which one applies
For an entry, the first of these that exists:
- its own
role; - the
roleof the first rule ofaccess.rulesthat fits it; - the organisation’s default for its kind.
For assets and job_history: access.assets or access.job_history, then
the organisation’s default. A kind without a default belongs to nobody.
Only the published version counts. A robot with nothing published has no entries, so it exposes nothing; its assets and job history follow the organisation’s defaults.
The warnings
A role the organisation does not have, and a rule that fits nothing, are
published as usual. Neither is an error: the editor and the draft response list
them as warnings, and the publish response carries all of the document’s
warnings in warnings.
| code | when | path |
|---|---|---|
unknown_role |
a key names no role of the organisation. It grants nothing, and neither does inheritance through it. | services.arm_home.role, access.rules[1].role, access.assets; in a list each key has its own index, as in services.arm_home.role[1] |
rule_matches_nothing |
a rule fits no entry of this document, kinds included, so it changes nothing. |
access.rules[1].match |
The messages read “services.arm_home names technician, which is no role of
this organization.” and “Rule 2 matches nothing, so it changes nothing.”
The message counts rules from 1 and the path counts from 0.
A malformed key, an empty list, an unknown key under access or a relative
match are errors, and block the publish like any other.
The robot ignores both
The robot is sent the stored document unmutated, as it is for every field. It
acts on neither role nor access, so a version that changes only them is
stored and enforced at once and pushes no configuration to the robot (see
what reaches the robot).
Realtime subscriptions that a publish narrows are re-checked and end with
forbidden.