> ## Documentation Index
> Fetch the complete documentation index at: https://docs.usepitboard.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Verify a download

> Check that a release file came from pitboard's release workflow, using GitHub attestations, checksums and Gatekeeper.

Check a [release download](/install#install-without-homebrew) before you run it. The attestation check needs the [GitHub CLI](https://cli.github.com), `gh`.

## What each release attests

An attestation is a signed record, kept by GitHub, of the workflow and commit that produced a file. Every release attests these files:

* each command line tarball
* the app's zip file
* a bill of materials (SBOM) for each of those, in CycloneDX format (`.cdx.json`)
* `SHA256SUMS`, the checksums of the tarballs and the app
* `appcast.xml`, the update feed that tells an installed app what to update to

A pre-release publishes no `appcast.xml`.

On macOS, the command line and the app are also signed with a Developer ID and notarised by Apple. Files for Linux are not signed.

The app carries its notarisation ticket. For the command line, macOS fetches the ticket from Apple the first time you open a copy downloaded in a browser.

Homebrew installs these same files, and refuses one changed on the release page after the release workflow ran.

## Check an attestation

In the download's folder, run this, where `<file>` is the file's name:

```sh theme={null}
gh attestation verify <file> --repo datlechin/pitboard
```

When a workflow in pitboard's repository attested that exact file, it prints `Verification succeeded!` and exits with status 0. A changed file has no attestation, and the command fails with an error starting `Error: HTTP 404: Not Found`.

`--repo` accepts an attestation from any workflow in the repository. To accept only the release workflow, add `--signer-workflow`:

```sh theme={null}
gh attestation verify <file> --repo datlechin/pitboard \
  --signer-workflow datlechin/pitboard/.github/workflows/release.yml
```

## Check the checksums

Download `SHA256SUMS` from the same release and check it first:

```sh theme={null}
gh attestation verify SHA256SUMS --repo datlechin/pitboard
```

By itself, `SHA256SUMS` shows that a download arrived whole. Someone able to change the release could change a file and its checksum together, and the attestation of `SHA256SUMS` catches that.

Then, in the folder holding both files, run this on macOS:

```sh theme={null}
shasum -a 256 -c SHA256SUMS --ignore-missing
```

On Linux:

```sh theme={null}
sha256sum -c SHA256SUMS --ignore-missing
```

`--ignore-missing` skips files you did not download. A file that matches prints a line like this, where `<version>` is the release's version:

```text theme={null}
Pitboard-v<version>-macos.zip: OK
```

A file that differs prints `FAILED`, and the command exits with status 1.

## Check the signature on macOS

`spctl` asks Gatekeeper whether macOS would open a file. For the app:

```sh theme={null}
spctl --assess --type execute -v /Applications/Pitboard.app
```

```text theme={null}
/Applications/Pitboard.app: accepted
source=Notarized Developer ID
```

For the command line, use `--type install`, because `--type execute` accepts only apps. In the folder the tarball unpacked into, run this:

```sh theme={null}
spctl --assess --type install -v pitboard
```

It prints the same, as it would for any developer's notarised file. With `-vvv` in place of `-v`, an `origin` line names the signer. For pitboard's files, it ends with the team identifier `(D7HJ5TFYCU)`.

For what else pitboard protects against, see [Security and privacy](/security#what-pitboard-protects-against).
