The Get-WinSCP.ps1 unblock-on-extract fix wasn't enough - if the WinSCP
folder is ever copied again afterward (network share, zip, sync tool),
Windows can reapply Mark-of-the-Web and silently re-block it. Unblock the
whole folder at the top of every engine.ps1 run instead of relying on
setup.bat timing. Also wrapped Add-Type in try/catch so a real load failure
now stops the run with a clear message instead of silently continuing into
a script that would only fail later once it actually tried to upload
something.
CAMBS, RMI, CONSENSIO, and INLAND always export TIFs into the daily date
folder instead of PDFs, so engine.ps1's hardcoded "*.pdf" filter silently
found nothing to upload (no error, just "No PDFs" for every practice).
Added optional entity.json field "insurance_file_type" (defaults to "pdf"
when omitted, so existing entities are unaffected); the PT STMT split logic
already worked on filename regardless of extension, so no other changes
needed.
- Unblock-File the extracted WinSCP files after unzip: Windows tags
downloaded files with Mark-of-the-Web, which makes Add-Type refuse to
load WinSCPnet.dll (FileLoadException 0x80131515) until unblocked.
- run.bat passed -EntityDir "%~dp0", but %~dp0 always ends in a trailing
backslash. cmd's argument parser treats a lone backslash before a closing
quote as an escaped literal quote rather than the string terminator, so
PowerShell received the path with a stray " character baked in
(Entities\CAMBS" instead of Entities\CAMBS), breaking Test-Path. Strip the
trailing backslash before quoting it.
Root cause found: winscp.net's download URL serves a human "please wait"
landing page (18KB HTML) instead of redirecting to the real file, unless
the User-Agent contains a known download-tool signature like curl or Wget.
PowerShell's own default UA always gets the landing page - confirmed by
reproducing locally with various UAs against the live URL. Not antivirus,
not TLS, not a network block; overriding -UserAgent to a curl string on
Invoke-WebRequest resolves it.
The 1MB size-check catches a bad download but gave no way to see why - on a
locked-down network something is very likely substituting a small HTML page
(proxy/AV block page) for the real zip. Print the first lines of whatever
was actually saved so the content is visible without another round trip.
Expand-Archive was failing with a cryptic "End of Central Directory record
could not be found" on Melissa's PC - the inline one-liner in setup.bat had
no error handling, so a blocked/truncated download (antivirus, firewall, or
an older TLS default) surfaced as a raw .NET exception instead of a useful
message. Moved the logic to Get-WinSCP.ps1: forces TLS 1.2, validates the
downloaded file size before unzipping, and reports what actually went wrong.
Windows PowerShell (5.1) reads .ps1 files without a UTF-8 BOM using the
system codepage, which mangles multi-byte UTF-8 characters like -> and --
into garbage that includes smart-quote characters PowerShell treats as
string terminators - this broke parsing on Melissa's PC (error at
engine.ps1:283, cascading missing-brace errors above it). Sticking to plain
ASCII avoids the whole encoding-dependent failure class.
Practice.json already supported overriding insurance_path/pdf_path/patient_path
via Merge-Config, but the README and example only mentioned login overrides —
document that practices can have different folder paths, not just credentials.