Use certify.py to collect, evaluate, redact, and package Cryptad release evidence.
The tooling requires Python 3.12 or newer and uses only the Python standard library. Run commands
from the repository root unless a command supplies --workspace-root explicitly.
Run every offline characterization and contract test:
python3 tools/release-certification/certify.py self-test allRun one focused suite:
python3 tools/release-certification/certify.py app-platform --self-test
python3 tools/release-certification/certify.py release-certification --self-test
python3 tools/release-certification/certify.py production-beta --self-test
python3 tools/release-certification/certify.py stable-rc --self-test
python3 tools/release-certification/certify.py stable-ga --self-test
python3 tools/release-certification/certify.py stable-backport --self-test
python3 tools/release-certification/certify.py stable-maintenance --self-test
python3 tools/release-certification/certify.py stable-lifecycle --self-test
python3 tools/release-certification/certify.py stable-supply-chain --self-test
python3 tools/release-certification/certify.py stable-dependency-vulnerability --self-test
python3 tools/release-certification/certify.py stable-vulnerability --self-test
python3 tools/release-certification/certify.py stable-protected-release --self-test
python3 tools/release-certification/certify.py stable-independent-reproducibility --self-test
python3 tools/release-certification/certify.py stable-catalog-authority --self-test
python3 tools/release-certification/certify.py stable-third-party-pilot --self-test
python3 tools/release-certification/certify.py stable-federated-catalog --self-test
python3 tools/release-certification/certify.py stable-platform-api-1x --self-test
python3 tools/release-certification/certify.py stable-legacy-plugin-migration --self-testBefore dispatching the protected Stable workflows, validate one versioned non-secret execution contract:
python3 tools/release-certification/certify.py stable-protected-release \
--mode preflight \
--execution-contract build/protected-release/stable-1.0-protected-release.jsonThe contract distinguishes authenticated Stable producer evidence, exact caller-supplied RC input
bytes, and gates that the protected RC run regenerates. Native third-party intake remains an exact
rcInputs file; the production-beta aggregate is regenerated rather than relabeling the native
bytes. After preflight, bind its exact passing summary as operationEvidence.preflight. The RC
workflow first checks the complete contract, exact receipt digest, and canonical passing receipt in
its credential-free job, before requesting the protected RC environment. It then invokes the same
command with
--mode rc-dispatch --rc-input-map <path> after materialization. This second side-effect-free check
rejects a missing or substituted preflight receipt and any changed evidence byte, Stable producer
coordinate, known-issues/intake/waiver/exception file, refreeze predecessor, source, release, mode,
authority class, target, or runtime app-signing/reviewer/review-policy/catalog identity before
stable-rc can freeze the candidate.
The default preflight summary remains directly beneath
build/release-certification/<execution-id>/stable-protected-release/; default RC-dispatch and
closeout reports use its rc-dispatch/ and closeout/ subdirectories. A bound preflight receipt is
immutable input evidence. The command rejects any explicit output path that would overwrite the
contract, RC input map, or a contract-bound evidence file.
After real workflow receipts and an independently produced public-observation record exist, update
that contract with their exact repository-relative files, immutable workflow/run/attempt/artifact
coordinates, the canonical GA validation and publication-plan members retained in the protected
validation artifact, its canonical validation-authorization identity member, and the separate
read-only observation coordinate, then run the same command with --mode closeout. Closeout
also consumes the unmodified RC and GA-publication Actions ZIP downloads, binds their container
digests to the authenticated workflow coordinates, and requires the local RC freeze and GA
publication receipt to be byte-identical to their canonical ZIP members. The RC ZIP also carries
the exact canonical preflight summary consumed by rc-dispatch; bind those bytes as
operationEvidence.rcPreflight. Closeout rejects a regenerated or re-serialized substitute even
when its decision is semantically equivalent. It consumes the exact RC freeze record bound by the
authenticated lineage, reconstructs the GA
promotion identity from the authenticated validation-authorization identity, and requires the
exact passing preflight receipt before protected completion. The publication plan cannot
authenticate its own digest. Repository policy selects every upstream schema and canonical Stable
public target form; contract rows cannot substitute a permissive schema or private/non-global
target. The command delegates release semantics to stable-rc and stable-ga; it does not freeze,
rebuild, publish, or infer remote success. See
docs/stable-1.0-protected-release-execution.md.
Run a CI-safe app-platform collection with the checked-in manifest:
python3 tools/release-certification/certify.py app-platform \
--manifest tools/release-certification/manifests/developer-dry-run.jsonAll non-test commands require a versioned JSON manifest. Copy one of the examples under
tools/release-certification/manifests/, replace its placeholders, and keep private keys,
passwords, tokens, private insert material, and reviewer key bytes out of the file.
The public entry point is tools/release-certification/certify.py.
| Command | Purpose |
|---|---|
app-platform |
Collect app-platform source, contract, app, security, recovery, and redaction evidence. |
app-platform-docs |
Validate developer portal, tutorial, beta-program, and documentation evidence. |
network-scale-soak |
Generate deterministic network-scale and budget evidence. |
live-network-beta |
Collect explicitly configured localhost live-network evidence. |
multi-node-beta |
Plan, run, or verify multi-node soak and previous-candidate upgrade evidence. |
security-response |
Verify the runbook or create and verify security drill artifacts. |
release-certification |
Aggregate release evidence and evaluate ecosystem certification gates. |
production-beta |
Build, certify, redact, and package a production-beta candidate. |
go-no-go |
Build the release-manager launch dashboard. |
stable-readiness |
Evaluate the Stable 1.0 promotion gate. |
stable-rc |
Execute, freeze, package, and verify a protected Stable 1.0 release candidate. |
stable-ga |
Validate and prepare explicit promotion of one exact frozen Stable 1.0 RC without rebuilding or publishing it. |
stable-backport |
Classify Stable 1.0 fixes, authenticate source-to-candidate provenance, account for one release train, and verify completion without changing Git or public state. |
stable-maintenance |
Authenticate, validate, freeze, and prepare one built-once Stable 1.0 maintenance or security-hotfix release. |
stable-lifecycle |
Evaluate and prepare authenticated Stable 1.0 build-support lifecycle transitions without publishing them. |
stable-supply-chain |
Assemble and verify Stable component, SBOM, license, isolated-rebuild, promotion, and publication-observation evidence; the CLI is side-effect-free and the protected workflow has an explicit publication boundary. |
stable-independent-reproducibility |
Prepare a candidate-byte-free verifier kit, authenticate a provider-distinct external build, reuse the Stable comparison authority, and produce protected closeout without publication. |
stable-catalog-authority |
Prepare and verify the role-separated Stable key ceremony, exact catalog publication, rotation and rollback drills, transparency artifact, and authenticated closeout without remote mutation. |
stable-third-party-pilot |
Authenticate one external developer handoff, reviewed/rejected/corrected/caution cohort, bounded publisher approval, PR-293 beta publication, exact live-collector bytes, isolated-node runtime drill, and read-only Actions-authenticated operational closeout without remote mutation. |
stable-federated-catalog |
Authenticate bounded signed discovery and non-transitive endorsements, local scoped trust and conflicts, pinned origin/runtime observations, and exact digest-bound PR-291–294 predecessor summaries and closeout coordinates without fetching or mutating local or remote state. |
stable-platform-api-1x |
Verify the append-only Platform API contract ledger, future-baseline proposals, experimental graduation records, monotonic deprecation timelines, static cross-release app matrix, bounded runtime observation, and exact PR-291–295 protected roots without activating a baseline or mutating release state. |
stable-legacy-plugin-migration |
Validate a closed sanitized local Sharesite observation while keeping private payloads out of evidence. Local claims remain unverified; runtime and closeout fail closed because no protected migration producer is configured. |
stable-dependency-vulnerability |
Validate authenticated advisory snapshots, exact PR-289 component matching, bounded dispositions, PR-288/287/285 remediation lineage, promotion, and public observation without live retrieval or remote mutation. |
stable-vulnerability |
Validate the protected Stable 1.0 vulnerability case lifecycle, exact disclosure authorization, publication observation, and closure without remote mutation. |
migrate-v1 |
Convert validated v1 previous-candidate or history summaries for the first v2 release. |
self-test |
Run one focused unittest suite or all suites. |
Use --help on the entry point or a command for its exact syntax.
The unified vulnerability engine is side-effect-free. Run it only from an isolated protected execution workspace after an approved protected assembler has materialized the exact phase input:
vulnerability_run_root="$(mktemp -d)"
# Resolve platform temporary-directory aliases before protected path validation.
vulnerability_run_root="$(cd "$vulnerability_run_root" && pwd -P)"
install -d -m 700 "$vulnerability_run_root/workspace"
install -d -m 700 "$vulnerability_run_root/protected-inputs"
git archive --format=tar HEAD | tar -xf - -C "$vulnerability_run_root/workspace"
# Materialize the authenticated flat phase set at
# "$vulnerability_run_root/protected-inputs", outside the archived checkout.
export CRYPTAD_STABLE_VULNERABILITY_PROTECTED_IN="$vulnerability_run_root/protected-inputs"
export CRYPTAD_STABLE_VULNERABILITY_PROTECTED_OUT="$vulnerability_run_root/protected-output"
(
cd "$vulnerability_run_root/workspace"
python3 tools/release-certification/certify.py stable-vulnerability \
--manifest "$vulnerability_run_root/protected-inputs/manifest.json"
)Its closed modes are evaluate-intake, read-only evaluate-promotion, validate-triage,
record-reporter-update, prepare-remediation,
validate-disclosure-authorization, verify-disclosure-publication, and verify-closure.
The checked-in policy is stable-1.0-vulnerability-disclosure-policy.json; the immutable empty
root is stable-1.0-vulnerability-ledger-genesis.json; and
manifests/stable-1.0-vulnerability.example.json shows the intake manifest shape. Its
protected-inputs/<name>.json values are names inside the isolated protected input root. A real
protected assembler materializes those exact flat names and never stores private material in the
repository build tree.
evaluate-promotion authenticates a genesis or unchanged predecessor ledger and emits a fresh
release/build-bound blocker summary without creating a case transition, successor ledger, or
public artifact. The protected workflow reseals that summary. Aggregate release certification
requires the exact summary, successor binding, materialization provenance, encrypted handoff,
protected handoff key, matching candidate release/build identities, and a current Actions
ledger-tip observation; self-digested, superseded, or wrong-candidate summaries fail closed. The
retention-independent authority is the closed, digest-chained
STABLE_1_0_VULNERABILITY_LEDGER_TIP_ANCHOR repository Actions variable. It must be explicitly
provisioned before first use to the compact, sorted JSON emitted by
jq -cS . tools/release-certification/stable-1.0-vulnerability-ledger-tip-anchor-genesis.json.
Missing, deleted, noncanonical, wrong-policy, or digest-invalid anchor state never means genesis.
Validators and promotion consumers receive only
CRYPTAD_STABLE_VULNERABILITY_ANCHOR_READ_TOKEN, scoped to repository Variables read. Every
appender compares its predecessor ledger digest and edition to
the freshly retrieved anchor before evaluation. Retained successor artifacts remain exact
producer and promotion evidence, but ordinary Actions retention cannot reset the ledger.
Backport and maintenance consumers use the same authenticator, but accept only
evaluate-promotion with null case-specific subject fields and the exact ledger-wide binding.
Their protected input artifacts carry the binding, provenance, and encrypted
sealed-successor/ files, never a plaintext ledger-wide summary; only the protected consumer
environment opens and materializes the exact summary in a confined external temporary root.
Release-candidate aggregate certification runs only in the protected
stable-1-0-release-certification job. Configure the vulnerability handoff key and anchor-read
token on that environment; PR and nightly certification run in a separate non-promotion job and
receive neither credential.
record-reporter-update is a protected append-only case transition for contactable reports. It
accepts exactly one new remediation-status-update, resolves the current reporter-status
obligation with that record, and creates the next policy-cadence obligation until exact public
observation ends the pre-disclosure cadence. It accepts no reporter address or raw message body.
Case-transition artifacts are proposals until
.github/workflows/stable-1.0-vulnerability-ledger-activation.yml authenticates the exact
successful validator artifact and performs the final compare-and-swap. That separate protected
environment alone receives CRYPTAD_STABLE_VULNERABILITY_ANCHOR_WRITE_TOKEN, scoped to repository
Variables write. It compares the expected anchor digest and sequence, advances exactly one ledger
edition, binds the producer workflow/commit/run/attempt/artifact and successor-binding digest,
then freshly reads back the exact canonical anchor. The shared cross-workflow lock serializes the
read/compare/update boundary. evaluate-promotion is read-only and cannot activate an anchor.
Multiple validator proposals for the same successor edition may coexist before activation. The
activation and promotion verifiers authenticate only the explicitly selected run, attempt,
artifact name, digest, and binding; they never infer committed history or a fork from other
unactivated proposals. After one proposal advances the anchor, every alternative built from the
old predecessor is stale and fails the anchor comparison without blocking later operations.
The support-lifetime protected archive remains responsible for the encrypted ledger bytes; the
anchor contains only bounded governance digests and producer coordinates.
The authoritative case, ledger, report envelope, acknowledgements, authorizations, and operational
summary are never written into the repository’s ordinary build/ tree. The case and successor
ledger go only to the mandatory protected output directory, which must be initially empty and
outside the repository and public run. Protected workflows seal it with
protected/stable_backport_protected_handoff.py using the separately configured
CRYPTAD_STABLE_VULNERABILITY_HANDOFF_KEY_BASE64. Policy and engine cap the exact canonical ledger
at the handoff primitive's 16 MiB per-file limit; the independent 4,096-case ceiling does not
authorize an oversized, untransportable ledger. Before disclosure, an Actions public upload
contains only the case-scoped public-safe projection and passing redaction result. The bounded operational
summary and its ledger-wide report remain encrypted even after disclosure. Independent exact-byte
observation permits only the current case's projection, advisory, publication receipt,
public-observation receipt, and passing redaction result to enter the public upload.
The checked-in workflows are validation shells, not a report collector or network publisher.
Configure the repository variable STABLE_VULNERABILITY_PHASE_ASSEMBLER_WORKFLOW to the exact
approved protected assembler workflow path. It authenticates the prior protected successor, joins
only the new phase-specific protected inputs, creates the canonical manifest, and emits the sealed
phase artifact. No initial case can enter until that configured producer exists; validators fail
closed rather than inventing a report source.
Mitigation, catalog-security, and key-lifecycle receipts are not trusted from their embedded
producer object. Before sealing a phase, the configured assembler must authenticate the native
authority workflow against its protected allowlist, exact commit, successful run attempt, one
non-expired exact artifact name/digest, and the exact bounded receipt member. It emits
stableVulnerabilityAuthorityReceiptProvenance, bound to the canonical receipt file and semantic
digests, in the encrypted bundle. Disclosure authorization and closure require that provenance
whenever one of those receipts is present. A mitigation-only case is noncritical and remains on the
policy's routine-maintenance lane; it cannot use security-hotfix as a lane exception.
Configure STABLE_VULNERABILITY_OBSERVER_WORKFLOW to the exact independent read-only observer
workflow path. Remote publication belongs to a separately protected, attested advisory provider.
The provider returns an append-only exact-byte receipt; the observer authenticates it and performs
a fresh public read without mutation credentials. The checked-in
stable-1.0-vulnerability-disclosure-publication.yml workflow authenticates the observer
run/artifact and validates those records. It never publishes.
All four validators require exact release id, integer build, source commit, producer run
id/attempt, artifact name/digest, phase-manifest digest, and predecessor ledger edition/digest.
Case-transition modes require an opaque case id, while evaluate-promotion requires the reserved
ledger-wide subject. The publication-observation validator also requires the publication-receipt,
public-observation, and advisory-byte digests. They authenticate one non-expired exact Actions
artifact before download, reconstruct the expected HMAC binding, execute in a temporary
Git-archive workspace, generate a successor-specific binding, and stage exact scanned protected or
public file allowlists.
The command validates PR-287, maintenance/hotfix, CoreUpdater, lifecycle, catalog, and key
receipts; it does not execute those authorities. It performs no network or Git mutation and does
not allocate CVE/GHSA identifiers. See
docs/stable-1.0-vulnerability-intake-and-coordinated-disclosure-operations.md for phase inputs,
SLAs, workflow roles, advisory publication boundaries, and closure rules.
certify.py is a thin entry point. Keep the public contract and shared safety boundaries in the
cryptad_certification package:
cryptad_certification/
cli.py command tree and collection orchestration
manifest.py strict release-run manifest loading
workspace.py marked, candidate-scoped workspace confinement
envelope.py evidence envelope v2 normalization and validation
redaction.py reusable evidence and migration scanning
migration.py one-time v1 history conversion
legacy.py controlled adapters for the split engines
engines/ component implementations, split by responsibility
tests/ contract, characterization, workflow, and safety tests
Do not restore the removed top-level per-engine scripts or shell wrappers. Split an engine by
responsibility before a Python source file exceeds 5,000 lines; self-test core enforces that
limit.
The manifest schema is schemas/release-run-v1.schema.json. A manifest contains:
- release identity, version, and profile;
- output and reset policy;
- required evidence and promotion gates;
- non-secret input paths;
- catalog, artifact, freshness, and signing-profile labels;
- execution controls and command-specific arguments.
The structured maps are closed contracts. Unknown keys and values of the wrong type fail before the release workspace is prepared:
| Map | Supported fields |
|---|---|
requirements |
Boolean history, liveNetwork, multiNodeSoak, sandboxProviderTests, stableReadiness, and thirdPartyIntake gates. |
inputs |
Non-empty paths for interop, performance, app-platform, live-network, network-scale, multi-node, security-drill, production, dashboard, certification, Stable, waiver, policy, known-limitation, previous-candidate, release-history, stable catalog operations, previous Stable RC freeze, Stable RC freeze exceptions, and the selected Stable RC/GA validation, authorization, policy, lineage, or optional publication-receipt artifacts. |
policies |
artifactBaseUri, catalogChannel, candidateSourceCommit, candidateSourceRef, expectedPreviousReleaseId, expectedPreviousProductDigest, historyDir, historyLabel, publicationIntent, stableRcFreezeMode (first-freeze or refreeze), and string-valued metadata. |
execution |
Boolean collection/build/test controls plus positive integer timeoutSeconds. |
commands.<name>.args remains an advanced engine-specific escape hatch. The unified command owns
workspace, output, mode, and release identity arguments and removes attempts to override them.
Exact controlled options are removed, and abbreviated forms are rejected before legacy argparse
processing so prefixes cannot escape the marked workspace or replace candidate policy and identity.
For commands that evaluate release policy, commands.<name>.mode may only restate the mode derived
from release.profile; a conflicting value is rejected instead of weakening or relabeling the
candidate. commands.multi-node-beta.mode remains the separate topology execution mode.
Supported profiles are pr, nightly, developer-dry-run, release-candidate,
production-beta, and stable-review. Unknown fields, unsafe release IDs, incompatible types,
secret-like field names, and secret-bearing scalar values fail before a command creates artifacts.
The loader rejects private SSK/USK material, private keys, authorization values, credentials, and
secret assignments without copying the rejected value into its error message.
--workspace-root and --out-root are the only location overrides outside the manifest. Relative
input paths are resolved from the workspace. Secret inputs continue to use the protected
environment variables and protected files documented by the production release workflow.
Every command writes below one release-scoped directory:
<out-root>/<release-id>/
.cryptad-certification-run.json
<component>/
summary.json
report.md
redaction-report.json
artifacts/
For Stable 1.0 RC execution, copy
manifests/stable-1.0-rc.example.json, replace every placeholder, and run:
python3 tools/release-certification/certify.py stable-rc \
--manifest build/stable-1.0-rc.jsonThe manifest retains the stable-review profile and integer build number. The command generates a
unified production-beta component inside the same marked run; that protected pipeline produces and
binds its go/no-go, release-certification, app-platform, ecosystem-matrix, and Stable-readiness
native artifacts for the Stable RC engine. Do not attach unrelated precomputed copies to the
canonical manifest. External prerequisites use the coordinated stableCatalogOperations,
previousStableRcFreeze, stableRcFreezeExceptions, and authenticated
stableVulnerabilitySummary input names. The manifest must set
requirements.stableVulnerability=true and
policies.stableVulnerabilityGovernance=required. The protected workflow accepts only the exact
current ledger-wide evaluate-promotion run/attempt/artifact coordinates, opens the encrypted
handoff outside public roots, and forwards the release/build-bound summary into nested aggregate
certification. The RC engine then requires the exact passing non-waivable PR-288 evidence and
child gate; a generic passing aggregate or omitted summary cannot authorize the RC. Stable RC
output lives under
<out-root>/<release-id>/stable-rc/; see the
Stable RC runbook for its freeze schema,
artifact inventory, drift and exception semantics, and protected workflow.
stableCatalogOperations.artifactTimestamp is the immutable producer timestamp for the signed
catalog and first-party review receipts. The same protected value is used on every refreeze. The
production pipeline emits crypta-stable-1.0-rc-<build>-product.tar.gz with normalized member
metadata and no run-specific evidence reports; this is the exact distribution bound by the Stable
RC freeze. The ordinary production-beta evidence archive remains available to its existing
consumers. These requirements apply only when stable-rc orchestrates the production stage; a
direct production-beta run with the stable-review profile keeps the pre-existing manifest and
intake contracts.
Set policies.stableRcFreezeMode=first-freeze only for the initial candidate baseline and omit
inputs.previousStableRcFreeze. Every later run uses stableRcFreezeMode=refreeze and must supply
the exact freeze from the latest successful protected workflow run. The workflow authenticates
that parent against the latest uploaded artifact when available. Each successful protected run
also creates a commit-bound check-run lineage anchor for the exact freeze file digest, release,
build, run, and attempt. After the uploaded artifact expires, a retained freeze is accepted only
when its digest matches that latest authenticated anchor; stale or unauthenticated lineage fails
closed. The canonical freeze binds the exact deterministic product-distribution digest. Rebuilding
the unchanged candidate must produce identical bytes; a catalog, review receipt, bundle, launcher,
policy, or product member change remains candidate drift even when semantic producer summaries are
unchanged.
For Stable 1.0 GA validation, copy
manifests/stable-1.0-ga.example.json, replace every placeholder, and run:
python3 tools/release-certification/certify.py stable-ga \
--manifest build/stable-1.0-ga.jsonstable-ga retains the stable-review profile and writes to
<out-root>/<release-id>/stable-ga/. It is side-effect-free: the command authenticates one exact
successful Stable RC, evaluates post-freeze production validation and explicit GA authorization,
and prepares promotion records. It does not rebuild the product, create a branch or tag, publish a
GitHub Release, change a catalog, insert an update descriptor, or perform a network insert.
The GA manifest uses these exact input names:
selectedStableRcSummary
selectedStableRcFreeze
selectedStableRcFreezeSidecar
selectedStableRcArchive
selectedStableRcProduct
selectedStableRcChecksums
selectedStableRcProvenance
selectedStableRcLineage
previousCandidate
stableRcValidation
stableGaAuthorization
stableGaPolicy
stableGaPublicationReceipt
stableGaPublicationReceipt is optional and is used only to verify a returned protected
publication result. stableGaPolicy normally points to the checked-in
stable-1.0-ga-policy.json. The non-secret policy values bind the public HTTPS artifact base,
stable catalog primary/mirror/rollback confirmation URIs, stable catalog channel, exact candidate
source commit/ref, and publication intent. The canonical metadata keys are
catalogPrimaryUri, catalogMirrorUris, and catalogRollbackUri; all three are included in the
authorized publication-target digest. Stable GA also requires expectedPreviousReleaseId and
expectedPreviousProductDigest. The exact migrated previousCandidate envelope authenticates the
predecessor release/build against the PR-283 freeze and provenance, while the manifest supplies the
published predecessor product digest; the authorization identity binds all four predecessor
fields. Signing keys,
private insert URIs, GitHub credentials, authorization headers, tokens, and publication credentials
remain protected environment or file inputs and must never appear in the manifest.
The selected RC files must form one authenticated, symlink-free artifact set. Stable GA verifies
the common RC envelope; freeze schema, canonical digest, and sidecar; exact checksums; provenance;
outer archive; immutable product; catalog, app, Platform API, content-profile, limitation, waiver,
and freeze-exception bindings; and latest protected refreeze lineage. The post-freeze
stable-1.0-rc-validation record must bind every scenario to the exact frozen product digest and
meet the checked-in policy, including at least 24 hours of real production soak measured from the
long-soak scenario's own timestamps. Top-level validation and scenario start times must not precede
the authenticated protected RC run completion in the selected lineage.
Because the vulnerability ledger can advance during that interval, the RC-time decision is not a
GA-time authorization. Every publish=true GA dispatch supplies a new exact ledger-wide
evaluate-promotion run, attempt, artifact name, and artifact digest. The protected publication
job holds stable-1-0-vulnerability-ledger, authenticates the selected producer and current anchor,
opens and validates the sealed summary outside public roots, and rejects any promotion blocker
before the first tag, Release, or asset mutation. None of that handoff enters the GA artifact.
For the explicit authorization review pass, set commands.stable-ga.mode to
prepare-authorization and omit stableGaAuthorization. The command validates the exact RC and
writes stable-1.0-ga-validation-authorization-identity.json, but it does not report promotion
readiness. The protected authorization's gaValidationDigest is the canonical semantic SHA-256 of
that identity. The identity and authorization also bind a canonical publication-target digest for
the expected tag and release branch, artifact base, catalog primary, ordered mirror list, and
rollback catalog location.
Changing any destination requires a new preparation, authorization, and protected evidence pass.
Rerun in validate-only mode with the authorization input. This two-pass contract prevents an
authorization/final-record circular digest and rejects authorization or publication receipt inputs
during the preparation pass.
Input acquisition and producer authentication are separate controls. A confined repository path,
public HTTPS URL, or actions-artifact:// reference only determines how the workflow obtains a
record. Before publication, run .github/workflows/stable-1.0-ga-promotion.yml with
publish=false on the exact release/<build-number> candidate. The protected
stable-1-0-ga-evidence job attests the exact validation, authorization, and canonical
publication-target identity bytes. A later publish=true dispatch accepts only identical bytes and
destinations with attestations from that workflow, release ref, candidate commit, and a
GitHub-hosted runner. After protected publication approval, it reruns stable-ga before every
tag, Release, asset-upload, or finalization mutation and again before recording completion. Thus,
evidence, waivers, authorization, or targets that expire or change during a lengthy publication
attempt fail closed at the next mutation boundary.
The protected publication environment also supplies STABLE_CATALOG_TRUSTED_KEYS_BASE64, a
base64-encoded production trusted catalog public-key properties registry. The workflow uses it
only to verify freshly fetched primary, mirror, and rollback catalog signatures and deletes the
decoded file before job exit. It must not contain private signing keys and is never a manifest or
public artifact input. The retained rollback revision must verify under the catalog signing-key
identity frozen by the selected RC.
The native public output includes:
stable-1.0-ga-validation.json
stable-1.0-ga-validation-authorization-identity.json
stable-1.0-ga-authorization-summary.json
stable-1.0-ga-promotion-summary.json
stable-1.0-ga-go-no-go.md
stable-1.0-ga-known-limitations.json
stable-1.0-ga-release-notes.md
stable-1.0-ga-publication-plan.json
stable-1.0-ga-publication-receipt.json
stable-1.0-ga-checksums.txt
stable-1.0-ga-provenance.json
stable-1.0-maintenance-baseline.json
The public checksum file names the six non-checksum Release assets. The checksum file is the seventh planned asset and is itself bound by its size and digest in the publication plan, provenance, and receipt. Internal validation, authorization, and redaction records are not added to the public checksum rows because they are not public Release assets.
All seven planned assets must already exist at the independently populated artifactBaseUri
before a protected publish=true dispatch. The publication job verifies them immediately before
its first mutation and again after GitHub publication. The canonical publication receipt is
generated only when a returned publication result is independently verified. A
passing pre-publication run records validated or publication-authorized; it must not claim
publication-complete. Publication verification fetches every planned asset from both the GitHub
Release and its exact artifactBaseUri + <asset-name> public location. The receipt binds that base
and each asset's exact public URI, size, and digest, and rejects every unplanned or non-passing
asset row. See the
Stable GA runbook for exact-RC selection,
24-hour validation, authorization, protected publication, conflict recovery, catalog verification,
receipt semantics, and the post-1.0 maintenance baseline.
Nested operations use nested component names, for example multi-node-beta/run/ and
security-response/drill-run-all/. JSON and Markdown artifact references are relative to the run
root. The common summary.json, report.md, and redaction-report.json are the public component
surface. Component-specific engine output remains below artifacts/legacy/; extracted reusable
inputs remain below artifacts/inputs/.
A manifest with output.reset=true may replace only a directory containing a matching run marker.
The command rejects unmarked directories and markers for another release, version, or profile.
This prevents a misspelled output path from deleting source-controlled files and prevents stale
candidate evidence from being silently reused.
When execution.collectEvidence=true, every internally collected component is deleted and rebuilt
before aggregation, even when output.reset=false. To reuse evidence intentionally, provide it
through the corresponding inputs field; the adapter then applies that evidence type's identity,
status, freshness, and redaction validation instead of treating an interrupted component as a
cache.
Before replacing an internally collected component, every path segment is checked for symlinks and
workspace confinement so cleanup cannot follow an intermediate link into another component.
Nested legacy-engine output directories are checked before and after creation so a restored or
tampered artifacts/legacy symlink cannot redirect engine writes outside the marked run.
The shared JSON and text writers also reject symlinked file targets. Extracted-input directories,
security-drill sidecars, and production output staging receive the same resolved-path confinement
checks before a write or cleanup.
When an aggregate release-certification/summary.json already exists, recollection is rejected
before any component is deleted or rebuilt; use output.reset=true for a complete rerun.
Every summary.json follows schemas/evidence-envelope-v2.schema.json. The common envelope
contains:
subject: release ID, version, profile, and component;result: normalizedpass,warn, orfail, a component decision, promotion readiness, and exit code;- evidence, blocker, warning, and waiver counts;
- standard evidence rows, issues, and waiver records;
- a redaction result and non-secret guarantees;
- relative input and artifact references;
- component-specific data under
payload.
Consumers validate every required envelope field, nested field type, evidence kind, candidate
identity, profile compatibility, component identity, declared version, array count, result
consistency, and redaction status before unwrapping payload.legacy. Strict profiles reject
evidence produced by PR, nightly, or developer-dry-run policy. Stable review may consume the
production-beta evidence it evaluates, and release or production aggregation may consume an
explicit Stable-review summary; these are the only cross-profile input transitions.
For release-candidate, production-beta, and stable-review, an attached v2 input also requires
a non-null manifest release.version. The adapter rejects the input instead of treating an absent
expected version as a wildcard.
Relative and absolute manifest inputs are resolved against the workspace before publication and
rendered only as <repo>/... or <external-input>. A component process with a nonzero exit always
produces failed evidence; pass and warn envelopes require exitCode: 0.
Legacy outputs without native redaction metadata pass only after a complete payload scan; malformed
metadata, scan findings, or false direct/nested guarantees fail the envelope. Production-beta
envelopes expose the final nested goNoGo.decision through the common result.decision field.
Negative live-network safety facts such as rawBodiesStored: false are converted to positive v2
guarantees such as rawBodiesNotStored: true; an unsafe true value still fails closed.
Migration and fallback scans inspect nested JSON field names as well as values, rejecting
payload-bearing password, token, key, private-URI, raw-body, and raw-app-data fields. They also
reject POSIX, Windows drive, and UNC absolute filesystem paths outside the documented public route
shapes before any migrated artifact or envelope is written. Canonical sanitized
<repo>/relative/path values are allowed so existing release-certification history can migrate;
malformed, traversing, mixed, or backslash-bearing placeholders remain blocked.
Each unified component input has one expected v2 kind and rejects raw v1 summaries as well as v2
envelopes of another kind. Explicit external or non-envelope inputs—interop, performance,
ecosystem matrix, and third-party intake—retain their native JSON contracts, and their input slots
reject v2 envelopes instead of accepting an arbitrary kind.
Non-migration policy consumers may inspect warn evidence with
passing redaction so Stable waiver evaluation can run. Failed results and failed redaction remain
rejected, and migrated previous-candidate/history evidence remains pass-only. Reused
inputs.securityDrills envelopes also restore the referenced public drill JSON files beside the
extracted legacy summary so downstream digest and scenario validation sees the same complete
artifact set that the v2 producer published. Every referenced drill sidecar is parsed, scanned,
and checked against its recorded digest before it is copied. The verification adapter copies from
the effective configured input directory, not from a previous internally generated drill run.
Attached v2 payloads are scanned before extraction even when their outer redaction record says
pass. Safety-labelled fields are exempt only when their value has the expected scalar, boolean,
or digest shape; containers are still traversed. Credential assignments, cookie or authorization
values, credential-bearing URLs, local file: URIs, filesystem roots, and labelled absolute paths
remain findings. Canonical sanitizer output such as <repo>/..., <path>/python3, relative app
assets, and public API routes remains reusable.
If an engine writes unsafe output, the adapter removes the raw legacy copies from the publishable
workspace and emits only sanitized failed evidence. Early engine SystemExit, nonzero exits, and
redaction failures all produce a failed common envelope with promotionReady=false. Common
normalization preserves production failure reasons as blockers and release-certification
waiverRecords as auditable v2 waivers.
Normal v2 consumers reject legacy release-certification summaries. Convert the previous beta candidate once with:
python3 tools/release-certification/certify.py migrate-v1 previous-candidate \
--manifest path/to/release-run.jsonSet inputs.previousCandidate in the manifest. Use migrate-v1 release-history with
inputs.releaseHistory for the previous certification record. Migration validates the source
shape, release binding, status, and redaction state, records its SHA-256 digest, and writes the
converted artifact under the marked release workspace. It does not run automatically.
Redaction must use either an explicit passing status with an empty findings array or the older recognized boolean-guarantee form with every recognized guarantee set to true; missing, unrecognized, malformed, or contradictory redaction metadata is rejected.
For the subsequent certification or production run, point inputs.previousCandidate or
inputs.releaseHistory at the corresponding migration component’s v2 summary.json. Normal
adapters validate its candidate binding and redaction result, then extract the legacy payload into
the current component’s adapter area. They reject a raw v1 path.
The migration manifest and the consuming run manifest must use the same release.id. For a
protected production workflow dispatch, set candidate_release_id to that value. Do not use a
workflow run number as the candidate identity because the migration artifacts must be prepared
before the consuming workflow starts.
The release workflows derive release.version from ./gradlew -q printVersion. Bind migrated and
attached v2 evidence to that checked-out build version; a matching release ID does not authorize
evidence for another build version.
For a release-certification workflow dispatch, set candidate-release-id whenever
previous-summary-path is supplied; the workflow rejects migrated history without its bound
candidate identity. The same explicit identity is required for any attached candidate-bound v2
multi-node, security-drill, or Stable-readiness summary, even when the corresponding gate is
optional.
Migration output is immutable within a completed marked workspace. A second migration for the
same release and kind is rejected when output.reset=false; use an explicit matching reset to
replace the candidate-bound record and its source digest.
Set execution.writeHistory=true to archive a completed certification result. Unless
policies.historyDir is set, the legacy aggregator keeps its shared default at
build/release-certification-history/, outside the per-candidate run root. Passing runs update
latest-summary.json, latest-history-comparison.json, and
releases/<history-label>/; failed candidates are retained under failed/<history-label>/
without replacing the last passing summary. Set policies.historyLabel when the release label
cannot be derived safely. The release-certification workflow uploads both the candidate workspace
and this shared history directory.
Release-candidate, production-beta, and Stable review modes remain fail closed. Missing, stale,
malformed, wrong-candidate, skipped, fixture-only, or redaction-unsafe required evidence cannot
promote a release unless the existing policy explicitly permits a valid waiver.
Requirements are evaluated by the gate engine rather than treated as manifest dependencies. In
particular, requirements.history=true without inputs.releaseHistory is valid configuration and
records the missing mandatory history in the certification report; release-candidate policy fails
the aggregate and blocks promotion.
Redaction findings involving private insert URIs, private keys, signing material, form passwords, tokens, cookies, authorization headers, raw fetched content, raw app data, identity material, browser sessions, local absolute paths, unsafe archives, symlinks, or special files remain non-waivable. Do not publish private interop insert material or raw live-node fixtures.
The multi-OS CI job runs:
python3 tools/release-certification/certify.py self-test allThe characterization suite runs on Ubuntu, macOS, and Windows with Python 3.12. Ubuntu and macOS
retain a 30-minute job limit; Windows has a 60-minute limit because the same subprocess-heavy
scenarios run materially slower there. Integration assertions compare canonical paths so macOS
aliases such as /var and Windows temporary-directory aliases do not create false failures.
Release workflows generate their runtime manifest with jq from workflow-dispatch inputs. Secret
values remain in protected environment variables or files and are never serialized into the
manifest or uploaded workspace.
.github/workflows/stable-1.0-rc-release.yml is manual and protected. It requires an explicit
candidate release ID and integer build, JDK 25, a clean candidate commit, production
signing/reviewer material, full build/stage/sign/verify, and real live, sandbox, multi-node,
previous-candidate, network-scale, security-drill, third-party-intake, and catalog-operations
evidence. It verifies the post-package freeze, checksums, archive hygiene, final v2 redaction, and
go/go-with-waivers result before uploading only the public RC component. It does not tag,
release, merge, or publish Stable 1.0 GA.
.github/workflows/stable-1.0-ga-promotion.yml keeps validation, protected evidence attestation,
and publication in separate jobs. The validation job authenticates the latest protected Stable RC
run and has no tag or GitHub Release permission. Protected HTTPS acquisition rejects redirects,
URL credentials, query strings, fragments, non-public DNS results, and local/private targets;
repository and Actions-artifact inputs remain path-confined and reject symlinks and special files.
The evidence job requires stable-1-0-ga-evidence approval and attests the exact validation,
authorization, and canonical publication-target identity bytes. The publication job requires an
explicit dispatch selection, passing validation, prior evidence attestations, and approval in the
stable-1-0-ga environment. It reruns
the gate at every publication mutation boundary, holds the global vulnerability-ledger lock after
its current nonblocking handoff check, uses the required leumor GitHub identity,
creates or verifies the annotated v<build-number> tag and exact GitHub Release assets, fetches the
same assets from the declared artifact base, and verifies the unchanged stable catalog at the
primary, mirrors, and authorized rollback URI. It never merges a release branch automatically.
Matching existing public state is idempotent only after a fresh latest-RC lineage query;
conflicting state fails closed. The failure audit path is read-only and uploads a sanitized failed
receipt even when no side-effect marker or GitHub Release exists. Recovery distinguishes an
observed absence from an unavailable GitHub observation and records only counts and SHA-256
identifiers for unplanned remote asset names. The receipt must pass its closed schema, placeholder,
and redaction checks before upload. Only a verified publication receipt may record
publication-complete.
The Stable RC and Stable GA workflows share one integer-build concurrency group across validation,
protected approval waits, and publication. Cancel a waiting GA run before an urgent refreeze and
inspect the shared build queue, because GitHub retains at most one pending run for the group. During
publication the workflow also rereads release/<build-number> at every side-effect boundary,
before creating a tag reference from a newly created tag object, and before accepting idempotent or
new public state as publication-complete.
Follow the production security response runbook when collecting release-blocking drill evidence or responding to an app ecosystem incident.
Use stable-backport before stable-maintenance to govern the exact contents of one routine or
security-hotfix candidate:
python3 tools/release-certification/certify.py stable-backport \
--manifest build/stable-1.0-backport.jsonThe component has four side-effect-free modes:
evaluatevalidates intake, policy, lifecycle coverage, prior queue state, and proposed dispositions before any accepted fix is required to be landed;prepare-candidatebinds the exact candidate, source-to-candidate provenance, evidence, and complete commit/change coverage;validate-authorizationvalidates a narrow authorization for the exact train composition and candidate handoff;verify-release-completionauthenticates publication, lifecycle activation or an explicit pending state, and no-squash--no-ffreconciliation intomainanddevelop.
The candidate may advance between evaluate and prepare-candidate while approved fixes are
landed. Candidate equality is frozen from prepare-candidate through authorization, maintenance,
and completion; it is not required for the pre-landing evaluation handoff.
The versioned policy closes classifications, dispositions, states, provenance modes, deadlines,
roles, Git object rules, queue bounds, evidence windows, redaction, and non-waivable blockers. The
two release lanes are routine-maintenance and security-hotfix; future-milestone, deferred,
and rejected keep ineligible or unscheduled work outside a Stable candidate.
Git evidence uses full canonical commit object ids and verified object graph operations. It rejects
abbreviations, symbolic revision syntax, wrong repositories, spoofed branch roles, wrong bases,
parallel predecessors, patch-id misuse, missing candidate ancestry, and incomplete manual conflict
evidence. Routine manifests carry policies.developmentLineageCommit: the protected workflow
resolves and freezes the exact protected develop tip independently of candidateBaseCommit,
then the engine requires the declared base to be the exact candidate/lineage merge base and a
member of that protected tip's first-parent chain. A merged side-parent tip is not an authenticated
develop base. Patch
identity supports a reviewed clean-cherry-pick; it never authorizes one.
Clean cherry-pick and manual-conflict records also require an exact
stableBackportReviewAuthorizations protected input. Each row comes from the successful
.github/workflows/stable-1.0-backport-review-authorization.yml producer in the
stable-1.0-backport-review environment and binds the reviewer role, policy, source,
predecessor, candidate, normalized diff, path inventory, focused tests, validity interval, run,
workflow, and artifact. Matching caller-provided digests without that producer artifact fail.
Security-hotfix manifests instead carry policies.mainLineageCommit, independently resolved from
the exact protected main tip. The hotfix base must equal that tip, while the tagged publication
predecessor must remain its ancestor; branching directly from the predecessor cannot omit a later
main reconciliation merge or its resolution.
The queue is append-only and digest chained. It carries unresolved accepted fixes, deferred and
rejected history, superseding relationships, critical obligations, hotfix follow-up, and prior
merge-back obligations. Candidate coverage assigns every commit or change to an accepted fix,
approved release metadata/tooling/docs, explained merge context, or unaccounted; any
unaccounted entry blocks the train.
Each evidence row carries the exact reviewed policy and queue digests. The queue digest normalizes
only its embedded evidence queue-binding slots before hashing, which provides deterministic
self-binding without excluding the evidence content or any other queue field. Policy-designated
protected evidence must remain visibility: protected.
Landed fix provenance is immutable. Resolving a carried obligation requires a new evidence digest, and both that digest and its resolution timestamp are immutable after resolution. Security incident/advisory identity and severity are immutable across queue snapshots. A disposition or lane change must be explained by an appended state transition, which prevents a critical security record from being relabeled as noncritical routine work.
GA is the sole queue genesis. A later maintenance successor must provide both
previousStableBackportQueue and previousStableBackportValidation; the published successor
baseline authenticates the validation file digest, and that validation binds the exact queue
digest and predecessor commit. Critical 4/8/12-hour response windows are computed from state
transition timestamps, not from a caller-selected final deadline. An expired critical deferral
review remains blocking. Rejecting a critical record does not remove it from the blocker index;
an append-only authorized rejected-to-triaged transition reopens investigation without
rewriting that history. The record remains critical and blocking throughout re-triage.
superseding one requires a critical replacement with the same incident, advisory, and affected
scope.
Every accepted security-hotfix row is a critical security-fix under one incident/advisory pair;
package, app, or tooling effects are recorded in the security fix’s affected scope and evidence,
not as unrelated ordinary rows. A superseding hotfix may carry one publication-created follow-up
even when it was not present in the prior authorized train queue: the first queue projection must
bind the authenticated predecessor baseline’s exact open/overdue obligation digest, build/train and
generation time to the prior queue’s critical source fixes. Subsequent queues inherit it unchanged.
An authenticated overdue high PR-288 blocker remains on routine-maintenance and may proceed only
when every blocking case is present in the train's accepted fix scope with the exact severity and
vulnerability public-projection digest. This scoped remediation rule does not let an unrelated
high blocker pass and does not move a critical case out of security-hotfix.
A new transition to released is valid only from an authenticated prior queue and with the exact
previousStableBackportCompletion artifact. The fix transition and its
stable-backport.release-completion evidence row both bind that artifact's file digest, train,
queue, and candidate identity. The immutable per-fix provenance commit must be an ancestor of the
publication tip; it is not required to equal that tip. The intake snapshot, completion-evidence
row, and final state transition must be timestamped no earlier than the authenticated maintenance
publication receipt, completion artifact, and protected completion handoff. Backdating any of
those events cannot make a later train authorization appear to postdate publication.
Every fix included by the prior authorized validation must complete this released-state proof
before it can be superseded.
When an otherwise authenticated reconciliation merge contains non-automatic content, strict Git
inspection does not certify that content as reconciled. Completion instead derives the exact
policy-named blocker, marks reconciliationStatus: content-review-required, and binds its evidence
digest to the merge record and bounded resolution-path digest. The next intake must seed that exact
completion-created obligation before moving the published fixes to released; its queue remains
blocked pending separately authenticated content-review evidence. Other Git, parent, branch-tip,
or attestation failures still produce no completion artifact.
The successor also requires previousStableBackportCompletionHandoff. The protected workflow
creates this record only after authenticating the successful prior completion run and exact
Actions artifact, byte-comparing its completion and validation, resolving current protected
main/develop, and proving both merge commits remain on their first-parent chains.
Stable 1.0 remains one successor chain. Historical supported-maintenance,
security-fixes-only, or deprecated builds are upgrade/advisory coverage sources.
end-of-support and revoked builds are recovery sources only when policy explicitly permits it.
They are never mutable release targets or parallel LTS branches.
Every train re-authenticates the full existing GA promotion, validation, authorization-summary,
publication-plan, receipt, checksums, provenance, and maintenance-baseline bundle as its immutable
root. For the first post-GA train, the exact authenticated GA baseline and publication receipt are
the predecessor and latestPublishedMaintenancePointer must be absent. Every later train requires
that input and verifies that it selects the exact immediate maintenance predecessor. This matches
the existing stable-maintenance genesis/no-fork invariant.
The lifecycle authority input also includes a fresh public observation receipt bound to the exact
descriptor edition, descriptor bytes, ledger, publication plan, update-key scope, and prior
authorization. Train authorization must be issued no earlier than that observation or any state,
evidence, obligation, or intake event it approves.
The checked-in stable-1.0-backport.example.json deliberately models only that first post-GA
shape. Replace its complete predecessor identity—integer build, release id, and product
digest—before use. A later successor must add latestPublishedMaintenancePointer,
previousStableBackportQueue, and previousStableBackportValidation; copying the genesis shape
unchanged is rejected.
When an authenticated hotfixFollowUpClosure closes the predecessor's publication-created
shortened-window follow-up, the backport command uses the maintenance authority's closure-adjusted
predecessor state. Its protected queue, candidate, lineage, and validation bind the closure digest
so the next routine train can proceed without mutating the published baseline; the public
validation omits that protected digest, and train authorization cannot predate the closure.
Successful applicable modes write the canonical intake, plan, lineage, authoritative queue,
public queue projection, candidate,
authoritative validation, filtered public validation, authorization summary, optional completion,
train summary/report, checksums,
provenance, redaction, and component summary records below
build/release-certification/<release-id>/stable-backport/. Failure does not manufacture
placeholder success artifacts.
The authorization-summary filename contains the complete schema-validated train authorization.
The protected validate-authorization envelope contains that exact file together with the exact
train validation. stable-maintenance requires both manifest inputs, recomputes their complete
binding, and the protected maintenance workflow resolves the source run, workflow, candidate,
artifact name, and Actions artifact digest from the manifest’s
stableBackportRunId, stableBackportArtifactName, and
stableBackportArtifactDigest metadata. Producer copies must match the authenticated artifact
byte-for-byte. Maintenance then reseals those two authoritative files for every freeze,
preparation, validation, publication, and independent-verification handoff. Repository-readable
maintenance artifacts contain the encrypted envelope and no plaintext duplicate under either
authenticated-inputs or staged protected-inputs. Train candidateDigest is the candidate JSON
file digest and is intentionally not the maintenance candidate’s separate semantic
candidateIdentityDigest.
The protected .github/workflows/stable-1.0-backport-release-train.yml workflow maps
evaluate-intake, prepare-candidate, validate-authorization, and
verify-release-completion to those command modes. It binds an exact checkout and reviewed input
digest, runs with a read-only token, and separates the exact protected handoff from an allowlisted
public-safe projection. It
does not create or modify branches, commits, tags, pull requests, releases, catalogs, update
descriptors, or lifecycle state.
The authoritative stable-1.0-release-train-queue.json remains inside the protected component
and input chain. The workflow uploads two distinct artifacts: an authenticated encrypted envelope
for the next protected phase or maintenance consumer, and an allowlisted public artifact. The
latter contains
stable-1.0-release-train-queue-public.json and
stable-1.0-release-train-validation-public.json, not the authoritative queue, full validation,
authorization record, completion record, predecessor-completion handoff, or internal
checksums/provenance. The public schemas exclude touched/conflict paths, protected evidence ids
and digests, private-record digests, and exact per-fix source/backport internals while retaining
digest-bound public disposition, decision, and status projections.
Each non-initial phase resolves and downloads the exact prior Actions artifact and authenticates
its run, workflow, commit, operation, run attempt, digest, and encrypted-envelope binding before
decrypting the checksums, provenance, queue, and validation inside a protected environment. Use
the same canonical base64 32-byte
CRYPTAD_STABLE_BACKPORT_HANDOFF_KEY_BASE64 secret in the protected backport-review,
backport-evidence, backport-authorization, maintenance-evidence,
stable-1.0-maintenance-publication, and
stable-1.0-security-hotfix-publication environments. Never expose that key in an input,
variable, log, summary, or artifact, and retain required plaintext records only in the separately
access-controlled support-lifetime input archive. The
completion phase uses that downloaded validation as stableBackportFrozenValidation. It also
supports a support-lifetime predecessor-completion reauthentication path: the protected input
bundle retains the exact completion, validation, authoritative queue, receipt, and lifecycle
authority after Actions retention expires. A new protected evaluation rechecks that digest-pinned
bundle and the current protected main and develop first-parent histories, then emits the exact
handoff consumed by later phases. Supplying an unexpired completion artifact remains an optional
byte-comparison fast path.
The release-train candidate-handoff authorization is bounded to 72 hours. That covers the required 24-hour post-freeze routine-maintenance soak plus up to 48 hours for evidence review and handoff; it remains separate from, and never substitutes for, maintenance publication authorization. The protected publisher requires that grant to have been current at the exact maintenance-authorization handoff frozen into the bundle. It does not re-age that composition-only grant against each later publication target or retry. Candidate evidence freshness and the separate maintenance publication/activation authorizations retain their existing current-time checks.
The evaluate-to-prepare handoff is deliberately different from the later frozen-candidate
handoffs: the candidate may advance while approved fixes are landed, but the evaluated composition
may not be exchanged. The public queue contains a digest commitment to the protected immutable
fix/obligation composition and opaque transition digests. prepare-candidate requires the same
fix and obligation identities, the same composition commitment, and prefix-only state-transition
evolution. The obligation commitment includes its exact source train and source-fix identities;
otherwise rerun evaluate-intake.
The workflow resolves the protected main and develop tips and binds their exact reachability
evidence.
Routine phase provenance carries the frozen protected-development commit; a later phase rejects
the handoff if that commit is no longer reachable from the live protected develop tip.
Completion fetches the exact GitHub-API-selected protected-tip commit identities from the canonical
origin before checking their local object types and ancestry, so a protected branch advancing
after checkout does not create a false missing-object failure.
Completion verifies separate no-ff merges of the same published release/hotfix candidate into
main and develop; the develop merge does not name the main merge commit as its merged tip.
Because completion is read-only proof over the already published train digest, it may run after
the original candidate-handoff authorization expires. The receipt-bound frozen validation is
replayed at authorization issuance rather than re-aging candidate evidence against completion
time.
Authorization projections preserve the exact schema-valid expiresAt text from the full
authorization, including fractional seconds or an explicit UTC offset.
Protected provenance-review authorization uses an exclusive expiry boundary: it is invalid when
the captured validation time equals expiresAt.
See the backport and release-train runbook for the full fix model, Git provenance contract, security projection, maintenance integration, release-note behavior, and manual operations.
Create a local Gradle resolution export for review:
./gradlew exportStableSupplyChainResolutionThe exporter writes build/stable-supply-chain/resolved-dependency-snapshot.json,
build/stable-supply-chain/resolved-dependency-export.json, and
build/stable-supply-chain/build-material-inputs.json. The snapshot is the canonical selected
component, variant, edge, and artifact view for the policy-selected configurations. The raw export
retains the complete reviewed resolution projection. Build materials record source, wrapper,
toolchain, repository policy, external input, and build-recipe identities.
The export builds the jlink image and derives its module list from that generated runtime's
java --list-modules output, not only the requested jdeps roots. It also fingerprints the exact
Gradle-selected JDK installation with the policy's path-independent installed-tree algorithm. The
final material record contains distinct Linux, macOS, and Windows installation rows, and each
protected builder must independently observe the matching row before any product task. A local
system JDK whose tree contains escaping or absolute external symlinks is deliberately unsuitable
for this protected fingerprint and causes the exporter to fail closed.
Protected inventory, producer, and verifier runs authenticate exact files named
resolved-dependency-export.json and resolved-dependency-snapshot.json in the phase bundle before
running the strict comparison:
./gradlew exportStableSupplyChainResolution verifyStableSupplyChainResolution \
-PstableSupplyChainExpectedResolutionExport=build/stable-supply-chain-phase/resolved-dependency-export.json \
-PstableSupplyChainExpectedResolutionSnapshot=build/stable-supply-chain-phase/resolved-dependency-snapshot.jsonBoth expected paths must remain confined to the attested phase artifact. Aliases, unreferenced files, links, and generated-output substitutions fail. The default no-property export is intentionally unlocked and is not strict verification by itself.
The policy also closes direct build inputs to five named materials: the Gradle distribution,
seedrefs source archive, Tanuki wrapper delta pack, and the AMD64 and ARM64 Windows wrappers. The
wrapper checksum is pinned in gradle-wrapper.properties; protected jobs supply reviewed SHA-256
values for the other four Gradle downloads, verify before extraction, and bind the same identities
to final packagingInputs plus both authenticated builder receipts. Missing or drifting direct
material remains promotion-blocking.
The generated build-material-inputs.json has the raw
cryptad-stable-build-material-inputs-v1 contract. It is not the final
stable-1.0-build-materials-v1 manifest input and cannot replace it. The manifest's
inputs.buildMaterials path remains confined to the attested phase bundle. Inventory execution
cross-checks the raw export and Gradle/material digests across the generated document, reviewed
snapshot, and final build-material record, then retains the raw document as separately named
attested workflow evidence. Only the final record occupies the public build-materials role.
Use tools/release-certification/stable-1.0-supply-chain-policy.json as the checked-in policy and
tools/release-certification/stable-1.0-supply-chain-license-overrides.json as the checked-in
override set. The exact release-subject inventory is release-specific and must come from the
authenticated phase bundle path named in the manifest; it is not a checked-in template or a local
discovery result.
Each policy subject has an evidencePhase. Builder receipts and comparison records cover exactly
the selected independent-builder subjects: core, portable/runtime archives, native installers,
and seven app bundles. Frozen catalog/signature/updater bytes are authenticated-post-build: they
retain exact byte and freeze-signature bindings but are not claimed as independently reproduced by
the current Gradle recipe. Review/release/supply-chain records are derived-governance and
not-a-product-subject; their exact bytes are bound by inventory, promotion, and immutable
publication evidence instead of builder assertions.
The current native-installer builder matrix is closed to AMD64 DEB, RPM, DMG, and EXE subjects. Flatpak and Snap remain valid maintenance package-format vocabulary, but are not authorized by the current supply-chain policy. Selecting either format requires a future reviewed policy edition that also introduces its isolated build, safe extraction, and normalized comparison evidence.
Set inputs.licenseTextRoot to the repository root, .. License registries may reference only the
root LICENSE or regular files below docs/licenses/; the broader root is a resolution anchor and
does not make arbitrary repository files eligible notice evidence.
Run one side-effect-free phase with a candidate-bound stable-review manifest:
python3 tools/release-certification/certify.py stable-supply-chain \
--manifest build/stable-supply-chain-phase.jsoncommands.stable-supply-chain.mode is closed to assemble-inventory, verify-inventory,
prepare-rebuild-comparison, compare-rebuilds, evaluate-promotion, and
verify-publication. Each mode accepts exactly its declared inputs set; a caller cannot attach
an irrelevant earlier-phase file to cross a trust boundary. Native component, license, SBOM,
binding, build-material, builder, comparison, reverse-index, promotion, and publication-verification
records are written under
build/release-certification/<release-id>/stable-supply-chain/artifacts/legacy/. The common
candidate-bound summary, report, and redaction result remain at the component root.
evaluate-promotion requires execution.evaluationClock and the fixed-name authenticated
stable-1.0-vulnerability-summary.json handoff. The existing protected handoff verifier checks
the sealed producer bytes, provenance, summary expiry, and current durable vulnerability-ledger
tip; a raw JSON path is not promotion authority. Vulnerability ledgers that contain a
runtime-component scope likewise require componentReverseIndex in every later protected
phase. The current reverse index must match the manifest's authenticated full candidate commit and
immutable commit:<sha> source ref, and every newly resolved alias must map to the candidate build.
Historical scope rows retain their original inventory digest; this current-candidate routing check
does not retroactively rebind them. Historical ledgers with no such scope remain valid without that
irrelevant input.
Its promotion summary is a prepublication gate. Every non-publication evidence row must pass, but
stable-supply-chain.publication must not be reported as passing by evaluate-promotion; only
verify-publication can establish that row from the exact receipt and fresh public observation.
Downstream maintenance and generic release certification also require the sibling
stable-1.0-supply-chain-summary-provenance.json. That bounded record binds the summary byte
digest to the exact successful protected supply-chain workflow run/attempt, fixed comparison
artifact name, Actions artifact digest, candidate source commit, and verified attestation. A local
summary plus its own semantic digest is not release authority. After those GitHub and attestation
checks, the protected producer adds a domain-separated HMAC-SHA256 tag using the dedicated
CRYPTAD_STABLE_SUPPLY_CHAIN_HANDOFF_KEY_BASE64 secret. Consumers require that tag and compare the
summary's sourceCommit and immutable commit:<sha> source ref with a direct read of the current
checkout; provenance booleans, caller-supplied metadata, and a stale genuine summary are
insufficient.
The protected .github/workflows/stable-1.0-supply-chain.yml workflow is manual-only. Its closed
orchestration operations are inventory, producer-build, verifier-build,
compare-evaluate, publish, and verify-publication. Producer and verifier jobs have isolated
workspaces; the verifier authenticates only the closed recipe and reviewed resolution expectation
files before its Java 25 wrapper build, then digests its own subjects while producer candidate
bytes remain unavailable. Every handoff is authenticated against the exact repository,
workflow path, protected source ref, source commit, run attempt, artifact name, artifact digest,
and file attestations.
Each producer or verifier run has four authenticated executions: portable-apps,
linux-installers, macos-installer, and windows-installer. The aggregate preserves the exact
runner-image, job, subject-partition, handoff, and attestation identities for all four; it does not
flatten platform provenance. compare-evaluate additionally requires the original producer and
verifier run/attempt/artifact/digest coordinates, downloads both originals directly, and derives
the formal receipts from their verified file attestations. For evaluate-promotion, the fixed
Stable vulnerability summary is opened and current-tip verified outside the checkout and public
output roots before the CLI runs.
Both roles receive the same product-byte-free five-input recipe plus the reviewed raw resolution export before building. The recipe contains no builder receipt; the comparison job derives both receipts only after authenticating the original completed builder artifacts. Per-execution receipts bind Java, Gradle, verification, plugin/build-logic, task-set, canonical environment, direct-input, payload-manifest-set, and extraction-manifest-set identities. Native package jobs extract the actual DEB/RPM/DMG/EXE container, canonicalize the complete installed tree without ignored files, and require one embedded app-image root to equal the pre-signing stage. The distinct attested extraction record binds package, extractor, full extracted, embedded staged, and candidate freeze signing/notarization identities. Unsupported layouts, unavailable tools, and policy-bound expansion overflows fail closed.
For producer-build, candidate bytes are not downloaded until the local build has completed. The
workflow then authenticates the existing maintenance freeze-candidate run and the exact
run/attempt-bound stable-1-0-maintenance-frozen-... artifact. The closed freeze record and every
attested freeze/assets entry must agree with the subject inventory by canonical filename,
digest, size, signing receipt, and notarization receipt. Frozen bytes are used wherever that
maintenance freeze selected a subject; non-selected deterministic companions must still match the
authenticated inventory exactly.
Developer-ID-signed/notarized DMGs use the closed macos-code-signature-normalized view. The
producer authenticates the frozen DMG, signing and notarization receipts, signed mounted app, and
signature-material inventory; the verifier authenticates its independently built unsigned app.
Their role-specific extractionManifestSetDigest values intentionally differ. Equality is required
for the role-neutral payloadManifestSetDigest, normalized pre-signing payload, non-code entries,
package metadata, normalization rule/version, and empty ignored-path set. Any unaccounted code or
non-code payload difference remains a release blocker; signatures are accounted for, not stripped
from the publication identity.
The command-line component never creates a tag or GitHub Release, uploads a public SBOM, changes a
catalog, or publishes CoreUpdater state. The separate publish workflow job runs only in the
protected supply-chain publication environment and is the only supply-chain job with job-scoped
contents: write. It authenticates the exact promotion bundle, annotated tag, existing Release,
input attestations, and reviewed publication-backend wheel before it verifies the
LEUMOR_GITHUB_TOKEN identity as exactly leumor. Secrets are supplied through the step
environment, never interpolated into command-line arguments.
The fixed cryptad_stable_maintenance_backend:supply_chain_factory entry point accepts only the
eight policy roles—build-materials, component-inventory, component-reverse-index,
license-inventory, release-subject-inventory, reproducibility-report, sbom, and
supply-chain-summary. It records absent assets as created, accepts exact existing assets as
verified-existing, and never deletes or overwrites a conflict. It immediately re-observes the
eight public byte streams and emits the receipt and fresh observation in an attested immutable
handoff. verify-publication consumes that handoff without a publication credential and performs
no mutation. Report publication or reproducibility only when those exact records pass; a local
inventory or one successful build is informational.
The side-effect-free verifier derives all eight filenames and their
https://github.com/crypta-network/cryptad/releases/download/v<build>/ targets from the reviewed
policy. Self-consistent plan, receipt, and observation records at any other HTTPS location fail.
See Stable 1.0 supply-chain inventory and reproducible-build governance for the authority model, component roles, app/catalog coverage, license rules, vulnerability reverse index, redaction boundary, and external-verification procedure.
Provider-distinct verification is a separate layer around this same comparison authority. Run
stable-independent-reproducibility in the closed prepare-verifier-kit,
verify-external-receipt, compare, or closeout mode. The checked-in fixture and generic OIDC
template are non-operational; repository implementation or self-tests cannot complete the gate.
Operational success requires a concrete reviewed profile and real adapter verification of the raw
DSSE/Sigstore bundle and bounded verification transcript. The protected coordinator accepts all
six sealed external core files before it can download primary or selected-RC evidence. The
checked-in operational external-adapter allowlist is empty; changing a policy flag or supplying a
self-asserted transcript cannot complete the gate. See
Stable 1.0 independent reproducible-build
verification.
Run the focused offline contract suite with:
python3 tools/release-certification/certify.py stable-federated-catalog --self-test
python3 tools/release-certification/certify.py stable-federated-catalog --helpThe command has six closed modes: preflight, verify-discovery, verify-local-trust,
verify-conflicts, verify-runtime, and closeout. It verifies exact bounded evidence already
present beneath the workspace. It does not fetch descriptors, alter node trust, contact a runtime
node, install or update an app, publish a catalog, or mutate GitHub.
Discovery descriptors and endorsements are separate signed public formats. Descriptor import is pending evidence only. Their certification schemas are the exact nested runtime wire formats, and the execution contract separately binds the locally approved issuer SPKI used for verification. The closed endorsement format has no transitive-trust or trust-creation field; neither format installs a key, adds a source, authorizes a publisher/reviewer, or selects an app. The signed runtime observation proves the bounded local properties: at least three catalog identities, distinct local bindings, scoped catalog/publisher/reviewer policy digests, deliberate duplicate and hard conflicts, disabled lexical tie-breaking, strongest security blocks, pinned origin, explicit source/publisher switch consent, exact rollback origin restoration, isolated catalog revocation, privacy-safe discovery, redacted support output, and complete cleanup.
closeout additionally requires exact successful PR-291, PR-292, PR-293, and PR-294 protected
artifact coordinates. Its runtime receipt must come from the exact successful attempt of
stable-1.0-federated-catalog-runtime.yml: the protected runtime-observation environment selects
the reviewed adapter digest and observer identity, the workflow publishes distinct immutable
observation and signed-receipt artifacts, and the evidence producer authenticates both before it
uploads the confined aggregate. A public key embedded only in a caller-authored receipt is not an
observer authority. Fixtures and self-tests can reach only fixture-verification-complete.
Fixture-, sample-, template-, and test-shaped identities cannot become operational merely by
changing classification flags. Missing, stale, substituted, partial, or unredacted evidence emits
bounded blockers and never reports operational completion.
See Federated catalog discovery and local trust for the trust model, certification contract, privacy boundary, state machine, and operational prerequisites.
Run the focused offline authority suite with:
python3 tools/release-certification/certify.py stable-platform-api-1x --self-test
python3 tools/release-certification/certify.py stable-platform-api-1x --helpThe seven closed modes verify preflight, append-only contract history, a conditionally required
future-baseline proposal, descriptor graduation records, a monotonic deprecation ledger, the static
cross-release app matrix, an optional bounded runtime observation, and closeout. Exact inputs use
the closed platform-api-1.x-*-v1 schemas and the checked-in compatibility policy. The example
execution contract is fixture-only and cannot produce operational completion. History verification
parses the real contract-envelope shape, recomputes its compatibility-window digest, validates the
complete named-baseline registry and its self-digested lifecycle, and binds the current history
head to the exact registry artifact bytes. Operational history additionally requires the exact
selected RC freeze authenticated by both PR-291 and PR-292: their selected-RC coordinates must
agree, and the freeze byte/content digests, product root, release/build/source identity, contract
version, and contract-snapshot digest must match the head. Proposal membership, graduation
descriptor semantics, and matrix verdicts are recomputed from the accepted registry and
digest-bound history snapshots; producer assertions do not substitute for those checks.
Production matrix verification also requires the closed app-subject inventory. It independently
commits the complete compatibility declaration behind every matrix row and the required release-app
set. Matrix rows and requiredAppIds are redundant projections that must exactly match this input;
removing an app from both matrix collections, or pairing authentic bundle digests with changed
permissions, baseline, or contract-range fields, fails. The policy fixes the seven required
first-party IDs, and operational input must additionally carry authenticated third-party-pilot
coverage. Existing PR-292, PR-294, and PR-295 summaries remain valid for their original purposes,
but summaries that omit full compatibility subjects cannot alone satisfy this new operational gate.
Version 1 fails closed before app-matrix-verified when only such a broad digest is supplied. It
does not infer complete compatibility metadata from legacy summaries; operational matrix completion
remains pending until a versioned protected subject-projection authority can authenticate every
matrix field.
The singular version-1 proposal binding may be absent only when the registry has no nonterminal future definition. One such definition requires its exact proposal and app-matrix bytes; multiple simultaneous future definitions require a later evidence schema. The verifier also rejects a definition whose member descriptor was introduced after its claimed first-complete contract and a graduation observation dated after the execution evaluation time.
The protected import is three-stage. stable-1.0-platform-api-1x-runtime-observation.yml verifies
the static matrix, runs the digest-pinned adapter selected by its protected managed-node
environment, and uploads the one bounded redaction-checked observation for its exact run and source.
stable-1.0-platform-api-1x-evidence.yml independently authenticates that observation and every
other protected input, constructs the runtime authority binding locally, and uploads one confined
aggregate from the exact protected source. The compatibility workflow accepts only that fixed
aggregate producer and authenticates its exact run, job, protected environment deployment,
dispatch actors, source, artifact ownership, timestamps, name, and digest before closeout.
Current authorities are checked against the execution source ref. The previous-history run is
checked against its authenticated ledger head's source ref so a valid successor may cross release
branches without weakening ref binding.
Operational closeout requires exact non-fixture PR-291 through PR-295 authority roots. The command
does not activate Platform API 1.1, change /api/v1, authorize an app capability, mutate a runtime,
publish a release, or claim the long-duration cross-version soak assigned to PR-300. See
Platform API 1.x compatibility operations.
The runtime execution template must leave both runtime fields null; a checked-in or caller-filled
observation cannot bypass the dedicated producer. The protected evidence producer authenticates
each predecessor's exact run attempt, successful allowlisted job, protected deployment, artifact
ownership/name/digest, and bound summary bytes before closeout. History records bind both the
deprecation-ledger head and an explicit
oldestSupportedRecordDigest; matrix verification independently authenticates the published
Stable lifecycle receipt and descriptor, derives the minimum ordinarily supported build, and
requires the ledger projection to match. New deprecation rows must match their first authenticated
history notice. The version-1 authority permits future proposal and preview states but rejects any
future baseline activation. A production runtime result requires the separately authenticated
managed-node producer rather than caller-authored status or check labels; actual protected
execution remains a release operation and is not implied by this implementation.
Run the focused local contract suite with:
python3 tools/release-certification/certify.py stable-catalog-authority --self-test
python3 tools/release-certification/certify.py stable-catalog-authority --helpOutside fixture self-tests, pass the exact authenticated handoff with --evidence-dir. Publication
modes hash and verify the canonical frozen catalog and detached signature, authenticate the PR-291,
PR-292, GA, and HTTPS-observation members, and compare a supplied sanitized live result when
--live-publication-result is present. A manifest containing only claimed digests or pass flags
fails closed for non-fixture verification.
The catalog-authority engine is deterministic and side-effect-free. Its closed operations prepare
or verify a ceremony and publication, use verify-rotation-drill for closed typed planned-rotation
or rollback evidence, and close out the authenticated result. It does not possess production
private keys, contact a live publisher, mutate a catalog, create a tag or GitHub Release, or infer
remote completion. The protected workflow exposes a distinct rollback-drill orchestration
operation and is the only place that may call the existing live USK publication boundary; only its
approved mutation job may materialize the private insert URI and form password.
Non-fixture drill verification additionally requires the original
stable-1.0-catalog-drill-receipts.json artifact from
.github/workflows/stable-1.0-catalog-drill-acceptance.yml. Its protected release and security
approval boundaries accept a bounded evidence-digest inventory and emit one closed bundle for the
exact six drill types. Each manifest subjectDigest must equal its matching receipt's semantic
digest, and rollback lifecycle checks use the authenticated receipt completion time. The authority
workflow cannot self-produce or reupload this bootstrap evidence; missing, substituted, replayed,
fixture, or non-operational receipts keep drill verification and closeout blocked.
The checked-in policy closes four key roles—catalog signing, first-party app signing, app review, and offline recovery—and binds the exact PR-291 protected release root plus PR-292 independent reproducibility result. Ceremony verification checks global key-ID and fingerprint uniqueness, Ed25519 X.509 SubjectPublicKeyInfo, validity and lifecycle, acyclic same-role lineage, canonical proof of possession, recovery-only usage, protected transition authorization, and evidence classification. Public key bytes are confined to the public key-transparency artifact and derived role registries; summaries and receipts use IDs, fingerprints, and digests.
Proof records are lifecycle-specific. Staged, active, and retiring routine keys use a
current-keyset statement and signature over the exact new keyset digest. Retired and revoked
routine keys use a retained-historical statement and its already-existing signature from an
earlier keyset; the verifier checks the historical signature and immutable public identity without
requesting a new signature from the predecessor. Offline recovery keys are
not-applicable-recovery and carry no routine proof material. Ceremony receipts and public
transparency rows preserve this classification so historical proof metadata cannot be confused
with current signing eligibility.
Publication verification reuses the frozen catalog and detached-signature identities instead of forking Stable GA comparison semantics. It binds catalog ID, channel, revision, USK edition, digests, sizes, signer ID and fingerprint, public Crypta USK primary, independently operated mirror, and an older eligible rollback subject. Every source must return the same exact catalog and signature. Duplicate or aliased locations, stale or unauthorized newer bytes, signature sibling mismatch, changed signer without a later revision/edition, compromised-key rollback, and conflicting existing state fail closed. Protected public-web locations are canonical credential-free HTTPS on port 443, matching the exact port resolved, pinned, and fetched by the collector.
Normal output is confined beneath the selected output root and includes ceremony, transparency, publication, drill, closeout, Markdown report, and redaction records. Closed schemas reject duplicate JSON keys and unknown roles, lifecycle states, ceremony types, locations, and drill types. Redaction rejects private-key-shaped material, insert capability, credentials, secret-bearing command lines, absolute or temporary paths, raw fetched bodies, unsafe archives, and unpublished incident details.
Fixture and self-test inputs can prove only fixture verification. Authentic protected receipts are required before the summary can report ceremony authentication, network-primary publication, mirror observation, operational drills, transparency publication, or complete closeout. Preserve sanitized partial evidence and bounded blockers on failure; never relabel it as success.
The protected network-primary mutation step preserves its sanitized local result across ordinary
publisher or post-publication verification failures. It records both exit statuses, removes the
insert URI and form password before certification, bounds and checks the result file, and stages it
only after the generated and receipt-local redaction checks pass and the receipt binds the exact
result digest. The atomically committed retention set contains exactly that result, its partial
receipt, and the redaction report. Its artifact upload uses always(), while the mutation step
returns the original failure status after staging. This retains authenticated retry evidence
without turning an incomplete insert or failed exact-subject check into success.
Every protected catalog-authority operation uses a closed v1 coordinate aggregate rather than one catch-all artifact. The operation-specific aggregate authenticates every contributing Actions run and artifact digest, then verifies the digest of each selected member while flattening only the exact PR-291, PR-292, original supply-chain primary subject bundle, Stable GA, live publication, mirror observation, rollback, and applicable transition files into a confined input directory. The subject bundle must come directly from the selected attempt-scoped supply-chain producer; its inventory-bound app bundles and inline review receipts prove that the ceremony app and reviewer public keys are the keys that authenticated the frozen Stable subjects. Successful side-effect-free publication preparation retains the exact PR-291, PR-292, subject-inventory, and public-observation members it already verified; it does not substitute the earlier PR-291 RC-dispatch summary for the required publicly observed PR-291 closeout summary. Stable GA separately stages the current and rollback catalog sidecars plus its exact plan and final receipt only after its existing verifier passes. Network publication and observation remain separate artifacts. A single coordinate, an incomplete aggregate, or a member supplied by the wrong protected phase fails before certification starts.
The first mirror receipt comes only from
.github/workflows/stable-1.0-catalog-mirror-observation.yml, whose managed observer has no insert
capability and generates the root-level receipt after exact primary, mirror, detached-signature,
and scheduler checks. The dedicated collector revalidates its reviewed timestamp after protected
admission, requires the active catalog signer to remain valid through actual collection completion,
and accepts scheduler refresh verification only when an exact primary success falls within that
collection window and scheduler health exposes a configured mirror fallback. Normal refresh stops
after primary success, so the collector proves mirror availability through its separate exact-byte
catalog-and-signature fetches rather than requiring a synthetic fallback attempt. The closed receipt
binds both actual collection instants, and closeout
independently rechecks the signer against its completion instant. Its FProxy and HTTPS transfers
are bounded to the schema's 1 MiB catalog and
64 KiB signature limits before files or memory are accepted. The protected recovery-quorum
exception comes only from
.github/workflows/stable-1.0-catalog-recovery-quorum.yml; two fixed protected approval jobs derive
the count and emit the exact transition-bound root-level receipt. Catalog-authority verification
artifacts can consume these receipts but are never accepted as their origin. Drill and closeout
aggregates likewise accept the protected drill bundle only from the dedicated drill-acceptance
producer and bind every row to the exact PR-291 root, PR-292 result/inventory, keyset, ceremony,
catalog subject, completion time, and supporting evidence digests.
The first preparation does not depend on a previous preparation artifact. Run the protected
release closeout workflow over the reviewed PR-291 contract and its exact authenticated producer
artifacts; it calls the existing PR-291 closeout engine and emits the canonical
publicly-observed summary. PR-292 closeout now retains its already-authenticated subject
inventory beside its summary, and the public-observation receipt is consumed directly from its
producer. Later preparation artifacts may retain those verified members, but cannot bootstrap or
replace their original authorities.
The security-response and maintenance CLIs reject local catalogAuthority objects that claim
protected operational completion. Those digest-only objects remain reserved for a future
protected archive/coordinate intake; omitting the optional binding preserves historical operation.
The engine constructs and scans the complete output set before writing its first file. Any final redaction finding aborts the command without uploadable evidence. The selected output directory must be empty at entry, preventing stale evidence from an earlier successful attempt from surviving a failed retry.
See the Stable 1.0 catalog publication and key ceremony runbook for custody, approvals, role-registry deployment, legacy fallback, exact-byte publication, retry, stop, and remaining protected operations.
Run the offline, phase-separated dependency security engine with:
python3 tools/release-certification/certify.py stable-dependency-vulnerability \
--manifest build/stable-1.0-dependency-vulnerability.jsonThe command accepts only validate-intelligence, match-inventory,
authorize-dispositions, prepare-remediation, evaluate-promotion, or
verify-publication. Retrieval is deliberately absent: the protected producer emits bounded raw
digests, source provenance, and canonical records, while this command deterministically validates
snapshots, matches the exact PR-289 inventory, and enforces the four closed dispositions. The
companion promotion summary is prospectively required for Stable maintenance and security hotfixes
and becomes the non-waivable ecosystem.stable-dependency-vulnerability release-certification
gate. Publication uses the closed authenticated backend and verified-existing-or-create semantics;
self-tests never publish.
stable-1.0-dependency-vulnerability-phase-bundle.yml is the only protected producer accepted
for evaluator phase manifests. It authenticates every operation-specific upstream run, attempt,
artifact name, and Actions digest, downloads only those exact artifacts, and invokes the reviewed
phase-bundle helper to construct manifest.json itself. A caller-supplied manifest is never used.
Its chain is: producer records to validate-intelligence; the retained intelligence and exact
PR-289 artifacts to match-inventory; match output plus a protected bounded disposition proposal
to authorize-dispositions; the authorized output plus PR-288/remediation proposal to
prepare-remediation; and the authorized/remediation chain plus exact PR-289, PR-288, candidate,
freeze, closeout, and optional authenticated PR-287/PR-285 fixed evidence to
evaluate-promotion. Proposal artifacts are protected, bounded digest-only inputs; they are not
committed as repository history.
When fixed findings are present, the evaluation workflow—not the caller or phase bundle—creates
the remediation provenance sidecar. It binds the exact phase Actions digest, protected run and
attempt, PR-287 validation/completion/handoff bytes, PR-285 receipt bytes, current PR-289
summary/inventory/reverse-index bytes, and the exact fixed remediation set under the phase-scoped
remediation HMAC key before the offline engine is invoked.
The protected intelligence producer shares stable-1-0-vulnerability-ledger serialization with
PR-290 evaluation. It emits an exact source artifact and a separate activation proposal without a
lineage-write token. stable-1.0-dependency-authority-activation.yml is the serialized activation
drainer. Its single lock-holding activation job dispatches and awaits
stable-1.0-dependency-intelligence-activation.yml once for each retained candidate, oldest first;
it does not rely on matrix execution order. The dispatched authority authenticates the exact live
drainer run, protected branch, and commit before it requests the activation environment. The
finalizer requires the overall producer run to be completed-success,
requires both mandatory proposal/source pairs for a scheduled matrix run, reauthenticates their
exact Actions digests, and then constructs both successors and performs one compare-and-swap of
STABLE_1_0_DEPENDENCY_INTELLIGENCE_SOURCE_LINEAGE_SET. Failed or cancelled producer runs, and
failures while preparing either member, cannot partially supersede a usable source set. Seed that
variable with the exact compact bytes represented by
stable-1.0-dependency-intelligence-source-lineage-set-genesis.json; missing state never implies
genesis. Before the evaluation workflow creates its promotion HMAC, it rereads the durable
GitHub-public and OSV members and requires the selected source record and
provenance to match each current anchor's exact edition, snapshot/content/inventory digests,
workflow commit, run, attempt, artifact name, and Actions artifact digest. Configure the
least-privilege lineage-read token in the protected evaluation environment; it is not exposed to
ordinary PR or offline validation. Superseded but still fresh producer artifacts cannot authorize
promotion.
The final publication-verified handoff carries and HMAC-binds the exact source-status file; final
release certification compares both mandatory rows with this same lineage set immediately before
running the PR-290 gate.
OSV inventory selection has a separate retention-independent authority:
STABLE_1_0_DEPENDENCY_OSV_INVENTORY_ANCHOR. Seed it with the exact compact bytes from
stable-1.0-dependency-osv-inventory-anchor-genesis.json, then use the protected
stable-1.0-dependency-osv-inventory-retention.yml workflow to activate an exact PR-289
supply-chain comparison artifact. The anchor preserves that inventory's release, build, source
commit, semantic digest, byte digest, and original PR-289 coordinates. Its current retained
artifact may be renewed from protected develop without changing the inventory identity, so a
moving scheduled-workflow commit or ordinary 30-day Actions expiry cannot silently replace or
strand the Stable inventory. Renewal is required seven days before expiry; missing, expired, or
uninitialized state fails closed. The retention producer uploads a closed proposal and has no
write token. After source proposals have drained, the same serialized activation job dispatches
and awaits stable-1.0-dependency-osv-inventory-activation.yml for every retained
completed-success producer in oldest-first order. The finalizer independently authenticates the
exact run, attempt, artifact digest, source coordinates, inventory bytes, and predecessor, and
makes the anchor compare-and-swap its final
operation. Configure the read token in the producer and the write token only in the protected
activation environment.
The append-only PR-290 ledger tip is independently retained in the repository Actions variable
STABLE_1_0_DEPENDENCY_VULNERABILITY_LEDGER_TIP_ANCHOR. Provision it before the first protected
authorization with the compact sorted bytes from
stable-1.0-dependency-vulnerability-ledger-tip-anchor-genesis.json. Missing state is never
treated as genesis. The first successor is accepted only against that exact uninitialized anchor;
later authorizations use an exact predecessor digest-and-edition compare-and-swap. Evaluation is
read-only while it is running. Disposition authorization, dependency-evidence publication, and maintenance publication
or baseline activation share the Stable vulnerability ledger concurrency lock and recheck the
current PR-290 tip and the promotion summary's exclusive validUntil immediately before mutation.
Disposition, remediation, and retention producers upload only encrypted proposals and receive no
anchor-write token. The protected
shared drainer dispatches and awaits
stable-1.0-dependency-vulnerability-tip-activation.yml for each retained producer, oldest first,
only after source and inventory proposals have drained. GitHub must record every selected producer
as completed-success. The finalizer reauthenticates the exact run, attempt, artifact digest,
encrypted binding, and ledger predecessor before performing the final CAS.
Failed, cancelled, and still-running producers can never become the durable current tip. The
event-driven drainer also rediscovers retained proposals on a bounded schedule; this recovers an
older pending notification that GitHub concurrency replaced without weakening the single shared
ledger lock or combining the three environment-scoped write credentials.
Phase assembly therefore compares producer coordinates with this anchor only for disposition
authorization, prepare-remediation, and retention artifacts. Read-only evaluation artifacts,
including intentionally blocked match-inventory evidence needed for disposition review, remain
exact candidate-commit-bound inputs and are not misclassified as committed ledger producers.
The same anchor binds the exact ledger byte digest and Actions artifact expiry. The scheduled
stable-1.0-dependency-vulnerability-ledger-retention.yml workflow runs under the shared lock,
authenticates and copies the complete current artifact; the post-success activation workflow
compare-and-swaps its renewed artifact coordinate without advancing the ledger edition. Its
API-derived renewal deadline is seven days
before artifact expiry; ordinary current/predecessor verification blocks at that deadline. If the
exact bytes expire before renewal, the workflow fails closed and cannot synthesize a new genesis.
Configure the phase-handoff key plus anchor read/write tokens in the protected
stable-1.0-dependency-vulnerability-ledger-activation environment. Producer and retention
environments receive only the phase key and least-privilege anchor-read token they require.
The aggregate release-certification workflow uses pre-publication for release-branch pushes and
ordinary candidate checks. It does not request the final PR-290 handoff before a tag and non-draft
GitHub Release exist. After publication, dispatch it with
dependency-vulnerability-stage=post-publication and the exact PR-290 publication run, attempt,
artifact name, and Actions digest. The protected job then authenticates the verify-publication
handoff and rechecks its validity deadline and current ledger tip. Historical pre-activation
candidates remain on their original certification contract.
See the governance and operations runbook and the Phase 11 closeout.
Use one command and policy family for both release classes:
python3 tools/release-certification/certify.py stable-maintenance \
--manifest build/stable-1.0-maintenance.jsonThe manifest selects maintenance or security-hotfix and one side-effect-free mode:
validate-only, prepare-authorization, or close-hotfix-follow-up. Output is release-scoped
under build/release-certification/<release-id>/stable-maintenance/. Self-tests and ordinary local
execution never tag, publish, insert a CoreUpdater descriptor, or update the latest baseline.
The generated stable-1.0-maintenance-checksums.txt names only noncircular public payloads:
product and package bytes, the stable catalog and detached signature, release notes, the
known-limitations delta, provenance, and core-info.json. It does not name internal certification
records. The checksum file itself and the public authorization are separately bound by exact size
and digest in the publication plan and receipt because including either would introduce a checksum
or authorization cycle. The separate
stable-1.0-maintenance-audit-checksums.txt deterministically inventories every other file in the
component output for internal audit and recovery and is never a planned public asset.
Candidate construction has a separate protected freeze-candidate boundary. Its versioned
stable-1.0-maintenance-candidate-freeze.json records the one-build producer and source identities,
toolchain and dependency-verification state, latest predecessor observation, exact checksum digest,
and the complete product, catalog, and package byte/signing/notarization receipt set. Subsequent
validation supplies that file as inputs.maintenanceCandidateFreeze; the candidate declaration,
candidate provenance, authorization, evidence envelope, and every evidence row bind its exact file
digest. Evidence must start after the recorded frozenAt. A rebuild, stale predecessor, extra or
replaced asset, or pre-freeze evidence requires a new freeze and cannot be repaired during
authorization preparation.
Production evidence rows bind the immediate predecessor build and product. The
stable-maintenance.direct-ga-upgrade row also binds the separately authenticated immutable GA
release id, build, and product digest; all non-GA rows forbid those GA fields. Normal validation and
hotfix follow-up closure enforce both identities, so a later successor cannot relabel its immediate
predecessor as the direct-GA upgrade source.
For immutable security hotfixes published before release-train governance, the v1 maintenance
authorization schema continues to accept an absent backportReleaseTrainDigest only so
close-hotfix-follow-up can authenticate the original authorization digest. Current preparation,
validation, and protected publication still require that field semantically and reject its
absence.
The standard manifest supplies previousStableLifecycleLedger,
previousStableLifecycleDescriptor, stableLifecycleAuthorization,
stableLifecyclePublicationPlan, and stableLifecyclePublicationReceipt from
build/protected-inputs/lifecycle/. The five inputs are indivisible: the engine authenticates the
predecessor's lifecycle eligibility, exact mutable descriptor edition and bytes, approved
authorization digest, authorized plan digest, trusted update-key scope, ledger digest, and verified
public receipt before it can report promotion readiness. Every post-GA successor predecessor
requires the exact five-artifact authority chain. A chain-depth-0 GA genesis run may omit all five
only to evaluate the first proposal; that bootstrap result is deliberately
promotionReady=false and decision=no-go until the separately protected GA-rooted lifecycle
descriptor has been published and verified.
The protected maintenance workflow uses four closed operations in four runs:
freeze-candidate, prepare-authorization, validate-authorization, and publish. Freeze is the
only operation that builds packages; it signs, notarizes, staples, and verifies the DMG before
recording any digest. Prepare consumes the exact attested freeze plus later candidate-bound evidence
and cannot replace an asset. Authorization validation consumes the exact prepared artifact plus an
approval artifact containing only the authorization JSON. Publish consumes the exact authorized
bundle and rejects separately supplied candidate, evidence, package, manifest, or authorization
inputs. Its provider is one protected, attested wheel pinned by producer run, artifact digest,
source commit, wheel digest, signer workflow, and entry point, then installed on each clean hosted
runner without dependency resolution. Publication and latest-baseline activation reread the remote
release/hotfix ref at their mutation boundaries. Publication requires the original authorization to
remain current before every public target. After the protected activation environment gate, the
workflow issues a separate activation-only authorization, valid for at most one hour and bound to
the exact verified receipt, successor, history, original authorization, and predecessor pointer.
That renewable grant prevents an environment wait from stranding already-published exact bytes;
activation audit state is uploaded even if post-mutation verification fails.
The protected input producer requires the lifecycle authority chain's exact five files in the normal post-GA freeze and preparation bundles. Authorization validation still accepts only the approval JSON, so the maintenance workflow restores the complete prepared manifest and protected-input tree, proves that only the mode and authorization field changed, and stages exact lifecycle audit copies again. Publish consumes the authorized artifact unchanged and retains those copies in its publication audit; it cannot substitute a new lifecycle state at a later phase. Before re-attesting the phase manifest, the producer verifies every lifecycle file against the canonical lifecycle workflow and the exact reviewed lifecycle source commit.
Hotfix closure authenticates the already published successor baseline, publication receipt,
latest-published pointer, original authorization, and obligation, then emits a separately versioned
closure overlay. The next release lineage binds that overlay digest; closure never changes the
published hotfix bytes or rewrites an activated baseline. When a later hotfix carries the
obligation, candidate-freeze authentication uses the original predecessor observation in the exact
authorized freeze while the latest baseline, receipt, and pointer independently authenticate the
current carrier.
Protected publication writes stable-1.0-maintenance-publication-receipt.json only for a complete,
independently verified result. Failure and partial state use the closed
stable-1.0-maintenance-publication-failure-audit.json schema so unavailable observations and
possible side effects are recorded without manufacturing a canonical receipt.
An interrupted operation can resume only when the observed public targets are an exact matching
prefix in canonical mutation order followed solely by absent targets; any other partial topology is
a conflict and is never overwritten or deleted automatically.
The protected evidence environment must configure exact input and Windows signer-workflow
identities. It must also configure STABLE_CATALOG_TRUSTED_KEYS_BASE64 as a base64-encoded
TrustedAppKeys properties registry containing production catalog public keys only. Before
freezing, the workflow decodes that registry into a mode-0600 temporary file, verifies the exact
candidate catalog and detached signature with AppCatalogVerifier, and requires the signature key
id to equal the candidate's declared signingKeyId. The workflow deletes the registry before job
exit and records only the catalog digest, signature digest, key id, trusted-key-registry SHA-256,
algorithm, verifier identity, and passing status. It never writes public-key bytes or raw signature
content into a JSON verification record. The exact detached signature sidecar remains a separately
frozen and published asset.
Configure the approved publication backend source commit, wheel digest, signer workflow, and entry point as repository-level Actions variables so the evidence-scoped independent verifier and both publication environments receive the same immutable, public-safe identity pins. Do not scope those four backend identity variables only to a publication environment. Keep the separate catalog, CoreUpdater, and maintenance-state protected inputs in their purpose-specific publication environments. Private target values are environment indirections only and are forbidden in manifests, component outputs, failure audits, and receipts.
Build that backend only through
.github/workflows/stable-1.0-maintenance-publication-backend-producer.yml at a reviewed main
commit. The consumer pins the producer run, artifact name and digest, source commit, deterministic
wheel digest, signer workflow, and cryptad_stable_maintenance_backend:factory entry point before
installing it outside the candidate import path. The deployment service accepts canonical public
HTTPS roots with or without a trailing slash and non-root endpoints with at most one terminal
slash; it rejects internal empty or dot segments and non-global destinations. Its
verify-publication request receives the closed, digest-bound verificationInputs record set
needed to construct receipts, successor state, and history without out-of-band candidate data.
See the publication-backend protocol.
The adapter materializes each target input, permanently scrubs all target-input names from its
local and ambient environments before importing the provider, and passes an opaque value only to
the one matching target operation. It also expands every concrete artifact, catalog/signature,
mirror/rollback, GitHub Release, and update-descriptor URI before authorization and rejects any
canonical cross-role collision.
The canonical signer workflows are
.github/workflows/stable-1.0-maintenance-input-producer.yml and
.github/workflows/stable-1.0-maintenance-windows-package-producer.yml. The former authenticates an
exact-digest public-safe phase ZIP from a secret protected-environment HTTPS locator. It rejects any
non-global DNS answer, pins the connection to the validated numeric endpoints, verifies the actual
peer, and uses the original hostname for TLS certificate verification before transmitting an
optional bearer credential. The complete extracted tree is allowlisted: only the canonical phase
manifest and its referenced protected inputs may survive into the attested artifact, so unrelated
root-level or sibling files fail intake. The latter builds the Windows EXE once,
Authenticode-signs and verifies it, rechecks the immutable tracked source, and attests the exact
EXE and producer receipt. Neither
workflow publishes release state.
The protected workflow performs current-time revalidation before exact-byte public mutations and independent receipt verification afterward. See the Stable 1.0 maintenance release and security hotfix path for required inputs, lineage, evidence, authorization, private secret boundaries, idempotency, and recovery.
The lifecycle command authenticates the immutable Stable 1.0 GA root and every published maintenance or security-hotfix successor before it assigns support state:
python3 tools/release-certification/certify.py stable-lifecycle \
--manifest build/stable-1.0-support-lifecycle.jsonThe command has four side-effect-free modes: evaluate, prepare-transition,
validate-authorization, and verify-publication. It writes below
build/release-certification/<release-id>/stable-lifecycle/. Evaluation derives the release
inventory from exact GA and maintenance publication receipts, successor baselines, history links,
and the latest published pointer. A manifest label cannot add a release to that inventory.
stable-1.0-support-lifecycle-policy.json is the reviewed source of product support windows,
transition rules, authorization roles, descriptor freshness, Platform API removal constraints,
governance references, and non-waivable blockers. The closed lifecycle order is
current-stable, supported-maintenance, security-fixes-only, deprecated, and
end-of-support. Any non-revoked state can instead enter the separately authorized terminal
revoked state. The engine does not infer update-key compromise from build revocation.
Normal descriptors select exactly one current-stable authenticated chain tip. The versioned
policy permits zero current builds only when that exact tip is explicitly revoked before a safe
successor is available. Recovery-only transitions keep current, recommended, and replacement build
fields null and publish bounded recovery guidance; certification never manufactures the unsafe tip
as its own replacement.
Generated descriptors must remain directly consumable by the runtime parser. The complete
inventory is capped at 256 entries, each statusEffectiveAt is no later than descriptor
effectiveAt, and a revoked entry uses the same value for statusEffectiveAt and
securityRevocationEffectiveAt. A supported-maintenance entry leaves replacementBuild null;
the descriptor-level recommendedBuild carries its optional upgrade guidance. Certification and
the protected adapter reject schema/runtime text or release-identity mismatches before
publication.
Lifecycle output includes the authenticated inventory, append-only digest-chained ledger, proposed
transition set, runtime descriptor, Platform API deprecation timeline, catalog/app/content-profile
governance projection, publication plan, provenance, checksums, summary, report, and redaction
report. Historical GA and maintenance artifacts, including already published core-info.json
files, remain immutable. Changing support state produces a new edition of the separately
authenticated support-lifecycle update-key document.
Descriptor edition 1 requires a fresh protected proof that the exact lifecycle target returned
HTTP 404 and has never been published. Bootstrap may occur against the authenticated GA alone or
against a complete no-fork history containing already-published maintenance/hotfix builds. The
proof binds the inventory digest, GA root, chain tip, public URI, and update-key scope. HTTP 410
is a tombstone, not absence, and fails closed. Once edition 1 exists, both
previousStableLifecycleLedger and previousStableLifecycleDescriptor are mandatory.
Ordinary certification never inserts that document. The protected
stable-1.0-support-lifecycle-input-producer.yml workflow first fetches one reviewed public-safe
ZIP by exact digest, rejects redirects, private endpoints, unsafe archives, unreferenced files, and
non-production execution flags, then attests its manifest and every protected input. The
stable-1.0-support-lifecycle.yml consumer pins that canonical producer identity.
Lifecycle input and publication jobs run only from protected main, the exact
release/<build_version>, or the exact hotfix/<build_version> ref. Their job conditions first
require GitHub's protected-ref context. The source_commit input must equal both the
workflow-dispatch GITHUB_SHA and the checked-out HEAD, which keeps GitHub's attested source
digest aligned with the code handling protected inputs. The jobs then query the live GitHub branch
record, require protected=true, fetch the same remote branch, and require the dispatch commit to
remain its ancestor. This ancestry check tolerates the branch advancing after dispatch; it does not
permit an independently selected older commit. The publication job repeats that proof before
insert material is made available; the input producer first completes it in a credential-free job
before requesting its environment, then repeats it before receiving the protected bundle locator
and bearer token.
Configure the lifecycle evidence, authorization, and publication environments with deployment
branch rules limited to protected main, release/*, and hotfix/* refs. Workflow job conditions
retain the exact-build allowlist independently of those repository settings.
Authorization validation restores those attested inputs and reruns stable-lifecycle; it does not
trust a caller-assembled authorization summary or publication plan. Publication repeats the same
certification immediately before mutation, then performs a live read of the separately bound
maintenance latest-pointer URI. GA-only history requires pointer absence. Post-GA history requires
the exact pointer digest and tip identity. Lifecycle and maintenance publication share the
stable-1-0-maintenance-publication concurrency lock so the pointer cannot advance between that
read and lifecycle insertion within the protected workflows.
Publication material is supplied only through the protected lifecycle environment. The publisher
accepts identical existing bytes as an idempotent verification, rejects conflicting bytes without
overwrite, fetches the public result again, and emits an exact-byte receipt. It preserves the
authorized component and its checksum closure unchanged; the actual receipt, preflight, and
operation summary are root-level siblings in the complete published bundle. Independent
verification consumes that complete bundle, proves the original publication receipt was generated
inside the bound authorization window, and writes a separate receipt. The read-only re-fetch may
run after that approval expires; validation and publication may not. Pull requests,
self-tests, and the default evaluate path cannot invoke publication.
See the support lifecycle and deprecation governance runbook for policy clocks, descriptor rollback protection, runtime behavior, Platform API and ecosystem deprecation rules, security revocation, protected operations, recovery, and public-data boundaries.
stable-legacy-plugin-migration accepts only a bounded sanitized observation, never a source
database, conversion package, private plan, backup, or raw content comparison. Use --mode preflight or --mode verify-migration with --observation, --workspace-root, and a fresh
--out-dir. The example at
manifests/sharesite-migration-local-observation.example.json has synthetic identity placeholders
and unobserved outcomes; it does not prove an executable migration.
Output contains only summary.json, report.md, and redaction-report.json. The closed allowlist
permits exact public adapter/app identities, pinned source format, opaque operation ID, bounded
counts, exclusions and outcome enums. It rejects source paths/hashes, labels, old read references,
private payloads and arbitrary producer assertions before the shared redaction scan runs.
Local reports never become authenticated format/runtime/real-data evidence. verify-runtime and
closeout return nonzero with protected-migration-producer-not-configured; release eligibility
also retains pr296-protected-subject-projection-pending. A local self-digest, fixture, or resealed
receipt cannot bypass those prerequisites. No protected workflow or new release authority is
introduced. See the pilot runbook for conversion,
consent, identity, private-data recovery and the four evidence levels.
python3 tools/release-certification/certify.py stable-content-profile-review --mode review
executes the policy-selected production Java/JavaScript conformance suites and exports the actual
five-profile registry through crypta-app api content-formats. --mode inspect only inspects
source/corpus identity; --self-test exercises review validation, not content interoperability.
See the scoped review. Local outputs do not
promote profiles, authenticate remote runners, or satisfy PR-296/297 operational prerequisites.
Upload only the bounded public summary; execution logs can contain synthetic assertion payloads
and remain private. Historical RC/GA digest semantics and frozen bytes remain unchanged.