diff --git a/docs/deployment/deployment-records/2026-06-27-wonder-app-vd03.md b/docs/deployment/deployment-records/2026-06-27-wonder-app-vd03.md new file mode 100644 index 00000000..f1d7e7ab --- /dev/null +++ b/docs/deployment/deployment-records/2026-06-27-wonder-app-vd03.md @@ -0,0 +1,81 @@ +# Deployment record — wonder-app-vd03 — 2026-06-27 + +Point-in-time record of a ScadaBridge upgrade + live configuration changes on the +single-host install at **`wonder-app-vd03.zmr.zimmer.com`** (`E:\ApiInstall\ScadaBridge`, +three Windows services: `ScadaBridge-LDAP`, `ScadaBridge-Central` :8085, `ScadaBridge-Site`). + +> Runtime config on this box (instance connection bindings, template compositions) is +> **config-as-data** held in the `ScadaBridge` SQL ConfigDb and applied via the management +> API — it is **not** source-controlled. This file is the durable record of those changes. +> Secrets (DB password, gateway API key, JWT/pepper) are intentionally omitted. + +## 1. Binary + schema upgrade + +| Item | Value | +|---|---| +| Build deployed | `main` @ **`06f2df4f`** (from `1f261263`; 40 commits) | +| Headline change | **notify-and-fetch deploy rework** — Central stages a `PendingDeployment` row + sends `RefreshDeploymentCommand`; the Site fetches config over HTTP from `GET {CentralFetchBaseUrl}/api/internal/deployments/{id}/config`. Retires the old cross-cluster `DeployInstanceCommand` config-push path. | +| EF migration applied | **`20260626161432_AddPendingDeployment`** (additive: new `PendingDeployments` table + FK + 3 indexes). Baseline was `20260619191520_SmsFromNumberOptional`. From→to script via `sqlcmd -C -b -I`. | +| New required config | **`ScadaBridge:Communication:CentralFetchBaseUrl = http://localhost:8085`** in `appsettings.Central.json` (empty → deploy fail-fast). Site needs nothing new — it receives the URL+token in the notify/reconcile message. | +| Not deployed | the new standalone `DelmiaNotifier` console tool (external client, not part of the Host service). | +| Preserved across swap | box `appsettings.json` + `appsettings.Site.json` + the entire `app\data\` (`inbound-api-keys.sqlite`, 53 KB). | +| DB backup | `E:\ApiInstall\ScadaBridge-backups\ScadaBridge_pre-AddPendingDeployment_20260627T001136.bak` | +| Binary backup | `E:\ApiInstall\ScadaBridge\app.bak.20260627T001254` (old `1f261263` binaries + appsettings + data) | + +### Verification +- `/health/ready` = **200 Healthy** (database + akka-cluster Up + all 5 required singletons). +- DisableLogin active (mgmt API no-auth → 200); inbound auth intact (bogus `X-API-Key` → 401). +- New `SiteReconciliationActor` / `SiteReplicationActor` started; reconcile pass `0 fetched, 0 failed, 0 orphan(s)`. +- **Notify-and-fetch proven end-to-end**: deploying an instance staged a `PendingDeployment` → Site fetched config (`200`, ~118 KB) over `CentralFetchBaseUrl` → applied → re-subscribed. + +## 2. Live ConfigDb changes (config-as-data, not in git) + +### 2a. Instance connection-binding completeness fixes +Several CvdReactor instances failed *pre-deployment validation* (missing binding rows for +data-sourced attributes — every existing binding correctly pointed at the only site +connection, `MxGateway` id=1). Fixed by adding the missing bindings via +`SetConnectionBindings` (full-list replace), then redeploying. Galaxy object names were +read from the gateway snapshot hierarchy (`galaxy-snapshot.json`). + +| Instance (id) | Reactor-level `DelmiaReceiver` object | LeakTest side objects | Result | +|---|---|---|---| +| Z28061 (1) | `DelmiaReceiver_038` | (already bound: `Left_002`/`Right_002`) | +10 bindings → **deploys**, 270 tags, DelmiaReceiver 10/10 Good | +| Z28062 (2) | `DelmiaReceiver_039` | `Left_003.LeakTest.*` / `Right_003.LeakTest.*` | +60 bindings → **deploys**, 270 tags, DelmiaReceiver 10/10 Good, LeakTest 28/50 Good (22 Bad = genuine idle-2nd-reactor source state) | +| Z28061Sim (8) | `DelmiaReceiver_037` | `Left_001`/`Right_001` | already complete (reference instance) | + +### 2b. CvdReactor template rename: `DelmiaRecv` → `DelmiaReceiver` +The `CvdReactor` template (id 1) had a typo'd reactor-level composition `DelmiaRecv` +(built from a duplicate template named `DelmiaRecv`, byte-identical to the proper +`DelmiaReceiver` template id 12). Corrected: + +- `DeleteTemplateComposition` (the `DelmiaRecv` composition) — this also auto-removed its + composition-owned clone template (the old `DelmiaRecv` template id 25). +- `AddTemplateComposition` → `DelmiaReceiver` from template 12 (engine cloned 12 → new + template id 26; composition uses the clone). +- Flattened attribute paths changed `DelmiaRecv.*` → `DelmiaReceiver.*`, so all three + CvdReactor instances were rebound (binding prefix renamed; source `DelmiaReceiver_03x` + objects unchanged) and redeployed. + +Result: CvdReactor components are now `LeftMESReceiver, RightMESReceiver, LeftReactorSide, +RightReactorSide, LeftDelmiaReceiver, RightDelmiaReceiver, DelmiaReceiver`. No `DelmiaRecv` +template or component remains. Z28061 `DelmiaReceiver.*` reads 10/10 Good. + +## 3. Instance deployability — final + +| Instance | Template | Deploys? | +|---|---|---| +| Z28061 | CvdReactor | ✅ | +| Z28062 | CvdReactor | ✅ | +| Z28061Sim | CvdReactor | ✅ | +| ZIPSEN (id 7) | IpsenSim (18) | ❌ pre-existing `MESReceiver (26)` binding gap — unfinished/draft instance, not touched | + +## 4. Rollback +- Schema: restore `ScadaBridge_pre-AddPendingDeployment_20260627T001136.bak` (the migration + `Down` drops `PendingDeployments`). +- Binaries: restore `app.bak.20260627T001254` + restart Central then Site. +- Binding/template changes: pre-edit binding sets were captured at deploy time; the template + composition swap is reversible via `DeleteTemplateComposition`/`AddTemplateComposition`. + +## 5. Outstanding +- **ZIPSEN** is the only non-deployable instance — needs its full `MESReceiver` binding set + authored (or to be retired). Deferred pending confirmation it is wanted.