From fd7d06bb122642fbb7f5e7ac9c9762d05cb555ac Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Mon, 10 Aug 2026 07:03:02 -0400 Subject: [PATCH] docs(reviews): regenerate README for 14 new module reviews; fix MTConnect finding-heading level (#### invisible to the generator) --- .../Driver.MTConnect.Contracts/findings.md | 2 +- code-reviews/Driver.MTConnect/findings.md | 16 ++-- code-reviews/README.md | 77 ++++++++++++++++++- 3 files changed, 85 insertions(+), 10 deletions(-) diff --git a/code-reviews/Driver.MTConnect.Contracts/findings.md b/code-reviews/Driver.MTConnect.Contracts/findings.md index 4b450198..3fbf237c 100644 --- a/code-reviews/Driver.MTConnect.Contracts/findings.md +++ b/code-reviews/Driver.MTConnect.Contracts/findings.md @@ -33,7 +33,7 @@ a category produced nothing rather than leaving it blank. module, never reused. Findings are never deleted — close them by changing Status and completing Resolution. --> -#### Driver.MTConnect.Contracts-001 +### Driver.MTConnect.Contracts-001 | Field | Value | |---|---| diff --git a/code-reviews/Driver.MTConnect/findings.md b/code-reviews/Driver.MTConnect/findings.md index 2cb22dd6..25f6a9a4 100644 --- a/code-reviews/Driver.MTConnect/findings.md +++ b/code-reviews/Driver.MTConnect/findings.md @@ -33,7 +33,7 @@ a category produced nothing rather than leaving it blank. never reused. Findings are never deleted — close them by changing Status and completing Resolution. --> -#### Driver.MTConnect-001 +### Driver.MTConnect-001 | Field | Value | |---|---| @@ -70,7 +70,7 @@ while a buffer roll behind a working stream still reopens instantly. Pinned by `A_rebaseline_after_a_delivered_chunk_still_reopens_immediately`, which fails any "back off on every re-baseline" over-correction. -#### Driver.MTConnect-002 +### Driver.MTConnect-002 | Field | Value | |---|---| @@ -103,7 +103,7 @@ and the type remarks now state the URL-composing rule. Pinned by requested `/probe`, expected `/VMC-1/probe`) and the control `An_absent_deviceName_leaves_the_probe_agent_wide`. -#### Driver.MTConnect-003 +### Driver.MTConnect-003 | Field | Value | |---|---| @@ -154,7 +154,7 @@ mapper that had stopped setting the row's type. modules. The stale premises this defect invalidated inside these two modules are corrected under `Driver.MTConnect-008` and `Driver.MTConnect.Contracts-001`.)_ -#### Driver.MTConnect-004 +### Driver.MTConnect-004 | Field | Value | |---|---| @@ -188,7 +188,7 @@ rather than High. **Resolution:** _(open — the fix belongs in `ZB.MOM.WW.OtOpcUa.AdminUI`, outside this review's modules.)_ -#### Driver.MTConnect-005 +### Driver.MTConnect-005 | Field | Value | |---|---| @@ -218,7 +218,7 @@ touches ~10 read sites and the exposure does not justify unreviewed churn. **Resolution:** _(open)_ -#### Driver.MTConnect-006 +### Driver.MTConnect-006 | Field | Value | |---|---| @@ -245,7 +245,7 @@ that happens to have it: `if (value is null or Array or not IConvertible) return **Resolution:** _(open)_ -#### Driver.MTConnect-007 +### Driver.MTConnect-007 | Field | Value | |---|---| @@ -267,7 +267,7 @@ state on `Dispose` that it is not thread-safe and is called only under the drive **Resolution:** _(open)_ -#### Driver.MTConnect-008 +### Driver.MTConnect-008 | Field | Value | |---|---| diff --git a/code-reviews/README.md b/code-reviews/README.md index 3b798cc6..15a470a4 100644 --- a/code-reviews/README.md +++ b/code-reviews/README.md @@ -33,6 +33,8 @@ Each module's `findings.md` is the source of truth; this file is generated from | [Driver.AbLegacy](Driver.AbLegacy/findings.md) | Claude Code | 2026-06-19 | `7286d320` | Reviewed | 0 | 15 | | [Driver.AbLegacy.Cli](Driver.AbLegacy.Cli/findings.md) | Claude Code | 2026-06-19 | `111d6983` | Reviewed | 0 | 8 | | [Driver.AbLegacy.Contracts](Driver.AbLegacy.Contracts/findings.md) | Claude Code | 2026-06-19 | `a19b0f86` | Reviewed | 0 | 4 | +| [Driver.Calculation](Driver.Calculation/findings.md) | Claude (automated review agent) | 2026-08-10 | `b990adae` | Reviewed | 1 | 5 | +| [Driver.Calculation.Contracts](Driver.Calculation.Contracts/findings.md) | Claude (automated review agent) | 2026-08-10 | `b990adae` | Reviewed | 1 | 1 | | [Driver.Cli.Common](Driver.Cli.Common/findings.md) | Claude Code | 2026-06-19 | `7286d320` | Reviewed | 0 | 10 | | [Driver.FOCAS](Driver.FOCAS/findings.md) | Claude Code | 2026-06-19 | `04e0877b` (re-review; prior `76d35d1`) | Reviewed | 0 | 12 | | [Driver.FOCAS.Cli](Driver.FOCAS.Cli/findings.md) | Claude Code | 2026-06-19 | `7286d320` | Reviewed | 0 | 7 | @@ -40,19 +42,31 @@ Each module's `findings.md` is the source of truth; this file is generated from | [Driver.Galaxy](Driver.Galaxy/findings.md) | Claude Code | 2026-06-19 | `7286d320` | Reviewed | 0 | 19 | | [Driver.Galaxy.Browser](Driver.Galaxy.Browser/findings.md) | Claude Code | 2026-06-19 | `7286d320` | Reviewed | 0 | 4 | | [Driver.Galaxy.Contracts](Driver.Galaxy.Contracts/findings.md) | Claude Code | 2026-06-19 | `7286d320` | Reviewed | 0 | 3 | +| [Driver.Historian.Gateway](Driver.Historian.Gateway/findings.md) | Claude Code | 2026-08-10 | `b990adae` | Reviewed | 0 | 3 | | [Driver.Historian.Wonderware](Driver.Historian.Wonderware/findings.md) | Claude Code | 2026-06-19 | `7286d320` | Reviewed | 0 | 12 | | [Driver.Historian.Wonderware.Client](Driver.Historian.Wonderware.Client/findings.md) | Claude Code | 2026-06-19 | `7286d320` | Reviewed | 0 | 13 | | [Driver.Historian.Wonderware.Client.Contracts](Driver.Historian.Wonderware.Client.Contracts/findings.md) | Claude Code | 2026-06-19 | `a19b0f86` | Reviewed | 0 | 4 | +| [Driver.MTConnect](Driver.MTConnect/findings.md) | Claude (per-module review) | 2026-08-10 | `b990adae` | Complete | 5 | 8 | +| [Driver.MTConnect.Contracts](Driver.MTConnect.Contracts/findings.md) | Claude (per-module review) | 2026-08-10 | `b990adae` | Complete | 0 | 1 | | [Driver.Modbus](Driver.Modbus/findings.md) | Claude Code | 2026-06-19 | `7286d320` | Reviewed | 0 | 14 | | [Driver.Modbus.Addressing](Driver.Modbus.Addressing/findings.md) | Claude Code | 2026-06-19 | `7286d320` | Reviewed | 0 | 11 | | [Driver.Modbus.Cli](Driver.Modbus.Cli/findings.md) | Claude Code | 2026-06-19 | `7286d320` | Reviewed | 0 | 11 | | [Driver.Modbus.Contracts](Driver.Modbus.Contracts/findings.md) | Claude Code | 2026-06-19 | `a19b0f86` | Reviewed | 0 | 4 | +| [Driver.Mqtt](Driver.Mqtt/findings.md) | Claude Code | 2026-08-10 | `b990adae` | Reviewed | 2 | 10 | +| [Driver.Mqtt.Browser](Driver.Mqtt.Browser/findings.md) | Claude | 2026-08-10 | `b990adae` | Reviewed | 4 | 5 | +| [Driver.Mqtt.Contracts](Driver.Mqtt.Contracts/findings.md) | Claude | 2026-08-10 | `b990adae` | Reviewed | 4 | 7 | +| [Driver.Mqtt.Transport](Driver.Mqtt.Transport/findings.md) | Claude Code | 2026-08-10 | `b990adae` | Reviewed | 1 | 2 | | [Driver.OpcUaClient](Driver.OpcUaClient/findings.md) | Claude Code | 2026-06-19 | `7286d320` | Reviewed | 0 | 16 | | [Driver.OpcUaClient.Browser](Driver.OpcUaClient.Browser/findings.md) | Claude Code | 2026-06-19 | `7286d320` | Reviewed | 0 | 3 | | [Driver.OpcUaClient.Contracts](Driver.OpcUaClient.Contracts/findings.md) | Claude Code | 2026-06-19 | `a19b0f86` | Reviewed | 0 | 3 | +| [Driver.OpcUaClient.Session](Driver.OpcUaClient.Session/findings.md) | Claude (automated review agent) | 2026-08-10 | `b990adae` | Reviewed | 0 | 0 | | [Driver.S7](Driver.S7/findings.md) | Claude Code | 2026-06-19 | `7286d320` | Reviewed | 0 | 16 | | [Driver.S7.Cli](Driver.S7.Cli/findings.md) | Claude Code | 2026-06-19 | `111d6983` | Reviewed | 0 | 12 | | [Driver.S7.Contracts](Driver.S7.Contracts/findings.md) | Claude Code | 2026-06-19 | `a19b0f86` | Reviewed | 0 | 3 | +| [Driver.Sql](Driver.Sql/findings.md) | Claude Code | 2026-08-10 | `b990adae` | Reviewed | 7 | 10 | +| [Driver.Sql.Browser](Driver.Sql.Browser/findings.md) | Claude Code | 2026-08-10 | `b990adae` | Reviewed | 3 | 3 | +| [Driver.Sql.Contracts](Driver.Sql.Contracts/findings.md) | Claude Code | 2026-08-10 | `b990adae` | Reviewed | 2 | 2 | +| [Driver.Sql.Dialect](Driver.Sql.Dialect/findings.md) | Claude Code | 2026-08-10 | `b990adae` | Reviewed | 3 | 3 | | [Driver.TwinCAT](Driver.TwinCAT/findings.md) | Claude Code | 2026-06-19 | `04e0877b` | Reviewed | 0 | 17 | | [Driver.TwinCAT.Cli](Driver.TwinCAT.Cli/findings.md) | Claude Code | 2026-06-19 | `111d6983` | Reviewed | 0 | 9 | | [Driver.TwinCAT.Contracts](Driver.TwinCAT.Contracts/findings.md) | Claude Code | 2026-06-19 | `a19b0f86` | Reviewed | 0 | 2 | @@ -66,7 +80,41 @@ Each module's `findings.md` is the source of truth; this file is generated from Findings with status `Open` or `In Progress`, ordered by severity. -_No pending findings._ +| ID | Severity | Category | Location | Description | +|---|---|---|---|---| +| Driver.MTConnect-003 | High | Correctness & logic bugs | `src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/RawBrowseCommitMapper.cs:256` (cause) · `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.MTConnect/MTConnectDriver.cs:3286` (`BuildBinding` precedence) | **Every browse-committed MTConnect tag is coerced to `String` at runtime while its OPC UA node is typed from the probe inference**, so a browsed `SAMPLE` publishes text into a `Double` node. `RawBrowseCommitMapper.MapLeaf` does two things… | +| Driver.Calculation-005 | Medium | Concurrency & thread safety | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Calculation/CalculationDriver.cs:300-314` (`OnDependencyValue`), `:374-410` (`EvaluateTag`); cross-module: `src/Server/ZB.MOM.WW.OtOpcUa.Runtime/VirtualTags/DependencyConsumerMuxAdapter.cs` | `OnDependencyValue` evaluates every change-triggered dependent tag **inline, under `_lock`**, and `EvaluateTag`'s call into `CalculationEvaluator.Evaluate` ultimately runs `TimedScriptEvaluator<...>.RunAsync(context).GetAwaiter().GetResult… | +| Driver.MTConnect-004 | Medium | Design-document adherence | `src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Drivers/Forms/MTConnectDriverForm.razor:1` · `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.MTConnect.Contracts/MTConnectDriverOptions.cs:146` | `IWritable` shipped for this driver on 2026-08-05 (`b29623cf`) behind `Write.Enabled`, and `docs/drivers/MTConnect.md` §"Two independent gates" tells the operator to set `"Write": { "Enabled": true }` in the driver config. **There is no wa… | +| Driver.Sql-002 | Medium | Error handling & resilience | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql/SqlGroupPlanner.cs:127` | `BuildKeyValuePlan` emits one bind parameter per distinct `keyValue` in a group, with no upper bound and no chunking. Every provider caps this: `Microsoft.Data.SqlClient` allows 2100 parameters per command, and Oracle limits an `IN` expres… | +| Driver.Calculation.Contracts-001 | Low | Performance & resource management | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Calculation.Contracts/CalculationTagDefinitionFactory.cs:107-160` (`Inspect`) | `Inspect` parses `reference` with `JsonDocument.Parse` once directly (to check the root kind and read `changeTriggered`/`timerIntervalMs` for the "present-but-discarded" warnings), and then — when the object parsed cleanly — calls `TryRead… | +| Driver.MTConnect-005 | Low | Concurrency & thread safety | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.MTConnect/MTConnectDriver.cs:2655` · `:689` · `:797` · `:1425` | `_options` is the one piece of shared driver state published by a **plain** field write (`_options = options;` at the `StartCoreAsync` commit point) and read lock-free from other threads — `ReadAsync`, `WriteAsync`, `DiscoverAsync`, `HostN… | +| Driver.MTConnect-006 | Low | Correctness & logic bugs | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.MTConnect/MTConnectDriver.cs:914` | `TryFormatValue` refuses `null` and `Array`, then renders everything else with `Convert.ToString(value, InvariantCulture)`. Its own remark gives the right reason for the array guard — `Convert.ToString` falls back to `object.ToString()` fo… | +| Driver.MTConnect-007 | Low | Performance & resource management | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.MTConnect/MTConnectAgentClient.cs:85` | `MTConnectAgentClient.Dispose()` is a plain check-then-set on a non-volatile `_disposed` field, so two concurrent disposals can both pass the guard. The second then calls `_disposeCts.Cancel()` on an already-disposed `CancellationTokenSour… | +| Driver.Mqtt-006 | Low | Concurrency & thread safety | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt/Sparkplug/SparkplugPrimaryHost.cs:278` | `DisposeAsync` calls `_gate.Dispose()`. `StopAsync` cancels the reconcile loop but does not await it, so a `ReconcileAsync` already in flight can be sitting in `ClaimAsync`/`ReleaseAsync`'s `_gate.WaitAsync(...)`, or on its way to the `fin… | +| Driver.Mqtt-007 | Low | Error handling & resilience | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt/MqttSubscriptionManager.cs:406-424` (`OnReconnectedAsync`) | When the reconnect path finds live subscribed topics but resolves **zero** filters for them, it logs a warning and returns normally. The type's own contract, stated two paragraphs later, is that a reconnect which re-establishes nothing mus… | +| Driver.Mqtt.Browser-002 | Low | Correctness & logic bugs | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Browser/MqttBrowseSession.cs:469` | The plain-mode and Sparkplug-mode paths disagree about what may become a tree label. `ObserveSparkplugBirth` runs every group/edge-node/device/metric identifier through `IsUsableLabel`, whose doc explains the reason: "a metric name is arbi… | +| Driver.Mqtt.Browser-003 | Low | Concurrency & thread safety | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Browser/MqttBrowseSession.cs:685` | `GetOrCreate` reads `_nodeCount` and compares it to `_nodeCap`, then increments after a successful `GetOrAdd`. The read and the increment are not atomic with respect to each other, so N threads can each observe `_nodeCount == _nodeCap - 1`… | +| Driver.Mqtt.Browser-004 | Low | Correctness & logic bugs | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Browser/MqttBrowseSession.cs:1079` | `Project` orders a level by `n.Segment`, but the dictionary is keyed by `n.Path` — and the whole reason for that keying (documented on `GetOrCreate`) is that in Sparkplug mode two siblings *can* share a `Segment`: a device folder `Plant1/E… | +| Driver.Mqtt.Browser-005 | Low | Performance & resource management | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Browser/MqttBrowseSession.cs:59`, `:81` | The per-session memory ceiling is higher than the constants suggest at a glance. `DefaultNodeCap` is 50,000 nodes, and each `TopicNode` retains its full `Path` (up to `MaxTopicChars` = 1,024 chars), its `Segment` (up to 256) and a snippet… | +| Driver.Mqtt.Contracts-004 | Low | Documentation & comments | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Contracts/MqttTagDefinitionFactory.cs:124`, `:234`, `:476` | `retainSeed` is the one behavioural key still read leniently. `ReadBoolOrDefault` returns the default for any non-boolean JSON value, so `"retainSeed": "false"` (a string, which a CSV import or a hand-edited blob produces naturally) silent… | +| Driver.Mqtt.Contracts-005 | Low | Testing coverage | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Contracts/MqttDriverOptions.cs:25`, `:71`, `:75`, `:79`, `:83`, `:99`, `:229` | `MqttDriverOptions` / `MqttPlainOptions` carry seven `System.ComponentModel.DataAnnotations` `[Range]` attributes and **nothing ever runs them**. Grepping `Validator.TryValidateObject` / `ValidationContext` across all four MQTT projects re… | +| Driver.Mqtt.Contracts-006 | Low | Correctness & logic bugs | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Contracts/MqttWriteEncoder.cs:281` | Two edge cases in the `DriverDataType.DateTime` write arm. First, `(ulong)…ToUnixTimeMilliseconds()` on a pre-1970 value wraps a negative `long` into a very large `ulong`, so writing `1969-12-31` publishes a timestamp roughly 584 million y… | +| Driver.Mqtt.Contracts-007 | Low | Error handling & resilience | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Contracts/Sparkplug/SparkplugTopic.cs:202`, `:232` | `SparkplugTopic` validates asymmetrically. `TryParse` enforces `IsValidSegment` (non-empty, no `+`/`#`) on every segment it reads, but `Format` and `FormatState` enforce only `ArgumentException.ThrowIfNullOrEmpty` on `groupId`/`edgeNodeId`… | +| Driver.Mqtt.Transport-002 | Low | Correctness & logic bugs | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Transport/MqttClientOptionsFactory.cs:97-100` | Credentials are attached only when `Username` is non-empty: `if (!string.IsNullOrEmpty(options.Username)) builder.WithCredentials(options.Username, options.Password ?? "")`. A config carrying a `Password` and **no** `Username` therefore co… | +| Driver.Sql-004 | Low | Error handling & resilience | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql/SqlDriver.cs:651` | `HandlePollError` skips the connection class by testing `ex is DbException`, on the stated premise that "a subscribed-read outage surfaces as a DbException the reader threw, which ReadAsync has ALREADY classified". Not every unreachable-da… | +| Driver.Sql-005 | Low | Correctness & logic bugs | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql/SqlDriver.cs:641` | `IsConnectionClass` treats `BadCommunicationError` as "the database did not answer", so a poll carrying it reports the endpoint `Stopped`. But that code is minted by `GroupResult.Failed`, which the reader raises only after the connection h… | +| Driver.Sql-006 | Low | Correctness & logic bugs | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql/SqlDriver.cs:599` | `ObservePollOutcome` advances `LastSuccessfulRead` only when at least one snapshot is Good. Several codes are proof the database answered without being Good: `BadNoData` (the query ran, the row is absent), `Uncertain`/`Bad` (a present row… | +| Driver.Sql-008 | Low | Documentation & comments | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql/SqlPollReader.cs:556` | `SelectWideRow`'s remarks justify giving the `topByTimestamp` form the dialect's single-row limit on the grounds that "there the `ORDER BY` makes 'the first row' a defined answer". That holds only when the ordering column is unique. `ORDER… | +| Driver.Sql-009 | Low | Security | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql/SqlDriverProbe.cs:83` | The probe surfaces the raw parser text on a malformed config ("Config JSON is invalid: " + `ex.Message`) where `SqlDriverBrowser.ParseDocument` deliberately withholds the identical message "because the malformed text may carry a connection… | +| Driver.Sql-010 | Low | Concurrency & thread safety | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql/SqlDriver.cs:675` | Every health transition is a read-modify-write over a `Volatile`-accessed field with no compare-and-swap: `Degrade`, `TouchLastSuccessfulRead` and `SetHealthUnlessFaulted` each `ReadHealth()`, build a new record and `WriteHealth()` it. Con… | +| Driver.Sql.Browser-001 | Low | Correctness & logic bugs | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql.Browser/SqlBrowseSession.cs:290` | `PreferredTimestampColumn` nominates the first column whose dialect-mapped type is `DriverDataType.DateTime`. That set includes **date-only** types: `SqlServerDialect.MapColumnType` maps `"date"` to DateTime, and so does `PostgresDialect`… | +| Driver.Sql.Browser-002 | Low | Concurrency & thread safety | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql.Browser/SqlBrowseSession.cs:204`, `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql.Browser/SqlBrowseSession.cs:325` | Two small races around the registry reaper. (1) `DisposeAsync` disposes `_gate` unconditionally; a call already blocked in `_gate.WaitAsync` then throws `ObjectDisposedException` from inside the semaphore rather than the guarded `ObjectDis… | +| Driver.Sql.Browser-003 | Low | Security | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql.Browser/SqlDriverBrowser.cs:262` | `OpenAsync` accepts an ad-hoc `connectionString` literal from the browse form and dials it verbatim. That is an unrestricted outbound-connect primitive on the AdminUI host: an arbitrary host and port, plus whatever the provider's keyword s… | +| Driver.Sql.Contracts-001 | Low | Correctness & logic bugs | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql.Contracts/SqlEquipmentTagParser.cs:65`, `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql.Contracts/SqlTagDefinitionFactory.cs:132` | The two value-bearing fields are read asymmetrically and nothing documents it. `whereValue` goes through `ReadScalar`, which accepts a JSON string, number or boolean and captures the raw token — the design doc's own wide-row example author… | +| Driver.Sql.Contracts-002 | Low | Correctness & logic bugs | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql.Contracts/SqlEquipmentTagParser.cs:50` | Cross-module, and reachable through every driver rather than only this one. The strict enum read is `TagConfigJson.TryReadEnumStrict`, which classifies via `Enum.TryParse(text, ignoreCase: true, …)` — and that method accepts a **numeric st… | +| Driver.Sql.Dialect-001 | Low | Correctness & logic bugs | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql.Dialect/PostgresDialect.cs:178`, `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql.Dialect/OracleDialect.cs:212` | Both identifier ceilings are enforced as `ident.Length`, i.e. UTF-16 code units, but the server limits they stand in for are **byte** limits: PostgreSQL's `NAMEDATALEN - 1` is 63 bytes and Oracle 12.2's is 128 bytes, both measured in the d… | +| Driver.Sql.Dialect-002 | Low | Code organization & conventions | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql.Dialect/ISqlDialect.cs:29` | The seam models identifier quoting, catalog SQL, row-limit syntax, parameter spelling and command setup — everything that differs per backend *except* the per-command bind-parameter ceiling, which also differs per backend (2100 for `Micros… | +| Driver.Sql.Dialect-003 | Low | Documentation & comments | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql.Dialect/OracleDialect.cs:135` | `OracleDialect.ListSchemasSql` reads `ALL_USERS`, and its remarks justify the divergence from the other two dialects (which list only schemas that own a visible relation) purely from the catalog gate's point of view: "harmless here — the l… | ## Closed findings @@ -104,6 +152,7 @@ Findings with status `Resolved`, `Won't Fix`, or `Deferred`. | Driver.AbCip-008 | High | Resolved | Concurrency & thread safety | `AbCipDriver.cs:144-152`, `AbCipDriver.cs:169-183`, `AbCipDriver.cs:235-281` | | Driver.AbLegacy-001 | High | Resolved | Correctness & logic bugs | `AbLegacyAddress.cs:54`, `AbLegacyDriver.cs:368-374` | | Driver.AbLegacy-006 | High | Resolved | Concurrency & thread safety | `AbLegacyDriver.cs:107-158`, `AbLegacyDriver.cs:162-234`, `LibplctagLegacyTagRuntime.cs` | +| Driver.Calculation-002 | High | Resolved | Correctness & logic bugs | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Calculation/CalculationDriver.cs:374-410` (pre-fix `EvaluateTag`) | | Driver.Cli.Common-001 | High | Resolved | Correctness & logic bugs | `src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Cli.Common/SnapshotFormatter.cs:106-119` | | Driver.Cli.Common-007 | High | Resolved | Correctness & logic bugs | `src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Cli.Common/SnapshotFormatter.cs:129` | | Driver.FOCAS-001 | High | Resolved | Correctness & logic bugs | `FocasDriverFactoryExtensions.cs:54-86`, `FocasDriverFactoryExtensions.cs:132-140` | @@ -111,11 +160,15 @@ Findings with status `Resolved`, `Won't Fix`, or `Deferred`. | Driver.Galaxy-002 | High | Resolved | Correctness & logic bugs | `Browse/DataTypeMap.cs:13`, `Runtime/MxValueDecoder.cs:9` | | Driver.Galaxy-008 | High | Resolved | Error handling & resilience | `GalaxyDriver.cs:264-276`, `Runtime/EventPump.cs:97-103` | | Driver.Galaxy.Browser-001 | High | Resolved | Correctness & logic bugs | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Browser/GalaxyBrowseSession.cs:152` | +| Driver.Historian.Gateway-001 | High | Resolved | Correctness & logic bugs | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway/Mapping/AlarmEventMapper.cs:39` (write side) and `Mapping/EventMapper.cs:62` (read side) | | Driver.Historian.Wonderware-001 | High | Resolved | Correctness and logic bugs | `Backend/SdkAlarmHistorianWriteBackend.cs:68`, `Backend/AahClientManagedAlarmEventWriter.cs:82-103` | | Driver.Historian.Wonderware.Client-001 | High | Resolved | Correctness & logic bugs | `WonderwareHistorianClient.cs:98-113` | | Driver.Historian.Wonderware.Client.Contracts-001 | High | Resolved | Security | `WonderwareHistorianClientOptions.cs:24-30` | | Driver.Modbus-001 | High | Resolved | Concurrency & thread safety | `ModbusDriver.cs:92,99-122` | | Driver.Modbus.Addressing-001 | High | Resolved | Correctness & logic bugs | `ModbusAddressParser.cs:230-235`, `DirectLogicAddress.cs:66-73` | +| Driver.Mqtt-001 | High | Resolved | Correctness & logic bugs | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt/MqttSubscriptionManager.cs:193` (`AttachTo`), `:328` (`SubscribeAsync`'s pending set) | +| Driver.Mqtt-002 | High | Resolved | Concurrency & thread safety | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt/MqttDriver.cs:1000` (`_connection = connection`), `:1297` (`_primaryHost = host`) | +| Driver.Mqtt.Contracts-001 | High | Resolved | Correctness & logic bugs | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Contracts/MqttWriteEncoder.cs:119` | | Driver.OpcUaClient-001 | High | Resolved | Correctness & logic bugs | `OpcUaClientDriver.cs:444`, `:466`, `:517`, `:540`, `:599`, `:610` | | Driver.OpcUaClient-002 | High | Resolved | Error handling & resilience | `OpcUaClientDriver.cs:1330-1359` | | Driver.OpcUaClient-003 | High | Resolved | Correctness & logic bugs | `OpcUaClientDriver.cs:644-711` | @@ -213,6 +266,9 @@ Findings with status `Resolved`, `Won't Fix`, or `Deferred`. | Driver.AbLegacy-012 | Medium | Resolved | Design-document adherence | `PlcFamilies/AbLegacyPlcFamilyProfile.cs:7-54`, `AbLegacyDriver.cs:48-52` | | Driver.AbLegacy-014 | Medium | Resolved | Correctness & logic bugs | `LibplctagLegacyTagRuntime.cs:145` | | Driver.AbLegacy.Cli-001 | Medium | Resolved | Error handling & resilience | `Commands/WriteCommand.cs:46`, `Commands/WriteCommand.cs:62-72` | +| Driver.Calculation-001 | Medium | Resolved | Correctness & logic bugs | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Calculation/CalculationDriver.cs:103-106` (pre-fix), `CalculationEvaluator.cs:47,56-59` (pre-fix) | +| Driver.Calculation-003 | Medium | Resolved | Correctness & logic bugs / Code organization & conventions | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Calculation/CalculationDriverProbe.cs:16-21` (pre-fix) | +| Driver.Calculation-004 | Medium | Resolved | Testing coverage | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Calculation/CalculationDriverProbe.cs`, `CalculationDriver.cs` (`ISkippedTagReporter`/`GetSkippedTags()`), `CalculationTimerScheduler.cs` (`SkippedTickCount`) | | Driver.Cli.Common-002 | Medium | Resolved | Correctness & logic bugs | `src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Cli.Common/SnapshotFormatter.cs:101-122` | | Driver.Cli.Common-003 | Medium | Resolved | Concurrency & thread safety | `src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Cli.Common/DriverCommandBase.cs:51-59` | | Driver.Cli.Common-005 | Medium | Resolved | Testing coverage | `tests/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Cli.Common.Tests/SnapshotFormatterTests.cs:27-37` | @@ -231,6 +287,7 @@ Findings with status `Resolved`, `Won't Fix`, or `Deferred`. | Driver.Galaxy-016 | Medium | Resolved | Performance & resource management | `ZB.MOM.WW.OtOpcUa.Driver.Galaxy.csproj:43-47`, `libs/README.md:32-37` | | Driver.Galaxy.Browser-002 | Medium | Resolved | Concurrency & thread safety | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Browser/GalaxyBrowseSession.cs:167` | | Driver.Galaxy.Contracts-002 | Medium | Resolved | Correctness & logic bugs | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Contracts/GalaxyDriverOptions.cs:91` | +| Driver.Historian.Gateway-003 | Medium | Resolved | Testing coverage | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway/Recorder/GatewayHistorianValueWriter.cs`, `Recorder/HistorizationOutboxEntrySerializer.cs` | | Driver.Historian.Wonderware-002 | Medium | Resolved | Correctness and logic bugs | `Ipc/HistorianFrameHandler.cs:162`, `:181` | | Driver.Historian.Wonderware-003 | Medium | Resolved | Correctness and logic bugs | `Backend/HistorianDataSource.cs:320-323`, `:457-460` | | Driver.Historian.Wonderware-006 | Medium | Resolved | Error handling and resilience | `Ipc/PipeServer.cs:120-128` | @@ -241,6 +298,8 @@ Findings with status `Resolved`, `Won't Fix`, or `Deferred`. | Driver.Historian.Wonderware.Client-009 | Medium | Resolved | Testing coverage | `tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Client.Tests/WonderwareHistorianClientTests.cs` | | Driver.Historian.Wonderware.Client.Contracts-002 | Medium | Deferred | Security | `WonderwareHistorianClientOptions.cs:50-54` | | Driver.Historian.Wonderware.Client.Contracts-003 | Medium | Resolved | Correctness & logic bugs | `WonderwareHistorianClientOptions.cs:26` | +| Driver.MTConnect-001 | Medium | Resolved | Error handling & resilience | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.MTConnect/MTConnectDriver.cs:1932` | +| Driver.MTConnect-002 | Medium | Resolved | Correctness & logic bugs | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.MTConnect/MTConnectDriverProbe.cs:192` | | Driver.Modbus-002 | Medium | Resolved | Correctness & logic bugs | `ModbusDriver.cs:127-186` | | Driver.Modbus-004 | Medium | Resolved | Performance & resource management | `ModbusDriver.cs:1468-1473` | | Driver.Modbus-005 | Medium | Resolved | Correctness & logic bugs | `ModbusDriver.cs:777-798,323-330` | @@ -254,6 +313,11 @@ Findings with status `Resolved`, `Won't Fix`, or `Deferred`. | Driver.Modbus.Cli-002 | Medium | Resolved | Correctness & logic bugs | `src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Cli/Commands/WriteCommand.cs:54-89` | | Driver.Modbus.Contracts-001 | Medium | Resolved | Correctness & logic bugs | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Contracts/ModbusEquipmentTagParser.cs:35` | | Driver.Modbus.Contracts-002 | Medium | Resolved | Correctness & logic bugs | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Contracts/ModbusEquipmentTagParser.cs:36` | +| Driver.Mqtt-003 | Medium | Resolved | Correctness & logic bugs | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt/MqttDriver.cs:376,903`; `MqttConnection.cs:474,486,657,1039,1134,1368,1384`; `Sparkplug/SparkplugPrimaryHost.cs:267` | +| Driver.Mqtt.Browser-001 | Medium | Resolved | Security | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Browser/MqttBrowseSession.cs:898`, `:712` | +| Driver.Mqtt.Contracts-002 | Medium | Resolved | Correctness & logic bugs | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Contracts/MqttWriteEncoder.cs:169`, `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Contracts/Sparkplug/SparkplugTopic.cs:202` | +| Driver.Mqtt.Contracts-003 | Medium | Resolved | Design-document adherence | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Contracts/MqttTagDefinitionFactory.cs:361` | +| Driver.Mqtt.Transport-001 | Medium | Resolved | Security | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Transport/MqttClientOptionsFactory.cs:120-128` (`ConfigureTls`) | | Driver.OpcUaClient-006 | Medium | Resolved | Concurrency & thread safety | `OpcUaClientDriver.cs:1330-1359` | | Driver.OpcUaClient-007 | Medium | Resolved | Concurrency & thread safety | `OpcUaClientDriver.cs:1374`, `:1376-1383`, `:508` | | Driver.OpcUaClient-008 | Medium | Resolved | Error handling & resilience | `OpcUaClientDriver.cs:1092-1099` | @@ -274,6 +338,8 @@ Findings with status `Resolved`, `Won't Fix`, or `Deferred`. | Driver.S7.Cli-002 | Medium | Resolved | Design-document adherence | `src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.S7.Cli/Commands/ReadCommand.cs:22-29`, `Commands/WriteCommand.cs:21-33`, `Commands/SubscribeCommand.cs:18-21`; `docs/Driver.S7.Cli.md:70-73,80-81` | | Driver.S7.Cli-003 | Medium | Resolved | Error handling & resilience | `src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.S7.Cli/Commands/ProbeCommand.cs:38-50` | | Driver.S7.Cli-008 | Medium | Resolved | Error handling & resilience | `src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.S7.Cli/S7CommandBase.cs` | +| Driver.Sql-001 | Medium | Resolved | Correctness & logic bugs | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql/SqlCatalogLoader.cs:139` | +| Driver.Sql-003 | Medium | Resolved | Design-document adherence | `docs/drivers/Sql.md:55`, `docs/drivers/Sql.md:90` | | Driver.TwinCAT-003 | Medium | Resolved | Correctness & logic bugs | `AdsTwinCATClient.cs:264-281`, `283-300` | | Driver.TwinCAT-005 | Medium | Resolved | OtOpcUa conventions | `TwinCATDriver.cs` (whole file), `AdsTwinCATClient.cs` (whole file) | | Driver.TwinCAT-009 | Medium | Resolved | Concurrency & thread safety | `TwinCATDriver.cs:80-99`, `41-72`, `366-388` | @@ -468,6 +534,7 @@ Findings with status `Resolved`, `Won't Fix`, or `Deferred`. | Driver.Galaxy.Browser-004 | Low | Resolved | Testing coverage | `tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Browser.Tests/GalaxyBrowseSessionTests.cs` | | Driver.Galaxy.Contracts-001 | Low | Resolved | Documentation & comments | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Contracts/GalaxyDriverOptions.cs:43` | | Driver.Galaxy.Contracts-003 | Low | Resolved | Code organization & conventions | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Browser/GalaxyDriverBrowser.cs:149` (duplicate) and `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/GalaxyDriver.cs:472` (original) | +| Driver.Historian.Gateway-002 | Low | Resolved | Performance & resource management | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway/GatewayTagProvisioner.cs` | | Driver.Historian.Wonderware-004 | Low | Resolved | Correctness and logic bugs | `Backend/SdkAlarmHistorianWriteBackend.cs:198-201` | | Driver.Historian.Wonderware-005 | Low | Resolved | Concurrency and thread safety | `Backend/HistorianDataSource.cs:124`, `:126-127` | | Driver.Historian.Wonderware-007 | Low | Resolved | Error handling and resilience | `Ipc/PipeServer.cs:70-75` | @@ -484,6 +551,8 @@ Findings with status `Resolved`, `Won't Fix`, or `Deferred`. | Driver.Historian.Wonderware.Client-012 | Low | Resolved | Performance & resource management | `Internal/FrameChannel.cs:38` | | Driver.Historian.Wonderware.Client-013 | Low | Resolved | Testing coverage | `tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Client.Tests/ContractsWireParityTests.cs` | | Driver.Historian.Wonderware.Client.Contracts-004 | Low | Resolved | Documentation & comments | `WonderwareHistorianClientOptions.cs:50-54` | +| Driver.MTConnect-008 | Low | Resolved | Documentation & comments | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.MTConnect/MTConnectDriver.cs:3210` · `docs/drivers/MTConnect.md:169` · `MTConnectDriver.cs:1227`/`:1245`/`:1255` | +| Driver.MTConnect.Contracts-001 | Low | Resolved | Documentation & comments | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.MTConnect.Contracts/MTConnectDataTypeInference.cs:31` · `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.MTConnect.Contracts/MTConnectDriverOptions.cs:86` | | Driver.Modbus-003 | Low | Resolved | Concurrency & thread safety | `ModbusDriver.cs:59,188,241,259,266,726,745,759` | | Driver.Modbus-007 | Low | Resolved | Design-document adherence | `ModbusDriver.cs:1392`, `ModbusDriverOptions.cs:74-80` | | Driver.Modbus-008 | Low | Resolved | Documentation & comments | `ModbusDriver.cs:411-417,700-703,737-744` | @@ -509,6 +578,11 @@ Findings with status `Resolved`, `Won't Fix`, or `Deferred`. | Driver.Modbus.Cli-011 | Low | Resolved | Correctness & logic bugs | `src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Cli/Commands/SubscribeCommand.cs:119-122` | | Driver.Modbus.Contracts-003 | Low | Resolved | Documentation & comments | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Contracts/ModbusDriverOptions.cs:40` | | Driver.Modbus.Contracts-004 | Low | Resolved | Documentation & comments | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Contracts/ModbusDriverOptions.cs:53-60` | +| Driver.Mqtt-004 | Low | Resolved | Error handling & resilience | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt/MqttDriver.cs:375` (`ShutdownAsync`) | +| Driver.Mqtt-005 | Low | Resolved | Code organization & conventions | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt/MqttConnection.cs:1-4` | +| Driver.Mqtt-008 | Low | Resolved | Testing coverage | `tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt.Tests/` (708 tests at `b990adae`) | +| Driver.Mqtt-009 | Low | Resolved | Documentation & comments | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt/MqttConnection.cs:241-248` (type remarks) | +| Driver.Mqtt-010 | Low | Resolved | Documentation & comments | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Mqtt/Sparkplug/SequenceTracker.cs:294` (`Reset`) | | Driver.OpcUaClient-011 | Low | Resolved | Documentation & comments | `OpcUaClientDriver.cs:1007-1015` | | Driver.OpcUaClient-014 | Low | Resolved | Performance & resource management | `OpcUaClientDriver.cs:1138`, `:1314` | | Driver.OpcUaClient-016 | Low | Resolved | Performance & resource management / Error handling & resilience | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient/OpcUaClientDriver.cs:934-948` | @@ -533,6 +607,7 @@ Findings with status `Resolved`, `Won't Fix`, or `Deferred`. | Driver.S7.Contracts-001 | Low | Resolved | Documentation & comments | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.S7.Contracts/S7DriverOptions.cs:107` | | Driver.S7.Contracts-002 | Low | Resolved | Correctness & logic bugs | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.S7.Contracts/S7EquipmentTagParser.cs:38` | | Driver.S7.Contracts-003 | Low | Deferred | Design-document adherence | `docs/v2/driver-specs.md:369` | +| Driver.Sql-007 | Low | Resolved | Code organization & conventions | `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql/ZB.MOM.WW.OtOpcUa.Driver.Sql.csproj:21` | | Driver.TwinCAT-004 | Low | Resolved | Correctness & logic bugs | `TwinCATDataType.cs:24-27` | | Driver.TwinCAT-006 | Low | Resolved | OtOpcUa conventions | `TwinCATDriver.cs:406-411` | | Driver.TwinCAT-014 | Low | Resolved | Design-document adherence | `TwinCATDriverOptions.cs:41-43`, `TwinCATDriverOptions.cs:57-62`, `AdsTwinCATClient.cs:145` |