docs: point markdown backlogs at Gitea issues (status lives in Gitea)
v2-ci / unit-tests (push) Waiting to run
v2-ci / unit-tests (push) Waiting to run
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
# Monaco Script Editor (Roslyn-backed IntelliSense)
|
||||
|
||||
> **Status lives in Gitea.** Open follow-ups and known gaps noted in this doc are tracked as issues on
|
||||
> gitea.dohertylan.com/dohertj2/lmxopcua (label `migrated`, 2026-11-06). This doc describes the system — do not track status here; file new work as an issue.
|
||||
|
||||
The script editor gives AdminUI users a first-class C# authoring experience for
|
||||
virtual-tag scripts: completions, diagnostics, hover, signature help, document
|
||||
formatting, and context-aware tag-path completions — all backed by the same
|
||||
@@ -208,7 +211,7 @@ scripted-alarm predicates) runs scripts through the shared `ScriptRunGuard`:
|
||||
- **Allocation budget.** A single run allocating more than
|
||||
`Scripting:MaxAllocBytesPerRun` (64 MB) is quarantined. This is sampled after the
|
||||
run returns, so a run that OOMs the process first is not stopped — that needs an
|
||||
out-of-process runner.
|
||||
out-of-process runner (→ #750).
|
||||
- **Configuration keys and their ranges.** All three knobs are node-wide (the
|
||||
`Scripting` appsettings section, shared by virtual tags, Calculation tags and
|
||||
scripted alarms) and are clamped when bound, with one startup Warning per
|
||||
@@ -491,20 +494,20 @@ site.
|
||||
|
||||
- **Tag-path completion shows resolvable keys only.** Surfacing the UNS browse
|
||||
path as a completion *detail* (a non-inserted hint shown alongside the
|
||||
resolvable key) for discoverability is a tracked follow-up.
|
||||
resolvable key) for discoverability is a tracked follow-up. → #759
|
||||
- **Literal gate matches by method name, not receiver.** `anything.GetTag("…")`
|
||||
would also trigger tag-path completion (not just `ctx.GetTag("…")`). Harmless
|
||||
in the sandbox today — no other `GetTag` methods exist in the allowed reference
|
||||
set — but tighter binding to `ctx` / `VirtualTagContext` is a follow-up.
|
||||
set — but tighter binding to `ctx` / `VirtualTagContext` is a follow-up. (Reconcile: → #759)
|
||||
- **Analysis runs synchronous Roslyn (CPU-bound).** Each endpoint call builds a
|
||||
`CSharpCompilation` synchronously. This is intentional: the endpoints are
|
||||
admin-only, client-side debounced (~500 ms), and `Task.Run` offload adds
|
||||
unnecessary complexity for infrequent admin use. If concurrency becomes a
|
||||
concern under heavy admin usage, wrapping each `Analyze` call in `Task.Run` is
|
||||
the correct fix.
|
||||
the correct fix. (Reconcile: → #759)
|
||||
- **InlayHints is a stub.** `/api/script-analysis/inlay-hints` returns an empty
|
||||
list. Filling it in (parameter name hints from the semantic model) is a
|
||||
follow-up task.
|
||||
follow-up task. (Dropped — reconcile: → #759)
|
||||
- **Language providers register globally at Monaco load.** The six providers are
|
||||
registered for the `csharp` language on the global Monaco instance (loaded once
|
||||
per page in `App.razor`). There is no impact today because only
|
||||
@@ -514,7 +517,7 @@ site.
|
||||
results).
|
||||
- **Creating a new script from the VirtualTagModal inline panel** is deferred.
|
||||
The current inline panel loads and saves an existing `Script` row; creating a
|
||||
brand-new script requires a separate create flow and is a follow-up.
|
||||
brand-new script requires a separate create flow and is a follow-up. (Shipped — reconcile: → #759)
|
||||
|
||||
---
|
||||
|
||||
|
||||
+4
-1
@@ -1,5 +1,8 @@
|
||||
# UNS — Global Unified-Namespace Management
|
||||
|
||||
> **Status lives in Gitea.** Open follow-ups and known gaps noted in this doc are tracked as issues on
|
||||
> gitea.dohertylan.com/dohertj2/lmxopcua (label `migrated`, 2026-11-06). This doc describes the system — do not track status here; file new work as an issue.
|
||||
|
||||
The **UNS** page (`/uns` in the AdminUI) is the single surface for managing
|
||||
the Unified Namespace across the whole fleet. It replaces the old
|
||||
per-cluster **UNS**, **Equipment**, and **Tags** tabs and the standalone
|
||||
@@ -528,7 +531,7 @@ equipment page.
|
||||
Phase 6 did **not** implement per-driver-instance status rows on the Hosts
|
||||
page. This item (H7-runtime) is **F7-runtime-blocked**: the runtime plumbing
|
||||
needed to surface per-instance health rows is not yet in place. It remains on
|
||||
the backlog.
|
||||
the backlog. (Stale — reconcile: → #759)
|
||||
|
||||
## Bulk import
|
||||
|
||||
|
||||
+4
-1
@@ -1,5 +1,8 @@
|
||||
# Virtual Tags
|
||||
|
||||
> **Status lives in Gitea.** Open follow-ups and known gaps noted in this doc are tracked as issues on
|
||||
> gitea.dohertylan.com/dohertj2/lmxopcua (label `migrated`, 2026-11-06). This doc describes the system — do not track status here; file new work as an issue.
|
||||
|
||||
> ⚠️ **Correction (2026-07-28): `GenericDriverNodeManager` is NOT a production dispatch path.** It is test
|
||||
> scaffolding — its own source says so (`Core/OpcUa/GenericDriverNodeManager.cs:71`, "verified 07/#10: zero
|
||||
> production references"). The production chain is `OpcUaPublishActor` → `IOpcUaAddressSpaceSink`
|
||||
@@ -34,7 +37,7 @@ User scripts are compiled via `Microsoft.CodeAnalysis.CSharp` (regular compiler,
|
||||
|
||||
#### Known resource limits (accepted trade-offs)
|
||||
|
||||
The sandbox cannot pre-empt a script. **Memory:** each run's own-thread allocation is sampled (`GC.GetAllocatedBytesForCurrentThread`) and a run over `Scripting:MaxAllocBytesPerRun` (default 64 MB) quarantines the script — but the sample is taken after the run returns, so a script that allocates fast enough (`new byte[int.MaxValue]` in a loop) can still OOM the process first. **CPU:** a tight loop keeps its pool thread after the timeout fires; `ScriptRunGuard` bounds that to one orphan per script by refusing further runs while it spins (Bad `"previous evaluation still running"`) and quarantines after three consecutive timeouts (a refusal is not a strike) — or immediately on a refusal behind an orphan that has run longer than `Scripting:StuckOrphanQuarantineFactor` (default 10) × the timeout, which is what quarantines a never-returning `while(true)`. Both are mitigations; pre-emptive CPU/memory limits need an out-of-process runner. Script authoring is gated behind the Admin permission as the primary control. See `docs/ScriptEditor.md` §"Runtime safety".
|
||||
The sandbox cannot pre-empt a script. **Memory:** each run's own-thread allocation is sampled (`GC.GetAllocatedBytesForCurrentThread`) and a run over `Scripting:MaxAllocBytesPerRun` (default 64 MB) quarantines the script — but the sample is taken after the run returns, so a script that allocates fast enough (`new byte[int.MaxValue]` in a loop) can still OOM the process first. **CPU:** a tight loop keeps its pool thread after the timeout fires; `ScriptRunGuard` bounds that to one orphan per script by refusing further runs while it spins (Bad `"previous evaluation still running"`) and quarantines after three consecutive timeouts (a refusal is not a strike) — or immediately on a refusal behind an orphan that has run longer than `Scripting:StuckOrphanQuarantineFactor` (default 10) × the timeout, which is what quarantines a never-returning `while(true)`. Both are mitigations; pre-emptive CPU/memory limits need an out-of-process runner (→ #750). Script authoring is gated behind the Admin permission as the primary control. See `docs/ScriptEditor.md` §"Runtime safety".
|
||||
|
||||
`System.Threading.Tasks` is denied (Core.Scripting-003), which prevents `Task.Run` / `Parallel` fan-out that would spawn background work outliving the timeout.
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# AB Legacy Driver
|
||||
|
||||
> **Status lives in Gitea.** Open follow-ups and known gaps noted in this doc are tracked as issues on
|
||||
> gitea.dohertylan.com/dohertj2/lmxopcua (label `migrated`, 2026-11-06). This doc describes the system — do not track status here; file new work as an issue.
|
||||
|
||||
In-process native-protocol driver that exposes legacy Allen-Bradley PLCs —
|
||||
**SLC 500**, **MicroLogix**, **PLC-5**, and Logix-via-PCCC — as OPC UA nodes. It
|
||||
runs inside the OtOpcUa server's .NET 10 AnyCPU process and speaks PCCC over
|
||||
@@ -274,7 +277,7 @@ Simulator evidence:
|
||||
[Wire evidence](#wire-evidence-native-pccc).
|
||||
- **PLC-5 native is N-file reads only.** Every other file type and all PLC-5 writes are refused before the
|
||||
wire and reach the client as `BadNotSupported` (handle kept, health unchanged; #571 closed). Native is opt-in
|
||||
for every family; an explicit Native on PLC-5 / `logixpccc` logs a Warning at init.
|
||||
for every family; an explicit Native on PLC-5 / `logixpccc` logs a Warning at init. PLC-5 hardware proof → #752 (SLC/MicroLogix evidence → #592).
|
||||
- Status-bit sub-element writes (e.g. `T4:0.DN`, `C5:0.DN`) are Unsupported natively (they would clobber the
|
||||
control word); nothing goes on the wire — the driver refuses before creating the tag's runtime, so not even an
|
||||
init read is sent (`NativeAbLegacyTagRuntime.WriteRefusal` is the single predicate, asked through
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# MQTT Driver
|
||||
|
||||
> **Status lives in Gitea.** Open follow-ups and known gaps noted in this doc are tracked as issues on
|
||||
> gitea.dohertylan.com/dohertj2/lmxopcua (label `migrated`, 2026-11-06). This doc describes the system — do not track status here; file new work as an issue.
|
||||
|
||||
In-process MQTT **broker-subscribe** driver. It holds one MQTTnet 5 client against one broker,
|
||||
subscribes to the topics its authored tags name, and forwards each PUBLISH straight to
|
||||
`ISubscribable.OnDataChange`. Ingest is **push, not poll**; writes go back out as ordinary publishes
|
||||
@@ -250,7 +253,7 @@ One subscription (`spBv1.0/{GroupId}/#`) feeds a per-edge-node state machine
|
||||
- **Unsupported datatypes are skipped with a warning, never guessed**: `PropertySetList`, `Unknown`,
|
||||
extension values, and any `Template`/`DataSet` that cannot be flattened honestly. `Int8`→`Int16` and
|
||||
`UInt8`→`UInt16` widen; `*Array` variants map to the element type with the array bit set — but
|
||||
**array metrics are not read in v1** (warned once, never fed), so the browse picker offers them, and any
|
||||
**array metrics are not read in v1** (warned once, never fed; → #754), so the browse picker offers them, and any
|
||||
metric whose type is unsupported, **without an address**: the browse-commit refuses them rather than
|
||||
committing a tag that waits for initial data forever (R06:M-5).
|
||||
- **Ingest state is reset at every session/authoring seam** — a reconnect or a `ReinitializeAsync`
|
||||
|
||||
+6
-3
@@ -1,5 +1,8 @@
|
||||
# SQL Poll Driver
|
||||
|
||||
> **Status lives in Gitea.** Open follow-ups and known gaps noted in this doc are tracked as issues on
|
||||
> gitea.dohertylan.com/dohertj2/lmxopcua (label `migrated`, 2026-11-06). This doc describes the system — do not track status here; file new work as an issue.
|
||||
|
||||
Getting-started guide for the `Sql` driver — a **read-only** Equipment-kind driver that polls rows
|
||||
out of a relational database and publishes them as OPC UA variables. For the design rationale read
|
||||
[`docs/plans/2026-07-15-sql-poll-driver-design.md`](../plans/2026-07-15-sql-poll-driver-design.md);
|
||||
@@ -16,7 +19,7 @@ already writes to. There is no protocol here and nothing to "connect" to a machi
|
||||
(`Npgsql`) and `Oracle` (ODP.NET managed — **Oracle 12.2 or later**, the floor the
|
||||
`FETCH FIRST` paging needs). `SqlProvider` also declares `MySql` and `Odbc`, but those remain
|
||||
**reserved names, not working backends** — authoring one fails the driver rather than silently
|
||||
falling back.
|
||||
falling back. → #753
|
||||
|
||||
Two provider-specific things are worth knowing before you author against them:
|
||||
|
||||
@@ -30,7 +33,7 @@ Two provider-specific things are worth knowing before you author against them:
|
||||
**Read-only, structurally.** `SqlDriver` does not implement `IWritable`, so no configuration can
|
||||
produce a write. The `allowWrites` config field exists and is **inert**; the factory *warns* when it
|
||||
is authored `true` rather than failing, on the grounds that the flag cannot do harm but an operator
|
||||
who believes writes are enabled can.
|
||||
who believes writes are enabled can. → #753
|
||||
|
||||
## Tag models
|
||||
|
||||
@@ -106,7 +109,7 @@ canonical text form. SQL Server behaves the same way.
|
||||
authored `keyValue` refused the tag while the identically-bound `whereValue` was served — and the
|
||||
deploy gate reported the key as *missing* when it was right there in the blob.)
|
||||
|
||||
### `Query` — deferred to P3
|
||||
### `Query` — deferred to P3 (→ #753)
|
||||
|
||||
Named arbitrary-`SELECT`. **The v1 parser rejects it**, and that refusal is enforced end-to-end —
|
||||
parser, validator, planner and the AdminUI editor all decline it rather than accepting the value and
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# QuestDB historian — live gate (T9), 2026-10-11
|
||||
|
||||
> **Status lives in Gitea.** Open items from this file are tracked as issues on gitea.dohertylan.com/dohertj2/lmxopcua
|
||||
> (label `migrated`, 2026-11-06). This file is a historical/design record — do not track status here; file new work as an issue.
|
||||
|
||||
**Verdict: PASSED.** All six legs of spec §7 passed on the docker-dev rig. The rig ran `feat/questdb-historian` at
|
||||
`2ebe0a42`, with the central pair on image `0701f6a833ea`, rebuilt for this gate. The QuestDB backend pointed at the
|
||||
overlay `questdb` service (`questdb/questdb:10.0.1`, `docker-dev/docker-compose.questdb.yml`), with default table
|
||||
@@ -8,7 +11,7 @@ prefix `hist_`.
|
||||
The gate also produced two findings, neither in the QuestDB backend. Both are described under "Gate findings" below:
|
||||
- A crash failover (SIGKILL of the recording Primary) leaves a recording gap of about 30 s. This is the #537
|
||||
Primary-gated capture waiting for Akka downing; it is backend-independent.
|
||||
- One `libgssapi_krb5.so.2` load error is printed per central boot. It is benign.
|
||||
- One `libgssapi_krb5.so.2` load error is printed per central boot. It is benign. → #758
|
||||
|
||||
## Setup
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# Review 03 — Host / ControlPlane / Security / Configuration
|
||||
|
||||
> **Status lives in Gitea.** Open items from this file are tracked as issues on gitea.dohertylan.com/dohertj2/lmxopcua
|
||||
> (label `migrated`, 2026-11-06). This file is a historical/design record — do not track status here; file new work as an issue.
|
||||
|
||||
Repo: `/Users/dohertj2/Desktop/OtOpcUa` @ `d51d35bd` (master). Read-only audit of production code in
|
||||
`src/Server/ZB.MOM.WW.OtOpcUa.Host`, `src/Server/ZB.MOM.WW.OtOpcUa.ControlPlane`,
|
||||
`src/Server/ZB.MOM.WW.OtOpcUa.Security`, `src/Core/ZB.MOM.WW.OtOpcUa.Configuration`.
|
||||
@@ -35,7 +38,7 @@ Severity: Critical / High / Medium / Low. Confidence: High / Medium.
|
||||
- **Suggested fix:** Track consecutive timeouts per `virtualTagId` in `VirtualTagHostActor`/evaluator and
|
||||
quarantine the tag (stop evaluating, publish Bad, log Error, surface on `/uns`) after N (e.g. 3)
|
||||
timeouts until the script is edited. Longer term: cooperative `CancellationToken` polling injected
|
||||
into compiled scripts, or an out-of-process runner.
|
||||
into compiled scripts, or an out-of-process runner (→ #750).
|
||||
|
||||
### 1.2 `Deployment` / `NodeDeploymentState` / `ConfigEdit` / `ConfigAuditLog` grow without bound — every deploy stores a full artifact blob forever
|
||||
- **Severity:** Medium **Confidence:** High
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# Core slice review (Commons, Core, Core.Abstractions, Core.Scripting[.Abstractions], Core.ScriptedAlarms, Core.VirtualTags, Core.AlarmHistorian)
|
||||
|
||||
> **Status lives in Gitea.** Open items from this file are tracked as issues on gitea.dohertylan.com/dohertj2/lmxopcua
|
||||
> (label `migrated`, 2026-11-06). This file is a historical/design record — do not track status here; file new work as an issue.
|
||||
|
||||
Reviewer 05. Read-only audit of production code. master @ d51d35bd.
|
||||
|
||||
Scope note: this slice is unusually mature — collectible-ALC script unloading, per-generation
|
||||
@@ -100,7 +103,7 @@ closed and commented. The findings below are the residue.
|
||||
- Location: `src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/ScriptSandbox.cs:30-35` (class remarks acknowledge it)
|
||||
- Evidence: the sandbox comment states "cannot prevent a script from allocating unbounded memory or spinning in a tight loop — those are budget concerns, handled by the per-evaluation timeout". The timeout bounds wall-clock but not allocation; a `new byte[int.MaxValue]`-style allocation or a growing collection in a loop can OOM the whole in-process server before the 250 ms timeout fires.
|
||||
- Failure scenario: an authored script (buggy or hostile) allocates aggressively and OOMs the server. Only mitigated by operators authoring sane scripts and the preview harness.
|
||||
- Suggested fix: documented trade-off; a true fix needs an out-of-process runner (noted as a v3 concern). Flagging for awareness.
|
||||
- Suggested fix: documented trade-off; a true fix needs an out-of-process runner (noted as a v3 concern). Flagging for awareness. → #750
|
||||
|
||||
### 12. `ScriptedAlarmEngine.OnUpstreamChange` writes `_valueCache` before the disposed check
|
||||
- Severity: Low · Confidence: High
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# Review 06 — Drivers (session slice): Galaxy, OpcUaClient, Mqtt, MTConnect, Sql
|
||||
|
||||
> **Status lives in Gitea.** Open items from this file are tracked as issues on gitea.dohertylan.com/dohertj2/lmxopcua
|
||||
> (label `migrated`, 2026-11-06). This file is a historical/design record — do not track status here; file new work as an issue.
|
||||
|
||||
Repo: `/Users/dohertj2/Desktop/OtOpcUa` @ `d51d35bd` (master). Production code only (`src/Drivers/...`). Read-only audit; every finding was verified by reading the cited lines (fork-sourced MQTT/MTConnect/SQL findings were spot-checked by the lead against the cited lines). Line numbers are as of this commit. Prefix key: **G** Galaxy, **O** OpcUaClient, **M** MQTT, **T** MTConnect, **S** Sql.
|
||||
|
||||
Host context that shapes several findings (verified outside the slice):
|
||||
@@ -134,6 +137,7 @@ Host context that shapes several findings (verified outside the slice):
|
||||
- Location: `SparkplugIngestor.cs:1274-1285` (`if (binding.DataType.IsSparkplugArray()) { WarnOnce(...); return; }`; DataSet/Template/PropertySet at `:1287-1302`); `MqttBrowseSession.cs:387-392` lists the leaf with `IsArray: true`.
|
||||
- Impact: an operator can commit a tag the ingestor never feeds — warned once, then `BadWaitingForInitialData` forever.
|
||||
- Suggested fix: mark array leaves not-bindable in `DescribeMetric` as `mapped is null` already is.
|
||||
- Tracking: the array-read capability itself → #754.
|
||||
|
||||
### T-2. MTConnect Agent-restart detection lives only on the `/sample` pump; `ReadAsync` discards `instanceId`
|
||||
- **Severity: Low** · **Confidence: High**
|
||||
@@ -144,6 +148,7 @@ Host context that shapes several findings (verified outside the slice):
|
||||
- **Severity: Low** · **Confidence: High** (all documented deferrals that fail loudly or warn once)
|
||||
- Location: `Driver.Sql.Contracts/SqlEquipmentTagParser.cs:75-76`, `SqlGroupPlanner.cs:336-339`; `SqlDriverFactoryExtensions.cs:214-225`, `SqlDriverProbe.cs:196-211`, `SqlDriverBrowser.cs:135-141`; `SqlDriverFactoryExtensions.cs:151-161` + `SqlDriver.cs:30-31` (no `IWritable`).
|
||||
- Note: a `model: "Query"` tag is silently skipped (ledger + `BadNodeIdUnknown`) rather than refused at the deploy gate.
|
||||
- Tracking: the Query/MySql/Odbc/allowWrites features → #753.
|
||||
|
||||
### Dead parsed surface (Low, High confidence)
|
||||
- **T-3** `MTConnectObservation.SampleRate` parsed per observation (`MTConnectStreamsParser.cs:424-428`) and never read; `MTConnectTagDefinition.MtType/MtSubType/Units` carried but only `MtCategory` is read (`MTConnectDriver.cs:3493`).
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# Review 07 — PLC drivers (AbCip, AbLegacy, Ab.Transport, Ab.LibplctagShared, Modbus, S7, TwinCAT, FOCAS, Calculation, Cli)
|
||||
|
||||
> **Status lives in Gitea.** Open items from this file are tracked as issues on gitea.dohertylan.com/dohertj2/lmxopcua
|
||||
> (label `migrated`, 2026-11-06). This file is a historical/design record — do not track status here; file new work as an issue.
|
||||
|
||||
Repo: `/Users/dohertj2/Desktop/OtOpcUa` @ `d51d35bd` (master). Production code only. Every finding below was verified by reading the cited lines; sub-reviewer candidates that could not be confirmed were dropped. Paths are relative to `src/Drivers/` unless absolute.
|
||||
|
||||
Legend: **Sev** Critical/High/Medium/Low · **Conf** High/Medium.
|
||||
@@ -81,7 +84,7 @@ Default-configured device with 200 holding registers = 200 FC03 round-trips per
|
||||
**Sev Medium · Conf High** — `CalculationDriver.cs:178-186` (`_changeDependents` from `DependencyRefs` only), `:354-359`; `src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Validation/DraftValidator.cs:395-456` (only Missing/NotFound/Cycle). `ctx.GetTag("Plant/" + line + "/Temp")` or `return ctx.Now.Hour;` with the default `changeTriggered:true` stays `BadWaitingForInitialData` forever while the driver reports Healthy. **Fix:** deploy-gate `CalculationNoEffectiveTrigger` when change-triggered && deps.Count == 0 && no timer; or evaluate once at init.
|
||||
|
||||
### U6. AbLegacy native: PLC-5 writes are not shipped, PLC-5 reads are N-file only, PLC-5 sub-elements refused (documented, surfaced correctly)
|
||||
**Sev Low · Conf High** — `Ab.Transport/Pccc/PcccServices.cs:16-19` (`Plc5WriteVerified = false`), `:112-114`; `ZB.MOM.WW.OtOpcUa.Driver.AbLegacy/NativeAbLegacyTagRuntime.cs:150, 261-263`. All surface as `AbStatus.Unsupported` → `BadNotSupported` with no health impact, and `Native` is opt-in for AbLegacy. Noted as a capability gap, not a defect.
|
||||
**Sev Low · Conf High** — `Ab.Transport/Pccc/PcccServices.cs:16-19` (`Plc5WriteVerified = false`), `:112-114`; `ZB.MOM.WW.OtOpcUa.Driver.AbLegacy/NativeAbLegacyTagRuntime.cs:150, 261-263`. All surface as `AbStatus.Unsupported` → `BadNotSupported` with no health impact, and `Native` is opt-in for AbLegacy. Noted as a capability gap, not a defect. → #752
|
||||
|
||||
### U8. FOCAS: `FocasDataType.String` is authorable but every read path publishes a number at Good
|
||||
**Sev Medium · Conf High** — editor lists every enum member (`AdminUI/Components/Shared/Uns/TagEditors/FocasTagConfigEditor.razor:18`); `ZB.MOM.WW.OtOpcUa.Driver.FOCAS/Wire/FocasConstants.cs:116` (`_ => FocasPmcDataType.Byte`), `FocasPmcCoalescer.cs:135` (`_ => (object)raw`, a `long`), `Wire/WireFocasClient.cs:392-393` (PARAM default reads Int32), `:456-458` (MACRO returns `double`). A String-typed OPC UA node receives a boxed `long`/`int`/`double` at Good. **Fix:** reject `String` in `FocasTagDefinitionFactory.FromTagConfig`/capability matrix and drop it from the editor.
|
||||
|
||||
+4
-1
@@ -1,5 +1,8 @@
|
||||
# Security
|
||||
|
||||
> **Status lives in Gitea.** Open follow-ups and known gaps noted in this doc are tracked as issues on
|
||||
> gitea.dohertylan.com/dohertj2/lmxopcua (label `migrated`, 2026-11-06). This doc describes the system — do not track status here; file new work as an issue.
|
||||
|
||||
> **v2 status (2026-05-26).** The four security concerns below are unchanged in v2.
|
||||
> Paths + project names moved: `OtOpcUa.Server/Security/` → `OtOpcUa.Security/`
|
||||
> (`Ldap/`, `Jwt/`, `Endpoints/AuthEndpoints.cs`), `OtOpcUa.Admin` is gone (its
|
||||
@@ -264,7 +267,7 @@ guards in front of the store, bound from the same `Security:ApiKeys` section
|
||||
|
||||
The budget is **process-wide, not per remote endpoint**: the OPC UA SDK's impersonation callback (the
|
||||
`IOpcUaUserAuthenticator` seam) does not carry the client's address, so per-endpoint accounting needs that
|
||||
seam widened in the OpcUaServer project (a Wave 3 follow-up). Neither guard applies to a driver-only node:
|
||||
seam widened in the OpcUaServer project (a Wave 3 follow-up → #751). Neither guard applies to a driver-only node:
|
||||
its `ArtifactApiKeyStore` is two in-memory dictionary probes and is never wrapped.
|
||||
|
||||
### LDAP bind flow (`OtOpcUaLdapAuthService`)
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# System Review Remediation Implementation Plan
|
||||
|
||||
> **Status lives in Gitea.** Open items from this file are tracked as issues on gitea.dohertylan.com/dohertj2/lmxopcua
|
||||
> (label `migrated`, 2026-11-06). This file is a historical/design record — do not track status here; file new work as an issue.
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers-extended-cc:subagent-driven-development (recommended) or superpowers-extended-cc:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Resolve every finding from the 2026-10-21 8-slice Fable system review of OtOpcUa (master `d51d35bd`): 1 Critical, ~25 High, ~60 Medium, ~85 Low. These are memory/resource leaks, unimplemented features, performance limiters, and concurrency/health-contract hazards.
|
||||
@@ -247,7 +250,7 @@ Merge order inside a wave is alphabetical by lane, rebasing as needed. Two lanes
|
||||
- **E2 Sandbox hardening** (`R05:10`, `R05:11`):
|
||||
- Deny `System.Threading` with an allow-list (`CancellationToken`, `Interlocked`, `Volatile`).
|
||||
- Deny `System.Type.GetType`/`GetMethod*`/`InvokeMember` and `System.Runtime.CompilerServices.RuntimeHelpers`.
|
||||
- Add an allocation budget: sample `GC.GetAllocatedBytesForCurrentThread` around each run and quarantine on breach (`Scripting:MaxAllocBytesPerRun`, default 64 MB). Document that a pre-emptive OOM still needs an out-of-process runner, and file a follow-up issue for that.
|
||||
- Add an allocation budget: sample `GC.GetAllocatedBytesForCurrentThread` around each run and quarantine on breach (`Scripting:MaxAllocBytesPerRun`, default 64 MB). Document that a pre-emptive OOM still needs an out-of-process runner, and file a follow-up issue for that (→ #750).
|
||||
- Tests: each forbidden form gets an `OTSCRIPT` diagnostic, and the Monaco editor parity test still matches.
|
||||
- **E3 Scripted-alarm engine** (`R05:1`, `3`, `6`, `7`, `9`, `12`):
|
||||
- Clear `_valueCache` in `LoadAsync`; move its write below the `_disposed` guard.
|
||||
@@ -335,7 +338,7 @@ Each lane owns `src/Drivers/<Driver>*/**` + its `tests/Drivers/<Driver>*`, its A
|
||||
- `NotSupportedException` ⇒ `BadNotSupported`, no health, reject at `FromTagConfig` (`H16`).
|
||||
- Table swap (`H13`); prune semaphores on index change (`L7`).
|
||||
- **Array write encode** (`U10`); `IBatchSubscribable`.
|
||||
- Document the PLC-5 write capability gap with a hardware follow-up issue (`U6`).
|
||||
- Document the PLC-5 write capability gap with a hardware follow-up issue (`U6`) (→ #752).
|
||||
|
||||
### Lane TwinCAT
|
||||
- Per-registration isolation with dead-registration retry (`R07:H11`).
|
||||
@@ -399,7 +402,7 @@ Each lane owns `src/Drivers/<Driver>*/**` + its `tests/Drivers/<Driver>*`, its A
|
||||
**MQTT:**
|
||||
- Failed SUBSCRIBE ⇒ pending set retried on reconnect/reconcile, `SubscribeAsync` throws on a transport failure (`R06:M-1`).
|
||||
- **Wire `birthObservationWindowSeconds`** into `MqttDriverBrowser.OpenBudget` + discovery UntilStable (`M-4`).
|
||||
- Array leaves not bindable, plus a Sparkplug-array-read feature issue (`M-5`).
|
||||
- Array leaves not bindable, plus a Sparkplug-array-read feature issue (`M-5`) (→ #754).
|
||||
- Prune `LastValueCache` on Register (`M-2`).
|
||||
- Dispose the failed connection (`M-3`).
|
||||
- Wildcard topic trie (`M-6`); static UTF-8 encoder (`M-7`).
|
||||
@@ -409,7 +412,7 @@ Each lane owns `src/Drivers/<Driver>*/**` + its `tests/Drivers/<Driver>*`, its A
|
||||
- Row cap with a `TOP/LIMIT N+1` dialect + config-error status (`S-1`).
|
||||
- Rate-limited warnings (`S-6`); plan cache (`S-7`).
|
||||
- Dispose `_gate` (`S-3`).
|
||||
- `Query` model refused at the deploy gate via the parser + feature issues for MySql/Odbc/allowWrites (`S-4`).
|
||||
- `Query` model refused at the deploy gate via the parser + feature issues for MySql/Odbc/allowWrites (`S-4`) (→ #753).
|
||||
- `IS_NULLABLE` in browse attributes (`S-5`).
|
||||
- Withhold JSON parser text (`S-8`); `IBatchSubscribable`.
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# TwinCAT driver — v3 backlog
|
||||
|
||||
> **Status lives in Gitea.** Open items from this file are tracked as issues on gitea.dohertylan.com/dohertj2/lmxopcua
|
||||
> (label `migrated`, 2026-11-06). This file is a historical/design record — do not track status here; file new work as an issue.
|
||||
|
||||
The v2 TwinCAT driver is considered solid: 28 integration tests (14 `[TwinCATFact]` +
|
||||
16-case `[TwinCATTheory]`) running live against the TCBSD fixture, 110 unit tests,
|
||||
three latent driver bugs shaken out (notification cycle units, `STRING(N)` mapper,
|
||||
@@ -27,7 +30,7 @@ user's approval, an `oee-tagdump-mac` route for the Mac's current VPN IP (`10.18
|
||||
to **Z35474** (TC3) and **Z34834** (TC2, `5.69.178.220.1.1`, 10.201.45.197) by UDP-48899 AddRoute with the
|
||||
factory login. ⚠️ A same-name AddRoute does **not** replace on either runtime: both presses now carry TWO
|
||||
`oee-tagdump-mac` entries — the stale `10.181.198.189.1.1` and the new one (route table read back over ADS,
|
||||
port 10000 / IG 803). Removing the stale one needs an ADS write and was not done. Every other press still
|
||||
port 10000 / IG 803). Removing the stale one needs an ADS write and was not done (→ #755). Every other press still
|
||||
has only the stale route, so it refuses the Mac; the VPN IP changes again ⇒ the routes go stale again.
|
||||
|
||||
## Status of the original items
|
||||
@@ -38,14 +41,14 @@ has only the stale route, so it refuses the Mac; the VPN IP changes again ⇒ th
|
||||
|
||||
2. **Notification coalescing under load** — run the subscribe test while the PLC cycle is saturated.
|
||||
Needs the TCBSD fixture (loading a production press is out of the question) and the `GVL_Perf` /
|
||||
`FB_PerfChurn` fixture project from the stranded `auto/driver-gaps` branch. Fixture-gated.
|
||||
`FB_PerfChurn` fixture project from the stranded `auto/driver-gaps` branch. Fixture-gated. → #755
|
||||
|
||||
3. **Multi-hop AMS route** — a test behind an IPC gateway with a chained route entry. No hardware.
|
||||
3. **Multi-hop AMS route** — a test behind an IPC gateway with a chained route entry. No hardware. → #755
|
||||
|
||||
4. **License-rotation automation** — XAR's 7-day trial expires on schedule. Ops item, not code.
|
||||
4. **License-rotation automation** — XAR's 7-day trial expires on schedule. Ops item, not code. → #755
|
||||
|
||||
5. **Lab rig** — cheapest IPC on a dedicated network; the only route that covers real EtherCAT I/O
|
||||
timing and cycle jitter under CPU load. Blocked on hardware + budget.
|
||||
timing and cycle jitter under CPU load. Blocked on hardware + budget. → #755
|
||||
|
||||
## Added by #612 / #645
|
||||
|
||||
@@ -69,4 +72,4 @@ has only the stale route, so it refuses the Mac; the VPN IP changes again ⇒ th
|
||||
returned 10,628 variables. No `SymbolsLoadMode` option is needed.
|
||||
|
||||
9. **Discovered struct/FB member writes (#612)** — deferred: writes, never on a press; fixture-only.
|
||||
Likewise **sum-write** was deliberately NOT ported from the stranded branch.
|
||||
Likewise **sum-write** was deliberately NOT ported from the stranded branch. → #755
|
||||
|
||||
Reference in New Issue
Block a user