/* RFC-0357/RFC-0851: Zod schemas for release manifest (artifact-only prepared|ready), behavior snapshot wrapper, snapshot diff, and legacy release diagnostics. Do not introduce app-specific runtime composition or deployment behavior into this reusable package source file. Do not reintroduce legacy deployment states (published, dev-deployed, alt-deployed, promoted, main-deployed, rolled-back) into the artifact state schema. RFC-0357: initial release and behavior snapshot schemas. RFC-0608: extend releaseStateSchema with alt-deployed and promoted; add buildIdentitySchema. RFC-0627: add dev-deployed state (precedes alt-deployed in the three-channel deployment chain). RFC-0628: remove dev-deployed state (workpiece-based dev deploy does not enter the release state machine). RFC-0851: replace legacy state enum with artifact-only prepared|ready; make manifest strict; replace publishedAt with readyAt; add legacyReleaseStateSchema and legacyReleaseDiagnosticSchema. */ import { z } from "zod"; import { STERNSYSTEM_ID_REGEX, MISSION_ID_REGEX, RELEASE_ID_REGEX } from "./naming-policy.ts"; import { releaseArtifactRefSchema as artifactRefSchema } from "./artifact-store.ts"; export const releaseArtifactStateSchema = z.enum(["prepared", "ready"]); export const releaseStateSchema = releaseArtifactStateSchema; export const legacyReleaseStateSchema = z.enum([ "published", "dev-deployed", "alt-deployed", "promoted", "main-deployed", "rolled-back", ]); export const legacyReleaseDiagnosticSchema = z .object({ schema: z.literal("werkstatt/legacy-release-diagnostic@1"), releaseId: z.string().regex(RELEASE_ID_REGEX), legacyState: legacyReleaseStateSchema, ruleId: z.literal("CERT-LEGACY-STATE-01"), message: z.string().min(1), fixHint: z.string().min(1), }) .strict(); export const releaseManifestSchema = z .object({ schemaVersion: z.string().min(1), releaseId: z.string().regex(RELEASE_ID_REGEX), systemId: z.string().regex(STERNSYSTEM_ID_REGEX), missionId: z.string().regex(MISSION_ID_REGEX), semver: z.string(), platformVersion: z.string(), createdAt: z.string().datetime(), readyAt: z.string().datetime().nullable(), state: releaseArtifactStateSchema, commitSha: z.string(), platformSemanticHash: z.string(), siteContentHash: z.string(), distTreeHash: z.string(), distArtifactHash: z.string().nullable(), artifact: artifactRefSchema.nullable(), behaviorSnapshotHash: z.string(), readableSnapshotHash: z.string(), qualityReportHash: z.string().nullable(), snapshotDiffVerdict: z.enum(["pass", "fail"]), migratorVerdict: z.enum(["pass", "fail"]), versionCompareVerdict: z.enum(["in-sync", "catch-up", "refuse-downgrade"]), bootSmokeVerdict: z.enum(["pass", "fail"]), }) .strict(); export const releaseArtifactRefSchema = z.object({ store: z.literal("werkstatt-local"), algorithm: z.literal("sha256"), digest: z.string(), uri: z.string(), manifestHash: z.string(), }); export const behaviorSnapshotDifferenceSchema = z.object({ field: z.string(), kind: z.enum(["added", "removed", "changed"]), detail: z.string(), }); export const behaviorSnapshotDiffSchema = z.object({ schemaVersion: z.string().min(1), baselineHash: z.string(), candidateHash: z.string(), verdict: z.enum(["pass", "fail"]), differences: z.array(behaviorSnapshotDifferenceSchema), }); export const buildIdentitySchema = z.object({ releaseId: z.string().regex(/^(workpiece-)?[a-z0-9]+(-[a-z0-9]+)*(-r\d{6}|-m\d{6})$/), systemId: z.string().regex(STERNSYSTEM_ID_REGEX), missionId: z.string().regex(MISSION_ID_REGEX), semver: z.string(), distTreeHash: z.string(), behaviorSnapshotHash: z.string(), siteContentHash: z.string(), platformVersion: z.string(), platformSemanticHash: z.string(), commitSha: z.string(), buildTimestamp: z.string().datetime(), targetPlatform: z.string(), // --- RFC-0931 signature fields (optional, added during signing phase) --- signature: z.string().optional(), publicKeyUrl: z.string().optional(), signedAt: z.string().datetime().optional(), }); export type ReleaseArtifactState = z.infer; export type ReleaseState = z.infer; export type LegacyReleaseState = z.infer; export type LegacyReleaseDiagnostic = z.infer; export type ReleaseManifest = z.infer; export type BuildIdentity = z.infer; export type BehaviorSnapshotDifference = z.infer; export type BehaviorSnapshotDiff = z.infer;