docs(rules): scripted-alarm commands authorize at the owning equipment (#797); #808 gap
v2-ci / unit-tests (push) Successful in 1h8m48s

This commit is contained in:
Joseph Doherty
2026-11-10 22:28:58 -05:00
parent 047491d90e
commit 308b1b3b56
+16
View File
@@ -87,6 +87,22 @@ Two things to know before relying on any of this:
identifier is an ordinary Area), and its Browse considers transit in **either** realm because it
fronts both trees. Before this every narrow Browse grant was unreachable by navigation — the Browse
gate denies the whole call when its source node is denied, so clients were stopped at the front door.
- **Scripted-alarm commands are authorized at the OWNING EQUIPMENT, never by splitting the id (#797).**
Production `ScriptedAlarmId`s are opaque (`^[A-Za-z0-9_-]+$`, e.g. `scripted-eqa-hi`) and become the
condition NodeId, so `BuildScope` on them can never match an Equipment grant. Two halves, both re-read
per call and uncached: (1) the node manager binds each live condition **instance** to its `EquipmentId`
in `MaterialiseAlarmCondition` (only when parented under that equipment's folder; cleared on every
teardown + rebuild); (2) the authority generation carries `EquipmentScopePaths` (built by the same
`AclScopePathResolver` call that places Equipment grants) **and** `ScriptedAlarmOwners`
(alarmId → EquipmentId from the artifact). `DataPlaneAuthorizer.AuthorizeScriptedCondition` denies
unless the bound instance is the live one AND its equipment equals the generation's owner — this
closes the install-authority-then-rebuild window and a failed apply leaving a moved alarm on its old
equipment. ⚠️ **Fail closed, even for Cluster grants:** an unbound / replaced / undeployed / line-less
owner is denied under every grant (no realm-root fallback). Native alarms still use RawPath; ACL-off
is unchanged. ⚠️ **Not end-to-end yet — #808:** UNS folders and scripted condition children still
split opaque ids for Read/Browse/Subscribe/Server-object event visibility, so a narrow principal can't
obtain the EventId Ack/Confirm/AddComment need (Shelve/Enable work). `ServerEventRig`'s folder id
`EqA` == scope path `[uns, EqA]` hides this — tests must use opaque `UA-/UL-/EQ-` ids.
- **Revocation reaches live subscriptions** (stage 6): every other operation re-asks per request, but a
subscription is authorized once and then streams — and streaming is how machine consumers actually
read this server. `DataPlaneAuthorityState.Changed` fires `RevalidateMonitoredItems`. ⚠️ A denied