Files
Joseph Doherty dc9c0c950c rename: prefix gateway projects/namespaces with ZB.MOM.WW + sln→slnx
Apply the ZB.MOM.WW. prefix to all gateway-side projects, folders,
.csproj/.sln contents, C# namespaces, using directives, generated proto
C# (csharp_namespace + checked-in generated files), InternalsVisibleTo
attributes, project-name string literals (LoadProject, .sln lookups,
worker exe paths, staticwebassets manifest), and the install/script/doc
references that point at any of the above. Migrate the solution from
.sln to .slnx via `dotnet sln migrate` and delete the old file.

External-runtime identifiers are intentionally NOT prefixed so external
configuration keeps working:
- GatewayMetrics.cs MeterName ("MxGateway.Server")
- DashboardAuthenticationDefaults Scheme/Policy ("MxGateway.Dashboard")
- GatewayRequestLoggingMiddleware logger category ("MxGateway.Request")
- StaRuntime thread name ("MxGateway.Worker.STA")
- appsettings.json root section "MxGateway" + env-var prefix
  MxGateway__... and secret-name MxGateway:ApiKeyPepper
- C:\ProgramData\MxGateway\ data dir paths

Also fixes two tests that were not rename-related but became visible
while validating the rename:

- WorkerLiveMxAccessSmokeTests.ShutDownAsync: cancellation that the
  gateway service correctly maps to RpcException(Cancelled) per gRPC
  convention was being misclassified as a stream fault. Added a sibling
  catch on RpcException with StatusCode.Cancelled.

- IntegrationTestEnvironment.ResolveRepositoryRoot: extracted IsRepositoryRoot
  and made it accept either a .git marker OR a .sln/.slnx next to src/
  so the worker-exe walker works in non-git working copies.

clients/proto/proto-inputs.json's protoRoot updated to point at
src/ZB.MOM.WW.MxGateway.Contracts/Protos.

Verified by `dotnet build` and a full `dotnet test` of the .slnx with
MXGATEWAY_RUN_LIVE_{MXACCESS,LDAP,GALAXY}_TESTS=1:
  Tests: 472/472 pass
  Worker.Tests: 280/280 pass (4 dev-rig [Fact(Skip=...)] skipped)
  IntegrationTests: 18/18 pass

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 16:22:23 -04:00

5.7 KiB

Protobuf Contracts

The contracts project contains the public gRPC API and the gateway-to-worker IPC messages. The .proto files are the source of truth; generated C# files are recreated by the contracts project build.

Files

src/ZB.MOM.WW.MxGateway.Contracts/Protos/mxaccess_gateway.proto defines the public MxAccessGateway gRPC service, command payloads, command replies, event DTOs, MxValue, MxArray, and MxStatusProxy.

The public command model includes bulk subscription command kinds for AddItemBulk, AdviseItemBulk, RemoveItemBulk, UnAdviseItemBulk, SubscribeBulk, and UnsubscribeBulk. These commands are normal unary Invoke payloads. They do not add separate gRPC methods, and they return a BulkSubscribeReply containing per-item SubscribeResult records with ServerHandle, TagAddress, ItemHandle, WasSuccessful, and ErrorMessage.

The gateway forwards each bulk command as one worker command. The worker runs the corresponding MXAccess AddItem, Advise, UnAdvise, and RemoveItem calls sequentially on the session STA and preserves input order in the result list.

The command model also includes bulk write/read command kinds: WriteBulk, Write2Bulk, WriteSecuredBulk, WriteSecured2Bulk, and ReadBulk. They are unary Invoke payloads on the same MxAccessGateway surface (not separate gRPC methods) and exist so a caller can submit one list of items per round trip while preserving MXAccess parity per entry.

  • WriteBulkCommand / Write2BulkCommand / WriteSecuredBulkCommand / WriteSecured2BulkCommand each carry a server_handle and a repeated list of entries (WriteBulkEntry, Write2BulkEntry, WriteSecuredBulkEntry, WriteSecured2BulkEntry). Each entry mirrors the single-item command shape — item_handle + value (+ timestamp_value on the *2 variants, + current_user_id / verifier_user_id on the secured variants). All four replies use BulkWriteReply, which carries repeated BulkWriteResult. A BulkWriteResult has server_handle, item_handle, was_successful, optional int32 hresult, repeated MxStatusProxy statuses, and error_message. Per-entry failures populate error_message + hresult and never raise — callers iterate and inspect each entry. The credential-sensitive redaction rules for WriteSecured / WriteSecured2 apply to every value inside WriteSecuredBulkEntry and WriteSecured2BulkEntry.

  • ReadBulkCommand carries server_handle, repeated string tag_addresses, and uint32 timeout_ms (0 means use the gateway-configured default). The reply is BulkReadReply carrying repeated BulkReadResult. A BulkReadResult has server_handle, tag_address, item_handle, was_successful, was_cached, value, quality, source_timestamp, repeated MxStatusProxy statuses, and error_message. MXAccess has no synchronous Read, so ReadBulk is dual-mode per entry: when a tag is already advised in the session the worker returns the cached OnDataChange payload without touching the subscription (was_cached = true); otherwise the worker takes a full AddItem + Advise + wait-for-first-OnDataChange + UnAdvise + RemoveItem snapshot lifecycle and returns the result (was_cached = false). The asymmetry that BulkReadResult has no hresult field is intentional — ReadBulk outcomes are timeout / cache / lifecycle states rather than MXAccess COM return codes.

See gateway.md for the full cached-vs-snapshot ReadBulk lifecycle and the per-command scope requirements, and docs/DesignDecisions.md "Bulk Command Family" for the rationale behind the per-entry result shape (independent success tracking, input-order preservation, no partial-failure exceptions).

src/ZB.MOM.WW.MxGateway.Contracts/Protos/mxaccess_worker.proto defines the named-pipe worker IPC envelope and control messages. It imports mxaccess_gateway.proto so the worker and gateway use the same command, reply, event, value, and status shapes.

src/ZB.MOM.WW.MxGateway.Contracts/Protos/galaxy_repository.proto defines the GalaxyRepository service used by clients to browse the Galaxy Repository (deployed object hierarchy and dynamic attributes). The service is metadata- only and does not share types with mxaccess_gateway.proto. See Galaxy Repository Browse for the RPC catalog and behavior.

Generated C# output is written to src/ZB.MOM.WW.MxGateway.Contracts/Generated/. Do not hand-edit generated files.

Client generation inputs are published through clients/proto/proto-inputs.json and the descriptor set under clients/proto/descriptors/. See Client Proto Generation for language-specific generation inputs, output directories, and golden protobuf JSON fixtures.

Generation

Run the contracts build to regenerate C# protobuf and gRPC code:

dotnet build src/ZB.MOM.WW.MxGateway.Contracts/ZB.MOM.WW.MxGateway.Contracts.csproj

Run the focused contract tests after changing either .proto file:

dotnet test src/ZB.MOM.WW.MxGateway.Tests/ZB.MOM.WW.MxGateway.Tests.csproj --filter ProtobufContractRoundTripTests

The full solution build also regenerates the C# contracts before compiling gateway and test projects:

dotnet build src/ZB.MOM.WW.MxGateway.slnx

Regenerate the client descriptor after changing either .proto file:

powershell -ExecutionPolicy Bypass -File scripts/publish-client-proto-inputs.ps1