The provider sandbox never ran. bubblewrap 0.9.0 stops parsing an `--args` file at the first non-option and never hands the remainder back, so the command written into that file was silently dropped: bwrap printed its usage text, exited 1, and the provider produced no evidence at all. The options still travel in the args file — that is what keeps host paths and credentials out of `/proc/<pid>/cmdline` — but the command now rides on real argv, and `encodeProviderBwrapInput` refuses a `--` so the drop cannot come back. The scope wrapper then could not exit. It read the supervisor's liveness pipe through `fs`, which runs a blocking `read(2)` on a threadpool thread; the supervisor holds that pipe open for the scope's whole life, so the read never returned and closing the descriptor did not interrupt it. Once bubblewrap finished the wrapper deadlocked in `process.exit`, the scope outlived the provider, and a completed run was reported as a timeout kill. The channel is now read through the event loop, so teardown is observable and terminal. Creation modes were left to the ambient umask. `mkdir(mode)` and `open(mode)` are requests the kernel subtracts the umask from, so a runner exporting a restrictive umask produced directories it could not enter and handed `tar` a file it could not re-open. Private modes are pinned instead of inherited. Promotion cleanup deleted before it checked. Removals run through a pinned descriptor, so a leaf substituted after validation had this promotion's exact five destroyed first and the substitution reported afterwards, leaving a half-emptied directory a retry could not tell from a completed one. The name is re-bound to the inode before anything is removed, so the failure is total. Separately, release coherence proved the artifacts agreed with each other but never that they belonged where they were going: a build whose runtime document said `APP_ENV: local`, `AUTH_MODE: demo` and a loopback API is coherent with itself and passed every gate. `public/` is copied verbatim into `dist/`, so that local document shipped with every build regardless of what the build was for. Runtime configuration now comes from a declared profile, and FE-GATE-027 refuses to admit an artifact to an environment it does not match — including refusing an undeclared destination, so nothing is admitted by omission. `REQUEST_TIMEOUT_MS` and `VITE_ROUTER_BASE_PATH` were validated and then dropped: the V3 executor ran every operation on its contract's own deadline, and Vite emitted root-absolute assets for a sub-path deployment. The timeout is now a ceiling that may tighten a contract but never loosen one, and one base path feeds the router, the Service Worker scope and the asset base together. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1437 lines
47 KiB
TypeScript
1437 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();
|
|
|
|
/**
|
|
* FE-GATE-027. The record of which environment an artifact was admitted to, and
|
|
* every reason it was refused. Refusals are kept in the artifact so a rejected
|
|
* promotion leaves evidence rather than only a non-zero exit code.
|
|
*/
|
|
export const deploymentAdmissionArtifactSchema = z
|
|
.object({
|
|
schemaVersion: z.literal(1),
|
|
target: z.enum(["local", "development", "staging", "production"]),
|
|
appEnv: z.enum(["local", "development", "staging", "production"]),
|
|
authMode: z.enum(["external", "demo"]),
|
|
apiBaseUrl: nonEmptyString,
|
|
buildId: nonEmptyString.nullable(),
|
|
releaseId: nonEmptyString.nullable(),
|
|
status: z.enum(["ADMITTED", "REFUSED"]),
|
|
violations: z.array(
|
|
z.object({ field: nonEmptyString, reason: nonEmptyString }).strict(),
|
|
),
|
|
})
|
|
.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" });
|
|
}
|
|
});
|