444 lines
23 KiB
Markdown
444 lines
23 KiB
Markdown
# Cluster 01 — Architecture
|
||
|
||
DOC: gateway.md
|
||
LINES: 737–769
|
||
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: 231–248
|
||
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,20–38 — 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: 898–913
|
||
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: 119–121
|
||
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: 662–663
|
||
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:5–12 — 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: 360–363
|
||
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 291–299 and `gateway.md` lines 147–156.
|
||
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: 249–255
|
||
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: 854–855
|
||
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: 36–48
|
||
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,29–30,35–36,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: 88–94
|
||
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: 162–165
|
||
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:5–7 — `<TargetFramework>net48</TargetFramework>`, `<PlatformTarget>x86</PlatformTarget>`, `<Prefer32Bit>true</Prefer32Bit>`. Matches.
|
||
CODE_AREA: arch.layout
|
||
SEVERITY: low
|
||
PROPOSED_FIX: flag only
|
||
|
||
---
|
||
|
||
DOC: gateway.md
|
||
LINES: 198–210
|
||
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 26–29).
|
||
CODE_AREA: arch.layout
|
||
SEVERITY: low
|
||
PROPOSED_FIX: flag only
|
||
|
||
---
|
||
|
||
DOC: gateway.md
|
||
LINES: 646–650
|
||
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: 420–428
|
||
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: 459–475
|
||
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,28–31,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: 713–719
|
||
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:121–135 — all five subcommands are parsed. Matches.
|
||
CODE_AREA: arch.auth
|
||
SEVERITY: low
|
||
PROPOSED_FIX: flag only
|
||
|
||
---
|
||
|
||
DOC: docs/GatewayProcessDesign.md
|
||
LINES: 408–410
|
||
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:17–18 — `public const string WorkerNonceEnvironmentVariableName = "MXGATEWAY_WORKER_NONCE"`. Matches.
|
||
CODE_AREA: arch.ipc
|
||
SEVERITY: low
|
||
PROPOSED_FIX: flag only
|
||
|
||
---
|
||
|
||
DOC: docs/GatewayProcessDesign.md
|
||
LINES: 223–229
|
||
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:7–8 — enum values `EventSubscriberAlreadyActive` and `EventQueueOverflow` present. Also used at `MxAccessGatewayService.cs:929–930` and `EventStreamService.cs:150,160`.
|
||
CODE_AREA: arch.ipc
|
||
SEVERITY: low
|
||
PROPOSED_FIX: flag only
|
||
|
||
---
|
||
|
||
DOC: docs/GatewayProcessDesign.md
|
||
LINES: 291–299
|
||
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: 527–530
|
||
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: 301–314
|
||
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 898–913.
|
||
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: 1023–1025
|
||
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: 62–93
|
||
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: 110–116
|
||
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: 119–121
|
||
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:63–65,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: 121–122
|
||
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: 864–893
|
||
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:6–7,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: 85–95
|
||
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: 217–225
|
||
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: 129–130
|
||
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: 2–19
|
||
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:26–28 — "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: 100–105
|
||
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: 266–273
|
||
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
|