fix(release): preserve focused evidence lineage (#129060)

* fix(release): preserve focused evidence lineage

* fix(release): bind focused evidence to authorized tooling

* fix(release): revalidate focused evidence after Docker approval
This commit is contained in:
Peter Steinberger
2026-08-25 01:58:18 -07:00
committed by GitHub
parent ccd8ede95e
commit afa89f03ee
6 changed files with 455 additions and 24 deletions
@@ -24,7 +24,11 @@ type ParsedWorkflow = {
jobs?: Record<
string,
{
needs?: string | string[];
outputs?: Record<string, string>;
permissions?: Record<string, string>;
steps?: Array<{
env?: Record<string, string>;
if?: string;
name?: string;
run?: string;
@@ -83,6 +87,17 @@ function fixturePolicy(): { policy: AuthorizedBetaFocusedPolicy; root: string }
execFileSync("git", ["config", "user.email", "test@example.com"], { cwd: root });
execFileSync("git", ["config", "user.name", "Test"], { cwd: root });
writeFileSync(join(root, "published.txt"), "published\n");
const historicalToolingSha = commit(root, "historical tooling");
mkdirSync(join(root, ".github", "workflows"), { recursive: true });
mkdirSync(join(root, "scripts"));
writeFileSync(
join(root, ".github", "workflows", "authorized-beta-focused-validation.yml"),
"name: Authorized Beta Focused Validation\n",
);
writeFileSync(
join(root, "scripts", "authorized-beta-focused-policy.json"),
JSON.stringify({ historicalToolingSha }),
);
mkdirSync(join(root, "tests"));
writeFileSync(join(root, "tests", "proof.test.ts"), "one\n");
const baseCandidateSha = commit(root, "base");
@@ -101,6 +116,7 @@ function fixturePolicy(): { policy: AuthorizedBetaFocusedPolicy; root: string }
...readAuthorizedBetaFocusedPolicy(),
baseCandidateSha,
candidateSha,
historicalToolingSha,
reviewedHeadSha: candidateSha,
candidateTreeSha,
baseTreeSha,
@@ -117,7 +133,215 @@ function fixturePolicy(): { policy: AuthorizedBetaFocusedPolicy; root: string }
};
}
function resolveFocusedProducer(
options: {
annotatedTag?: boolean;
boundary?: "docker" | "resolve";
consumer?: "ancestor" | "current" | "diverged";
missingTag?: boolean;
producer?: "policy-drift" | "unanchored" | "workflow-drift";
run?: Record<string, unknown>;
tag?: Record<string, unknown>;
} = {},
) {
const { policy, root } = fixturePolicy();
let producerSha = options.consumer === "current" ? policy.candidateSha : policy.baseCandidateSha;
const consumerSha = policy.candidateSha;
if (options.consumer === "diverged" || options.producer) {
if (options.producer === "unanchored") {
git(root, ["checkout", "--quiet", "--orphan", "unanchored-producer"]);
} else {
git(root, ["checkout", "--quiet", "--detach", policy.baseCandidateSha]);
}
if (options.producer === "policy-drift") {
writeFileSync(
join(root, "scripts", "authorized-beta-focused-policy.json"),
JSON.stringify({ historicalToolingSha: "f".repeat(40) }),
);
} else if (options.producer === "workflow-drift") {
writeFileSync(
join(root, ".github", "workflows", "authorized-beta-focused-validation.yml"),
"name: Untrusted Validation\n",
);
} else {
writeFileSync(join(root, "published.txt"), "protected producer branch\n");
}
producerSha = commit(root, "protected producer");
git(root, ["checkout", "--quiet", "--detach", consumerSha]);
}
const producerRef = `release-publish/${producerSha.slice(0, 12)}-123`;
const outputPath = join(root, "github-output");
const isDockerBoundary = options.boundary === "docker";
const workflow = parse(
readFileSync(
isDockerBoundary
? ".github/workflows/docker-release.yml"
: ".github/workflows/openclaw-release-publish.yml",
"utf8",
),
) as ParsedWorkflow;
const run = {
id: 123,
run_attempt: 2,
name: "Authorized Beta Focused Validation",
path: ".github/workflows/authorized-beta-focused-validation.yml",
event: "workflow_dispatch",
status: "completed",
conclusion: "success",
head_branch: producerRef,
head_sha: producerSha,
...options.run,
};
const tag = {
ref: `refs/tags/${producerRef}`,
object: { sha: producerSha, type: options.annotatedTag ? "tag" : "commit" },
...options.tag,
};
const result = spawnSync(
"bash",
[
"-c",
[
"gh() {",
' if [[ "$2" == */actions/runs/* ]]; then',
' if [[ "${3:-}" == --jq ]]; then',
' printf "%s\\n" "$MOCK_RUN_JSON" | jq -r "$4"',
" else",
' printf "%s\\n" "$MOCK_RUN_JSON"',
" fi",
' elif [[ "$2" == */git/ref/tags/* && "$MOCK_TAG_MISSING" != true ]]; then',
' printf "%s\\n" "$MOCK_TAG_JSON" | jq -r "$4"',
" else",
" return 1",
" fi",
"}",
namedStep(
workflow,
isDockerBoundary ? "resolve_build_provenance" : "resolve_release_target",
isDockerBoundary
? "Revalidate focused evidence producer after Docker approval"
: "Resolve focused release evidence run",
).run,
].join("\n"),
],
{
cwd: root,
encoding: "utf8",
env: {
...process.env,
FOCUSED_RELEASE_EVIDENCE_RUN_ATTEMPT: "2",
FOCUSED_RELEASE_EVIDENCE_RUN_ID: "123",
GITHUB_OUTPUT: outputPath,
GITHUB_REPOSITORY: "openclaw/openclaw",
MOCK_RUN_JSON: JSON.stringify(run),
MOCK_TAG_JSON: JSON.stringify(tag),
MOCK_TAG_MISSING: String(options.missingTag ?? false),
PRODUCER_WORKFLOW_FULL_REF: `refs/tags/${producerRef}`,
PRODUCER_WORKFLOW_SHA: producerSha,
WORKFLOW_SHA: consumerSha,
},
},
);
return { consumerSha, outputPath, producerRef, producerSha, result };
}
describe("authorized beta focused evidence", () => {
it.each(["ancestor", "current", "diverged"] as const)(
"accepts an exact protected focused producer from %s trusted tooling",
(consumer) => {
const { outputPath, producerRef, producerSha, result } = resolveFocusedProducer({ consumer });
expect(result.stderr).toBe("");
expect(result.status).toBe(0);
expect(readFileSync(outputPath, "utf8")).toBe(
`attempt=2\nworkflow_full_ref=refs/tags/${producerRef}\nworkflow_sha=${producerSha}\n`,
);
},
);
it.each([
{ name: "unanchored producer", options: { producer: "unanchored" as const } },
{ name: "producer policy drift", options: { producer: "policy-drift" as const } },
{ name: "producer workflow drift", options: { producer: "workflow-drift" as const } },
{
name: "moved producer tag",
options: { tag: { object: { sha: "f".repeat(40), type: "commit" } } },
},
{ name: "missing producer tag", options: { missingTag: true } },
{ name: "annotated producer tag", options: { annotatedTag: true } },
{
name: "producer SHA prefix mismatch",
options: { run: { head_branch: "release-publish/ffffffffffff-123" } },
},
{
name: "malformed producer tag",
options: { run: { head_branch: "release-publish/ffffffffffff-0" } },
},
{
name: "wrong producer workflow path",
options: { run: { path: ".github/workflows/openclaw-release-publish.yml" } },
},
{ name: "wrong producer workflow name", options: { run: { name: "Other Validation" } } },
{ name: "wrong producer event", options: { run: { event: "push" } } },
{ name: "unfinished producer", options: { run: { status: "in_progress" } } },
{ name: "failed producer", options: { run: { conclusion: "failure" } } },
{ name: "wrong producer attempt", options: { run: { run_attempt: 3 } } },
])("rejects $name before focused artifact download", ({ options }) => {
expect(resolveFocusedProducer(options).result.status).not.toBe(0);
});
it("accepts the exact focused producer again after Docker approval", () => {
const { result } = resolveFocusedProducer({ boundary: "docker", consumer: "diverged" });
expect(result.stderr).toBe("");
expect(result.status).toBe(0);
});
it.each([
{
name: "moved producer tag",
options: { tag: { object: { sha: "f".repeat(40), type: "commit" } } },
},
{ name: "missing producer tag", options: { missingTag: true } },
{ name: "rerun producer", options: { run: { run_attempt: 3 } } },
{ name: "substituted producer", options: { run: { head_sha: "f".repeat(40) } } },
{ name: "failed producer", options: { run: { conclusion: "failure" } } },
])("rejects $name after Docker approval before registry access", ({ options }) => {
expect(resolveFocusedProducer({ ...options, boundary: "docker" }).result.status).not.toBe(0);
});
it("gates every Docker build on post-approval focused evidence revalidation", () => {
const docker = parse(
readFileSync(".github/workflows/docker-release.yml", "utf8"),
) as ParsedWorkflow;
const gate = docker.jobs?.resolve_build_provenance;
if (!gate) {
throw new Error("Docker build provenance gate is missing");
}
expect(gate.needs).toContain("approve_docker_publish");
expect(gate.permissions).toMatchObject({
actions: "read",
attestations: "read",
contents: "read",
});
const names = (gate.steps ?? []).map((step) => step.name);
const revalidation = names.indexOf(
"Revalidate focused evidence producer after Docker approval",
);
const download = names.indexOf("Download focused release evidence after Docker approval");
const verification = names.indexOf("Verify focused release evidence after Docker approval");
const provenance = names.indexOf("Resolve shared build provenance");
expect(revalidation).toBeGreaterThan(-1);
expect(revalidation).toBeLessThan(download);
expect(download).toBeLessThan(verification);
expect(verification).toBeLessThan(provenance);
for (const jobName of ["build-amd64", "build-arm64"]) {
expect(docker.jobs?.[jobName]?.needs).toContain("resolve_build_provenance");
}
});
it("pins the exact beta.3 candidate, inventories, trust split, and repaired leaves", () => {
const policy = readAuthorizedBetaFocusedPolicy();
expect(policy.releaseTag).toBe("v2026.8.1-beta.3");
@@ -320,8 +544,11 @@ describe("authorized beta focused evidence", () => {
const source = readFileSync(path, "utf8");
expect(source).toContain("Verify focused release evidence");
expect(source).toContain("gh attestation verify");
expect(source).toContain('--signer-digest "${WORKFLOW_SHA}"');
expect(source).toContain('--source-digest "${WORKFLOW_SHA}"');
const signerSha = path.endsWith("openclaw-release-publish.yml")
? "PRODUCER_WORKFLOW_SHA"
: "WORKFLOW_SHA";
expect(source).toContain(`--signer-digest "\${${signerSha}}"`);
expect(source).toContain(`--source-digest "\${${signerSha}}"`);
expect(source).toContain("validate-authorized-beta-focused-evidence.mts");
expect(source).toContain("inputs.release_evidence_mode == 'full-release-validation'");
expect(source).toContain("validate-full-release-validation-evidence.mjs");
@@ -348,6 +575,30 @@ describe("authorized beta focused evidence", () => {
const resolveSteps = parentWorkflow.jobs?.resolve_release_target?.steps ?? [];
const resolveStepNames = resolveSteps.map((step) => step.name);
expect(resolveStepNames).not.toContain("Install focused release verifier dependency");
expect(parentWorkflow.jobs?.resolve_release_target?.outputs).toMatchObject({
focused_release_evidence_workflow_full_ref:
"${{ steps.focused_run.outputs.workflow_full_ref }}",
focused_release_evidence_workflow_sha: "${{ steps.focused_run.outputs.workflow_sha }}",
});
for (const [jobName, stepName] of [
["resolve_release_target", "Verify focused release evidence"],
["publish", "Verify focused release evidence after approval"],
] as const) {
const verifyStep = namedStep(parentWorkflow, jobName, stepName);
const outputPrefix =
jobName === "publish"
? "needs.resolve_release_target.outputs.focused_release_evidence_"
: "steps.focused_run.outputs.";
expect(verifyStep.env).toMatchObject({
PRODUCER_WORKFLOW_FULL_REF: `\${{ ${outputPrefix}workflow_full_ref }}`,
PRODUCER_WORKFLOW_SHA: `\${{ ${outputPrefix}workflow_sha }}`,
});
expect(verifyStep.run).toContain('--source-ref "${PRODUCER_WORKFLOW_FULL_REF}"');
expect(verifyStep.run).toContain(
'--producer-workflow-full-ref "${PRODUCER_WORKFLOW_FULL_REF}"',
);
expect(verifyStep.run).toContain('--producer-workflow-sha "${PRODUCER_WORKFLOW_SHA}"');
}
const publishSteps = parentWorkflow.jobs?.publish?.steps ?? [];
const publishStepNames = publishSteps.map((step) => step.name);
expect(publishStepNames.indexOf("Verify focused release evidence after approval")).toBeLessThan(
+6 -1
View File
@@ -2043,7 +2043,12 @@ NODE
DOCKERHUB_USERNAME: "${{ secrets.DOCKERHUB_USERNAME }}",
DOCKERHUB_TOKEN: "${{ secrets.DOCKERHUB_TOKEN }}",
});
expect(publish.permissions).toEqual({ contents: "read", packages: "write" });
expect(publish.permissions).toEqual({
actions: "read",
attestations: "read",
contents: "read",
packages: "write",
});
expect(releaseWorkflow.jobs.approve_docker_publish.environment).toBe("docker-release");
});
@@ -1483,6 +1483,14 @@ describe("release validation no-push transport", () => {
expect(dockerCall.with).toEqual({
tag: "${{ inputs.tag }}",
release_sha: "${{ needs.resolve_release_target.outputs.sha }}",
focused_release_evidence_run_id:
"${{ inputs.release_evidence_mode == 'authorized-beta-focused-v1' && inputs.focused_release_evidence_run_id || '' }}",
focused_release_evidence_run_attempt:
"${{ needs.resolve_release_target.outputs.focused_release_evidence_run_attempt }}",
focused_release_evidence_workflow_full_ref:
"${{ needs.resolve_release_target.outputs.focused_release_evidence_workflow_full_ref }}",
focused_release_evidence_workflow_sha:
"${{ needs.resolve_release_target.outputs.focused_release_evidence_workflow_sha }}",
});
expect(dockerCall.secrets).toEqual({
DOCKERHUB_USERNAME: "${{ secrets.DOCKERHUB_USERNAME }}",