Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 22 additions & 11 deletions docs/NodeManagement.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,15 @@ override the four `StandardServer` service methods themselves.
per-item collection to the matching
`IMasterNodeManager.AddNodesAsync` etc. dispatcher.
3. `MasterNodeManager` looks up the owning NodeManager for every item
(parent's owner for `AddNodes`, target node's owner for the rest)
and asks it to perform the work via the optional
`INodeManagementAsyncNodeManager` interface.
(the requested NodeId namespace, or the BrowseName namespace when the
Server assigns the NodeId, for `AddNodes`; node for `DeleteNodes`; and
source for reference changes)
and validates the matching `PermissionType` before asking it to
perform the work via the optional `INodeManagementAsyncNodeManager`
interface. `AddNodes` requires `AddNode` in the target namespace's
default policy and `AddReference` on the parent. Every Node permission
is evaluated together with the Node's applicable
`AccessRestrictions`.
4. The aggregated per-item results are wrapped in the matching response
envelope and the audit event (`AuditAddNodesEvent`,
`AuditDeleteNodesEvent`, `AuditAddReferencesEvent`,
Expand Down Expand Up @@ -97,11 +103,15 @@ use it as the working example.
NodeManager that has opted in to NodeManagement.
- **DeleteNodes**: routed to the owning NodeManager of the target node.
- **AddReferences / DeleteReferences**: routed to the source node's
owning NodeManager. When the target node lives in a different
NodeManager that has also opted in, the dispatcher mirrors the
complementary (inverse) edge on the target's owning NodeManager —
best-effort; a failure on the target side is logged at Warning level
and does not roll the source side back.
owning NodeManager. Target-side validation and inverse mutation occur
only when the target is explicitly local: `targetServerUri` is empty,
and the `ExpandedNodeId` has neither a server index nor namespace URI.
When that target lives in a different opted-in NodeManager, the
dispatcher resolves the actual source and target `NodeClass`, checks
both local endpoints before mutation, and mirrors the complementary
edge. If the inverse mutation fails or is cancelled, the source
mutation is compensated with an independent bounded cleanup token
before the original failure is returned or rethrown.

## Request handling on `AsyncCustomNodeManager`

Expand All @@ -115,7 +125,7 @@ The default implementation honors the following request fields:
| `ReferenceTypeId` | Must be a `HierarchicalReferences` subtype. |
| `NodeAttributes` | Optional `VariableAttributes` / `ObjectAttributes` are applied to the new node (`DisplayName`, `Description`, `DataType`, `ValueRank`, `AccessLevel`, `UserAccessLevel`, `Historizing`, `MinimumSamplingInterval`, `Value`, `EventNotifier`). |
| `DeleteTargetReferences` | When true, `DeleteNodes` also removes references on other NodeManagers that target the deleted node. |
| `DeleteBidirectional` | When true on `DeleteReferences`, the inverse edge on the target's owning NodeManager is also deleted. |
| `DeleteBidirectional` | When true on `DeleteReferences`, the inverse edge is also deleted only for an explicitly local target. Remote targets remain source-side operations. |

## Error codes returned

Expand All @@ -125,12 +135,13 @@ The default implementation honors the following request fields:
| AddNodes | `BadParentNodeIdInvalid` | `ParentNodeId` is null or unknown. |
| AddNodes | `BadReferenceTypeIdInvalid` | `ReferenceTypeId` is null or unknown. |
| AddNodes | `BadReferenceNotAllowed` | `ReferenceTypeId` is not a hierarchical reference. |
| AddNodes | `BadNodeIdRejected` | `RequestedNewNodeId` is outside this NodeManager's namespace. |
| AddNodes | `BadNodeIdRejected` | The requested or BrowseName namespace has no owning NodeManager, or `RequestedNewNodeId` is outside the selected NodeManager's namespace. |
| AddNodes | `BadNodeIdExists` | `RequestedNewNodeId` already exists. |
| AddNodes | `BadBrowseNameDuplicated` | A sibling beneath the same local parent already uses the browse name. |
| AddNodes | `BadNodeClassInvalid` | Only `Object` and `Variable` are supported by the default implementation. |
| AddNodes | `BadNodeAttributesInvalid` | The supplied attributes extension object does not match the node class. |
| AddNodes / DeleteNodes / AddReferences / DeleteReferences | `BadUserAccessDenied` | The owning NodeManager has not opted in to NodeManagement. |
| AddNodes / DeleteNodes / AddReferences / DeleteReferences | `BadUserAccessDenied` | The owning NodeManager has not opted in to NodeManagement or the Session lacks `AddNode`, `DeleteNode`, `AddReference`, or `RemoveReference` permission. |
Comment thread
marcschier marked this conversation as resolved.
| AddNodes / DeleteNodes / AddReferences / DeleteReferences | `BadSecurityModeInsufficient` | An applicable namespace, parent, source, or local target `AccessRestrictions` policy requires a stronger SecureChannel. |
| DeleteNodes | `BadNodeIdInvalid` / `BadNodeIdUnknown` | The node to delete is null or unknown. |
| AddReferences | `BadSourceNodeIdInvalid` | Source is null or unknown to this NodeManager. |
| AddReferences | `BadTargetNodeIdInvalid` | Target is null. |
Expand Down
3 changes: 2 additions & 1 deletion src/Opc.Ua.Server/NodeManager/INodeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -713,7 +713,8 @@ public interface INodeManagementAsyncNodeManager

/// <summary>
/// Adds a single node defined by <paramref name="item"/>. The implementation
/// owns the parent node identified by <see cref="AddNodesItem.ParentNodeId"/>.
/// owns the target namespace identified by the requested NodeId, or by the
/// BrowseName when the Server assigns the NodeId.
/// </summary>
/// <param name="context">The operation context.</param>
/// <param name="item">The AddNodesItem to process.</param>
Expand Down
Loading
Loading