1416 lines
47 KiB
TypeScript
1416 lines
47 KiB
TypeScript
import { z } from "zod";
|
|
|
|
export * from "../../src/contracts/release-artifacts.ts";
|
|
|
|
import { MANUAL_A11Y_ROUTE_IDS } from "../lib/manual-a11y-evidence.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(),
|
|
secretScan: z
|
|
.object({
|
|
policySha256: sha256,
|
|
sarifSha256: sha256,
|
|
scanInputSha256: 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();
|
|
|
|
const bundleOutputInventoryShape = {
|
|
schemaVersion: z.literal(1),
|
|
generatedAt: timestamp,
|
|
context: z
|
|
.object({
|
|
nodeVersion: nonEmptyString,
|
|
packageManager: nonEmptyString,
|
|
runnerImage: nonEmptyString,
|
|
})
|
|
.strict(),
|
|
outputs: z.array(outputDigestSchema).min(1),
|
|
} as const;
|
|
|
|
function addUniqueBundleOutputIssues(
|
|
artifact: Readonly<{ outputs: readonly Readonly<{ path: string }>[] }>,
|
|
context: z.RefinementCtx,
|
|
): void {
|
|
const paths = artifact.outputs.map(({ path }) => path);
|
|
if (new Set(paths).size !== paths.length) {
|
|
context.addIssue({
|
|
code: "custom",
|
|
path: ["outputs"],
|
|
message: "output paths must be unique",
|
|
});
|
|
}
|
|
}
|
|
|
|
export const bundleOutputInventoryArtifactSchema = z
|
|
.object(bundleOutputInventoryShape)
|
|
.strict()
|
|
.superRefine(addUniqueBundleOutputIssues);
|
|
|
|
const bundleMeasurementSchema = z
|
|
.object({ path: nonEmptyString, gzipBytes: z.int().nonnegative() })
|
|
.strict();
|
|
const bundleClassificationSchema = z
|
|
.object({
|
|
initialFiles: z.array(nonEmptyString),
|
|
lazyFiles: z.array(nonEmptyString),
|
|
missingImports: z.array(nonEmptyString),
|
|
})
|
|
.strict();
|
|
const bundleThresholdsSchema = z
|
|
.object({
|
|
initialJsGzipBytes: z.int().positive(),
|
|
lazyChunkGzipBytes: z.int().positive(),
|
|
})
|
|
.strict();
|
|
const bundleBudgetResultSchema = z
|
|
.object({
|
|
initialPassed: z.boolean(),
|
|
lazyResults: z.array(
|
|
bundleMeasurementSchema.extend({
|
|
threshold: z.int().positive(),
|
|
passed: z.boolean(),
|
|
}),
|
|
),
|
|
passed: z.boolean(),
|
|
})
|
|
.strict();
|
|
|
|
export const bundlePerformanceArtifactSchema = z
|
|
.object({
|
|
...bundleOutputInventoryShape,
|
|
measurements: z
|
|
.object({
|
|
initialJsGzipBytes: z.int().nonnegative(),
|
|
lazyChunks: z.array(bundleMeasurementSchema),
|
|
})
|
|
.strict(),
|
|
classification: bundleClassificationSchema,
|
|
missingOutputs: z.array(nonEmptyString),
|
|
thresholds: bundleThresholdsSchema,
|
|
results: bundleBudgetResultSchema,
|
|
fixtures: z.tuple([
|
|
z.object({ name: z.literal("initial-js-over-budget"), passed: z.boolean() }).strict(),
|
|
z.object({ name: z.literal("lazy-chunk-over-budget"), passed: z.boolean() }).strict(),
|
|
]),
|
|
passed: z.boolean(),
|
|
})
|
|
.strict()
|
|
.superRefine((artifact, context) => {
|
|
addUniqueBundleOutputIssues(artifact, context);
|
|
const issue = (path: PropertyKey[], message: string) =>
|
|
context.addIssue({ code: "custom", path, message });
|
|
const uniqueSorted = (values: readonly string[]) =>
|
|
new Set(values).size === values.length &&
|
|
JSON.stringify(values) === JSON.stringify([...values].sort());
|
|
for (const [field, values] of [
|
|
["initialFiles", artifact.classification.initialFiles],
|
|
["lazyFiles", artifact.classification.lazyFiles],
|
|
["missingImports", artifact.classification.missingImports],
|
|
["missingOutputs", artifact.missingOutputs],
|
|
] as const) {
|
|
if (!uniqueSorted(values)) {
|
|
issue(
|
|
field === "missingOutputs" ? [field] : ["classification", field],
|
|
"paths must be unique and sorted",
|
|
);
|
|
}
|
|
}
|
|
const initial = new Set(artifact.classification.initialFiles);
|
|
if (artifact.classification.lazyFiles.some((file) => initial.has(file))) {
|
|
issue(["classification"], "initial and lazy files must be disjoint");
|
|
}
|
|
const outputs = new Map(
|
|
artifact.outputs.map((output) => [output.path.replace(/^dist\//u, ""), output]),
|
|
);
|
|
const expectedMissing = [
|
|
...artifact.classification.initialFiles,
|
|
...artifact.classification.lazyFiles,
|
|
].filter((file) => !outputs.has(file)).sort();
|
|
if (JSON.stringify(artifact.missingOutputs) !== JSON.stringify(expectedMissing)) {
|
|
issue(["missingOutputs"], "must equal classified JavaScript outputs not found in inventory");
|
|
}
|
|
const expectedInitialBytes = artifact.classification.initialFiles.reduce(
|
|
(total, file) => total + (outputs.get(file)?.gzipBytes ?? 0),
|
|
0,
|
|
);
|
|
if (artifact.measurements.initialJsGzipBytes !== expectedInitialBytes) {
|
|
issue(["measurements", "initialJsGzipBytes"], "must equal classified initial output bytes");
|
|
}
|
|
const expectedLazyChunks = artifact.classification.lazyFiles.map((file) => ({
|
|
path: file,
|
|
gzipBytes: outputs.get(file)?.gzipBytes ?? 0,
|
|
}));
|
|
if (JSON.stringify(artifact.measurements.lazyChunks) !== JSON.stringify(expectedLazyChunks)) {
|
|
issue(["measurements", "lazyChunks"], "must equal classified lazy output bytes");
|
|
}
|
|
const expectedInitialPassed =
|
|
artifact.measurements.initialJsGzipBytes <= artifact.thresholds.initialJsGzipBytes;
|
|
if (artifact.results.initialPassed !== expectedInitialPassed) {
|
|
issue(["results", "initialPassed"], "must agree with initial threshold");
|
|
}
|
|
const expectedLazyResults = artifact.measurements.lazyChunks.map((chunk) => ({
|
|
...chunk,
|
|
threshold: artifact.thresholds.lazyChunkGzipBytes,
|
|
passed: chunk.gzipBytes <= artifact.thresholds.lazyChunkGzipBytes,
|
|
}));
|
|
if (JSON.stringify(artifact.results.lazyResults) !== JSON.stringify(expectedLazyResults)) {
|
|
issue(["results", "lazyResults"], "must agree with lazy measurements and threshold");
|
|
}
|
|
const expectedBudgetPassed =
|
|
expectedInitialPassed && expectedLazyResults.every(({ passed }) => passed);
|
|
if (artifact.results.passed !== expectedBudgetPassed) {
|
|
issue(["results", "passed"], "must agree with budget results");
|
|
}
|
|
const expectedPassed =
|
|
expectedBudgetPassed &&
|
|
artifact.fixtures.every(({ passed }) => passed) &&
|
|
artifact.classification.missingImports.length === 0 &&
|
|
artifact.missingOutputs.length === 0;
|
|
if (artifact.passed !== expectedPassed) {
|
|
issue(["passed"], "must agree with budgets, fixtures, and manifest integrity");
|
|
}
|
|
});
|
|
|
|
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();
|
|
|
|
const failureList = z.array(nonEmptyString).max(4_096);
|
|
const sourceOrFixtureMode = z.enum(["source", "negative-fixture"]);
|
|
const namedBooleanResultSchema = z
|
|
.object({ id: nonEmptyString, passed: z.boolean() })
|
|
.strict();
|
|
|
|
function addPassedFailureInvariant(
|
|
artifact: Readonly<{ passed: boolean; failures: readonly string[] }>,
|
|
context: z.RefinementCtx,
|
|
): void {
|
|
if (artifact.passed !== (artifact.failures.length === 0)) {
|
|
context.addIssue({
|
|
code: "custom",
|
|
path: ["passed"],
|
|
message: "passed must agree with failures",
|
|
});
|
|
}
|
|
}
|
|
|
|
function addUniqueStringIssues(
|
|
values: readonly string[],
|
|
path: PropertyKey[],
|
|
context: z.RefinementCtx,
|
|
): void {
|
|
if (new Set(values).size !== values.length) {
|
|
context.addIssue({ code: "custom", path, message: "must not contain duplicates" });
|
|
}
|
|
}
|
|
|
|
export const automatedA11yArtifactSchema = z
|
|
.object({
|
|
schemaVersion: z.literal(1),
|
|
generatedAt: timestamp,
|
|
scope: z.array(nonEmptyString).min(1).max(128),
|
|
threshold: z.object({ critical: z.literal(0), serious: z.literal(0) }).strict(),
|
|
automatedStatus: z.literal("passed"),
|
|
manualReview: z.literal("see artifacts/tests/a11y-manual/report.json"),
|
|
})
|
|
.strict()
|
|
.superRefine((artifact, context) => {
|
|
addUniqueStringIssues(artifact.scope, ["scope"], context);
|
|
if (JSON.stringify(artifact.scope) !== JSON.stringify(MANUAL_A11Y_ROUTE_IDS)) {
|
|
context.addIssue({ code: "custom", path: ["scope"], message: "must match the installed route registry" });
|
|
}
|
|
});
|
|
|
|
const manualA11yResultSchema = z
|
|
.object({
|
|
routeId: nonEmptyString,
|
|
path: nonEmptyString,
|
|
reviewer: z.string().nullable(),
|
|
reviewedAt: z.string().nullable(),
|
|
releaseId: z.string().nullable(),
|
|
failures: failureList,
|
|
passed: z.boolean(),
|
|
})
|
|
.strict()
|
|
.superRefine((result, context) => {
|
|
if (result.path !== `artifacts/tests/a11y-manual/${result.routeId}.md`) {
|
|
context.addIssue({ code: "custom", path: ["path"], message: "path must match routeId" });
|
|
}
|
|
const hasIdentity = Boolean(
|
|
result.reviewer &&
|
|
result.releaseId &&
|
|
result.reviewedAt &&
|
|
Number.isFinite(Date.parse(result.reviewedAt)),
|
|
);
|
|
if (result.passed !== (result.failures.length === 0 && hasIdentity)) {
|
|
context.addIssue({
|
|
code: "custom",
|
|
path: ["passed"],
|
|
message: "passed must agree with failures and review identity",
|
|
});
|
|
}
|
|
});
|
|
|
|
export const manualA11yReportArtifactSchema = z
|
|
.object({
|
|
schemaVersion: z.literal(1),
|
|
generatedAt: timestamp,
|
|
scope: z.array(nonEmptyString).min(1).max(128),
|
|
results: z.array(manualA11yResultSchema).min(1).max(128),
|
|
coherentRelease: z.boolean(),
|
|
passed: z.boolean(),
|
|
})
|
|
.strict()
|
|
.superRefine((artifact, context) => {
|
|
const routeIds = artifact.results.map(({ routeId }) => routeId);
|
|
addUniqueStringIssues(artifact.scope, ["scope"], context);
|
|
addUniqueStringIssues(routeIds, ["results"], context);
|
|
if (JSON.stringify(artifact.scope) !== JSON.stringify(MANUAL_A11Y_ROUTE_IDS)) {
|
|
context.addIssue({ code: "custom", path: ["scope"], message: "must match the installed route registry" });
|
|
}
|
|
if (JSON.stringify(routeIds) !== JSON.stringify(artifact.scope)) {
|
|
context.addIssue({ code: "custom", path: ["results"], message: "result routeIds must match scope" });
|
|
}
|
|
const releaseIds = artifact.results.map(({ releaseId }) => releaseId);
|
|
const coherentRelease =
|
|
releaseIds.every((releaseId): releaseId is string => Boolean(releaseId)) &&
|
|
new Set(releaseIds).size === 1;
|
|
if (artifact.coherentRelease !== coherentRelease) {
|
|
context.addIssue({ code: "custom", path: ["coherentRelease"], message: "must represent one non-empty releaseId" });
|
|
}
|
|
if (
|
|
artifact.passed !==
|
|
(coherentRelease && artifact.results.every(({ passed }) => passed))
|
|
) {
|
|
context.addIssue({ code: "custom", path: ["passed"], message: "must agree with route results" });
|
|
}
|
|
});
|
|
|
|
const architectureDependencySchema = z
|
|
.object({
|
|
source: nonEmptyString,
|
|
target: nonEmptyString,
|
|
specifier: nonEmptyString,
|
|
kind: z.enum(["local", "external"]),
|
|
})
|
|
.strict();
|
|
const architectureUnresolvedSchema = z
|
|
.object({ source: nonEmptyString, specifier: nonEmptyString, reason: nonEmptyString })
|
|
.strict();
|
|
const architectureViolationSchema = z
|
|
.object({
|
|
rule: nonEmptyString,
|
|
severity: nonEmptyString,
|
|
source: nonEmptyString,
|
|
target: nonEmptyString,
|
|
cycle: z.array(nonEmptyString).optional(),
|
|
})
|
|
.strict();
|
|
const staticImportGraphSchema = z
|
|
.object({
|
|
analyzer: z.literal("babel-parser-node-resolver"),
|
|
modules: z.array(nonEmptyString),
|
|
dependencies: z.array(architectureDependencySchema),
|
|
unresolved: z.array(architectureUnresolvedSchema),
|
|
parseFailures: z.array(
|
|
z.object({ source: nonEmptyString, reason: nonEmptyString }).strict(),
|
|
),
|
|
cycles: z.array(z.array(nonEmptyString).min(1)),
|
|
violations: z.array(architectureViolationSchema),
|
|
summary: z
|
|
.object({
|
|
modules: z.int().nonnegative(),
|
|
typescriptModules: z.int().nonnegative(),
|
|
dependencies: z.int().nonnegative(),
|
|
localDependencies: z.int().nonnegative(),
|
|
unresolved: z.int().nonnegative(),
|
|
parseFailures: z.int().nonnegative(),
|
|
cycles: z.int().nonnegative(),
|
|
errors: z.int().nonnegative(),
|
|
typeScriptOnlyPolicyPassed: z.boolean(),
|
|
nonTypeScriptExecutableSources: z.int().nonnegative(),
|
|
})
|
|
.strict(),
|
|
fixtureChecks: z
|
|
.object({ passed: z.boolean(), checks: z.array(nonEmptyString), failures: failureList })
|
|
.strict(),
|
|
typeScriptOnlySourcePolicy: z
|
|
.object({
|
|
checkedRoots: z.array(nonEmptyString).min(1),
|
|
exceptionsAllowed: z.literal(false),
|
|
violations: z.array(nonEmptyString),
|
|
passed: z.boolean(),
|
|
})
|
|
.strict(),
|
|
})
|
|
.strict()
|
|
.superRefine((graph, context) => {
|
|
const counts = [
|
|
["modules", graph.modules.length],
|
|
["dependencies", graph.dependencies.length],
|
|
["localDependencies", graph.dependencies.filter(({ kind }) => kind === "local").length],
|
|
["unresolved", graph.unresolved.length],
|
|
["parseFailures", graph.parseFailures.length],
|
|
["cycles", graph.cycles.length],
|
|
["errors", graph.violations.filter(({ severity }) => severity === "error").length],
|
|
["nonTypeScriptExecutableSources", graph.typeScriptOnlySourcePolicy.violations.length],
|
|
] as const;
|
|
for (const [field, expected] of counts) {
|
|
if (graph.summary[field] !== expected) {
|
|
context.addIssue({ code: "custom", path: ["summary", field], message: "count does not match evidence rows" });
|
|
}
|
|
}
|
|
if (graph.summary.typescriptModules > graph.summary.modules) {
|
|
context.addIssue({ code: "custom", path: ["summary", "typescriptModules"], message: "cannot exceed modules" });
|
|
}
|
|
if (graph.fixtureChecks.passed !== (graph.fixtureChecks.failures.length === 0)) {
|
|
context.addIssue({ code: "custom", path: ["fixtureChecks", "passed"], message: "must agree with failures" });
|
|
}
|
|
if (
|
|
graph.typeScriptOnlySourcePolicy.passed !==
|
|
(graph.typeScriptOnlySourcePolicy.violations.length === 0) ||
|
|
graph.summary.typeScriptOnlyPolicyPassed !== graph.typeScriptOnlySourcePolicy.passed
|
|
) {
|
|
context.addIssue({ code: "custom", path: ["typeScriptOnlySourcePolicy", "passed"], message: "must agree with violations and summary" });
|
|
}
|
|
});
|
|
const dependencyCruiserSummarySchema = z
|
|
.object({
|
|
violations: z.array(jsonObject),
|
|
error: z.int().nonnegative(),
|
|
warn: z.int().nonnegative(),
|
|
info: z.int().nonnegative(),
|
|
ignore: z.int().nonnegative(),
|
|
totalCruised: z.int().nonnegative(),
|
|
totalDependenciesCruised: z.int().nonnegative(),
|
|
})
|
|
.catchall(z.json());
|
|
export const architectureDependencyReportArtifactSchema = z.union([
|
|
z
|
|
.object({
|
|
modules: z.array(jsonObject),
|
|
summary: dependencyCruiserSummarySchema,
|
|
staticImportGraph: staticImportGraphSchema,
|
|
})
|
|
.strict(),
|
|
z
|
|
.object({
|
|
summary: z.object({ errors: z.literal(1) }).strict(),
|
|
dependencyCruiserOutput: z.string(),
|
|
staticImportGraph: staticImportGraphSchema,
|
|
})
|
|
.strict(),
|
|
]);
|
|
|
|
export const designSystemReportArtifactSchema = z
|
|
.object({
|
|
schemaVersion: z.literal(1),
|
|
mode: sourceOrFixtureMode,
|
|
checkedTokenCount: z.int().positive(),
|
|
failures: failureList,
|
|
passed: z.boolean(),
|
|
})
|
|
.strict()
|
|
.superRefine(addPassedFailureInvariant);
|
|
|
|
export const i18nReportArtifactSchema = z
|
|
.object({
|
|
schemaVersion: z.literal(1),
|
|
mode: sourceOrFixtureMode,
|
|
localeCount: z.int().positive(),
|
|
messageKeyCount: z.int().positive(),
|
|
checkedFiles: z.int().nonnegative(),
|
|
failures: failureList,
|
|
passed: z.boolean(),
|
|
})
|
|
.strict()
|
|
.superRefine(addPassedFailureInvariant);
|
|
|
|
export const diagnosticsReportArtifactSchema = z
|
|
.object({
|
|
schemaVersion: z.literal(1),
|
|
mode: sourceOrFixtureMode,
|
|
telemetryEventCount: z.int().positive(),
|
|
diagnosticEventCount: z.int().positive(),
|
|
checkedFiles: z.int().nonnegative(),
|
|
failures: failureList,
|
|
passed: z.boolean(),
|
|
})
|
|
.strict()
|
|
.superRefine(addPassedFailureInvariant);
|
|
|
|
export const realtimeBoundariesArtifactSchema = z
|
|
.object({
|
|
schemaVersion: z.literal(1),
|
|
sourceRoot: nonEmptyString,
|
|
violations: z.array(
|
|
z
|
|
.object({
|
|
ruleId: z.enum([
|
|
"NATIVE_REALTIME_API_OUTSIDE_ADAPTER",
|
|
"PRESENTATION_INTERVAL_OWNER",
|
|
"UNSELECTED_REALTIME_RUNTIME_COMPOSED",
|
|
]),
|
|
file: nonEmptyString,
|
|
line: z.int().positive(),
|
|
})
|
|
.strict(),
|
|
),
|
|
passed: z.boolean(),
|
|
})
|
|
.strict()
|
|
.superRefine((artifact, context) => {
|
|
if (artifact.passed !== (artifact.violations.length === 0)) {
|
|
context.addIssue({ code: "custom", path: ["passed"], message: "must agree with violations" });
|
|
}
|
|
const keys = artifact.violations.map(({ ruleId, file, line }) => `${file}\0${line}\0${ruleId}`);
|
|
addUniqueStringIssues(keys, ["violations"], context);
|
|
});
|
|
|
|
const optionalRecipeBundleOutputSchema = z
|
|
.object({
|
|
fileName: nonEmptyString,
|
|
bytes: z.int().nonnegative(),
|
|
gzipBytes: z.int().nonnegative(),
|
|
sha256,
|
|
})
|
|
.strict();
|
|
const optionalRecipeBundleMeasurementSchema = z
|
|
.object({
|
|
recipeId: nonEmptyString,
|
|
sourceRoots: z.array(nonEmptyString).min(1),
|
|
sourceFileCount: z.int().positive(),
|
|
toolchain: z
|
|
.object({
|
|
bundler: z.literal("vite"),
|
|
viteVersion: nonEmptyString,
|
|
mode: z.literal("production"),
|
|
target: z.literal("es2022"),
|
|
format: z.literal("es"),
|
|
minifier: z.literal("esbuild"),
|
|
treeshake: z.literal(false),
|
|
compression: z.literal("node-zlib-gzip"),
|
|
})
|
|
.strict(),
|
|
outputs: z.array(optionalRecipeBundleOutputSchema).min(1),
|
|
bytes: z.int().nonnegative(),
|
|
gzipBytes: z.int().nonnegative(),
|
|
bundleBudgetGzipBytes: z.int().positive(),
|
|
remainingGzipBytes: z.int(),
|
|
sha256,
|
|
passed: z.boolean(),
|
|
})
|
|
.strict()
|
|
.superRefine((measurement, context) => {
|
|
if (measurement.bytes !== measurement.outputs.reduce((total, output) => total + output.bytes, 0)) {
|
|
context.addIssue({ code: "custom", path: ["bytes"], message: "must equal output bytes" });
|
|
}
|
|
if (measurement.gzipBytes !== measurement.outputs.reduce((total, output) => total + output.gzipBytes, 0)) {
|
|
context.addIssue({ code: "custom", path: ["gzipBytes"], message: "must equal output gzip bytes" });
|
|
}
|
|
if (measurement.remainingGzipBytes !== measurement.bundleBudgetGzipBytes - measurement.gzipBytes) {
|
|
context.addIssue({ code: "custom", path: ["remainingGzipBytes"], message: "must equal budget minus gzip bytes" });
|
|
}
|
|
if (measurement.passed !== (measurement.gzipBytes <= measurement.bundleBudgetGzipBytes)) {
|
|
context.addIssue({ code: "custom", path: ["passed"], message: "must agree with bundle budget" });
|
|
}
|
|
});
|
|
const optionalRecipeReferenceRuntimeSchema = z
|
|
.object({
|
|
status: z.literal("AVAILABLE_NOT_COMPOSED"),
|
|
coveredCapabilities: z.array(nonEmptyString).min(1),
|
|
sourceRoots: z.array(nonEmptyString).min(1),
|
|
conformanceScripts: z.array(nonEmptyString).min(1),
|
|
productionComposition: z.literal(false),
|
|
})
|
|
.strict();
|
|
const optionalRecipeViolationSchema = z
|
|
.object({ ruleId: nonEmptyString, path: nonEmptyString, detail: nonEmptyString.optional() })
|
|
.strict();
|
|
export const optionalRecipesArtifactSchema = z
|
|
.object({
|
|
schemaVersion: z.literal(1),
|
|
decisionId: z.literal("VD-10"),
|
|
selectedCapabilities: z.array(nonEmptyString).max(0),
|
|
referenceRuntimes: z.array(
|
|
z.object({ id: nonEmptyString, referenceRuntime: optionalRecipeReferenceRuntimeSchema }).strict(),
|
|
).min(1),
|
|
recipeCount: z.int().nonnegative(),
|
|
productionRuntimeDependencies: z.array(nonEmptyString).nullable(),
|
|
referenceRuntimeBundleBudgets: z.array(optionalRecipeBundleMeasurementSchema).min(1),
|
|
bundleStatus: z.enum(["PASS", "FAIL", "NOT_BUILT"]),
|
|
violations: z.array(optionalRecipeViolationSchema),
|
|
passed: z.boolean(),
|
|
})
|
|
.strict()
|
|
.superRefine((artifact, context) => {
|
|
if (artifact.recipeCount < artifact.referenceRuntimes.length) {
|
|
context.addIssue({ code: "custom", path: ["recipeCount"], message: "cannot be smaller than reference runtimes" });
|
|
}
|
|
if (artifact.passed !== (artifact.violations.length === 0)) {
|
|
context.addIssue({ code: "custom", path: ["passed"], message: "must agree with violations" });
|
|
}
|
|
const runtimeIds = artifact.referenceRuntimes.map(({ id }) => id).sort();
|
|
const budgetIds = artifact.referenceRuntimeBundleBudgets.map(({ recipeId }) => recipeId).sort();
|
|
addUniqueStringIssues(runtimeIds, ["referenceRuntimes"], context);
|
|
addUniqueStringIssues(budgetIds, ["referenceRuntimeBundleBudgets"], context);
|
|
if (JSON.stringify(runtimeIds) !== JSON.stringify(budgetIds)) {
|
|
context.addIssue({ code: "custom", path: ["referenceRuntimeBundleBudgets"], message: "must cover every reference runtime" });
|
|
}
|
|
});
|
|
|
|
const OPTIONAL_RECIPE_FIXTURE_IDS = [
|
|
"cleanup-omission",
|
|
"unselected-runtime-dependency",
|
|
"server-state-policy",
|
|
"vendor-direct-import",
|
|
"credential-leak",
|
|
"server-state-source-duplication",
|
|
"production-imports-recipe",
|
|
"reference-runtime-not-composed",
|
|
"reference-runtime-not-bundled",
|
|
"reference-runtime-module-not-bundled",
|
|
"reference-runtime-bundle-over-budget",
|
|
] as const;
|
|
const OPTIONAL_RECIPE_BUDGET_FIXTURE_IDS = [
|
|
"file-transfer",
|
|
"offline-indexeddb",
|
|
"realtime",
|
|
"service-worker-pwa",
|
|
] as const;
|
|
export const optionalRecipeFixturesArtifactSchema = z
|
|
.object({
|
|
schemaVersion: z.literal(1),
|
|
results: z.array(
|
|
namedBooleanResultSchema.extend({ id: z.enum(OPTIONAL_RECIPE_FIXTURE_IDS) }),
|
|
).length(OPTIONAL_RECIPE_FIXTURE_IDS.length),
|
|
bundleBudgetFixtures: z.array(
|
|
z
|
|
.object({
|
|
recipeId: z.enum(OPTIONAL_RECIPE_BUDGET_FIXTURE_IDS),
|
|
gzipBytes: z.int().nonnegative(),
|
|
fixtureBudgetGzipBytes: z.int().positive(),
|
|
rejected: z.boolean(),
|
|
})
|
|
.strict(),
|
|
).length(OPTIONAL_RECIPE_BUDGET_FIXTURE_IDS.length),
|
|
passed: z.boolean(),
|
|
})
|
|
.strict()
|
|
.superRefine((artifact, context) => {
|
|
addUniqueStringIssues(artifact.results.map(({ id }) => id), ["results"], context);
|
|
addUniqueStringIssues(artifact.bundleBudgetFixtures.map(({ recipeId }) => recipeId), ["bundleBudgetFixtures"], context);
|
|
if (artifact.passed !== artifact.results.every(({ passed }) => passed)) {
|
|
context.addIssue({ code: "custom", path: ["passed"], message: "must agree with fixture results" });
|
|
}
|
|
artifact.bundleBudgetFixtures.forEach((fixture, index) => {
|
|
if (fixture.rejected !== (fixture.gzipBytes > fixture.fixtureBudgetGzipBytes)) {
|
|
context.addIssue({ code: "custom", path: ["bundleBudgetFixtures", index, "rejected"], message: "must agree with fixture budget" });
|
|
}
|
|
});
|
|
});
|
|
|
|
const registryCompatibilityValueSchema = z.union([
|
|
z.enum(["none", "additive", "behavior-change", "breaking"]),
|
|
z.boolean(),
|
|
]);
|
|
const REGISTRY_COMPATIBILITY_FIXTURE_IDS = [
|
|
"ordering-only",
|
|
"row-addition",
|
|
"behavior-change",
|
|
"row-removal",
|
|
"field-type-narrowing",
|
|
"route-path-change",
|
|
"registry-contract-narrowing",
|
|
"breaking-evidence-required",
|
|
"tampered-baseline-digest",
|
|
] as const;
|
|
export const registryCompatibilityFixturesArtifactSchema = z
|
|
.object({
|
|
schemaVersion: z.literal(1),
|
|
results: z.array(
|
|
z
|
|
.object({
|
|
id: z.enum(REGISTRY_COMPATIBILITY_FIXTURE_IDS),
|
|
expected: registryCompatibilityValueSchema,
|
|
actual: registryCompatibilityValueSchema,
|
|
passed: z.boolean(),
|
|
})
|
|
.strict(),
|
|
).length(REGISTRY_COMPATIBILITY_FIXTURE_IDS.length),
|
|
})
|
|
.strict()
|
|
.superRefine((artifact, context) => {
|
|
addUniqueStringIssues(artifact.results.map(({ id }) => id), ["results"], context);
|
|
artifact.results.forEach((result, index) => {
|
|
if (result.passed !== (result.actual === result.expected)) {
|
|
context.addIssue({ code: "custom", path: ["results", index, "passed"], message: "must agree with expected and actual" });
|
|
}
|
|
});
|
|
});
|
|
|
|
const buildDigestSchema = z.union([sha256, z.literal("BUILD_FAILED")]);
|
|
export const reproducibleBuildArtifactSchema = z
|
|
.object({
|
|
schemaVersion: z.literal(1),
|
|
sourceDateEpoch: z.string().regex(/^\d+$/u),
|
|
buildId: nonEmptyString,
|
|
commitSha: nonEmptyString,
|
|
releaseId: nonEmptyString,
|
|
runnerImage: nonEmptyString,
|
|
firstDigest: buildDigestSchema,
|
|
secondDigest: buildDigestSchema,
|
|
restored: z.boolean(),
|
|
status: z.enum(["PASS", "FAIL"]),
|
|
})
|
|
.strict()
|
|
.superRefine((artifact, context) => {
|
|
const passed =
|
|
artifact.restored &&
|
|
artifact.firstDigest !== "BUILD_FAILED" &&
|
|
artifact.firstDigest === artifact.secondDigest;
|
|
if ((artifact.status === "PASS") !== passed) {
|
|
context.addIssue({ code: "custom", path: ["status"], message: "must agree with build digests and restoration" });
|
|
}
|
|
});
|
|
|
|
const SUPPLY_CHAIN_FIXTURE_IDS = [
|
|
"transitive-removal-is-real-diff",
|
|
"tampered-integrity-rejected",
|
|
"high-risk-self-approval-rejected",
|
|
"denied-license-rejected",
|
|
"critical-vulnerability-expired-exception-rejected",
|
|
"sbom-provenance-mismatch-rejected",
|
|
"dependency-ordering-deterministic",
|
|
"baseline-digest-tamper-rejected",
|
|
"vulnerability-provider-evidence-invalid",
|
|
] as const;
|
|
export const supplyChainFixturesArtifactSchema = z
|
|
.object({
|
|
schemaVersion: z.literal(1),
|
|
results: z.array(
|
|
namedBooleanResultSchema.extend({ id: z.enum(SUPPLY_CHAIN_FIXTURE_IDS) }),
|
|
).length(SUPPLY_CHAIN_FIXTURE_IDS.length),
|
|
})
|
|
.strict()
|
|
.superRefine((artifact, context) =>
|
|
addUniqueStringIssues(artifact.results.map(({ id }) => id), ["results"], context)
|
|
);
|
|
|
|
const providerFixtureResultSchema = z
|
|
.object({ status: z.enum(["PASS", "FAIL_UNVERIFIED"]), failures: failureList })
|
|
.strict()
|
|
.superRefine((result, context) => {
|
|
if ((result.status === "PASS") !== (result.failures.length === 0)) {
|
|
context.addIssue({ code: "custom", path: ["status"], message: "must agree with failures" });
|
|
}
|
|
});
|
|
export const supplyChainProviderFixturesArtifactSchema = z
|
|
.object({
|
|
schemaVersion: z.literal(1),
|
|
actualDefaultVerifier: providerFixtureResultSchema,
|
|
fixtures: z
|
|
.object({
|
|
absent: providerFixtureResultSchema,
|
|
validImmutable: providerFixtureResultSchema,
|
|
wrongDigest: providerFixtureResultSchema,
|
|
invalidTar: providerFixtureResultSchema,
|
|
})
|
|
.strict(),
|
|
externalTreeCanary: providerFixtureResultSchema,
|
|
passingFixtureCount: z.int().nonnegative(),
|
|
status: z.enum(["PASS", "FAIL"]),
|
|
})
|
|
.strict()
|
|
.superRefine((artifact, context) => {
|
|
const expectedPass =
|
|
artifact.actualDefaultVerifier.status === "PASS" &&
|
|
artifact.fixtures.validImmutable.status === "PASS" &&
|
|
artifact.externalTreeCanary.status === "PASS" &&
|
|
[artifact.fixtures.absent, artifact.fixtures.wrongDigest, artifact.fixtures.invalidTar]
|
|
.every(({ status }) => status === "FAIL_UNVERIFIED");
|
|
if (artifact.passingFixtureCount !== (artifact.fixtures.validImmutable.status === "PASS" ? 1 : 0)) {
|
|
context.addIssue({ code: "custom", path: ["passingFixtureCount"], message: "must count the passing immutable fixture" });
|
|
}
|
|
if ((artifact.status === "PASS") !== expectedPass) {
|
|
context.addIssue({ code: "custom", path: ["status"], message: "must agree with required fixture outcomes" });
|
|
}
|
|
});
|
|
|
|
const compatibilityClassificationSchema = z.enum(["additive", "breaking"]);
|
|
export const compatibilityFixturesArtifactSchema = z
|
|
.object({
|
|
schemaVersion: z.literal(1),
|
|
generatedAt: timestamp,
|
|
rules: z.array(nonEmptyString).length(5),
|
|
results: z.array(
|
|
z
|
|
.object({
|
|
family: z.enum(["api", "config", "storage", "release"]),
|
|
expected: compatibilityClassificationSchema,
|
|
actual: compatibilityClassificationSchema,
|
|
passed: z.boolean(),
|
|
})
|
|
.strict(),
|
|
).length(8),
|
|
})
|
|
.strict()
|
|
.superRefine((artifact, context) => {
|
|
const keys = artifact.results.map(({ family, expected }) => `${family}\0${expected}`);
|
|
addUniqueStringIssues(keys, ["results"], context);
|
|
artifact.results.forEach((result, index) => {
|
|
if (result.passed !== (result.actual === result.expected)) {
|
|
context.addIssue({ code: "custom", path: ["results", index, "passed"], message: "must agree with expected and actual" });
|
|
}
|
|
});
|
|
});
|
|
|
|
export const documentationReviewArtifactSchema = z
|
|
.object({
|
|
schemaVersion: z.literal(1),
|
|
generatedAt: timestamp,
|
|
status: z.literal("PASS_SCOPED"),
|
|
reviewer: z.literal("wiki-diagram-reviewer"),
|
|
standard: z.literal("rules/diagram-standards.md v2"),
|
|
evidenceReport: z
|
|
.object({ repoPath: nonEmptyString, canonicalPath: nonEmptyString, canonicalSha256: sha256 })
|
|
.strict(),
|
|
reportDigestValid: z.boolean(),
|
|
results: z.array(
|
|
z
|
|
.object({
|
|
diagram: z.enum(["overview", "staticDelivery"]),
|
|
sourcePath: nonEmptyString,
|
|
sha256,
|
|
sourceReferenced: z.boolean(),
|
|
digestReferenced: z.boolean(),
|
|
reviewer: z.literal("wiki-diagram-reviewer"),
|
|
score: z.number().min(0).max(100),
|
|
scorePass: z.boolean(),
|
|
passed: z.boolean(),
|
|
})
|
|
.strict(),
|
|
).length(2),
|
|
passed: z.boolean(),
|
|
})
|
|
.strict()
|
|
.superRefine((artifact, context) => {
|
|
addUniqueStringIssues(artifact.results.map(({ diagram }) => diagram), ["results"], context);
|
|
artifact.results.forEach((result, index) => {
|
|
const passed = result.sourceReferenced && result.digestReferenced && result.scorePass;
|
|
if (result.passed !== passed) {
|
|
context.addIssue({ code: "custom", path: ["results", index, "passed"], message: "must agree with review evidence" });
|
|
}
|
|
});
|
|
if (artifact.passed !== (artifact.reportDigestValid && artifact.results.every(({ passed }) => passed))) {
|
|
context.addIssue({ code: "custom", path: ["passed"], message: "must agree with report digest and review results" });
|
|
}
|
|
});
|
|
|
|
export const hostingHeadersArtifactSchema = z
|
|
.object({
|
|
schemaVersion: z.literal(1),
|
|
generatedAt: timestamp,
|
|
mode: z.enum(["live", "invalid-live", "fixture"]),
|
|
baseUrl: z.string().nullable(),
|
|
providerVerificationRequired: z.boolean(),
|
|
results: z.array(
|
|
z
|
|
.object({
|
|
surface: nonEmptyString,
|
|
header: nonEmptyString,
|
|
expected: z.json(),
|
|
observed: z.json().optional(),
|
|
reason: nonEmptyString.optional(),
|
|
passed: z.boolean(),
|
|
})
|
|
.strict(),
|
|
).min(1),
|
|
passed: z.boolean(),
|
|
})
|
|
.strict()
|
|
.superRefine((artifact, context) => {
|
|
const keys = artifact.results.map(({ surface, header }) => `${surface}\0${header}`);
|
|
addUniqueStringIssues(keys, ["results"], context);
|
|
const requiredKeys = [
|
|
...["index", "runtimeConfig", "releaseManifest"].flatMap((surface) =>
|
|
[
|
|
"cache-control",
|
|
"content-type",
|
|
"content-security-policy",
|
|
"strict-transport-security",
|
|
"x-frame-options",
|
|
"referrer-policy",
|
|
"x-content-type-options",
|
|
"permissions-policy",
|
|
].map((header) => `${surface}\0${header}`)
|
|
),
|
|
"hashedAsset\0cache-control",
|
|
"hashedAsset\0content-type",
|
|
"sourceMap\0public",
|
|
"serviceWorker\0enabled",
|
|
];
|
|
for (const requiredKey of requiredKeys) {
|
|
if (!keys.includes(requiredKey)) {
|
|
context.addIssue({ code: "custom", path: ["results"], message: `missing required probe: ${requiredKey}` });
|
|
}
|
|
}
|
|
if (artifact.providerVerificationRequired !== (artifact.mode !== "live")) {
|
|
context.addIssue({ code: "custom", path: ["providerVerificationRequired"], message: "must agree with hosting mode" });
|
|
}
|
|
if ((artifact.mode === "live") !== (artifact.baseUrl !== null)) {
|
|
context.addIssue({ code: "custom", path: ["baseUrl"], message: "must be present only for live mode" });
|
|
}
|
|
if (artifact.passed !== artifact.results.every(({ passed }) => passed)) {
|
|
context.addIssue({ code: "custom", path: ["passed"], message: "must agree with probe results" });
|
|
}
|
|
});
|