Files
lmxopcua/scripts/validation/opcua-scripted-alarm-baseline/README.md
T
Joseph Doherty 3d1b86b451 fix(acl): authorize scripted alarm commands at their owning equipment's scope (#797)
Scripted condition NodeIds are opaque ScriptedAlarmIds, so splitting them as a
topology path could never match an Equipment grant: a narrow equipment grant was
denied while a Cluster grant passed.

- OtOpcUaNodeManager binds each LIVE scripted condition instance to the
  EquipmentId it was materialised under (only when it hangs under that folder);
  dropped on remove / drop-recreate / equipment-subtree removal / rebuild; a
  same-id re-materialise under another equipment re-parents and re-binds.
- DataPlaneAuthoritySnapshot carries EquipmentScopePaths (EquipmentId ->
  [uns, Area, Line, Equipment]) decoded from the artifact by the same
  AclScopePathResolver call that plants Equipment grants.
- DataPlaneAuthorizer.AuthorizeScriptedCondition re-reads key, grant and
  generation per call (uncached) and evaluates at the owner path; unbound,
  replaced or unplaceable owners deny under every grant. No id-split or
  realm-root fallback.
- Native conditions (RawPath) and the ACL-off role gate are unchanged.
  NodeIds and AlarmCommand.AlarmId are unchanged.

Sdk2OpaqueScriptedScopeBaselineTests deliberately flipped: it pinned the denial
and now pins owner-grant allow / sibling deny / cluster allow. Follow-up #808
(folder ids + Server-object event visibility for narrow UNS grants).
2026-11-10 21:23:57 -05:00

2.1 KiB

Independent scripted-alarm scope baseline

This SDK 1.5.378.182-only source probe records the existing opaque-ID behavior tracked by #797. It is deliberately outside the candidate solution and is not a runtime adapter.

Use a clean, separate checkout at original application commit 83ed880e4471344deaf008da9bd028c7e170bdc7. Confirm its package pins before running. Copy only ScriptedScopeProbe.cs temporarily into that checkout's tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests/, refusing to overwrite an existing file. Run:

dotnet test tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests \
  -c Release --filter FullyQualifiedName~BaselineScriptedScopeProbe \
  --logger trx --results-directory /absolute/fresh-baseline-evidence

Preserve the test exit and run the baseline checkout's scripts/ci/assert-not-all-skipped.sh with MIN_EXECUTED=1 against the fresh TRX. Remove only the temporary probe you copied after the run, keeping the source and TRX evidence here/outside the checkout. Verify baseline tracked files remain unchanged. Never load this assembly or old SDK into the candidate process.

The real session has no application-wide roles. The production-valid opaque scripted ID is denied by an Equipment grant, routes nothing, and is then allowed by an explicit Cluster grant. A passing probe pins both outcomes; it does not claim narrow equipment authorization works. The candidate counterpart Sdk2OpaqueScriptedScopeBaselineTests pinned the same denial until #797 was fixed; it now pins the fixed behaviour (owning equipment grant allows, sibling equipment grant denies, cluster grant still allows). This probe remains the record of the pre-fix behaviour on the original commit.

Do not make the ID slash-qualified to get a positive result: the current UI rejects /, and that would hide the production scope-resolution defect. A future fix requires reviewed ownership/scope binding without changing opaque IDs or widening permissions. This upgrade preserves the baseline denial and links the separate defect.