Files

69 lines
3.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Canonical roles (standardized)
Status: **Standardized**. The org-wide role set every sister project maps onto. This is a
mapping **layer above** each project's native authorization: native *enforcement* (OtOpcUa
`NodePermissions`, mxaccessgw gRPC scopes, ScadaBridge native roles + site-scoping) is
unchanged — each project adds a `canonical → native` expansion via the `IGroupRoleMapper<CanonicalRole>`
seam ([`SPEC.md`](SPEC.md) §3). LDAP groups (or API keys) are assigned a **canonical** role;
the project translates it to native permissions at runtime.
## Capabilities
| Capability | Meaning |
|---|---|
| `OBSERVE` | browse / read / subscribe / history **+ read audit logs** |
| `OPERATE` | operate-level writes; alarm acknowledge / confirm |
| `TUNE` | tune-level writes; alarm shelve; method calls |
| `AUTHOR` | create / edit configuration & templates |
| `DEPLOY` | publish / push configuration to runtime / sites (scoped) |
| `ADMINISTER` | manage users / security / system **+ export audit** |
There is no standalone `AUDIT` capability and **no Auditor role**: audit *read* is part of
`OBSERVE`, audit *export* is part of `ADMINISTER`.
## The six roles (capability bundles)
| Role | OBSERVE | OPERATE | TUNE | AUTHOR | DEPLOY | ADMINISTER |
|---|:-:|:-:|:-:|:-:|:-:|:-:|
| **Viewer** | ✓ | | | | | |
| **Operator** | ✓ | ✓ | | | | |
| **Engineer** | ✓ | ✓ | ✓ | | | |
| **Designer** | ✓ | | | ✓ | | |
| **Deployer** | ✓ | | | | ✓ | |
| **Administrator** | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
Two privilege axes meet at the top: **operations** (Viewer → Operator → Engineer) and
**configuration lifecycle** (Viewer → Designer → Deployer → Administrator). Administrator is
the only role that holds every capability.
## Orthogonal modifiers (not roles)
- **Scope** — a grant is `role × scope`. OtOpcUa scopes by OPC-UA node tree
(cluster→area→line→equipment→tag); ScadaBridge scopes `Deployer` by **site**; mxaccessgw
scopes API keys by subtree/tag globs. The canonical layer carries an abstract scope selector;
each project resolves it to its own granularity.
- **Principal type** — humans (LDAP group → canonical role) and machines (API key → a subset of
canonical capabilities) both take canonical roles.
## Mapping to each project
| Canonical | OtOpcUa | MxAccessGateway | ScadaBridge |
|---|---|---|---|
| **Viewer** | data-plane `ReadOnly` bundle; ctrl `ConfigViewer` | dashboard `Viewer`; scopes `invoke:read`+`metadata:read`+`events:read`+`session:*` | `AuditReadOnly` (← audit read); ⚠ no general config-viewer role yet |
| **Operator** | data-plane `Operator` bundle | scope `invoke:write` | ⚠ N/A — runtime ops live at sites, not a central role |
| **Engineer** | data-plane `Engineer` bundle | scope `invoke:secure` (closest) | ⚠ N/A |
| **Designer** | ctrl `ConfigEditor` (+ `WriteConfigure`) | ⚠ N/A — no config-authoring surface | `Design` |
| **Deployer** | ◑ part of `FleetAdmin` (config publish/generation) | ⚠ N/A | `Deployment` (+ site scope) |
| **Administrator** | ctrl `FleetAdmin`; data-plane `Admin` bundle | dashboard `Admin`; scope `admin` | `Admin` (+ `Audit` export ←) |
## Consequences & gaps (accepted)
- **Auditor removed:** ScadaBridge `AuditReadOnly`**Viewer**, `Audit`**Administrator**.
This **loses ScadaBridge's auditor/admin separation-of-duties** (an auditor who can export but
is not a full admin no longer has a distinct role). Accepted as the cost of standardizing.
- Each project implements only the **subset** of canonical roles that applies; the ⚠ cells are
simply never assigned there (ScadaBridge: no Operator/Engineer; mxaccessgw: no Designer/Deployer).
- OtOpcUa has no first-class Deployer (config publish ⊂ `FleetAdmin`) — `Deployer` maps partially
until/unless OtOpcUa splits a publish-only control-plane role.
- Adoption is governance + a mapping layer, not enforcement changes — see [`GAPS.md`](../GAPS.md) backlog.