Files
mxaccessgw/code-reviews/Contracts/findings.md
T
Joseph Doherty ae164ea34f Add per-module code review tree under code-reviews/
Set up the code review process scaffolding adapted to mxaccessgw and
record a full per-module review of every src/MxGateway.* project at
commit 6c64030.

- code-reviews/_template/findings.md: per-module findings template
- code-reviews/regen-readme.py: generates README.md from findings.md
  files; --check fails if stale
- code-reviews/<Module>/findings.md: reviews for Contracts, Server,
  Worker, Tests, Worker.Tests, IntegrationTests (74 findings:
  1 Critical, 10 High, 23 Medium, 40 Low; all Open)
- code-reviews/README.md: generated cross-module index
- REVIEW-PROCESS.md: review process document

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 16:28:50 -04:00

9.0 KiB

Code Review — Contracts

Field Value
Module src/MxGateway.Contracts
Reviewer Claude Code
Review date 2026-05-18
Commit reviewed 6c64030
Status Reviewed
Open findings 8

Checklist coverage

# Category Result
1 Correctness & logic bugs No functional bugs; one missing reply-payload case for the by-name ack command and an int32-typed success flag that reads like a bool (Contracts-002, Contracts-006).
2 mxaccessgw conventions Additive-only evolution honored (no renumbered/removed tags), MXAccess-aligned naming consistent, generated code untouched; no reserved statements declared as a guardrail (Contracts-005).
3 Concurrency & thread safety N/A — pure contract definitions plus a static const class with no shared mutable state.
4 Error handling & resilience HRESULT / MxStatusProxy / ProtocolStatus carriers are complete; the worker-side by-name alarm ack has no dedicated reply payload (Contracts-002).
5 Security Credential-sensitive fields are clearly commented; no secrets forced into loggable shapes. No issues found.
6 Performance & resource management DiscoverHierarchy is paged; alarm-snapshot streams are server-streamed; no bloat issues. No issues found.
7 Design-document adherence .proto files match design intent but docs/Grpc.md is stale (Contracts-001); worker vs public alarm-status shapes unreconciled in docs (Contracts-008).
8 Code organization & conventions Package/file layout correct; mxaccess_worker.proto Protobuf item missing ProtoRoot (Contracts-003); stale class summary (Contracts-004).
9 Testing coverage Gateway/worker/alarm round-trips covered; Galaxy Repository protos and raw MxArray paths untested (Contracts-007).
10 Documentation & comments Proto comments accurate and domain-rich; one stale class summary (Contracts-004).

Findings

Contracts-001

Field Value
Severity Low
Category Design-document adherence
Location docs/Grpc.md:13 (and :3, :32, :39)
Status Open

Description: mxaccess_gateway.proto now declares six RPCs on MxAccessGateway (OpenSession, CloseSession, Invoke, StreamEvents, AcknowledgeAlarm, QueryActiveAlarms). docs/Grpc.md still describes "the four MxAccessGateway RPCs" in its type table and omits AcknowledgeAlarm/QueryActiveAlarms from the Validation Rules table. CLAUDE.md requires docs to change in the same commit as the contract; the alarm RPC commits left this doc stale and misleading about the public surface.

Recommendation: Update docs/Grpc.md to enumerate all six RPCs and add AcknowledgeAlarm/QueryActiveAlarms to the type/handler and validation tables, or explicitly cross-reference AlarmClientDiscovery.md.

Resolution: (open)

Contracts-002

Field Value
Severity Medium
Category Error handling & resilience
Location src/MxGateway.Contracts/Protos/mxaccess_gateway.proto:384-385, :95
Status Open

Description: MxCommandKind includes MX_COMMAND_KIND_ACKNOWLEDGE_ALARM_BY_NAME = 29 and MxCommand.payload carries AcknowledgeAlarmByNameCommand acknowledge_alarm_by_name_command = 38, but MxCommandReply.payload has only acknowledge_alarm = 34 and query_active_alarms = 35 — there is no by-name reply case. The by-name ack must reuse AcknowledgeAlarmReplyPayload or rely on the top-level hresult. The command/reply payload asymmetry is undocumented and easy to dispatch incorrectly.

Recommendation: Either add an explicit comment to MxCommandReply stating that by-name ack reuses the acknowledge_alarm payload case, or add a dedicated payload case for symmetry, and document the chosen contract in docs/Contracts.md / AlarmClientDiscovery.md.

Resolution: (open)

Contracts-003

Field Value
Severity Low
Category Code organization & conventions
Location src/MxGateway.Contracts/MxGateway.Contracts.csproj:10
Status Open

Description: The <Protobuf> item for mxaccess_worker.proto omits ProtoRoot="Protos", while the items for mxaccess_gateway.proto (line 9) and galaxy_repository.proto (line 11) both set it. mxaccess_worker.proto does import "mxaccess_gateway.proto", which resolves only because Grpc.Tools adds the importing file's own directory to the proto path. The inconsistency is fragile — tooling changes to ProtoRoot handling could break import resolution.

Recommendation: Add ProtoRoot="Protos" to the mxaccess_worker.proto <Protobuf> item so all three entries are consistent.

Resolution: (open)

Contracts-004

Field Value
Severity Low
Category Documentation & comments
Location src/MxGateway.Contracts/GatewayContractInfo.cs:3-6
Status Open

Description: The XML summary says the class exposes version metadata "before generated protobuf contracts are introduced." Generated protobuf contracts have long been introduced and are consumed across the solution. The comment is stale; the class now holds the authoritative GatewayProtocolVersion/WorkerProtocolVersion advertised in OpenSessionReply and used to validate WorkerEnvelope framing.

Recommendation: Reword the summary to describe the current purpose — version constants advertised in OpenSessionReply and used to validate WorkerEnvelope protocol framing.

Resolution: (open)

Contracts-005

Field Value
Severity Low
Category mxaccessgw conventions
Location src/MxGateway.Contracts/Protos/mxaccess_gateway.proto, src/MxGateway.Contracts/Protos/mxaccess_worker.proto
Status Open

Description: The ProtobufStyleGuide mandates reserving removed field numbers / enum values. Evolution to date has been purely additive, so this is not a current violation — but none of the .proto files contain any reserved declarations, leaving no in-file guardrail for the first removal. This is a latent maintainability gap.

Recommendation: When any field or enum value is eventually removed, add a reserved range/name in the same change. Consider a short comment block in each message documenting the policy so future editors apply reserved rather than reusing tags.

Resolution: (open)

Contracts-006

Field Value
Severity Low
Category Correctness & logic bugs
Location src/MxGateway.Contracts/Protos/mxaccess_gateway.proto:647
Status Open

Description: MxStatusProxy.success is declared int32 success = 1 with no comment. The name reads like a boolean flag but the type is a 32-bit integer (mirroring MXAccess MXSTATUS_PROXY, which stores a numeric success/HResult-like value). Without a comment a client author can reasonably misinterpret the field (treat non-1 as failure, or expect only 0/1).

Recommendation: Add a comment clarifying the semantic — what range of values it carries and how 0 vs non-zero map to MXAccess status — per the style guide rule to comment fields carrying raw MXAccess status detail.

Resolution: (open)

Contracts-007

Field Value
Severity Low
Category Testing coverage
Location src/MxGateway.Tests/Contracts/ProtobufContractRoundTripTests.cs
Status Open

Description: ProtobufContractRoundTripTests covers gateway command/reply/event, alarm transition, alarm ack request/reply, active-alarm snapshot, and the worker envelope. It has no coverage for: (a) any galaxy_repository.proto message (DiscoverHierarchy*, GalaxyObject, GalaxyAttribute, DeployEvent, the root oneof, wrapper-typed fields); (b) BulkSubscribeReply/SubscribeResult and the bulk command kinds; (c) MxValue/MxArray raw_value/RawArray (bytes) paths and the WorkerFault/WorkerHeartbeat IPC bodies.

Recommendation: Add round-trip tests for the Galaxy Repository messages (including the root oneof and proto wrapper fields), the bulk-subscribe reply, and the remaining WorkerEnvelope body cases.

Resolution: (open)

Contracts-008

Field Value
Severity Low
Category Design-document adherence
Location src/MxGateway.Contracts/Protos/mxaccess_gateway.proto:451-459, :627-636
Status Open

Description: The worker-side AcknowledgeAlarmReplyPayload carries the alarm-ack outcome as int32 native_status, while the public AcknowledgeAlarmReply carries it as MxStatusProxy status plus optional int32 hresult. The comment explains the worker echoes native_status into AcknowledgeAlarmReply.hresult, but the two outcome shapes (raw int32 vs structured MxStatusProxy) are not reconciled in docs/Contracts.md / AlarmClientDiscovery.md. A reader cannot tell whether MxStatusProxy status is always populated or only on COM-layer failure.

Recommendation: Document in docs/Contracts.md (or AlarmClientDiscovery.md) how the worker native_status maps onto the public reply's status/hresult pair so client authors know which field is authoritative.

Resolution: (open)