Files
clean-architecture-frontend…/scripts/contracts/release-artifacts.ts
T

426 lines
11 KiB
TypeScript

import { z } from "zod";
export * from "../../src/contracts/release-artifacts.ts";
const nonEmptyString = z.string().min(1);
const timestamp = z.iso.datetime();
const sha256 = z.string().regex(/^[a-f0-9]{64}$/u);
const jsonObject = z.record(z.string(), z.json());
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().nonnegative(),
directDependencyCount: z.int().nonnegative(),
dependencies: z.array(dependencyInventoryRowSchema),
})
.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();
export const registrySnapshotArtifactSchema = 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(),
failures: z.array(z.string()),
registries: z.array(registryArtifactRowSchema),
})
.strict();
const outputDigestSchema = z
.object({
path: nonEmptyString,
bytes: z.int().nonnegative(),
gzipBytes: z.int().nonnegative(),
sha256,
})
.strict();
export const bundlePerformanceArtifactSchema = z
.object({
schemaVersion: z.literal(1),
generatedAt: timestamp,
context: z
.object({
nodeVersion: nonEmptyString,
packageManager: nonEmptyString,
runnerImage: nonEmptyString,
})
.strict(),
outputs: z.array(outputDigestSchema).min(1),
})
.strict();
const cyclonedxComponentSchema = z
.object({
type: z.literal("library"),
"bom-ref": nonEmptyString,
name: nonEmptyString,
version: nonEmptyString,
scope: z.enum(["optional", "required"]),
hashes: z.array(
z.object({ alg: z.literal("SHA-512"), content: nonEmptyString }).strict(),
),
licenses: z.array(
z.object({ expression: nonEmptyString }).strict(),
),
properties: z.array(
z.object({ name: nonEmptyString, value: nonEmptyString }).strict(),
),
})
.strict();
export const sbomArtifactSchema = z
.object({
bomFormat: z.literal("CycloneDX"),
specVersion: z.literal("1.6"),
serialNumber: nonEmptyString,
version: z.literal(1),
metadata: z
.object({
component: z
.object({
type: z.literal("application"),
name: nonEmptyString,
version: nonEmptyString,
})
.strict(),
properties: z.array(
z.object({ name: nonEmptyString, value: nonEmptyString }).strict(),
),
})
.strict(),
components: z.array(cyclonedxComponentSchema),
dependencies: z.array(
z
.object({ ref: nonEmptyString, dependsOn: z.array(nonEmptyString) })
.strict(),
),
})
.strict();
export const provenanceArtifactSchema = z
.object({
_type: z.literal("https://in-toto.io/Statement/v1"),
subject: z
.array(
z
.object({
name: z.literal("dist"),
digest: z.object({ sha256 }).strict(),
})
.strict(),
)
.length(1),
predicateType: z.literal("https://slsa.dev/provenance/v1"),
predicate: z
.object({
buildDefinition: z
.object({
buildType: nonEmptyString,
externalParameters: jsonObject,
internalParameters: jsonObject,
resolvedDependencies: z.array(
z
.object({ uri: nonEmptyString, digest: z.object({ sha256 }).strict() })
.strict(),
),
})
.strict(),
runDetails: z
.object({
builder: z.object({ id: nonEmptyString }).strict(),
metadata: z.object({ invocationId: nonEmptyString }).strict(),
})
.strict(),
materials: z
.object({ lockfileSha256: sha256, sourceSetSha256: sha256, sbomSha256: sha256 })
.strict(),
})
.strict(),
})
.strict();
export const dependencyDiffArtifactSchema = z
.object({
schemaVersion: z.literal(2),
baselineDigest: sha256.nullable(),
currentDigest: sha256,
...dependencyDiffSchema.shape,
highRisk: z.array(nonEmptyString),
reviewFailures: z.array(z.string()),
})
.strict();
export const licenseReportArtifactSchema = z
.object({
schemaVersion: z.literal(1),
status: z.enum(["PASS", "FAIL"]),
dependencyCount: z.int().nonnegative(),
results: z.array(
z
.object({
package: nonEmptyString,
license: nonEmptyString,
passed: z.boolean(),
reason: z.string().nullable(),
})
.strict(),
),
failures: z.array(z.string()),
})
.strict();
export const vulnerabilityReportArtifactSchema = z
.object({
schemaVersion: z.literal(1),
provider: nonEmptyString,
scannedLockfileSha256: sha256,
status: z.enum(["PASS", "FAIL", "FAIL_UNVERIFIED"]),
findings: z.array(jsonObject),
exceptionsApplied: z.array(jsonObject),
failures: z.array(z.string()),
blocking: z.array(z.string()),
})
.strict();
export const fieldWebVitalsArtifactSchema = z
.object({
schemaVersion: z.literal(1),
generatedAt: timestamp,
window: z
.object({ days: z.literal(28), start: timestamp, end: timestamp })
.strict(),
context: z
.object({
source: nonEmptyString,
sourceSystem: z.string().nullable(),
exportId: z.string().nullable(),
network: z.literal("production-real-user"),
routeAggregation: z.literal("route-id-only"),
releaseId: z.string().nullable(),
privacyApprovalRef: z.string().nullable(),
thresholdDecisionRef: z.string().nullable(),
validationFailures: z.array(z.string()),
})
.strict(),
metrics: z
.object({
p75LcpMs: z.number().finite().nonnegative().nullable(),
p75Cls: z.number().finite().nonnegative().nullable(),
p75InpMs: z.number().finite().nonnegative().nullable(),
})
.strict(),
thresholds: z
.object({
p75LcpMs: z.number().finite().nonnegative(),
p75Cls: z.number().finite().nonnegative(),
p75InpMs: z.number().finite().nonnegative(),
minimumEligibleSamples: z.int().positive().nullable(),
})
.strict(),
eligibility: z
.object({
consentRequired: z.literal(true),
totalSamples: z.int().nonnegative(),
eligibleSamples: z.int().nonnegative(),
minimumEligibleSamples: z.int().positive().nullable(),
routeSamples: z.record(z.string(), z.int().nonnegative()),
})
.strict(),
status: z.enum(["PASS", "FAIL_THRESHOLD", "FAIL_UNVERIFIED"]),
passed: z.boolean(),
})
.strict();
export const labPerformanceArtifactSchema = z
.object({
schemaVersion: z.literal(1),
generatedAt: timestamp,
context: jsonObject,
metrics: jsonObject,
thresholds: jsonObject,
fixtures: z.array(
z.object({ name: nonEmptyString, passed: z.boolean() }).strict(),
),
passed: z.boolean(),
})
.strict();
export const releaseVerificationArtifactSchema = z
.object({
schemaVersion: z.literal(1),
generatedAt: timestamp,
artifact: z
.object({
checked: z.boolean(),
compatible: z.boolean(),
mismatches: z.array(z.string()),
releaseId: nonEmptyString,
})
.strict(),
fixtures: z.array(
z
.object({
name: nonEmptyString,
expectedCompatible: z.boolean(),
actualCompatible: z.boolean(),
mismatches: z.array(z.string()),
passed: z.boolean(),
})
.strict(),
),
passed: z.boolean(),
})
.strict();
export const runbookRecordArtifactSchema = z
.object({
schemaVersion: z.literal(1),
runbookId: z.string().regex(/^FE-RB-00[1-5]$/u),
releaseId: nonEmptyString,
drillTimestamp: timestamp,
triggerInjected: nonEmptyString,
triggerAsserted: z.boolean(),
containmentAsserted: z.boolean(),
escalationPathAsserted: z.boolean(),
recoveryAssertions: z.array(
z
.object({
assertion: nonEmptyString,
evidence: nonEmptyString,
passed: z.boolean(),
})
.strict(),
),
negativeFixtureFailedAsExpected: z.boolean(),
windowObservedBucket: nonEmptyString,
providerVerificationRequired: z.boolean(),
passed: z.boolean(),
})
.strict();