import { isStringArray } from '@ankhorage/utility/array'; import { isRecord } from '@ankhorage/utility/object'; import { isNonEmptyString } from '@ankhorage/utility/string'; import { isSerializableSet } from '../collections'; import type { InfraShape } from '../types/infraValidation'; import type { InfraWorkloadSpec } from '../types/infraWorkload'; import { infraFields } from './infraFields'; import { isInfraShape } from './isInfraShape'; import { isInfraWorkloadHealth } from './isInfraWorkloadHealth'; import { isInfraWorkloadValue } from './isInfraWorkloadValue'; /*** Validate the portable desired workload; runtime-specific fields and plaintext secret objects fail. */ export function isInfraWorkloadSpec(value: unknown): value is InfraWorkloadSpec { if ( !isInfraShape(value, { id: isNonEmptyString, artifact: (artifact) => isInfraShape(artifact, { kind: (kind) => kind === 'image', image: isNonEmptyString }), command: infraFields.optionalStrings, args: (args) => args === undefined || isStringArray(args), ports: (ports) => ports === undefined || isPortRegistry(ports), environment: (environment) => environment === undefined || (isRecord(environment) && Object.values(environment).every(isInfraWorkloadValue)), files: (files) => files === undefined || isFileMap(files), health: (health) => health === undefined || isInfraWorkloadHealth(health), resources: (resources) => resources === undefined || isInfraShape(resources, { cpuMillis: infraFields.optionalPositiveInteger, memoryMiB: infraFields.optionalPositiveInteger, }), persistence: (volumes) => volumes === undefined || isVolumeRegistry(volumes), exposure: (exposure) => exposure === undefined || exposure === 'internal' || exposure === 'public', replicas: infraFields.optionalNonnegativeInteger, dependsOn: (dependsOn) => dependsOn === undefined || isSerializableSet(dependsOn), } satisfies InfraShape) ) { return false; } return hasValidPublishedPorts(value); } /*** Validate named transport ports keyed by their stable authored name. */ function isPortRegistry(value: unknown): boolean { return ( isRecord(value) && Object.entries(value).every(([name, port]) => isNonEmptyString(name) && isPort(port)) ); } /*** Named transport ports stay independent from runtime resource types. */ function isPort(value: unknown): boolean { return isInfraShape(value, { port: infraFields.port, protocol: (protocol) => protocol === undefined || protocol === 'tcp' || protocol === 'udp', publishedPort: infraFields.optionalPort, }); } /*** Require fixed external listeners to belong to one public workload replica. */ function hasValidPublishedPorts(workload: unknown): boolean { if (!isRecord(workload)) return false; const ports = isRecord(workload.ports) ? Object.values(workload.ports) : []; const published = ports.flatMap((port) => { if (!isRecord(port) || typeof port.publishedPort !== 'number') return []; return [port.publishedPort]; }); return ( new Set(published).size === published.length && (published.length === 0 || (workload.exposure === 'public' && (workload.replicas === undefined || (typeof workload.replicas === 'number' && workload.replicas <= 1)))) ); } /*** Validate portable config/policy files keyed by their absolute container path. */ function isFileMap(value: unknown): boolean { return ( isRecord(value) && Object.entries(value).every( ([filePath, content]) => isAbsoluteWorkloadPath(filePath) && isInfraWorkloadValue(content), ) ); } /*** Validate persistence volumes by stable ID and keep mount paths unique within one workload. */ function isVolumeRegistry(value: unknown): boolean { if (!isRecord(value)) return false; const entries = Object.entries(value); if ( !entries.every( ([volumeId, volume]) => isVolume(volume) && isRecord(volume) && volume.id === volumeId, ) ) { return false; } const mountPaths = Object.values(value).map((volume) => isRecord(volume) ? volume.mountPath : undefined, ); return new Set(mountPaths).size === mountPaths.length; } /*** Persistence has explicit ownership-local identity, optional initialization and retention policy. */ function isVolume(value: unknown): boolean { return isInfraShape(value, { id: isNonEmptyString, mountPath: isAbsoluteWorkloadPath, sizeGiB: infraFields.positiveInteger, seed: (seed) => seed === undefined || seed === 'image', retention: (retention) => retention === 'retain' || retention === 'delete-on-destroy', }); } /*** Workload paths are absolute container paths, never relative host traversal. */ function isAbsoluteWorkloadPath(value: unknown): boolean { return ( typeof value === 'string' && value.startsWith('/') && value.length > 1 && !value.split('/').includes('..') ); }