Adapts the code-review procedure, folder layout, template, and tooling from the sibling mxaccessgw repo to lmxopcua. - REVIEW-PROCESS.md: per-module review workflow — a module is one src/ or tests/ project (ZB.MOM.WW.OtOpcUa. prefix stripped); 10-category checklist; finding IDs/severities/statuses; re-review rules. - code-reviews/_template/findings.md: per-module findings template. - code-reviews/regen-readme.py: generates the cross-module README.md index from the per-module findings.md files; --check gates staleness and consistency. - code-reviews/test_regen_readme.py: dependency-free generator tests. - code-reviews/prompt.md: orchestration prompt for clearing the backlog. - code-reviews/README.md: generated index (no modules reviewed yet). - scripts/check-code-reviews-readme.ps1: CI / pre-commit check wrapper. Adapted to this repo: ZB.MOM.WW.OtOpcUa module naming, OtOpcUa conventions checklist (in-process GalaxyDriver + mxaccessgw, contained-name vs tag-name, ACL at DriverNodeManager), single .NET solution build/test commands, and the lmxopcua design docs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8.7 KiB
Code Review Process
This document describes how to perform a comprehensive, per-module code review of
the lmxopcua codebase (the ZB.MOM.WW.OtOpcUa OPC UA server) and how to track
findings to resolution.
A module is one buildable project under src/ (e.g.
src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy) or one test project under tests/
(e.g. tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Tests). Each module has its
own folder under code-reviews/ containing a single findings.md.
1. Before you start
-
Pick the module to review. Its folder is
code-reviews/<Module>/, where<Module>is the project name with theZB.MOM.WW.OtOpcUa.prefix stripped:src/Server/ZB.MOM.WW.OtOpcUa.Serveris reviewed incode-reviews/Server/.src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy→code-reviews/Driver.Galaxy/.src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions→code-reviews/Core.Abstractions/.tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Tests→code-reviews/Driver.Galaxy.Tests/.
The solution
ZB.MOM.WW.OtOpcUa.slnxenumerates every project;src/is grouped intoCore/,Server/,Drivers/,Client/, andTooling/. -
Identify the design context for the module:
CLAUDE.md— project goal, the data-flow architecture, the contained-name vs tag-name concept, and the Library Preferences / build & runtime constraints.StyleGuide.md— repository code-style conventions.- The relevant docs under
docs/anddocs/v2/— e.g.docs/OpcUaServer.md,docs/AddressSpace.md,docs/ReadWriteOperations.md,docs/security.md,docs/Redundancy.md,docs/ScriptedAlarms.md,docs/AlarmTracking.md,docs/ServiceHosting.md,docs/v2/plan.md,docs/v2/acl-design.md,docs/v2/driver-specs.md,docs/v2/driver-stability.md, thedocs/v2/Galaxy.*.mdset, and the driver notes underdocs/drivers/. - The auto-memory index at
~/.claude/projects/.../memory/MEMORY.mdrecords non-obvious project decisions and is worth a scan before a review.
-
Record the exact commit being reviewed:
git rev-parse --short HEAD. Every review is a snapshot — a finding only means something relative to a known commit. -
Open
code-reviews/<Module>/findings.md(copy it fromcode-reviews/_template/findings.mdif it does not exist yet) and fill in the header table (reviewer, date, commit SHA, status).
2. Review checklist
Work through every category below for the module. A comprehensive review means the checklist is completed even where it produces no findings — record "No issues found" for a category rather than leaving it ambiguous.
- Correctness & logic bugs — off-by-one, null handling, incorrect conditionals, misuse of APIs, broken edge cases, wrong data-type mapping.
- OtOpcUa conventions — the rules in
CLAUDE.mdandStyleGuide.md: Galaxy access flows through the in-processGalaxyDriverover gRPC to the separately installedmxaccessgwgateway — nothing in this repo loads MXAccess COM directly; browse uses contained names and runtime read/write uses tag names (tag_name.AttributeName); authorization decisions happen inDriverNodeManagerat the server layer, never in driver-level code — drivers only reportSecurityClassificationas metadata; .NET 10 / AnyCPU; Serilog with a rolling daily file sink; xUnit + Shouldly for unit tests; the .NET generic host withAddWindowsServicefor the Server and Admin hosts; the OPC Foundation UA .NET Standard stack for OPC UA; generated code is not hand-edited. - Concurrency & thread safety — shared mutable state, race conditions,
correct use of
async/await, locking, disposal races, background-loop and reconnect-supervisor lifetimes. - Error handling & resilience — exception paths, driver/gateway reconnect
handling, transient vs permanent error classification, graceful degradation,
correct OPC UA
StatusCodes, address-space rebuild on redeploy. - Security — OPC UA transport security profiles (
SecurityProfileResolver), LDAP bind authentication and the group→permission mapping (LdapUserAuthenticator), ACL enforcement at theDriverNodeManagerlayer, input validation, SQL injection in theConfigDb/ Galaxy Repository queries, certificate handling, and secret handling (no logging of credentials, LDAP service-account passwords, or API keys). - Performance & resource management —
IDisposabledisposal, gRPC channel / stream / session lifetimes, buffering and back-pressure on event pumps, unnecessary allocations on hot paths, N+1 queries. - Design-document adherence — does the code match
CLAUDE.md, the relevantdocs/anddocs/v2/designs? Flag both code that drifts from the design and design docs that are now stale. - Code organization & conventions — namespace hierarchy, project layout, the
Options pattern, separation of concerns, the capability-interface seams
(
IReadable,IWritable,ISubscribable,IAlarmSource, etc.). - Testing coverage — are the module's behaviours covered? Unit suites are
*.Tests(xUnit + Shouldly); integration suites are*.IntegrationTestsand need their Docker fixture up; DB-backed tests in*.Configuration.Tests,*.Admin.Tests, and*.Server.Testsneed the central SQL Server. Note untested critical paths and missing edge-case tests. - Documentation & comments — XML doc accuracy, misleading or stale comments, undocumented non-obvious behaviour.
3. Recording findings
Add one entry per finding to the ## Findings section of the module's
findings.md, using the entry format in
_template/findings.md.
- Finding ID —
<Module>-NNN, numbered sequentially within the module and never reused (e.g.Driver.Galaxy-001). IDs are permanent even after resolution. - Severity:
- Critical — data loss, security breach, crash/deadlock, or outage.
- High — incorrect behaviour with significant impact; no safe workaround.
- Medium — incorrect or risky behaviour with limited impact or a workaround.
- Low — minor issues, style, maintainability, documentation.
- Category — one of the 10 checklist categories above.
- Location —
file:line(clickable), or a list of locations. - Description — what is wrong and why it matters.
- Recommendation — concrete suggested fix.
After recording findings, update the module header table (status, open-finding count) and regenerate the base README (step 5).
4. Marking an item resolved
Findings are never deleted — they are an audit trail. To close one, change its Status and complete the Resolution field:
Open— newly recorded, not yet addressed.In Progress— a fix is actively being worked on.Resolved— fixed. The Resolution field must state the fixing commit SHA, the date, and a one-line description of the fix.Won't Fix— intentionally not fixed. The Resolution field must justify why.Deferred— valid but postponed. The Resolution field must say what it is waiting on (e.g. a tracked issue or a later milestone).
Resolved, Won't Fix, and Deferred findings are all considered closed.
Open and In Progress are pending and appear in the base README's Pending
Findings table.
5. Updating the base README
code-reviews/README.md holds the single cross-module view (the Module Status
table and the Pending / Closed Findings tables). It is generated from the
per-module findings.md files — do not edit it by hand.
After any review or status change, regenerate it:
python code-reviews/regen-readme.py
regen-readme.py --check exits non-zero if README.md is stale, if a module
header's Open findings count disagrees with its finding statuses, or if a
finding carries an unrecognised Status value. The PowerShell wrapper
scripts/check-code-reviews-readme.ps1 runs that check and is the intended hook
for CI or a pre-commit step. code-reviews/test_regen_readme.py covers the
generator itself (python code-reviews/test_regen_readme.py).
The repo's installed
pythonis the real interpreter; the barepython3alias on this box resolves to the Windows Store stub and fails. Usepython.
The per-module findings.md files are the source of truth; README.md is the
aggregated index and must always agree with them — which the script guarantees.
6. Re-reviewing a module
Re-reviews append to the same findings.md. Update the header to the new commit
and date, continue the finding numbering from the last used ID, and leave prior
findings (including closed ones) in place as history.