Commit Graph

63 Commits

Author SHA1 Message Date
Joseph Doherty 3a0e0907e4 feat(adminui): add connection-health signal to in-process broadcaster + bridges 2026-06-11 09:20:36 -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 142635b402 feat(adminui): tag-path hover (tag kind/type/driver inside ctx.GetTag literals)
v2-ci / build (push) Failing after 47s
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
2026-06-10 05:48:02 -04:00
Joseph Doherty fc7dc3b57d feat(adminui): inline script-source editor in the virtual-tag modal 2026-06-09 15:23:35 -04:00
Joseph Doherty 4a2f7e37e5 feat(adminui): script document formatting (NormalizeWhitespace) 2026-06-09 15:06:40 -04:00
Joseph Doherty 9104b6c614 feat(adminui): script hover + signature help 2026-06-09 15:03:40 -04:00
Joseph Doherty 521fb61e44 feat(adminui): tag-path completion inside ctx.GetTag/SetVirtualTag literals 2026-06-09 14:53:15 -04:00
Joseph Doherty d1434933b4 feat(adminui): IScriptTagCatalog for tag-path completion 2026-06-09 14:49:19 -04:00
Joseph Doherty 93f5a745a3 feat(adminui): scope + dot-member script completions 2026-06-09 14:36:28 -04:00
Joseph Doherty 6a9b052fc7 feat(adminui): script diagnostics (Roslyn + forbidden-type + dynamic-path) 2026-06-09 14:29:08 -04:00
Joseph Doherty fa96989e2a feat(uns): validate typed TagConfig before save (F-uns-2 / #156)
v2-ci / build (push) Failing after 38s
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
The per-driver editor models expose Validate() (required-field checks) but the
TagModal never called them, so a blank required field (e.g. S7 address, AbCip
tag path) saved silently and only failed at deploy/connect. Add a
TagConfigValidator registry (DriverType -> model.FromJson(json).Validate(),
parallel to TagConfigEditorMap) and call it in SaveAsync before the service
call — a non-null result sets the modal error and blocks save. Unmapped drivers
(no typed editor) and Modbus (no required field) return null. Editors untouched.

AdminUI.Tests 307/307 (12 new validator tests); build clean.
2026-06-09 11:45:35 -04:00
Joseph Doherty c0afecda50 fix(uns): omit blank optional keys from TagConfig + add omission tests; drop unused ParseInt (T4-T8 review) 2026-06-09 09:49:33 -04:00
Joseph Doherty 75021fa2c9 feat(uns): S7/AbCip/AbLegacy/TwinCAT/Focas typed tag-config editors (F-uns-1 T4-T8) 2026-06-09 09:42:40 -04:00
Joseph Doherty 5990b673cc feat(uns): Modbus typed tag-config editor (F-uns-1 T3) 2026-06-09 09:36:19 -04:00
Joseph Doherty fd9fa75d0e feat(uns): TagConfig JSON helper + editor map + TagModal dispatch scaffold (F-uns-1 T2) 2026-06-09 09:26:50 -04:00
Joseph Doherty d9dbd7917a feat(uns): surface DriverType to the TagModal driver dropdown (F-uns-1 T1) 2026-06-09 09:16:07 -04:00
Joseph Doherty 8ba64b1d99 fix(uns): enforce #122 on line reparent across clusters (final review)
v2-ci / build (push) Failing after 4m38s
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
2026-06-08 14:12:46 -04:00
Joseph Doherty 7db9a24403 feat(uns): equipment CSV import folded into the tree toolbar 2026-06-08 13:56:01 -04:00
Joseph Doherty c0346f14ce feat(uns): tag + virtual-tag modals wired into the tree 2026-06-08 13:47:34 -04:00
Joseph Doherty d637b834b9 fix(uns): reject equipment bind to non-existent driver + modal-xl (review) 2026-06-08 13:38:33 -04:00
Joseph Doherty 2beaa43d60 feat(uns): equipment modal wired into the tree 2026-06-08 13:31:14 -04:00
Joseph Doherty a4a9dc912a feat(uns): area + line modals wired into the tree 2026-06-08 13:20:25 -04:00
Joseph Doherty 307cec5a3d test(uns): cover no-script + update-duplicate-name virtual-tag guards (review) 2026-06-08 13:15:10 -04:00
Joseph Doherty d8fba02a5e feat(uns): equipment-bound virtual-tag CRUD 2026-06-08 13:11:12 -04:00
Joseph Doherty 77024f87da fix(uns): reject tag create on non-existent equipment + narrow JSON catch (review) 2026-06-08 13:06:45 -04:00
Joseph Doherty 5a392c5db0 feat(uns): equipment-bound tag CRUD with namespace + cluster guards 2026-06-08 13:00:26 -04:00
Joseph Doherty ab0ff8aedf fix(uns): reject driver-bind on unresolvable line + enforce MachineCode uniqueness on update (review) 2026-06-08 12:55:36 -04:00
Joseph Doherty 2836a0704b feat(uns): equipment CRUD with #122 driver-cluster guard 2026-06-08 12:47:19 -04:00
Joseph Doherty ace366ebcf test(uns): cover #122 allow-when-driver-already-in-target-cluster (review) 2026-06-08 12:42:13 -04:00
Joseph Doherty 47b1d2259f feat(uns): area + line CRUD with #122 reassignment guard 2026-06-08 12:35:58 -04:00
Joseph Doherty b33cf1c80d feat(uns): lazy per-equipment tag + virtual-tag load
Add LoadEquipmentChildrenAsync to IUnsTreeService and UnsTreeService; returns
Tag nodes (ordered by Name) then VirtualTag nodes (ordered by Name) as leaf
nodes with ChildCount=0, HasLazyChildren=false, keys tag:{id}/vtag:{id}.
2026-06-08 12:29:52 -04:00
Joseph Doherty cec670f0c8 feat(uns): IUnsTreeService structural load + DI registration 2026-06-08 12:23:00 -04:00
Joseph Doherty 3e8941bce4 docs(uns): clarify HasLazyChildren + cluster EntityId, add tie-break test (review I1/I2/M2) 2026-06-08 12:18:37 -04:00
Joseph Doherty d9082e22e3 feat(uns): UnsNode VM + pure tree-assembly helper 2026-06-08 12:14:49 -04:00
Joseph Doherty ad7f9e731f feat(admin): headless POST /api/deployments REST endpoint (API-key gated)
v2-ci / build (push) Failing after 50s
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
A thin gateway over the admin-operations cluster singleton so CI/scripts can trigger a
deployment without the Blazor button. Forwards to the same IAdminOperationsClient.
StartDeploymentAsync; mounted on admin-role nodes. Auth is a fixed-time X-Api-Key check
against Security:DeployApiKey (orthogonal to the cookie-only web auth); AllowAnonymous so the
auth fallback doesn't 401 it, self-disabling (503) until the key is set. Outcome->status:
202/200/409/422. Unit tests for the key check + outcome mapping; HTTP E2E (real auth + real
deploy via the 2-node harness). Documented in docs/security.md.
2026-06-06 15:54:51 -04:00
Joseph Doherty 61193629b6 fix(adminui): wire Test Connect probes + live panels on admin-only nodes
v2-ci / build (push) Failing after 36s
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
Both bugs surfaced only on split-role deployments (the MAIN cluster's
admin-only nodes), where the AdminUI runs without the driver role.

- Test Connect returned "No probe registered" for every driver: the
  IDriverProbe set was registered only under the driver role, but the
  admin-operations singleton that consumes it is pinned to admin. Extract
  AddOtOpcUaDriverProbes() (idempotent via TryAddEnumerable) and call it
  in the hasAdmin path too.

- Live driver-status/alerts/script-log panels showed "SignalR error:
  Connection refused": these Blazor Server components opened a HubConnection
  to their own hub via the browser's public URL, which server-side code
  can't reach behind Traefik (host :9200 -> container :9000). Read the
  in-process source directly instead -- DriverStatus via
  IDriverStatusSnapshotStore.SnapshotChanged, Alerts/ScriptLog via a new
  IInProcessBroadcaster<T>. Fleet status was unaffected (reads DB/ActorSystem).

Adds unit tests for probe registration, the snapshot-store event, and the
broadcaster.
2026-05-29 16:38:32 -04:00
Joseph Doherty e3a27422a1 fix(adminui): Galaxy editor 500 — read DriverConfig case-insensitively + null-safe FromRecord
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
GalaxyDriverPage deserialized DriverConfig with case-sensitive camelCase opts, but the
persisted/seeded config is PascalCase (the runtime reads it case-insensitively). So all four
nested option records read as null -> FromRecord NRE (HTTP 500) on edit, and the form would
have shown defaults instead of the real config (risking a clobber on save). Fix: add
PropertyNameCaseInsensitive=true (matches the runtime) so real values load, plus null-coalesce
the nested records in FromRecord as defense-in-depth. Regression test asserts the seeded
PascalCase config loads its real values.
2026-05-29 12:45:44 -04:00
Joseph Doherty 7570df76d3 feat(adminui): editable OpcUaClient endpoint URL list via CollectionEditor 2026-05-29 09:41:09 -04:00
Joseph Doherty 244949caa3 feat(adminui): editable S7 tag list via CollectionEditor 2026-05-29 09:37:12 -04:00
Joseph Doherty a5a0d06dbe feat(adminui): editable FOCAS device + tag lists via CollectionEditor 2026-05-29 09:33:53 -04:00
Joseph Doherty 6882761f4c feat(adminui): editable TwinCAT device + tag lists via CollectionEditor 2026-05-29 09:29:57 -04:00
Joseph Doherty 15f3797f1e feat(adminui): editable AbLegacy device + tag lists via CollectionEditor 2026-05-29 09:26:25 -04:00
Joseph Doherty 534d670b21 feat(adminui): editable AbCip device + tag lists via CollectionEditor 2026-05-29 09:22:51 -04:00
Joseph Doherty b351a81c8f fix(adminui): preserve un-edited Modbus tag fields across edit (review)
Capture the original ModbusTagDefinition as _source in ModbusTagRow and
rewrite ToDefinition() to use 'with {}', so StringByteOrder, ArrayCount,
Deadband, UnitId, and CoalesceProhibited survive a load→edit→save cycle.
2026-05-29 09:18:36 -04:00
Joseph Doherty c4116e54c9 feat(adminui): editable Modbus tag list via CollectionEditor 2026-05-29 09:14:06 -04:00
Joseph Doherty c3fec1426c fix(adminui): case-insensitive resilience policy keys + malformed-json test (review) 2026-05-29 09:10:41 -04:00
Joseph Doherty 4a469fbe06 feat(adminui): typed resilience override form model + tests 2026-05-29 09:06:45 -04:00