100% free and open source · every tool, every host, no licence key · read the licence
Secronyx

Project

Releases and versioning

How semantic-release derives versions from conventional commits, what each release publishes, and how to verify a downloaded binary against its SLSA provenance and GitHub attestation before installing it.

Secronyx releases are cut automatically from the commit history, built by GitHub-hosted workflows, and published with build provenance you can verify before you install anything. Nothing in the pipeline depends on a maintainer's laptop. This page describes how a version number is decided, what a release contains, and — the part that matters operationally — how to check that the binary you downloaded is the one those workflows produced.

The first public release is v1.0.0. The project was developed privately before that; the changelog records that history under "Pre-release development".

Versioning

The project follows Semantic Versioning 2.0.0. Version numbers are not chosen by hand: semantic-release derives them from Conventional Commits on main.

.releaserc.json is the whole configuration:

{
  "branches": ["main"],
  "plugins": [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    "@semantic-release/github"
  ]
}

The mapping from commit to version bump:

Commit Bump Example from the history
fix: patch (1.2.3 → 1.2.4) fix(build): restore the macOS build and clear formatting and lint debt
feat: minor (1.2.3 → 1.3.0) feat(netconfig): police outbound connectivity probe targets
BREAKING CHANGE: footer major (1.2.3 → 2.0.0) any type, with the footer
docs:, style:, refactor:, test:, chore: none docs: compare against shell-based alternatives

Only main produces releases; there is no prerelease or maintenance branch configured. The plugin set means release notes are generated from the commits and published to a GitHub release — there is no changelog-committing or npm-publishing plugin in the chain, so CHANGELOG.md in the repository is maintained by hand in Keep a Changelog format.

What counts as breaking

For an agent whose output is consumed by automation, treat all of these as major:

  • removing a tool, or renaming one
  • changing the shape of a tool's JSON result — removing a field, renaming it, changing its type
  • renaming or removing a command-line flag or environment variable
  • changing a default in a way that changes behaviour, including a security default
  • changing a scope a tool belongs to, because that changes who can call it

Adding a tool, adding an optional argument, or adding a field to a result is a feat:.

Version metadata in the binary

Version, commit and build date are injected at link time with -X main.version=..., -X main.commit=... and -X main.date=..., so a binary can always account for itself:

secronyx --version

The five lines it prints are the version, the commit, the build date, the Go toolchain and the GOOS/GOARCH of the binary:

secronyx <version>
  commit: <commit>
  built:  <build date>
  go:     go1.24.4
  os:     linux/amd64

The first three are the stamped values; the last two are read from the running binary's runtime package. The build date is the UTC timestamp the release workflow generates in ISO 8601 basic form (%Y%m%dT%H%M%SZ), chosen without colons for SLSA compatibility. The Go line reports whichever toolchain built the binary — go.mod currently pins toolchain go1.24.4.

Include that output when reporting a bug; the issue template asks for it.

What a release publishes

Two workflows are involved. .github/workflows/ci.yml runs on pushes to main and develop, on pull requests to main, and on manual dispatch. Its release job is gated on if: github.ref == 'refs/heads/main' && github.event_name == 'push', and needs the build matrix (the five targets) and the custom-actions test; build in turn needs the three platform integration-test jobs, lint, the gosec security job and sonarcloud. Once those pass, release runs semantic-release, which creates the GitHub release and tag, and then attaches the binaries CI itself built.

Publishing that release fires .github/workflows/slsa-release.yml on the release: [published] event. That workflow rebuilds every target with the release metadata stamped in, uploads each asset with gh release upload --clobber — replacing what CI attached — and adds the two installers and the Linux provenance. It can also be run manually with workflow_dispatch and a tag input.

Assets on a release, for tag vX.Y.Z:

Asset Platform Built by
secronyx-linux-amd64 Linux x86-64 SLSA Go builder (Ubuntu)
secronyx-linux-arm64 Linux arm64 SLSA Go builder (Ubuntu)
secronyx-darwin-amd64 macOS Intel native macOS runner, CGO_ENABLED=1
secronyx-darwin-arm64 macOS Apple silicon native macOS runner, CGO_ENABLED=1
secronyx-windows-amd64.exe Windows x86-64 native Windows runner, CGO_ENABLED=1
secronyx-X.Y.Z-macos-universal.pkg macOS installer deploy/macos/build-pkg.sh
secronyx-X.Y.Z-windows-amd64.msi Windows installer WiX v5 on a Windows runner
secronyx-token-server-* all five targets as above
*.intoto.jsonl Linux binaries only SLSA provenance, uploaded beside each subject

The asymmetry is deliberate, and the workflow says so in a comment: the SLSA Go builder runs only on Ubuntu and cannot cross-compile cgo, and the macOS collectors for CPU, memory, disk and uptime are cgo. So the Linux binaries get SLSA level 3 provenance from the reusable builder, while the macOS and Windows binaries are built natively with cgo enabled and covered by GitHub build attestations instead. Both are verifiable; they are different mechanisms with different trust roots, described below.

The Linux builds are reproducible-friendly: CGO_ENABLED=0, -trimpath, -tags=netgo, and ldflags -s -w plus the three version stamps, all declared in .slsa-goreleaser/*.yml rather than in the workflow.

Supply-chain controls in the pipeline

  • The release workflow's metadata and attestation jobs start with step-security/harden-runner in audit mode, which records the runner's outbound network calls.
  • The release workflow pins its third-party actions by commit SHA — actions/checkout, actions/setup-go, harden-runner and actions/attest-build-provenance all carry a full SHA with the version in a trailing comment. actions/setup-dotnet in the MSI job is still referenced by tag. In CI, the scanning actions (golangci-lint, gosec, SonarCloud) and aws-actions/configure-aws-credentials are SHA-pinned; the first-party actions/* steps there are referenced by major tag.
  • The SLSA generator is referenced by tag (@v2.1.0) because the reusable-workflow trust model requires it.
  • Smoke tests run the freshly published binary on Linux, macOS and Windows runners against a broad set of queries before attestations are generated, so an asset that cannot start never gets attested.
  • actions/attest-build-provenance generates a GitHub attestation for every binary and installer, including the ones the SLSA builder did not produce.

Verifying a download

Do this before you install on anything that matters. Both checks bind the artefact's SHA-256 digest to the workflow, repository and commit that produced it; neither depends on trusting the download mirror.

Linux binaries: SLSA provenance with slsa-verifier

Each Linux asset has a sibling .intoto.jsonl provenance file on the same release.

VERSION=v1.0.0
BASE=https://github.com/levantar-ai/secronyx/releases/download/$VERSION

curl -sSLO $BASE/secronyx-linux-amd64
curl -sSLO $BASE/secronyx-linux-amd64.intoto.jsonl

slsa-verifier verify-artifact secronyx-linux-amd64 \
  --provenance-path secronyx-linux-amd64.intoto.jsonl \
  --source-uri github.com/levantar-ai/secronyx \
  --source-tag "$VERSION"

Treat the exit status as the verdict: slsa-verifier exits non-zero and explains why when verification fails. Anything other than a clean pass — a mismatched digest, a provenance file from a different repository, a tag that does not match — is a failure, and the correct response is to stop and report it, not to retry the download.

--source-tag pins the release tag; drop it if you are verifying an asset you cannot attribute to a tag, but then you are only verifying that some build of that repository produced it. --builder-id can be added to pin the exact builder workflow if your policy requires it.

Install slsa-verifier from the slsa-framework/slsa-verifier releases, and verify that download with its own provenance — a verifier you obtained insecurely verifies nothing.

Every asset: GitHub build attestations

macOS and Windows binaries and both installers have no .intoto.jsonl, but every asset — Linux included — carries a GitHub build provenance attestation generated by the github-attestations job. Verify with the GitHub CLI:

gh attestation verify secronyx-darwin-arm64 \
  --repo levantar-ai/secronyx

gh attestation verify secronyx-1.0.0-windows-amd64.msi \
  --repo levantar-ai/secronyx

This checks the file's digest against the attestation recorded for that repository and reports the workflow that built it. Add --signer-workflow levantar-ai/secronyx/.github/workflows/slsa-release.yml to pin the producing workflow rather than accepting any workflow in the repository.

Checksums

The release does not publish a separate checksums.txt. The authoritative digest for an artefact is the one inside its provenance or attestation, which is what the two commands above compare against — a checksum file downloaded from the same place as the binary adds nothing an attacker who controlled that place could not also change.

To record a digest for your own inventory or configuration management:

sha256sum secronyx-linux-amd64

Then pin that value in your deployment tooling, and verify the provenance once at the point you adopt the version.

Container images

The release does not publish a container image. The repository ships a Dockerfile for the agent and Dockerfile.token-server for the token server, and the bundled docker-compose.yml builds locally and refers to the result as secronyx:latest. If you run the agent in a container you are building and hosting that image yourself, so pin it by digest rather than by tag in your manifests and verify it the way you verify anything else in your own registry. Docker and Compose and Kubernetes and Helm cover the deployment side.

Upgrading

The binary is self-contained and holds no state beyond what you configured: its audit log, its API key store and, in hybrid mode, the credentials --login stores for it. Upgrading is replacing the file and restarting the service.

Before upgrading across a major version, read the release notes for removed flags and changed result shapes, and re-check the two places a default change will bite you: the scopes registered on each host, and anything in your automation that parses a tool result by field name. Both are covered in Configuration reference and Tool reference.

A rollback is the same operation in reverse: fetch the previous tag's asset, verify it, replace, restart. Because a release's assets are immutable once published, keeping the verified previous binary alongside the current one is a reasonable practice on hosts where a failed upgrade is expensive.

Support policy

The project ships from main and supports the latest release. Fixes, including security fixes, are delivered as a new version rather than as patches to older tags; there are no long-term support branches published in the repository, and no backport policy is defined there. Run the current release.

If your organisation needs something firmer than that — a defined support window, an SLA, or an indemnified agreement — support contracts are sold separately from the licence and do not change it. See Licensing, or write to sales@levantar.ai.

Security fixes are announced through the release notes and the changelog. The v1.0.0 changelog is the model for how they are described: what the flaw was, what it allowed, and what changed — for example, that a crafted site_name could previously execute commands with the agent's privileges on a host with IIS installed. Report a suspected vulnerability privately as described in Reporting a vulnerability.

Reading the changelog

CHANGELOG.md follows Keep a Changelog, with Security listed first in the 1.0.0 entry because that is where the operationally significant changes were. When assessing an upgrade, read the Security section for behaviour that changed under you — in 1.0.0 that included redaction and audit logging becoming on by default, the HTTP transport refusing insecure non-loopback binds, get_process_environ moving into the sensitive scope, and the 4 MiB result cap.

Installation · Contributing · Licensing · Reporting a vulnerability · Compliance mapping · Documentation home

Built 2026-09-19. Source: levantar-ai/secronyx. Found a mistake? Tell us.