import { JAVASCRIPT_APPLICATION_PROVIDER, JAVASCRIPT_RUNTIME_RECONCILIATION_PROVIDER, MANAGED_WORKFLOW_PROVIDER, } from "../InvestigationProviders.js"; import { parseEvidence, type Evidence } from "../../domain/evidence.js"; import { analyzeJavaScriptApplicationInputSchema, javascriptApplicationAnalysisResultSchema, type JavaScriptApplicationAnalysisResult, } from "../../domain/javascript/javascriptApplicationAnalysis.js"; import type { JavaScriptApplicationGraph } from "../../domain/javascript/javascriptApplicationGraph.js"; import type { JavaScriptSemanticGraph } from "../../domain/javascript/javascriptSemanticGraph.js"; import { javascriptRuntimeReconciliationResultSchema } from "../../domain/javascript/javascriptRuntimeReconciliationSchemas.js"; import { managedApplicationGraphResultSchema } from "../../domain/managedApplicationGraph.js"; /** Supported immutable source for an application-level graph workflow. */ export interface ApplicationGraphEvidenceSource { readonly evidence: Evidence; readonly graph: JavaScriptApplicationGraph; readonly kind: | "static-application" | "static-runtime-reconciliation" | "managed-application"; readonly rootArtifactSha256: string; readonly semanticGraph: JavaScriptSemanticGraph | null; } /** Parse and authenticate one REA-produced JavaScript Application Graph Evidence. */ export const parseApplicationGraphEvidence = ( input: unknown, ): ApplicationGraphEvidenceSource => { const evidence = parseEvidence(input); if ( evidence.operation === "analyze_javascript_application" && evidence.predicate_type === "rea.javascript-application-analysis" && providerMatches(evidence, JAVASCRIPT_APPLICATION_PROVIDER) ) return staticApplicationSource(evidence); if ( evidence.operation === "reconcile_javascript_runtime" && evidence.predicate_type === "rea.javascript-runtime-reconciliation" && providerMatches(evidence, JAVASCRIPT_RUNTIME_RECONCILIATION_PROVIDER) ) return staticRuntimeSource(evidence); if ( evidence.operation === "project_managed_application_graph" && evidence.predicate_type === "rea.managed-application-graph" && providerMatches(evidence, MANAGED_WORKFLOW_PROVIDER) ) return managedApplicationSource(evidence); throw new TypeError( "Application workflow requires authenticated analyze_javascript_application, reconcile_javascript_runtime, or project_managed_application_graph Evidence", ); }; const staticApplicationSource = ( evidence: Evidence, ): ApplicationGraphEvidenceSource => { if ( evidence.authority !== "shipped-artifact" || evidence.confidence !== "derived" ) throw new TypeError( "JavaScript application Evidence authority or confidence is invalid", ); const result = javascriptApplicationAnalysisResultSchema.parse( evidence.normalized_result, ); if (evidence.predicate_type !== "rea.javascript-application-analysis") throw new TypeError( "JavaScript application Evidence predicate does not match its result shape", ); analyzeJavaScriptApplicationInputSchema.parse({ input_path: result.input_path, ...evidence.parameters, }); assertApplicationSubject(evidence, result); return { evidence, graph: result.graph, kind: "static-application", rootArtifactSha256: result.root_artifact_sha256, semanticGraph: result.semantic_graph, }; }; const staticRuntimeSource = ( evidence: Evidence, ): ApplicationGraphEvidenceSource => { if ( evidence.authority !== "analyst-inference" || evidence.confidence !== "inferred" ) throw new TypeError( "JavaScript runtime reconciliation Evidence authority or confidence is invalid", ); const result = javascriptRuntimeReconciliationResultSchema.parse( evidence.normalized_result, ); if ( result.evidence_links.some( (evidenceId) => !evidence.evidence_links.includes(evidenceId), ) ) throw new TypeError( "Runtime reconciliation result references Evidence outside its envelope", ); const applicationLayer = result.static_layers.find( ({ role }) => role === "application", ); if (applicationLayer === undefined) throw new TypeError("Runtime reconciliation application layer is missing"); return { evidence, graph: result.graph, kind: "static-runtime-reconciliation", rootArtifactSha256: applicationLayer.root_artifact_sha256, semanticGraph: null, }; }; const managedApplicationSource = ( evidence: Evidence, ): ApplicationGraphEvidenceSource => { if ( evidence.authority !== "analyst-inference" || evidence.confidence !== "inferred" ) throw new TypeError( "Managed application graph Evidence authority or confidence is invalid", ); const result = managedApplicationGraphResultSchema.parse( evidence.normalized_result, ); if ( result.evidence_links.some( (evidenceId) => !evidence.evidence_links.includes(evidenceId), ) ) throw new TypeError( "Managed application graph result references Evidence outside its envelope", ); return { evidence, graph: result.graph, kind: "managed-application", rootArtifactSha256: result.root_artifact_sha256, semanticGraph: null, }; }; const assertApplicationSubject = ( evidence: Evidence, result: JavaScriptApplicationAnalysisResult, ): void => { if ( evidence.subject === null || evidence.subject.digest.sha256 !== result.root_artifact_sha256 || evidence.subject.format !== result.format || evidence.subject.local_path !== result.input_path ) throw new TypeError( "JavaScript application Evidence subject does not match its result", ); }; const providerMatches = ( evidence: Evidence, provider: { readonly id: string; readonly name: string; readonly version: string; }, ): boolean => evidence.provider.id === provider.id && evidence.provider.name === provider.name && evidence.provider.version === provider.version; /** Parse unique, artifact-bound Evidence that may extend a native handoff. */ export const parseNativeApplicationEvidence = ( inputs: readonly unknown[], ): Evidence[] => { const parsed = inputs.map((input) => parseEvidence(input)); if (parsed.some(({ subject }) => subject === null)) throw new TypeError("Native handoff Evidence requires an artifact subject"); const ids = parsed.map(({ evidence_id: id }) => id); if (new Set(ids).size !== ids.length) throw new TypeError("Native handoff Evidence must be unique"); return parsed; };