# Env2 + Transport Manual Verification Checklist **Date created:** 2026-05-24 **Companion to:** [`2026-05-24-second-environment-design.md`](2026-05-24-second-environment-design.md), [`Component-Transport.md`](../requirements/Component-Transport.md) **Goal:** Exercise the Transport (#24) bundle export/import flow against two real running environments (primary + env2). ## Prerequisites - `infra/` services running: `cd infra && docker compose up -d` - Primary stack running and healthy: `bash docker/deploy.sh && bash docker/seed-sites.sh` - `scadalink-mssql` reachable (`docker ps | grep scadalink-mssql`) ## Step 0: Bring up env2 - [ ] `bash docker-env2/deploy.sh` completes without error - [ ] `docker ps --format '{{.Names}}'` shows 5 new `scadalink-env2-*` containers - [ ] `curl -s http://localhost:9101/health/ready` returns 200 with `"status": "Healthy"` - [ ] `curl -s http://localhost:9100/health/active` is routed through Traefik - [ ] http://localhost:9100 loads the env2 login page in a browser - [ ] Login as `multi-role` / `password` succeeds - [ ] Env2 dashboard renders, Sites page is empty ## Step 1: Seed env2's test site - [ ] `bash docker-env2/seed-sites.sh` completes without error - [ ] Env2 UI → Sites page shows `site-x` (Env2 Site X) - [ ] Within ~30s, site-x health turns green ## Step 2: Prepare bundle source on primary - [ ] Primary UI (http://localhost:9000) → Design → Templates contains at least one template (create one if empty) - [ ] Optional: prepare at least one shared script and one external system for fuller round-trip coverage ## Step 3: Export from primary - [ ] Primary UI → Design → **Export Bundle** - [ ] Selection step: tick at least one template (folder + items) - [ ] Review step: confirm selected entity counts - [ ] Encrypt step: set passphrase `test-passphrase-1` - [ ] Download step: receive a `.scadabundle` file (note exact filename) - [ ] Verify the manifest's `SourceEnvironment` field equals `docker-cluster` (peek inside the zip; `manifest.json` is plaintext) ## Step 4: Import into env2 - [ ] Env2 UI (http://localhost:9101) → Admin → **Import Bundle** - [ ] Upload step: select the bundle file from Step 3 - [ ] Passphrase step: enter `test-passphrase-1` → diff loads successfully - [ ] Diff step: all rows are "Create" (env2 was empty for these entities) - [ ] Confirm step: import succeeds; result step shows the per-row outcome - [ ] Env2 audit log row(s) are tagged with the bundle's `BundleImportId` ## Step 5: Verify imported artifacts in env2 - [ ] Env2 UI → Design → Templates shows the imported template(s) - [ ] Env2 UI → Audit → Configuration Audit Log filtered by `BundleImportId` shows the import events - [ ] (Optional) Deploy an imported template to env2's `site-x` to prove runtime validity ## Step 6: Conflict-resolution probe - [ ] Re-upload the same `.scadabundle` to env2 with the same passphrase - [ ] Diff step: all rows are now "Update" - [ ] Pick mixed Skip / Overwrite / Rename per row; confirm - [ ] Verify the chosen resolutions land correctly (Skip rows unchanged, Overwrite rows match the bundle, Rename rows present under the new name) ## Negative tests - [ ] Wrong passphrase: try `wrong-passphrase` → friendly error, no diff loaded - [ ] Wrong passphrase 3 times in one session → session lockout enforced (`MaxUnlockAttemptsPerSession`) - [ ] Bump primary's `Transport.SchemaVersionMajor` to 99, export, attempt env2 import → schema-version mismatch error - [ ] Tamper with `manifest.json` content hash (unzip → edit → re-zip) → content-hash mismatch error ## Round-trip parity - [ ] Export the same templates from env2 (with `Transport.SourceEnvironment` = `docker-cluster-env2`) - [ ] Re-import into primary with Skip-on-conflict for all rows - [ ] Primary's audit log shows no actual mutations - [ ] Primary's template revision hashes are unchanged after the no-op import ## Cleanup (optional) - [ ] `bash docker-env2/teardown.sh` stops env2 containers - [ ] Drop env2 databases if needed: ```bash docker exec scadalink-mssql /opt/mssql-tools18/bin/sqlcmd \ -S localhost -U sa -P 'ScadaLink_Dev1#' -C \ -Q "DROP DATABASE ScadaLinkConfig2; DROP DATABASE ScadaLinkMachineData2;" ``` ## Pass criteria All checkboxes ticked, no defects found, both stacks remain healthy after the run.