docs(mesh): Phase 6 plan+ledger updates through Task 7
Records the Task 2/3 fallback+scoping corrections, the Task 6 no-flip decision (data-backed), and task statuses 0-7. Claude-Session: https://claude.ai/code/session_01GASWkNEi68FSCtvr6rLoEW
This commit is contained in:
@@ -354,34 +354,43 @@ legacy nodes unaffected.
|
||||
|
||||
---
|
||||
|
||||
### Task 6: Flip compiled transport-mode defaults to split-correct
|
||||
### Task 6: Compiled transport-mode defaults — DECIDED: do NOT flip (data-backed deviation)
|
||||
|
||||
**Classification:** small
|
||||
**Estimated implement time:** ~3 min
|
||||
**Parallelizable with:** Task 5 (disjoint files)
|
||||
**Classification:** small → **resolved as a no-code decision 2026-07-24**
|
||||
**Parallelizable with:** Task 5
|
||||
|
||||
**Context (decision 2):** so a fresh deploy is split-correct without per-node overrides, change the
|
||||
compiled defaults. `redundancy-state`/`fleet-status` stay DPS regardless.
|
||||
**Original intent (decision 2):** change the compiled `MeshTransport:Mode`/`Telemetry:Mode`/
|
||||
`TelemetryDial:Mode` defaults to the split-correct values so a fresh deploy is split-correct without
|
||||
per-node overrides.
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/Core/ZB.MOM.WW.OtOpcUa.Cluster/MeshTransportOptions.cs` (default `Mode` → `ClusterClient`)
|
||||
- Modify: `src/Core/ZB.MOM.WW.OtOpcUa.Cluster/TelemetryOptions.cs` (`TelemetryOptions.Mode` and
|
||||
`TelemetryDialOptions.Mode` defaults → `Grpc`)
|
||||
- Leave `ConfigSourceOptions.Mode` default = `Direct` (fused central stays Direct; Phase 4 validator
|
||||
forces driver-only to FetchAndCache).
|
||||
- Update tests that assert the old defaults (grep for `ModeDps`/`Mode == "Dps"`/`.Mode.ShouldBe` in
|
||||
the Cluster.Tests and any options tests; adjust to the new defaults). Update `appsettings.json`
|
||||
comments/keys if they document the default.
|
||||
**What the blast-radius assessment found (read-only, this session):** flipping the compiled defaults
|
||||
is **HIGH-RISK and low-value**. Every one of the three transport-option validators fail-closes when its
|
||||
mode is the non-Dps value but the mode's prerequisites are unset — and *nothing in the repo sets those
|
||||
sections*:
|
||||
- `MeshTransport:Mode=ClusterClient` requires `CentralContactPoints` — no `appsettings*.json` and no
|
||||
test harness sets it → `ValidateOnStart` throws at boot.
|
||||
- `Telemetry:Mode=Grpc` requires `GrpcListenPort`+`ApiKey` on a driver node — same gap.
|
||||
- `TelemetryDial:Mode=Grpc` requires `ApiKey` with **no role gate at all** — breaks even roleless
|
||||
fixtures and docker-dev's 4 site nodes.
|
||||
- Concretely this hard-fails **all 14 `Host.IntegrationTests`** (via `TwoNodeClusterHarness`, which
|
||||
sets none of these), **all 5 shipped appsettings profiles**, and several unit tests asserting the
|
||||
Dps default.
|
||||
|
||||
**Steps:**
|
||||
1. Change the three default initializers.
|
||||
2. Grep + update every test asserting the prior default (there are a handful — do not miss the
|
||||
Phase 2/5 option tests).
|
||||
3. Confirm the docker-dev rig (Task 7) does not *rely* on the old default anywhere (it will set modes
|
||||
explicitly anyway).
|
||||
**Why not flipping is correct, not a compromise:** the Task 5 `SplitTopologyTransportValidator`
|
||||
already forces `ClusterClient`/`Grpc`/`Grpc` onto **exactly** the nodes carrying a post-Phase-6
|
||||
`cluster-{ClusterId}` role, fail-closed, with a precise message — which *is* "a fresh Phase-6 deploy is
|
||||
split-correct," achieved more robustly than a default flip (a split node cannot even boot on the wrong
|
||||
transport). Flipping the compiled defaults would merely duplicate that enforcement for split nodes
|
||||
while indiscriminately breaking every legacy/test/admin node that legitimately still runs Dps. The
|
||||
docker-dev rig (Task 7) sets the modes **explicitly** on its cluster-role nodes, so it never relies on
|
||||
the default anyway.
|
||||
|
||||
**Acceptance:** `new MeshTransportOptions().Mode == ClusterClient`; both telemetry defaults `Grpc`;
|
||||
all options tests green.
|
||||
**Decision:** keep `MeshTransportOptions.Mode`/`TelemetryOptions.Mode`/`TelemetryDialOptions.Mode`
|
||||
defaults at `Dps`. No code change. Enforcement of split-correctness lives in Task 5's validator + the
|
||||
explicit Task 7 rig config. Recorded in `docs/Configuration.md` (Task 8) so the next reader knows the
|
||||
defaults are intentionally Dps and the validator is the guardrail.
|
||||
|
||||
**Acceptance:** MET by decision — the split validator (Task 5) is the guardrail; no default flip.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -5,17 +5,17 @@
|
||||
"branch": "feat/mesh-phase6",
|
||||
"decisions": {
|
||||
"secrets": "pair-local Akka (no SQL-hub; sites have no SQL)",
|
||||
"dpsBranches": "flip rig + change compiled defaults + split-topology validator; keep DPS code",
|
||||
"dpsBranches": "flip rig + split-topology validator; keep DPS code. NOTE: compiled defaults NOT flipped (Task 6) — blast-radius assessment showed a flip hard-fails all 14 Host.IntegrationTests + all 5 appsettings profiles + docker-dev site nodes; the Task 5 validator already enforces split-correctness fail-closed on cluster-role nodes, which is the actual intent.",
|
||||
"rigScope": "OtOpcUa-only three 2-node meshes on one shared network"
|
||||
},
|
||||
"tasks": [
|
||||
{"id": 0, "subject": "Task 0: RoleParser accepts cluster-{ClusterId}; consolidate driver literal", "classification": "small", "status": "completed", "commit": "87ff00fd"},
|
||||
{"id": 1, "subject": "Task 1: ClusterRoleInfo exposes node's own ClusterRole/ClusterId", "classification": "small", "status": "completed", "commit": "2d2f1dec", "note": "interface in Commons/Interfaces/IClusterRoleInfo.cs; ctor (ActorSystem, IOptions<AkkaClusterOptions>, ILogger)"},
|
||||
{"id": 2, "subject": "Task 2: re-home RedundancyStateActor to cluster-role singleton on drivers", "classification": "high-risk", "status": "pending", "blockedBy": [1], "parallelizableWith": [3, 4]},
|
||||
{"id": 3, "subject": "Task 3: re-scope ClusterNodeAddressReconciler to own-cluster rows", "classification": "standard", "status": "pending", "blockedBy": [1], "parallelizableWith": [2, 4]},
|
||||
{"id": 4, "subject": "Task 4: one ClusterClient per cluster in CentralCommunicationActor", "classification": "high-risk", "status": "pending", "blockedBy": [], "parallelizableWith": [2, 3]},
|
||||
{"id": 5, "subject": "Task 5: split-topology startup validator (cluster-role => non-DPS)", "classification": "standard", "status": "pending", "blockedBy": [0, 1], "parallelizableWith": [6]},
|
||||
{"id": 6, "subject": "Task 6: flip compiled transport-mode defaults (ClusterClient/Grpc)", "classification": "small", "status": "pending", "blockedBy": [], "parallelizableWith": [5]},
|
||||
{"id": 2, "subject": "Task 2: re-home RedundancyStateActor to cluster-role singleton on drivers", "classification": "high-risk", "status": "completed", "commit": "a4d3ab40", "note": "re-home a2c5d57f + review fixes a4d3ab40 (comments + driver-fallback registry test + fixed a cross-task admin-boot NRE race); 14/14 tests"},
|
||||
{"id": 3, "subject": "Task 3: re-scope ClusterNodeAddressReconciler to own-cluster rows", "classification": "standard", "status": "completed", "commit": "1ce2042e", "note": "impl 2535df01 + review-fix 1ce2042e (observed ALSO scoped by cluster role via testable FilterOwnClusterDriverMembers helper; 17/17)"},
|
||||
{"id": 4, "subject": "Task 4: one ClusterClient per cluster in CentralCommunicationActor", "classification": "high-risk", "status": "completed", "commit": "6531ec19", "note": "impl 6531ec19 + comment fix d98b3264; two-mesh boundary test proves partitioned delivery, red-before-green"},
|
||||
{"id": 5, "subject": "Task 5: split-topology startup validator (cluster-role => non-DPS)", "classification": "standard", "status": "completed", "commit": "344b0d33", "note": "impl a886d5e6 + review-fix 344b0d33 (resolve EFFECTIVE roles incl OTOPCUA_ROLES fallback matching Program.cs, case-normalize -> guardrail can't be defeated by role-source/case mismatch); 16/16 filter, 124/124 Cluster.Tests"},
|
||||
{"id": 6, "subject": "Task 6: compiled transport-mode defaults", "classification": "small", "status": "resolved-no-flip", "note": "DECIDED not to flip — blast-radius assessment: high-risk (breaks all integration tests + appsettings profiles + docker-dev site nodes), low-value (Task 5 validator already enforces split-correctness fail-closed). Documented in plan Task 6 + Configuration.md."},
|
||||
{"id": 7, "subject": "Task 7: rewrite docker-dev rig into three 2-node meshes", "classification": "standard", "status": "pending", "blockedBy": [0, 2, 3, 4, 5, 6]},
|
||||
{"id": 8, "subject": "Task 8: docs sweep — status tables, caveat removal, pair-local secrets note", "classification": "small", "status": "pending", "blockedBy": [2, 3, 4, 5, 6], "parallelizableWith": [7]},
|
||||
{"id": 9, "subject": "Task 9: live gate — three meshes, per-pair redundancy, cross-mesh transports","classification": "high-risk", "status": "pending", "blockedBy": [7, 8]}
|
||||
|
||||
Reference in New Issue
Block a user