import { z } from "zod"; import { contractSetSchema } from "./contract-set.ts"; const versionSchema = z.string().regex(/^\d+(?:\.\d+){0,2}$/); function assertEndpointUrl( value: string, local: boolean, options: Readonly<{ trailingSlashPath?: boolean }> = {}, ): void { const parsed = new URL(value); if ( (parsed.protocol !== "http:" && parsed.protocol !== "https:") || parsed.username || parsed.password || parsed.hash || parsed.search || (!local && parsed.protocol !== "https:") ) { throw new TypeError("invalid"); } if (options.trailingSlashPath && !parsed.pathname.endsWith("/")) { throw new TypeError("invalid"); } } export function isValidReleaseManifestUrl(value: string): boolean { if (!value.startsWith("/") || value.startsWith("//")) return false; if (new TextEncoder().encode(value).byteLength > 256) return false; if (value.includes("?") || value.includes("#") || value.includes("\\")) { return false; } if (/%2f|%5c/i.test(value)) return false; return !value .split("/") .some((segment) => segment === "." || segment === ".."); } export const capabilityOverrideArtifactSchema = z .object({ REALTIME: z.enum(["DEFAULT", "DISABLED"]).default("DEFAULT"), WEB_WORKER: z.enum(["DEFAULT", "DISABLED"]).default("DEFAULT"), SERVICE_WORKER: z.enum(["DEFAULT", "DISABLED"]).default("DEFAULT"), OFFLINE_COMMANDS: z.enum(["DEFAULT", "DISABLED"]).default("DEFAULT"), }) .strict() .default({ REALTIME: "DEFAULT", WEB_WORKER: "DEFAULT", SERVICE_WORKER: "DEFAULT", OFFLINE_COMMANDS: "DEFAULT", }); /** * §3.5 / §6.1. A runtime switch that can take an installed feature out of * service without a rebuild. * * Values are `DEFAULT | DISABLED` for the same reason `CAPABILITY_OVERRIDES` * is: a configuration document may subtract from what the build installed and * may never add to it. Keys are feature ids; naming a feature this build does * not contain is inert rather than an error, so a shared configuration * document can cover several builds. */ export const featureOverrideArtifactSchema = z .record( z.string().regex(/^[a-z][a-z0-9-]{0,63}$/u, "feature id is invalid"), z.enum(["DEFAULT", "DISABLED"]), ) .default({}); type RuntimeConfigArtifactDraft = Readonly<{ APP_ENV: "local" | "development" | "staging" | "production"; API_BASE_URL: string; TELEMETRY_ENABLED: boolean; TELEMETRY_ENDPOINT?: string; AUTH_MODE: "external" | "demo"; RELEASE_MANIFEST_URL: string; }>; function runtimeConfigArtifactInvariants( config: RuntimeConfigArtifactDraft, context: z.RefinementCtx, ): void { const local = config.APP_ENV === "local" || config.APP_ENV === "development"; if (config.TELEMETRY_ENABLED && !config.TELEMETRY_ENDPOINT) { context.addIssue({ code: "custom", path: ["TELEMETRY_ENDPOINT"], message: "required when telemetry is enabled", }); } if (!local && config.AUTH_MODE === "demo") { context.addIssue({ code: "custom", path: ["AUTH_MODE"], message: "demo authentication is limited to local environments", }); } try { assertEndpointUrl(config.API_BASE_URL, local, { trailingSlashPath: true }); } catch { context.addIssue({ code: "custom", path: ["API_BASE_URL"], message: "absolute credential-free URL ending in / is required; HTTPS outside local", }); } if (config.TELEMETRY_ENDPOINT) { try { assertEndpointUrl(config.TELEMETRY_ENDPOINT, local); } catch { context.addIssue({ code: "custom", path: ["TELEMETRY_ENDPOINT"], message: "absolute credential-free URL is required; HTTPS outside local", }); } } if (!isValidReleaseManifestUrl(config.RELEASE_MANIFEST_URL)) { context.addIssue({ code: "custom", path: ["RELEASE_MANIFEST_URL"], message: "same-origin absolute path without query, hash or traversal", }); } } const runtimeConfigArtifactFields = { APP_ENV: z.enum(["local", "development", "staging", "production"]), API_BASE_URL: z.url(), REQUEST_TIMEOUT_MS: z.int().min(100).max(60_000).default(10_000), MAX_RETRY_ATTEMPTS: z.int().min(0).max(2).default(2), TELEMETRY_ENABLED: z.boolean(), TELEMETRY_ENDPOINT: z.url().optional(), AUTH_MODE: z.enum(["external", "demo"]), RELEASE_MANIFEST_URL: z.string().min(1).default("/release-manifest.json"), RELEASE_ID: z.string().min(1).optional(), BUILD_ID: z.string().min(1).optional(), } as const; export const runtimeConfigV1ArtifactSchema = z .object({ ...runtimeConfigArtifactFields, CONFIG_SCHEMA_VERSION: z.literal("1"), API_CONTRACT_VERSION: versionSchema, }) .strict() .superRefine(runtimeConfigArtifactInvariants); export const runtimeConfigV2ArtifactSchema = z .object({ ...runtimeConfigArtifactFields, CONFIG_SCHEMA_VERSION: z.literal("2.0"), CAPABILITY_OVERRIDES: capabilityOverrideArtifactSchema, FEATURE_OVERRIDES: featureOverrideArtifactSchema, }) .strict() .superRefine(runtimeConfigArtifactInvariants); export const runtimeConfigArtifactSchema = z.discriminatedUnion( "CONFIG_SCHEMA_VERSION", [ runtimeConfigV1ArtifactSchema, runtimeConfigV2ArtifactSchema, ], ); const releaseManifestArtifactFields = { appVersion: z.string().min(1), buildId: z.string().min(1), commitSha: z.string().min(1), assetManifestHash: z.string().min(1), releaseId: z.string().min(1), builtAt: z.string().min(1), routeChunks: z.record(z.string().min(1), z.string().min(1)), } as const; export const releaseManifestV1ArtifactSchema = z .object({ schemaVersion: z.literal(1), ...releaseManifestArtifactFields, configSchemaVersion: versionSchema, apiContractVersion: versionSchema, }) .strict(); export const releaseManifestV2ArtifactSchema = z .object({ schemaVersion: z.literal(2), ...releaseManifestArtifactFields, configSchemaVersion: z.literal("2.0"), contractSet: contractSetSchema, }) .strict(); export const releaseManifestArtifactSchema = z.discriminatedUnion( "schemaVersion", [releaseManifestV1ArtifactSchema, releaseManifestV2ArtifactSchema], ); export const buildManifestArtifactSchema = z .object({ schemaVersion: z.literal(1), buildId: z.string().min(1), commitSha: z.string().min(1), releaseId: z.string().min(1), moduleInventoryHash: z.string().min(1), generatedAt: z.string().min(1), buildContext: z .object({ nodeVersion: z.string().min(1), packageManagerVersion: z.string().min(1), runnerImage: z.string().min(1), sourceDateEpoch: z.string().min(1).nullable(), }) .strict(), outputs: z .object({ directory: z.string().min(1), viteManifest: z.string().min(1), moduleInventory: z.string().min(1), routeChunks: z.record(z.string().min(1), z.string().min(1)), runtimeConfigSchema: z.string().min(1), }) .strict(), }) .strict(); export type RuntimeConfigV1Artifact = z.output< typeof runtimeConfigV1ArtifactSchema >; export type RuntimeConfigV2Artifact = z.output< typeof runtimeConfigV2ArtifactSchema >; export type CapabilityOverrideArtifact = z.output< typeof capabilityOverrideArtifactSchema >; export type RuntimeConfigArtifact = z.output; export type ReleaseManifestV1Artifact = z.output< typeof releaseManifestV1ArtifactSchema >; export type ReleaseManifestV2Artifact = z.output< typeof releaseManifestV2ArtifactSchema >; export type ReleaseArtifact = z.output; export type BuildManifestArtifact = z.output; export function parseReleaseArtifact(value: unknown): ReleaseArtifact { return releaseManifestArtifactSchema.parse(value); } export function parseRuntimeConfigArtifact(value: unknown): RuntimeConfigArtifact { return runtimeConfigArtifactSchema.parse(value); } export function parseBuildManifestArtifact(value: unknown): BuildManifestArtifact { return buildManifestArtifactSchema.parse(value); } export function projectReleaseTokens(release: ReleaseArtifact) { const common = { schemaVersion: release.schemaVersion, appVersion: release.appVersion, buildId: release.buildId, commitSha: release.commitSha, configSchemaVersion: release.configSchemaVersion, assetManifestHash: release.assetManifestHash, releaseId: release.releaseId, builtAt: release.builtAt, } as const; return release.schemaVersion === 1 ? Object.freeze({ ...common, schemaVersion: 1 as const, apiContractVersion: release.apiContractVersion, }) : Object.freeze({ ...common, schemaVersion: 2 as const, contractSetDigest: release.contractSet.setDigest, }); }