status: draft period: ongoing theme: sealed-publication-authority doc_type: protocol source_level: local-files confidence: high sensitivity: public evidence_grade: B review_state: unreviewed last_reviewed: 2026-07-15 ai_provenance: model_family: GPT-5 product: Codex generated_at: 2026-07-15 limits: Live provider configuration must be re-audited; no credential values are represented.
Sealed Publication Authority
Buildchain publication authority is a closed-world, fail-closed protocol. It does not mint registry or cloud credentials. It independently verifies whether an already protected publication job is allowed to request a short-lived provider credential for one exact product, target, version, channel, and artifact digest.
The machine-readable authority inventory is
dist/site/publication-authority-registry.json. Any workflow with a write,
environment, OIDC, cloud credential, registry publish, release, or Git push
signal must have an explicit descriptor. A new authority-bearing workflow that
is absent from the inventory fails site generation. Unknown workflows and every
descriptor not marked product-publication are denied product publication.
Evidence chain
A qualifying admission binds exact source and runtime SHAs; contract, consumer policy, qualifying controller receipt, Shifu/Gate aggregate, artifact, runner, and control-plane digests; repository, authority workflow, provider publisher workflow, Environment policy, product, target, version, and channel; plus a unique nonce and a lifetime of no more than 15 minutes. Every expected binding is mandatory at verification time; an omitted expected field is not a wildcard.
The independent verifier recomputes every digest and ignores a producer’s own
allow/deny conclusion. It fetches the exact evidence run, validates the actual
release-candidate passport and referenced qualifying controller receipt,
recomputes the Shifu Gate aggregate or explicit consumer-owned no-Gate policy,
recomputes the downloaded artifact manifests, and hashes every declared product
payload file against those manifests. The .buildchain/ diagnostics envelope is
bound by the manifest digest but excluded from the product-byte set because it can
be finalized after the lifecycle scan. The verifier also compares the PR evidence tree to the
admitted post-merge source commit tree. It rejects an unknown
workflow, stale or replayed nonce, runner downgrade, control-plane drift,
source/runtime mismatch, and artifact substitution. A successful result is a
scoped capability receipt, not a bearer credential.
Runner and control-plane evidence
Runner evidence uses exactly four classes: ephemeral, reimaged,
persistent-measured, and unqualified. Ephemeral runners also record their
job-isolation boundary. Reimaged and persistent runners qualify only when a
clean baseline is proven and baseline, toolchain, cache-contract, and task-
isolation digests are all present. Otherwise they still emit diagnostic
evidence with qualificationStatus = unqualified, but cannot receive a product
capability.
The external audit records digests and pass/fail status for repository Actions
defaults, classic branch protection or an active matching repository ruleset,
declared protected Environment policy or an explicit no-Environment binding,
job-scoped credentials,
absence of long-lived workflow publication credentials, provider authority,
and authorized runner class. Provider modes are npm-trusted-publisher,
github-token, and oidc-role. The OIDC-role mode consumes only a sanitized
provider audit containing a role digest and qualifying decision; raw IAM policy,
tokens, or credentials are rejected. Package-owner, cloud-root, GitHub
administrator, and registry-root credentials remain outside Buildchain’s trust
boundary. Missing or unreadable facts fail closed.
An unauthenticated local npm CLI is not evidence that Trusted Publishing is
missing. npm whoami reports only the local CLI session and does not report the
OIDC identity that npm creates during npm publish. The default read-only audit
therefore binds the exact provider, repository, caller workflow, optional
Environment, job-scoped OIDC permission, and absence of long-lived credentials,
then records provider-at-transaction: npm makes the final authorization
decision when npm publish exchanges the job’s OIDC token. A missing or drifted
trusted-publisher configuration consequently denies the transaction safely; it
is not preflighted through an unrelated long-lived npm login.
An authenticated external auditor can add stronger point-in-time evidence by
supplying sanitized npm trust list --json output with --npm-trust-json. This
changes the publisher fact to audited-control-plane; the workflow never runs
npm trust list itself and never receives that auditor’s npm credential.
The credential-free collector proves effective Actions and runner scope from
the publication workflow fetched at --workflow-ref: explicit read-only
workflow defaults, job-scoped write/OIDC permissions, and an exact GitHub-hosted
runner label. It does not call repository Actions-default or self-hosted-runner
administration endpoints. Branch/ruleset and OIDC subject facts remain live
read-only provider queries. When the detailed branch-protection endpoint is not
readable with the workflow token, --source-sha binds the provider’s public
protected-branch summary to the exact merged PR, independent approval, required
successful check, same-repository lineage, and current branch head. This records
provider-enforced transaction evidence without treating an unavailable
administration endpoint as an unprotected branch. It avoids turning a
repository-admin token into a publication prerequisite.
When a legacy caller declares a reusable job id such as build, the collector
accepts it only if the protected branch exposes exactly one required context
under build / ...; it then verifies that exact context, configured app, and PR
head SHA. Exact declarations remain unchanged, and ambiguous prefixes fail
closed.
For non-dry-run workflows, missing admission, runner, control-plane, Gate, or expected-binding evidence is rejected before Buildchain downloads candidate artifacts. The denial explicitly records that npm Trusted Publishing and OIDC were not evaluated, so downstream diagnostics cannot misclassify an admission assembly failure as an npm authentication failure.
An explicitly opted-in managed workflow_run promotion lane may assemble those
inputs from evidence owned by its caller repository. It downloads the exact prior RC passport,
summary, referenced controller receipt, manifests, and product payloads; proves
the admitted channel commit has the same Git tree as the RC; performs the live
read-only control-plane audit; records the GitHub-hosted job as ephemeral runner
provenance; and consumes either a caller-supplied Gate aggregate or an explicit
caller no-Gate decision. The
independent verifier then recomputes every receipt and payload digest exactly as
it does for externally supplied admission. Automatic assembly keeps Buildchain
as the canonical authority repository, requires evidence to belong to the
caller, binds a repository-local publisher workflow, and rejects unknown refs,
non-exact source SHAs, package/target mismatches, or an undeclared Gate policy.
Manual apply and consumers that do not opt in still require their own explicit
admission inputs.
Before authority verification, the reusable promotion controller runs the same release transaction selector in read-only mode. That plan supplies one exact publication version and tag to the admission verifier, the publish-gate source lock, and the real promotion action. The verifier rejects a capability for a different version, and the promotion action rechecks the planned version before any publish transaction side effect. Release-candidate fixture versions are artifact evidence only; they never name Buildchain’s own source-lock or publication capability.
Evidence publication is a separate authority class and never grants product publication.
Managed web-surface production
The reusable web-surface controller owns a complete standard producer path for
its documented production mechanisms. A reviewed matching release-PR merge or a
manual dispatch by an actor with current repository write authority creates a
signed decision bound to the exact source SHA. After build, verify, and
production planning, the workflow creates a qualifying pre-publication
controller receipt and assembles a ten-minute admission over the source tree,
immutable Buildchain runtime, deployment plan, artifact hash, production
Environment, AWS role/deploy target, runner provenance, decision digest, and
nonce. The independent verifier emits the scoped web-production capability.
The production job rechecks the capability and candidate against the same plan
before downloading product artifacts. AWS authorization is deliberately
recorded as provider-at-transaction: the capability binds the exact role and
Environment, while configure-aws-credentials performs the live OIDC exchange
and remains the final provider authorization gate before mutation. Buildchain
does not claim that an IAM trust relationship passed before that transaction.
Externally assembled admissions remain an optional compatibility path and must provide the full admission, runner, control-plane, Gate aggregate, expected bindings, and nonce set. They are not required for the managed web-surface release-PR or trusted-manual paths.
Consumer qualification handoff
Consumers may explicitly opt in to a final, consumer-owned qualification predicate. Buildchain then transports the complete Gate aggregate alongside the sealed capability instead of reducing it to a summary. The capability binds the authority registry, consumer Gate registry and policy, exact source and runtime, controller, runner, control-plane, artifact, provider target, channel, version, freshness window, nonce, and exact predicate command digest.
The predicate runs in a separate job with read-only source access, no inherited
secrets, no OIDC permission, and no provider write permission. It receives only
paths to capability.json and gate-aggregate.json plus the exact predicate id
and digest. The consumer writes a
kungfu-buildchain-consumer-publication-decision; Buildchain seals that result
as a deterministic
kungfu-buildchain-publication-qualification-receipt. Buildchain does not parse
product-specific Gate meanings.
The provider action revalidates the capability, full aggregate, receipt,
predicate identity, freshness, nonce, source, version, channel, target, and all
sealed digests immediately before the publish transaction. Missing, denied,
stale, replayed, substituted, or drifted receipts fail before provider mutation.
Direct calls to the provider action cannot bypass the receipt when
require-publication-qualification is enabled. Consumers that do not opt in
retain the existing publication contract.
API and CLI
Use @kungfu-tech/buildchain/publication-authority or run:
buildchain verify publication-admission admission.json \
--registry-json publication-authority-registry.json \
--runner-json runner.json \
--control-plane-audit-json control-plane.json \
--publication-evidence-json publication-evidence.json \
--expected-json expected.json \
--used-nonce previous-run-nonce \
--json
The read-only live collector defaults to npm trusted publishing. Other product providers select an explicit adapter:
buildchain audit publication-control-plane \
--repository kungfu-systems/buildchain \
--branch dev/v2/v2.12 \
--source-sha <exact-merged-branch-sha> \
--workflow .github/workflows/release-candidate-promote.yml \
--workflow-ref <exact-buildchain-sha> \
--publisher-workflow .github/workflows/buildchain-ref-promotion.yml \
--job promote \
--environment none
# Optional stronger external evidence; generate the JSON outside the workflow.
buildchain audit publication-control-plane \
--repository kungfu-systems/buildchain \
--branch dev/v2/v2.12 \
--workflow .github/workflows/release-candidate-promote.yml \
--publisher-workflow .github/workflows/buildchain-ref-promotion.yml \
--job promote \
--environment none \
--npm-trust-json sanitized-npm-trust.json
buildchain audit publication-control-plane \
--repository kungfu-systems/buildchain \
--branch release/v2/v2.12 \
--workflow .github/workflows/.binary-release-assets.yml \
--job publish \
--environment buildchain-release-assets \
--publisher-mode github-token
buildchain audit publication-control-plane \
--repository OWNER/CONSUMER \
--workflow-repository kungfu-systems/buildchain \
--branch main \
--workflow .github/workflows/.web-surface.yml \
--job production-apply \
--environment production \
--publisher-mode oidc-role \
--provider-audit-json sanitized-oidc-role-audit.json
The authority workflow identifies the reusable implementation that performs the
publication job. The publisher workflow identifies the caller filename bound by
the provider’s trusted-publisher policy; these identities are deliberately
separate. --environment none is an explicit assertion that the job declares no
GitHub Environment and the provider policy has no Environment restriction. A
named Environment must exist, be protected, and be declared by the job. The
Buildchain receipt alone is never sufficient authorization.
Publication lanes
Binary Distribution is evidence-only. It builds platform archives and a
release evidence bundle with read-only repository permissions. GitHub Release
asset writes live in Binary Release Assets, which downloads an exact prior
evidence run, verifies its bundle digest against the sealed capability, and is
the only binary job with contents: write in the protected
buildchain-release-assets Environment.
The npm/promotion, paper, binary-release, and web-production lanes all depend on the independent verifier. Preview, staging, build, source-check, controller, and failure-evidence lanes do not inherit product publication capability.