f4919ba97c
Six domain reports + overall synthesis. All 47 cycle-2 Done claims verified at HEAD with zero false Dones and zero regressions; 34 new findings (0 Critical, 0 High, 4 Medium, 25 Low, 5 Info): GWC-31..38, WRK-32..34, IPC-33..39, SEC-37..41, CLI-46..50, TST-31..36.
105 lines
26 KiB
Markdown
105 lines
26 KiB
Markdown
# Testing, Documentation & Underdeveloped Areas — Re-Review (cycle 3)
|
||
|
||
- **Date:** 2026-08-19
|
||
- **Commit:** `8b3e3b3` (`main`, "Merge feat/sweep-reread-tag-summary…")
|
||
- **Baseline:** prior report `archreview/2026-07-12/60-testing-docs-gaps.md` @ `4f5371f` (2026-07-12); ~288 commits since.
|
||
- **Method:** macOS static review — reading only, no builds, no test runs, no remote hosts. One read-only script executed (`python3 code-reviews/regen-readme.py --check`, sanctioned by REVIEW-PROCESS.md). All paths relative to `/Users/dohertj2/Desktop/MxAccessGateway`.
|
||
|
||
## Prior-finding verification
|
||
|
||
### Cycle-2 findings (TST-25..30)
|
||
|
||
| ID | Claimed status | Verified? | Evidence (file:line) | Notes |
|
||
|----|----------------|-----------|----------------------|-------|
|
||
| TST-25 | Done | **Yes** | `.gitea/workflows/ci.yml:144-165` (`windows-x86` per-push job, Linux runner → SSH to windev, exit-code propagation) and `:167-201` (`nightly-windev`, `if: github.event_name == 'schedule'`, `run-windev-ci.sh live`, on-failure Gitea-issue step); `scripts/ci/run-windev-ci.sh` (SHA-shape validation `:46-49`, base64 key decode `:70-78`, bootstrap holds the worktree lock `:91-119`); `scripts/ci/windev-worker-ci.ps1` (lock reuse via `MXGW_CI_LOCK_HELD` `:77-94`, re-checkout under lock + HEAD verification `:99-111`, cumulative build/test/live modes `:119-139`) | The whole design shipped as specified, including the acceptance-check hardening: the CI key is stored base64 single-line so Gitea's line-oriented masker redacts it (`ci.yml:156-159`), the bootstrap fetch/checkout races were serialized under the mkdir lock, and the nightly failure issue carries a browser-reachable link via `PUBLIC_SERVER_URL` (`ci.yml:174-181`, Check 6 closed 2026-08-10 per `docs/runbooks/TST-30-second-ci-runner.md`). Ground truth from the operator confirms the tier runs green. |
|
||
| TST-26 | Done | **Yes** | `docs/GatewayTesting.md:624-657` describes exactly the four jobs that exist (`portable`, `java`, `windows-x86`, `nightly-windev`) incl. the "red can mean the tier is down" triage (`:649-652`); `scripts/check-codegen.ps1:26-27` now attributes the x86 guard to "the SSH-driven `windows-x86` CI job"; `ci.yml:14-18` cron comment matches what the schedule runs | Guard attribution is correct both ways: primary = Check 2 regeneration diff in `portable`, secondary = the windows-x86 net48 compile (`GatewayTesting.md:699-703`). No named job is missing and no phantom job survives. |
|
||
| TST-27 | Done | **Yes** | `docs/GatewayConfiguration.md:195` — the `ShowTagValues` row now describes all three seams (events-hub mirror, alarms hub, `/browse` live values incl. the successful-read-only nuance from `e50ec49`), the clone-don't-mutate guarantee, and the ACL layering | "Reserved" is gone; the row was rewritten a second time when TST-16's residuals shipped (2026-08-17), so it documents strictly more than the finding asked. |
|
||
| TST-28 | Done | **Yes** | `src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerClientTests.cs:46` — `StartAsync_SendsGatewayHelloWithConfiguredMaxFrameBytes(int maxMessageBytes)` theory, in the CI-run portable suite | Exactly the designed test (default + override), pinning the gateway half of the IPC-02 negotiation on Linux CI. |
|
||
| TST-29 | Done | **Yes** | `oldtasks.md` absent from the tree; the five `*-docs-*.md` root artifacts absent; `docs/DesignDecisions.md:264` "Session-Resilience Epic Scope" carries the Phase-5 deferred-not-planned record and `:295` the "`EnableOrphanReattach` does not exist and must not be referenced" rule; CLAUDE.md's invariant paragraph points at DesignDecisions | Governance record migrated intact before deletion, exactly per the design. Residual: `stillpending.md` (also a TST-14 root artifact) still contradicts the migrated record — see new finding TST-33. |
|
||
| TST-30 | Done | **Yes, with one pending operator action** | `docs/runbooks/TST-30-second-ci-runner.md:1-13` (Executed 2026-08-07: `gitea-runner-2`, id 5, capacity 2, `container.network: traefik`, token from a `0600` file mount; concurrency verified across three simultaneous runs) plus the honest correction that the per-repo runners endpoint legitimately returns 0 (instance-level registration); `docs/GatewayTesting.md:659-685` documents the shared-capacity/no-cancel reality and the `run-windev-ci.sh` bypass | The runner exists and the docs match the executed state. The **follow-up it surfaced is still open**: the shared instance registration token (world-readable ~5 months, proven still live by a probe registration) needs a web-UI reset — promoted to new finding TST-32 so it stops living only inside a closed finding's runbook. |
|
||
|
||
**Done claims that failed verification: none.** All six hold with file:line evidence; TST-30 carries the one explicitly-tracked operator residual (TST-32 below).
|
||
|
||
### Cycle-1 leftovers still tracked open (spot-verified at HEAD)
|
||
|
||
| ID | Tracker status | State at HEAD |
|
||
|----|----------------|---------------|
|
||
| TST-05 | Partially done | **Residual confirmed open.** The live suite is 8 `[LiveMxAccessFact]`s (`WorkerLiveMxAccessSmokeTests.cs:34-920`) with zero references to `Ping`/`GetSessionState`/`GetWorkerInfo`/`DrainEvents`/`ShutdownWorker`; the gap is honestly documented at `docs/GatewayTesting.md:90-95`. The scheduling half stays closed (nightly-windev runs the suite). The two control-command live facts specified in `archreview/remediation/60-testing-docs-gaps.md` remain unauthored (windev-only work). |
|
||
| TST-06 | Not started | **Materially narrowed, tracker stale.** `Tests/Gateway/Dashboard/DashboardLiveDataServiceTests.cs`, `EventsHubTests.cs`, `EventsHubViewerRegistryTests.cs`, `AlarmsHubPublisherTests.cs`, `SessionDetailsPageEventAclTests.cs` all exist now (mostly landed with SEC-25/TST-16 closeouts and the in-process dashboard-feed work). The cycle-1 row deserves a re-audit-and-close pass rather than "Not started". |
|
||
| TST-07 | Not started | Partially addressed: the `WorkerClientTests` 150 ms sleep-then-negative-assert is gone; `SessionManagerTests.cs:491` still has a real-clock `Task.Delay(50)`. |
|
||
| TST-09 | Not started | Partially addressed: `GatewayApplication.cs:117-124` now registers `AuthStoreHealthCheck` **and** `SessionHealthCheck` (the `/health/active` probe with off-repo consumers). Still no Galaxy SQL / LDAP / worker-executable checks. |
|
||
| TST-10 | Not started | Still no `docs/Deployment.md`; partial mitigation via `docs/runbooks/IdentifyingADeployedBuild.md` and the SEC-36 rotation runbook, but deploy/upgrade mechanics (dated `Server-YYYYMMDD` dirs, NSSM repoint, env-var config) still live in operator memory notes, and the 2026-08-09 credential-store-renamed-away outage (`docs/GatewayConfiguration.md:100`) shows the cost. |
|
||
| TST-14 | Not started | Mostly discharged by TST-29 (oldtasks + the five untracked artifacts gone). Remaining root-file triage: `stillpending.md` (now the stale one — see TST-33) and `A2-galaxyrepository-adoption-handoff.md` (carries a current "ADOPTED" banner; acceptable as a handoff record). |
|
||
| TST-17 | Not started | **Materially changed — row needs refresh by the worker domain.** `WnWrapAlarmConsumer.cs:309-327` now passes `szDomainName`/`szOprFullName` into the COM call (the `_ = ackOperatorDomain` discard is gone), and the 2026-08 probe cycle recorded the vendor 8-arg leg as "unavailable by configuration" with evidence (`docs/AlarmProbeFindings.md`, commits `d1ae43d`, `540a118`). Whether a caller-visible degrade signal exists is the worker reviewer's call, but "silent drop, unchanged" is no longer an accurate row. |
|
||
| TST-18 | Not started | Confirmed open — no `*HostedService*` tests under `src/ZB.MOM.WW.MxGateway.Tests`. |
|
||
| TST-19 | Not started | Confirmed open — `FakeWorkerHarness.cs` still has no lockstep note / `WorkerPipeSession` pointer. Mitigation since: the harness's canned control replies are no longer the *only* automation (windows-x86 runs the real worker suite per push), but the drift risk the finding names is intact. |
|
||
| TST-20 | Not started | Confirmed open — `run-client-e2e-tests.ps1:48` `DrainEveryTags = 15` workaround intact. |
|
||
| TST-21 | Not started | Confirmed open — `Server/appsettings.json:10` daily rolling file sink, no size cap / retained-count. |
|
||
| TST-22 | Not started | Confirmed open — the shape block (`docs/GatewayConfiguration.md:12-88`) is maintained (gained `GroupToTag`, `UntaggedSessionVisibility`, `RecentFaultLimit`/`RecentSessionLimit`) but still omits documented keys (`DisableLogin`, `AutoLoginUser`, `CookieName`, `Tls`, `Ldap`, `Security`, `Alarms:Fallback`, `Worker:WriteCompletionWaitMilliseconds`, …). The option **tables** below it are complete and current — the omissions are only in the illustrative block. |
|
||
|
||
## New-code / new-docs review since `4f5371f`
|
||
|
||
**CI workflow evolution — verified sound.** `ci.yml` at HEAD is a four-job pipeline whose comments are accurate down to the failure semantics. Details worth recording: the portable job now runs the .NET client *tests* (TST-24 wire tests included, `ci.yml:83-90`), installs pwsh and the pinned Check-4 generators explicitly (`:58-72`), and pins protoc 34.1; the java job's `git diff --exit-code` is the true drift gate after IPC-24 deleted the churn-revert; `run-windev-ci.sh` validates `CI_SHA` shape before it reaches a remote shell (`:46-49`), never echoes the key, and pins host keys from the committed `windev.known_hosts`; `windev-worker-ci.ps1` re-checks-out under the lock, verifies `HEAD == Sha`, `git clean -fdx -e ci.log`, and is deliberately PS5.1-safe. The nightly's issue-on-failure path uses the runner-resolvable `github.server_url` for the API call but `PUBLIC_SERVER_URL` for the human link — the exact defect Check 6 caught, fixed in `30c92e8`.
|
||
|
||
**check-codegen.ps1 —** now four checks with the Check 3 reverse sweep (`:98-103`, canonical proto missing a vendored copy fails — the drift class no in-repo build can surface, `711793f`) and Check 4 Windows support (`.exe` banner normalization in the per-client `generate-proto.ps1` probes, `c94c4d4`; PS5.1-safe native-arg quoting, `8ae0c2f`). The header comment (`:2-27`) is accurate.
|
||
|
||
**fca978d marker sweep → f82dac1 restoration — assessed complete on sampled evidence.** The sweep (2026-07-07, 203 files) deleted ~1,100 prose-bearing comment lines alongside the tracking markers; the 2026-08-18 re-read narrowed those to 816 residual lines, judged each, and restored 17 collateral deletions across 10 files (`f82dac1`, merged `8b3e3b3`). Spot-checks of four substantive deletions **outside** the restored set all found surviving equivalents at HEAD: the `SessionEventDistributor` mode-vs-count FailFast race rationale survives in `docs/Sessions.md:206` (including the "fixed mode rather than a live subscriber-count snapshot" decision) and `docs/GatewayConfiguration.md:159`; the `MxAccessStaSession` off-STA-deadlock affinity-guard rationale survives in `AlarmCommandHandler.cs:68-80`; the subtag source's own-COM-object isolation rationale survives in `LmxSubtagAlarmSource.cs` class remarks; the watchdog `HeartbeatStuckCeiling` rationale survives in `WorkerPipeSessionOptions.cs:35+`. No residual collateral damage found. The companion `d3ac527` audit (re-verifying 20 doc-only `Server-0xx` resolutions, re-fixing the two the sweep had silently reverted — Server-040 among them) closes the loop on the sweep's other damage class. This is a model recovery process.
|
||
|
||
**Doc currency at HEAD — high.** Sampled claims all match code: `docs/Sessions.md:17` pipe-name prose matches `SessionManager.cs:536` (`mxgw-{pid}-{uid}`, with the sun_path rationale); `docs/Sessions.md:248` owner-scoped attach matches `EventStreamService`; `docs/GatewayConfiguration.md` documents the new `WriteCompletionWaitMilliseconds` (`:121`, with the OtOpcUa 2 s budget interaction), `EventQueueCapacity` (`:122`), alarm poll/fetch ceilings incl. truncation semantics (`:435-436`), and the `Fallback` block (`:448-451`); `docs/GatewayTesting.md` is the standout — the windev sections (`:488-622`) record the 879 baseline, the two "environmental" failures that were test bugs, the load-sensitivity list, and a first-class post-mortem of the zero-buffer-pipe testhost hang with the structural fixes (`TestNamedPipe.CreateServer`, bounded `PipePair.WriteAsync`). `docs/Authentication.md` was made runnable-as-written (`2b2748b`); `docs/AlarmProbeFindings.md` states the probe questions and their evidence honestly (ack leg unavailable-by-configuration, GUID leg still assumed). `python3 code-reviews/regen-readme.py --check` passes at HEAD ("up to date and consistent").
|
||
|
||
**New-feature test placement — correct layers.** Alarm truncation / `snapshot_status`: proto-level flag plumbed with direct tests (`b9fb0dd` atomic snapshot+truncation read), gateway feed frame (`AlarmTruncationSignalTests.cs`), dashboard banner (`AlarmsPageTruncationBannerTests.cs` incl. the mid-truncation attach case, `f57a6ae`), and all five clients regenerated with render coverage (`4d4f443`). SEC-25 tag ACL: `DashboardSessionAclTests`, both subscribe seams covered (`EventsHubTests`, `SessionDetailsPageEventAclTests`), decision-table corners pinned (`7ec0b35`), plus live-LDAP ACL coverage (`1d8a4a6`). Drain cluster (WRK-21/IPC-23/IPC-30): worker-side byte-budget tests run per-push via windows-x86; the gateway side keeps the drain-to-empty walk inside the pipe-harness envelope (`a256560`). Write-completion correlation: worker executor tests (`b0e2b8b`, `c867aca`) plus gateway-side config plumb tests (`GatewayOptionsTests`, `WorkerProcessLauncherTests`). In-process wire tests (TST-24) exist for all five clients and run in CI (`docs/GatewayTesting.md:280-321`).
|
||
|
||
## New findings
|
||
|
||
### TST-31 — `glauth.md`'s pre-provisioned-users table contradicts the directory, and its wrong credential propagated into the live-test surface — **Medium** · documentation currency / test fixtures (promotes NEXT-10)
|
||
|
||
- **Files:** `glauth.md:55` (ReadOnly gid `5501` vs actual `5601`), `:65-78` (pre-provisioned users table: `readonly`/`readonly123` does not exist in `scadaproj/infra/glauth/config.toml`; `admin` carries the standard dev password, not `admin123`), `:124` (`Password: admin123` in a worked example); propagation: `docs/GatewayTesting.md:119` (`MXGATEWAY_LIVE_MXACCESS_WRITE_SECURED_PASSWORD` default `admin123`) and `src/ZB.MOM.WW.MxGateway.IntegrationTests/WorkerLiveMxAccessSmokeTests.cs:1432` (`?? "admin123"`, with `:517` attributing the identity to the GLAuth-bridged ArchestrA `admin`/`admin123`).
|
||
- **Description:** Carried over from `archreview/2026-07-12/remediation/90-candidate-findings-next-cycle.md` NEXT-10, which was deliberately deferred pending the OPC-UA group-taxonomy sweep and is still fully present at HEAD. The table was already the proven root cause of one defect (the NEXT-06 live-LDAP fixture drift, fixed 2026-08-07 — the *fixtures* were realigned but the table that misled them was not). The remaining propagation has a quiet coverage cost: the nightly live smoke's `WriteSecured` parity test authenticates with the defaulted `admin`/`admin123`, and because `AuthenticateUser` legitimately returns a real MXAccess *failure* reply on bad credentials (parity, not `InvalidRequest`), a wrong default does not fail the test — it silently degrades the WriteSecured leg from "authenticated round-trip" to "failure-reply shape check" every night. A reader also cannot tell which half of `glauth.md` to trust, since its dashboard section is correct.
|
||
- **Recommendation:** Reconcile the table against `scadaproj/infra/glauth/config.toml` as one unit with the OPC-UA group taxonomy (the reason it was deferred), or — if that sweep stays parked — fix the two provably-wrong rows and the gid now and leave the taxonomy note. In the same change, re-derive the `MXGATEWAY_LIVE_MXACCESS_WRITE_SECURED_PASSWORD` default and the `WorkerLiveMxAccessSmokeTests` literal from whatever the rig's ArchestrA-bridged identity actually is, and make the live test log (not assert) whether `AuthenticateUser` succeeded, so a credential regression in the nightly is at least visible.
|
||
|
||
### TST-32 — The shared Gitea runner registration token (world-readable for ~5 months, proven live) still awaits its web-UI reset — **Medium** · CI/ops security
|
||
|
||
- **Files:** `docs/runbooks/TST-30-second-ci-runner.md:33-42` ("Follow-up 2026-08-07 — token hygiene"); `archreview/2026-07-12/remediation/90-candidate-findings-next-cycle.md:24` (the pending-operator-action row).
|
||
- **Description:** Both CI runners share one **instance-scope** registration token that sat world-readable in `/opt/gitea/docker-compose.yml` for roughly five months and is **still valid** — a probe registered runner id 6 with it and then deleted it. Host hygiene is done (token now a `0600` file mount, compose + backups locked down), but hygiene does not retire the credential: anyone who read it can register a rogue runner that receives this repo's jobs, including the `WINDEV_SSH_KEY` secret that grants shell on windev. Gitea 1.26.4 exposes no rotation via CLI or API (both are get-or-create), so the reset must be done in the admin web UI, then `/opt/gitea/runner_token` refreshed and the two token-bearing compose backups shredded. This has been a documented "pending operator action" since 2026-08-07 with no tracked finding forcing it to a close — precisely the state in which such actions rot.
|
||
- **Recommendation:** Execute the reset per the runbook (minutes of work; re-registration of the two runners with the new token is the only follow-on). Track it here rather than only in a closed finding's runbook, and after the reset append the dated "Executed" note the runbook's own convention expects.
|
||
|
||
### TST-33 — `stillpending.md` has drifted into self-contradiction and now overstates what is pending — **Low** · repo hygiene / documentation currency
|
||
|
||
- **Files:** `stillpending.md:54` (reconnect "not safe to rely on end-to-end yet" — Tasks 13–15 shipped and were verified as cycle-2 TST-01/TST-02 with all-five-client consumers); `:56` (Phase 5 orphan reattach "**planned** (epic Phase 5, not started)" — directly contradicts the governance record TST-29 migrated to `docs/DesignDecisions.md:264-295`, which says **deferred, not planned**, and CLAUDE.md's invariant); `:111` ("WorkerLiveMxAccessSmokeTests.cs (6 `[LiveMxAccessFact]`)" — there are 8); `:118` ("Cross-language client↔gateway wire behavior — no per-client integration unit tests… All client wire behavior is unverified in default unit runs" — false since TST-24 closed 2026-08-10: all five clients have real-transport wire tests running in CI); `:150` (§8: per-session-ACL "still scheduled… not yet started") vs `:65` (§2: the same item "RESOLVED (2026-08-17)") — the file contradicts itself.
|
||
- **Description:** The file is not a frozen snapshot — it has been annotated through 2026-08-17 — so readers reasonably treat it as live, and it is one of the two remaining root-level triage artifacts from TST-14. Its most dangerous staleness is `:56`: it re-asserts the "planned Phase 5 / `EnableOrphanReattach`" framing that TST-04/TST-29 spent two cycles extinguishing, in the exact file a future contributor greps when asking "what's still pending".
|
||
- **Recommendation:** One currency pass: fix the five spots above (§2 reconnect → shipped; §2 Phase 5 → deferred-not-planned, pointing at DesignDecisions; §5 counts and the wire-test bullet; §8 ACL row → resolved, matching §2). Then either commit to keeping it current or stamp it "historical snapshot — see archreview trackers for live status" at the top, which is the cheaper honest option.
|
||
|
||
### TST-34 — The code-reviews README consistency check is "the intended hook for CI" but is wired into no CI job — **Low** · CI
|
||
|
||
- **Files:** `REVIEW-PROCESS.md:124-131` ("`regen-readme.py --check` exits non-zero if README.md is stale… The PowerShell wrapper `scripts/check-code-reviews-readme.ps1` runs that check and is the intended hook for CI or a pre-commit step"); `.gitea/workflows/ci.yml` (no reference to either script in any job); also `REVIEW-PROCESS.md:130-131` (the "bare `python3` alias resolves to the Windows Store stub — use `python`" note is Windows-only advice presented unconditionally; on the macOS tree `python` may be absent and `python3` is correct).
|
||
- **Description:** The check passes at HEAD (verified this review), and the repo's process doc names CI as its intended home, but 13 months of CI evolution never picked it up — so a stale `code-reviews/README.md` or an inconsistent open-findings count merges silently until the next human runs the script. The portable job already installs Python 3.12, so the cost is one step.
|
||
- **Recommendation:** Add a `Code-reviews README consistency` step to the `portable` job (`python code-reviews/regen-readme.py --check`), and qualify the interpreter note in REVIEW-PROCESS.md as Windows-specific (macOS/Linux: `python3`).
|
||
|
||
### TST-35 — The Windows-host run of the gateway (net10) suite is still manual-only, and its failure class recurred three times in August — **Low** · CI/coverage
|
||
|
||
- **Files:** `docs/GatewayTesting.md:488-498` ("The gateway suite… is not part of the CI Windows tier — `windows-x86` and `nightly-windev` run only the x86 Worker build and `Worker.Tests`. It is still run on windev by hand…"); evidence the class is real: `e2352d1` (two Windows-only gateway test bugs long dismissed as environmental), `bfcf829`/`02baf0c` (zero-buffer Windows pipe wedged the whole suite's testhost), `25f07f8` (SQLite pool sharing-violation on Windows-only cleanup).
|
||
- **Description:** TST-25 restored the Worker tier, but the *gateway* suite's Windows-specific divergences (platform crypto formatting, Windows pipe buffer semantics, file-sharing rules) surface only when someone remembers the manual windev run. Every one of the three August finds was a real defect in test code that CI could have caught nightly; the suite's idle wall time on windev is ~31 s, and the nightly job already builds the full slnx there — the marginal cost of running the suite is small. Severity Low, not Medium: the same 879 tests run on Linux per push, the manual procedure is well documented with a current baseline, and known load-sensitivity (the suite flakes when run concurrently with the x86 tier, `GatewayTesting.md:530-555`) means naive stacking into the nightly needs care.
|
||
- **Recommendation:** Extend `windev-worker-ci.ps1`'s `live` mode with a `dotnet test src/ZB.MOM.WW.MxGateway.Tests` step **after** the Worker tier finishes (the lock already serializes the box, which addresses the documented load sensitivity), and record the 879 expectation in the script log. If nightly wall time becomes a concern, a weekly cadence still beats "when someone remembers".
|
||
|
||
### TST-36 — Docs and CLAUDE.md refer to the "`event` scope"; the canonical scope string is `events:read` — **Low** · documentation
|
||
|
||
- **Files:** `CLAUDE.md:160` (twice: "Possessing the `event` scope…", "an `event`-scoped key"); `docs/Sessions.md:248` (twice); `docs/DesignDecisions.md:93`; `docs/Grpc.md:103` (mitigated — it parenthesizes `GatewayScopes.EventsRead`); canonical constants in `src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/GatewayScopes.cs:10` (`"events:read"`).
|
||
- **Description:** `f2a422b` ("canonical scope strings in the two remaining stale lists") fixed the scope *lists* but left the `event`-scope shorthand in running prose. There is no `event` scope: an operator who takes the prose literally and runs `apikey create-key --scopes event` mints a key that cannot stream. CLAUDE.md even uses the correct `events:read` forty lines earlier (`:158`), so the same file teaches both spellings.
|
||
- **Recommendation:** Mechanical sweep: replace "`event` scope" with "`events:read` scope" in the four prose sites (Grpc.md's parenthesized form is acceptable as-is). One grep verifies completion: `git grep -n '\`event\` scope'` over `CLAUDE.md docs/` returns nothing.
|
||
|
||
## Severity roll-up (new findings)
|
||
|
||
| Severity | Count | IDs |
|
||
|---|---|---|
|
||
| High | 0 | — |
|
||
| Medium | 2 | TST-31, TST-32 |
|
||
| Low | 4 | TST-33, TST-34, TST-35, TST-36 |
|
||
|
||
## Still good / preserved
|
||
|
||
- **The windev CI tier is the best piece of infrastructure this domain has reviewed in three cycles.** It shipped exactly per design and then got hardened by its own acceptance checks: the cleartext-key leak was found and fixed by storing the key base64 (with the masking rationale documented in three places), the bootstrap lock race was closed with an explicit `MXGW_CI_LOCK_HELD` handoff, the SHA is shape-validated before it reaches a remote shell, an unreachable windev fails red instead of wedging, and the nightly's failure path was itself tested to failure (Check 6) and fixed. `scripts/ci/README.md` records the bring-up, the acceptance checks with dated outcomes, and the degraded mode.
|
||
- **The codegen guard now covers every generated surface in both directions:** descriptor set, `Contracts/Generated`, Rust vendored protos (including the reverse sweep for never-vendored canonical protos — drift no in-repo build can surface), Go/Python bindings with pinned generators that fail rather than skip when missing, and the Java aggregates via the java job's git-diff gate. Check 4 was additionally made Windows-runnable, so windev regen workflows use the same guard.
|
||
- **The prior cycle's High (TST-25) is not just closed — its unlocks were followed through:** old TST-24 closed with real-transport wire tests in all five clients running in CI, old TST-05's scheduling half closed by the nightly, the EventBurst flake root-caused and deflaked (flush-edge sampling), the two "windev-environmental" failures exposed as test bugs, and the months-old full-suite testhost hang root-caused to a zero-buffer Windows pipe with structural fixes (`TestNamedPipe.CreateServer`, bounded `PipePair.WriteAsync`) plus a first-class post-mortem in `docs/GatewayTesting.md` — the windev baseline now equals macOS at 879.
|
||
- **Documentation discipline visibly recovered from its one big self-inflicted wound.** The fca978d sweep's collateral damage was found by a systematic re-read (816 lines judged, 17 restorations), the doc-only `Server-0xx` resolutions were re-audited with the two regressions re-fixed (`d3ac527`), and every doc-currency spot-check this review ran (Sessions, GatewayConfiguration, GatewayTesting, Authentication, alarm probes, pipe naming, write-completion) matched code at HEAD. The two currency findings this cycle (TST-31, TST-33) are inherited debris, not new drift from the ~288-commit period.
|
||
- **New features landed with tests at the right layers**: alarm truncation is asserted from the worker flag through the proto, the gateway feed frame, the dashboard banner (including mid-truncation attach), and all five client renders; the SEC-25 tag ACL is pinned at both subscribe seams with decision-table corners and live-LDAP coverage; `regen-readme.py --check` passes; `code-reviews/README.md` is consistent with the per-module findings at HEAD.
|