27 KiB
MxAccessGateway — Remediation Plan & Tracking (2026-08-19 review)
Source review: ../00-overall.md (HEAD 8b3e3b3, committed as f4919ba). Generated 2026-08-20.
Tracks the 34 cycle-3 IDs (GWC-31+, WRK-32+, IPC-33+, SEC-37+, CLI-46+, TST-31+) plus the tracker-housekeeping actions the overall asked for. Cycle-1/2 trackers remain the record for their own IDs.
Status legend: Not started · In progress · Done · Blocked (external) · Deferred (P2) · N/A.
Execution model
This plan is executed as seven parallel batches, each by one subagent working in an isolated git worktree on its own fix/c3-<batch> branch, merged back into main by the coordinator in the order listed (lowest conflict surface first). Every batch must: build the affected component(s) on macOS (NonWindows.slnx — the x86 worker cannot build here), run only the filtered tests it touches, update docs in the same commit, and cite finding IDs in commit messages (fix(IPC-34): …). Worker-side changes (batches E, F) are verified afterwards on windev via windev-worker-ci.ps1 -Mode test.
Model assignment rationale: opus for batches that change concurrency/authorization logic or require reasoning across several interacting files with regression tests; sonnet for contained, well-specified edits with a clear recipe (version bumps, doc reconciliation, a two-line worker fix); haiku for none — every batch either touches code invariants or needs judgement about stale prose, where the cost of a wrong mechanical sweep exceeds the saving.
| Batch | Branch | Findings | Model | Why this model | Status |
|---|---|---|---|---|---|
| A | fix/c3-client-versions |
CLI-46 | sonnet | Mechanical five-client bump + README note + one script guard; recipe is fully specified | Done |
| B | fix/c3-glauth-doc |
TST-31 | sonnet | Reconcile a table against one TOML source of truth, re-derive one default, change an assert to a log | Done |
| C | fix/c3-tracker-hygiene |
GWC-31 + housekeeping (close GWC-16/IPC-08/IPC-31, refresh TST-06/TST-17, register WRK-31) | sonnet | Cross-file comment/ID sweep needs care about what each ID means, but no logic changes | Done (3619152) |
| D | fix/c3-dashboard-acl |
SEC-40, SEC-41, GWC-38 | opus | Authorization semantics, fail-closed decisions, claims re-resolution; each needs a regression test | Done (b177636 GWC-38, 2ef7b93 SEC-41+SEC-40, 8257a03 comment fixup; branch not merged/pushed) |
| E | fix/c3-ipc-boundaries |
IPC-33, IPC-39, IPC-34, IPC-35 | opus | Changes the WorkerClient command lifecycle, the options validator, and the worker drain budget; race-sensitive | Done (577a0db IPC-33, a71663a IPC-39, b27035b IPC-34, ab41362 IPC-35; branch fix/c3-ipc-boundaries, not merged/pushed) — worker half verified on windev (f2ab9cc, Worker.Tests 524/524) |
| F | fix/c3-worker-residuals |
WRK-32, WRK-33 (+WRK-34 opportunistic) | sonnet | Small, precisely located worker edits + doc prose; cannot be built on macOS so the agent's job is a careful, minimal diff | Done (windev x86 build + Worker.Tests 524/524 green on f2ab9cc) |
| G | fix/c3-session-lifecycle |
GWC-32, GWC-34, GWC-37 | opus | Distributor/dispose lifecycle races and an alarm-monitor re-resolve path; needs lock-discipline reasoning | Done (058d8d5, 282a0e7, 1932217) |
Out of scope for this execution (recorded, not dropped):
| ID | Status | Why |
|---|---|---|
| TST-32 | Blocked (external) | Gitea runner registration-token reset is a web-UI action on the Gitea admin page; no repo change. Operator to-do. |
| SEC-37 | Blocked (external) | Family-wide: TLS on the shared GLAuth lives in scadaproj/infra/glauth/ (separate repo + docker host). Plan separately; after it lands, move the deployed service to Production. |
| CLI-47/48/49/50, IPC-36/37, TST-35 | Not started | Activated by the 2026-08-25 P2 continuation below. |
| GWC-33/35, SEC-38/39 | Done | Closed by continuation batch I; regression counts and commits are recorded below. |
| GWC-36, IPC-38, TST-33/34/36 | Done | Closed by continuation batch H; verification and commit are recorded below. |
| WRK-34 | Done | Completed opportunistically in batch F (3679e59): watchdog faults use CommandMethod=Watchdog and carry the stuck correlation ID in the diagnostic message. Tracker correction recorded by the continuation audit. |
Batch specifications
A — CLI-46 client release-train bump (sonnet)
- Bump .NET/Go/Python/Rust clients
0.2.0 → 0.2.1, Java0.2.1 → 0.2.2in every version-bearing file (pyproject.toml+version.py,Cargo.tomlworkspace + anyversion =consumers,Directory.Build.props/csproj<Version>, Javabuild.gradle/gradle.properties, Go module is tag-driven — update anyVersionconst if one exists). Followdocs/ClientPackaging.mdfor the authoritative file list. clients/python/README.md+docs/ClientPackaging.md: note that published pypi 0.2.0 has a brokenconnect()(event-loop binding, fixed bya8f86b5) and is superseded by 0.2.1.- Add a PR-time check to
scripts/check-codegen.ps1(or a newscripts/check-client-versions.ps1wired where the other checks run): fail if anyclients/<lang>source differs from its last publish tag while the version constant still equals that tag's version. Document indocs/ClientPackaging.md. - Verify:
dotnet build clients/dotnet/...slnx;cargo check --workspace;python -m pytest(clients/python);JAVA_HOME=/opt/homebrew/opt/openjdk@17 gradle testthen revert spurious generated-proto churn;go build ./... && go test ./....
B — TST-31 glauth.md + live-test credential (sonnet)
- Reconcile
glauth.mdagainst~/Desktop/scadaproj/infra/glauth/config.toml: ReadOnly gid, the pre-provisioned users table (dropreadonly/readonly123, fixadminpassword), the worked example at:124. Keep the OPC-UA taxonomy note. - Re-derive
MXGATEWAY_LIVE_MXACCESS_WRITE_SECURED_PASSWORDdefault indocs/GatewayTesting.mdand the?? "admin123"literal inWorkerLiveMxAccessSmokeTests.csfrom the config; make the test log (not assert) whetherAuthenticateUsersucceeded. - Verify:
dotnet build src/ZB.MOM.WW.MxGateway.NonWindows.slnx(IntegrationTests compiles on mac? if excluded, note it).
C — GWC-31 + tracker housekeeping (sonnet)
- Sweep code comments citing unregistered
GWC-30/GWC-31(perf pass) inWorkerClient.cs,GatewayMetrics.cs,WorkerClientTests.cs, workerWorkerFrameReader/Writer.cstoPERF-nnkeyed to task numbers indocs/plans/2026-08-15-perf-review-remediation.md; add a PERF-ID table to that plan. Do not touch the genuine GWC-30 (frame-reader prefix) citations if any exist. archreview/REVIEW-PROCESS.md(or wherever the ID rule lives): state that GWC/WRK/IPC/SEC/CLI/TST prefixes are reserved for archreview registers.- Cycle-2 tracker (
archreview/2026-07-12/remediation/00-tracking.md+ domain docs): GWC-16 → Won't fix (rationale from cycle-3 10-gateway-core.md), IPC-08 → Done (7c1ea12, residual IPC-34), IPC-31 → Done (superseded by GWC-28), refresh TST-06/TST-17 rows, register WRK-31 (interim ID burned bye913dab) so it is never reused. - Verify:
dotnet build src/ZB.MOM.WW.MxGateway.NonWindows.slnx;dotnet test --filter FullyQualifiedName~WorkerClientTests.
D — SEC-40, SEC-41, GWC-38 (opus)
- SEC-41:
DashboardSessionAclre-resolves tags fromLdapGroupClaimTypeclaims viaDashboardGroupTagMapping.MapGroupsToTagsagainst current options (asHubTokenServicedoes) instead of trusting login-stamped tag claims; keep stamped claims only as fallback when no group claims exist (document). Test: principal with stale tag claim + group whose grant was removed → denied. - SEC-40: decide tighten:
AlarmsHubgets a dedicated policy requiring a real role claim (anonymous-loopback/Disabled bypass excluded) — and document indocs/GatewayDashboardDesign.mdACL section +docs/GatewayConfiguration.mdGroupToTag row that alarm metadata remains galaxy-wide for authenticated Viewers (central monitor, no per-session provenance). Test for the policy. - GWC-38:
GatewayBrowseScopeProviderthrowsRpcException(PermissionDenied)(and logs) whenCurrentis null and API-key auth is enabled; unchanged when auth mode is Disabled. Test both branches. - Verify: build Server;
dotnet test --filter "FullyQualifiedName~DashboardSessionAcl|FullyQualifiedName~AlarmsHub|FullyQualifiedName~BrowseScope"(adjust to real class names).
Outcome (done, branch fix/c3-dashboard-acl, commits b177636, 2ef7b93, 8257a03; not merged, not pushed). Decisions worth carrying forward:
- SEC-41 fallback: the ACL re-resolves from
mxgateway:ldap_groupclaims when the principal has any, and falls back to the stampedzb:dashboardtagclaims only when it has none. That is exactly the hub-token principal —HubTokenService.Validaterehydrates roles and tags but not groups, so re-resolution already happened at mint. The fallback cannot re-open the cookie gap, becauseDashboardAuthenticatorstamps both claim kinds from one group list. - SEC-40 requirement type: new
AuthenticatedDashboardRoleRequirement+AuthenticatedDashboardRoleHandlerand aMxGateway.Dashboard.Alarmspolicy.DashboardAuthorizationHandlerisAuthorizationHandler<DashboardAuthorizationRequirement>, so it is never invoked for the new type — the same structural device the Secrets UI'ssecrets:managealready relies on. Both hub schemes are retained on the policy. - SEC-40 scope answer: the
/alarmsBlazor page carries the SAME policy (it reads the central monitor in process — gating only the hub left the disclosure one navigation away), and the side-rail Alarms link is wrapped in anAuthorizeViewon that policy.AlarmsHubPublisheris unchanged and stays unfiltered by design: audience is decided at hub admission and the feed carries no per-session provenance. - GWC-38:
PermissionDenied+ warning only whenAuthentication:Mode=ApiKey;Mode=Disabledstill returns unscoped.GalaxyRepositoryHostWiringTestsphase 1 was changed to push an unconstrained identity rather than none — that is production's real unscoped case. - New/changed tests:
AlarmFeedAuthorizationTests(new, 7),DashboardSessionAclTests(+5),GatewayBrowseScopeProviderTests(+2),SecretsNavRenderTests(+2, and it must register the new policy — an unregistered policy name throws insideAuthorizeViewrather than denying). Filtered run over the touched classes: 92 passed / 0 failed;NonWindows.slnxbuilds zero-warning.
E — IPC-33, IPC-39, IPC-34, IPC-35 (opus)
- IPC-33 option (a):
GatewayOptionsValidatoradds the upper couplingWorker:MaxMessageBytes ≤ Protocol:MaxGrpcMessageBytes + 2×reserve; workerResolveDrainReplyByteBudgetbecomesMaxMessageBytes − 2×DrainReplyFrameHeadroomBytes(floorMaxMessageBytes/2); updatedocs/GatewayConfiguration.md,docs/WorkerFrameProtocol.md. Test:GatewayOptionsTestscase for the new bound. - IPC-39: pre-check compares against
MaxMessageBytes − MaxSequenceEncodingBytes (11); fix the comment direction. - IPC-34: caller-cancellation arms call
TrySendCancelForAbandonedCommand(renamed) gated onremoved, skipped when_stopCtsis the source; newWorkerClientErrorCode.CallerCancelledreplacing theGatewayShutdownmislabel, mapped toCancelledin the gRPC layer; updatedocs/Grpc.mdmapping line,gateway.md:913-919,docs/GatewayProcessDesign.md:596-602. Test: twin of the timeout test driven by the caller token. - IPC-35:
ReadHandshakeEnvelopeAsyncspecial-casesWorkerFault→WorkerClientException(WorkerFaulted, CreateWorkerFaultMessage(...)). Test: fake writesWorkerFault{MxaccessCreationFailed}instead ofWorkerReady, category text surfaces. - Verify: build Server;
dotnet test --filter "FullyQualifiedName~WorkerClientTests|FullyQualifiedName~GatewayOptions". Worker half → windev afterwards.
F — WRK-32, WRK-33 (sonnet)
- WRK-33:
ObserveFaultWhenever(ObserveCommandTaskAsync(commandTask));atWorkerPipeSession.cs:1235(or catch-all-and-log in the observer). - WRK-32: one
pumpStep()before capturing theCurrentVersionbaseline inMxAccessCommandExecutor.cs; rewrite the executor doc comment (:996-1003) to state the recency-based contract; add the same todocs/MxAccessWorkerInstanceDesign.mdwrite-completion section and the reply-field comment inmxaccess_gateway.proto(comment-only proto edit → regenerate all generated artifacts in the same commit, per the repo rule; if regen tooling is unavailable on macOS, skip the proto comment and say so). - WRK-34 if trivial:
CreateFault(StaHung, "Watchdog", …)with the correlation id moved into the message. - Cannot build on macOS: keep diff minimal, net48-safe (no init-only/positional records). Verified on windev afterwards.
G — GWC-32, GWC-34, GWC-37 (opus)
- GWC-32:
DisposeAsynctransitions_statetoClosedunder_syncRootbefore completing channels (orif (_disposed || IsTerminalState()) return;inStageWorkerEvent); update the XML doc to name all three completion paths. Test: dispose a Ready client mid-dispatch → noProtocolViolationfault/metric. - GWC-34:
_eventDistributorDisposedflag set under_syncRootwhen nulling;EnsureDistributorCreatedthrowsSessionManagerException(SessionNotReady)when set. Test: attach after dispose → throws, no silent hang. - GWC-37: on
ApplyProviderModeChangeAsync(toMode == Subtag)re-resolve the watch list and re-subscribe; additionally surface "zero targets resolved while mode can need them" on the provider status (Degraded+ reason). Updatedocs/alarm-subtag section. Test with the fake worker: GR discovery fails at start, succeeds at failover → watch list non-empty after failover. - Verify: build Server;
dotnet test --filter "FullyQualifiedName~WorkerClientTests|FullyQualifiedName~GatewaySession|FullyQualifiedName~AlarmMonitor|FullyQualifiedName~AlarmWatchList". - Outcome (Done):
058d8d5GWC-32,282a0e7GWC-34,1932217GWC-37 onfix/c3-session-lifecycle. Filtered run 176/176 green;NonWindows.slnxclean.- GWC-37 does not re-send the watch-list on the failover edge. The worker's
AlarmCommandHandler.Subscriberejects a secondSubscribeAlarmswhile subscribed, and the only expressible replacement (UnsubscribeAlarms+SubscribeAlarms) rebuildsFailoverAlarmConsumer— restarting it on the primary that just failed and discarding the warm standby — so it would flap the feed rather than repair it. The re-resolve happens and any drift is reported on the same status frame as the failover; a monitor restart is the supported way to apply a new list. Adding a watch-list-update worker command is a possible future item, not done here. - GWC-37 changes
IAlarmWatchListResolver.ResolveAsyncto returnAlarmWatchListResolution, and givesDegraded && Mode==ALARMMGRa real meaning (empty/undiscoverable standby) with a new dashboard labelAlarm Manager (no subtag standby). - GWC-32's dispose path now also records
WorkerStopped("dispose")via the existing once-latch, closing aworkers_runninggauge leak on the dispose-a-Ready-client path. GWC-12's double-dispose interlock got a natural home (the_disposedclaim moved under_syncRoot) but is not claimed as fixed.
- GWC-37 does not re-send the watch-list on the failover edge. The worker's
Merge order
C is merged last (its comment sweep touches the same files E and G edit). Order: A, B, F, D, G, E, C. After merge: full NonWindows build + one full gateway test run; then windev worker CI for E+F.
Integration gate (2026-08-20)
All seven branches merged into main (A ee68cc3, B f59c34a, C f2ab9cc, D 9f0c3fd, E cfbc995, F aa07497, G c6650c1). Merged tree: NonWindows.slnx 0 warnings; full gateway suite 1183/1183 passed; windev windev-worker-ci.ps1 -Sha f2ab9cc -Mode test: x86 Worker build succeeded, Worker.Tests 524 passed / 11 skipped / 0 failed. Follow-ups surfaced by the batches: a worker command to refresh a live alarm subscription's watch-list (would let GWC-37's re-resolve be applied, not just reported); WRK-32's proto reply-field comment deferred until the next proto regen wave; the five clients are bumped but not yet published.
P2 continuation (planned 2026-08-25)
Current-state audit: refreshed origin/main and re-checked every deferred finding and integration-gate follow-up. Sixteen of the seventeen P2 findings remain open; WRK-34 was already completed by 3679e59. All three follow-ups remain open. Exact target client coordinates are still absent from Gitea (HTTP 404), and clients/go/v0.2.1 does not exist.
Approved design: ../../../docs/plans/2026-08-25-cycle-3-p2-followups-design.md (30548da).
Execution plan: ../../../docs/plans/2026-08-25-cycle-3-p2-followups.md.
The continuation runs serially in the isolated .worktrees/c3-p2-followups worktree on codex/c3-p2-followups, with a tracker update at every batch boundary. Codex equivalents are selected from the implementation risk: gpt-5.6-terra/medium for contained documentation, CI, and client work; gpt-5.6-sol/high for concurrency, authorization, protocol, and live alarm lifecycle changes.
| Batch | Findings / follow-ups | Codex model | Status | Exit gate |
|---|---|---|---|---|
| H — tracker and currency | WRK-34 record, GWC-36, IPC-38, TST-33/34/36 | gpt-5.6-terra medium |
Done | Currency greps clean; README check in portable CI; NonWindows build clean |
| I — gateway correctness/security | GWC-33/35, SEC-38/39 | gpt-5.6-sol high |
Done | Focused regression tests green; NonWindows build clean |
| J — secondary contracts | IPC-36/37 | gpt-5.6-sol high |
Done | Shared launch constants and descriptor parity tests green |
| K — client alarm parity | CLI-47/48/49/50 | gpt-5.6-terra high |
Done | All five client suites green |
| L — live watch-list/proto wave | watch-list refresh follow-up + WRK-32 proto comment | gpt-5.6-sol high |
Done | Codegen clean; portable alarm/contract tests green; windev Worker.Tests green |
| M — Windows gateway CI | TST-35 | gpt-5.6-terra medium |
Done | windev live mode proves Worker, gateway, full-slnx, and live smoke tiers |
| N — integration and release | publish five clients + Contracts | gpt-5.6-sol high |
Done | Full local/windev gates; merged main; registry coordinates and Go tag verified |
Continuation tasklist
H — tracker and currency
- Correct WRK-34 from Deferred to Done with commit
3679e59. - GWC-36: correct
EventSubscriberReplayAttachment.OldestAvailableSequencesemantics. - IPC-38: add public
DrainEventsbehavior todocs/Grpc.mdand correct the cycle-2 omission rationale. - TST-33: reconcile the five stale/self-contradictory
stillpending.mdclaims and mark its live-status boundary. - TST-34: run
code-reviews/regen-readme.py --checkin portable CI and qualify the interpreter note. - TST-36: replace prose
eventscope references with canonicalevents:read. - Record batch-H commit and verification evidence here.
Batch-H verification (2026-08-25): python3 code-reviews/regen-readme.py --check
reported the generated README current and consistent; the TST-33 and live-document
TST-36 stale-pattern greps returned no matches; docs/Grpc.md contains the public
DrainEvents contract; and dotnet build src/ZB.MOM.WW.MxGateway.NonWindows.slnx
succeeded with 0 warnings / 0 errors in 1.59 s. Batch commit: 92aae28.
I — gateway correctness and security
- GWC-33: unregister terminal clients from the event-queue-depth gauge without shortening fault retention.
- GWC-35: repair acknowledged-to-active snapshot deltas with a Raise transition and instance identity.
- SEC-38: feed/consult the aggregate for valid key IDs that overflow the peer partition cap.
- SEC-39: prove a null effective key ID cannot reset the shared fallback partition.
- Run focused tests and clean NonWindows build; record counts and commits here.
Batch-I verification (2026-08-25): the combined WorkerClientTests,
GatewayAlarmMonitorAttachOrderTests, and ApiKeyFailureLimiterTests filter passed
55/55 tests in 12 s; dotnet build src/ZB.MOM.WW.MxGateway.NonWindows.slnx
succeeded with 0 warnings / 0 errors in 3.42 s. Finding commits: GWC-33
b0156c6, GWC-35 7807201, and SEC-38/SEC-39 1875426.
J — secondary contracts
- IPC-36: centralize all six worker-launch environment names in Contracts and consume them on both sides.
- IPC-36: document variable/config/default mapping and test launcher completeness.
- IPC-37: add normalized retained-vs-served Galaxy descriptor parity test.
- Run focused tests and clean NonWindows build; record counts and commits here.
Batch-J verification (2026-08-25): the combined WorkerProcessLauncherTests and
GalaxyContractParityTests filter passed 10/10 tests in 1 s; the descriptor
mutation proof identified the changed protobuf message; and dotnet build src/ZB.MOM.WW.MxGateway.NonWindows.slnx succeeded with 0 warnings / 0
errors in 2.20 s. IPC-36/IPC-37 commit: d6c5a11.
K — client alarm-feed parity
- CLI-47: make .NET text status flags explicit and document deliberate JSON differences.
- CLI-48: test provider/snapshot status arms in .NET, Go, and Java; add Go stream-alarm scaffold.
- CLI-49: export Go aliases for
AlarmProviderStatusandAlarmSnapshotStatus; fix five-arm documentation. - CLI-50: stream Python alarm rows incrementally with an unbounded default and bounded opt-in.
- Run .NET, Go, Python, Rust, and Java client suites; record counts and commits here.
Batch-K verification (2026-08-25): dotnet test clients/dotnet/ZB.MOM.WW.MxGateway.Client.slnx passed 134/134 portable
tests (1 live test skipped); go test ./... passed both tested packages;
python -m pytest passed 169/169 portable tests (1 opt-in TLS test
skipped); cargo test --workspace passed 108/108 tests; and
JAVA_HOME=/opt/homebrew/opt/openjdk@17 gradle test passed 132/132 tests.
CLI-47/CLI-48/CLI-49/CLI-50 commit: 5cdb3da.
L — live watch-list refresh and protobuf wave
- Add explicit fallback-enabled subscription semantics for an initially empty discovered list.
- Add and round-trip
UpdateAlarmWatchListCommandand itsMxCommandKind. - Route the command through the worker executor and alarm handler on the STA.
- Build/subscribe/attach a replacement standby before swap; preserve the old standby on failure.
- Preserve current primary/subtag mode during a successful replacement.
- Re-resolve on the existing gateway reconciliation cadence and send only material changes/recovery.
- Refresh immediately at failover edge, update acknowledged fingerprint only after worker OK, and reconcile after success.
- Expand WRK-32's public reply-field comment to the sequential stale-callback/recency case.
- Replace IPC-36's internal env-var name in the proto comment with the public configuration key.
- Regenerate Contracts and all client generated trees once; run codegen and all affected suites.
- Verify x86 Worker build and Worker.Tests on windev; record SHA/counts here.
Batch-L verification (2026-08-25): pwsh scripts/check-codegen.ps1 passed all
four descriptor/C#/Rust/Go/Python freshness checks, and Java
checkGeneratedClean passed. The exact portable alarm/contract/descriptor
filter passed 77/77; NonWindows.slnx built with 0 warnings / 0 errors;
the .NET, Go, Python, Rust, and Java client suites were green (respectively
134 passed / 1 live skip, both Go packages, 169 passed / 1 opt-in TLS
skip, 108 passed, and 132 passed). Windev test mode at
986c6c0ce4f02c62b4f59ec44780de5af6d291b8 built the x86/net48 Worker with
0 warnings / 0 errors and passed Worker.Tests 529 passed / 11 opt-in
skips / 0 failed. Feature/proto commit: 484028e; Batch-J x86 compile
follow-up: 986c6c0.
M — Windows gateway CI
- TST-35: add the serialized net10 gateway suite to windev
livemode. - Update
docs/GatewayTesting.mdandscripts/ci/README.mdwith order/failure semantics. - Execute
livemode on windev and record Worker, gateway, full-slnx, and live-smoke evidence here.
Batch-M verification (2026-08-25): windev live mode at exact commit
cc143b52cf04be0b2f08350922a987b2e250bc1d completed the serialized sequence in
4m45s with remote exit code 0. The x86/net48 Worker build succeeded with 0
warnings / 0 errors in 22.59 s; Worker.Tests passed 529, skipped 11
opt-in probes, and failed 0; the full Windows slnx build succeeded with 0
warnings / 0 errors in 43.24 s; the net10 gateway suite passed 1193/1193
in 53 s; and the live-MXAccess smoke passed 8/8 in 1m46s. TST-35 commit:
cc143b5.
N — integration and release
- Run
git diff --check, codegen, client-version, README, NonWindows build, and full gateway suite gates. - Run all five client suites on the final candidate.
- Run final windev
livegate at the exact candidate SHA. - Merge/push the verified continuation to
main; wait for green CI. - Re-query all package coordinates and Go tag immediately before publish; abort on collision.
- Publish .NET Client + Contracts 0.2.1, Python 0.2.1, Rust 0.2.1, Java 0.2.2.
- Create/push
clients/go/v0.2.1at the exact release commit. - Verify every registry coordinate and Go module/tag, update
docs/ClientPackaging.md, and record immutable release evidence here.
Batch-N portable verification (2026-08-25): git diff --check, codegen freshness,
client-version freshness, and the generated README check all passed without changing
the worktree. NonWindows.slnx built with 0 warnings / 0 errors; the gateway
suite passed 1193/1193, and the portable integration suite passed 5 with
19 live-only skips. The final .NET, Go, Python, Rust, and Java client gates were
green (respectively 134 passed / 1 live skip, all Go packages built/tested with
clean gofmt, 169 passed / 1 opt-in TLS skip from a clean virtual environment,
108 passed plus clean cargo fmt/Clippy, and 132 passed / 0 failed with the
generated Java tree unchanged).
Batch-N integration/release verification (2026-08-25): main was integrated and
released at exact commit 5776021970cbbe59813ba57579abe00d9fc61a46; Gitea CI
run 783 concluded success. Windev live mode at that SHA built the x86/net48
Worker with 0 warnings / 0 errors, passed Worker.Tests 529 passed / 11
opt-in skips / 0 failed, built the full Windows solution with 0 warnings / 0
errors, passed the Windows gateway suite 1193/1193, and passed the live
MXAccess smoke 8/8. One preceding full-suite attempt hit a transient fake-worker
disconnect in the reconnect/replay test; the test then passed 50/50 isolated
macOS runs and 20/20 isolated windev runs before the clean full-gate pass.
Immediately before publication, all five package coordinates returned HTTP 404
and clients/go/v0.2.1 was absent locally/remotely. The published coordinates are
NuGet ZB.MOM.WW.MxGateway.Client 0.2.1 and
ZB.MOM.WW.MxGateway.Contracts 0.2.1, PyPI
zb-mom-ww-mxaccess-gateway-client 0.2.1, Cargo
zb-mom-ww-mxgateway-client 0.2.1, and Maven
com.zb.mom.ww.mxgateway:zb-mom-ww-mxgateway-client 0.2.2. Each exact Gitea
package API coordinate returned HTTP 200 after publication. Annotated Go tag
clients/go/v0.2.1 resolves locally, remotely, and through go list -m to
5776021970cbbe59813ba57579abe00d9fc61a46.