Files
mxaccessgw/docs/GatewayConfiguration.md
T
Joseph Doherty e541339c07 docs(audit): apply per-cluster judgment fixes across living docs
Resolve audit findings: correct WorkerEnvelope proto/route/metric/session
facts; rewrite auth (ZB.MOM.WW.Auth migration), dashboard (ZB.MOM.WW.Theme),
and StyleGuide (foreign-project copy-paste); document alarm subsystem, Ldap
options, and gateway alarm broker; fix client CLI flags and package paths.
2026-06-03 16:01:28 -04:00

28 KiB
Raw Blame History

Gateway Configuration

This document describes every option bound under the MxGateway configuration section by GatewayOptions.

The gateway binds configuration at startup and validates it with GatewayOptionsValidator. Startup fails before the server listens when required paths, timeouts, queue sizes, enum values, or protocol values are invalid.

Configuration Shape

{
  "MxGateway": {
    "Authentication": {
      "Mode": "ApiKey",
      "SqlitePath": "C:\\ProgramData\\MxGateway\\gateway-auth.db",
      "PepperSecretName": "MxGateway:ApiKeyPepper",
      "RunMigrationsOnStartup": true
    },
    "Ldap": {
      "Enabled": true,
      "Server": "localhost",
      "Port": 3893,
      "Transport": "None",
      "AllowInsecure": true,
      "SearchBase": "dc=zb,dc=local",
      "ServiceAccountDn": "cn=serviceaccount,dc=zb,dc=local",
      "ServiceAccountPassword": "serviceaccount123",
      "UserNameAttribute": "cn",
      "DisplayNameAttribute": "cn",
      "GroupAttribute": "memberOf"
    },
    "Worker": {
      "ExecutablePath": "src\\ZB.MOM.WW.MxGateway.Worker\\bin\\x86\\Release\\ZB.MOM.WW.MxGateway.Worker.exe",
      "WorkingDirectory": null,
      "RequiredArchitecture": "X86",
      "StartupTimeoutSeconds": 30,
      "StartupProbeRetryAttempts": 3,
      "StartupProbeRetryDelayMilliseconds": 250,
      "PipeConnectAttemptTimeoutMilliseconds": 2000,
      "ShutdownTimeoutSeconds": 10,
      "HeartbeatIntervalSeconds": 5,
      "HeartbeatGraceSeconds": 15,
      "MaxMessageBytes": 16777216
    },
    "Sessions": {
      "DefaultCommandTimeoutSeconds": 30,
      "MaxSessions": 64,
      "MaxPendingCommandsPerSession": 128,
      "DefaultLeaseSeconds": 1800,
      "LeaseSweepIntervalSeconds": 30,
      "AllowMultipleEventSubscribers": false
    },
    "Events": {
      "QueueCapacity": 10000,
      "BackpressurePolicy": "FailFast"
    },
    "Dashboard": {
      "Enabled": true,
      "AllowAnonymousLocalhost": true,
      "RequireHttpsCookie": true,
      "SnapshotIntervalMilliseconds": 1000,
      "RecentFaultLimit": 100,
      "RecentSessionLimit": 200,
      "ShowTagValues": false,
      "GroupToRole": {
        "GwAdmin": "Administrator",
        "GwReader": "Viewer"
      }
    },
    "Protocol": {
      "WorkerProtocolVersion": 1,
      "MaxGrpcMessageBytes": 16777216
    },
    "Galaxy": {
      "ConnectionString": "Server=localhost;Database=ZB;Integrated Security=True;TrustServerCertificate=True;Encrypt=False;",
      "CommandTimeoutSeconds": 60,
      "DashboardRefreshIntervalSeconds": 30,
      "PersistSnapshot": true,
      "SnapshotCachePath": "C:\\ProgramData\\MxGateway\\galaxy-snapshot.json"
    },
    "Alarms": {
      "Enabled": false,
      "SubscriptionExpression": "",
      "DefaultArea": "",
      "ReconcileIntervalSeconds": 30
    }
  }
}

Environment variables use the normal .NET double-underscore form. For example, MxGateway__Sessions__MaxSessions=20 overrides MxGateway:Sessions:MaxSessions.

Authentication Options

Option Default Description
MxGateway:Authentication:Mode ApiKey Selects public gRPC authentication. Supported values are ApiKey and Disabled. Disabled bypasses API-key verification and is for local development only.
MxGateway:Authentication:SqlitePath C:\ProgramData\MxGateway\gateway-auth.db SQLite database path for API-key records and audit rows when API-key authentication is enabled.
MxGateway:Authentication:PepperSecretName MxGateway:ApiKeyPepper Configuration key used to read the HMAC pepper for API-key secret hashing. The dashboard effective configuration redacts this value.
MxGateway:Authentication:RunMigrationsOnStartup true Runs SQLite auth schema migrations at gateway startup when API-key authentication is enabled.

When Mode is ApiKey, SqlitePath and PepperSecretName must be present. SqlitePath must be a valid filesystem path.

Ldap Options

The MxGateway:Ldap section configures the dashboard's LDAP login (the gRPC API uses API keys, not LDAP — see Authentication). The same section is bound twice: the runtime bind/search is performed by the shared ZB.MOM.WW.Auth.Ldap provider wired up by AddZbLdapAuth, while the gateway's own LdapOptions shadow exists only for startup validation, the redacted effective-config display, and the dev/default values. The two stay field-compatible so the one section binds onto both. The gateway ships dev-friendly defaults (plaintext localhost); the shared provider's own defaults are secure-by-default.

Option Default Description
MxGateway:Ldap:Enabled true Enables LDAP-backed dashboard login. When false, the rest of the section is not validated and LDAP login is not wired up.
MxGateway:Ldap:Server localhost LDAP server host. Required when Enabled.
MxGateway:Ldap:Port 3893 LDAP server port. Must be a valid port (165535).
MxGateway:Ldap:Transport None Transport/TLS mode. One of None (plaintext), StartTls (upgrade a plaintext connection to TLS), or Ldaps (TLS from connect). Replaces the former boolean UseTls.
MxGateway:Ldap:AllowInsecure true Allows plaintext LDAP connections. Must be true when Transport is None; setting Transport=None with AllowInsecure=false fails validation.
MxGateway:Ldap:SearchBase dc=zb,dc=local Search base distinguished name for user lookup. Required when Enabled.
MxGateway:Ldap:ServiceAccountDn cn=serviceaccount,dc=zb,dc=local Service account DN used to bind before searching for the logging-in user. Required when Enabled. Redacted in the effective-config display.
MxGateway:Ldap:ServiceAccountPassword serviceaccount123 Service account bind password. Required when Enabled. Never logged; redacted in the effective-config display.
MxGateway:Ldap:UserNameAttribute cn Attribute matched against the login user name (the dev GLAuth directory keys users by cn, not uid). Required when Enabled.
MxGateway:Ldap:DisplayNameAttribute cn Attribute read for the user's display name. Required when Enabled.
MxGateway:Ldap:GroupAttribute memberOf Attribute read for the user's group membership. The resulting group names are mapped to dashboard roles by MxGateway:Dashboard:GroupToRole. Required when Enabled.

When Enabled is true, Server, SearchBase, ServiceAccountDn, ServiceAccountPassword, UserNameAttribute, DisplayNameAttribute, and GroupAttribute must be non-blank, Port must be valid, and AllowInsecure must be true whenever Transport is None. Group-to-role mapping lives in the dashboard section; see MxGateway:Dashboard:GroupToRole below and glauth.md.

Worker Options

Option Default Description
MxGateway:Worker:ExecutablePath src\ZB.MOM.WW.MxGateway.Worker\bin\x86\Release\ZB.MOM.WW.MxGateway.Worker.exe Path to the x86 worker executable launched for each gateway session. The path must be valid and point to a .exe file.
MxGateway:Worker:WorkingDirectory null Optional working directory for the worker process. When set, it must be a valid filesystem path.
MxGateway:Worker:RequiredArchitecture X86 Required Portable Executable architecture for the worker. Supported values are X86 and X64; MXAccess parity uses X86.
MxGateway:Worker:StartupTimeoutSeconds 30 Total startup budget for process launch, startup probe, pipe connect, handshake, and worker readiness.
MxGateway:Worker:StartupProbeRetryAttempts 3 Number of retry attempts for transient worker startup probe failures before pipe connection and handshake continue.
MxGateway:Worker:StartupProbeRetryDelayMilliseconds 250 Delay between transient startup probe retry attempts.
MxGateway:Worker:PipeConnectAttemptTimeoutMilliseconds 2000 Per-attempt timeout used by the worker named-pipe connect retry path. The overall pipe connection still stays under the startup budget.
MxGateway:Worker:ShutdownTimeoutSeconds 10 Grace period for worker shutdown before the gateway treats shutdown as failed and may kill the worker process tree.
MxGateway:Worker:HeartbeatIntervalSeconds 5 Worker heartbeat send interval and gateway heartbeat check cadence input.
MxGateway:Worker:HeartbeatGraceSeconds 15 Maximum age of the last worker heartbeat before the gateway faults the worker. This must be greater than or equal to HeartbeatIntervalSeconds.
MxGateway:Worker:MaxMessageBytes 16777216 Maximum worker IPC frame payload size in bytes. The validator allows values from 1024 through 268435456.

StartupProbeRetryAttempts, StartupProbeRetryDelayMilliseconds, PipeConnectAttemptTimeoutMilliseconds, timeout values, heartbeat values, and MaxMessageBytes must be positive. MaxMessageBytes is intentionally bounded to avoid accidental large allocations from malformed or oversized frames.

Session Options

Option Default Description
MxGateway:Sessions:DefaultCommandTimeoutSeconds 30 Default timeout used while the gateway waits for a worker command reply when an open-session request does not provide a positive command timeout.
MxGateway:Sessions:MaxSessions 64 Maximum number of concurrently open gateway sessions. Session opens reserve a slot atomically before worker creation.
MxGateway:Sessions:MaxPendingCommandsPerSession 128 Maximum number of pending worker commands for one session. Excess commands fail fast instead of queueing indefinitely.
MxGateway:Sessions:DefaultLeaseSeconds 1800 Initial session lease and refresh duration. Unary client activity extends the lease by this duration.
MxGateway:Sessions:LeaseSweepIntervalSeconds 30 Hosted monitor interval for closing expired leases. Active event-stream subscribers keep a session from expiring while the stream remains attached.
MxGateway:Sessions:AllowMultipleEventSubscribers false Controls whether multiple StreamEvents subscribers may attach to one session. true is rejected until event fan-out is implemented.

All numeric session options must be greater than zero. The current event stream implementation supports one active subscriber per session; this preserves event ordering and avoids competing consumers.

Event Options

Option Default Description
MxGateway:Events:QueueCapacity 10000 Capacity for bounded per-session event queues used by the gateway worker event channel and the public gRPC event stream queue.
MxGateway:Events:BackpressurePolicy FailFast Event backpressure behavior. FailFast faults the session on public stream queue overflow. DisconnectSubscriber disconnects only the slow stream.

QueueCapacity must be greater than zero. With FailFast, queue overflow faults the affected worker or session instead of silently dropping MXAccess events. With DisconnectSubscriber, public gRPC stream overflow terminates only the affected stream while the MXAccess session remains active.

Dashboard Options

Option Default Description
MxGateway:Dashboard:Enabled true Enables Blazor Server dashboard route mapping. The dashboard mounts at the host root (/); there is no separate path-base prefix.
MxGateway:Dashboard:AllowAnonymousLocalhost true Allows loopback dashboard requests to bypass the dashboard cookie requirement for local development. Remote requests still require dashboard authentication.
MxGateway:Dashboard:RequireHttpsCookie true Sets the dashboard auth cookie's secure policy. true keeps CookieSecurePolicy.Always — the cookie is only sent over HTTPS, which matches a production HTTPS deployment. Set to false for plain-HTTP dev deployments to use CookieSecurePolicy.SameAsRequest; the cookie is still flagged Secure on HTTPS requests, but it can round-trip over HTTP. Browsers drop Secure cookies set over HTTP from non-localhost hosts, so leaving this true while serving the dashboard over plain HTTP will break login from any remote browser.
MxGateway:Dashboard:CookieName MxGatewayDashboard Dashboard auth cookie name. Leave unset (null/blank) to use the default. Override it to give a distinct name to a gateway that shares a hostname with another gateway instance: browser cookies are scoped by host+path but not by port, so two instances on the same host would otherwise clobber each other's dashboard session under a shared cookie name. Changing it signs out existing dashboard sessions on next deploy.
MxGateway:Dashboard:SnapshotIntervalMilliseconds 1000 Dashboard snapshot refresh interval used by the snapshot SignalR hub and the pages that subscribe to it.
MxGateway:Dashboard:RecentFaultLimit 100 Maximum number of fault summaries projected into each dashboard snapshot.
MxGateway:Dashboard:RecentSessionLimit 200 Maximum number of session summaries projected into each dashboard snapshot.
MxGateway:Dashboard:ShowTagValues false Reserved display control for tag values. The dashboard does not show full tag values by default.
MxGateway:Dashboard:GroupToRole (empty) LDAP group → dashboard role mapping. Keys are LDAP group names (short CN or full DN — leading-RDN match). Values must be Administrator (read/write, API-key CRUD) or Viewer (read-only). A user whose LDAP groups don't intersect this map cannot sign in; with no mapping at all, only the loopback bypass admits anyone.

SnapshotIntervalMilliseconds must be greater than zero. RecentFaultLimit and RecentSessionLimit must be greater than or equal to zero. GroupToRole values are validated at startup; invalid role names fail validation. Emptiness is allowed (a closed deployment that admits no LDAP users) but practical deployments populate at least one Admin group.

Authorization policies

Three authorization policies are registered out of these options:

  • MxGateway.Dashboard.Viewer — gates the Razor component routes. Satisfied by either dashboard role (Administrator or Viewer), by AllowAnonymousLocalhost on loopback, or by Authentication.Mode = Disabled.
  • MxGateway.Dashboard.Admin — gates write-capable surfaces (API-key CRUD). Satisfied only by the Administrator role (same environmental bypasses).
  • MxGateway.Dashboard.HubClients — attached to the SignalR hubs. Accepts either the dashboard cookie scheme or the MxGateway.Dashboard.HubToken bearer scheme (used by SignalR's WebSocket upgrade path where the HttpOnly cookie can't be forwarded).

SignalR hubs

When the dashboard is enabled, three hubs are mapped under /hubs/*:

  • GET /hubs/snapshot — pushes DashboardSnapshot whenever the snapshot service produces a new one. Drives every page that inherits DashboardPageBase; replaces the earlier polling loop.
  • GET /hubs/alarms — re-broadcasts the AlarmFeedMessage stream from the central alarm monitor to all connected clients (group __alarms__).
  • GET /hubs/events — per-session MxEvent feed. Clients call SubscribeSession(sessionId) to join session:{id}. Events are mirrored from the corresponding gRPC StreamEvents call as a fire-and-forget side-effect; the dashboard only sees events while a gRPC client is also subscribed to that session.

GET /hubs/token (cookie-only) mints a 30-minute data-protected bearer token for the calling user; the Blazor pages use it via DashboardHubConnectionFactory to authenticate the SignalR connection.

Protocol Options

Option Default Description
MxGateway:Protocol:WorkerProtocolVersion 1 Worker IPC protocol version expected by the gateway and worker. This must match GatewayContractInfo.WorkerProtocolVersion.
MxGateway:Protocol:MaxGrpcMessageBytes 16777216 Public gRPC max send and receive message size in bytes. The same default is used by official clients. The validator allows values from 1024 through 268435456.

The protocol option is exposed for diagnostics and explicit deployment configuration, not for compatibility negotiation. A mismatch fails validation at startup.

Galaxy Options

Option Default Description
MxGateway:Galaxy:ConnectionString Server=localhost;Database=ZB;Integrated Security=True;TrustServerCertificate=True;Encrypt=False; SQL Server connection string for the Galaxy Repository (ZB) used by the GalaxyRepository browse RPCs. Override in production via MxGateway__Galaxy__ConnectionString.
MxGateway:Galaxy:CommandTimeoutSeconds 60 Per-command SQL timeout for all Galaxy browse RPCs.
MxGateway:Galaxy:DashboardRefreshIntervalSeconds 30 Interval between background refreshes of the dashboard Galaxy summary cache. SQL is hit at most once per interval regardless of dashboard render rate.
MxGateway:Galaxy:PersistSnapshot true Persists the latest successful Galaxy browse dataset to disk. When true, the cache reloads that snapshot at startup so clients can still browse last-known data while the Galaxy database is unreachable. The restored data is served with Stale status until a live query confirms it.
MxGateway:Galaxy:SnapshotCachePath C:\ProgramData\MxGateway\galaxy-snapshot.json File path for the persisted Galaxy browse snapshot. Ignored when PersistSnapshot is false. The snapshot is written atomically (temp file plus rename).

See Galaxy Repository Browse for the RPC surface and behavior.

Alarm Options

Option Default Description
MxGateway:Alarms:Enabled false Gates the gateway's always-on central alarm monitor. When true, the gateway opens one gateway-owned worker session dedicated to alarms, caches the active-alarm set, and fans it out to every client through the StreamAlarms RPC — no client opens its own session to see alarms.
MxGateway:Alarms:SubscriptionExpression (empty) AVEVA alarm-subscription expression the monitor subscribes on startup, in canonical \\<machine>\Galaxy!<area> form. The literal Galaxy provider is correct regardless of the Galaxy database name. When empty and Enabled is true, the gateway falls back to \\<MachineName>\Galaxy!<DefaultArea> if DefaultArea is set.
MxGateway:Alarms:DefaultArea (empty) Area name used to compose a default subscription when SubscriptionExpression is empty. If both are empty while Enabled is true, the monitor faults with a configuration diagnostic.
MxGateway:Alarms:ReconcileIntervalSeconds 30 How often the monitor reconciles its in-process alarm cache against the worker's authoritative active-alarm snapshot, catching transitions the live poll-and-diff feed missed. Floored at 5 seconds.

The alarm monitor is independent of client sessions: AcknowledgeAlarm and StreamAlarms are session-less RPCs served by the monitor.

Host Endpoints and Transport Security (Kestrel)

The listening endpoints are not part of the MxGateway section. The gateway uses the stock ASP.NET Core host (WebApplication.CreateBuilder) with no ConfigureKestrel call in code, so endpoints come entirely from the standard Kestrel configuration section. On the deployed hosts these values are supplied as NSSM environment variables (Kestrel__Endpoints__...), not from appsettings.json.

Two named endpoints are bound:

Endpoint name Purpose Protocol requirement
Http Public gRPC API (sessions, invoke, events, Galaxy browse) HTTP/2
Dashboard Blazor dashboard and SignalR hubs HTTP/1.1 (HTTP/2 optional)

Both endpoints share one routing pipeline; the names only select which TCP port serves which traffic. The gRPC endpoint must negotiate HTTP/2, which drives the protocol settings below.

Plaintext (current deployments)

Both running hosts (10.100.0.48 and wonder-app-vd03) serve the gRPC port in cleartext HTTP/2 (h2c). Because cleartext HTTP/2 has no ALPN to negotiate the protocol, the gRPC endpoint must be pinned to Http2 with prior knowledge:

Kestrel__Endpoints__Http__Url=http://0.0.0.0:5120
Kestrel__Endpoints__Http__Protocols=Http2
Kestrel__Endpoints__Dashboard__Url=http://0.0.0.0:5130

In this mode all client↔gateway traffic — including the authorization: Bearer mxgw_... API key and any WriteSecured / AuthenticateUser payloads — crosses the network unencrypted. This is acceptable only on a trusted/isolated network segment. Prefer TLS for anything else.

TLS

To encrypt the gRPC channel, give the Http endpoint an https:// URL and a certificate. Over TLS, ALPN negotiates HTTP/2, so the explicit Protocols=Http2 pin is no longer required (the default Http1AndHttp2 works for gRPC over TLS).

appsettings.json form:

{
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "https://0.0.0.0:5120",
        "Certificate": {
          "Path": "C:\\ProgramData\\MxGateway\\certs\\gateway.pfx",
          "Password": "<pfx-password>"
        }
      },
      "Dashboard": {
        "Url": "https://0.0.0.0:5130",
        "Certificate": {
          "Path": "C:\\ProgramData\\MxGateway\\certs\\gateway.pfx",
          "Password": "<pfx-password>"
        }
      }
    }
  }
}

Equivalent NSSM environment-variable form (how config is delivered on the hosts — see [server deploy mechanics in the project notes]):

Kestrel__Endpoints__Http__Url=https://0.0.0.0:5120
Kestrel__Endpoints__Http__Certificate__Path=C:\ProgramData\MxGateway\certs\gateway.pfx
Kestrel__Endpoints__Http__Certificate__Password=<pfx-password>
Kestrel__Endpoints__Dashboard__Url=https://0.0.0.0:5130
Kestrel__Endpoints__Dashboard__Certificate__Path=C:\ProgramData\MxGateway\certs\gateway.pfx
Kestrel__Endpoints__Dashboard__Certificate__Password=<pfx-password>

Certificate sourcing options (any standard ASP.NET Core form is accepted):

Form Keys
PFX file Certificate:Path (+ Certificate:Password if encrypted)
PEM pair Certificate:Path (cert) + Certificate:KeyPath (private key)
Windows cert store Certificate:Subject, Certificate:Store (e.g. My), Certificate:Location (LocalMachine), Certificate:AllowInvalid

The certificate's CN/SAN must cover the host name clients dial (or clients must set a server-name override — see below). The dashboard endpoint can keep its own certificate independent of the gRPC endpoint; pair this with MxGateway:Dashboard:RequireHttpsCookie (true) for production HTTPS.

Automatic self-signed certificate

mxaccessgw is an internal tool with no PKI to issue certificates, so requiring an operator to supply one before TLS works pushed deployments toward plaintext. To avoid that, the gateway fills in a self-signed certificate when an HTTPS endpoint is configured without one.

Trigger. At startup the gateway inspects Kestrel:Endpoints:*. If any endpoint has an https:// URL and no Certificate subsection of its own, and no Kestrel:Certificates:Default is set, the gateway generates (or loads) a persisted self-signed certificate and wires it in as the HTTPS default via ConfigureHttpsDefaults. All-plaintext deployments are untouched: when no HTTPS endpoint is configured, no certificate or key material is generated or written.

Generated certificate. ECDSA P-256, serverAuth EKU, validity ≈ ValidityYears (default 10 years, with one day of clock-skew slack before notBefore). SANs cover localhost, the machine name (and its FQDN when resolvable), each entry in AdditionalDnsNames, and the loopback addresses 127.0.0.1 and ::1.

MxGateway:Tls:* options. All optional; the zero-config path needs none of them.

Option Default Purpose
Tls:SelfSignedCertPath C:\ProgramData\MxGateway\certs\gateway-selfsigned.pfx Where the generated certificate is persisted
Tls:ValidityYears 10 Lifetime of the generated certificate (validated 1100)
Tls:AdditionalDnsNames [] Extra DNS SANs (e.g. a load-balancer name)
Tls:RegenerateIfExpired true Replace an expired persisted certificate instead of failing

ValidityYears is validated by GatewayOptionsValidator (range 1100); the "HTTPS endpoint configured but no certificate available" fail-fast lives in the bootstrap/provider, because the validator only sees the MxGateway section, not Kestrel:Endpoints.

Persistence. The PFX is written with an empty export password — a random in-memory password could not be reused across restarts, which the persist-and-reuse model requires. The private key is instead protected at rest by filesystem permissions: a restrictive ACL on Windows (SYSTEM + Administrators, inherited ACEs stripped) on the certs directory and file, and mode 0600 on non-Windows. The write is atomic (hardened temp file, then move). The persisted certificate is reused across restarts (stable thumbprint, so CA-pinning clients keep working) and regenerated only when it is missing, expired (and RegenerateIfExpired is true), or unreadable/corrupt. If the directory is not writable or the ACL cannot be applied, the gateway fails fast with a diagnostic naming the path rather than falling back to an in-memory certificate.

Logging. On generate or load, the gateway logs the certificate thumbprint, SAN list, and notAfter at Information. The PFX bytes, export password, and private key are never logged.

Operator override. The generated certificate is only the HTTPS default. To use a real certificate, configure one explicitly — either per endpoint via Kestrel:Endpoints:<name>:Certificate (Path/Subject/Thumbprint, etc., as in the table above) or globally via Kestrel:Certificates:Default. An explicitly-configured certificate takes precedence, and the gateway then writes no self-signed material.

Client side

Each official client opts into TLS explicitly. For the .NET client (MxGatewayClientOptions):

Option Effect
UseTls (default false) Enables TLS. Requires an https:// endpoint; an https:// endpoint without UseTls fails validation, and vice versa.
CaCertificatePath Pins a custom root (self-signed / private CA) using CustomRootTrust chain validation instead of the OS trust store; the .NET client also enforces the certificate hostname/SAN match on this path.
RequireCertificateValidation (default false) Forces OS/system-trust verification on a TLS connection with no pinned CA. Leave false for the lenient default.
ServerNameOverride SNI / certificate host name override when the dialed host differs from the certificate CN/SAN.

To pair with the auto-generated self-signed certificate above, the clients are lenient by default: a TLS connection with no pinned CA accepts whatever certificate the gateway presents. Pin CaCertificatePath to verify, or set RequireCertificateValidation to force system-trust verification without pinning. The other language clients expose the equivalent options; the exact behavior differs per stack — Python uses trust-on-first-use and Rust is pin-only. See each client README for the as-built behavior.

Gateway↔worker IPC

Transport security here applies only to the public gRPC channel. The gateway↔worker link is a per-session named pipe (mxaccess-gateway-{gatewayPid}-{sessionId}), not a network socket. It is not TLS-encrypted and does not need to be: it never leaves the local Windows host and is secured by the OS pipe ACL. See Worker Frame Protocol.