Files
lmxopcua/archreview/plans/00-INDEX.md
T

141 lines
11 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.
> **✅ 2026-07-13 — ALL 12 ROUND-2 PLANS EXECUTED + MERGED** to `master` (`31c98200`), each as a Gitea PR
> (#426–#437) in 3 dependency-ordered waves. Consolidated unit sweep green (integration + live-`/run` gates
> deferred to a serialized heavy pass). See the "Round-2 COMPLETE" capstone at the bottom of
> [`STATUS.md`](STATUS.md) for the PR/wave map, unit-sweep tallies, the 3 confirmed-pre-existing failures, and
> the deferred heavy/live-pass checklist.
## Round 3 plans — tranche 1 (2026-08-20, verified at `7c77a8c7` ≡ `12b0035a`)
The 2026-08-19 round-3 re-review ([`../00-OVERALL.md`](../00-OVERALL.md)) produced a 12-item action
list. **Tranche 1 = items 1–5** — the Critical, the four new Highs, and the two small Medium-Highs they
carry along. Items 6–12 are queued as tranche 2. Each plan follows the round-2 house format and carries a
co-located `.tasks.json`.
| # | Plan | Findings | Tasks | Plan author | Executor | Reviewer |
|---|---|---|---|---|---|---|
| 1 | [R3-01 Mesh gRPC `.AllowAnonymous()`](R3-01-mesh-grpc-allowanonymous-plan.md) | 03/S14 **Critical** | 10 | opus | sonnet (+ fable for the `DisableLogin=false` rig gate) | opus |
| 2 | [R3-02 Stale-Good family](R3-02-stale-good-family-plan.md) | 03/S15, 05/STAB-19, 05/STAB-18, 02/S14 | 19 | **fable** | opus | opus |
| 3 | [R3-03 Restart re-subscribe + watchdog `max()`](R3-03-restart-resubscribe-watchdog-plan.md) | 03/S16, S17, U6 | 9 | opus | opus (upgraded from sonnet: the plan redesigns the spawn path + adds a supervision-restart hook) | opus |
| 4 | [R3-04 One role authority](R3-04-one-role-authority-plan.md) | 01/S-12 = 03/C5, 01/C-9 | 13 | opus | sonnet | opus |
| 5 | [R3-05 ACL hot path + key expiry](R3-05-acl-hot-path-expiry-plan.md) | 03/S18, S19 | 12 | opus | opus | opus |
**Model rationale.** Plan-writing is where design judgment lives, so every plan is opus or better; R3-02
spans four seams with one shared contract and a known vacuity trap (value-dedup), so it gets fable. Execution
of R3-01/03/04 is mechanical once planned (one-line-per-map, one re-push call, one normalizing authority) —
sonnet, with the adversarial review on opus. R3-02 and R3-05 change hot-path semantics (quality propagation;
the SDK session-activation callback) — opus executes. The rig gate that flips `DisableLogin=false` is the one
step that reasons about an observed failure rather than following a recipe — fable.
**Status 2026-08-20: all five EXECUTED, REVIEWED, MERGED and LIVE-GATED (PASS) — see `STATUS.md`.**
**Execution shape.** One branch per plan (`fix/r3-0N-…`) in an isolated worktree; unit suite of the touched
projects green before review; opus code-review against the plan; `--no-ff` merge to master in the order
**R3-03 → R3-01 → R3-04 → R3-05 → R3-02** (R3-03 and R3-02 both touch `DriverHostActor`; the small one
lands first and R3-02 rebases). Live gates run on docker-dev after the merges.
## 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 (~2–3 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 (~2–3 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.5–2 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.5–4 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 (~4–6 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.5–2 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.5–7 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 (~2–2.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 1–6 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.