NodePilot 1.2.22
An update can now repair an install directory it would previously have refused, and the header's help button reaches the documentation on a development server.
Fixed
An update no longer dead-ends on an install directory that someone widened. C:\Program Files\NodePilot must not grant write access to anyone but SYSTEM, Administrators and TrustedInstaller — the service executes the binaries that live there, so write access is code execution as the service account. The installer both applies that DACL and verifies it; the updater only ever verified it, and refused when it did not hold.
That refusal came after the binaries had already been replaced, so it cost a rollback and left the host on the old version with no route forward, over a condition an update can simply fix. Nothing reads that ACL between updates, so an entry granted after the installation was laid down stays invisible until the next one — and then surfaces at the worst possible moment.
The updater now repairs the directory once, with the same protected DACL the installer applies: inheritance dropped, every explicit ACE wiped, owner forced back to Administrators. Then it checks again. That second check is what keeps this a hardening step rather than a bypass — if the directory is still writable by an untrusted principal, the update fails and rolls back exactly as before. The rule itself is unchanged.
Verified end to end against a real installation: a host was put into the failure state deliberately, and the update repaired it, completed with exit 0, and left the directory carrying SYSTEM and Administrators only.
The help button reaches the documentation on a development server. In production the API serves the documentation site from wwwroot/docs at /docs, and that path was always served correctly. On a development server nothing answered it, so /docs/ fell through to the application's own index.html and the router replied with its not-found screen — the question mark in the header led into an error page.
The app dev server now proxies /docs to the documentation dev server, which serves under /docs/ itself so its entry module stays inside the proxied prefix. Development-only; an installation is unaffected.
Verifying this download
Every file below is listed in NodePilot-1.2.22.SHA256SUMS.txt, the publisher certificate included.
Get-FileHash .\NodePilot-1.2.22.zip -Algorithm SHA256The installers and the standalone switcher are Authenticode-signed with the NodePilot release certificate:
Subject CN=NodePilot Release Signing
Thumbprint 277EAB317A581C88302CE92BE805938C86B4650D
Compare that thumbprint against nodepilot-release-signing.cer, attached here:
(Get-PfxCertificate .\nodepilot-release-signing.cer).Thumbprint
$sig = Get-AuthenticodeSignature .\NodePilot-Server-Setup-1.2.22.exe
$sig.SignerCertificate.Subject
$sig.SignerCertificate.ThumbprintGet-AuthenticodeSignature reports Status: UnknownError, and that is the expected result — the certificate is self-signed, so its root is in nobody's trust store and no chain can be built. What carries the meaning is the pair above: the signer's subject, and a thumbprint equal to the certificate shipped alongside. The checksum file proves the download is intact; the thumbprint is what proves who built it.
SmartScreen
Windows SmartScreen warns on first run of a downloaded installer — "Windows protected your PC". That is expected and unrelated to the signature: the release certificate is self-signed and carries no reputation, so signing does not silence it. Choose More info → Run anyway. SmartScreen ignores antivirus exclusion lists entirely; see the deployment guide for the full explanation.