Files
scadalink-design/code-reviews
Joseph Doherty 89636e2bbf docs(code-reviews): re-review batch 2 at 39d737e — ConfigurationDatabase, DataConnectionLayer, DeploymentManager, ExternalSystemGateway, HealthMonitoring
17 new findings: ConfigurationDatabase-012..014, DataConnectionLayer-014..017, DeploymentManager-015..017, ExternalSystemGateway-015..017, HealthMonitoring-013..016.
2026-05-17 00:45:10 -04:00
..

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 5
Medium 12
Low 17
Total 34

Module Status

Module Last reviewed Commit Open (C/H/M/L) Open Total
CLI 2026-05-16 9c60592 0/0/1/2 3 16
CentralUI 2026-05-16 9c60592 0/1/2/3 6 25
ClusterInfrastructure 2026-05-16 9c60592 0/0/1/1 2 10
Commons 2026-05-16 9c60592 0/0/0/2 2 14
Communication 2026-05-16 9c60592 0/1/1/2 4 15
ConfigurationDatabase 2026-05-16 9c60592 0/0/2/1 3 14
DataConnectionLayer 2026-05-16 9c60592 0/1/2/1 4 17
DeploymentManager 2026-05-16 9c60592 0/1/1/1 3 17
ExternalSystemGateway 2026-05-16 9c60592 0/1/1/1 3 17
HealthMonitoring 2026-05-16 9c60592 0/0/1/3 4 16
Host 2026-05-16 9c60592 0/0/0/0 0 11
InboundAPI 2026-05-16 9c60592 0/0/0/0 0 13
ManagementService 2026-05-16 9c60592 0/0/0/0 0 13
NotificationService 2026-05-16 9c60592 0/0/0/0 0 13
Security 2026-05-16 9c60592 0/0/0/0 0 11
SiteEventLogging 2026-05-16 9c60592 0/0/0/0 0 11
SiteRuntime 2026-05-16 9c60592 0/0/0/0 0 16
StoreAndForward 2026-05-16 9c60592 0/0/0/0 0 14
TemplateEngine 2026-05-16 9c60592 0/0/0/0 0 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 (5)

ID Module Title
CentralUI-020 CentralUI Idle-session redirect never fires: SessionExpiry polls a frozen auth-state snapshot
Communication-012 Communication gRPC client factory ignores the endpoint on a cache hit, breaking NodeA→NodeB stream failover
DataConnectionLayer-014 DataConnectionLayer DCL-012 security warning is never logged in production: RealOpcUaClient is created without a logger
DeploymentManager-015 DeploymentManager Site-query reconciliation marks a deployment Success but skips instance-state and snapshot updates
ExternalSystemGateway-015 ExternalSystemGateway MaxRetries == 0 is buffered as "retry forever", contradicting the ExternalSystemGateway-004 "never retry" claim

Medium (12)

ID Module Title
CLI-014 CLI update commands require "core" fields, making partial updates impossible
CentralUI-021 CentralUI DebugView stream callback mutates Dictionary off the render thread
CentralUI-022 CentralUI Deployments push handler fires InvokeAsync with no disposal guard
ClusterInfrastructure-009 ClusterInfrastructure DownIfAlone is an inert configuration knob — never consumed by the HOCON builder
Communication-013 Communication Site gRPC address changes are never applied; RemoveSiteAsync has no production caller
ConfigurationDatabase-012 ConfigurationDatabase Inbound-API ApiKey.KeyValue bearer credential stored in plaintext
ConfigurationDatabase-013 ConfigurationDatabase Secret-column encryption silently falls back to an ephemeral (throwaway) key
DataConnectionLayer-015 DataConnectionLayer Initial-connect failures never trigger failover; an unreachable primary at startup never tries the backup
DataConnectionLayer-016 DataConnectionLayer HandleSubscribeCompleted reports SubscribeTagsResponse success even on a connection-level subscribe failure
DeploymentManager-016 DeploymentManager Reconciled prior record keeps its stale RevisionHash
ExternalSystemGateway-016 ExternalSystemGateway ConfigureHttpClientDefaults applies the ESG connection cap to every HttpClient in the host process
HealthMonitoring-015 HealthMonitoring Heartbeat-registered site is left with a year-0001 LastReportReceivedAt

Low (17)

ID Module Title
CLI-015 CLI Component-CLI.md command surface has drifted again in two places
CLI-016 CLI WriteAsTable derives columns from the first array element only
CentralUI-023 CentralUI Residual bare catch {} blocks swallow JS interop errors
CentralUI-024 CentralUI Claim lookups use magic strings instead of JwtTokenService constants
CentralUI-025 CentralUI SessionExpiry polling/redirect path has no test coverage
ClusterInfrastructure-010 ClusterInfrastructure Validator does not enforce DownIfAlone = true despite the design doc requiring it
Commons-013 Commons DynamicJsonElement.TryGetIndex rejects non-int index values
Commons-014 Commons OpcUaEndpointConfigSerializer.Deserialize can mislabel a corrupt typed row as Legacy
Communication-014 Communication Untrusted gRPC correlation_id flows directly into an Akka actor name
Communication-015 Communication No test exercises the real gRPC client factory across a node flip
ConfigurationDatabase-014 ConfigurationDatabase Redundant, inconsistent cast on one HasConversion call
DataConnectionLayer-017 DataConnectionLayer WriteBatchAsync aborts the whole batch on a mid-batch disconnect
DeploymentManager-017 DeploymentManager GetDeploymentStatusAsync XML doc describes behaviour it does not implement
ExternalSystemGateway-017 ExternalSystemGateway BuildUrl appends a bare trailing ? when a GET method's parameters are all null
HealthMonitoring-013 HealthMonitoring Offline-check interval comment claims "shorter timeout" but only ever uses OfflineTimeout
HealthMonitoring-014 HealthMonitoring HealthMonitoringOptions intervals are unvalidated; a zero/negative value crashes the hosted service
HealthMonitoring-016 HealthMonitoring SiteHealthCollector.CollectReport reads DateTimeOffset.UtcNow directly instead of an injected TimeProvider