docs: close native-alarm spec gaps surfaced by docs audit
The native alarms feature merged with 7 component docs updated, but the spec layer drifted: HighLevelReqs, Commons, and ManagementService had no native-alarm coverage and the README table flagged it on only one row. Add HighLevelReqs §3.4.2 (+ validation), document the Commons types/entities/messages and the 7 ManagementService commands, sync the README rows + link the TreeView sub-component, fix 2 broken plan links, and drop the one-off native-alarms RESUME scratchpad.
This commit is contained in:
@@ -44,9 +44,9 @@ Both stacks share the infrastructure services in [`infra/`](infra/) (MS SQL, LDA
|
||||
|---|-----------|----------|-------------|
|
||||
| 1 | Template Engine | [docs/requirements/Component-TemplateEngine.md](docs/requirements/Component-TemplateEngine.md) | Template modeling, inheritance, composition, path-qualified member addressing, override granularity, locking, alarms, native alarm source bindings, flattening, semantic validation, revision hashing, diff calculation, and folder organization (nested folders, drag-drop). |
|
||||
| 2 | Deployment Manager | [docs/requirements/Component-DeploymentManager.md](docs/requirements/Component-DeploymentManager.md) | Central-side deployment pipeline with deployment ID/idempotency, per-instance operation lock, state transition matrix, all-or-nothing site apply, system-wide artifact deployment with per-site status. |
|
||||
| 3 | Site Runtime | [docs/requirements/Component-SiteRuntime.md](docs/requirements/Component-SiteRuntime.md) | Site-side actor hierarchy with explicit supervision strategies, staggered startup, script trust model (constrained APIs), Tell/Ask conventions, concurrency serialization, and site-wide Akka stream with per-subscriber backpressure. |
|
||||
| 4 | Data Connection Layer | [docs/requirements/Component-DataConnectionLayer.md](docs/requirements/Component-DataConnectionLayer.md) | Common data connection interface (OPC UA, MxGateway, custom), Become/Stash connection actor model, auto-reconnect, immediate bad quality on disconnect, transparent re-subscribe, synchronous write failures, tag path resolution retry, protocol-agnostic address-space browse. |
|
||||
| 5 | Central–Site Communication | [docs/requirements/Component-Communication.md](docs/requirements/Component-Communication.md) | Dual transport: Akka.NET ClusterClient (command/control) + gRPC server-streaming (real-time data). 9 message patterns with per-pattern timeouts, SiteStreamGrpcServer/Client, application-level correlation IDs, transport heartbeat config, gRPC keepalive, message ordering, connection failure behavior. |
|
||||
| 3 | Site Runtime | [docs/requirements/Component-SiteRuntime.md](docs/requirements/Component-SiteRuntime.md) | Site-side actor hierarchy with explicit supervision strategies, staggered startup, script trust model (constrained APIs), Tell/Ask conventions, concurrency serialization, site-wide Akka stream with per-subscriber backpressure, and a read-only Native Alarm Actor (peer to the computed Alarm Actor) mirroring native OPC UA A&C / MxAccess alarms with site SQLite persistence. |
|
||||
| 4 | Data Connection Layer | [docs/requirements/Component-DataConnectionLayer.md](docs/requirements/Component-DataConnectionLayer.md) | Common data connection interface (OPC UA, MxGateway, custom), Become/Stash connection actor model, auto-reconnect, immediate bad quality on disconnect, transparent re-subscribe, synchronous write failures, tag path resolution retry, protocol-agnostic address-space browse, and optional read-only native alarm mirroring (`IAlarmSubscribableConnection`, one alarm feed per connection with snapshot replay). |
|
||||
| 5 | Central–Site Communication | [docs/requirements/Component-Communication.md](docs/requirements/Component-Communication.md) | Dual transport: Akka.NET ClusterClient (command/control) + gRPC server-streaming (real-time data). 9 message patterns with per-pattern timeouts, SiteStreamGrpcServer/Client, application-level correlation IDs, transport heartbeat config, gRPC keepalive, message ordering, connection failure behavior. The gRPC stream additively carries the read-only native alarm mirror (computed + native OPC UA / MxAccess) via the enriched `AlarmStateUpdate`. |
|
||||
| 6 | Store-and-Forward Engine | [docs/requirements/Component-StoreAndForward.md](docs/requirements/Component-StoreAndForward.md) | Buffering (transient failures only), fixed-interval retry, parking, async best-effort replication, SQLite persistence at sites. |
|
||||
| 7 | External System Gateway | [docs/requirements/Component-ExternalSystemGateway.md](docs/requirements/Component-ExternalSystemGateway.md) | HTTP/REST + JSON, API key/Basic Auth, per-system timeout, dual call modes (Call/CachedCall), transient/permanent error classification, dedicated blocking I/O dispatcher, ADO.NET connection pooling. |
|
||||
| 8 | Notification Service | [docs/requirements/Component-NotificationService.md](docs/requirements/Component-NotificationService.md) | Central-only — manages typed notification-list and SMTP definitions, supplies per-type delivery adapters (SMTP with OAuth2 (M365) or Basic Auth, BCC, plain text); delivery performed by the Notification Outbox. |
|
||||
@@ -57,8 +57,8 @@ Both stacks share the infrastructure services in [`infra/`](infra/) (MS SQL, LDA
|
||||
| 13 | Cluster Infrastructure | [docs/requirements/Component-ClusterInfrastructure.md](docs/requirements/Component-ClusterInfrastructure.md) | Akka.NET cluster, keep-oldest SBR with down-if-alone, min-nr-of-members=1, 2s/10s/15s failure detection, CoordinatedShutdown, automatic dual-node recovery. The `ClusterInfrastructure` project owns the `ClusterOptions` config model; the Akka bootstrap/SBR/CoordinatedShutdown wiring lives in the Host. |
|
||||
| 14 | Inbound API | [docs/requirements/Component-InboundAPI.md](docs/requirements/Component-InboundAPI.md) | POST /api/{methodName}, X-API-Key header, flat JSON, extended type system (Object/List), script-based implementations, failures-only logging. |
|
||||
| 15 | Host | [docs/requirements/Component-Host.md](docs/requirements/Component-Host.md) | Single deployable binary, role-based component registration, per-component config binding (Options pattern), readiness gating, dead letter monitoring, Akka.NET bootstrap, ASP.NET Core hosting for central. |
|
||||
| 16 | Commons | [docs/requirements/Component-Commons.md](docs/requirements/Component-Commons.md) | Namespace/folder convention (Types/Interfaces/Entities/Messages), shared data types, POCOs, repository interfaces, message contracts with additive-only versioning, UTC timestamp convention. |
|
||||
| 17 | Configuration Database | [docs/requirements/Component-ConfigurationDatabase.md](docs/requirements/Component-ConfigurationDatabase.md) | EF Core data access, per-component repositories, unit-of-work, optimistic concurrency on deployment status, audit logging (IAuditService), migration management. |
|
||||
| 16 | Commons | [docs/requirements/Component-Commons.md](docs/requirements/Component-Commons.md) | Namespace/folder convention (Types/Interfaces/Entities/Messages), shared data types, POCOs, repository interfaces, message contracts with additive-only versioning, UTC timestamp convention, the unified read-only alarm condition model (`AlarmConditionState`/`AlarmKind`), and native alarm source entities + the `IAlarmSubscribableConnection` capability seam. |
|
||||
| 17 | Configuration Database | [docs/requirements/Component-ConfigurationDatabase.md](docs/requirements/Component-ConfigurationDatabase.md) | EF Core data access, per-component repositories, unit-of-work, optimistic concurrency on deployment status, audit logging (IAuditService), migration management (incl. the `AddNativeAlarmSources` migration + native alarm source repository CRUD). |
|
||||
| 18 | Management Service | [docs/requirements/Component-ManagementService.md](docs/requirements/Component-ManagementService.md) | Akka.NET ManagementActor on central, ClusterClientReceptionist registration, programmatic access to all admin operations, CLI interface. |
|
||||
| 19 | CLI | [docs/requirements/Component-CLI.md](docs/requirements/Component-CLI.md) | Standalone command-line tool, System.CommandLine, HTTP transport via Management API, JSON/table output, mirrors all Management Service operations. |
|
||||
| 20 | Traefik Proxy | [docs/requirements/Component-TraefikProxy.md](docs/requirements/Component-TraefikProxy.md) | Reverse proxy/load balancer fronting central cluster, active node routing via `/health/active`, automatic failover. |
|
||||
@@ -67,6 +67,8 @@ Both stacks share the infrastructure services in [`infra/`](infra/) (MS SQL, LDA
|
||||
| 23 | Audit Log | [docs/requirements/Component-AuditLog.md](docs/requirements/Component-AuditLog.md) | New central append-only AuditLog spanning every script-trust-boundary action (outbound API sync+cached, outbound DB sync+cached, notifications, inbound API). Site-local SQLite hot-path append + gRPC telemetry + central reconciliation; combined telemetry packet with Site Call Audit; central direct-write for Notification Outbox dispatch + Inbound API middleware; monthly partitioning, 365-day default retention. |
|
||||
| 24 | Transport | [docs/requirements/Component-Transport.md](docs/requirements/Component-Transport.md) | Bundle export/import for templates, shared scripts, external systems, central-only artifacts. AES-256-GCM encryption; per-conflict resolution on import; correlated audit trail. |
|
||||
|
||||
**Shared UI sub-component** (not a top-level component): [TreeView](docs/requirements/Component-TreeView.md) — reusable hierarchical tree/grid Blazor component used by the Central UI (#9) for the templates folder hierarchy, data-connection browse, and tag pickers.
|
||||
|
||||
### Reference Documentation
|
||||
|
||||
- [AkkaDotNet/](AkkaDotNet/) — Akka.NET reference notes covering actors, remoting, clustering, persistence, streams, serialization, hosting, testing, and best practices.
|
||||
|
||||
@@ -760,7 +760,7 @@ Mirrors `docker/README.md`'s structure but documents the env2 specifics. Reuses
|
||||
|
||||
A second Docker deployment of a minimal ScadaBridge cluster topology, designed to run **concurrently with** the primary `docker/` stack so the Transport (#24) feature can be exercised end-to-end across two real environments.
|
||||
|
||||
See [`docs/plans/2026-05-24-second-environment-design.md`](../docs/plans/2026-05-24-second-environment-design.md) for the design rationale.
|
||||
See [`docs/plans/2026-05-24-second-environment-design.md`](2026-05-24-second-environment-design.md) for the design rationale.
|
||||
|
||||
## Cluster Topology
|
||||
|
||||
@@ -886,7 +886,7 @@ Same as primary (env2 shares LDAP). See `infra/glauth/config.toml` and primary `
|
||||
|
||||
## Transport Testing Workflow
|
||||
|
||||
See [`docs/plans/2026-05-24-second-environment-verification.md`](../docs/plans/2026-05-24-second-environment-verification.md) for the manual golden-path checklist.
|
||||
See [`docs/plans/2026-05-24-second-environment-verification.md`](2026-05-24-second-environment-verification.md) for the manual golden-path checklist.
|
||||
|
||||
## What's Different from Primary
|
||||
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
# Native Alarms — Execution Resume Notes
|
||||
|
||||
**Skill in progress:** `superpowers-extended-cc:executing-plans` on `docs/plans/2026-05-29-native-alarms.md`.
|
||||
**To resume:** `/superpowers-extended-cc:executing-plans docs/plans/2026-05-29-native-alarms.md` (reads `…md.tasks.json`).
|
||||
|
||||
## Workspace
|
||||
- **Worktree:** `/Users/dohertj2/Desktop/scadalink-design-native-alarms` (branch `feat/native-alarms`, off `main` @ `09e19db` which holds the design + plan).
|
||||
- Do all work here; `main` checkout stays untouched. Build: `dotnet build ZB.MOM.WW.ScadaBridge.slnx`.
|
||||
- The shared MS SQL container `scadabridge-mssql` is up (the ConfigDB MsSql migration-fixture tests use it).
|
||||
|
||||
## Progress: ALL 28 TASKS DONE & COMMITTED ✅
|
||||
|
||||
## T28 (live integration) — results & a real bug it caught
|
||||
- **OPC UA A&C live smoke** `[SkippableFact]` **PASSED** against the infra OPC PLC server (real ConditionRefresh snapshot round-trip) — opc-plc DOES expose A&C; noted in test_infra.md.
|
||||
- **Full build + `dotnet test ZB.MOM.WW.ScadaBridge.slnx`: zero native-alarm regressions.** Every project I touched passes in isolation (SiteRuntime 314, CentralUI 584, DCL 104, ManagementService 111, Communication 200, TemplateEngine 332, ConfigDB 248). Pre-existing/known-flaky failures only: Commons `StaleTagMonitor*` (5, timing), 1 SiteRuntime parallelism flake (314/314 isolated), AuditLog (2) + IntegrationTests (2, `near "IF"` SQLite) — the latter **confirmed failing identically on `main`**.
|
||||
- **env2 cluster rebuilt** with the new image; **backend verified live** (`template native-alarm-source add`/`list` round-trip through the rebuilt ManagementActor; instance deployed).
|
||||
- **UI verified live via Claude-for-Chrome** at env2 Traefik LB `:9100`: template editor **Native Alarms tab** lists `GalaxyAlarms` + Add-modal connection dropdown filtered to alarm-capable (MxGateway) conns; instance **Native Alarm Source Overrides** card; Debug View **enriched alarm table (Kind + Sev columns)** + connects live ("Streaming MxAlarmDemo-1").
|
||||
- **RUNTIME BUG found live + fixed (`add7210`):** the NativeAlarmActor sends `SubscribeAlarmsRequest` to the DCL **manager**, but `DataConnectionManagerActor` only routed tag/write/browse — alarm subscribe/unsubscribe were **unhandled → dead-lettered**, so native alarms never subscribed. Unit tests missed it (T15 used a probe, T10 tested the connection actor directly). Added `HandleRouteAlarms` forwarding (mirrors `HandleRoute`) + regression test. **Re-verified live:** after rebuild, the logs show `[ScadaBridge Site X] Alarm feed subscribed for source $Area_001` → `Native alarm subscription established for GalaxyAlarms` — full chain InstanceActor→NativeAlarmActor→DCL manager→DataConnectionActor→**live MxAccess Gateway** working. (No transitions flowed only because `$Area_001` had no active alarms at the time.)
|
||||
- **T26 seed bug found live + fixed (`f4ae44a`):** `instance deploy` used `--instance-id`; corrected to `--id`.
|
||||
|
||||
## (historical) Progress: Tasks 1–27 done & committed; only T28 pending
|
||||
Commits (oldest→newest): `696da92` T1 … `3bf1d26` T21, `a6dcbf6` T22, `1f6c420` T23, T24, `046797e` T25, `2b7c765` T26, `003e54c` T27. (Full list in git log.)
|
||||
|
||||
**Cadence is batches of 3 (user choice on resume).** Batches 4–8 (T13–27) all ✅. Greens: SiteRuntime 313/313, Communication 200/200, ManagementService 111/111, CentralUI 581/581, Commons registry 8/8, CLI CommandTree 21/21. **Next & final: T28 (integration / live verification).**
|
||||
|
||||
## Decisions / deviations — Batch 8 (T25–27)
|
||||
- **T25:** InstanceConfigure "Native Alarm Source Overrides" card — inline per-row override (connection dropdown / source-ref / filter; blank=inherited), repo-direct upsert/clear + SaveChangesAsync (same rationale as T24). **Structural test** (source assertions) — InstanceConfigure is heavy (7 services incl. InstanceService + IFlatteningPipeline); CRUD behavior covered by T21. Lists the *template's direct* native sources (mirrors how the Alarm Overrides card uses `GetAlarmsByTemplateIdAsync`, not full flatten).
|
||||
- **T26:** seed-sites.sh adds a `MxAlarmDemo` template + `GalaxyAlarms` native source (connection "ScadaBridge Site X", source-ref `$Area_001`) + deployed `MxAlarmDemo-1` instance. **bash -n valid.** Live-verified the CLI→cluster path: `template create` works against the running env2 (:9100); `AddTemplateNativeAlarmSource` returns "Unknown command" because the **running env2 image is pre-T21** — proves the seed/commands are correct but full live run needs a cluster rebuild (`docker-env2/deploy.sh`), which is **T28's** job. Cleaned up the test template afterward (env2 templates back to []).
|
||||
- **T27:** CLAUDE.md (Native Alarms bullet under Data & Communication) + README (Template Engine row) inline; 7 component docs (DCL/SiteRuntime/TemplateEngine/CentralUI/CLI/Communication/ConfigurationDatabase) via 7 parallel `documenter` subagents. All landed (+265 lines).
|
||||
|
||||
## T28 plan (final)
|
||||
- Add `OpcUaAlarmLiveSmokeTests` SkippableFact (skips when no alarm-capable OPC UA endpoint) mirroring the existing live OPC UA smoke pattern; note infra OPC UA A&C support in `docs/test_infra/test_infra.md`.
|
||||
- Full `dotnet build` + `dotnet test ZB.MOM.WW.ScadaBridge.slnx`. Watch known-flaky: 5 StaleTagMonitor*Tests (Commons.Tests) + `CliConfigTests.Load_MalformedConfigFile` (parallelism race) — NOT regressions.
|
||||
- Rebuild cluster: `bash docker-env2/deploy.sh` (or docker/deploy.sh), then re-run `docker-env2/seed-sites.sh` and confirm native alarms appear in the Central UI Debug View with severity + condition badges.
|
||||
|
||||
## Decisions / deviations — Batch 7 (T22–24)
|
||||
- **T22:** CLI `template native-alarm-source add/list/remove` + `instance native-alarm-source set/clear` + README. **Known-flaky:** `CliConfigTests.Load_MalformedConfigFile…` fails ~deterministically in the FULL CLI suite (passes in isolation) due to process-global `HOME`/`Console.SetError` racing under xUnit parallelism — **confirmed pre-existing** (baseline fails 3/3 full runs; my added tests merely perturbed scheduling). Not my regression; treat as known-flaky like the StaleTagMonitor set.
|
||||
- **T23:** DebugView alarm table enriched — added Kind + Sev columns, folded SourceReference into the Alarm cell (monospace subtitle), condition badges (Unacked/Shelved/Suppressed) into the State cell, Type/Category/operator/raise-time/value into the row tooltip; `FilteredAlarmStates` also matches SourceReference. bUnit test sets `_connected`/`_snapshot`/`_alarmStates` via reflection then asserts markup.
|
||||
- **T24:** Template editor got a new **"Native Alarms" tab** (not a sub-panel) — fits the existing tabbed editor. **Repo-direct, NOT the plan's "management HTTP client":** TemplateEdit is Blazor Server in-process and calls `ITemplateEngineRepository` + `SaveChangesAsync` directly (mirrors how `_alarms` load/save works). Connection dropdown loads alarm-capable (OpcUa/MxGateway) connections via `ICentralUiRepository.GetAllDataConnectionsAsync` deduped by name. **Test is structural** (source-text assertions like `TestRunWarningTests`), NOT a full interactive bUnit render — TemplateEdit has ~10 injected services with their own graphs (ScriptAnalysisService/IMemoryCache/ISharedScriptCatalog/BuildParentContextsAsync/GetInstancesFilteredAsync…); the codebase has no precedent for fully rendering it, and the CRUD path is already covered behaviorally by the T21 ManagementActor tests. **T25 (InstanceConfigure) may be lighter to full-render — check first.**
|
||||
|
||||
## Decisions / deviations — Batch 6 (T19–21)
|
||||
- **T19:** `AlarmShelveStateCodec` (string↔enum, default Unshelved). Server `StreamRelayActor` maps `msg.Condition.*` + `Kind.ToString()` + nullable `OriginalRaiseTime` out; client `ConvertToDomainEvent` rebuilds `Condition` (severity = wire `Priority`) + `ParseAlarmKind` back. **Gotcha:** client imports `Google.Protobuf.WellKnownTypes`, so `Enum` is ambiguous — used `System.Enum.TryParse`. `confirmed` proto bool → domain `bool?` (false, never null after round-trip).
|
||||
- **T20:** `ManagementCommandRegistry` is **reflection-based** (auto-discovers `*Command` records in the Management namespace) — no manual registry edit needed; just added the 7 records to TemplateCommands.cs / InstanceCommands.cs.
|
||||
- **T21:** Handlers call `ITemplateEngineRepository` **directly** + `SaveChangesAsync` (per plan's "call the Task 6 repo methods"), NOT through TemplateService/InstanceService. **Trade-off:** this skips the service-layer `IAuditService` logging that the existing template/instance alarm CRUD gets. Acceptable for the read-only-mirror authoring commands and matches the plan's Files scope (ManagementService only), but flag if audit parity is wanted later. Roles: template mutations = Design, instance-override mutations = Deployment, lists = any authenticated. Update = fetch-then-mutate (preserves TemplateId for the unique index). Set-override = upsert (Add if absent else Update).
|
||||
|
||||
## Decisions / deviations — Batch 5 (T16–18)
|
||||
- **T16:** Connection protocol IS in `FlattenedConfiguration.Connections[name].Protocol` → `ResolveNativeKind` maps protocol-contains-"Mx" → `NativeMxAccess` else `NativeOpcUa`; passed into NativeAlarmActor. Added `_latestAlarmEvents` (enriched event per AlarmName) + extracted `BuildAlarmStatesSnapshot()` used by both `HandleSubscribeDebugView` and `HandleDebugSnapshot` (enriched events ∪ Normal-projection fallback for computed alarms that haven't fired). Native actors skipped when `_dclManager == null` (isolated tests). **Beyond the plan's Files list (justified):** redeploy/undeploy clear — added `native_alarm_state` DELETE to `SiteStorageService.RemoveDeployedConfigAsync` transaction (undeploy) + `ClearNativeAlarmsForInstanceAsync` next to `ClearStaticOverridesAsync` in `DeploymentManagerActor` redeploy path. Native state survives failover (rehydrate) but resets on redeploy — mirrors static-override semantics.
|
||||
- **T17:** Test-only (as the plan predicted) — `AlarmStateChanged.Condition` getter already defaults to `ForComputed(State, Priority)` from T2, so computed alarms carry the unified condition without code change. Added regression `AlarmActor_ComputedAlarm_CarriesUnifiedConditionState`.
|
||||
- **T18:** Proto regen done via the documented macOS manual flow (uncomment `<Protobuf>` → delete vendored → build → copy `obj/Debug/net10.0/Protos/*.cs` → re-comment). csproj nets to no change. Only `Sitestream.cs` changed (service `SitestreamGrpc.cs` untouched — message-only change). `confirmed` is proto `bool` per plan (null→false fidelity loss accepted). New fields 8–21 on `AlarmStateUpdate`.
|
||||
|
||||
## Decisions / deviations made during execution — Batch 4 (T13–15)
|
||||
- **T15:** `NativeAlarmActor` ctor has an optional trailing `AlarmKind nativeKind = AlarmKind.NativeOpcUa` (additive — keeps the 7-arg call working). T16 will pass `NativeMxAccess` when the connection protocol is MxGateway. Persistence is **fire-and-forget** (`ContinueWith` OnlyOnFaulted logs) — never blocks the actor. State keyed by `SourceReference`; `AlarmName` on the emitted `AlarmStateChanged` is set to the `SourceReference`. Snapshot path: `Snapshot` buffers, `SnapshotComplete` atomic-swaps (dropped → emit `Active=false`). Live path ignores older `TransitionTime`; retention drops a condition once `!Active && Acknowledged`. `NativeAlarmSourceUnavailable` = log + retain (no emit). Subscribe retry via `ScheduleTellOnceCancelable` at `NativeAlarmRetryIntervalMs`.
|
||||
|
||||
## Known-flaky baseline (NOT my regressions)
|
||||
- 5 `StaleTagMonitor*Tests` in `ZB.MOM.WW.ScadaBridge.Commons.Tests` are timing-flaky under load. User approved treating as known-flaky; do not "fix". Watch only for NEW failures.
|
||||
|
||||
## Decisions / deviations made during execution (carry forward)
|
||||
- **T2:** `AlarmStateChanged.Condition` is a computed-default property (getter falls back to `AlarmConditionStateFactory.ForComputed(State, Priority)`); additions are init-props (additive). `AlarmConditionStateFactory` lives in `Commons/Types/Alarms`.
|
||||
- **T8:** `ResolvedNativeAlarmSource` has **no `IsLocked`** field (per plan). Inheritance lock is enforced via a **local `lockedNames` HashSet** inside `ResolveInheritedNativeAlarmSources`. Override-lock is NOT enforced at flatten (matches plan; UI/validation layer handles it).
|
||||
- **T9:** `SemanticValidator.Validate` gained an **optional** 3rd param `IReadOnlySet<string>? alarmCapableConnectionNames = null`. Connection-existence check only runs when callers pass it; empty source-ref / empty connection-name always checked. `ValidationCategory.NativeAlarmSourceInvalid` added. (Wiring real callers to pass the connection set is not yet done — fine for now.)
|
||||
- **T10:** `DataConnectionActor` routes alarm transitions by **source-ref prefix** (`transition.SourceObjectReference`/`SourceReference` StartsWith bound key), dedup per transition. One feed per source-ref, ref-counted. Internal records `AlarmTransitionReceived`, `AlarmSubscribeCompleted`. `NativeAlarmSourceUnavailable` pushed on entering Reconnecting; `ReSubscribeAllAlarms` on reconnect.
|
||||
- **T11 (OPC UA):** `OpcUaAlarmMapper` is pure/tested. `RealOpcUaClient.CreateAlarmSubscriptionAsync` does event MonitoredItem + `EventFilter` (select clauses indexed 0–12) + `ConditionRefresh` via `CallAsync` (the sync `Call` is obsolete→error). **`AlarmConditionState` collides with `Opc.Ua.AlarmConditionState`** — fully-qualified as `Commons.Types.Alarms.AlarmConditionState` at the one `new` site. **Behavior unverified until Task 28 (live A&C server).**
|
||||
- **T12 (MxGateway):** `MxGatewayAlarmMapper` is pure/tested. Gateway proto enums `AlarmConditionState`/`AlarmTransitionKind` collide with Commons enums → aliased (`ProtoConditionState`/`ProtoTransitionKind` for proto; explicit `using X = Commons…` for the Commons ones). `MxGatewayClient.StreamAlarmsAsync(StreamAlarmsRequest, ct) → IAsyncEnumerable<AlarmFeedMessage>` confirmed present in pkg v0.1.0. Adapter opens **one shared session-less feed** (gateway-wide, null prefix), ref-counted, first-callback drives it (the actor routes). `RealMxGatewayClient.RunAlarmStreamAsync` reconnects internally (5s) — does NOT use `RaiseDisconnected`. Reference: OtOpcUa `…Driver.Galaxy/Runtime/GatewayGalaxyAlarmFeed.cs`. **Behavior unverified until Task 28 (live gateway).**
|
||||
|
||||
## Execution cadence
|
||||
- Per-task TDD: write test → confirm RED → implement → GREEN → commit. Update native task status + this `.tasks.json` each task; report at each batch boundary and wait for "start"/feedback.
|
||||
- Batches so far: B1 = T1–4, B2 = T5–8, B3 = T9–12. Next proposed: B4 = T13–17.
|
||||
- Native task IDs map plan Task N → native id (N+6) — but on resume the native list is rebuilt from `.tasks.json` (Step 0).
|
||||
|
||||
## Watch items for remaining tasks
|
||||
- **T18 (proto):** `sitestream.proto` is **not auto-compiled** — `<Protobuf>` include is commented out, generated `.cs` vendored in `SiteStreamGrpc/`. Manual macOS regen only (toggle include → `dotnet build` → copy generated files → re-comment). Do NOT auto-compile on Linux.
|
||||
- **T28:** OPC UA A&C live smoke (SkippableFact) + confirm infra OPC UA server exposes A&C; manual deploy check via `bash docker/deploy.sh` / `docker-env2/deploy.sh`.
|
||||
@@ -34,6 +34,11 @@ Commons must define shared primitive and utility types used across multiple comp
|
||||
- **`AlarmState` enum**: Active, Normal.
|
||||
- **`AlarmLevel` enum**: None, Low, LowLow, High, HighHigh. Severity level for an active alarm; always `None` for binary trigger types, set by `HiLo` triggers.
|
||||
- **`AlarmTriggerType` enum**: ValueMatch, RangeViolation, RateOfChange, HiLo.
|
||||
- **`AlarmKind` enum**: Computed, NativeOpcUa, NativeMxAccess. Discriminates how an alarm's state is produced — evaluated at the site by an `AlarmActor` from attribute triggers (`Computed`) vs. mirrored read-only from a native source (OPC UA Alarms & Conditions / MxAccess Gateway).
|
||||
- **`AlarmShelveState` enum**: Unshelved, OneShotShelved, TimedShelved, PermanentShelved. OPC UA Part 9 shelving sub-state of an alarm condition; mirrored read-only from the source. Computed alarms are always `Unshelved`.
|
||||
- **`AlarmTransitionKind` enum**: Snapshot, SnapshotComplete, Raise, Acknowledge, Clear, Retrigger, StateChange. Classifies a `NativeAlarmTransition`; `Snapshot`/`SnapshotComplete` carry the initial active-condition replay produced on every (re)subscribe so consumers can re-seed state.
|
||||
- **`AlarmConditionState`**: The unified, read-only alarm condition state. The OPC UA Part 9 sub-conditions are orthogonal (and MxAccess's ACTIVE / ACTIVE_ACKED / INACTIVE map cleanly onto them), so they are modeled as independent flags — `Active`, `Acknowledged`, `Confirmed` (`bool?`; null when not confirmable), `Shelve` (`AlarmShelveState`), `Suppressed` — plus a `Severity` on the unified 0–1000 scale. Computed alarms populate it from State + Priority; native alarms mirror it from the source. (Helper `AlarmConditionStateFactory` builds the computed-alarm projection.)
|
||||
- **`NativeAlarmTransition`**: The protocol-neutral alarm transition emitted by an `IAlarmSubscribableConnection` adapter — `SourceReference` (stable per-condition key), `SourceObjectReference` (owning source object, used for instance routing), `AlarmTypeName`, `Kind` (`AlarmTransitionKind`), `Condition` (`AlarmConditionState`), source taxonomy/operator/value metadata (`Category`, `Description`, `Message`, `OperatorUser`, `OperatorComment`, `CurrentValue`, `LimitValue`), and `OriginalRaiseTime?` / `TransitionTime`.
|
||||
- **`ConnectionHealth` enum**: Connected, Disconnected, Connecting, Error.
|
||||
- **`TrackedOperationId`**: A GUID identifying a tracked store-and-forward operation (`ExternalSystem.CachedCall`, `Database.CachedWrite`, `Notify.Send`). Generated caller-side at the site at call time, returned to the script as a tracking handle, and reused as the idempotency key for telemetry sent to central. The notification domain's existing `NotificationId` is the notification-specific name for this same concept.
|
||||
- **`TrackedOperationKind` enum**: ExternalCall, DatabaseWrite. Discriminates the two cached-call kinds carried by a tracked operation (notifications are tracked separately via the `NotificationType` enum).
|
||||
@@ -54,6 +59,7 @@ Types defined here must be immutable and thread-safe.
|
||||
Commons must define the protocol abstraction interfaces that the Data Connection Layer implements and other components consume:
|
||||
|
||||
- **`IDataConnection`**: The common interface for reading, writing, and subscribing to device data regardless of the underlying protocol (OPC UA, custom legacy, etc.).
|
||||
- **`IAlarmSubscribableConnection`**: An **optional capability interface** an `IDataConnection` implementation *may also* implement when its source can mirror native alarms (OPC UA Alarms & Conditions, MxAccess Gateway). Exposes `SubscribeAlarmsAsync(sourceReference, conditionFilter, callback, ct)` (returns a subscription id; replays a snapshot of currently-active conditions on every (re)subscribe) and `UnsubscribeAlarmsAsync(subscriptionId, ct)`. Transitions are delivered via the `AlarmTransitionCallback` delegate as protocol-neutral `NativeAlarmTransition` records. Mirrors the `IBrowsableDataConnection` capability-interface pattern; consumed by the Data Connection Layer's `DataConnectionActor` only.
|
||||
- **Related types**: Tag identifiers, read/write results, subscription callbacks, connection status enums, and quality codes.
|
||||
|
||||
These interfaces must not reference any specific protocol implementation.
|
||||
@@ -69,8 +75,8 @@ Commons must define persistence-ignorant POCO entity classes for all configurati
|
||||
|
||||
Entity classes are organized by domain area:
|
||||
|
||||
- **Template & Modeling**: `Template`, `TemplateAttribute`, `TemplateAlarm`, `TemplateScript`, `TemplateComposition`, `TemplateFolder`.
|
||||
- **Instances**: `Instance`, `InstanceAttributeOverride`, `InstanceConnectionBinding`, `InstanceAlarmOverride`, `Area`.
|
||||
- **Template & Modeling**: `Template`, `TemplateAttribute`, `TemplateAlarm`, `TemplateNativeAlarmSource`, `TemplateScript`, `TemplateComposition`, `TemplateFolder`. `TemplateNativeAlarmSource` is a read-only binding (Name, Description, ConnectionName, SourceReference, optional ConditionFilter, plus `IsLocked`/`IsInherited`/`LockedInDerived` lock flags) to a native alarm source; inheritance/lock semantics mirror `TemplateAlarm`.
|
||||
- **Instances**: `Instance`, `InstanceAttributeOverride`, `InstanceConnectionBinding`, `InstanceAlarmOverride`, `InstanceNativeAlarmSourceOverride`, `Area`. `InstanceNativeAlarmSourceOverride` retargets an inherited native alarm source per physical instance, keyed by `SourceCanonicalName`; its `ConnectionNameOverride` / `SourceReferenceOverride` / `ConditionFilterOverride` fields each apply only when non-null (null keeps the inherited value), mirroring `InstanceAlarmOverride`.
|
||||
- **Shared Scripts**: `SharedScript`.
|
||||
- **Sites & Data Connections**: `Site`, `DataConnection`.
|
||||
- **External Systems & Database Connections**: `ExternalSystemDefinition`, `ExternalSystemMethod`, `DatabaseConnectionDefinition`.
|
||||
@@ -86,7 +92,7 @@ The **`Notification`** entity is the persistence-ignorant POCO for a row of the
|
||||
|
||||
Commons must define repository interfaces that consuming components use for data access. Each interface is tailored to the data needs of its consuming component:
|
||||
|
||||
- `ITemplateEngineRepository` — Templates, attributes, alarms, scripts, compositions, template folders, instances, overrides, alarm overrides, connection bindings, areas.
|
||||
- `ITemplateEngineRepository` — Templates, attributes, alarms, native alarm sources, scripts, compositions, template folders, instances, overrides, alarm overrides, native alarm source overrides, connection bindings, areas.
|
||||
- `IDeploymentManagerRepository` — Deployment records, deployed configuration snapshots, system-wide artifact deployment records.
|
||||
- `ISecurityRepository` — LDAP group mappings, site scoping rules.
|
||||
- `IInboundApiRepository` — API keys, API method definitions.
|
||||
@@ -134,7 +140,8 @@ Commons must define the shared DTOs and message contracts used for inter-compone
|
||||
- **Instance Lifecycle DTOs**: Disable, enable, delete commands and responses.
|
||||
- **Health DTOs**: Health check results, site status reports, heartbeat messages. Includes script error rates and alarm evaluation error rates.
|
||||
- **Communication DTOs**: Site identity, connection state, routing metadata.
|
||||
- **Attribute Stream DTOs**: Attribute value change messages (instance name, attribute path, value, quality, timestamp) and alarm state change messages (instance name, alarm name, state, priority, timestamp) for the site-wide Akka stream.
|
||||
- **Attribute Stream DTOs**: Attribute value change messages (instance name, attribute path, value, quality, timestamp) and alarm state change messages (instance name, alarm name, state, priority, timestamp) for the site-wide Akka stream. The alarm state change message (`AlarmStateChanged`) is **additively enriched** to carry both computed and native alarms on one shape: an `AlarmKind` discriminator, the unified `AlarmConditionState`, and native metadata (`SourceReference`, `AlarmTypeName`, `Category`, `OperatorUser`, `OperatorComment`, `OriginalRaiseTime`, `CurrentValue`, `LimitValue`) — defaulted/empty for computed alarms. Subject to the additive-only evolution rules in REQ-COM-5a, since it crosses the site→central gRPC stream.
|
||||
- **Native Alarm DTOs** (`Messages/DataConnection/`): the read-only native alarm mirror messages between the Site Runtime and the Data Connection Layer — `SubscribeAlarmsRequest` / `SubscribeAlarmsResponse` (subscribe a source binding; response carries success + optional error), `UnsubscribeAlarmsRequest`, `NativeAlarmTransitionUpdate` (`ConnectionName`, `Transition` — one routed `NativeAlarmTransition`, including snapshot replay), and `NativeAlarmSourceUnavailable` (`ConnectionName`, `SourceReference`, `Timestamp` — the feed dropped on connection loss).
|
||||
- **Debug View DTOs**: Subscribe/unsubscribe requests, one-shot snapshot request (`DebugSnapshotRequest`), initial snapshot, stream filter criteria.
|
||||
- **Script Execution DTOs**: Script call requests (with recursion depth), return values, error results.
|
||||
- **System-Wide Artifact DTOs**: Shared script packages, external system definitions, database connection definitions, notification list definitions.
|
||||
@@ -174,13 +181,17 @@ ZB.MOM.WW.ScadaBridge.Commons/
|
||||
│ ├── SiteCallOperational.cs # SiteCalls operational-row projection
|
||||
│ ├── TrackingStatusSnapshot.cs # site-local Tracking.Status(id) projection
|
||||
│ ├── Enums/ # InstanceState, DeploymentStatus, AlarmState,
|
||||
│ │ # AlarmLevel, AlarmTriggerType, ConnectionHealth,
|
||||
│ │ # AlarmLevel, AlarmTriggerType, AlarmKind,
|
||||
│ │ # AlarmShelveState, AlarmTransitionKind,
|
||||
│ │ # ConnectionHealth,
|
||||
│ │ # DataType, StoreAndForwardCategory,
|
||||
│ │ # StoreAndForwardMessageStatus,
|
||||
│ │ # NotificationType, NotificationStatus,
|
||||
│ │ # TrackedOperationKind, TrackedOperationStatus,
|
||||
│ │ # AuditChannel, AuditKind, AuditStatus,
|
||||
│ │ # AuditForwardState
|
||||
│ ├── Alarms/ # AlarmConditionState, AlarmConditionStateFactory,
|
||||
│ │ # NativeAlarmTransition (unified read-only condition model)
|
||||
│ ├── Audit/ # AuditLogPaging, AuditLogQueryFilter,
|
||||
│ │ # AuditQueryParamParsers, ExecutionTreeNode,
|
||||
│ │ # SiteCallKpiSnapshot, SiteCallPaging,
|
||||
@@ -199,7 +210,9 @@ ZB.MOM.WW.ScadaBridge.Commons/
|
||||
├── Interfaces/ # Shared interfaces by concern
|
||||
│ ├── IOperationTrackingStore.cs # site-local tracked-operation status store
|
||||
│ ├── IPartitionMaintenance.cs # central partition-switch / retention purge hook
|
||||
│ ├── Protocol/ # REQ-COM-2: Protocol abstraction (IDataConnection, etc.)
|
||||
│ ├── Protocol/ # REQ-COM-2: Protocol abstraction (IDataConnection,
|
||||
│ │ # IBrowsableDataConnection, IAlarmSubscribableConnection,
|
||||
│ │ # AlarmTransitionCallback)
|
||||
│ ├── Repositories/ # REQ-COM-4: Per-component repository interfaces
|
||||
│ │ ├── ITemplateEngineRepository.cs
|
||||
│ │ ├── IDeploymentManagerRepository.cs
|
||||
@@ -231,9 +244,11 @@ ZB.MOM.WW.ScadaBridge.Commons/
|
||||
│ └── IBundleSessionStore.cs
|
||||
├── Entities/ # REQ-COM-3: Domain entity POCOs, by domain area
|
||||
│ ├── Templates/ # Template, TemplateAttribute, TemplateAlarm,
|
||||
│ │ # TemplateScript, TemplateComposition, TemplateFolder
|
||||
│ │ # TemplateNativeAlarmSource, TemplateScript,
|
||||
│ │ # TemplateComposition, TemplateFolder
|
||||
│ ├── Instances/ # Instance, InstanceAttributeOverride,
|
||||
│ │ # InstanceConnectionBinding, InstanceAlarmOverride, Area
|
||||
│ │ # InstanceConnectionBinding, InstanceAlarmOverride,
|
||||
│ │ # InstanceNativeAlarmSourceOverride, Area
|
||||
│ ├── Sites/ # Site, DataConnection
|
||||
│ ├── ExternalSystems/ # ExternalSystemDefinition, ExternalSystemMethod,
|
||||
│ │ # DatabaseConnectionDefinition
|
||||
@@ -256,7 +271,8 @@ ZB.MOM.WW.ScadaBridge.Commons/
|
||||
│ ├── DebugView/
|
||||
│ ├── ScriptExecution/
|
||||
│ ├── Artifacts/
|
||||
│ ├── DataConnection/ # data-connection subscribe/write/health messages
|
||||
│ ├── DataConnection/ # data-connection subscribe/write/health messages,
|
||||
│ │ # native alarm subscribe/transition messages
|
||||
│ ├── Instance/ # attribute get/set request/command messages
|
||||
│ ├── Integration/ # external-integration call request/response,
|
||||
│ │ # cached-call tracking telemetry + reconcile,
|
||||
|
||||
@@ -105,6 +105,8 @@ Both endpoints honour any site-scope rules attached to the caller's audit role b
|
||||
|
||||
- **AddTemplateAttribute** / **UpdateTemplateAttribute** / **DeleteTemplateAttribute**: Manage attributes on a template.
|
||||
- **AddTemplateAlarm** / **UpdateTemplateAlarm** / **DeleteTemplateAlarm**: Manage alarm definitions on a template.
|
||||
- **AddTemplateNativeAlarmSource** / **UpdateTemplateNativeAlarmSource** / **DeleteTemplateNativeAlarmSource**: Manage native alarm source bindings (the read-only OPC UA Alarms & Conditions / MxAccess Gateway mirror) on a template — `Name`, `ConnectionName`, `SourceReference`, optional `ConditionFilter` / `Description`, `IsLocked`. Mutations gated to the **Design** role; handlers write through `ITemplateEngineRepository` directly.
|
||||
- **ListTemplateNativeAlarmSources** (`TemplateId`): List a template's native alarm source bindings (read-only; any authenticated user).
|
||||
- **AddTemplateScript** / **UpdateTemplateScript** / **DeleteTemplateScript**: Manage scripts on a template.
|
||||
- **AddTemplateComposition** / **DeleteTemplateComposition**: Manage feature module compositions on a template.
|
||||
|
||||
@@ -113,6 +115,9 @@ Both endpoints honour any site-scope rules attached to the caller's audit role b
|
||||
- **ListInstances** / **GetInstance**: Query instances, with filtering by site and area.
|
||||
- **CreateInstance**: Create a new instance from a template.
|
||||
- **UpdateInstanceOverrides**: Set attribute overrides on an instance.
|
||||
- **SetInstanceAlarmOverride** / **DeleteInstanceAlarmOverride** / **ListInstanceAlarmOverrides**: Manage per-instance computed-alarm overrides.
|
||||
- **SetInstanceNativeAlarmSourceOverride** / **DeleteInstanceNativeAlarmSourceOverride**: Retarget or clear a per-instance native alarm source binding, keyed by `SourceCanonicalName` — `ConnectionNameOverride` / `SourceReferenceOverride` / `ConditionFilterOverride` each apply only when non-null. Gated to the **Deployment** role.
|
||||
- **ListInstanceNativeAlarmSourceOverrides** (`InstanceId`): List an instance's native alarm source overrides (read-only).
|
||||
- **SetInstanceBindings** / **BindDataConnections**: Bind data connections to instance attributes.
|
||||
- **AssignArea**: Assign an instance to an area.
|
||||
- **EnableInstance** / **DisableInstance** / **DeleteInstance**: Instance lifecycle commands.
|
||||
@@ -193,8 +198,8 @@ Both endpoints honour any site-scope rules attached to the caller's audit role b
|
||||
Every incoming message carries the authenticated user's identity and roles. The ManagementActor enforces the same role-based authorization rules as the Central UI:
|
||||
|
||||
- **Admin** role required for: site management, area management, API key management, role mapping management, scope rule management, system configuration.
|
||||
- **Design** role required for: template authoring (including template member management: attributes, alarms, scripts, compositions), shared scripts, external system definitions, database connection definitions, notification lists, inbound API method definitions.
|
||||
- **Deployment** role required for: instance management, deployments, debug view, debug snapshot, parked message queries, site event log queries. Site scoping is enforced for site-scoped Deployment users.
|
||||
- **Design** role required for: template authoring (including template member management: attributes, alarms, native alarm sources, scripts, compositions), shared scripts, external system definitions, database connection definitions, notification lists, inbound API method definitions.
|
||||
- **Deployment** role required for: instance management (including instance alarm overrides and native alarm source overrides), deployments, debug view, debug snapshot, parked message queries, site event log queries. Site scoping is enforced for site-scoped Deployment users.
|
||||
- **Read-only access** (any authenticated role): health summary, health site, site event log queries, parked message queries.
|
||||
|
||||
Unauthorized commands receive an `Unauthorized` response message. Failed authorization attempts are not audit logged (consistent with existing behavior).
|
||||
|
||||
@@ -119,6 +119,28 @@ Each alarm has:
|
||||
- Alarm state is **not persisted** — on restart, alarm states are re-evaluated from incoming values.
|
||||
- Alarm state changes are published to the site-wide Akka stream as `[InstanceUniqueName].[AlarmName]`, alarm state (active/normal), alarm level, priority, timestamp.
|
||||
|
||||
### 3.4.2 Native Alarms (Read-Only Mirror)
|
||||
|
||||
Sections 3.4 and 3.4.1 describe **computed alarms** — alarms ScadaBridge evaluates at the site from attribute triggers. The system additionally **mirrors native alarms** already raised by upstream systems — **OPC UA Alarms & Conditions** servers and the **MxAccess Gateway**. Native alarms are surfaced read-only alongside computed alarms; ScadaBridge reflects source-reported state but **never acknowledges, confirms, shelves, suppresses, or otherwise writes back** to the source — the source system owns the alarm lifecycle.
|
||||
|
||||
**Native alarm source bindings** are first-class template members alongside attributes, alarms, and scripts, following the same **inheritance, override, and lock rules**. Each binding has:
|
||||
- **Name**: Identifier for the source binding within the template.
|
||||
- **Description** *(optional)*.
|
||||
- **Connection**: The data connection that carries the native alarms (must be alarm-capable — an OPC UA A&C or MxAccess Gateway connection).
|
||||
- **Source Reference**: The source-side address the alarms are read from — an OPC UA `SourceNode`/notifier nodeId, or an MxAccess object/area.
|
||||
- **Condition Filter** *(optional)*: Narrows which conditions under the source are mirrored; when omitted, **all** conditions under the source are mirrored.
|
||||
- **Lock Flag**: Controls whether the binding can be overridden downstream.
|
||||
|
||||
Because the source reference typically varies per physical instance (e.g. `Tank01` vs `Tank02`), an instance may **override** a non-locked binding's connection, source reference, and/or condition filter individually — a null override field keeps the inherited value. Bindings cannot be added or removed at the instance level, only retargeted.
|
||||
|
||||
**Unified condition model.** Computed and native alarms share one **condition state** so they present uniformly: orthogonal **Active**, **Acknowledged**, **Confirmed** (when confirmable), **Shelved**, and **Suppressed** flags plus a **0–1000 severity**. An **alarm kind** discriminator distinguishes `Computed`, `NativeOpcUa`, and `NativeMxAccess`. Computed alarms project onto this model as auto-acknowledged with severity equal to their priority; native alarms mirror the source condition directly.
|
||||
|
||||
**Runtime behavior:**
|
||||
- Native alarm sources are **discovered and subscribed at runtime** — at deploy time the site subscribes each resolved binding through the Data Connection Layer, which opens **one alarm feed per connection** and routes transitions to instances by source-object reference. A site-side actor (peer to the computed alarm actor) mirrors each source binding.
|
||||
- On every (re)subscribe the source **replays a snapshot** of currently-active conditions so state is reconciled after a reconnect. On connection loss, mirrored conditions are **marked uncertain rather than cleared**, so a transient disconnect does not flap every condition to normal.
|
||||
- Unlike computed alarm state (not persisted, re-evaluated on restart), mirrored native alarm state **is persisted at the site** so it survives restart/failover; it is **cleared on redeployment/undeployment** (mirroring static attribute overrides).
|
||||
- Native alarm state is streamed to the central cluster over the **existing real-time gRPC stream** (additively, alongside computed alarm state) and is surfaced **only in the on-demand debug view** — there is no dedicated operator/alarm-summary page and **no central alarm tables**. The debug view shows the alarm kind, unified severity, and condition sub-state badges, but offers **no ack-back or command actions** for native alarms.
|
||||
|
||||
### 3.5 Template Relationships
|
||||
|
||||
Templates participate in two distinct relationship types:
|
||||
@@ -192,6 +214,7 @@ Before any deployment is sent to a site, the central cluster performs **comprehe
|
||||
- **Naming collision detection**: No duplicate attribute, alarm, or script names exist in the flattened configuration.
|
||||
- **Script compilation**: All instance scripts and alarm on-trigger scripts are test-compiled and must compile without errors.
|
||||
- **Alarm trigger references**: Alarm trigger definitions reference attributes that exist in the flattened configuration.
|
||||
- **Native alarm source bindings**: Each resolved native alarm source has a non-empty source reference and connection name, and — when the alarm-capable connection set is supplied — the bound connection exists and is alarm-capable (an OPC UA A&C or MxAccess Gateway connection).
|
||||
- **Script trigger references**: Script triggers (value change, conditional) reference attributes that exist in the flattened configuration.
|
||||
- **Data connection binding completeness**: Every attribute with a data source reference has a data connection binding assigned on the instance, and the bound data connection name exists as a defined connection at the instance's site.
|
||||
- **Exception**: Validation does **not** verify that data source relative paths resolve to real tags on physical devices — that is a runtime concern that can only be determined at the site.
|
||||
|
||||
Reference in New Issue
Block a user