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

23 KiB
Raw Blame History

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. commandworker_command, eventworker_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:167StreamAlarms 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