import { createHash, generateKeyPairSync, sign, type KeyObject, } from "node:crypto"; import { mkdir, mkdtemp, writeFile } from "node:fs/promises"; import { tmpdir } from "node:os"; import path from "node:path"; import { localEvidenceAssessmentArtifactSchema } from "../../scripts/contracts/release-artifacts.ts"; import { PROMOTED_FILE_NAMES } from "../../scripts/contracts/promotion-artifacts.ts"; import { providerEvidenceSignaturePayload, trustPolicySha256, } from "../../scripts/lib/provider-evidence.ts"; import { LOCAL_EVIDENCE_ASSESSMENT_PATH, distSha256, type ReleaseCandidateManifest, } from "../../scripts/lib/release-candidate.ts"; import { supplyChainDigest } from "../../scripts/lib/supply-chain.ts"; export const PROCESS_HEAVY_TIMEOUT_MS = 30_000; export const digest = (value: string): string => createHash("sha256").update(value).digest("hex"); export const digestBytes = (value: Buffer): string => createHash("sha256").update(value).digest("hex"); export function passingAssessment(): any { return { schemaVersion: 1 as const, artifactType: "local-evidence-assessment" as const, generatedAt: "2026-08-02T00:00:00.000Z", status: "PASS" as const, verifier: { id: "clean-architecture-frontend-template/local-evidence-verifier", version: "1", sourceSha256: digest("verifier source"), }, source: { revision: "a".repeat(40), sourceSetSha256: digest("source set"), }, candidate: { distSha256: digest("dist"), lockfileSha256: digest("lockfile"), sbomSha256: digest("sbom"), }, secretScan: { policySha256: digest("secret policy"), sarifSha256: digest("secret sarif"), scanInputSha256: digest("secret scan input"), }, policyInputs: [ { path: "config/security/dependency-policy.json", bytes: 3, sha256: digest("{}\n"), }, ], evidenceInputs: [ { path: "pnpm-lock.yaml", bytes: 9, sha256: digest("lockfile\n") }, ], checks: { release: "PASS" as const, supplyChain: "PASS" as const, dependencyPolicy: "PASS" as const, licensePolicy: "PASS" as const, vulnerabilityPolicy: "PASS" as const, secretScan: "PASS" as const, }, failures: [] as string[], }; } export function providerExpectedContext() { return { run: { id: "run-42", attempt: 1 }, source: { revision: "b".repeat(40), sourceSetSha256: digest("provider source") }, candidate: { archiveSha256: digest("archive"), bundleSha256: digest("bundle"), distSha256: digest("provider dist"), lockfileSha256: digest("provider lockfile"), }, secretScanAttestation: { status: "PASS" as const, localEvidenceAssessmentSha256: digest("provider assessment"), sourceSetSha256: digest("provider source"), policySha256: digest("provider secret policy"), sarifSha256: digest("provider secret sarif"), scanInputSha256: digest("provider secret input"), }, } as const; } export function privatePromotionFiles() { return PROMOTED_FILE_NAMES.map((name) => { const bytes = Buffer.from(`${name}\n`); return { name, bytes, sha256: digestBytes(bytes) }; }); } export function syntheticSignedPromotionBundle() { const vulnerabilityKeys = generateKeyPairSync("ed25519"); const provenanceKeys = generateKeyPairSync("ed25519"); const archiveBytes = Buffer.from("synthetic signed replay archive\n"); const run = { id: "signed-run", attempt: 1 } as const; const source = { revision: "a".repeat(40), sourceSetSha256: digest("synthetic-source-set"), } as const; const candidate = { archiveSha256: digestBytes(archiveBytes), bundleSha256: digest("synthetic-bundle"), distSha256: digest("synthetic-dist"), lockfileSha256: digest("synthetic-lock"), } as const; const vulnerability = signedProviderV2( { schemaVersion: 2, evidenceType: "vulnerability-report", provider: "synthetic-vulnerability-provider", issuedAt: "2026-08-02T01:00:00.000Z", expiresAt: "2026-08-02T02:00:00.000Z", run: { ...run, invocationNonce: "1".repeat(64) }, source, candidate, secretScanAttestation: { status: "PASS", localEvidenceAssessmentSha256: digest("synthetic-assessment"), sourceSetSha256: source.sourceSetSha256, policySha256: digest("synthetic-policy"), sarifSha256: digest("synthetic-sarif"), scanInputSha256: digest("synthetic-scan-input"), }, findings: [], }, "synthetic-vulnerability", vulnerabilityKeys.publicKey, vulnerabilityKeys.privateKey, ); const provenance = signedProviderV2( { schemaVersion: 2, evidenceType: "provenance-attestation", provider: "synthetic-provenance-provider", signer: "synthetic-signer", issuedAt: "2026-08-02T01:00:00.000Z", expiresAt: "2026-08-02T02:00:00.000Z", run: { ...run, invocationNonce: "2".repeat(64) }, source, candidate, subject: { name: "dist", digest: { sha256: candidate.distSha256 } }, }, "synthetic-provenance", provenanceKeys.publicKey, provenanceKeys.privateKey, ); const vulnerabilityBytes = Buffer.from(`${JSON.stringify(vulnerability)}\n`); const provenanceBytes = Buffer.from(`${JSON.stringify(provenance)}\n`); const vulnerabilityTrust = trust("synthetic-vulnerability", vulnerabilityKeys.publicKey); const provenanceTrust = trust("synthetic-provenance", provenanceKeys.publicKey); const providerEvidence = { vulnerabilityReportSha256: digestBytes(vulnerabilityBytes), provenanceAttestationSha256: digestBytes(provenanceBytes), vulnerabilityInvocationNonce: "1".repeat(64), provenanceInvocationNonce: "2".repeat(64), vulnerabilityKeyId: vulnerabilityTrust.keyId, vulnerabilityKeyFingerprint: vulnerabilityTrust.publicKeyFingerprint, provenanceKeyId: provenanceTrust.keyId, provenanceKeyFingerprint: provenanceTrust.publicKeyFingerprint, secretScanAttestation: vulnerability.secretScanAttestation, }; const common = { schemaVersion: 3, verifiedAt: "2026-08-02T01:00:00.000Z", status: "PASS", verifier: { id: "clean-architecture-frontend-template/promotion-verifier", version: "3", }, run, source, candidate, providerEvidence, trustPolicySha256: trustPolicySha256({ vulnerabilityTrust, provenanceTrust }), failures: [], }; const providerBytes = Buffer.from( `${JSON.stringify({ ...common, artifactType: "provider-verification", vulnerabilityStatus: "PASS", provenanceAttestationStatus: "PASS", }, null, 2)}\n`, ); const promotionBytes = Buffer.from( `${JSON.stringify({ ...common, artifactType: "promotion-verification", localEvidenceStatus: "PASS", localEvidenceAssessmentSha256: digest("synthetic-assessment"), providerVerificationSha256: digestBytes(providerBytes), }, null, 2)}\n`, ); return { files: { "release-candidate.tar.gz": archiveBytes, "vulnerability-report.json": vulnerabilityBytes, "provenance-attestation.json": provenanceBytes, "provider-verification.json": providerBytes, "promotion-verification.json": promotionBytes, }, verification: { vulnerabilityTrust, provenanceTrust, nowEpochMs: () => Date.parse("2026-08-02T01:00:00.000Z"), expected: { run, sourceRevision: source.revision, sourceSetSha256: source.sourceSetSha256, archiveSha256: candidate.archiveSha256, bundleSha256: candidate.bundleSha256, distSha256: candidate.distSha256, lockfileSha256: candidate.lockfileSha256, }, }, vulnerabilityPem: vulnerabilityKeys.publicKey.export({ type: "spki", format: "pem" }), provenancePem: provenanceKeys.publicKey.export({ type: "spki", format: "pem" }), }; } export function fingerprint(publicKey: KeyObject): string { return `sha256:${createHash("sha256") .update(publicKey.export({ type: "spki", format: "der" })) .digest("hex")}`; } export function trust(keyId: string, publicKey: KeyObject) { return { keyId, publicKey, publicKeyFingerprint: fingerprint(publicKey) }; } export function signedProviderV2( unsigned: Record, keyId: string, publicKey: KeyObject, privateKey: KeyObject, fingerprintOverride?: string, ): Record { const { signature: existingSignature, ...payload } = unsigned; const value = { ...payload, signature: { algorithm: "Ed25519" as const, keyId, publicKeyFingerprint: fingerprintOverride ?? (existingSignature && typeof existingSignature === "object" && "publicKeyFingerprint" in existingSignature ? String(existingSignature.publicKeyFingerprint) : fingerprint(publicKey)), value: "", }, }; value.signature.value = sign( null, providerEvidenceSignaturePayload(value), privateKey, ).toString("base64"); return value; } export function providerUnsigned( kind: "vulnerability" | "provenance", expected: ReturnType, ): Record { const common = { source: expected.source, candidate: expected.candidate, schemaVersion: 2, evidenceType: kind === "vulnerability" ? "vulnerability-report" : "provenance-attestation", provider: `fixture-${kind}`, issuedAt: "2026-08-02T01:00:00.000Z", expiresAt: "2026-08-02T02:00:00.000Z", run: { ...expected.run, invocationNonce: kind === "vulnerability" ? "1".repeat(64) : "2".repeat(64), }, }; return kind === "vulnerability" ? { ...common, secretScanAttestation: expected.secretScanAttestation, findings: [], } : { ...common, signer: "fixture-workload", subject: { name: "dist", digest: { sha256: expected.candidate.distSha256 }, }, }; } export async function createArchivedAssessmentFixture(): Promise<{ root: string; manifest: ReleaseCandidateManifest; assessmentSha256: string; }> { const root = await mkdtemp(path.join(tmpdir(), "archived-assessment-")); const sourceRevision = "a".repeat(40); const sourceSetSha256 = digest("source set"); const releaseManifestBytes = Buffer.from( `${JSON.stringify({ schemaVersion: 1, appVersion: "1.0.0", buildId: "build-1", commitSha: sourceRevision, configSchemaVersion: "1", apiContractVersion: "1", assetManifestHash: digest("vite manifest"), releaseId: "release-1", builtAt: "2026-08-02T00:00:00.000Z", routeChunks: { home: "assets/home.js" }, })}\n`, ); const distInputs = [ { path: "dist/app.js", bytes: Buffer.byteLength("app\n"), sha256: digest("app\n"), gzipBytes: 0 }, { path: "dist/release-manifest.json", bytes: releaseManifestBytes.byteLength, sha256: digestBytes(releaseManifestBytes), gzipBytes: 0, }, ]; const candidateDist = distSha256(distInputs); const sbomBytes = Buffer.from( `${JSON.stringify({ bomFormat: "CycloneDX", specVersion: "1.6", serialNumber: "urn:uuid:00000000-0000-4000-8000-000000000001", version: 1, metadata: { component: { type: "application", name: "fixture", version: "1.0.0" }, properties: [], }, components: [], dependencies: [], })}\n`, ); const sbomSha256 = digestBytes(sbomBytes); const lockfileBytes = Buffer.from("lockfile\n"); const lockfileDigest = digestBytes(lockfileBytes); const buildManifest = { schemaVersion: 1, buildId: "build-1", commitSha: sourceRevision, releaseId: "release-1", moduleInventoryHash: digest("module inventory"), generatedAt: "2026-08-02T00:00:00.000Z", buildContext: { nodeVersion: "v24.0.0", packageManagerVersion: "11.0.0", runnerImage: "linux-x64", sourceDateEpoch: "1785638400", }, outputs: { directory: "dist", viteManifest: "dist/.vite/manifest.json", moduleInventory: "artifacts/quality/vite-module-inventory.json", routeChunks: { home: "assets/home.js" }, runtimeConfigSchema: "dist/runtime-config.schema.json", }, }; const provenance = { _type: "https://in-toto.io/Statement/v1", subject: [{ name: "dist", digest: { sha256: candidateDist } }], predicateType: "https://slsa.dev/provenance/v1", predicate: { buildDefinition: { buildType: "https://vite.dev/build/v1", externalParameters: {}, internalParameters: {}, resolvedDependencies: [ { uri: "pnpm-lock.yaml", digest: { sha256: lockfileDigest } }, ], }, runDetails: { builder: { id: "fixture-builder" }, metadata: { invocationId: "LOCAL_UNSIGNED" }, }, materials: { lockfileSha256: lockfileDigest, sourceSetSha256, sbomSha256 }, }, }; const supplyVerification = { schemaVersion: 1, localStatus: "PASS", promotionStatus: "FAIL_UNVERIFIED", lockfileSha256: lockfileDigest, sourceSetSha256, distSha256: candidateDist, sbomSha256, dependencyDiff: { added: [], removed: [], changed: [], upgrades: [] }, highRiskReview: [], vulnerabilityStatus: "FAIL_UNVERIFIED", provenanceAttestationStatus: "FAIL_UNVERIFIED", failures: [], }; const members = new Map([ ["dist/app.js", Buffer.from("app\n")], ["dist/release-manifest.json", releaseManifestBytes], ["pnpm-lock.yaml", lockfileBytes], ["artifacts/release/build-manifest.json", Buffer.from(`${JSON.stringify(buildManifest)}\n`)], ["artifacts/release/provenance.json", Buffer.from(`${JSON.stringify(provenance)}\n`)], [ "artifacts/security/supply-chain-verification.json", Buffer.from(`${JSON.stringify(supplyVerification)}\n`), ], ["artifacts/release/sbom.cdx.json", sbomBytes], ]); const evidenceInputs = [...members.entries()] .map(([memberPath, bytes]) => ({ path: memberPath, bytes: bytes.byteLength, sha256: digestBytes(bytes), })) .sort((left, right) => (left.path < right.path ? -1 : left.path > right.path ? 1 : 0)); const policyPaths = [ "config/security/dependency-baseline.approval.json", "config/security/dependency-baseline.json", "config/security/dependency-change-evidence.json", "config/security/dependency-policy.json", "config/security/secret-scan-policy.json", "config/security/vulnerability-exceptions.json", "config/security/vulnerability-policy.json", "schemas/artifacts/build-manifest.schema.json", "schemas/artifacts/dependency-inventory.schema.json", "schemas/artifacts/supply-chain-verification.schema.json", "scripts/contracts/release-artifacts.ts", "scripts/create-release-candidate.ts", "scripts/generate-supply-chain.ts", "scripts/lib/build-manifest-outputs.ts", "scripts/lib/json-schema.ts", "scripts/lib/local-policy-evidence.ts", "scripts/lib/local-release-evidence.ts", "scripts/lib/release-candidate.ts", "scripts/lib/release-input-evidence.ts", "scripts/lib/release-runtime-coherence.ts", "scripts/lib/repository-file-inventory.ts", "scripts/lib/secret-scan-evaluator.ts", "scripts/lib/secret-scan-policy.ts", "scripts/lib/secret-scan.ts", "scripts/lib/supply-chain.ts", "scripts/lib/validated-json-artifact.ts", "src/contracts/release-artifacts.ts", "src/features/installed-contract-contributions.ts", "src/features/installed-feature-contracts.ts", ]; const sbomRow = evidenceInputs.find( ({ path: memberPath }) => memberPath === "artifacts/release/sbom.cdx.json", )!; const policyInputs = policyPaths.map((policyPath) => ({ path: policyPath, bytes: 2, sha256: digest(`policy:${policyPath}`), })); const verifierPaths = new Set([ "scripts/contracts/release-artifacts.ts", "scripts/create-release-candidate.ts", "scripts/generate-supply-chain.ts", "scripts/lib/build-manifest-outputs.ts", "scripts/lib/json-schema.ts", "scripts/lib/local-policy-evidence.ts", "scripts/lib/local-release-evidence.ts", "scripts/lib/release-candidate.ts", "scripts/lib/release-input-evidence.ts", "scripts/lib/release-runtime-coherence.ts", "scripts/lib/repository-file-inventory.ts", "scripts/lib/secret-scan-evaluator.ts", "scripts/lib/secret-scan-policy.ts", "scripts/lib/secret-scan.ts", "scripts/lib/supply-chain.ts", "scripts/lib/validated-json-artifact.ts", "src/contracts/release-artifacts.ts", "src/features/installed-contract-contributions.ts", "src/features/installed-feature-contracts.ts", ]); const assessment = localEvidenceAssessmentArtifactSchema.parse({ ...passingAssessment(), verifier: { id: "clean-architecture-frontend-template/local-evidence-verifier", version: "1", sourceSha256: supplyChainDigest( policyInputs.filter(({ path: policyPath }) => verifierPaths.has(policyPath)), ), }, source: { revision: sourceRevision, sourceSetSha256 }, candidate: { distSha256: candidateDist, lockfileSha256: evidenceInputs.find(({ path: memberPath }) => memberPath === "pnpm-lock.yaml")! .sha256, sbomSha256: sbomRow.sha256, }, policyInputs, evidenceInputs, }); const assessmentBytes = Buffer.from(`${JSON.stringify(assessment)}\n`); members.set(LOCAL_EVIDENCE_ASSESSMENT_PATH, assessmentBytes); for (const [memberPath, bytes] of members) { await mkdir(path.dirname(path.join(root, memberPath)), { recursive: true }); await writeFile(path.join(root, memberPath), bytes); } const files = [...members.entries()] .map(([memberPath, bytes]) => ({ path: memberPath, bytes: bytes.byteLength, sha256: digestBytes(bytes), })) .sort((left, right) => (left.path < right.path ? -1 : left.path > right.path ? 1 : 0)); const manifest: ReleaseCandidateManifest = { schemaVersion: 1, distSha256: assessment.candidate.distSha256, lockfileSha256: assessment.candidate.lockfileSha256, bundleSha256: supplyChainDigest(files), files, }; await mkdir(path.join(root, "artifacts/release"), { recursive: true }); await writeFile( path.join(root, "artifacts/release/release-candidate.json"), `${JSON.stringify(manifest)}\n`, ); return { root, manifest, assessmentSha256: digestBytes(assessmentBytes) }; }