Merge fix/826-folder-event-acl
This commit is contained in:
+31
-2
@@ -600,9 +600,13 @@ and Write under old and new names until the address space re-points them. An id
|
||||
folder / virtual tag / condition, a probe, a NodeDeleted model change) is decided only by a `Cluster` or `uns`
|
||||
`Namespace` grant — so narrow grantees do not receive NodeDeleted for removed opaque-id nodes, and a removed id can
|
||||
never match an unrelated narrow grant that shares its name; a four-segment (reference-shaped) id keeps its split.
|
||||
Identifiers containing NUL are refused. Server-object (`i=2253`) delivery of a
|
||||
Identifiers containing NUL are refused. A UNS variable the reference pass wired to its raw node (the `Organizes`
|
||||
edge) is placed as a reference variable whatever its id spells (Gitea #826 — the id rule alone made an equipment's
|
||||
references folder-owned when an Area was named exactly like that equipment's id, losing their `Tag`-grant match).
|
||||
Server-object (`i=2253`) delivery of a
|
||||
**scripted** condition is now decided on the condition alone (its folders add nothing in steady state and would
|
||||
leak a moved alarm to its old owner). So a key holding only an `Equipment` grant can navigate to its equipment,
|
||||
leak a moved alarm to its old owner). Direct event items on a folder get the same per-event decision (Gitea #826,
|
||||
below). So a key holding only an `Equipment` grant can navigate to its equipment,
|
||||
read its alarm children, receive its scripted alarm events through the Server object and Acknowledge / Confirm /
|
||||
AddComment with the EventId it received. Fail-closed throughout: an unplaceable node is denied under every grant.
|
||||
| HistoryRead (all four variants) | **nothing** | `HistoryRead` on each node's scope, decided **per node in the batch** |
|
||||
@@ -709,6 +713,31 @@ Behaviours worth knowing before enabling it:
|
||||
condition) runs on removal, rebuild and Server-object subscribe/delete. A deploy of N alarms under a
|
||||
live Server-object item is therefore N bookkeeping steps, not N²/2 under the node-manager lock.
|
||||
|
||||
**Direct (per-folder) event items are filtered per event too** (Gitea #826). An item on an equipment or raw
|
||||
device folder is fed by the SDK's own per-notifier fan-out (`MonitoredNode2`), which the #586 dispatcher never
|
||||
touches — so after a deployment moved a scripted alarm (or dropped the reference projecting a native alarm into
|
||||
an equipment), the OLD folder's subscribers kept receiving it, EventId included, until the rebuild landed, and
|
||||
indefinitely after a failed apply (commands were already denied). With the flag **on**, each event to such an
|
||||
item now also needs, against the CURRENT state:
|
||||
- the event's condition to be the **live** instance (a torn-down one is withheld);
|
||||
- the folder to still be a legitimate notifier of it — a node it hangs beneath, or a folder it is wired into
|
||||
**that the current generation still projects its raw tag into** (`DataPlaneAuthoritySnapshot.TagReferencingEquipment`,
|
||||
`RawPath → EquipmentIds`, decoded from the artifact's `UnsTagReferences` by the same resolver as the grants);
|
||||
- and the condition to pass exactly the Server-object rule above for the item's session.
|
||||
|
||||
The generation check also narrows the **Server-object** rule: a wired folder whose reference the generation
|
||||
dropped no longer admits the native alarm there either. **`ConditionRefresh`** on a folder item is filtered the
|
||||
same way. The hook is `INodeManager3.ValidateEventRolePermissions`, which the node manager re-implements (the
|
||||
base method is not virtual); the SDK memoizes that verdict per `(item, event type, SourceNode)`, so the node
|
||||
manager clears each notifier's cache whole (sessions and orphaned, session-less subscriptions alike — an orphaned
|
||||
subscription must not queue a moved alarm's events for a later `TransferSubscriptions`) on every new generation or
|
||||
authorizer, on each `AclRevalidationTimer` tick, and at the end of every apply, and not at all while enforcement is
|
||||
off. A verdict is decided on the condition currently live under the event's NodeId, so a replaced instance's late
|
||||
event cannot leave a deny behind for its successor. Only alarm-bearing raw tags are carried in the reference map. Withheld events are not replayed and the client is not told; restoring the reference or
|
||||
grant resumes the feed on the next event. ⚠️ A native alarm reaches an equipment folder's items under
|
||||
enforcement only while the installed generation carries that reference — a hand-built authority (tests) must
|
||||
supply `tagReferencingEquipment`. Inert with the flag off.
|
||||
|
||||
**Model-change and audit events on the Server object are gated too** (Gitea #588). The node manager's
|
||||
own server-wide events — `GeneralModelChangeEvent` (NodeAdded / NodeDeleted / DataTypeChanged) and the
|
||||
`AuditWriteUpdateEvent` of a rejected device write — used to go straight to `Server.ReportEvent`, where
|
||||
|
||||
Reference in New Issue
Block a user