54 lines
2.5 KiB
TypeScript
54 lines
2.5 KiB
TypeScript
export const pipelineProvenanceAnnotationKeys = {
|
|
configRef: "unidesk.ai/owning-config-ref",
|
|
effectiveConfigSha256: "unidesk.ai/effective-config-sha256",
|
|
renderer: "unidesk.ai/source-artifact-renderer",
|
|
mode: "unidesk.ai/source-artifact-mode",
|
|
} as const;
|
|
|
|
export interface PipelineProvenanceContract {
|
|
readonly configRef: string;
|
|
readonly effectiveConfigSha256: string;
|
|
readonly renderer: string;
|
|
readonly mode: string;
|
|
}
|
|
|
|
export function pipelineProvenanceAnnotations(provenance: PipelineProvenanceContract): Record<string, string> {
|
|
return {
|
|
[pipelineProvenanceAnnotationKeys.configRef]: provenance.configRef,
|
|
[pipelineProvenanceAnnotationKeys.effectiveConfigSha256]: provenance.effectiveConfigSha256,
|
|
[pipelineProvenanceAnnotationKeys.renderer]: provenance.renderer,
|
|
[pipelineProvenanceAnnotationKeys.mode]: provenance.mode,
|
|
};
|
|
}
|
|
|
|
export function withPipelineProvenanceAnnotations(
|
|
manifest: Record<string, unknown>,
|
|
provenance: PipelineProvenanceContract,
|
|
): Record<string, unknown> {
|
|
const next = structuredClone(manifest);
|
|
const metadata = asRecord(next.metadata, "manifest.metadata");
|
|
const annotations = metadata.annotations === undefined ? {} : asRecord(metadata.annotations, "manifest.metadata.annotations");
|
|
metadata.annotations = { ...annotations, ...pipelineProvenanceAnnotations(provenance) };
|
|
return next;
|
|
}
|
|
|
|
export function pipelineProvenanceFromManifest(manifest: Record<string, unknown>): PipelineProvenanceContract | null {
|
|
const metadata = isRecord(manifest.metadata) ? manifest.metadata : {};
|
|
const annotations = isRecord(metadata.annotations) ? metadata.annotations : {};
|
|
const configRef = annotations[pipelineProvenanceAnnotationKeys.configRef];
|
|
const effectiveConfigSha256 = annotations[pipelineProvenanceAnnotationKeys.effectiveConfigSha256];
|
|
const renderer = annotations[pipelineProvenanceAnnotationKeys.renderer];
|
|
const mode = annotations[pipelineProvenanceAnnotationKeys.mode];
|
|
if ([configRef, effectiveConfigSha256, renderer, mode].some((value) => typeof value !== "string" || value.length === 0)) return null;
|
|
return { configRef, effectiveConfigSha256, renderer, mode } as PipelineProvenanceContract;
|
|
}
|
|
|
|
function asRecord(value: unknown, path: string): Record<string, unknown> {
|
|
if (!isRecord(value)) throw new Error(`${path} must be an object`);
|
|
return value;
|
|
}
|
|
|
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
}
|