Files
lmxopcua/archreview/plans/00-INDEX.md
T
Joseph Doherty 1891f5d6a7 docs(archreview): 2026-07-12 re-review at f6eaa267 + 12 round-2 remediation plans
Re-ran all seven domain reviews at master f6eaa267 (reports rewritten in
place, each with a prior-finding status table): all 4 round-1 Criticals
verified closed; new top findings are the S7 connect-timeout OCE regression
(05/STAB-14), the ResilienceConfig operator-authorable brick (01/S-6), and
a batch of resilience-seam Mediums. 00-OVERALL.md carries the updated
maturity matrix + 12-item action list.

Adds R2-01..R2-12 design/implementation plans (one per action item, house
format + bite-sized TDD task breakdowns + co-located .tasks.json; 193 tasks,
~18-24 dev-days). STATUS.md updated: round-1 topology marked historical
(all merged+pushed), re-review findings table + plan pointers added.
2026-07-12 23:52:23 -04:00

106 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Arch-Review Remediation Plans — Index
> **📊 Remediation status → [`STATUS.MD`](STATUS.md).** Round 1 (2026-07-08 review at `9cad9ed0`) is
> **fully remediated and merged to master** — all 4 Criticals + guards + follow-ups #9#13. The
> 2026-07-12 **re-review at `f6eaa267`** produced an updated 12-item action list
> ([`../00-OVERALL.md`](../00-OVERALL.md)) — see **Round 2 plans** below.
## Round 2 plans (2026-07-12, verified at `f6eaa267`)
One plan per action item in the updated `00-OVERALL.md` prioritized list. Each verifies its findings
against the tree, gives root cause → design (with alternatives) → file-level steps → tests → effort/risk,
and ends with a bite-sized TDD task breakdown (classification / estimate / parallelizability) plus a
co-located `.tasks.json` for resumable execution.
| # | Plan | Findings | Tasks | Effort |
|---|---|---|---|---|
| 1 | [R2-01 S7 fault-path hardening](R2-01-s7-fault-hardening-plan.md) | 05/STAB-14 (High regression), STAB-15, STAB-8 seam note | 13 | S-M (~23 h) |
| 2 | [R2-02 ResilienceConfig hardening](R2-02-resilience-config-hardening-plan.md) | 01/S-6 (High, +2nd brick vector), U-6 (delete), S-8, 04/C-7, S-7 race | 19 | S-M (~1 day) |
| 3 | [R2-03 VT failure quality](R2-03-vt-failure-quality-plan.md) | 02/S13, S12, P7 | 12 | S (~23 h) |
| 4 | [R2-04 Failure-visibility trio](R2-04-failure-visibility-plan.md) | 01/S-1, 06/S-1, 03/S4 (+ scripted-alarm emit gate) | 15 | M (~1.52 d + rig) |
| 5 | [R2-05 AdminUI authz](R2-05-adminui-authz-plan.md) | 04/C-1 (38-page census; ConfigEditor + AuthenticatedRead policies + reflection guard) | 16 | S-M (~2.54 h) |
| 6 | [R2-06 ServerHistorian fail-fast + 0.2.0 DataType](R2-06-serverhistorian-failfast-plan.md) | 06/S-11, U-7 (EnsureTags = upsert ⇒ retype probe), C-7 | 12 | S (~1 h + VPN gate) |
| 7 | [R2-07 Surgical pure-adds](R2-07-surgical-pure-adds-plan.md) | 03/P1 — 3 phases; Phase 1 needs zero new sink members | 15 | L (~46 d) |
| 8 | [R2-08 Async LDAP + HistoryRead](R2-08-ldap-historyread-async-plan.md) | 03/S2 (SDK raises callback under lock — worse than reported), S3 | 14 | M (~1.52 d) |
| 9 | [R2-09 Driver fleet batch](R2-09-driver-fleet-batch-plan.md) | 05/STAB-3/4/5/8/12/16/17, ResolveHost, onError — 6 PR-sized sub-batches | 29 | L (~5.57 d) |
| 10 | [R2-10 Resilience observability](R2-10-resilience-observability-plan.md) | 03/U10 = 04/U-5 — DPS mirror of the driver-health flow (+2 tracker bugs) | 11 | M (~1 day) |
| 11 | [R2-11 TagConfig consolidation](R2-11-tagconfig-consolidation-plan.md) | 01/C-1, P-1 + 05 ReadEnum/Writable — 3-phase strictness rollout | 24 | M (~22.5 d) |
| 12 | [R2-12 Repo hygiene](R2-12-repo-hygiene-plan.md) | 07/U-3/4/5/6, S-3, P-5, C-4/5/6 — destructive steps gated on sign-off | 13 | S (~½ day) |
**Suggested execution order:** 1 → 2 → 3 (small, close everything new-and-sharp from the re-review) →
5 → 4 (the two-round-old Highs) → 6 → 12 (quick wins) → 10 → 11 → 8 → 9 → 7 (large). R2-01/02/03/05/06/12
have no cross-plan dependencies and can run in parallel branches; R2-09's B3 (PollGroupEngine v2) has
explicit landing-order notes against R2-01; R2-11 Part 1 must precede any parse-site edits elsewhere.
---
## Round 1 (2026-07-08 at `9cad9ed0`) — COMPLETE, kept for reference
Design + implementation plans for every finding in the 2026-07-08 architecture review
(`archreview/*.md`, review commit `9cad9ed0`). Each plan verifies every finding against
the current tree, then gives root cause → design (with alternatives) → concrete file-level
steps → tests → effort/risk.
## Plan documents
| # | Plan | Findings | Verification |
|---|---|---|---|
| 01 | [Core & composition](01-core-composition-plan.md) | 21 | all confirmed, 0 stale |
| 02 | [Scripting & alarms](02-scripting-alarms-plan.md) | 30 | all confirmed, 0 stale |
| 03 | [Server & runtime](03-server-runtime-plan.md) | 28 | all confirmed (U1 = stale *doc* only) |
| 04 | [AdminUI](04-adminui-plan.md) | 20 | all confirmed (C-3/C-4 good, no action) |
| 05 | [Protocol drivers](05-protocol-drivers-plan.md) | 37 + 1 positive | all confirmed, 0 stale |
| 06 | [Gateway integrations](06-gateway-integrations-plan.md) | 28 (23 actionable) | all confirmed (U-1 = stale *doc*) |
| 07 | [Client, tooling & engineering](07-client-tooling-engineering-plan.md) | 26 | all confirmed, 0 stale |
**Total: ~190 findings planned. Zero were stale-because-already-fixed; the only "stale" items are
two documentation drifts (CLAUDE.md Known Limitation 2) both flagged for correction.**
## The 4 Criticals (fix first)
| # | Critical | Plan | Fix shape |
|---|---|---|---|
| 1 | Split-brain resolver never activated → no hard-crash failover | 03 S1 | `ClusterOptions.SplitBrainResolver = KeepOldestOption` + hard-kill failover test |
| 2 | Production VT script timeout is dead code → one loop wedges the actor | 02 U2 (+U3) | Route through `TimedScriptEvaluator` + `CompiledScriptCache` |
| 3 | S7 has no reconnect path → PLC reboot kills the driver | 05 STAB-1 | `IS7PlcFactory` seam + lazy `EnsureConnectedAsync` |
| 4 | TwinCAT ADS subs orphaned after reconnect → silent data stop | 05 STAB-2 | Store replayable registration intent, replay on client swap |
## Cross-cutting guardrails (from OVERALL themes, span multiple plans)
- **Theme #1 built-but-never-wired** — the recurring failure mode. Guardrails proposed across plans:
reflection-exhaustive `DeferredAddressSpaceSink` forwarding test (03 U2, sequenced *before* the
surgical-add work), wiring the OTOPCUA0001 analyzer repo-wide (07 C-1), a startup log line proving
SBR is active (03 S1), and wiring/removing the dormant historian health surface (06 S-6).
- **Theme #2/#6 fixes don't flow to shared templates** — Part B of plan 05: `PollGroupEngine` v2
(backoff + onError + delete the S7 fork), shared strict `ReadEnum`/`ReadBool`, `ConnectionBackoff`
primitive, `ResolveHost`-via-resolver; plus `TagConfigIntent.Parse` in Commons (01 C-1) killing the
4-project byte-parity duplication.
- **Theme #3 optimistic success** — failure-visibility fixes: `AddressSpaceApplyOutcome` failure field
(01 S-1), Galaxy write fail-closed (06 S-1), primary-gate default-deny on unknown role (03 S4).
- **Theme #4 verification gap** — CI to all unit suites + fail-on-skip (07 S-1/S-2), fault-injection tier
(hard-kill / drop-PLC), the missing bUnit substitute = reflection/policy guards (04 C-1).
- **Theme #5 doc drift** — fix CLAUDE.md Known Limitation 2 + scadaproj index (03 U1 / 06 U-1),
ScriptAnalysis policy doc, Client.CLI docs (07 U-3).
- **Theme #7 repo hygiene** — `git rm -r lib/` AVEVA DLLs, untrack planning files, delete Wonderware
husks (07 U-4/U-5/U-6).
## Suggested execution order
Front-loaded per the OVERALL prioritized action list — items 16 eliminate every Critical plus the two
systemic guards (analyzer + CI) that stop the built-but-never-wired pattern recurring:
1. **Criticals** — 03 S1, 02 U2+U3, 05 STAB-1, 05 STAB-2 (each with its missing test)
2. **Systemic guards** — 07 C-1 (analyzer) + 07 S-1/S-2 (CI to all suites, fail-on-skip); 03 U2 (Deferred-sink forwarding test)
3. **Silent-corruption Highs** — 05 STAB-4/5 (AbCip lock, FOCAS caches), 05 Modbus timeout-fatal classification
4. **Failure-visibility Highs** — 01 S-1, 06 S-1, 03 S4
5. **AdminUI authz** — 04 C-1 (ConfigEditor policy + reflection guard)
6. **Perf** — 03 P1 (surgical pure-adds, after 03 U2 guard)
7. **Consolidation + hygiene + docs** — 01 C-1, 05 Part B, 07 U-4/U-5, doc fixes
## Open maintainer decision
- **Prune vs. keep the dormant machinery** (01 U-2 / 02 U-1): the callerless Tier-C recycle machinery +
`IDriverSupervisor`, and the ~2.4k-line `Core.VirtualTags` engine that production bypasses. Plans
recommend retiring both *after* the live paths are hardened (02 U2/U3 first), but the delete-vs-keep
call is the maintainer's.