Resolve all high-severity architecture review findings
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# ScadaBridge — architectural / code review (whole system)
|
||||
|
||||
**Date:** 2026-09-09 · **Status:** SECOND-PASS REVIEW REPORT (documentation only; no production code changed)
|
||||
**Date:** 2026-09-09 · **Status:** ALL 13 HIGH FINDINGS COMPLETED (see §9)
|
||||
**Reviewed revision:** `main` @ `c078bc8f`. Its only difference from the first review's
|
||||
`d8229916` is the original findings document; production source/configuration is identical.
|
||||
**Scope:** all 26 `src/` projects, 32 test/support projects, both Docker rig configurations,
|
||||
@@ -13,7 +13,8 @@ rechecked all High source paths, ran build/test/format/package checks, and execu
|
||||
probes. Each area revalidated its existing IDs and searched for additional defects. Source-traced
|
||||
mechanisms, runtime probes, latent risks, and unproven operational impact are distinguished below.
|
||||
This is a focused whole-system review, not a claim that every line or production topology was
|
||||
exercised. No rig rebuild, device writes, failover drill, or remote QA/production inspection ran.
|
||||
exercised. The review phase ran no rig rebuild, device writes, failover drill, or remote QA/production inspection.
|
||||
Sections 1–8 preserve that reviewed baseline; §9 records the subsequent implementation and local rig verification.
|
||||
|
||||
**Second-pass changes:** 11 new findings; UI-3 withdrawn as unsupported; XC-6 merged into CM-5;
|
||||
UI-4/6/7 reclassified as Low hardening gaps. Existing IDs are preserved for traceability. The
|
||||
@@ -36,9 +37,11 @@ references; every mapped gRPC service is behind a fail-closed constant-time inte
|
||||
contract changes since August are additive; all eight migrations are sound and the model snapshot
|
||||
matches. The test suite is broad; fresh execution evidence and its limits are in §7.
|
||||
|
||||
The updated register has **92 unique active findings: 13 High, 33 Medium, 46 Low**.
|
||||
The reviewed baseline contained **92 unique findings: 13 High, 33 Medium, 46 Low**.
|
||||
**Remediation status: all 13 High findings completed; 79 findings remain open (33 Medium, 46 Low).**
|
||||
Completion evidence and limits are recorded in §9.
|
||||
This includes low-priority test/documentation gaps and latent risks, not just reproduced failures.
|
||||
The High-priority findings are:
|
||||
The reviewed High-priority findings were:
|
||||
|
||||
| # | Sev | Finding | Area |
|
||||
|---|---|---|---|
|
||||
@@ -821,3 +824,75 @@ A `pass` is limited to the cited check, not a blanket claim that the component i
|
||||
Add these to the repository's chosen CI system with existing build/test gates; keep formatting
|
||||
cleanup and framework/package migration in separate maintenance work so they do not obscure the
|
||||
correctness/security remediation.
|
||||
|
||||
|
||||
## 9. High-severity remediation completion
|
||||
|
||||
**Completed 2026-09-09. All 13 High findings are resolved and verified.** Implementation
|
||||
started from `8bfe6551` on `codex/resolve-high-review-findings`, with parallel device/runtime,
|
||||
transport, and UI/security agents plus primary-agent integration and independent reviews.
|
||||
The findings above preserve the reviewed baseline; this section supersedes their open status.
|
||||
Medium/Low findings remain outside this remediation unless a change was required for a High fix.
|
||||
|
||||
| Finding | Status | Implementation / verification |
|
||||
|---|---|---|
|
||||
| DC-1 | **Completed** | Owner-checked PostStop unsubscribe and DeathWatch release dead demand. Shared/replacement demand survives old-owner termination and in-flight completion. Deterministic lifecycle/race regressions pass. |
|
||||
| DC-2 | **Completed** | Initial subscribe and resolution exclude each other’s in-flight tags; equal live handles are never released. Mx reverse-map removal is atomic and identity-checked. Adapter and controlled-race regressions pass. |
|
||||
| DC-3 | **Completed** | Connecting/reconnecting reject single and batch writes immediately; subscription retries are deduplicated by owner/source. No stale setpoint replay after reconnect. Full DCL suite: 365 passed. |
|
||||
| DC-12 | **Completed** | OPC snapshot start/entries/end retain source and epoch; NativeAlarmActor ignores unrelated/duplicate ends and drops partial snapshots on disconnect. Legacy Mx framing remains supported. Actor tests prove standing-alarm preservation; live two-boiler feed verifies distinct wire scopes and epochs. |
|
||||
| CM-1 | **Completed** | Servers and all six application channels use explicit 32 MiB send/receive limits. Protobuf-exact 2 MiB audit budgets cover pending/cached drain and reconciliation paging. Both 256×64 KiB lanes drain without loss; real gRPC 17 MiB response passes. Oversize-row policy is explicit below. |
|
||||
| CM-9 | **Completed** | Authenticated site identity guards RPC payloads, audit rows and notification status. SQL upsert rejects another site’s stored operation ID, including duplicate-insert retry. Real gRPC denial, outbox ownership and 29 SQL Server lifecycle/ownership tests pass. |
|
||||
| CM-10 | **Completed** | Reads/idempotent ingests may retry; mutations retry only after explicit server pre-dispatch rejection. Ambiguous primary/secondary response loss returns `OUTCOME_UNKNOWN` without replay. Real transport and effect-count tests pass. |
|
||||
| UI-1 | **Completed** | All 16 configuration repository-bypass pages use typed commands. One transaction spans entity saves and final scrubbed audit flush, including generated IDs; cache publication follows commit. Direct instance/area paths retain domain checks within the same boundary. LDAP CRUD and audit-failure rollback regressions pass; deployed browser CRUD passes. |
|
||||
| UI-2 | **Completed** | Passive ping/Blazor validation neither slides cookies nor advances activity. Trusted browser input posts with antiforgery; per-login activity reaches existing circuits. Stable NameIdentifier preserves antiforgery across role refresh. Real HTTP fake-clock tests and deployed trusted/synthetic-input browser gate pass. |
|
||||
| UI-13 | **Completed** | Circuit authority remaps stored groups in fresh scopes; mutations require current roles and persisted-site scope. API keys, reports, failover, parked messages, instances and Topology recheck before dispatch. Revoked-scope and authorized-positive tests pass, including nonnumeric site identifiers. Explicit server-configured auto-login retains synthetic grants under its existing startup guard. |
|
||||
| SR-1 | **Completed** | Attribute get/set/wait/batch continuations use `ConfigureAwait(false)`. Saturated two-worker synchronous read/write regressions pass without watchdog assistance; wait/trace regression coverage remains green. |
|
||||
| SR-11 | **Completed** | Sync/async transaction and command connection/transaction readback retain auditing wrappers. SQLite regressions prove persisted writes and exactly one audit through each former escape. |
|
||||
| MG-1 | **Completed** | Trust gate denies Unsafe, RuntimeHelpers and Runtime.Loader, including alias/static imports, while preserving async and CallerMemberName. ScriptAnalysis suite: 81 passed. |
|
||||
|
||||
### Final verification
|
||||
|
||||
| Gate | Result / evidence |
|
||||
|---|---|
|
||||
| Final solution build | `dotnet build ZB.MOM.WW.ScadaBridge.slnx --no-restore`: **0 warnings, 0 errors**. `/tmp/high-final-build3.log` |
|
||||
| Selected full solution | `dotnet test ZB.MOM.WW.ScadaBridge.slnx --no-build --no-restore --filter 'FullyQualifiedName!~PlaywrightTests' --logger trx --results-directory /tmp/scadabridge-high-final-green`: **9,310 passed, 0 failed, 0 skipped**; exit 0. `/tmp/high-final-tests2.log` |
|
||||
| Final UI follow-up | After the final auto-login compatibility fix: **1,392 passed, 0 failed, 0 skipped** in the full CentralUI suite. This reruns the 1,391 UI cases included above plus the new regression; counts are not additive. `/tmp/high-ui-final.log` |
|
||||
| Deployed browser | LDAP create/edit/delete round trip and trusted-input/passive-input/antiforgery/throttle scenario: **2 passed, 0 failed, 0 skipped**. `/tmp/high-browser-final.log` |
|
||||
| Independent reviews | Runtime/trust, transport/ownership, and UI transaction/authorization reviews passed after corrections; final auto-login guard follow-up also passed. `/tmp/scadabridge-ui-independent-review.md` |
|
||||
| Local rig | Final image `sha256:b9d6b60ab77093ee537470992fb891f78cc9888170d290021855c902c0115eb6` on **all eight nodes**. All ready (200), one active per pair (200) and four standbys (503), two members per pair, zero unreachable/restarts, all five central singletons reachable. Site-A replication connected with backlog 0. `/tmp/scadabridge-final-loginfix-postdeploy-health.json` |
|
||||
| Change hygiene | `git diff --check` clean. Canonical original-repository config/log mounts and named data volumes preserved; env2 remains untouched. Component requirements updated with implementation. |
|
||||
|
||||
The local image was built with `bash docker/build.sh` from the implementation worktree, then
|
||||
all eight nodes were recreated using the canonical original repository’s Compose file. This
|
||||
keeps existing configuration, logs and data in place rather than rebinding them to the worktree.
|
||||
No device writes, failover drill, remote deployment, commit or push was performed by this remediation.
|
||||
|
||||
### Regression evidence and limits
|
||||
|
||||
- SR-1/SR-11 reproduced **five failures before** their fixes; the runtime follow-up passed 39
|
||||
targeted tests. MG-1 reproduced five forbidden-call failures while two benign cases passed;
|
||||
all 81 ScriptAnalysis cases pass afterward. Full SiteRuntime: **774 passed**.
|
||||
- CM-1’s 17 MiB response failed at the previous default limit. CM-9’s stored-owner SQL regression
|
||||
failed before its guard. Full Communication **756**, ConfigurationDatabase **411**, AuditLog
|
||||
**396**, Host **590**, and integration **117** tests pass. Two historical Host tests expected
|
||||
blind mutation retry on `Unavailable`; they now model explicit pre-dispatch rejection, with
|
||||
a separate real-transport test proving ambiguous failure never dispatches to the peer.
|
||||
- Device tests control owner death, replacement, shared-tag demand, subscribe/resolve races,
|
||||
disconnected writes and interleaved snapshots. A stale failover test assertion was corrected:
|
||||
backup demand must be restored while an original subscribe remains pending. The full DCL
|
||||
suite subsequently passed. The local two-boiler snapshots were empty; standing-condition
|
||||
preservation is proven by deterministic actor tests, **not by live raised alarms**.
|
||||
- UI revocation and Topology denied-mutation tests reproduced failures before correction.
|
||||
The first LDAP baseline test stopped at an incorrect seeded-row count, so it does **not**
|
||||
establish a before-fix missing-audit reproduction. Corrected real-SQLite CRUD/audit/rollback
|
||||
tests pass. A real HTTP regression found antiforgery failure after role refresh; stable user
|
||||
identity fixed it. The deployed browser found the synthetic auto-login role-loss regression;
|
||||
the explicit trusted-configuration guard passed its red/green test and repeat live CRUD gate.
|
||||
- A single audit row above 2 MiB travels alone up to the 32 MiB wire ceiling. A larger row remains
|
||||
durable/unacknowledged with an explicit operator-action error, without truncation or silent
|
||||
loss. Stored LDAP groups are remapped live; directory group-membership changes still require
|
||||
login. Pre-upgrade cookies without stable NameIdentifier may require a fresh sign-in.
|
||||
- No separate formatter cleanup or framework/package migration was included. The original
|
||||
Medium/Low register and baseline formatting debt remain. The local rig has an existing
|
||||
`zztest-conn-5d93ea81` test connection retrying unreachable `localhost:4840`; healthy cluster
|
||||
readiness does not assert that every configured device endpoint is reachable.
|
||||
|
||||
Reference in New Issue
Block a user