Releases publish the Python and TypeScript SDKs from one GitHub release event. Do not build or upload either package from a maintainer workstation.
Create protected GitHub environments named pypi and npm, each with a
required maintainer review and deployment restricted to protected tags.
Configure PyPI pending trusted publishing with:
- project:
agentrust-telemetry - owner/repository:
agentrust-io/agentrust-telemetry - workflow:
release.yml - environment:
pypi
Configure the npm trusted publisher for @agentrust-io/telemetry with:
- organization/repository:
agentrust-io/agentrust-telemetry - workflow:
release.yml - environment:
npm - allowed action:
npm publish
The npm package must be owned by the agentrust-io npm organization before its
trusted publisher can be configured. If npm does not expose publisher settings
until the first version exists, bootstrap only that first package ownership
using npm's interactive 2FA flow, then configure trusted publishing before any
subsequent release. Never store an npm publish token in GitHub.
- Move the changelog entries from
Unreleasedinto the new dated version. - Update
spec/VERSION; the Python and npm spellings are checked bytools/check_versions.py. - Run the complete CI and artifact smoke tests through a pull request.
- Merge the release-preparation pull request to
main. - Create a GitHub prerelease or release targeting
main, with tagv<contract-version>. - Approve the
pypiandnpmdeployment jobs after inspecting their exact source commit and built artifacts. - Confirm both registry versions, GitHub release assets, and provenance before announcing the release.
The workflow fails closed if the tag differs from the contract version. It requires the reusable CI workflow, including its Python matrix and TypeScript checks, to succeed before building. Failed, cancelled or skipped validation blocks both publishers. The final npm tarball is installed into a fresh consumer directory and exercised through its public imports, bundled valid/invalid conformance controls and golden event construction before artifact upload. The smoke check also verifies installed identity, import origin and declarations.
The release workflow builds each distribution once, sends the same artifacts to the registries, and attaches them to the GitHub release.
The npm dist-tag is derived from spec/VERSION by tools/npm_dist_tag.py, so a
prerelease publishes under alpha, beta, rc or dev and only a stable
version publishes under latest. npm refuses an untagged prerelease publish
outright, and an untagged stable publish would move latest, so nothing here is
left to the person running the release. If you ever must publish by hand, pass
the same tag: npm publish --tag "$(python tools/npm_dist_tag.py)".
Note that npm sets latest on a package's very first published version whatever
--tag says. That is expected on a bootstrap publish and corrects itself when
the first stable version ships. PyPI and npm create registry provenance
through trusted publishing; GitHub also attests the downloadable release assets.
CI runs python tools/check_workflow_oidc.py across every .yml and .yaml
workflow. The proposed existing-source baseline preserves release.yml jobs
publish-pypi, publish-npm and release-assets, and scorecard.yml/analysis.
It refuses workflow-wide OIDC grants even when current jobs override them,
write-all at either scope, and additions, removals or renames of these grants.
An intentional change needs review of the baseline and workflow delta together.
Unittest controls start from passing copies of the real workflows before each
mutation; a direct Python -O CLI check still refuses a broad grant.
This preserves current permissions, including the release-asset attestation and Scorecard grants; it does not establish that each grant remains necessary. The guard checks source, not live environment reviewers, administrator bypass, deployment restrictions, trusted-publisher bindings or backup-operator coverage. Those remain part of the release-safeguard sweep.