diff --git a/docker/verify-mes-test-machine.sh b/docker/verify-mes-test-machine.sh index 2a0b27e0..360e882e 100755 --- a/docker/verify-mes-test-machine.sh +++ b/docker/verify-mes-test-machine.sh @@ -159,8 +159,9 @@ def group_D(): print("D. Reset alarm sources") for inst in ("SBTEST01", "SBTEST02"): write(inst, "VacuumPressure", 0.5); write(inst, "DoorOpen", "false"); write(inst, "SensorStatus", 0) - r = call("AlarmStatusRequest", {"MachineFilter": {"Code": "SBTEST02"}}) - check("D1 cleared", r.get("WasSuccessful") is True and names(r) == [], names(r)) + if "C" in os.environ["VERIFY_GROUPS"].upper(): # the check reads through BTDB, like group C + r = call("AlarmStatusRequest", {"MachineFilter": {"Code": "SBTEST02"}}) + check("D1 cleared", r.get("WasSuccessful") is True and names(r) == [], names(r)) GROUPS = os.environ["VERIFY_GROUPS"].upper() for g in "ABCD": diff --git a/docs/deployment/deployment-records/2026-09-28-wonder-app-vd03-fe89363b.md b/docs/deployment/deployment-records/2026-09-28-wonder-app-vd03-fe89363b.md index 3480748f..45daff69 100644 --- a/docs/deployment/deployment-records/2026-09-28-wonder-app-vd03-fe89363b.md +++ b/docs/deployment/deployment-records/2026-09-28-wonder-app-vd03-fe89363b.md @@ -124,3 +124,52 @@ method 9 (`return new { WasSuccessful = true, Alarms = Array.Empty() };` Staging left on the box under `E:\psrem-stage\fe89363b\` (zip, unpacked tree, migration SQL, prep + swap scripts, `.reg` exports). The `_appsettings-keep-20260928T095846` copy and `*.bak.20260928T095846` directories can go once the build has soaked. + +--- + +# Second window, same day — `fe89363b` → `b3021e7c` (script file access + recipe-parsing receiver) + +**Build:** `main` @ `b3021e7c` (ProductVersion `1.0.0+b3021e7c5ff68ba20abc510f644045c7dbbccd86`; zip +125 585 217 B, SHA-256 `5b7d7c68…2d66df`). **Delta:** the read-only, allow-listed `Files` script global +(design `docs/plans/2026-09-28-script-file-access-design.md`) and the TestMesMachine Delmia simulator now +reading + parsing the downloaded recipe file. **No migrations** (57 before and after — asserted, nothing applied). + +**Config (the only change):** `appsettings.Site.json` gained +`ScadaBridge:SiteRuntime:ScriptFileAccess:AllowedRoots = ["E:\\ApiInstall\\ScadaBridge\\recipes"]` (+ a +`_comment_SiteRuntime`), edited on the Mac and pushed over SMB **before** the window so the swap script's +keep/restore carried it through (new SHA-256 `3E7AD9A4…`); original saved as +`E:\psrem-stage\b3021e7c\appsettings.Site.json.pre-b3021e7c`. The three sample recipes +(`docker/recipes/SBTEST-R100.txt`, `SBTEST-R200.txt`, `SBTEST-R900-invalid.txt`) were pushed to +`E:\ApiInstall\ScadaBridge\recipes\`. Central's appsettings unchanged. + +**Window:** prep 10:41:47 (COPY_ONLY backup `ScadaBridge_pre-b3021e7c_20260928T104147.bak`, 140 064 768 B, +VERIFYONLY valid); swap 10:42:08 → site ready 10:42:57 (**~50 s**); the swap script asserted the recipes root +(3 files) and logged `site AllowedRoots = E:\ApiInstall\ScadaBridge\recipes`; boot validation accepted it. +Backups: `app.bak.20260928T104207` / `cli.bak.20260928T104207`. + +**Re-seed + gate:** `seed-mes-test-machine.sh` added the 14 recipe attributes to `TestDelmiaReceiver` and +updated all nine scripts; `verify-mes-test-machine.sh` (with `RECIPE_ROOT='E:\ApiInstall\ScadaBridge\recipes'`, +`RECIPE_OUTSIDE='E:\ApiInstall\ScadaBridge\app\appsettings.Site.json'`) **PASS 31/31** — group A now proves +accept (12 typed values loaded), re-download, invalid-line rejection with line numbers and nothing loaded, +`NotFound`, and a file **outside** the root refused (`OutsideAllowedRoots`). Real HTTP with a key: + +``` +DelmiaRecipeDownload R100 -> {"Result":true,"ResultText":"Loaded 12 recipe values from SBTEST-R100.txt for WO-1001"} +DelmiaRecipeDownload R900 -> {"Result":false,"ResultText":"Recipe rejected: line 4: expected RecipeValueName,RecipeValue; + line 5: unknown recipe value 'MysterySetting'; line 6: PotTempSP expects Int32, got '980.5'"} +``` + +**Recipe file format** (`RecipeValueName,RecipeValue` per line; value = int / double (invariant `.`) / bool / +text; `#` comments and blank lines ignored; everything after the first comma is the value; surrounding double +quotes unwrapped). Loaded all-or-nothing into `TestDelmiaReceiver`'s typed recipe tags (`RecipeName`, +`RecipeRevision`, `CoatingType`, `ReactorTempSP`, `PotTempSP`, `ArgonFlowSP`, `HydrogenFlowSP`, +`ChlorineFlowSP`, `VacuumSP`, `TargetRuntime`, `PurgeEnabled`, `OperatorNote`) plus `RecipeValueCount` / +`RecipeLoadedFile`. To test your own file: drop it in `E:\ApiInstall\ScadaBridge\recipes\` (SMB) and call +`DelmiaRecipeDownload` with that full path. + +**Rollback:** stop Site + Central, rename `app` → `app.failed`, `app.bak.20260928T104207` → `app` (same for +`cli`), restore `appsettings.Site.json.pre-b3021e7c` if the key must go (the old build ignores it), start +Central then Site. No DB restore needed (no schema change). + +**Rig:** `docker/deploy.sh` from `b3021e7c` (site-a both nodes mount `docker/recipes` read-only at +`/app/recipes`, `AllowedRoots ["/app/recipes"]`); seeded on site-a; `VERIFY_GROUPS=AD` **PASS 8/8**.