Files
scadalink-design/code-reviews/README.md

17 KiB
Raw Blame History

Code Reviews

Comprehensive, per-module code reviews of the ScadaLink codebase. Each module (one buildable project under src/) has its own folder containing a findings.md. This README is the aggregated index — the single place to see all outstanding work.

Generated by regen-readme.py from the per-module findings.md files. Do not edit by hand — edit the findings files and re-run the script.

How it works

  • Reviews are performed one module at a time against a fixed checklist.
  • Every finding is recorded in the module's findings.md with a severity and status.
  • Findings are never deleted — they are closed by changing their status, keeping a full audit trail.
  • This README aggregates every pending finding (Open / In Progress) across all modules.

See REVIEW-PROCESS.md for the full procedure: the review checklist, severity definitions, finding format, and how to mark items resolved.

Layout

code-reviews/
├── README.md            # this file — process overview + pending findings
├── REVIEW-PROCESS.md     # how to perform a review and track findings
├── regen-readme.py       # regenerates this README from the findings files
├── _template/findings.md # copy-this template for a module review
└── <Module>/findings.md  # one folder per src/ project

Baseline review — 2026-05-16

All 19 modules were reviewed at commit 9c60592 (241 findings: 6 Critical, 46 High, 100 Medium, 89 Low). The tables below track what remains open as findings are resolved and re-triaged; findings discovered after the baseline are appended to their module file and counted in Total.

Severity Open findings
Critical 0
High 0
Medium 4
Low 90
Total 94

Module Status

Module Last reviewed Commit Open (C/H/M/L) Open Total
CLI 2026-05-16 9c60592 0/0/0/6 6 13
CentralUI 2026-05-16 9c60592 0/0/2/5 7 19
ClusterInfrastructure 2026-05-16 9c60592 0/0/0/3 3 8
Commons 2026-05-16 9c60592 0/0/0/8 8 12
Communication 2026-05-16 9c60592 0/0/0/3 3 11
ConfigurationDatabase 2026-05-16 9c60592 0/0/0/6 6 11
DataConnectionLayer 2026-05-16 9c60592 0/0/0/2 2 13
DeploymentManager 2026-05-16 9c60592 0/0/0/5 5 14
ExternalSystemGateway 2026-05-16 9c60592 0/0/0/4 4 14
HealthMonitoring 2026-05-16 9c60592 0/0/0/5 5 12
Host 2026-05-16 9c60592 0/0/1/7 8 11
InboundAPI 2026-05-16 9c60592 0/0/1/5 6 13
ManagementService 2026-05-16 9c60592 0/0/0/5 5 13
NotificationService 2026-05-16 9c60592 0/0/0/3 3 13
Security 2026-05-16 9c60592 0/0/0/4 4 11
SiteEventLogging 2026-05-16 9c60592 0/0/0/3 3 11
SiteRuntime 2026-05-16 9c60592 0/0/0/5 5 16
StoreAndForward 2026-05-16 9c60592 0/0/0/7 7 14
TemplateEngine 2026-05-16 9c60592 0/0/0/4 4 14

Pending Findings

Every Open / In Progress finding across all modules, highest severity first. Resolved findings drop off this list but remain recorded in their module's findings.md (see REVIEW-PROCESS.md §4§5). Full detail — description, location, recommendation — lives in the module's findings.md.

Critical (0)

None open.

High (0)

None open.

Medium (4)

ID Module Title
CentralUI-005 CentralUI Session expiry implementation diverges from the documented policy
CentralUI-006 CentralUI Deployment status page polls every 10s despite the documented SignalR-push design
Host-002 Host Akka.Persistence required by REQ-HOST-6 is not configured and not used
InboundAPI-007 InboundAPI Database.Connection() script API from the design doc is not implemented

Low (90)

ID Module Title
CLI-008 CLI --format value is not validated
CLI-009 CLI Exit-code documentation does not match HandleResponse behaviour
CLI-010 CLI debug stream reports Ctrl+C during connect as a connection failure
CLI-011 CLI CancellationTokenSource in debug stream is never disposed
CLI-012 CLI debug stream exit code is unreliable after stream termination
CLI-013 CLI HTTP client, debug stream, and JSON-argument parsing are untested
CentralUI-015 CentralUI DialogService continuations resolve off the render thread
CentralUI-016 CentralUI Pagers render one button per page with no windowing
CentralUI-017 CentralUI /auth/logout POST disables antiforgery, enabling logout CSRF
CentralUI-018 CentralUI Broad catch {} blocks swallow JS interop and storage errors silently
CentralUI-019 CentralUI Sparse unit-test coverage for a large module; critical paths untested
ClusterInfrastructure-005 ClusterInfrastructure No configuration section name constant for the Options pattern binding
ClusterInfrastructure-007 ClusterInfrastructure ClusterOptions lacks XML documentation comments
ClusterInfrastructure-008 ClusterInfrastructure "Phase 0 skeleton" status is undocumented at the module level
Commons-005 Commons OpcUaEndpointConfigSerializer.Deserialize discards malformed legacy input and over-reports IsLegacy
Commons-006 Commons DynamicJsonElement.TryConvert reports success for unconvertible target types
Commons-007 Commons Several Commons types carry non-trivial logic, stretching REQ-COM-6
Commons-008 Commons SetConnectionBindingsCommand uses ValueTuple in a wire message contract
Commons-009 Commons Component-Commons.md is stale relative to the actual file set
Commons-010 Commons Behavior-bearing Commons types have no unit tests
Commons-011 Commons Result<T>.Failure accepts a null error string
Commons-012 Commons ValueFormatter uses current-culture formatting without documenting it
Communication-009 Communication _siteClients field is mutable and reassignable; cache update is not atomic on failure
Communication-010 Communication DebugStreamBridgeActor XML doc incorrectly describes it as a "Persistent actor"
Communication-011 Communication No test coverage for snapshot-timeout cleanup, address-cache failure, or gRPC reconnect leak
ConfigurationDatabase-005 ConfigurationDatabase Audit Id type disagrees with the design doc
ConfigurationDatabase-006 ConfigurationDatabase Site.GrpcNodeAAddress / GrpcNodeBAddress columns are unbounded
ConfigurationDatabase-008 ConfigurationDatabase GetApprovedKeysForMethodAsync CSV parsing silently drops malformed ids
ConfigurationDatabase-009 ConfigurationDatabase Multi-collection eager loads issue cartesian-product queries
ConfigurationDatabase-010 ConfigurationDatabase Several repositories and InstanceLocator lack direct test coverage
ConfigurationDatabase-011 ConfigurationDatabase Inconsistent constructor null-guarding across repositories/services
DataConnectionLayer-008 DataConnectionLayer HandleUnsubscribe is O(n^2) over instances and rechecks _unresolvedTags redundantly
DataConnectionLayer-013 DataConnectionLayer Misleading XML comment: RaiseDisconnected claims thread safety it does not provide
DeploymentManager-009 DeploymentManager Misleading timeout comment on DeleteInstanceAsync
DeploymentManager-010 DeploymentManager SystemArtifactDeploymentRecord does not persist the deployment ID
DeploymentManager-012 DeploymentManager LifecycleCommandTimeout option is dead code
DeploymentManager-013 DeploymentManager SMTP credentials serialized and broadcast to all sites
DeploymentManager-014 DeploymentManager Dead CreateCommand helper in artifact tests
ExternalSystemGateway-011 ExternalSystemGateway Every call performs a full repository scan of all systems and methods
ExternalSystemGateway-012 ExternalSystemGateway Permanent-failure logging requirement is not met; _logger is injected but unused
ExternalSystemGateway-013 ExternalSystemGateway MaxConcurrentConnectionsPerSystem and DefaultHttpTimeout options are defined but never used
ExternalSystemGateway-014 ExternalSystemGateway Cached-call buffering path and DatabaseGateway are untested
HealthMonitoring-004 HealthMonitoring Inconsistent heartbeat interval described across XML docs
HealthMonitoring-006 HealthMonitoring Sequence seeding contradicts the doc's "starting at 1" wording and is untestable
HealthMonitoring-010 HealthMonitoring HealthReportSender silently swallows inner failures with bare catch {}
HealthMonitoring-011 HealthMonitoring AddHealthMonitoringActors is a dead no-op placeholder
HealthMonitoring-012 HealthMonitoring SiteHealthState.LatestReport initialized to null!, misrepresenting the contract
Host-005 Host Blocking sync-over-async (GetAwaiter().GetResult()) inside StartAsync
Host-006 Host HOCON assembled by unescaped string interpolation
Host-007 Host REQ-HOST-4 rule "GrpcPort ≠ RemotingPort" is not enforced
Host-008 Host MachineDataDb is validated and declared but never consumed
Host-009 Host StartAsync reports success before role actors are confirmed running
Host-010 Host No retry/backoff around startup preconditions (DB migration, readiness)
Host-011 Host LoggingOptions.MinimumLevel is dead configuration
InboundAPI-009 InboundAPI Failed compilation is retried on every subsequent request
InboundAPI-010 InboundAPI ParameterValidator ignores extra body fields and cannot validate Object/List element types
InboundAPI-011 InboundAPI Method-existence check leaks to unapproved callers (enumeration oracle)
InboundAPI-012 InboundAPI ParameterDefinition POCO declared in the component project, not Commons
InboundAPI-013 InboundAPI ApiKeyValidationResult.NotFound factory returns HTTP 400, contradicting its name
ManagementService-005 ManagementService ManagementActor declares no supervision strategy
ManagementService-008 ManagementService HandleResolveRoles constructs RoleMapper manually instead of via DI
ManagementService-010 ManagementService ManagementServiceOptions.CommandTimeout is defined but never used
ManagementService-011 ManagementService ResolveRolesCommand dispatch path is stale dead code
ManagementService-012 ManagementService ManagementEnvelope carries a loosely-typed object payload
NotificationService-010 NotificationService DeliverAsync does not disconnect the SMTP client on failure
NotificationService-011 NotificationService SmtpPermanentException declared in the wrong file; module conventions
NotificationService-012 NotificationService Test coverage gaps: OAuth2 delivery path, permanent-classification fallback, token-cache concurrency
Security-008 Security N+1 query loading site-scope rules in RoleMapper
Security-009 Security CancellationToken not honored inside Task.Run LDAP calls
Security-010 Security Design doc contradicts itself on Windows Integrated Authentication
Security-011 Security Missing tests for security-critical paths
SiteEventLogging-006 SiteEventLogging Missing indexes for severity and keyword-search query paths
SiteEventLogging-009 SiteEventLogging XML doc on LogEventAsync claims asynchronous behaviour
SiteEventLogging-011 SiteEventLogging Stale "Phase 4+" placeholder in ServiceCollectionExtensions
SiteRuntime-012 SiteRuntime AttributeAccessor/ScopeAccessors block the script on a synchronous Ask
SiteRuntime-013 SiteRuntime HandleUnsubscribeDebugView does nothing despite documented behaviour
SiteRuntime-014 SiteRuntime Trigger-expression evaluation blocks the coordinator actor thread
SiteRuntime-015 SiteRuntime LoggerFactory created per Instance Actor and never disposed
SiteRuntime-016 SiteRuntime Short-lived execution actors, replication actor, and repositories are untested
StoreAndForward-002 StoreAndForward Messages enqueued with no registered handler are buffered but never deliverable
StoreAndForward-006 StoreAndForward GetParkedMessagesAsync count and page run without a transaction
StoreAndForward-007 StoreAndForward Async work in ParkedMessageHandlerActor uses ContinueWith without scheduler/affinity guarantees
StoreAndForward-008 StoreAndForward A SQLite connection is opened and torn down on every storage call
StoreAndForward-009 StoreAndForward OnActivity event invocation is not thread-safe against concurrent subscribe/unsubscribe
StoreAndForward-011 StoreAndForward StoreAndForwardMessageStatus.InFlight is unused and the doc's "retrying" status is unmodelled
StoreAndForward-012 StoreAndForward StoreAndForwardMessage is a persistence entity but lives in the component, not Commons
TemplateEngine-011 TemplateEngine SortedPropertiesConverterFactory is dead code with a misleading comment
TemplateEngine-012 TemplateEngine DataType enum naming diverges from the design doc
TemplateEngine-013 TemplateEngine ToDictionary(t => t.Id) throws on duplicate IDs; cycle detectors overload Id 0 as a sentinel
TemplateEngine-014 TemplateEngine Template-deletion constraint logic is duplicated and divergent