Every public Pulsobot release is signed per platform, ships an SBOM,
a signing ledger and a checksums file, and reaches
downloads.pulsobot.com only through a promotion gate that
refuses an incomplete release.
<VER> is the release version, for example
2026.10.3.
| Asset | What it is |
|---|---|
pulsobot_<VER>_<os>_<arch> and
pulsobot-installer_<VER>_<os>_<arch>
archives |
pulsobot (CLI) and pulsobot-installer, for
macOS, Windows and Linux (amd64, arm64) |
pulsobot_<VER>_checksums.txt |
SHA-256 of every archive, the SBOM and the ledger, in
sha256sum format. Computed from the final, signed
bytes |
pulsobot_<VER>_sbom.cdx.json |
CycloneDX JSON SBOM (generated with syft from the source at the release tag): Go modules, the dashboard's npm dependencies, the Python job wrappers |
pulsobot_<VER>_signing.json |
Signing ledger: for each archive, the kind of signature found in the
published binary (notarized, authenticode,
unsigned) and whether it meets the platform's
requirement |
The download page links the checksums file, the SBOM and the release notes next to the downloads.
| Platform | Signature | How it is checked before publication |
|---|---|---|
| macOS | Signed with Pulsover's Apple Developer ID and notarized by Apple | The ledger opens the published binary, requires a Developer ID signature (not ad-hoc) and looks up its notarization ticket with Apple |
| Windows | Authenticode, through Azure Artifact Signing | signtool verify /pa on a Windows runner, then the
ledger checks the published binary carries an Authenticode
signature |
| Linux | Not code-signed | Covered by the checksums file and the SBOM |
Code: .github/workflows/release-notarized.yml,
release-windows-signed.yml,
release-ledger.yml,
scripts/release_signing_ledger.py.
Internal builds never reach customers directly. A release is
published on downloads.pulsobot.com only by the promotion
workflow (.github/workflows/promote-release.yml), behind
the public-release GitHub Environment, which needs a human
approval. Its gate (scripts/release_promotion.py gate)
fails closed unless the release has a complete signing
ledger, a CycloneDX SBOM and a checksums file that verifies every
promoted file. latest.json is never moved back to an older
version.
Download the archive, pulsobot_<VER>_checksums.txt
and, if you want it, the SBOM from the same release.
Checksums (all platforms):
# macOS
shasum -a 256 -c --ignore-missing pulsobot_<VER>_checksums.txt
# Linux
sha256sum -c --ignore-missing pulsobot_<VER>_checksums.txt# Windows: compare with the matching line of the checksums file
Get-FileHash .\pulsobot_<VER>_windows_amd64.zip -Algorithm SHA256macOS signature and notarization:
codesign --verify --strict --verbose=2 ./pulsobot-installer
codesign -dv --verbose=4 ./pulsobot-installer 2>&1 | grep -E 'Authority|TeamIdentifier'
spctl --assess --type execute --verbose ./pulsobot-installer # "source=Notarized Developer ID"The Authority chain must end with
Developer ID Application: … for Pulsover.
Windows signature:
Get-AuthenticodeSignature .\pulsobot-installer.exe | Format-List Status, SignerCertificate, TimeStamperCertificate
signtool verify /pa /v .\pulsobot-installer.exe # Windows SDKStatus must be Valid and the signer must
name Pulsover.
SBOM:
pulsobot_<VER>_sbom.cdx.json loads in any CycloneDX
tool (Dependency-Track,
grype sbom:pulsobot_<VER>_sbom.cdx.json, …) for your
own vulnerability scanning.
The binaries are built with the standard Go linker flags
-s -w (strip the symbol table and debug info;
.goreleaser.yaml,
.github/workflows/release.yml) and nothing more. We do not
obfuscate them, on purpose: