Files
mxaccessgw/docs/audit/fragments/01-architecture.md
T

444 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Cluster 01 — Architecture
DOC: gateway.md
LINES: 737769
CLAIM: Project layout lists `src/MxGateway.Server`, `src/MxGateway.Worker`, `src/MxGateway.Contracts`, `src/MxGateway.Tests`, `src/MxGateway.Worker.Tests`, `src/MxGateway.IntegrationTests` as suggested path names.
CLAIM_TYPE: path
VERDICT: stale
EVIDENCE: src/ directory listing — actual project directories are `ZB.MOM.WW.MxGateway.Server`, `ZB.MOM.WW.MxGateway.Worker`, `ZB.MOM.WW.MxGateway.Contracts`, `ZB.MOM.WW.MxGateway.Tests`, `ZB.MOM.WW.MxGateway.Worker.Tests`, `ZB.MOM.WW.MxGateway.IntegrationTests`
CODE_AREA: arch.layout
SEVERITY: medium
PROPOSED_FIX: Replace all short project names in the layout block with the fully-qualified names (e.g. `src/ZB.MOM.WW.MxGateway.Server/`, `src/ZB.MOM.WW.MxGateway.Worker/`, etc.).
---
DOC: gateway.md
LINES: 231248
CLAIM: `WorkerEnvelope` has `uint64 correlation_id = 4` and oneof body field numbers: `worker_hello=10, gateway_hello=11, worker_ready=12, command=20, command_reply=21, event=22, heartbeat=23, cancel=24, shutdown=25, fault=26`.
CLAIM_TYPE: rpc/proto
VERDICT: wrong
EVIDENCE: src/ZB.MOM.WW.MxGateway.Contracts/Protos/mxaccess_worker.proto:4,2038 — actual proto has `string correlation_id = 4` (not uint64); body fields are `gateway_hello=10, worker_hello=11, worker_ready=12, worker_command=13, worker_command_reply=14, worker_cancel=15, worker_shutdown=16, worker_shutdown_ack=17, worker_event=18, worker_heartbeat=19, worker_fault=20`; field names also differ (e.g. `command``worker_command`, `event``worker_event`).
CODE_AREA: arch.ipc
SEVERITY: high
PROPOSED_FIX: Replace the WorkerEnvelope protobuf block in gateway.md with the actual proto content from `mxaccess_worker.proto`, including the correct field type for `correlation_id` (string), the correct field numbers, and the correct field names. Also add the missing `WorkerShutdownAck worker_shutdown_ack = 17` entry.
---
DOC: gateway.md
LINES: 898913
CLAIM: Session state machine is `Creating -> StartingWorker -> WaitingForPipe -> InitializingWorker -> Ready -> Closing -> Closed -> Faulted`.
CLAIM_TYPE: behavior-rule
VERDICT: stale
EVIDENCE: src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionWorkerClientFactory.cs:75 — code transitions to `SessionState.Handshaking` between `WaitingForPipe` and `InitializingWorker`; this state also appears in the generated proto enum (`MxaccessGateway.cs:726`, `SESSION_STATE_HANDSHAKING = 4`).
CODE_AREA: arch.session
SEVERITY: medium
PROPOSED_FIX: Add `-> Handshaking` between `WaitingForPipe` and `InitializingWorker` in the state machine diagram, and add a description: "`Handshaking`: pipe is connected and protocol hello is being verified."
---
DOC: gateway.md
LINES: 119121
CLAIM: Blazor dashboard mounts at the host root and renders pages at `/`, `/sessions`, `/workers`, `/events`, `/galaxy`, `/alarms`, `/apikeys`, and `/settings`.
CLAIM_TYPE: path
VERDICT: stale
EVIDENCE: src/ZB.MOM.WW.MxGateway.Server/Dashboard/Components/Pages/BrowsePage.razor:1 — there is also a `/browse` page (`@page "/browse"`) that is not listed. `/login` is also present.
CODE_AREA: arch.layout
SEVERITY: low
PROPOSED_FIX: Add `/browse` (and `/login`) to the list of documented dashboard routes.
---
DOC: gateway.md
LINES: 662663
CLAIM: Rejects valid keys lacking the required `session, invoke, event, metadata, or admin` scope with gRPC `PermissionDenied`.
CLAIM_TYPE: config-key
VERDICT: stale
EVIDENCE: src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/GatewayScopes.cs:512 — actual scopes are `session:open`, `session:close`, `invoke:read`, `invoke:write`, `invoke:secure`, `events:read`, `metadata:read`, `admin`. The simplified short-form names (`session`, `invoke`, `event`) do not match the canonical scope strings.
CODE_AREA: arch.auth
SEVERITY: medium
PROPOSED_FIX: Replace the simplified scope names with the canonical forms: `session:open`, `session:close`, `invoke:read`, `invoke:write`, `invoke:secure`, `events:read`, `metadata:read`, `admin`.
---
DOC: docs/DesignDecisions.md
LINES: 360363
CLAIM: "Dashboard access should require API-key-backed dashboard authentication with `admin` scope when enabled."
CLAIM_TYPE: behavior-rule
VERDICT: wrong
EVIDENCE: src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardAuthenticator.cs:9 — dashboard authentication is LDAP-backed (bind + group-to-role mapping), not API-key-backed. This is also confirmed in `GatewayProcessDesign.md` lines 291299 and `gateway.md` lines 147156.
CODE_AREA: arch.auth
SEVERITY: high
PROPOSED_FIX: Replace "API-key-backed dashboard authentication with `admin` scope" with "LDAP-backed authentication with `GroupToRole` mapping to `Admin` or `Viewer` roles." Keep the note about `AllowAnonymousLocalhost` for local development.
---
DOC: docs/GatewayProcessDesign.md
LINES: 249255
CLAIM: Dashboard suggested routes use a `/dashboard` prefix: `/dashboard`, `/dashboard/sessions`, `/dashboard/sessions/{sessionId}`, `/dashboard/workers`, `/dashboard/events`, `/dashboard/settings`.
CLAIM_TYPE: path
VERDICT: wrong
EVIDENCE: src/ZB.MOM.WW.MxGateway.Server/Dashboard/Components/Pages/ — actual Blazor pages are mounted at `/` (DashboardHome.razor), `/sessions` (SessionsPage.razor), `/sessions/{SessionId}` (SessionDetailsPage.razor), `/workers` (WorkersPage.razor), `/events` (EventsPage.razor), `/settings` (SettingsPage.razor), `/alarms` (AlarmsPage.razor), `/galaxy` (GalaxyPage.razor), `/browse` (BrowsePage.razor), `/apikeys` (ApiKeysPage.razor). None have a `/dashboard` prefix.
CODE_AREA: arch.layout
SEVERITY: high
PROPOSED_FIX: Replace the `/dashboard`-prefixed route table with the actual routes: `/`, `/sessions`, `/sessions/{sessionId}`, `/workers`, `/events`, `/alarms`, `/galaxy`, `/browse`, `/apikeys`, `/settings`.
---
DOC: docs/GatewayProcessDesign.md
LINES: 689
CLAIM: "`Dashboard:AllowAnonymousLocalhost` permits loopback requests to bypass the cookie requirement."
CLAIM_TYPE: config-key
VERDICT: stale
EVIDENCE: src/ZB.MOM.WW.MxGateway.Server/Configuration/DashboardOptions.cs:9 — property is `AllowAnonymousLocalhost` under `DashboardOptions`, which maps to `MxGateway:Dashboard:AllowAnonymousLocalhost`. The shorthand `Dashboard:AllowAnonymousLocalhost` omits the root `MxGateway:` prefix used throughout the project (also confirmed in GatewayProcessDesign.md line 298 which correctly uses `MxGateway:Dashboard:AllowAnonymousLocalhost`).
CODE_AREA: arch.config
SEVERITY: low
PROPOSED_FIX: Standardize to `MxGateway:Dashboard:AllowAnonymousLocalhost` (the form used in GatewayOptions / the configuration section name) everywhere this key is referenced.
---
DOC: docs/GatewayProcessDesign.md
LINES: 854855
CLAIM: Worker `ExecutablePath` default is `src/ZB.MOM.WW.MxGateway.Worker/bin/x86/Release/ZB.MOM.WW.MxGateway.Worker.exe` (forward-slash path shown in JSON block).
CLAIM_TYPE: config-key
VERDICT: accurate
EVIDENCE: src/ZB.MOM.WW.MxGateway.Server/Configuration/WorkerOptions.cs:7 — actual default is `src\ZB.MOM.WW.MxGateway.Worker\bin\x86\Release\ZB.MOM.WW.MxGateway.Worker.exe` (backslashes on Windows). The path and filename match; only the separator style differs between the JSON doc sample and the C# literal.
CODE_AREA: arch.config
SEVERITY: low
PROPOSED_FIX: flag only
---
DOC: docs/DesignDecisions.md
LINES: 36
CLAIM: Interop assembly identity: `ArchestrA.MxAccess, Version=3.2.0.0, PublicKeyToken=23106a86e706d0ae`.
CLAIM_TYPE: version
VERDICT: unverifiable
EVIDENCE: src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessInteropInfo.cs — the file records the assembly path and name (`ArchestrA.MxAccess`) but does not hard-code the version or public key token; `InteropAssemblyVersion` is read dynamically from the loaded assembly at runtime (`typeof(LMXProxyServerClass).Assembly.GetName().Version`). Cannot verify the exact version string without MXAccess installed.
CODE_AREA: arch.ipc
SEVERITY: low
PROPOSED_FIX: flag only
---
DOC: docs/DesignDecisions.md
LINES: 3648
CLAIM: COM class `ArchestrA.MxAccess.LMXProxyServerClass`, CLSID `{C30B52F5-2CB5-4760-AF0A-3A344A7EB5DC}`, ProgID `LMXProxy.LMXProxyServer.1`, version-independent ProgID `LMXProxy.LMXProxyServer`, registered server `C:\Program Files (x86)\ArchestrA\Framework\Bin\LmxProxy.dll`, interop assembly `C:\Program Files (x86)\ArchestrA\Framework\Bin\ArchestrA.MXAccess.dll`.
CLAIM_TYPE: config-key
VERDICT: accurate
EVIDENCE: src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessInteropInfo.cs:14,19,24,2930,3536,41 — `ComClassName = "ArchestrA.MxAccess.LMXProxyServerClass"`, `Clsid = "{C30B52F5-2CB5-4760-AF0A-3A344A7EB5DC}"`, `ProgId = "LMXProxy.LMXProxyServer.1"`, `VersionIndependentProgId = "LMXProxy.LMXProxyServer"`, `RegisteredServerPath = @"C:\Program Files (x86)\ArchestrA\Framework\Bin\LmxProxy.dll"`, `InteropAssemblyPath = @"C:\Program Files (x86)\ArchestrA\Framework\Bin\ArchestrA.MXAccess.dll"`. All match.
CODE_AREA: arch.ipc
SEVERITY: low
PROPOSED_FIX: flag only
---
DOC: docs/DesignDecisions.md
LINES: 55
CLAIM: Worker should reference `ArchestrA.MXAccess.dll` (upper-case MXAccess in filename).
CLAIM_TYPE: path
VERDICT: accurate
EVIDENCE: src/ZB.MOM.WW.MxGateway.Worker/ZB.MOM.WW.MxGateway.Worker.csproj:27 — `<HintPath>C:\Program Files (x86)\ArchestrA\Framework\Bin\ArchestrA.MXAccess.dll</HintPath>`. Matches.
CODE_AREA: arch.layout
SEVERITY: low
PROPOSED_FIX: flag only
---
DOC: gateway.md
LINES: 8894
CLAIM: Gateway runtime is `.NET 10`, `C#`, `x64 preferred`, `ASP.NET Core gRPC server`.
CLAIM_TYPE: version
VERDICT: accurate
EVIDENCE: src/ZB.MOM.WW.MxGateway.Server/ZB.MOM.WW.MxGateway.Server.csproj:4 — `<TargetFramework>net10.0</TargetFramework>`; no explicit `<PlatformTarget>` is set (so the default is AnyCPU/x64-preferred on .NET 10). Grpc.AspNetCore is referenced. Matches.
CODE_AREA: arch.layout
SEVERITY: low
PROPOSED_FIX: flag only
---
DOC: gateway.md
LINES: 162165
CLAIM: Worker runtime is `.NET Framework 4.8`, `C#`, `x86 build by default`.
CLAIM_TYPE: version
VERDICT: accurate
EVIDENCE: src/ZB.MOM.WW.MxGateway.Worker/ZB.MOM.WW.MxGateway.Worker.csproj:57 — `<TargetFramework>net48</TargetFramework>`, `<PlatformTarget>x86</PlatformTarget>`, `<Prefer32Bit>true</Prefer32Bit>`. Matches.
CODE_AREA: arch.layout
SEVERITY: low
PROPOSED_FIX: flag only
---
DOC: gateway.md
LINES: 198210
CLAIM: Pipe name format is `mxaccess-gateway-{gatewayProcessId}-{sessionId}` and framing is `uint32 little-endian payload_length` followed by `payload_length bytes protobuf WorkerEnvelope`.
CLAIM_TYPE: rpc/proto
VERDICT: accurate
EVIDENCE: src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionManager.cs:433 — `string pipeName = $"mxaccess-gateway-{Environment.ProcessId}-{sessionId}"`. Framing confirmed by `WorkerFrameReader.cs` and `WorkerFrameWriter.cs` in `src/ZB.MOM.WW.MxGateway.Server/Workers/`.
CODE_AREA: arch.ipc
SEVERITY: low
PROPOSED_FIX: flag only
---
DOC: gateway.md
LINES: 108
CLAIM: "The gateway must never instantiate or call MXAccess directly."
CLAIM_TYPE: behavior-rule
VERDICT: accurate
EVIDENCE: src/ZB.MOM.WW.MxGateway.Server/ZB.MOM.WW.MxGateway.Server.csproj — no reference to `ArchestrA.MXAccess.dll`. MXAccess COM is only referenced in the Worker project csproj (line 2629).
CODE_AREA: arch.layout
SEVERITY: low
PROPOSED_FIX: flag only
---
DOC: gateway.md
LINES: 646650
CLAIM: Gateway restart does not reattach old workers; `OrphanWorkerCleanupHostedService` runs `OrphanWorkerTerminator` once on startup to kill leftover `ZB.MOM.WW.MxGateway.Worker.exe` processes.
CLAIM_TYPE: behavior-rule
VERDICT: accurate
EVIDENCE: src/ZB.MOM.WW.MxGateway.Server/Workers/OrphanWorkerCleanupHostedService.cs:7 — class exists and references `OrphanWorkerTerminator`. `OrphanWorkerTerminator.cs:19` is present. Worker executable name `ZB.MOM.WW.MxGateway.Worker.exe` confirmed in `IntegrationTestEnvironment.cs:66`.
CODE_AREA: arch.layout
SEVERITY: low
PROPOSED_FIX: flag only
---
DOC: docs/GatewayProcessDesign.md
LINES: 420428
CLAIM: Pipe name format is `mxaccess-gateway-{gatewayProcessId}-{sessionId}` and framing is `uint32 little-endian payload_length` followed by `payload_length bytes protobuf WorkerEnvelope`.
CLAIM_TYPE: rpc/proto
VERDICT: accurate
EVIDENCE: src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionManager.cs:433 — confirmed matching.
CODE_AREA: arch.ipc
SEVERITY: low
PROPOSED_FIX: flag only
---
DOC: docs/GatewayProcessDesign.md
LINES: 459475
CLAIM: `IWorkerClient` has methods `StartAsync`, `InvokeAsync(WorkerCommand, TimeSpan, CancellationToken)`, `ReadEventsAsync(CancellationToken)`, `ShutdownAsync(TimeSpan, CancellationToken)`, `Kill(string)`.
CLAIM_TYPE: rpc/proto
VERDICT: accurate
EVIDENCE: src/ZB.MOM.WW.MxGateway.Server/Workers/IWorkerClient.cs:22,2831,35,40,44 — all five methods are present with matching signatures.
CODE_AREA: arch.ipc
SEVERITY: low
PROPOSED_FIX: flag only
---
DOC: docs/GatewayProcessDesign.md
LINES: 713719
CLAIM: API-key admin CLI subcommands are `init-db`, `create-key`, `list-keys`, `revoke-key`, `rotate-key` on `ZB.MOM.WW.MxGateway.Server apikey`.
CLAIM_TYPE: command
VERDICT: accurate
EVIDENCE: src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/ApiKeyAdminCommandLineParser.cs:121135 — all five subcommands are parsed. Matches.
CODE_AREA: arch.auth
SEVERITY: low
PROPOSED_FIX: flag only
---
DOC: docs/GatewayProcessDesign.md
LINES: 408410
CLAIM: Nonce is passed via `MXGATEWAY_WORKER_NONCE` environment variable so the command line remains safe to log.
CLAIM_TYPE: config-key
VERDICT: accurate
EVIDENCE: src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerProcessLauncher.cs:1718 — `public const string WorkerNonceEnvironmentVariableName = "MXGATEWAY_WORKER_NONCE"`. Matches.
CODE_AREA: arch.ipc
SEVERITY: low
PROPOSED_FIX: flag only
---
DOC: docs/GatewayProcessDesign.md
LINES: 223229
CLAIM: `EventStreamService` rejects a second subscriber with `EventSubscriberAlreadyActive`; faults the session with `EventQueueOverflow` if the queue fills.
CLAIM_TYPE: term
VERDICT: accurate
EVIDENCE: src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionManagerErrorCode.cs:78 — enum values `EventSubscriberAlreadyActive` and `EventQueueOverflow` present. Also used at `MxAccessGatewayService.cs:929930` and `EventStreamService.cs:150,160`.
CODE_AREA: arch.ipc
SEVERITY: low
PROPOSED_FIX: flag only
---
DOC: docs/GatewayProcessDesign.md
LINES: 291299
CLAIM: Dashboard auth uses LDAP bind + role mapping (`MxGateway:Dashboard:GroupToRole`), issues HTTP-only secure cookie, allows `Dashboard:AllowAnonymousLocalhost` to default to `true`.
CLAIM_TYPE: behavior-rule
VERDICT: accurate
EVIDENCE: src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardAuthenticator.cs:9 (LDAP-backed); `DashboardOptions.cs:9` (`AllowAnonymousLocalhost` defaults to `true`). Matches.
CODE_AREA: arch.auth
SEVERITY: low
PROPOSED_FIX: flag only
---
DOC: docs/GatewayProcessDesign.md
LINES: 527530
CLAIM: "During shutdown the worker client treats `WorkerShutdownAck` as the protocol close signal."
CLAIM_TYPE: rpc/proto
VERDICT: accurate
EVIDENCE: src/ZB.MOM.WW.MxGateway.Contracts/Protos/mxaccess_worker.proto:34,80 — `WorkerShutdownAck` is field 17 in the oneof body and its message is defined at line 80.
CODE_AREA: arch.ipc
SEVERITY: low
PROPOSED_FIX: flag only
---
DOC: gateway.md
LINES: 301314
CLAIM: Session state machine (in the "Session Manager" section): `Creating -> StartingWorker -> WaitingForPipe -> InitializingWorker -> Ready -> Closing -> Closed -> Faulted`.
CLAIM_TYPE: behavior-rule
VERDICT: stale
EVIDENCE: src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionWorkerClientFactory.cs:75 — `session.TransitionTo(SessionState.Handshaking)` is called between `WaitingForPipe` and `InitializingWorker`. The `Handshaking` state also exists in the public `SessionState` proto enum (`MxaccessGateway.cs:726`). The state machine in gateway.md at this location (the Gateway Implementation Plan / Session Manager section) is missing the `Handshaking` state exactly as in the earlier reference at lines 898913.
CODE_AREA: arch.session
SEVERITY: medium
PROPOSED_FIX: Add `-> Handshaking` between `WaitingForPipe` and `InitializingWorker` in both state machine diagrams in gateway.md.
---
DOC: gateway.md
LINES: 10231025
CLAIM: "MXAccess COM target is `ArchestrA.MxAccess.LMXProxyServerClass` / `LMXProxy.LMXProxyServer.1` from the installed 32-bit `LmxProxy.dll`."
CLAIM_TYPE: term
VERDICT: accurate
EVIDENCE: src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessInteropInfo.cs:14,41 — `ComClassName = "ArchestrA.MxAccess.LMXProxyServerClass"`, `ProgId = "LMXProxy.LMXProxyServer.1"`, registered server `LmxProxy.dll`. Matches.
CODE_AREA: arch.ipc
SEVERITY: low
PROPOSED_FIX: flag only
---
DOC: docs/GatewayProcessDesign.md
LINES: 6293
CLAIM: High-level component list references namespace `ZB.MOM.WW.MxGateway.Server` with sub-components including `GatewayMetrics` (under `Metrics`) and `HealthChecks` (under `Diagnostics`).
CLAIM_TYPE: term
VERDICT: accurate
EVIDENCE: src/ZB.MOM.WW.MxGateway.Server/Metrics/GatewayMetrics.cs:4 — `namespace ZB.MOM.WW.MxGateway.Server.Metrics`; src/ZB.MOM.WW.MxGateway.Server/Diagnostics/AuthStoreHealthCheck.cs:5 — `namespace ZB.MOM.WW.MxGateway.Server.Diagnostics`. Matches.
CODE_AREA: arch.layout
SEVERITY: low
PROPOSED_FIX: flag only
---
DOC: gateway.md
LINES: 110116
CLAIM: Gateway observability foundation lives in `ZB.MOM.WW.MxGateway.Server.Diagnostics` and `ZB.MOM.WW.MxGateway.Server.Metrics`; `GatewayMetrics` exposes counters/gauges/histograms through .NET `Meter`; `DashboardSnapshotService` projects sessions/workers/metrics into immutable DTOs.
CLAIM_TYPE: term
VERDICT: accurate
EVIDENCE: src/ZB.MOM.WW.MxGateway.Server/Metrics/GatewayMetrics.cs:4; src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardSnapshotService.cs:8. Both namespaces confirmed. Matches.
CODE_AREA: arch.layout
SEVERITY: low
PROPOSED_FIX: flag only
---
DOC: gateway.md
LINES: 119121
CLAIM: SignalR hubs at `/hubs/{snapshot,alarms,events}` accept either the cookie or a 30-minute bearer minted at `/hubs/token`.
CLAIM_TYPE: path
VERDICT: accurate
EVIDENCE: src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardEndpointRouteBuilderExtensions.cs:6365,73 — `MapHub<DashboardSnapshotHub>("/hubs/snapshot")`, `MapHub<AlarmsHub>("/hubs/alarms")`, `MapHub<EventsHub>("/hubs/events")`, `/hubs/token` endpoint mapped at line 73. Matches.
CODE_AREA: arch.layout
SEVERITY: low
PROPOSED_FIX: flag only
---
DOC: gateway.md
LINES: 121122
CLAIM: "`/hubs/events` mirrors per-session `MxEvent` traffic from `EventStreamService` to clients subscribed to `session:{id}`."
CLAIM_TYPE: term
VERDICT: accurate
EVIDENCE: src/ZB.MOM.WW.MxGateway.Server/Dashboard/Hubs/EventsHub.cs:27 — `public static string GroupName(string sessionId) => $"session:{sessionId}"`. Matches.
CODE_AREA: arch.layout
SEVERITY: low
PROPOSED_FIX: flag only
---
DOC: docs/GatewayProcessDesign.md
LINES: 864893
CLAIM: Configuration JSON block shows `MxGateway:Worker:ExecutablePath`, `MxGateway:Sessions:AllowMultipleEventSubscribers`, `MxGateway:Events:QueueCapacity`, `MxGateway:Protocol:WorkerProtocolVersion`, etc.
CLAIM_TYPE: config-key
VERDICT: accurate
EVIDENCE: src/ZB.MOM.WW.MxGateway.Server/Configuration/WorkerOptions.cs:67,13 — `ExecutablePath` and `RequiredArchitecture` match; `SessionOptions.cs` and `EventsOptions` confirm the other keys through bound configuration.
CODE_AREA: arch.config
SEVERITY: low
PROPOSED_FIX: flag only
---
DOC: docs/DesignDecisions.md
LINES: 8595
CLAIM: The single-subscriber rule for `StreamEvents` no longer applies to alarms. `GatewayAlarmMonitor` owns one gateway-managed worker session, fans alarm state to any number of clients through session-less `StreamAlarms`. `AcknowledgeAlarm` is session-less and routes through the monitor.
CLAIM_TYPE: behavior-rule
VERDICT: accurate
EVIDENCE: src/ZB.MOM.WW.MxGateway.Server/Alarms/GatewayAlarmMonitor.cs:17 — class exists. `MxAccessGatewayService.cs:167``StreamAlarms` and `AcknowledgeAlarm` are session-less. Matches.
CODE_AREA: arch.session
SEVERITY: low
PROPOSED_FIX: flag only
---
DOC: docs/DesignDecisions.md
LINES: 217225
CLAIM: Bulk commands are `AddItemBulk`, `AdviseItemBulk`, `RemoveItemBulk`, `UnAdviseItemBulk`, `SubscribeBulk`, `UnsubscribeBulk`, `WriteBulk`, `Write2Bulk`, `WriteSecuredBulk`, `WriteSecured2Bulk`, `ReadBulk`. Each runs single-item MXAccess COM calls sequentially on the STA; per-entry failures are non-throwing.
CLAIM_TYPE: rpc/proto
VERDICT: accurate
EVIDENCE: src/ZB.MOM.WW.MxGateway.Contracts/Protos/mxaccess_gateway.proto — all eleven bulk command kinds are present in the `MxCommandKind` enum and corresponding request/reply messages. Verified by cross-referencing `GatewayGrpcScopeResolver.cs:39` which maps `WriteBulk`, `Write2Bulk`, etc.
CODE_AREA: arch.ipc
SEVERITY: low
PROPOSED_FIX: flag only
---
DOC: gateway.md
LINES: 129130
CLAIM: "`/browse` walks the `IGalaxyHierarchyCache` tree and reads subscribed tag values live through `IDashboardLiveDataService`."
CLAIM_TYPE: term
VERDICT: accurate
EVIDENCE: src/ZB.MOM.WW.MxGateway.Server/Dashboard/IDashboardBrowseService.cs — `IDashboardBrowseService` references `IGalaxyHierarchyCache`. `IDashboardLiveDataService.cs` exists in the same Dashboard directory. `/browse` page confirmed in `BrowsePage.razor:1`.
CODE_AREA: arch.layout
SEVERITY: low
PROPOSED_FIX: flag only
---
DOC: gateway.md
LINES: 219
CLAIM: Gateway preserves MXAccess behavior first, including public MXAccess command semantics, native MXAccess event families, STA/message-pump delivery behavior, HRESULT/status/value marshaling, and per-client isolation. "Installed MXAccess COM component is the compatibility baseline."
CLAIM_TYPE: behavior-rule
VERDICT: accurate
EVIDENCE: src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessInteropInfo.cs (installs/references real COM interop); docs/DesignDecisions.md:2628 — "target the installed MXAccess COM interop surface directly from the x86 worker." Consistent across all three docs.
CODE_AREA: arch.layout
SEVERITY: low
PROPOSED_FIX: flag only
---
DOC: docs/GatewayProcessDesign.md
LINES: 100105
CLAIM: gRPC service surface at this stage is limited to `OpenSession`, `CloseSession`, `Invoke`, `StreamEvents` (with `Session(stream ClientMessage) returns (stream ServerMessage)` deferred).
CLAIM_TYPE: rpc/proto
VERDICT: accurate
EVIDENCE: src/ZB.MOM.WW.MxGateway.Contracts/Protos/mxaccess_gateway.proto — `MxAccessGateway` service defines `OpenSession`, `CloseSession`, `Invoke`, `StreamEvents`, and additional alarm/galaxy RPCs. The bidirectional `Session` RPC is not present in the current proto, consistent with the deferral noted in the doc.
CODE_AREA: arch.ipc
SEVERITY: low
PROPOSED_FIX: flag only
---
DOC: gateway.md
LINES: 266273
CLAIM: Public gRPC service is `MxAccessGateway` with `OpenSession`, `CloseSession`, `Invoke`, `StreamEvents`, and deferred bidirectional `Session` RPC.
CLAIM_TYPE: rpc/proto
VERDICT: accurate
EVIDENCE: src/ZB.MOM.WW.MxGateway.Contracts/Protos/mxaccess_gateway.proto — confirmed. The `Session` bidirectional RPC is absent as expected for deferred rollout.
CODE_AREA: arch.ipc
SEVERITY: low
PROPOSED_FIX: flag only