docs(mesh-phase4): ServiceLevel semantics on DB-less nodes + driver ConfigDb cut

Claude-Session: https://claude.ai/code/session_01GASWkNEi68FSCtvr6rLoEW
This commit is contained in:
Joseph Doherty
2026-07-23 13:18:57 -04:00
parent 6f21213f70
commit 55a6e1f2b2
5 changed files with 116 additions and 15 deletions
+16 -1
View File
@@ -162,9 +162,24 @@ On the docker-dev rig every node carries these keys already; flip the whole rig
On the docker-dev rig the central pair carries `ConfigServe` (port `4055`, dev key) and stays `Direct`; the four site nodes carry `ConfigSource` (endpoints + matching key) defaulting to `Direct`. Flip only the site nodes with `OTOPCUA_CONFIG_MODE=FetchAndCache` at `docker compose up` — central keeps SQL and models the target topology.
**`FetchAndCache` is mandatory on a driver-only node — per-cluster mesh Phase 4.** `Program.cs` now
registers `AddOtOpcUaConfigDb` only when the node carries the `admin` role, so a **driver-only**
node (`Cluster:Roles` has `driver`, not `admin`) holds **no `ConfigDb` connection string at all**
there is nothing for `Direct` to read. `ConfigSourceOptionsValidator` enforces this at
`ValidateOnStart`: a driver-only node whose `ConfigSource:Mode` is `Direct` **fails host start**
with an error naming the fix (`ConfigSource:Mode=FetchAndCache`). A **fused** `admin,driver` node
still owns its ConfigDb via the admin role and may stay `Direct` — the validator only fires on
`driver` without `admin`. On a driver-only node the deployed configuration, the scripted-alarm Part
9 condition state (`LocalDbAlarmConditionStateStore`, replacing the ConfigDb-backed
`EfAlarmConditionStateStore`), and the alarm store-and-forward buffer all live in the node's
LocalDb; central remains the system of record for deploy acks (`ConfigPublishCoordinator.
PersistNodeAck`) and LDAP group→role DB grants (a driver-only node maps LDAP groups to roles from
the `Security:Ldap:GroupToRole` appsettings baseline only — see `docs/Redundancy.md` and
`CLAUDE.md` §"Phase 4" for the full picture, including the client-visible ServiceLevel change).
### `ConnectionStrings` → `ConfigDb`
- **Purpose:** the central Config DB connection string. **Required for every role**`Program.cs` calls `AddOtOpcUaConfigDb` unconditionally.
- **Purpose:** the central Config DB connection string. **Required on admin-role nodes only**`Program.cs` calls `AddOtOpcUaConfigDb` when `hasAdmin` (per-cluster mesh Phase 4). A driver-only node holds no `ConfigDb` connection string; it fetches its configuration via `ConfigSource:Mode=FetchAndCache` instead (see above). A fused `admin,driver` node still requires it.
- **Bound by:** `AddOtOpcUaConfigDb(config)` (`src/Core/ZB.MOM.WW.OtOpcUa.Configuration/ServiceCollectionExtensions.cs`). The connection-string name constant is `ConnectionStringName = "ConfigDb"`, read via `configuration.GetConnectionString("ConfigDb")`. If absent, startup throws with a message pointing to either `appsettings.json` or the `OTOPCUA_CONFIG_CONNECTION` env var.
- **Shape:** standard `ConnectionStrings:ConfigDb` SQL Server connection string. There is no checked-in default in the thin `appsettings*.json` — supply it per environment.