Files
lmxopcua/REVIEW-PROCESS.md
Joseph Doherty 76d35d1b9f chore: add per-module code review process and tracking infra
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>
2026-05-22 04:08:47 -04:00

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

  1. Pick the module to review. Its folder is code-reviews/<Module>/, where <Module> is the project name with the ZB.MOM.WW.OtOpcUa. prefix stripped:

    • src/Server/ZB.MOM.WW.OtOpcUa.Server is reviewed in code-reviews/Server/.
    • src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxycode-reviews/Driver.Galaxy/.
    • src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractionscode-reviews/Core.Abstractions/.
    • tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Testscode-reviews/Driver.Galaxy.Tests/.

    The solution ZB.MOM.WW.OtOpcUa.slnx enumerates every project; src/ is grouped into Core/, Server/, Drivers/, Client/, and Tooling/.

  2. 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/ and docs/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, the docs/v2/Galaxy.*.md set, and the driver notes under docs/drivers/.
    • The auto-memory index at ~/.claude/projects/.../memory/MEMORY.md records non-obvious project decisions and is worth a scan before a review.
  3. 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.

  4. Open code-reviews/<Module>/findings.md (copy it from code-reviews/_template/findings.md if 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.

  1. Correctness & logic bugs — off-by-one, null handling, incorrect conditionals, misuse of APIs, broken edge cases, wrong data-type mapping.
  2. OtOpcUa conventions — the rules in CLAUDE.md and StyleGuide.md: Galaxy access flows through the in-process GalaxyDriver over gRPC to the separately installed mxaccessgw gateway — 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 in DriverNodeManager at the server layer, never in driver-level code — drivers only report SecurityClassification as metadata; .NET 10 / AnyCPU; Serilog with a rolling daily file sink; xUnit + Shouldly for unit tests; the .NET generic host with AddWindowsService for the Server and Admin hosts; the OPC Foundation UA .NET Standard stack for OPC UA; generated code is not hand-edited.
  3. Concurrency & thread safety — shared mutable state, race conditions, correct use of async/await, locking, disposal races, background-loop and reconnect-supervisor lifetimes.
  4. 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.
  5. Security — OPC UA transport security profiles (SecurityProfileResolver), LDAP bind authentication and the group→permission mapping (LdapUserAuthenticator), ACL enforcement at the DriverNodeManager layer, input validation, SQL injection in the ConfigDb / Galaxy Repository queries, certificate handling, and secret handling (no logging of credentials, LDAP service-account passwords, or API keys).
  6. Performance & resource managementIDisposable disposal, gRPC channel / stream / session lifetimes, buffering and back-pressure on event pumps, unnecessary allocations on hot paths, N+1 queries.
  7. Design-document adherence — does the code match CLAUDE.md, the relevant docs/ and docs/v2/ designs? Flag both code that drifts from the design and design docs that are now stale.
  8. Code organization & conventions — namespace hierarchy, project layout, the Options pattern, separation of concerns, the capability-interface seams (IReadable, IWritable, ISubscribable, IAlarmSource, etc.).
  9. Testing coverage — are the module's behaviours covered? Unit suites are *.Tests (xUnit + Shouldly); integration suites are *.IntegrationTests and need their Docker fixture up; DB-backed tests in *.Configuration.Tests, *.Admin.Tests, and *.Server.Tests need the central SQL Server. Note untested critical paths and missing edge-case tests.
  10. 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.
  • Locationfile: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 python is the real interpreter; the bare python3 alias on this box resolves to the Windows Store stub and fails. Use python.

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.