Changelog
Version history and release notes for epack CLI and specification.
A failed collector is reported with a code that says why, and its exit code reaches the job. A collector that exits 0 without evidence now fails. A new collector project is laid out and checked the way the epack collectors are.
Collector failures
epack collect,epack collector run, andepack runreport each failed collector with a code:config_invalidwhen it exited 2,auth_failedfor 3,network_errorfor 4,collector_errorfor any other exit or a signal,invalid_outputwhen it exited 0 without a result, andtimeoutwhen it ran past--timeout. A failure epack finds before the collector runs keeps its own code, such asbinary_not_foundordigest_mismatch- The command's error has the code
collect_failedand readsokta: exited with code 3: ...for one collector, or2 collectors failed: okta, githubfor several - When one collector failed, epack exits with that collector's exit code from 2 to 9, or with epack's own code for a failure it found, such as 13 for a timeout. Several failures exit 1. Earlier releases exited 1 for any collector failure
- With
EPACK_ERROR_FILEset, each failed collector adds a line after the summary, such ascollector=okta code=auth_failed exit=3 code_source=exit_code.code_sourceisexit_codewhen the code was inferred from the exit code andrunnerwhen epack observed the failure itself - A failed
epack runreports each collector'scode,exit, andcode_sourceundermetadata.collect.failures.epack remote report-lock --outcome failurelists the same collectors, without their errors, fromEPACK_ERROR_FILEwhen its last error has the code given as--failure-code
Upgrade notes
- A collector that exits 0 must print a result. Empty stdout, JSON
null, text that is not JSON, and an envelope whoseartifactslist is empty ornullnow fail the collector withinvalid_output. Earlier releases packed text that was not JSON as a JSON string - A script that reads
EPACK_ERROR_FILEby sourcing it should read the^code=,^exit=, and^summary=lines instead, since acollector=line would also setcodeandexit
Collector SDK
ConfigError,AuthError, andNetworkErrorkeep their exit codes when returned as a pointer or wrapped with%w, and an error that reachescontext.DeadlineExceededwithout one of them exits 4epack sdk new collectorlays a project out as the epack collectors are: its entrypoint incmd/epack-collector-<name>/main.go, collection logic and its test ininternal/collector, aMakefile, andtestdata/conformance.json.--modulesets the Go module path, and the project needs Go 1.26- A new project's CI runs conformance at the epack version
go.modpins. A collector's runsmake conformance, which passestestdata/conformance.jsonand the variables inCONFORMANCE_SECRETS epack sdk mock collectorwritesconfig.jsonandrun-collector.sh, a script that runs the collector as epack does
Conformance
epack sdk testandepack-conformancetake--config, a collector config to collect with, and--secret, a variable the collector reads a credential from. Every run sets each secret to a canary value. The checks fail when a canary shows up in output, files, or error messages, and when a collector reports a rejected credential without exiting 3epack sdk testbuildscmd/<directory name>, or the only package undercmd/, and passes a collector project'stestdata/conformance.jsonunless--confignames another.epack-conformance -vlists every result, including passes
Releases
- A tag with a prerelease suffix, such as
v0.7.0-rc.1, publishes a GitHub prerelease. Homebrew and thelatestimage tags stay on the newest stable release
epack says when a newer release is out, at most once a day. CI mode is detected on more CI systems, and epack secret set says when a folder may be behind its configuration.
New
- At a terminal, a command checks at most once a day for a newer epack release. When one is out, the command ends with
epack X.Y.Z is available (you have A.B.C)and how to upgrade:brew upgradewith the formula when Homebrew installed epack, or else the releases page - The check asks GitHub without credentials, never sends
GITHUB_TOKEN, gives up after two seconds, and never fails a command. Prereleases are not offered - There is no check in CI mode, with
--quiet, when stderr is not a terminal, for a local or prerelease build, or for bareepack,help,version,completion,hooks, andcontext. SetEPACK_NO_UPDATE_NOTIFIERto turn it off - When the last check ran and the release it found are kept in
~/.epack/update-check.json, readable only by you. The check is in the full build only
Changes
- CI mode is also detected from
GITLAB_CI,CODEBUILD_BUILD_ID,JENKINS_URL,BUILDKITE, andTF_BUILD, besidesCIandGITHUB_ACTIONS. A job on a system that sets only one of these now runs in CI mode: no spinners, timestamps on output, and no keychain - When
epack secret setrefuses a name no component lists, in a folder a clone created, it names the revision the folder holds and says to runepack remote cloneto update the folder before passing--unlisted
When the revision a run fetches needs something the runner lacks, the run names what is missing and runs the newest earlier revision that works here, or stops and reports it. A job with no folder can run a configuration by name, signed in for that configuration.
Runs
epack run <name>checks the revision it fetched before installing anything: each variable or keychain secret it reads, approval for stored secrets, trust in each publisher it installs from, and the epack release the remote says it needs- When something is missing, the run lists it with where to add it, as the remote says or as epack knows, and asks the remote for the newest earlier revision that runs without it. That revision is fetched into
.epack/fallbackinside the folder and runs instead, and the run names both revisions. The fetched revision stays in the folder for you to finish - With no earlier revision that runs here, the run stops before installing anything, prints the remote's reason, reports what is missing to the remote with the code
requirements_missing, and exits withrevision N needs ..., and no earlier revision runs here without it epack run --checkreports an epack release older than the revision needs, with the release to upgrade to- After a fetch, epack prints what the remote says changed since the revision this runner last ran
Jobs
- A job can run a configuration by name with no folder. With
EPACK_PIPELINE_IDset and the job's GitLab ID token or the runner's key,epack run <name>and its check sign in for that configuration at the credential broker and fetch through the adapter installed for the user - That adapter must come from a publisher the job trusts, named with
--trust-publisherorEPACK_TRUSTED_PUBLISHERS, and the check happens before the adapter is installed or run - When a run by name needs the adapter a folder pins and it is not installed yet, a run with nobody at the terminal installs it without asking if its publisher is trusted, and verifies it before it runs. Earlier releases installed it only after a prompt
Security
- Trust in a new publisher is offered only for the revision you fetched. Earlier revisions a run falls back to are checked without prompting
EPACK_INSECURE_REMOTE_ENDPOINTandEPACK_INSECURE_REMOTE_AUTH_ENDPOINTpoint an adapter installed for the user at another instance of its remote, asinsecure_endpointdoes for a project's adapter. epack warns about each use and records it, and strict production builds refuse it
Remote Protocol
config.pullrequests carryconfig.purpose:run,check, orclone. A remote can count a run or a check as contact from the runner; a clone sets up a folder and is never a run- A run that lacks what a revision needs sends
config.fallbackwith that revision and what it lacks, by kind and name and never by value:variable,secret_approval,publisher, orepack. The answer is the newest earlier revision that runs without it, orno_fallbackwith a reason - A
config.pull.resultcan carryrequirements, the oldest epack that runs the revision and where a runner adds each variable, andchangeswithchanges_since, what changed since the revision this runner last ran - Adapter commands run with
EPACK_WRAPPER_VERSIONset to the running epack release
Fixes
- Choosing the newest release in a version range, and
epack remote update, order prereleases by semver precedence: a release sorts after its prereleases, andrc.10afterrc.9
The lock drops what the configuration no longer lists, and epack lock --keep-pins resolves only what changed. Inside a folder a clone created, epack remote clone needs no name.
Lockfile
epack lock,epack install, andepack runremove lockfile entries for collectors, tools, remotes, profiles, overlays, and mappings the configuration no longer lists.epack lockandepack installprint each one, as inremoved okta@v0.2.0 (not in config). Earlier releases kept the entry, and a locked sync refused it withLOCK_STALEepack lock --keep-pinskeeps each pinned version its range still allows from the same source, and resolves only components that are new, out of range, or from another source. A pin it keeps prints askept. Without the flag, every range resolves to its newest release as before
Remotes
- Inside a folder a clone created,
epack remote clonewith no name refreshes the folder from the configuration and remote it was cloned from - A configuration renamed since it was cloned still refreshes in place: from inside its folder,
epack runorepack remote clonewith the new name matches the folder by the configuration's ID instead of nesting a copy - A folder cloned from another configuration is refused unless you pass
--force - When a revision carries a lock, it replaces an
epack.lock.yamlthat a run wrote in the folder, and the fetch says so. The JSON result gainsreplaced. Earlier releases refused the fetch as a local change unless you passed--force - After a clone of a configuration with a CI job file that arrives locked, the next step reads commit the folder, without
epack lock --all-platformsfirst
The variables a configuration lists under secrets can live in your keychain, scoped to one configuration on one remote and approved for the components that read them. A run reports each stage to a remote that can show it, and a failed run names the collector that failed.
New
epack secretkeeps a configuration's secrets in the operating system keychain:setupwalks through every missing and unapproved secret,setstores one value (hidden at a prompt, from a pipe with--stdin, or from a file with--from-file),approvereviews what changed and records approval,listshows names, readers, and approval state without values, andremoveerases one. Run them in the folderepack remote clonecreated- Each stored secret is approved for the components that read it as they are now. A revision that changes a reader's entry in
epack.yaml, or adds a reader, is shown and must be approved before the value is used again. Storing or approving one secret never approves another - The environment always wins: a variable set in the shell reaches its readers as before, and the keychain is read only for the rest. CI never reads the keychain
- Remote adapters can take
run.progressevents, one as each stage and each collector or tool starts, finishes, or fails, so the remote can show the run while it is going. Adapters opt in with therun_progressfeature; epack sends nothing to one that does not
Running
epack run --checkreports variables asN of M readyand lists each one with where its value comes from: the environment, your keychain, stored but awaiting approval, or not set. A variable that is not ready comes with the command that resolves it. The JSON report gainsvariablesandsecret_storeepack runstops before collecting when a required variable is not ready, naming each one and theepack secretcommand to run. Runs and checks never prompt; only theepack secretcommands do- The summary printed after a fetch counts a variable as set when your keychain holds it for that configuration
epack run <name>andepack remote clone <name>from inside the folder a clone created refresh that folder instead of nesting a second copy- A failure report from the collect stage names the failed collector and its error, or counts and names several, in place of a bare failure count
- Every run has an id, carried in its progress events, on the release it pushes, and on the failure it reports, so a remote can join them
Security
- What the keychain protects is encryption at rest and isolation from other user accounts, not isolation from code running as the same user. Every platform lets a same-user process read what epack stored, as it can read an exported variable
- What epack records about stored secrets, their names, readers, and times but never values, lives in
~/.epack/secrets.yaml, readable only by you - The keychain is consulted only after the publisher trust gate, and the lookup behind a fetch summary never prompts
Upgrade notes
- The
epack secretcommands are in the full build only;epack-coresays so and exits - On Linux the keychain is the Secret Service over D-Bus, so a desktop session with gnome-keyring or kwallet is needed. Without one, the check reports the store as unavailable and the environment still works
After cloning a configuration that runs in CI, epack says to lock and commit rather than run.
Changes
- When the configuration
epack remote clonefetched carries a CI job file, a.gitlab-ci.ymlor a workflow under.github/workflows/, the next step readsepack lock --all-platformsand commit the folder withepack.lock.yaml, since CI runs from a committed lock - A configuration that runs where it was cloned keeps the
epack runhint
A fetched configuration can carry the profile and mapping files the validate tool reads, so a pipeline with profile validation runs from a laptop or a GitLab job.
Fixes
epack remote cloneandepack run <name>write.epack/profiles/<name>.yamland.epack/mappings/<name>.yamlfrom a pulled configuration. Earlier releases refused them as hidden paths, so a configuration with the validate tool failed with "is not a path epack writes"- Every other hidden path is still refused, including
.epack/collectors/,.epack/remotes/, and.git/
A secrets entry can be optional: a variable the run may hold, passed through when set and never required. Reported collector output no longer carries the values of passed secrets, and a timed-out collector takes its background processes with it.
Configuration
- A
secretsentry is a bare name or{name: AWS_PROFILE, optional: true}. A bare name is required, andepack run --checkreports it when unset. An optional entry is passed through when set and is neither counted nor reported - The summary printed after a fetch marks optional entries as
(optional)or(optional, set), and the check's report lists them underenv_optional - Earlier releases parse the list strictly and refuse a configuration with an optional entry, so upgrade before fetching one
Security
- Collector and adapter stderr in error messages and streamed output has every passed secret value replaced with
[REDACTED], before truncation and pattern redaction. Values shorter than six characters are not matched - On Unix, collectors and remote adapters run in their own process group, and a timeout kills the whole group, so a process a collector started cannot outlive the run with its environment
- A collector that exits but leaves a process holding its output open no longer hangs the run; after five seconds the run fails with an error naming the cause
Toolchain and dependency refresh. No behavior changes.
Changes
- Built with Go 1.26.9, with the golang.org/x modules and gRPC updated to their current releases, so the binaries carry those projects' latest fixes
Installing from a lock no longer calls the GitHub API, so runs on shared runners without a GitHub token stop failing with a 403.
Fixes
- When the lock records a component's release asset,
epack run,epack run --check, andepack syncdownload it and its Sigstore bundle from the release's download link instead of looking the release up through the GitHub API. Unauthenticated runners on shared addresses, such as AWS CodeBuild and hosted CI runners, often had no API quota left and failed with "unexpected status 403 fetching release" - The download is verified the same way: it must match the lock's digest and its Sigstore signature
- A lock that doesn't record asset names still looks each release up
epack run --check now offers to register this machine's signing key for a configuration that does not hold it yet, as a run does.
Runs
- In a terminal,
epack run --checkasks to register this machine's key when the remote does not hold it for the configuration, then waits for the approval the remote asks for and reports the key as usable or waiting. Previously the check only reported the key as not registered, and registering it took a run orepack key create - Without a terminal, or with
--yes, the check still reports the unregistered key, and the finding now also names--browser, which signs in the browser instead
A run on a laptop now gets its collectors' managed credentials with your epack remote login sign-in, and a failed run prints its output cleanly.
Runs
- A run or
epack run --checkwith no CI identity, such as one on a laptop, resolves managed collector credentials through the remote's sign-in when the remote's adapter supports it. Previously a collector with managed credentials failed there with "locktivity-managed credentials require a runtime identity" - That error now lists a sign-in with
epack remote loginamong the identities a run can use
Remote Protocol
- Added
credentials.resolveand thecredentials_resolvecapability. An adapter resolves a configuration's managed credentials with the sign-in it holds, so the person's token stays in the adapter and only the resolved credentials reach epack
Fixes
- After a failed collect, the spinner no longer keeps running into the post-collect hook's output. The failed stage closes with its failure line first
- A stage's result clears the rest of the line, so a shorter message no longer keeps the end of the spinner text it replaced
- The line saying a failure was reported to the remote ends with a newline, so the next output starts on its own line
- Collector errors no longer end with an escaped newline from the collector's stderr
epack run --check now installs the locked components before it signs in, so it works on a fresh machine or CI runner.
Fixes
epack run --checkinstalls the locked collectors, tools, and remote adapter the way a run does before collecting. Previously, on a machine where they were not installed yet, a check with a current lock stopped at "verifying adapter binary: opening binary: no such file or directory"- This affected the first check of a configuration fetched from a remote and checks in CI on fresh runners, including GitLab jobs run with
EPACK_CHECK=1
epack run --check now works before the first run of a configuration fetched from a remote.
Fixes
- In a folder fetched from a remote,
epack run --checklocks the configuration the way the first run does. Previously it stopped at "no epack.lock.yaml", and without a lock it could not verify the remote's adapter or sign in - In your own project, such as a folder committed for CI, a missing or stale lock is still reported with the
epack lockcommand to run and commit
Run a configuration a remote generated in one command, sign in with your browser, and sign runs with a key registered for the machine.
Runs
- Added
epack run: install the locked components, run the hooks, collect, run tools, sign, and push in one command. Given a configuration name, it fetches the configuration from the remote first. When a stage fails, the failure is reported to the remote with a stable code - Added
epack run --check(orEPACK_CHECK=1): sign in and verify the lock, secrets, credentials, and publishers, report the result, and collect nothing - A configuration fetched from a remote may only run collectors, tools, and remote adapters from trusted publishers. epack asks once in a terminal and records the answer in
~/.epack/config.yaml; a job names publishers with--trust-publisherorEPACK_TRUSTED_PUBLISHERS
Remotes
- Added
epack remote login: sign in with your browser, which returns to epack at127.0.0.1.--no-browserand--portsupport sign-in over SSH - Added
epack remote clone: fetch a named configuration into a folder, and pick up newer revisions without overwriting files you edited - Added
epack remote update: move the adapter installed for you, pinned in~/.epack/remotes.lock, to its newest release - The remote adapter protocol gains
auth.complete,config.pull, andkey.register,key.list,key.retire, andkey.revoke
Signing keys
- Added
epack key create,epack key list, andepack key rotate: make a key for the machine, register it with the remote, and wait for approval when the remote asks for it. Runs from the machine sign with the key once it is approved - A runner without its own identity signs in to the credential broker with its key, using
EPACK_SIGNING_KEYandEPACK_PIPELINE_ID. A GitHub Actions OIDC token or a GitLab ID token is used first when present - Added
epack verify --public-keyto verify packs signed with a key, andverify.WithPublicKeysin the SDK
Upgrade notes
- Sign-in moved from a device code to the browser.
epack remote loginneeds an adapter that supports browser sign-in, such asepack-remote-locktivityv0.2.0 - Adapters report a
browserauth mode where they reporteddevice_code
Version updates now re-lock every platform in the lockfile, so a lockfile updated on one OS works in CI on another.
Fixes
- When
epack update,epack lock, orepack installmoves a component to a new version, every platform already inepack.lock.yamlis downloaded, Sigstore-verified, and re-digested from the new release. Previously only the current platform was re-locked, and other platforms kept the previous release's digests, which failed sync on those platforms - A previously locked platform that the new release does not publish is now a lock error instead of a stale entry
Control mappings seal publisher-authored links from evidence to profile requirements into packs, plus toolchain and dependency security updates.
Control mappings
- A
mappings:section inepack.yamldeclares local mapping files (evidencepack/control-mapping@v1) recording which evidence supports which profile requirement - Each mapping file is locked by digest in
epack.lock.yaml, drift-checked, and verified under--frozen epack collectandepack runseal each mapping into the pack asartifacts/<name>.json, andepack buildaccepts a repeatable--mappingflag- Malformed entries, citations of artifacts the pack does not carry, and profile digests matching no locked profile are build warnings, never failures. Mappings never affect verification or validation results
epack inspectshows a Control Mappings section, the collect summary reports sealed entries, and lock provenance summaries gain amappingssection
Security
- Release binaries are built with Go 1.26.8, picking up the standard library fix for CVE-2026-39821
google.golang.org/grpcupdated to 1.83.1 for GHSA-vp52-pcj8-j9qc
Windows support for pack operations, catalog search across all component kinds, and dependency security updates.
Windows
- New
epack-core-windows-amd64.exeandepack-core-windows-arm64.exerelease binaries carry the same SLSA Level 3 provenance as every other platform - Windows covers pack operations: build, sign, verify, inspect, list, extract, merge, and diff. Collector and tool execution stays on macOS and Linux and fails closed on Windows
- Merge, filtered listing and extraction, and recursive result globbing handle Windows paths correctly
Catalog and utilities
epack catalog searchsearches collectors, tools, remotes, and utilities with an optional--kindfilter, andepack catalog refreshfetches the latest registry catalog with caching- The new
epack utilitycommand installs, lists, and removes user-scoped utilities with Sigstore verification, tracked in a global utilities lock
Security
- Dependency updates for published advisories in sigstore-go and grpc-go
- Path validation rejects rooted paths on every platform
Lockfile verification metadata: every locked component records whether its signature was checked at lock time.
Lockfile
- Locked collectors, tools, and remotes gain a
verificationblock recording the outcome of lock-time signature verification - Components locked from GitHub releases record
status: verifiedwith averified_attimestamp after their Sigstore bundles are checked against the pinned digests - External binaries record
status: skipped: they run from a local path and have no bundle to verify - Lockfiles written by earlier versions carry no
verificationblock, so consumers can tell verified and skipped entries apart from locks that predate verification recording
Committed-lockfile CI: strict locked installs, lockfile provenance reporting, and machine-readable errors.
CLI
- Added
epack sync --locked: clean-machine CI install that fetches exactly the locked versions with full signature and digest verification, fails on any drift, and never rewrites the lockfile - Added
epack remote report-lock: report the currentepack.lock.yamlto a remote without pushing a pack, for CI bootstrap and refresh flows - Sync and frozen paths now validate range satisfaction: a pinned version outside its configured range fails with
lock_config_mismatchinstead of silently keeping the old pin - Added
EPACK_ERROR_FILE: failed commands append stablecode=,exit=, andsummary=lines for log-free CI error handling - Runner context gains
head_shaviaEPACK_HEAD_SHA, the branch head onpull_requestworkflows whereGITHUB_SHAis the merge commit
Remote Protocol
- Added the
lock.reportcommand andlock_reportcapability for lockfile provenance reports (conformance rule REM-090) push.prepareandpush.finalizecarry a structuredlock_provenanceenvelope alongside the existing string build context, so releases record the exact lock that produced the pack
Errors
- New stable codes for frozen and locked failures:
lock_config_mismatch,lock_stale, andlock_missing_pinned_artifactreplace generic lockfile errors at the affected call sites
Richer artifact metadata for generated collector evidence.
Protocol
- Collector artifacts can carry
display_name,description, andcontrolsmanifest metadata
Go SDK
- Added
JSONArtifact,FileArtifact, andArtifactMetahelpers for metadata-bearing collector artifacts
Collector file artifacts for binary evidence such as PDFs, screenshots, and archives.
Protocol
- Added
EPACK_COLLECTOR_OUTPUT_DIR, a per-collector staging directory for raw file artifacts - Collectors can emit
fileartifact entries whose bytes are packaged at the declaredpath - Staged file paths reject traversal, absolute paths, symlinks, and non-regular files before packaging
- Staged bytes count toward artifact and pack budgets without counting against stdout limits
Go SDK
- Added
componentsdk.Staging(ctx)for optional file-artifact staging helpers - Added
WriteStagedFileandStageFilehelpers for buffered and streaming collector output
Security fixes for transitive dependencies.
Dependencies
- Bumped
go-joseto v4.1.4 to fix a JWE decryption panic (GHSA-78h2-9frx-2jm8) - Bumped
sigstore/timestamp-authorityto v2.0.6 for improper certificate validation in the verifier (GHSA-xm5m-wgh2-rrg3) - Bumped
go.opentelemetry.io/otelto v1.42.0 to fix a baggage-header allocation amplification (GHSA-mh2q-q3fh-2475)
Collection levels for graduated evidence gathering.
Protocol
- Reserved a top-level
levelconfig key with valuestrust,audit,internal; defaults totrustwhen absent - Levels are cumulative:
auditis a superset oftrust;internalis a superset ofaudit - Unknown values downgrade to
trustwith a stderr warning so collectors never gather more than was asked for - Collectors honoring the field stamp
collected_at_levelon their top-level artifact for downstream interpretation
Go SDK
- Added
componentsdk.LevelwithLevelTrust/LevelAudit/LevelInternalconstants - Added
ctx.Level()reader andLevel.AtLeast(other)comparator for gating field collection
Locktivity-managed credentials, portable hooks, build-context emission, and smoother GitHub Actions signing.
Managed Workflows
- Added top-level
credential_setsfor Locktivity-managed workflow integrations - Collectors, tools, and remotes can request managed credentials by logical ref
- Locktivity remote auth docs now reflect
access_token,device_code, andclient_credentials
Runner UX
- Added
epack hooks runfor portable project hooks under.epack/hooks/ - Added
epack context buildto emit build metadata for runners - Project scaffolding now keeps
.epack/hooks/tracked while ignoring other runtime state
CI/CD Signing
epack signnow uses ambient GitHub Actions OIDC automatically whenid-token: writeis granted- Other CI systems can continue to provide
EPACK_OIDC_TOKENexplicitly
Profile and overlay support, multiple collector artifacts, and new top-level commands.
Profiles & Overlays
- Added
profilesandoverlaysconfiguration sections in epack.yaml - Support for registry-sourced profiles with version locking
- Profile/overlay digests tracked in manifest for reproducibility
Collector SDK
- Breaking:
Emit()now accepts[]CollectedArtifactfor multiple artifacts per collection - New
CollectedArtifactstruct with Schema and Path metadata - Collectors can emit multiple artifacts in a single call
New Commands
epack catalog search— unified search across collectors, tools, remotes, and utilitiesepack catalog refresh— update local catalog cacheepack utility install/list/remove— manage global utilities
Remote Protocol
- Added
runs.syncandauth.whoamifeature capabilities - Consistent sync behavior across collector, tool, and remote adapters
Bug Fixes
- Fixed offline verification mode to properly use embedded timestamps
- Fixed JSON output returning
nullinstead of[]for empty arrays
Verification improvements and remote protocol enhancements.
Verification
- Improved error messages for attestation verification failures
- Added support for sigstore-js provenance bundles
Remote Protocol
- Added sidecar push support for parallel attestation uploads
- Improved push workflow reliability
Initial public release of the Evidence Pack specification and epack CLI.
Specification
- Evidence Pack format specification v1.0
- Manifest schema with SHA-256 digests for all artifacts
- Sigstore attestation bundle format
- Pack digest and manifest digest algorithms
CLI (epack-core)
build— create packs from artifactssign— keyless signing via Sigstoreverify— integrity and signature verificationinspect— view pack contents and metadatadiff— compare two packsmerge— combine multiple packslist— list artifacts in a packextract— extract artifacts from a pack
CLI (Full)
new— scaffold a new epack projectinit— initialize epack in existing directorycollect— run collectors and build packpush/pull— remote registry operationslock/sync/install/update— dependency managementcollector/tool— plugin management
Go SDK
pack— core pack types and operationspack/builder— fluent API for building packspack/verify— verification with policy optionssign— Sigstore signing integration
Stay Updated
Watch the repository for new releases and subscribe to release notifications.
View ReleasesVersioning Policy
epack follows Semantic Versioning:
- Major versions (1.0, 2.0) may include breaking changes to the specification or CLI
- Minor versions (0.2, 0.3) add new features in a backwards-compatible manner
- Patch versions (0.1.1, 0.1.2) include backwards-compatible bug fixes
Specification vs CLI versions
The Evidence Pack specification version is independent of the CLI version. The specification
is versioned in the manifest ("spec_version": "1.0") and changes less frequently
than the CLI.
Backwards compatibility
The CLI will always be able to read packs created by older versions. New features that require pack format changes will use new specification versions, and the CLI will indicate when a pack requires a newer version.