Files
scadaproj/components/health/current-state/mxaccessgw/CURRENT-STATE.md
T
Joseph Doherty 9cbe65c844 docs(health): re-verify per-app probe coverage against the SPEC; refresh GAPS and current-state (scadaproj#11)
Audited the registration and mapping code of each app at its origin default branch: OtOpcUa
c904472a, MxAccessGateway de86f8b8, ScadaBridge c7d868c5, HistorianGateway 4d6a9ad (all on Health
0.3.0, all MapZbHealth with default paths: /healthz runs nothing, /health/ready and /health/active
by tag). GAPS.md now carries the verified per-endpoint coverage matrix and a SPEC-by-app table;
each current-state doc lists exactly what each endpoint runs, and HistorianGateway gets its first
current-state doc.

Recorded: mxaccessgw#206 (worker-executable + galaxy-sql readiness checks, on /health/ready) is
merged; historiangw#87 (session-pool check latches 503 until restart) is still open at 4d6a9ad.
Deferred P2 downstream probes are now per-app; ScadaBridge IActiveNodeGate unification stays
deferred (shared rule already used, only the interface is local).

Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
2026-11-09 14:00:44 -05:00

4.4 KiB

Health — current state: MxAccessGateway

Verified 2026-11-09 at mxaccessgw@de86f8b8 (origin/main) for scadaproj#11. Read-only git grep / git show against the origin default branch; all paths relative to the repo root (~/Desktop/MxAccessGateway). The pre-adoption state (verified 2026-06-01: a hardcoded /health/live MapGet, a dead AddHealthChecks(), no probes) is gone; see git history of this file.

  • Package: ZB.MOM.WW.Health 0.3.0, core only (src/ZB.MOM.WW.MxGateway.Server/ZB.MOM.WW.MxGateway.Server.csproj:20). No .Akka, no .EntityFrameworkCore — the gateway has no Akka cluster and no EF context.
  • Registration: builder.Services.AddGatewayHealthChecks() (GatewayApplication.cs:118) → src/ZB.MOM.WW.MxGateway.Server/Diagnostics/GatewayHealthCheckExtensions.cs:19-41.
  • Mapping: endpoints.MapZbHealth() with default paths/writer (GatewayApplication.cs:346), anonymous unconditionally (the Overview dashboard polls /health/active without credentials).

Per-endpoint contents

Endpoint Checks run Can return 503 when
/healthz (live) none (_ => false) never (process up)
/health/ready auth-store, worker-executable, galaxy-sql auth SQLite unreachable; worker exe missing; Galaxy SQL unreachable or > 5 s
/health/active mxaccess-sessions every open session is Faulted (zero sessions = Healthy)

No check is tagged live (asserted by GatewayHealthCheckRegistrationTests).

Checks

All registered with AddTypeActivatedCheck, failureStatus: null (the check's own status is used). Files under src/ZB.MOM.WW.MxGateway.Server/Diagnostics/.

Name Class Tag Probes Failure
auth-store AuthStoreHealthCheck ready Opens the API-key SQLite store via AuthSqliteConnectionFactory, runs SELECT 1 Unhealthy
worker-executable WorkerExecutableHealthCheck ready File.Exists(Path.GetFullPath(MxGateway:Worker:ExecutablePath)) — same resolution as WorkerProcessLauncher.ResolveExecutablePath Unhealthy (missing or invalid path)
galaxy-sql GalaxySqlHealthCheck ready IGalaxyRepository.TestConnectionAsync bounded by a 5 s TimeProvider timeout Unhealthy (false, throw, or timeout)
mxaccess-sessions SessionHealthCheck active Buckets ISessionRegistry.Snapshot() by state; data = total/ready/faulted/starting/closing Healthy if 0 faulted (incl. 0 sessions); Degraded if some faulted; Unhealthy if all usable sessions faulted

worker-executable and galaxy-sql are new on main 8c21678c (mxaccessgw#206, closed 2026-11-09). They check that the worker binary exists and that Galaxy SQL answers; neither checks a running worker or the named-pipe IPC (workers are per-session and only exist while a client holds a session). No LDAP check was added (#206 comment: deliberately out of scope).

galaxy-sql is unconditional: AddZbGalaxyRepository is always registered (GatewayApplication.cs:167), so a gateway whose Galaxy SQL is down drops out of readiness even though its MXAccess data path does not use SQL. That is the #206 design ("must take the gateway out of rotation"), not an accident.

Active-node gating

None. The gateway is a singleton per host (no cluster), registers no IActiveNodeGate, and uses no RequireActiveNode(). The active tier is used for a session-health signal instead of an active/standby signal, so every gateway answers 200 on /health/active unless all its sessions are faulted.

Other endpoints

MapZbMetrics() (:347, anonymous by default, see MetricsOptions), MapZbGalaxyRepository() (:359), dashboard routes. No bespoke health endpoint remains.

vs SPEC

SPEC Status Note
§1 three tiers via MapZbHealth, canonical tags ✅ default paths
§1 nothing on live ✅ test-asserted
§2.1 DatabaseHealthCheck<T> n/a no EF; custom SQLite + Galaxy SQL checks
§2.3 active tier = oldest Up member 🟡 deviation no cluster; active tier carries mxaccess-sessions (deliberate, documented in SessionHealthCheck)
§2.4 GrpcDependencyHealthCheck for the worker ⛔ not used worker IPC is named pipes, not gRPC; worker-executable is a presence proxy (see GAPS P2)
§3 canonical JSON writer ✅ MapZbHealth default
§4 IActiveNodeGate n/a no active/standby