Commit Graph

1459 Commits

Author SHA1 Message Date
Joseph Doherty ac5db0a9f8 fix(client): TimedShelve milliseconds + shelve node guard + service-layer tests
Important 1: ShelveAlarmAsync Timed branch now multiplies shelvingTimeSeconds × 1000.0
before passing to CallMethodAsync — OPC UA Part 9 TimedShelve ShelvingTime is a Duration
in milliseconds, not seconds. IOpcUaClientService XML doc and ShelveCommand --duration
description updated to document the seconds-in / ms-out contract.

Important 2: ShelveAlarmAsync builds shelvingStateNodeId with the same
EndsWith(".ShelvingState") guard already used by the .Condition suffix in
AcknowledgeAlarmAsync / ConfirmAlarmAsync, preventing double-append.

Important 3: Add 6 service-layer tests to OpcUaClientServiceTests —
  ConfirmAlarmAsync_OnSuccess_ReturnsGood
  ConfirmAlarmAsync_OnServiceResultException_ReturnsBadStatusCode
  ShelveAlarmAsync_OneShot_CallsMethodWithNoArgs
  ShelveAlarmAsync_Timed_PassesDurationInMilliseconds (regression guard for Important 1)
  ShelveAlarmAsync_Unshelve_CallsMethodWithNoArgs
  ShelveAlarmAsync_OnServiceResultException_ReturnsBadStatusCode
FakeSessionAdapter extended with CallMethodInputArgs list to record per-call input
arguments so the Timed test can assert the ms value.

Minor 4: ShelveCommand output changed from "Shelve (OneShot) successful" to
"{shelveKind} successful/failed" so Unshelve reads "Unshelve successful: …".

Minor 6: ShelveCommand --duration description updated to "(must be > 0; in seconds,
converted to milliseconds for the OPC UA call; required for --kind Timed)".
2026-06-11 05:57:40 -04:00
Joseph Doherty 4b38a9d8c8 harden(security): freeze RoleCarryingUserIdentity.Roles to a defensive copy
Code-review follow-up to T17: copy the roles into a fresh array at construction so a
caller mutating the source list cannot retroactively alter a session's granted roles,
and so the T18 ack gate's per-invocation .Contains(...) runs over a known-small frozen
array.
2026-06-11 05:53:11 -04:00
Joseph Doherty 1f172e55f7 feat(client-cli): add ack/confirm/shelve alarm commands with service layer
Adds ConfirmAlarmAsync and ShelveAlarmAsync to IOpcUaClientService and
OpcUaClientService (mirroring the AcknowledgeAlarmAsync pattern: same
CallMethodAsync/ServiceResultException/StatusCode contract). Adds ShelveKind
enum (OneShot/Timed/Unshelve). Adds three new CLI commands — ack, confirm,
shelve — with hex EventId input and per-command argument validation.
Updates both fakes (CLI + UI) to implement the new interface members and
record calls. Adds 16 unit tests covering argument mapping, invalid-input
CommandException paths, bad-status output, and disconnect-in-finally.
2026-06-11 05:46:25 -04:00
Joseph Doherty a6fed85ac9 feat(security): carry LDAP roles onto session identity (T17)
Stop discarding the authenticator's resolved roles during impersonation.
HandleImpersonation now sets args.Identity to a RoleCarryingUserIdentity
(: UserIdentity) that carries result.Roles, so a downstream method handler
can read them off context.UserIdentity for the inbound AlarmAck gate (T18).

Verified via the decompiled SDK (1.5.378.106) that the instance we assign to
ImpersonateEventArgs.Identity is stored by reference onto Session.Identity /
EffectiveIdentity and surfaced unchanged on OperationContext.UserIdentity --
the custom subclass survives the round-trip. No auth-decision logic changes.
2026-06-11 05:42:27 -04:00
Joseph Doherty 2b890fa716 docs(plan): re-scope script-log Layer 2 inbound-ack into T17-T24
The original single T17 (inbound method dispatch + ack plumbing) proved on a
2026-06-11 deep dive to be four hard problems: roles on the session identity
(T17), node-manager command router + AlarmAck veto + alarm-commands DPS topic
(T18), host-actor inbound handler (T19), and delta-gate double-emit (T20). Old
T18->T21 (AdminUI), old T19 split into T22 (Client.CLI feature) + T23 (verify),
old T20->T24. Adds the Layer 2 design-decisions preamble.
2026-06-11 05:37:54 -04:00
Joseph Doherty 74e1abdf32 docs(plan): record disable-login feature merged to master (2ad1dbc8) 2026-06-11 05:37:54 -04:00
Joseph Doherty 2ad1dbc894 fix(security): AutoLoginAuthenticationHandler no-op sign-in/out (avoid 500 on /auth/logout when flag on) 2026-06-11 04:45:29 -04:00
Joseph Doherty 82fec753c8 feat(security): wire Security:Auth:DisableLogin into AddOtOpcUaAuth 2026-06-11 04:39:23 -04:00
Joseph Doherty caeaae21f9 feat(security): AutoLoginAuthenticationHandler for dev login bypass 2026-06-11 04:31:07 -04:00
Joseph Doherty a27e82c8d1 chore(dev): Security:Auth:DisableLogin default off; enable in docker-dev central nodes 2026-06-11 04:29:47 -04:00
Joseph Doherty a92ba6a10b feat(security): add AuthDisableLoginOptions + DevAuthRoles for dev login bypass 2026-06-11 04:26:20 -04:00
Joseph Doherty bc31b6a4de docs(adminui): implementation plan for Security:Auth:DisableLogin dev flag
6-task plan (T0 branch -> T1 options/roles -> T2 handler -> T3 wiring -> T5 verify;
T4 config+docker-dev parallel). AutoLoginAuthenticationHandler registered under the
cookie scheme name so existing policies keep working; enabled in docker-dev.
2026-06-11 04:24:00 -04:00
Joseph Doherty 789176738f docs(adminui): design for Security:Auth:DisableLogin dev flag
Approved brainstorming design: a config flag that disables AdminUI login,
auto-authenticating every request as 'multi-role-test' with all roles via an
always-succeeding AuthenticationHandler registered under the cookie scheme name.
Default off; enabled in docker-dev (central-1/central-2). AdminUI cookie surface
only; OPC UA LDAP + deploy API key untouched.
2026-06-11 04:19:43 -04:00
Joseph Doherty 43e8a37ded chore(plan): mark T0-T16 complete; T17-T20 deferred (Layer 2 partial) 2026-06-11 01:25:17 -04:00
Joseph Doherty 4c417f7fb8 fix(scripted-alarms): log failed event-report via SDK trace + correct sink doc (T16 review) 2026-06-10 19:54:37 -04:00
Joseph Doherty 295bb55dc6 feat(scripted-alarms): fire Part 9 condition events on transition (T16) 2026-06-10 19:50:09 -04:00
Joseph Doherty ab5d0752d8 fix(scripted-alarms): atomic alarm-condition lookup under Lock (T15 review) 2026-06-10 19:45:24 -04:00
Joseph Doherty 4eb1d65e2b feat(scripted-alarms): richer AlarmConditionState bridge to the OPC UA node (T15) 2026-06-10 19:41:16 -04:00
Joseph Doherty b31d7cb03f fix(scripted-alarms): lock CreateVariable + RemoveRootNotifier on rebuild (T14 review) 2026-06-10 19:26:01 -04:00
Joseph Doherty 60d48a2a0a feat(scripted-alarms): materialise real Part 9 AlarmConditionState nodes (T14) 2026-06-10 19:19:10 -04:00
Joseph Doherty 4217b213b0 docs(scripted-alarms): F14b OPC UA Part 9 SDK research notes (T13) 2026-06-10 18:19:52 -04:00
Joseph Doherty a8640a9331 test(scripted-alarms): cover bootstrap-restore path forwarding alarms (T10 review) 2026-06-10 15:24:39 -04:00
Joseph Doherty fc0d43a3dc refactor(scripted-alarms): retire orphaned ScriptedAlarmActor + F9b evaluator (T11) 2026-06-10 15:22:26 -04:00
Joseph Doherty 5256761368 feat(scripted-alarms): spawn + apply ScriptedAlarmHostActor in DriverHostActor (T10) 2026-06-10 15:17:29 -04:00
Joseph Doherty dafaf2faec fix(scripted-alarms): ScriptedAlarmHostActor review fixes — load-gen guard, quiet cancel, parse guard (T9 review) 2026-06-10 15:08:54 -04:00
Joseph Doherty 3b418a54f1 feat(scripted-alarms): ScriptedAlarmHostActor — engine runtime host (T9) 2026-06-10 14:57:42 -04:00
Joseph Doherty c9590c03d0 fix(scripted-alarms): harden artifact boolean decode + direct helper tests (T6 review)
Default HistorizeToAveva/Retain/Enabled to the entity defaults (true) when a
field is absent/null/non-boolean so a partial blob decodes identically to the
composer's view of a default-constructed ScriptedAlarm (byte-parity), and only
call GetBoolean for a genuine true/false token. Add direct ExtractAlarmDependencyRefs
unit tests (overlap dedup + reserved {{equip}} exclusion).
2026-06-10 14:47:24 -04:00
Joseph Doherty 8e8ca9efe8 feat(scripted-alarms): DeploymentArtifact byte-parity for the alarm plan (T6) 2026-06-10 14:41:46 -04:00
Joseph Doherty 55101baaa4 refactor(scripted-alarms): review-fix polish for T5/T7/T8 (observer isolation, warning hoist, doc) 2026-06-10 14:32:49 -04:00
Joseph Doherty b28c6bdb62 feat(scripted-alarms): EquipmentScriptedAlarmPlan + Phase7Composer enrichment (T5) 2026-06-10 14:21:28 -04:00
Joseph Doherty 1c96fe0be0 feat(scripted-alarms): EfAlarmConditionStateStore (T8) 2026-06-10 14:21:19 -04:00
Joseph Doherty 945ccd0b85 feat(scripted-alarms): DependencyMuxTagUpstreamSource (T7)
Concrete ITagUpstreamSource the scripted-alarm host actor pushes
DependencyValueChanged values into and ScriptedAlarmEngine reads/subscribes
from. Thread-safe: ConcurrentDictionary value cache + per-path ImmutableList
observer lists with atomic add/remove and capture-then-invoke fan-out.
ReadTag of an unknown path returns a Bad-quality (0x80000000) snapshot stamped
via the injected clock. Adds the Core.ScriptedAlarms project reference Runtime
needs to see the interface.
2026-06-10 14:20:02 -04:00
Joseph Doherty b5748288df test(scriptlog): prove bridge→broadcaster delivery off the script-logs DPS topic
Composes the one Layer-0 hop existing tests left uncovered together:
ScriptLogSignalRBridge subscribing to the script-logs DPS topic and
fanning a ScriptLogEntry out to the IInProcessBroadcaster<ScriptLogEntry>
singleton resolved from the SAME DI container the /script-log page injects.
Mirrors DriverStatusHubE2eTests. Confirms the server-side topic→page chain
delivers end-to-end (only the live Blazor circuit remains manual).
2026-06-10 13:53:34 -04:00
Joseph Doherty c42a056537 chore(plan): Layer 0 complete (T0-T3) — tracking update 2026-06-10 12:09:56 -04:00
Joseph Doherty 788bb68d1d fix(scripting): companion sink falls back to ScriptId for the main-log mirror (T3 review) 2026-06-10 12:08:29 -04:00
Joseph Doherty bd2dd05a0c feat(scripting): evaluators log through root script logger → script-log page (F8) 2026-06-10 12:03:51 -04:00
Joseph Doherty bf86b3def6 fix(scripting): explicit companion logger + disposable ScriptRootLogger (T2 review) 2026-06-10 11:56:51 -04:00
Joseph Doherty 73014258ef feat(scripting): root script logger + DPS publisher wired in Host 2026-06-10 11:50:50 -04:00
Joseph Doherty 14fe88fc80 feat(scripting): ScriptLogTopicSink — script LogEvent → ScriptLogEntry → publisher 2026-06-10 11:38:54 -04:00
Joseph Doherty 12423899aa docs(plan): script-log emit + scripted-alarm runtime implementation plan + tasks 2026-06-10 11:34:01 -04:00
Joseph Doherty df4c265753 docs(design): script-log engine emit + scripted-alarm runtime (3-layer) 2026-06-10 11:28:13 -04:00
Joseph Doherty ac1e1dfd12 fix(adminui): auto-generate ScriptId (SC-…) + drop the Language picker on ScriptEdit
v2-ci / build (push) Failing after 39s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped
ScriptId is now system-generated on create (mirrors EquipmentId's EQ-{12 hex}
convention, never operator-supplied) and shown read-only when editing. Language
is always CSharp, so the single-option dropdown is removed entirely and set on
save.
2026-06-10 09:07:38 -04:00
Joseph Doherty 27c34a556a docs(scripting): document {{equip}} equipment-relative tag paths 2026-06-10 08:14:25 -04:00
Joseph Doherty 6c23a6763a test(adminui): DB-backed tests for ScriptTagCatalog.GetEquipmentRelativeLeavesAsync 2026-06-10 08:12:52 -04:00
Joseph Doherty a7c1d7f7cb test(adminui): cover divergent-prefix {{equip}} rejection; use EquipToken constant in message 2026-06-10 08:08:13 -04:00
Joseph Doherty c7041a24e7 feat(adminui): {{equip}}-aware hover + {{equip}}. leaf completion in the script editor 2026-06-10 08:04:51 -04:00
Joseph Doherty cadd6c60b7 feat(adminui): reject {{equip}} virtual tags whose equipment has no derivable base 2026-06-10 07:58:38 -04:00
Joseph Doherty 66ea9c56f6 feat(runtime): DeploymentArtifact substitutes {{equip}} (parity with composer) 2026-06-10 07:53:20 -04:00
Joseph Doherty a4b36c54ba feat(opcuaserver): Phase7Composer substitutes {{equip}} per equipment 2026-06-10 07:49:28 -04:00
Joseph Doherty f431504825 feat(commons): EquipmentScriptPaths — derive base + {{equip}} substitution + shared dep extraction 2026-06-10 07:42:14 -04:00