Files
mxaccessgw/archreview/remediation/00-tracking.md
T

30 KiB
Raw Blame History

MxAccessGateway — Remediation Tracking

Master progress tracker for the 2026-07-08 architecture review. Generated 2026-07-09.

Source review: ../00-overall.md · Per-domain remediation designs are linked below and hold the full Finding / Impact / Design / Implementation / Verification for every entry here.

How to use this document

  • Each finding has a stable ID (GWC-01, WRK-01, …) that never changes. Cite it in commits, branches, and PRs (e.g. fix(GWC-01): split alarm feed).
  • The Status column is the single source of truth for progress. Update it in the same change that lands the fix.
  • Do the work in roadmap-tier order (P0 → P1 → P2), respecting the Dep (depends-on) column within a tier.
  • When a fix lands: flip Status to Done, and per the repo rule, update the affected docs in the same commit.

Status legend: Not started · In progress · In review · Done · Won't fix (record why in the domain doc) · N/A (informational / positive observation, no action).

Severity roll-up

Every finding from all six domain reports, including Lows and informational/positive notes (which exceed the headline "106" because the domain docs cover each sub-finding individually).

Domain Doc Critical High Medium Low Info Total
Gateway core 10-gateway-core.md 1 2 7 12 1 23
Worker 20-worker.md 1 6 13 20
Contracts & IPC 30-contracts-ipc.md 1 8 13 22
Security & dashboard 40-security-dashboard.md 12 15 3 30
Clients 50-clients.md 4 13 17 34
Testing, docs & gaps 60-testing-docs-gaps.md 4 13 7 24
Total 1 12 59 77 4 153

Roadmap-tier roll-up

Tiers follow the roadmap in 00-overall.md. Work top-down; within a tier, Dep gives ordering.

Tier Meaning Count Findings
P0 Correctness & safety — before wider rollout 8 GWC-01, GWC-02, GWC-03, WRK-01, CLI-01, CLI-03, TST-02, TST-12
P1 Process & hardening — next few weeks 26 GWC-04, WRK-07, IPC-01, IPC-02, IPC-03, IPC-04, IPC-09, IPC-19, IPC-20, SEC-01, SEC-02, SEC-04, SEC-05, SEC-06, SEC-07, SEC-08, SEC-10, SEC-11, SEC-12, SEC-20, CLI-02, TST-03, TST-05, TST-08
P2 Completeness & polish 39 GWC-06/07/08/14/15, WRK-06/11/12/15, IPC-05/06/07/13/14/15/17/21, SEC-03/09/22/25/30, CLI-04/12/15/16/18/21/26/29, TST-01/04/11/13/14/15/23/24
Not individually in the roadmap (mostly Low/Info) 80 see per-domain registers below

P0 — do first (8)

ID Sev Eff Dep Status Title
GWC-01 Critical M Done Alarm monitor and distributor pump both drain the single worker event channel
GWC-02 High M Done Faulted sessions are never swept (worker + slot pinned up to 30 min)
GWC-03 High S Done Documented sparse-array max-length bound is unimplemented
WRK-01 High M Done Long ReadBulk self-faults as StaHung; all replies then dropped
CLI-01 High M Done Go Session.Events() silently closes stream on 16-slot overflow
CLI-03 High M Done Rust invoke never validates HRESULT / MXSTATUS_PROXY
TST-02 High M TST-04 Done Reconnect owner re-validation not implemented (security control)
TST-12 Medium S Done CLAUDE.md misstates default retention behaviour (defaults are on, not off)

Finding registers by domain

Full design + implementation for each row lives in the linked domain doc under its ID heading.

Gateway core — 10-gateway-core.md

ID Sev Tier Eff Dep Status Title
GWC-01 Critical P0 M Done Alarm monitor and distributor pump both drain the single worker event channel
GWC-02 High P0 M Done Faulted sessions are never swept
GWC-03 High P0 S Done Documented sparse-array max-length bound is unimplemented
GWC-04 Medium P1 M Not started Full event channel stalls the worker read loop behind command replies
GWC-05 Medium S Not started Worker pipe created with no ACL / no CurrentUserOnly
GWC-06 Medium P2 S GWC-07,08 Not started Stopwatch allocated per streamed event
GWC-07 Medium P2 S GWC-06,08 Not started Every mapped event is deep-cloned
GWC-08 Medium P2 M GWC-06,07 Not started Pipe framing allocates per frame and writes twice
GWC-09 Medium M Not started Startup probe is a no-op; its retry pipeline can never retry
GWC-10 Medium S Not started Envelope sequence monotonicity specified but not enforced
GWC-11 Low S Not started _workerClient written under lock but read lock-free
GWC-12 Low S Not started WorkerClient.DisposeAsync not safe against double-dispose
GWC-13 Low M Not started Worker-ready wait is a 25 ms poll loop
GWC-14 Low P2 M Not started Replay ring is a LinkedList with a node alloc per event
GWC-15 Low P2 S Not started Per-event gauge reads ChannelReader.Count every event
GWC-16 Low S Not started Invoke resolves the session twice per command
GWC-17 Low M Not started Sessions layer throws Grpc.Core.RpcException (layering leak)
GWC-18 Low S Not started GatewaySession implements DisposeAsync without IAsyncDisposable
GWC-19 Low S Not started Dead GatewaySession.KillWorker(string) + stale doc
GWC-20 Low S Not started Heartbeat config semantics conflated (send vs check interval)
GWC-21 Low S GWC-04 Not started EventChannelFullModeTimeout / HeartbeatStuckCeiling not configurable
GWC-22 Low S Not started StreamDisconnected always labeled "Detached"
GWC-23 Info N/A MaxEventSubscribersPerSession dead in default single-subscriber mode

Worker — 20-worker.md

ID Sev Tier Eff Dep Status Title
WRK-01 High P0 M Done Long ReadBulk self-faults as StaHung; all replies then dropped
WRK-02 Medium M Not started STA thread death after startup is silent; future work hangs forever
WRK-03 Medium S WRK-02 Not started Commands after shutdown starts are dropped with no reply
WRK-04 Medium M Done Envelope sequence can appear out of order on the wire
WRK-05 Medium M Not started One transient alarm-poll failure kills the whole session
WRK-06 Medium P2 S Not started MXSTATUS_PROXY conversion reflects per field, per event
WRK-07 Medium P1 M WRK-04 Done Documented outbound write priority not implemented
WRK-08 Low S Not started Residual event queue discarded at graceful shutdown, undocumented
WRK-09 Low S Not started No AppDomain.UnhandledException hook
WRK-10 Low S Not started Top-level catch logs exception type but never message
WRK-11 Low P2 S Not started Every accepted event is defensively cloned on enqueue
WRK-12 Low P2 M WRK-04 Not started No event batching per envelope; one flush per event; 25 ms poll
WRK-13 Low S Not started Frame writer allocates a fresh buffer per frame; reader pools
WRK-14 Low M Not started Private-field naming split _camelCase vs camelCase
WRK-15 Low P2 S Not started Doc drift: STA thread name and heartbeat-counter note
WRK-16 Low S Not started Boilerplate duplication in IPC envelope/ctor overloads
WRK-17 Low S Not started Gateway death exits with wrong exit code (6 not 5)
WRK-18 Low S Not started Event-queue overflow exits as generic UnexpectedFailure
WRK-19 Low S Not started Command start/end logging with correlation id absent
WRK-20 Low M WRK-01..04 Not started Test-coverage gaps for the failure modes above

Contracts & IPC — 30-contracts-ipc.md

ID Sev Tier Eff Dep Status Title
IPC-01 High P1 M Done Published client descriptor set 7 weeks stale; nothing enforces freshness
IPC-02 Medium P1 M IPC-03 Done Worker max frame size hard-coded, cannot follow gateway config
IPC-03 Medium P1 M IPC-02 Done gRPC max == pipe max with zero headroom; oversized write faults whole session
IPC-04 Medium P1 S IPC-03 Done DrainEvents max_events=0 packs entire queue into one reply frame
IPC-05 Medium P2 S Not started Redundant deep copies on command and event hot paths
IPC-06 Medium P2 S Not started gateway.md Worker Envelope sketch no longer matches the contract
IPC-07 Medium P2 S Not started docs/Grpc.md says six RPCs; there are seven
IPC-08 Medium M Not started WorkerCancel defined and handled but never sent
IPC-09 Medium P1 M IPC-01 Done Known codegen fragilities have no in-repo guards
IPC-10 Low S Not started Envelope sequence is write-only; monotonicity never validated
IPC-11 Low S Not started No protocol version negotiation despite supported_protocol_version name
IPC-12 Low S Not started Gateway frame writer has no write lock; integrity rests on undocumented invariant
IPC-13 Low P2 S IPC-05 Not started Gateway writer serializes twice and issues two stream writes
IPC-14 Low P2 S IPC-05 Not started Gateway reader allocates fresh array per frame; worker rents from ArrayPool
IPC-15 Low P2 M Not started Worker event delivery 25 ms poll with per-event write+flush, no batching
IPC-16 Low S N/A Correlation id carried twice per reply (Info)
IPC-17 Low P2 S Not started Two docs name the wrong Python generated-output directory
IPC-18 Low S IPC-01 N/A Generated-code hygiene verified good — preserve under change (positive)
IPC-19 Low P1 S IPC-01 Done Generated/-must-be-committed rule for net48 undocumented and unguarded
IPC-20 Low P1 S IPC-01 Done Descriptor -Check byte-compares source-info bytes; protoc-version-sensitive
IPC-21 Low P2 S IPC-06 Not started gateway.md presents unimplemented Session RPC as live
IPC-22 Low S N/A Public error-detail model stops at status codes plus prose (Info)

Security & dashboard — 40-security-dashboard.md

ID Sev Tier Eff Dep Status Title
SEC-01 Medium P1 M Done Windows-absolute default paths become relative files off-Windows
SEC-02 Medium P1 S Done AllowAnonymousLocalhost satisfies AdminOnly, not just Viewer
SEC-03 Medium P2 S Not started Dashboard cookie lost its __Host- prefix; four docs still promise it
SEC-04 Medium P1 S SEC-03 Done DisableLogin has no production guard
SEC-05 Medium P1 M Done Hub bearer tokens irrevocable for 30 min, carried in query string
SEC-06 Medium P1 M Done LDAP plaintext-by-default with a committed service password
SEC-07 Medium P1 S Done QueryActiveAlarmsRequest missing from scope resolver; tests mislabeled
SEC-08 Medium P1 L Done Per-RPC SQLite read + last_used_utc write; no verification cache
SEC-09 Medium P2 S Not started Dashboard design-doc GroupToRole sample now fails startup validation
SEC-10 Medium P1 L Done No API-key expiry
SEC-11 Medium P1 M SEC-08 Done No rate limiting or lockout on either auth surface
SEC-12 Medium P1 M Done Dashboard Close/Kill bypass the canonical audit store
SEC-13 Low S SEC-30 Not started Redactor's credential-command list omits secured-bulk variants
SEC-14 Low S SEC-02,20 Not started /metrics + /health unauthenticated; a metric leaks session ids
SEC-15 Low S Not started GET /logout skips antiforgery
SEC-16 Low S Not started CLI accepts the pepper as a command-line argument
SEC-17 Low S Not started Interceptor does not override client-streaming/duplex handlers
SEC-18 Low S Not started Pepper-unavailable detection matches library message text
SEC-19 Low S Not started Canonical audit store re-issues CREATE TABLE per write/read
SEC-20 Low P1 S Done session_id metric tag is unbounded cardinality
SEC-21 Low M Not started Snapshot publisher works every second regardless of audience
SEC-22 Low P2 M Not started docs/Authentication.md documents types no longer in this repo
SEC-23 Low S SEC-03,04 Not started Validator ignores DisableLogin/AutoLoginUser/RequireHttpsCookie/CookieName
SEC-24 Low S SEC-04 Not started Effective-config view omits the riskiest dashboard flags
SEC-25 Low P2 M SEC-02 Not started Per-session EventsHub ACL is an acknowledged TODO
SEC-26 Low M Not started Audit trail has no retention or pruning
SEC-27 Low S Not started Dashboard GatewayStatus is hardcoded Healthy
SEC-28 Info S N/A Positive security observations (preserve under change)
SEC-29 Info S N/A UI-stack rule verified compliant
SEC-30 Info P2 S SEC-13 Not started Value-logging feature is unwired end-to-end

Clients — 50-clients.md

ID Sev Tier Eff Dep Status Title
CLI-01 High P0 M Done Go Session.Events() silently closes stream on 16-slot overflow
CLI-02 High P1 M Done Rust crate unbuildable outside the repo (build.rs path + --no-verify)
CLI-03 High P0 M Done Rust invoke never validates HRESULT / MXSTATUS_PROXY
CLI-04 High P2 L CLI-15 Not started Typed-command parity gap across all five clients
CLI-05 Medium S Not started .NET session cannot be re-attached to an existing session id
CLI-06 Medium S Not started .NET DisposeAsync blocks/throws on unreachable gateway
CLI-07 Medium S Not started .NET retry budget self-defeats on DeadlineExceeded
CLI-08 Medium S CLI-03 Not started .NET/Go/Java treat any nonzero HRESULT as failure (should be < 0)
CLI-09 Medium M Not started Go has no typed auth-error mapping (Unauthenticated vs PermissionDenied)
CLI-10 Medium M Not started Go uses deprecated grpc.DialContext + grpc.WithBlock()
CLI-11 Medium S Not started Go CLI cannot opt into strict TLS validation
CLI-12 Medium P2 S Not started Java docs still say "Java 21" after the JDK 17 retarget
CLI-13 Medium M Not started Java event-stream buffer hardcoded 16, cancel-on-overflow
CLI-14 Medium S Not started Python default TLS is blocking TOFU pin with silent localhost SNI
CLI-15 Medium P2 M Not started No client handles ReplayGap or offers a reconnect helper
CLI-16 Medium P2 S CLI-12 Not started docs/ClientPackaging.md drifted from Python naming and .NET .slnx
CLI-17 Medium M CLI-14 Not started TLS default posture inconsistent across the five clients
CLI-18 Low P2 S Not started .NET csproj records no <Version>
CLI-19 Low S Not started .NET duplicate InternalsVisibleTo (AssemblyInfo + csproj)
CLI-20 Low S CLI-17 Not started .NET --tls without CA installs accept-all callback
CLI-21 Low P2 S Not started Go ClientVersion = "0.1.0-dev" stale vs tagged releases
CLI-22 Low S Not started Go newCorrelationID swallows crypto/rand error → empty id
CLI-23 Low S Not started Go nil-vs-empty bulk short-circuit asymmetry
CLI-24 Low S Not started Java MxEventStream single-consumer constraint undocumented
CLI-25 Low S Not started Java close() does not await channel termination
CLI-26 Low P2 S Not started Python version.py (0.1.0) ≠ pyproject.toml (0.1.2)
CLI-27 Low S Not started Python Session.close() not concurrency-safe; synthesizes reply
CLI-28 Low S Not started Python circular-import workaround at end of session.py
CLI-29 Low P2 S Not started Rust CLIENT_VERSION (0.1.0-dev) ≠ Cargo.toml (0.1.2)
CLI-30 Low S CLI-04 Not started Rust has no unregister typed helper
CLI-31 Low M Not started Rust CLI is a single 2,699-line main.rs
CLI-32 Low S Not started Client-side bulk caps differ (.NET/Java unbounded)
CLI-33 Low S CLI-01,13 Not started Per-language event backpressure semantics undocumented
CLI-34 Low S Not started Python build//.pytest_cache/ present on disk (untracked)

Testing, docs & gaps — 60-testing-docs-gaps.md

ID Sev Tier Eff Dep Status Title
TST-01 High P2 L TST-04 Not started Reconnect/replay has no e2e test and no client consumer
TST-02 High P0 M TST-04 Done Reconnect owner re-validation not implemented
TST-03 High P1 M In review No CI exists
TST-04 High P2 L Not started Session-resilience epic 16/28 tasks unfinished
TST-05 Medium P1 S TST-03 Not started Real-worker control/COM paths verified opt-in only
TST-06 Medium M Not started Dashboard live-data path untested
TST-07 Medium S Not started Real-clock sleeps with negative assertions are latent flakes
TST-08 Medium P1 M Done Full-suite orphaned testhost processes (does not reproduce; doc de-stale)
TST-09 Medium M Not started Health checks cover only the auth store
TST-10 Medium M Not started Deployment/upgrade undocumented and hand-rolled
TST-11 Medium P2 M Not started No version discipline on server; client versions drift
TST-12 Medium P0 S Done CLAUDE.md misstates default retention behaviour
TST-13 Medium P2 S Not started gateway.md carries stale design-era sketches
TST-14 Medium P2 S Not started Repo-root working artifacts need triage
TST-15 Medium P2 M TST-04 Not started Dashboard EventsHub has no per-session ACL
TST-16 Medium S Not started Dashboard:ShowTagValues is a dead flag
TST-17 Medium S Not started Vendor-gated alarm parity residuals silently lossy
TST-18 Low S Not started Hosted-service wrappers untested
TST-19 Low S Not started Keep FakeWorkerHarness canned replies in lockstep
TST-20 Low S Not started E2E script papers over a real advise-without-consumer sharp edge
TST-21 Low S Not started Log rotation configured but minimal
TST-22 Low S Not started Config-shape JSON block omits documented keys
TST-23 Low P2 S Not started Bidirectional Session RPC never built
TST-24 Low P2 M TST-03 Not started Client wire behaviour has no automated verification

Cross-cutting clusters

Findings the review flagged as one coordinated design pass — sequence them together rather than piecemeal.

  • Size / backpressure topology: IPC-02, IPC-03, IPC-04 + GWC-04 + WRK-12/WRK-07 + CLI-13/CLI-32/CLI-33. Convey MaxMessageBytes to the worker, bound DrainEvents, decouple event backlog from command replies, make client buffer-overflow behavior uniform and loud.
  • Event hot-path performance: GWC-06/07/08/14/15 + WRK-06/11/12/13 + IPC-05/13/14/15. Kill double clones, cache the status converter, batch event frames, pool gateway frame buffers.
  • Silent-failure hardening: GWC-02, WRK-01/02/03, CLI-01, CLI-03. Every death or drop must produce an observable error or fault frame.
  • CI + codegen freshness (unlocks the rest): TST-03 + IPC-01/09/19/20 + CLI-34. Stand up minimal CI so the descriptor/codegen/version guards actually run.
  • Doc-drift sweep: IPC-06/07/17/21 + SEC-03/09/22 + CLI-12/16 + TST-12/13/14 + GWC-19 + WRK-15. Correct load-bearing docs to match shipped behavior.
  • Session-resilience epic: TST-01/02/04/15 + SEC-25 + CLI-15. Finish owner re-validation, client ReplayGap handling, per-session event ACL, and the replay e2e test.

Change log

Date Change
2026-07-09 Initial tracking doc generated from the six domain remediation designs. All 153 findings Not started.
2026-07-09 P0 tier executed via parallel agents. GWC-01/02/03, TST-02, TST-12, CLI-01, CLI-03 → Done (NonWindows build clean; gateway 135/135 targeted tests pass, Go go test ./... + -race pass, Rust test/clippy -D warnings pass).
2026-07-09 Windows full-suite temp-file-lock flakiness (discovered via TST-08) → fixed (commit 11a716a). Two shared-state parallel collisions that macOS never surfaces: (1) self-signed cert generation — SelfSignedCertificateProvider now stages the PFX in a unique <path>.<guid>.tmp (was a fixed name that concurrent/interrupted writers collided on); TestHostEnvironmentInitializer defaults the cert path to a per-process temp dir (so the suite never writes shared ProgramData or fights the deployed service); GatewayTlsBootstrapTests moved to a DisableParallelization collection so its process-global env-var mutation can't bleed into parallel tests. (2) AuthStoreHealthCheckTests — reuse the existing TempDatabaseDirectory helper (SqliteConnection.ClearAllPools() before delete) so the Microsoft.Data.Sqlite pool releases the temp .db handle. windev-verified: 3 consecutive full-suite runs all 793 passed / 2 failed, 0 new orphans (was flaky 24 fails, count-varying). The 2 stable remaining failures are pre-existing windev-environmental (SelfSignedCertificateProviderTests.GenerateCertificate_HasExpectedSansEkuAndValidity machine-name/FQDN SAN assertion; EventStreamServiceTests…TracksAggregateQueueDepth timing) — both pass on macOS, unrelated to this change.
2026-07-09 P1 TST-08 (orphaned testhost) → Done by evidence: the claimed leak does not reproduce. Full ZB.MOM.WW.MxGateway.Tests suite exits cleanly on macOS (0 survivors) and on the Windows dev box (windev, origin/main worktree: 0 new testhost and 0 new ZB.MOM.WW.MxGateway.Worker processes after a full run, isolated by StartTime). Static audit confirms the prime-suspect fixtures already dispose deterministically (WorkerClient cancels its _stopCts + awaits read/write/heartbeat tasks with a 5 s timeout; GatewaySession disposes the client; E2E/harness fixtures use await using). CLAUDE.md "Source Update Workflow" updated to drop the stale "leaves orphaned testhost processes" rationale (filtered runs kept as a speed guideline). Discovered separately (NOT TST-08, still open): Windows-only temp-file-lock flakiness in ~4 full-host test classes — AuthStoreHealthCheckTests (Microsoft.Data.Sqlite connection-pool holds the temp .db handle after await using, so the finally File.Delete throws "used by another process"), GatewayTlsBootstrapTests/DashboardCookieOptionsTests/DashboardHubsRegistrationTests (a gw.pfx.tmp handle from SelfSignedCertificateProvider's fixed-name path+".tmp" atomic-write racing teardown). Count varies run-to-run (24 fails); macOS never sees it (Unix allows deleting open files). Fix = SqliteConnection.ClearAllPools() before temp delete + a unique/guarded .tmp name; verify on windev.
2026-07-09 P1 Wave 3 (size/backpressure topology + write ordering). IPC-02/03/04 + WRK-04/07 → Done. Size negotiation (IPC-02): added GatewayHello.max_frame_bytes (regen Generated/ + clients/proto descriptor refresh with pinned protoc 34.1); the gateway sends its negotiated worker-frame max and the worker adopts it (WorkerFrameProtocolOptions.AdoptNegotiatedMaxMessageBytes, 0 = keep default, >256 MiB rejected) instead of a hard-coded default. Headroom (IPC-03): the pipe frame max now sits EnvelopeOverheadReserveBytes (64 KiB) above the public gRPC cap (default Worker.MaxMessageBytes 16 MiB→16 MiB+64 KiB), cross-validated at startup; WorkerClient pre-checks command envelope size and fails only the offending correlation (ResourceExhausted) instead of SetFaulteding the session. Drain bound (IPC-04): gateway request validator rejects DrainEvents max_events above 10 000; the worker caps each reply at MaxDrainEventsPerReply (10 000) and treats max_events = 0 as that cap, not "drain all". Sequence (WRK-04): WorkerFrameWriter stamps the envelope Sequence at the point of writing under the write lock, so wire order and stamped sequence always agree under concurrent producers. Priority (WRK-07): the worker writer is now a cooperative priority scheduler — control frames (reply/fault/heartbeat/shutdown-ack) drain ahead of event frames; per-frame validation/size rejections fail only that frame, a stream failure fails all queued. Docs same-change (GatewayConfiguration, WorkerFrameProtocol, gateway.md). Verified: macOS NonWindows build clean + validator/grpc tests green; windev x86 worker builds clean, Worker.Tests 352 passed / 0 failed / 11 skipped (incl. new monotonic-sequence, control-before-event priority, negotiated-max, drain-bound tests), gateway Tests 799 passed / 3 failed — all 3 pre-existing windev-environmental (SelfSigned SAN + 2 EventStreamServiceTests timing, both pass in isolation). Commits c8b3a22 (gateway half), ebe6aea (worker half), 309296f (descriptor + default-expectation refresh). GWC-04 (event-channel decoupling) is the remaining Wave 3 item.
2026-07-09 P1 S-misc (dashboard/observability hardening). SEC-02/12/20 → Done. SEC-02: DashboardAuthorizationHandler restricts the loopback + Authentication:Mode=Disabled bypasses to read-only (they satisfy a Viewer-bearing requirement but never AdminOnly), closing the policy-layer gap where anonymous localhost was authorized for Admin surfaces. SEC-12: DashboardSessionAdminService now emits canonical AuditEvents (dashboard-close-session/dashboard-kill-worker, category SessionAdmin) through IAuditWriter on Success/Failure/Denied, so Close/Kill land durable audit rows. SEC-20: dropped the unbounded session_id tag from the exported mxgateway.heartbeats.failed counter. Docs updated same-change (CLAUDE.md, GatewayDashboardDesign.md, Metrics.md). Server build clean (0 warnings); targeted classes 30/30 pass; broader Dashboard+Security+GatewayApplication+Metrics sweep 295/295 pass.
2026-07-09 P1 Wave 2b (security authz+hub). SEC-05/07/08/11 → Done (hub-token lifetime; QueryActiveAlarms scope arm; gateway-side verification cache + last-used coalescing; login rate limit + per-peer gRPC failure limiter). Full-suite checkpoint caught + fixed regressions the earlier narrow SEC-01/04/06 filter missed: cross-platform path-rooting, an IHostEnvironment fallback for minimal DI containers, a test-assembly ASPNETCORE_ENVIRONMENT=Development default, and a platform-correct default-path assertion. Suite: 747 passed / 42 failed, all 42 pre-existing macOS named-pipe-harness env failures.
2026-07-09 P1 Wave 2a (security). SEC-01/04/06 → Done (config path-rooting + production validator guards; Server build clean, validator+hygiene tests 53/53). SEC-10 → Done: the shared ZB.MOM.WW.Auth.ApiKeys gained optional ExpiresUtc (expired keys rejected, auth DB auto-migrates to schema v3) via a concurrent HistorianGateway-remediation session's "G-2"; this repo consumes it by bumping the four Auth.* refs 0.1.2→0.1.4 (commit 197731a). Remaining SEC-10 polish (apikey create --expires + dashboard staleness badge) tracked as a small follow-up.
2026-07-09 P1 Wave 1 (CI + codegen freshness + Rust buildability) via parallel agents. IPC-01/09/19/20, CLI-02 → Done; TST-03 → In review (CI pipeline authored + YAML/layout-validated, but not yet executed on a Gitea runner — proven on first push). Verified on macOS: NonWindows build clean, ClientProtoInputTests 5/5, publish-client-proto-inputs.ps1 -Check exit 0, cargo package (no --no-verify) compiles standalone. Added a vendored-Rust-proto drift guard (Check 3) to check-codegen.ps1 closing the CLI-02 static-copy risk. IPC-09 script guards not executed end-to-end (need pinned python/JRE toolchains); logic is PATH-resolution + version assertion.
2026-07-09 WRK-01 → Done. Verified on Windows host (windev) via an isolated origin/main worktree: worker builds x86 clean, StaRuntimeTests+WorkerPipeSessionTests 33/33 pass. Fixed an xUnit1030 build error (the new worker test used .ConfigureAwait(false) in [Fact] bodies) that the macOS tree could not surface. Also ran GWC-01's Windows-only WorkerClientTests on windev: 18/18 pass (incl. ReadEventsAsync_SecondEnumerator_Throws). All 8 P0 findings now Done. Not yet committed.