import { z } from "zod"; export * from "../../src/contracts/release-artifacts.ts"; const nonEmptyString = z.string().min(1); const timestamp = z.iso.datetime(); const sha256 = z.string().regex(/^[a-f0-9]{64}$/u); const jsonObject = z.record(z.string(), z.json()); const canonicalTimestamp = z .string() .regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/u) .refine((value) => new Date(value).toISOString() === value, { message: "must be a canonical ISO-8601 UTC timestamp", }); const safeRepositoryPath = z .string() .min(1) .max(1_024) .refine( (value) => !value.startsWith("-") && !value.startsWith("/") && !value.includes("\\") && !value.split("/").some((segment) => segment === "" || segment === "." || segment === "..") && ![...value].some((character) => { const codePoint = character.codePointAt(0)!; return codePoint <= 0x1f || codePoint === 0x7f; }), { message: "must be a safe canonical repository-relative path" }, ); const assessmentInputRowSchema = z .object({ path: safeRepositoryPath, bytes: z.int().nonnegative().max(268_435_456), sha256, }) .strict(); const assessmentStatusSchema = z.enum(["PASS", "FAIL"]); function addCanonicalInputIssues( rows: readonly Readonly<{ path: string }>[], pathPrefix: "policyInputs" | "evidenceInputs", context: z.RefinementCtx, ): void { const paths = rows.map(({ path }) => path); const canonical = [...paths].sort((left, right) => left < right ? -1 : left > right ? 1 : 0, ); if (JSON.stringify(paths) !== JSON.stringify(canonical)) { context.addIssue({ code: "custom", path: [pathPrefix], message: "must be in canonical ASCII path order", }); } if (new Set(paths).size !== paths.length) { context.addIssue({ code: "custom", path: [pathPrefix], message: "must not contain duplicate paths", }); } } export const localEvidenceAssessmentArtifactSchema = z .object({ schemaVersion: z.literal(1), artifactType: z.literal("local-evidence-assessment"), generatedAt: canonicalTimestamp, status: assessmentStatusSchema, verifier: z .object({ id: nonEmptyString, version: nonEmptyString, sourceSha256: sha256, }) .strict(), source: z .object({ revision: z.string().regex(/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/u), sourceSetSha256: sha256, }) .strict(), candidate: z .object({ distSha256: sha256, lockfileSha256: sha256, sbomSha256: sha256 }) .strict(), policyInputs: z.array(assessmentInputRowSchema).min(1).max(256), evidenceInputs: z.array(assessmentInputRowSchema).min(1).max(4_096), checks: z .object({ release: assessmentStatusSchema, supplyChain: assessmentStatusSchema, dependencyPolicy: assessmentStatusSchema, licensePolicy: assessmentStatusSchema, vulnerabilityPolicy: assessmentStatusSchema, secretScan: assessmentStatusSchema, }) .strict(), failures: z.array(z.string()), }) .strict() .superRefine((assessment, context) => { addCanonicalInputIssues(assessment.policyInputs, "policyInputs", context); addCanonicalInputIssues(assessment.evidenceInputs, "evidenceInputs", context); const failedChecks = Object.values(assessment.checks).filter( (status) => status === "FAIL", ); if ( assessment.status === "PASS" && (failedChecks.length > 0 || assessment.failures.length > 0) ) { context.addIssue({ code: "custom", path: ["status"], message: "PASS requires all six checks PASS and no failures", }); } if ( assessment.status === "FAIL" && (failedChecks.length === 0 || assessment.failures.length === 0) ) { context.addIssue({ code: "custom", path: ["status"], message: "FAIL requires a failed check and a failure diagnostic", }); } }); export type LocalEvidenceAssessment = z.infer< typeof localEvidenceAssessmentArtifactSchema >; export const moduleInventoryArtifactSchema = z .object({ schemaVersion: z.literal(1), chunks: z.array( z .object({ fileName: nonEmptyString, modules: z.array(nonEmptyString), }) .strict(), ), }) .strict(); export const jsonSchemaDocumentArtifactSchema = z .object({ $schema: z.literal("https://json-schema.org/draft/2020-12/schema"), }) .catchall(z.json()); const dependencyInventoryRowSchema = z .object({ name: nonEmptyString, version: nonEmptyString, direct: z.boolean(), scope: z.enum(["production", "development"]), optional: z.boolean(), license: nonEmptyString, integrity: z.string().regex(/^sha512-/u), dependencies: z.array(nonEmptyString), }) .strict(); export const dependencyInventoryArtifactSchema = z .object({ schemaVersion: z.literal(2), packageManager: nonEmptyString, lockfileSha256: sha256, dependencyCount: z.int().positive(), directDependencyCount: z.int().positive(), dependencies: z.array(dependencyInventoryRowSchema).min(1), }) .strict() .superRefine((inventory, context) => { if (inventory.dependencyCount !== inventory.dependencies.length) { context.addIssue({ code: "custom", path: ["dependencyCount"], message: "must equal dependencies.length", }); } const actualDirect = inventory.dependencies.filter( (dependency) => dependency.direct, ).length; if (inventory.directDependencyCount !== actualDirect) { context.addIssue({ code: "custom", path: ["directDependencyCount"], message: "must equal the number of direct dependencies", }); } }); const dependencyUpgradeSchema = z .object({ name: nonEmptyString, from: nonEmptyString, to: nonEmptyString, }) .strict(); export const dependencyDiffSchema = z .object({ added: z.array(nonEmptyString), removed: z.array(nonEmptyString), changed: z.array(nonEmptyString), upgrades: z.array(dependencyUpgradeSchema), }) .strict(); export const supplyChainVerificationArtifactSchema = z .object({ schemaVersion: z.literal(1), localStatus: z.enum(["PASS", "FAIL"]), promotionStatus: z.enum(["PASS", "FAIL_UNVERIFIED"]), lockfileSha256: sha256, sourceSetSha256: sha256, distSha256: sha256, sbomSha256: sha256, dependencyDiff: dependencyDiffSchema, highRiskReview: z.array(nonEmptyString), vulnerabilityStatus: z.enum(["PASS", "FAIL", "FAIL_UNVERIFIED"]), provenanceAttestationStatus: z.enum(["PASS", "FAIL_UNVERIFIED"]), failures: z.array(z.string()), }) .strict(); const registryChangeSchema = z .object({ changeId: nonEmptyString, registryId: nonEmptyString, rowName: nonEmptyString, field: nonEmptyString, kind: nonEmptyString, impact: z.enum(["none", "additive", "behavior-change", "breaking"]), before: z.json().optional(), after: z.json().optional(), }) .strict(); const registryArtifactRowSchema = z .object({ registryId: nonEmptyString, owner: nonEmptyString, source: nonEmptyString, rowCount: z.int().nonnegative(), contract: jsonObject, rows: jsonObject, }) .strict(); const registrySnapshotBaseArtifactSchema = z .object({ schemaVersion: z.literal(2), generatedAt: timestamp, baselineDigest: sha256.nullable(), currentDigest: sha256, compatibility: z .object({ impact: z.enum([ "not-evaluated", "none", "additive", "behavior-change", "breaking", ]), changes: z.array(registryChangeSchema), }) .strict(), }) .strict(); const successfulRegistrySnapshotArtifactSchema = registrySnapshotBaseArtifactSchema.extend({ failures: z.array(z.string()).max(0), registries: z.array(registryArtifactRowSchema).length(11), }); const failedRegistrySnapshotArtifactSchema = registrySnapshotBaseArtifactSchema.extend({ failures: z.array(z.string()).min(1), registries: z.array(registryArtifactRowSchema), }); export const registrySnapshotArtifactSchema = z.union([ successfulRegistrySnapshotArtifactSchema, failedRegistrySnapshotArtifactSchema, ]); export const registryGovernanceRunArtifactSchema = z.union([ registrySnapshotBaseArtifactSchema.extend({ failures: z.array(z.string()).max(0), registries: z.array(registryArtifactRowSchema).min(1), }), failedRegistrySnapshotArtifactSchema, ]); const outputDigestSchema = z .object({ path: nonEmptyString, bytes: z.int().nonnegative(), gzipBytes: z.int().nonnegative(), sha256, }) .strict(); export const bundlePerformanceArtifactSchema = z .object({ schemaVersion: z.literal(1), generatedAt: timestamp, context: z .object({ nodeVersion: nonEmptyString, packageManager: nonEmptyString, runnerImage: nonEmptyString, }) .strict(), outputs: z.array(outputDigestSchema).min(1), }) .strict(); const cyclonedxComponentSchema = z .object({ type: z.literal("library"), "bom-ref": nonEmptyString, name: nonEmptyString, version: nonEmptyString, scope: z.enum(["optional", "required"]), hashes: z.array( z.object({ alg: z.literal("SHA-512"), content: nonEmptyString }).strict(), ), licenses: z.array( z.object({ expression: nonEmptyString }).strict(), ), properties: z.array( z.object({ name: nonEmptyString, value: nonEmptyString }).strict(), ), }) .strict(); export const sbomArtifactSchema = z .object({ bomFormat: z.literal("CycloneDX"), specVersion: z.literal("1.6"), serialNumber: nonEmptyString, version: z.literal(1), metadata: z .object({ component: z .object({ type: z.literal("application"), name: nonEmptyString, version: nonEmptyString, }) .strict(), properties: z.array( z.object({ name: nonEmptyString, value: nonEmptyString }).strict(), ), }) .strict(), components: z.array(cyclonedxComponentSchema), dependencies: z.array( z .object({ ref: nonEmptyString, dependsOn: z.array(nonEmptyString) }) .strict(), ), }) .strict(); export const provenanceArtifactSchema = z .object({ _type: z.literal("https://in-toto.io/Statement/v1"), subject: z .array( z .object({ name: z.literal("dist"), digest: z.object({ sha256 }).strict(), }) .strict(), ) .length(1), predicateType: z.literal("https://slsa.dev/provenance/v1"), predicate: z .object({ buildDefinition: z .object({ buildType: nonEmptyString, externalParameters: jsonObject, internalParameters: jsonObject, resolvedDependencies: z.array( z .object({ uri: nonEmptyString, digest: z.object({ sha256 }).strict() }) .strict(), ), }) .strict(), runDetails: z .object({ builder: z.object({ id: nonEmptyString }).strict(), metadata: z.object({ invocationId: nonEmptyString }).strict(), }) .strict(), materials: z .object({ lockfileSha256: sha256, sourceSetSha256: sha256, sbomSha256: sha256 }) .strict(), }) .strict(), }) .strict(); export const dependencyDiffArtifactSchema = z .object({ schemaVersion: z.literal(2), baselineDigest: sha256.nullable(), currentDigest: sha256, ...dependencyDiffSchema.shape, highRisk: z.array(nonEmptyString), reviewFailures: z.array(z.string()), }) .strict(); export const licenseReportArtifactSchema = z .object({ schemaVersion: z.literal(1), status: z.enum(["PASS", "FAIL"]), dependencyCount: z.int().nonnegative(), results: z.array( z .object({ package: nonEmptyString, license: nonEmptyString, passed: z.boolean(), reason: z.string().nullable(), }) .strict(), ), failures: z.array(z.string()), }) .strict(); export const vulnerabilityReportArtifactSchema = z .object({ schemaVersion: z.literal(1), provider: nonEmptyString, scannedLockfileSha256: sha256, status: z.enum(["PASS", "FAIL", "FAIL_UNVERIFIED"]), findings: z.array(jsonObject), exceptionsApplied: z.array(jsonObject), failures: z.array(z.string()), blocking: z.array(z.string()), }) .strict(); export const fieldWebVitalsArtifactSchema = z .object({ schemaVersion: z.literal(1), generatedAt: timestamp, window: z .object({ days: z.literal(28), start: timestamp, end: timestamp }) .strict(), context: z .object({ source: nonEmptyString, sourceSystem: z.string().nullable(), exportId: z.string().nullable(), network: z.literal("production-real-user"), routeAggregation: z.literal("route-id-only"), releaseId: z.string().nullable(), privacyApprovalRef: z.string().nullable(), thresholdDecisionRef: z.string().nullable(), validationFailures: z.array(z.string()), }) .strict(), metrics: z .object({ p75LcpMs: z.number().finite().nonnegative().nullable(), p75Cls: z.number().finite().nonnegative().nullable(), p75InpMs: z.number().finite().nonnegative().nullable(), }) .strict(), thresholds: z .object({ p75LcpMs: z.number().finite().nonnegative(), p75Cls: z.number().finite().nonnegative(), p75InpMs: z.number().finite().nonnegative(), minimumEligibleSamples: z.int().positive().nullable(), }) .strict(), eligibility: z .object({ consentRequired: z.literal(true), totalSamples: z.int().nonnegative(), eligibleSamples: z.int().nonnegative(), minimumEligibleSamples: z.int().positive().nullable(), routeSamples: z.record(z.string(), z.int().nonnegative()), }) .strict(), status: z.enum(["PASS", "FAIL_THRESHOLD", "FAIL_UNVERIFIED"]), passed: z.boolean(), }) .strict(); export const labPerformanceArtifactSchema = z .object({ schemaVersion: z.literal(1), generatedAt: timestamp, context: jsonObject, metrics: jsonObject, thresholds: jsonObject, fixtures: z.array( z.object({ name: nonEmptyString, passed: z.boolean() }).strict(), ), passed: z.boolean(), }) .strict(); export const releaseVerificationArtifactSchema = z .object({ schemaVersion: z.literal(1), generatedAt: timestamp, artifact: z .object({ checked: z.boolean(), compatible: z.boolean(), mismatches: z.array(z.string()), releaseId: nonEmptyString, }) .strict(), fixtures: z.array( z .object({ name: nonEmptyString, expectedCompatible: z.boolean(), actualCompatible: z.boolean(), mismatches: z.array(z.string()), passed: z.boolean(), }) .strict(), ), passed: z.boolean(), }) .strict(); export const runbookRecordArtifactSchema = z .object({ schemaVersion: z.literal(1), runbookId: z.string().regex(/^FE-RB-00[1-5]$/u), releaseId: nonEmptyString, drillTimestamp: timestamp, triggerInjected: nonEmptyString, triggerAsserted: z.boolean(), containmentAsserted: z.boolean(), escalationPathAsserted: z.boolean(), recoveryAssertions: z.array( z .object({ assertion: nonEmptyString, evidence: nonEmptyString, passed: z.boolean(), }) .strict(), ), negativeFixtureFailedAsExpected: z.boolean(), windowObservedBucket: nonEmptyString, providerVerificationRequired: z.boolean(), passed: z.boolean(), }) .strict();