ProtectionAI v1.6.1
101 registered [WorkspaceView] modules, 30 AI copilot tools, 4 AI providers, 7 UI languages,
3,055 tests. Ribbon: 17 tabs, 85 groups, 144 controls. Unchanged from v1.6.0 — this release adds no
modules, tools or tests; it fixes one way the product could lose a user's data.
Fixed
-
A second instance could corrupt the database. Nothing prevented two copies of ProtectionAI
running at once, and everything the product persists — assets, settings versions, archived
sessions, the document repository — lives in one per-userprotectionai.db. Two processes writing
that file is how it gets damaged: the development machine recorded three
SQLite error 11 — database disk image is malformedquarantines in a single day while copies were
being started side by side.ProtectionDatabasealready recovered from this properly — the damaged file is moved aside with
its-waland-shmsidecars, never deleted, and a note beside it gives thesqlite3 .recover
salvage command — but recovery still costs every test record written since the last export, and
the user only finds out on the next launch. Preventing the second writer is the other half of the
fix.A named mutex is now taken in
Services\SingleInstance.csbefore anything opens the database, and
ahead of the EULA and licence gate, so a second launch costs nothing and shows no dialogs: it
raises the window that is already open and exits. The name carries the user's SID in the global
namespace, making the guard per user rather than per session — a remote session running
alongside a console one shares%AppData%, and therefore shares the database. Two different users
have separate data directories and are unaffected.An abandoned mutex counts as acquired, because the previous owner exiting without releasing is the
normal case here (this repository's own build steps force-kill the app);OnExitreleases it on a
clean shutdown so that path stays distinguishable from a crash in the log.
--allow-multiple-instancesremains for running two builds side by side and logs what it costs,
rather than being a silent hole.Verified against the published build rather than by unit test, which is the stronger evidence for
an OS-level guard: the second launch is refused and the first activated, the override switch runs
two and logs the warning, and a clean shutdown releases the name.
Installer
ProtectionAI-Setup.msi is a Windows Installer (MSI) package. It installs ProtectionAI in Program Files, creates a Start Menu shortcut, registers Apps & Features uninstall support, and supports in-place major upgrades. ProtectionAI.App.exe is the same application as a self-contained single-file executable, for people who cannot run an installer.
This release is not Authenticode code signed. Windows SmartScreen will warn you when you run it, and that warning is expected. The checks below prove integrity (the bytes are the bytes we built) and source binding (the signed manifest came from this repository, tag and commit). They are not a Windows trust decision and do not stop SmartScreen warning.
Artifact digests (SHA-256)
8883c576dc5805ef9737837b616ab2f45ee9006180da34e65c505766ab88dc1c protectionai-1.6.1-cyclonedx.json
356463bff1e3728d44492d6ec33b7e2cf9019118b8fb7f9640e4794e624c9a0c protectionai-1.6.1-cyclonedx.json.sha256
4d17b7795182fd8c862e4b8ce82ba172039a4dbaf3c8d64b78714b76da04c7e5 ProtectionAI-Setup.msi
8401fa04b12d645b930bde6a554539a0a435b2dd3139f86b55b2f73ece5f7f81 ProtectionAI.App.exe
Published alongside the artifacts as SHA256SUMS, with a detached Sigstore signature (SHA256SUMS.sig), the ephemeral signing certificate (SHA256SUMS.pem) and a self-contained bundle (SHA256SUMS.cosign.bundle). The software bill of materials (protectionai-1.6.1-cyclonedx.json) and its checksum sidecar (protectionai-1.6.1-cyclonedx.json.sha256) are both attached and covered by the signed manifest.
1. Verify integrity — the files are what we built
PowerShell:
foreach ($line in Get-Content .\SHA256SUMS) {
$expected, $name = $line -split '\s+', 2
$actual = (Get-FileHash $name.Trim() -Algorithm SHA256).Hash.ToLower()
"{0} {1}" -f $(if ($actual -eq $expected) { "OK " } else { "FAILED" }), $name.Trim()
}POSIX shell:
sha256sum -c SHA256SUMS2. Verify authenticity — the digest list itself is genuine
Step 1 only proves the files match the list. This proves the list was produced by this release workflow. Install cosign and run:
cosign verify-blob SHA256SUMS \
--signature SHA256SUMS.sig \
--certificate SHA256SUMS.pem \
--certificate-identity https://github.com/Cwgtshome/ProtectionAI/.github/workflows/release.yml@refs/tags/v1.6.1 \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-github-workflow-repository Cwgtshome/ProtectionAI \
--certificate-github-workflow-ref refs/tags/v1.6.1 \
--certificate-github-workflow-sha 6201ed4218343af77392b1b8653f0ff077164c3fOr with the bundle, which needs no separate certificate:
cosign verify-blob SHA256SUMS \
--bundle SHA256SUMS.cosign.bundle \
--certificate-identity https://github.com/Cwgtshome/ProtectionAI/.github/workflows/release.yml@refs/tags/v1.6.1 \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-github-workflow-repository Cwgtshome/ProtectionAI \
--certificate-github-workflow-ref refs/tags/v1.6.1 \
--certificate-github-workflow-sha 6201ed4218343af77392b1b8653f0ff077164c3fPin all five certificate constraints exactly as shown: identity, issuer, repository, ref and SHA. Together they reject a signature from another workflow, repository, tag or commit. There is no long-lived private key: the certificate above was issued to this workflow's OIDC identity, is valid for minutes, and the signing event is recorded in the public Rekor transparency log.
3. Build provenance — not available for this release
No GitHub-hosted SLSA build-provenance attestation was recorded, so gh attestation verify will not find one. GitHub's attestation store is not offered to user-owned private repositories on this plan, and the source repository is private.
What still holds: the signed SHA256SUMS manifest binds every shipped content file by digest, and the Sigstore certificate in step 2 binds that manifest to this repository, tag ref and exact source SHA against a public transparency log. What is missing is GitHub's separate SLSA predicate and attestation-store record; no SLSA level is claimed.
Built from Cwgtshome/ProtectionAI@6201ed4. See docs/RELEASE-INTEGRITY.md for what each file is and why it exists.