diff --git a/docs/tool-design.md b/docs/tool-design.md index 5c2d3b7391..1fb7e2d901 100644 --- a/docs/tool-design.md +++ b/docs/tool-design.md @@ -241,6 +241,17 @@ Put provider protocols/parsing in adapters and shared CLI/MCP workflows in the application layer. Share Evidence provenance, unknown projection, and session retention semantics; matching payloads alone do not establish parity. +Let `createEvidence` own JSON validation and snapshotting of ordinary observation +payloads. `EvidenceObservationInput` accepts semantically parsed parameters, +results, and raw results whose JSON validity still needs admission. Keep format, +selection, and identity validation at their producing boundary. Invalid JSON +issues are rooted at `parameters`, `normalized_result`, or `raw_result` in the +Evidence envelope. + +`EvidenceObservation` retains the stronger JSON contract used by producer +helpers and `createImmutableEvidenceSteps`. The cooperative constructor also +requires an authenticated immutable result; preserve that ownership proof. + Measure the resource before choosing a budget and enforce it before the costly step. Account for value alternatives, trace-frame products, retained records, serialization expansion, and temporary-file growth separately. Derive facet diff --git a/src/application/BrowserEvidence.ts b/src/application/BrowserEvidence.ts index 311d8ac549..a704a6b0e0 100644 --- a/src/application/BrowserEvidence.ts +++ b/src/application/BrowserEvidence.ts @@ -4,7 +4,6 @@ import { type Evidence, type EvidenceObservation, } from "../domain/evidence.js"; -import { jsonValueSchema } from "../domain/jsonValue.js"; import { sanitizeBrowserUrl } from "../domain/browserObservation.js"; import type { InspectWebPageInput, @@ -77,7 +76,7 @@ export const createBrowserEvidence = ( predicateType: browserPredicate(operation), operation, parameters: browserParameters(input, result), - result: jsonValueSchema.parse(result), + result, confidence: "observed", authority: "external-service", environment: diff --git a/src/application/BrowserScenarioEvidence.ts b/src/application/BrowserScenarioEvidence.ts index 5dae07c218..7fd9c2bd2e 100644 --- a/src/application/BrowserScenarioEvidence.ts +++ b/src/application/BrowserScenarioEvidence.ts @@ -7,7 +7,7 @@ import { type Evidence, type EvidenceObservation, } from "../domain/evidence.js"; -import { jsonObjectSchema, jsonValueSchema } from "../domain/jsonValue.js"; +import { jsonObjectSchema } from "../domain/jsonValue.js"; const browserScenarioParameters = ( scenario: BrowserScenario, @@ -26,7 +26,7 @@ export const createBrowserScenarioEvidence = ( predicateType: "rea.browser-scenario-capture", operation: "capture_browser_scenario", parameters: browserScenarioParameters(scenario), - result: jsonValueSchema.parse(capture), + result: capture, confidence: "observed", authority: "controlled-replay", environment: { diff --git a/src/application/ReconstructionObligationLedger.fixture.ts b/src/application/ReconstructionObligationLedger.fixture.ts index ca1da93d09..5d2e422592 100644 --- a/src/application/ReconstructionObligationLedger.fixture.ts +++ b/src/application/ReconstructionObligationLedger.fixture.ts @@ -12,7 +12,6 @@ import { createEvidenceBundle, type EvidenceBundle, } from "../domain/evidenceBundle.js"; -import { jsonValueSchema } from "../domain/jsonValue.js"; import { reconstructionObligationLedgerSchema, type ReconstructionObligationLedgerInput, @@ -47,12 +46,10 @@ export const processEvidence = ( predicateType: "rea.process-capture", operation: "capture_process_scenario", parameters: {}, - result: jsonValueSchema.parse( - processCaptureSchema.parse({ - ...EMPTY_PROCESS_CAPTURE_EXAMPLE, - ...overrides, - }), - ), + result: processCaptureSchema.parse({ + ...EMPTY_PROCESS_CAPTURE_EXAMPLE, + ...overrides, + }), confidence: "observed", authority: "controlled-replay", }); @@ -70,9 +67,7 @@ export const boundProofEvidence = ( predicateType: "rea.reconstruction-proof", operation: "verify_reconstruction_obligations", parameters: {}, - result: jsonValueSchema.parse( - reconstructionObligationProofSchema.parse(result), - ), + result: reconstructionObligationProofSchema.parse(result), confidence: "observed", authority, }, diff --git a/src/application/WebModuleTraceService.ts b/src/application/WebModuleTraceService.ts index b5f5878a67..ee57889e7a 100644 --- a/src/application/WebModuleTraceService.ts +++ b/src/application/WebModuleTraceService.ts @@ -261,7 +261,7 @@ export class WebModuleTraceService { }, { operation: OPERATION, - parameters: jsonObjectSchema.parse(input), + parameters: input, result: normalized.data, rawResult: resolution?.rawResult ?? null, confidence: "derived", diff --git a/src/application/WebRuntimeService.ts b/src/application/WebRuntimeService.ts index acdacb0f32..64dd8d4d3b 100644 --- a/src/application/WebRuntimeService.ts +++ b/src/application/WebRuntimeService.ts @@ -7,7 +7,6 @@ import { AnalysisOutputError, } from "../domain/analysisErrorCore.js"; import { createEvidence, type Evidence } from "../domain/evidence.js"; -import { jsonObjectSchema } from "../domain/jsonValue.js"; import { analysisInputErrorFromIssues } from "../domain/inputIssueProjection.js"; import { err, ok, type Result } from "../domain/result.js"; import { @@ -162,7 +161,7 @@ export class WebRuntimeService { createEvidence(undefined, this.provider.identity(), { predicateType: `rea.${operation.replaceAll("_", "-")}`, operation, - parameters: jsonObjectSchema.parse(input), + parameters: input, result, confidence: "observed", authority: "external-service", diff --git a/src/application/WebScriptExportService.ts b/src/application/WebScriptExportService.ts index c81617304f..c0a52b351a 100644 --- a/src/application/WebScriptExportService.ts +++ b/src/application/WebScriptExportService.ts @@ -21,7 +21,6 @@ import { AnalysisError } from "../domain/analysisErrorBase.js"; import { createEvidence, type Evidence } from "../domain/evidence.js"; import { analysisErrorWithCleanupFailure } from "../domain/analysisErrorCleanup.js"; import { analysisInputErrorFromIssues } from "../domain/inputIssueProjection.js"; -import { jsonValueSchema } from "../domain/jsonValue.js"; import { ProviderAdapterError } from "../domain/providerAdapterError.js"; import { ProviderCleanupError } from "../domain/providerCleanupError.js"; import { err, ok, type Result } from "../domain/result.js"; @@ -136,7 +135,7 @@ export const exportWebScriptsValidated = async ( capture_path: input.capture_path, output_directory: input.output_directory, }, - result: jsonValueSchema.parse(result), + result, rawResult: null, confidence: "derived", authority: "historical-reference", diff --git a/src/application/WebSourceLocationService.ts b/src/application/WebSourceLocationService.ts index b40ad21870..1a5ad8325b 100644 --- a/src/application/WebSourceLocationService.ts +++ b/src/application/WebSourceLocationService.ts @@ -9,7 +9,6 @@ import { } from "../domain/analysisErrorCore.js"; import { createEvidence, type Evidence } from "../domain/evidence.js"; import { analysisInputErrorFromIssues } from "../domain/inputIssueProjection.js"; -import { jsonObjectSchema } from "../domain/jsonValue.js"; import { err, ok, type Result } from "../domain/result.js"; import { selectedWebScriptArtifactsSchema, @@ -171,7 +170,7 @@ export class WebSourceLocationService { }, { operation: OPERATION, - parameters: jsonObjectSchema.parse(input), + parameters: input, result: normalized.data, rawResult: { source_map_text: map.text }, confidence: "derived", diff --git a/src/application/analysisView/AnalysisViewService.ts b/src/application/analysisView/AnalysisViewService.ts index 2d83a52a0b..55e614be31 100644 --- a/src/application/analysisView/AnalysisViewService.ts +++ b/src/application/analysisView/AnalysisViewService.ts @@ -2,7 +2,6 @@ import { setImmediate } from "node:timers/promises"; import { dispatchQueuedInterrupts } from "../../process/queuedInterrupts.js"; import { readImmutableEvidenceBundle } from "../EvidenceBundleFiles.js"; import { INSPECT_ANALYSIS_VIEW_OPERATION } from "../../domain/analysisView/analysisViewErrors.js"; -import { jsonValueSchema } from "../../domain/jsonValue.js"; import { ANALYSIS_VIEW_PROVIDER } from "../../domain/investigationProviders.js"; import type { EvidenceLookup } from "../EvidenceInputResolver.js"; @@ -346,9 +345,9 @@ const createAnalysisViewEvidence = ( operation: INSPECT_ANALYSIS_VIEW_OPERATION, parameters: { parent_evidence_id: parent.evidence_id, - view: jsonValueSchema.parse(input.view), + view: input.view, }, - result: jsonValueSchema.parse(result), + result, rawResult: null, confidence: // Grouping is whole-capture, so any templated group or parameter makes the result inferred; diff --git a/src/application/android/AndroidAnalysisService.ts b/src/application/android/AndroidAnalysisService.ts index f31dff0dc7..12433b3311 100644 --- a/src/application/android/AndroidAnalysisService.ts +++ b/src/application/android/AndroidAnalysisService.ts @@ -11,7 +11,6 @@ import { import { AnalysisCancelledError } from "../../domain/analysisErrorCore.js"; import type { AnalysisError } from "../../domain/analysisErrorBase.js"; import { createEvidence, type Evidence } from "../../domain/evidence.js"; -import { jsonObjectSchema } from "../../domain/jsonValue.js"; import { err, type Result } from "../../domain/result.js"; import { completeProviderEvidence } from "../ProviderOperationExecution.js"; @@ -62,7 +61,7 @@ export class AndroidAnalysisService { execution.provider, { operation, - parameters: jsonObjectSchema.parse(request.data.input), + parameters: request.data.input, result: execution.result, rawResult: execution.rawResult, limitations: execution.limitations, diff --git a/src/application/frida/FridaInstrumentationService.ts b/src/application/frida/FridaInstrumentationService.ts index 685347bd30..b0f52f7c67 100644 --- a/src/application/frida/FridaInstrumentationService.ts +++ b/src/application/frida/FridaInstrumentationService.ts @@ -3,7 +3,6 @@ import { access, stat } from "node:fs/promises"; import { setTimeout as delay } from "node:timers/promises"; import { createEvidence, type Evidence } from "../../domain/evidence.js"; -import { jsonObjectSchema, jsonValueSchema } from "../../domain/jsonValue.js"; import { resolvedAnalysisError, type AnalysisError, @@ -458,8 +457,8 @@ const fridaEvidence = ( { predicateType: "rea.frida.instrumentation-observation", operation, - parameters: jsonObjectSchema.parse(parameters), - result: jsonValueSchema.parse(result), + parameters, + result, ...(script?.sourceRepresentation === undefined ? {} : { diff --git a/src/application/javascript/ElectronActiveEvidence.ts b/src/application/javascript/ElectronActiveEvidence.ts index cbd844e263..ebf1569cda 100644 --- a/src/application/javascript/ElectronActiveEvidence.ts +++ b/src/application/javascript/ElectronActiveEvidence.ts @@ -4,7 +4,7 @@ import type { CanonicalElectronActiveObservationInput } from "./ElectronActiveOb import type { Evidence, EvidenceObservation } from "../../domain/evidence.js"; import { createEvidence } from "../../domain/evidence.js"; import type { ElectronActiveObservationResult } from "../../domain/javascript/electronActiveObservation.js"; -import { jsonObjectSchema, jsonValueSchema } from "../../domain/jsonValue.js"; +import { jsonObjectSchema } from "../../domain/jsonValue.js"; /** Commit the selected Electron experiment and its observed result. */ export const createElectronActiveEvidence = ( @@ -16,7 +16,7 @@ export const createElectronActiveEvidence = ( predicateType: "rea.electron-active-scenario", operation: "capture_electron_scenario", parameters: parameters(input), - result: jsonValueSchema.parse(result), + result, confidence: "observed", authority: "controlled-replay", environment: { diff --git a/src/application/javascript/JavaScriptRecoveryService.ts b/src/application/javascript/JavaScriptRecoveryService.ts index 5fa5624a9c..c5291f148d 100644 --- a/src/application/javascript/JavaScriptRecoveryService.ts +++ b/src/application/javascript/JavaScriptRecoveryService.ts @@ -11,7 +11,6 @@ import { javascriptRecoveryInputSchema, javascriptRecoveryResultSchema, } from "../../domain/javascript/javascriptRecovery.js"; -import { jsonObjectSchema, jsonValueSchema } from "../../domain/jsonValue.js"; import { analysisInputErrorFromIssues } from "../../domain/inputIssueProjection.js"; import { err, type Result } from "../../domain/result.js"; import type { ExecutionOptions } from "../AnalysisProvider.js"; @@ -115,8 +114,8 @@ export class JavaScriptRecoveryService { execution.value.provider, { operation: OPERATION, - parameters: jsonObjectSchema.parse(parsed.data), - result: jsonValueSchema.parse(result.data), + parameters: parsed.data, + result: result.data, rawResult: execution.value.rawResult, locations: execution.value.locations, limitations: execution.value.limitations, diff --git a/src/application/javascript/JavaScriptRuntimeObservationEvidence.ts b/src/application/javascript/JavaScriptRuntimeObservationEvidence.ts index a5f0d9a2a8..399f20b3f1 100644 --- a/src/application/javascript/JavaScriptRuntimeObservationEvidence.ts +++ b/src/application/javascript/JavaScriptRuntimeObservationEvidence.ts @@ -10,7 +10,6 @@ import type { ListJavaScriptRuntimeTargetsInput, ObserveJavaScriptRuntimeInput, } from "../../domain/javascript/javascriptRuntimeObservation.js"; -import { jsonValueSchema } from "../../domain/jsonValue.js"; type RuntimeObservationOperation = | "list_javascript_runtime_targets" @@ -30,7 +29,7 @@ export const createJavaScriptRuntimeObservationEvidence = ( : "rea.javascript-runtime-observation", operation, parameters: parameters(input), - result: jsonValueSchema.parse(result), + result, rawResult: null, confidence: "observed", authority: "external-service", diff --git a/src/application/process/ProcessEvidence.ts b/src/application/process/ProcessEvidence.ts index cee402e545..4fd233088a 100644 --- a/src/application/process/ProcessEvidence.ts +++ b/src/application/process/ProcessEvidence.ts @@ -10,7 +10,6 @@ import { PROCESS_PROVIDER, isProcessEvidenceProvider, } from "../../domain/process/processEvidenceProvider.js"; -import { jsonValueSchema } from "../../domain/jsonValue.js"; import { safeParseProcessCapture, type ProcessCapture, @@ -91,7 +90,7 @@ export const createProcessCaptureEvidence = ( predicateType: PROCESS_CAPTURE_EVIDENCE.predicate, operation: PROCESS_CAPTURE_EVIDENCE.operation, parameters: processEvidenceParameters(scenario, capture.manifest.platform), - result: jsonValueSchema.parse(capture), + result: capture, confidence: "observed", authority: "controlled-replay", environment: { diff --git a/src/application/sqlite/SqliteDatabaseService.ts b/src/application/sqlite/SqliteDatabaseService.ts index 187f008d1a..f1cc74eecd 100644 --- a/src/application/sqlite/SqliteDatabaseService.ts +++ b/src/application/sqlite/SqliteDatabaseService.ts @@ -23,7 +23,6 @@ import { } from "../../domain/sqlite/sqliteDatabase.js"; import { analysisInputErrorFromIssues } from "../../domain/inputIssueProjection.js"; import { err, ok, type Result } from "../../domain/result.js"; -import { jsonValueSchema } from "../../domain/jsonValue.js"; const OPERATION = "inspect_sqlite_database"; @@ -115,7 +114,7 @@ export class SqliteDatabaseService { createEvidence(execution.subject, execution.provider, { operation: OPERATION, parameters: sqliteInspectionParameters(input.data), - result: jsonValueSchema.parse(report.data), + result: report.data, ...(execution.rawResult === null ? {} : { rawResult: execution.rawResult }), diff --git a/src/contracts/investigationExamples.ts b/src/contracts/investigationExamples.ts index 293bf8d654..3fa2b1a826 100644 --- a/src/contracts/investigationExamples.ts +++ b/src/contracts/investigationExamples.ts @@ -1,5 +1,4 @@ import { createEvidence } from "../domain/evidence.js"; -import { jsonValueSchema } from "../domain/jsonValue.js"; import { FUNCTION_COMPARISON_PROVIDER } from "../domain/comparisonEvidenceIdentity.js"; import { compareProcessCaptureEvidence } from "../domain/process/processComparisonEvidence.js"; import { PROCESS_PROVIDER } from "../domain/process/processEvidenceProvider.js"; @@ -31,7 +30,7 @@ export const FUNCTION_COMPARISON_EVIDENCE = createEvidence( left_evidence_id: left.value.evidence.evidence_id, right_evidence_id: right.value.evidence.evidence_id, }, - result: jsonValueSchema.parse(comparison), + result: comparison, confidence: "derived", authority: "analyst-inference", limitations: comparison.limitations, @@ -48,7 +47,7 @@ const captureEvidence = (scenario: string) => predicateType: "rea.process-capture", operation: "capture_process_scenario", parameters: { scenario }, - result: jsonValueSchema.parse(capture), + result: capture, confidence: "observed", authority: "controlled-replay", environment: { diff --git a/src/domain/analysisObservation.ts b/src/domain/analysisObservation.ts index 06ed145a01..f43e8972a8 100644 --- a/src/domain/analysisObservation.ts +++ b/src/domain/analysisObservation.ts @@ -7,7 +7,7 @@ import { type EvidenceSubjectTarget, } from "./evidence.js"; import type { AnalysisProfileCommitment } from "./analysisProfile.js"; -import { jsonObjectSchema, type JsonValue } from "./jsonValue.js"; +import type { JsonValue } from "./jsonValue.js"; import type { RelationshipCoverage } from "./relationshipCoverage.js"; /** Provider observations that can be committed to Evidence. */ @@ -44,7 +44,7 @@ export const createAnalysisExecutionEvidence = ( execution.provider, { operation, - parameters: jsonObjectSchema.parse(input), + parameters: input, result: execution.result, rawResult: execution.rawResult, limitations: execution.limitations, diff --git a/src/domain/evidence.test.ts b/src/domain/evidence.test.ts index 2230190472..6d08843610 100644 --- a/src/domain/evidence.test.ts +++ b/src/domain/evidence.test.ts @@ -138,6 +138,102 @@ it("projects known provider fields and preserves open JSON payloads", () => { expect(parseEvidence(evidence)).toEqual(evidence); }); +it("admits typed semantic payloads with omitted optional facts without changing inputs or identity", () => { + interface Selection { + readonly procedure: string; + readonly address?: string; + } + interface SymbolRow { + readonly name: string; + readonly size?: number; + } + interface NativeRecord { + readonly producer: string; + readonly diagnostic?: string; + } + const parameters: Selection = { procedure: "main" }; + const row: SymbolRow = { name: "main" }; + const result = { symbols: [row] }; + const rawResult: NativeRecord = { producer: "authored fixture" }; + const evidence = createEvidence(TARGET, PROVIDER, { + operation: "inspect", + parameters, + result, + rawResult, + }); + const equivalent = createEvidence(TARGET, PROVIDER, { + operation: "inspect", + parameters: { procedure: "main" }, + result: { symbols: [{ name: "main" }] }, + rawResult: { producer: "authored fixture" }, + }); + + expect(evidence).toEqual(equivalent); + expect(evidence.evidence_id).toBe(equivalent.evidence_id); + expect(parameters).toEqual({ procedure: "main" }); + expect(result).toEqual({ symbols: [{ name: "main" }] }); + expect(result.symbols[0]).toBe(row); + expect(rawResult).toEqual({ producer: "authored fixture" }); + expect(Object.hasOwn(parameters, "address")).toBe(false); + expect(Object.hasOwn(row, "size")).toBe(false); + expect(Object.hasOwn(rawResult, "diagnostic")).toBe(false); + expect(Object.isFrozen(parameters)).toBe(false); + expect(Object.isFrozen(result)).toBe(false); + expect(Object.isFrozen(row)).toBe(false); + expect(Object.isFrozen(rawResult)).toBe(false); +}); + +it("keeps an omitted, undefined, or null raw payload equivalent", () => { + const observation = { operation: "inspect", parameters: {}, result: true }; + const omitted = createEvidence(TARGET, PROVIDER, observation); + const explicitUndefined = createEvidence(TARGET, PROVIDER, { + ...observation, + rawResult: undefined, + }); + const explicitNull = createEvidence(TARGET, PROVIDER, { + ...observation, + rawResult: null, + }); + + expect(omitted.raw_result).toBeNull(); + expect(explicitUndefined).toEqual(omitted); + expect(explicitNull).toEqual(omitted); +}); + +it.each([ + { field: "parameters", prefix: "parameters" }, + { field: "result", prefix: "normalized_result" }, + { field: "rawResult", prefix: "raw_result" }, +])( + "rejects explicit nested undefined in $field at its Evidence prefix", + ({ field, prefix }) => { + const invalid = { nested: { value: undefined } }; + let failure: unknown; + try { + createEvidence(TARGET, PROVIDER, { + operation: "inspect", + parameters: {}, + result: true, + [field]: invalid, + }); + } catch (cause: unknown) { + failure = cause; + } + + expect(failure).toMatchObject({ + name: "ZodError", + issues: [ + { + path: [prefix], + message: expect.stringContaining("JSON"), + }, + ], + }); + expect(Object.hasOwn(invalid.nested, "value")).toBe(true); + expect(invalid.nested.value).toBeUndefined(); + }, +); + it("preserves identity and bytes when reusing an owned immutable result", () => { const value = { nested: { values: ["observed", 1] } }; const mutable = createEvidence(TARGET, PROVIDER, { diff --git a/src/domain/evidence.ts b/src/domain/evidence.ts index bcbc959386..789537f564 100644 --- a/src/domain/evidence.ts +++ b/src/domain/evidence.ts @@ -242,13 +242,14 @@ type ExecutionEnvironment = z.infer; export type EvidenceProvider = Readonly>; -export interface EvidenceObservation { +/** Payloads admitted and snapshotted by the ordinary Evidence constructor. */ +export interface EvidenceObservationInput { readonly predicateType?: string; readonly operation: string; - readonly parameters: Readonly>; - readonly result: JsonValue; + readonly parameters: unknown; + readonly result: unknown; readonly analysisProfile?: AnalysisProfileCommitment; - readonly rawResult?: JsonValue; + readonly rawResult?: unknown; readonly confidence?: "observed" | "derived" | "inferred"; readonly authority?: EvidenceAuthority; readonly environment?: ExecutionEnvironment | null; @@ -260,6 +261,13 @@ export interface EvidenceObservation { readonly evidenceLinks?: readonly string[]; } +/** Producer facts that already promise JSON, including cooperative Evidence input. */ +export interface EvidenceObservation extends EvidenceObservationInput { + readonly parameters: Readonly>; + readonly result: JsonValue; + readonly rawResult?: JsonValue; +} + type EvidenceWithoutId = Omit; /** Content committed by an Evidence ID, excluding local request/display metadata. */ @@ -403,11 +411,11 @@ export interface EvidenceCreationOptions { readonly immutable?: boolean; } -/** Build deterministic Evidence from an immutable artifact subject. */ +/** Admit payloads into deterministic Evidence bound to an immutable artifact subject. */ export const createEvidence = ( target: EvidenceSubjectTarget | BinaryTarget | undefined, provider: EvidenceProvider, - observation: EvidenceObservation, + observation: EvidenceObservationInput, options?: EvidenceCreationOptions, ): Evidence => { const { normalized, sharedResult } = normalizeEvidenceObservation( @@ -460,7 +468,7 @@ export function* createImmutableEvidenceSteps( const normalizeEvidenceObservation = ( target: EvidenceSubjectTarget | BinaryTarget | undefined, provider: EvidenceProvider, - observation: EvidenceObservation, + observation: EvidenceObservationInput, ) => { const subject = target === undefined @@ -509,7 +517,7 @@ const normalizeEvidenceObservation = ( : { relationship_coverage: observation.relationshipCoverage }), locations: [...(observation.locations ?? [])], evidence_links: [...(observation.evidenceLinks ?? [])], - } satisfies JsonValue; + }; const sharedResult = typeof observation.result === "object" && observation.result !== null && diff --git a/src/domain/pcap/pcapEvidence.ts b/src/domain/pcap/pcapEvidence.ts index d2379ac75f..14892f533b 100644 --- a/src/domain/pcap/pcapEvidence.ts +++ b/src/domain/pcap/pcapEvidence.ts @@ -1,5 +1,5 @@ import { createEvidence } from "../evidence.js"; -import { jsonObjectSchema, type JsonValue } from "../jsonValue.js"; +import type { JsonValue } from "../jsonValue.js"; import type { PcapRequest } from "./pcapAnalysis.js"; /** Domain facts needed by both successful and retained partial observations. */ @@ -21,7 +21,7 @@ export const createPcapEvidence = ( ) => createEvidence(observation.subject ?? undefined, observation.provider, { operation: request.operation, - parameters: jsonObjectSchema.parse(request.input), + parameters: request.input, result: observation.result, rawResult: observation.rawResult, limitations: observation.limitations, diff --git a/src/domain/process/processComparisonEvidence.ts b/src/domain/process/processComparisonEvidence.ts index 4a27f80f51..2aa42ba9ee 100644 --- a/src/domain/process/processComparisonEvidence.ts +++ b/src/domain/process/processComparisonEvidence.ts @@ -1,5 +1,4 @@ import { createEvidence, type Evidence } from "../evidence.js"; -import { jsonValueSchema } from "../jsonValue.js"; import type { ProcessCapture } from "./processCaptureParsing.js"; import { compareProcessCaptures, @@ -37,9 +36,9 @@ export const compareProcessCaptureEvidence = ( : { max_capture_age_ms: options.maxCaptureAgeMs }), ...(options.traceSpecification === undefined ? {} - : { trace_spec: jsonValueSchema.parse(options.traceSpecification) }), + : { trace_spec: options.traceSpecification }), }, - result: jsonValueSchema.parse(comparison), + result: comparison, confidence: "derived", authority: "analyst-inference", limitations: comparison.limitations, diff --git a/src/server/registerArtifactComparisonTool.ts b/src/server/registerArtifactComparisonTool.ts index 3e9fe67a40..f21ddb8c7c 100644 --- a/src/server/registerArtifactComparisonTool.ts +++ b/src/server/registerArtifactComparisonTool.ts @@ -6,7 +6,6 @@ import { compareArtifacts } from "../domain/artifactComparison.js"; import { ARTIFACT_COMPARISON_PROVIDER } from "../domain/comparisonEvidenceIdentity.js"; import { createEvidence } from "../domain/evidence.js"; import { readEvidence } from "../domain/evidenceValidation.js"; -import { jsonValueSchema } from "../domain/jsonValue.js"; import { resolveArtifactComparisonEvidence } from "../application/artifacts/ArtifactComparisonEvidence.js"; import type { RecordUnknownInput } from "../domain/residualUnknown.js"; import { recordDerivedEvidence } from "./recordDerivedEvidence.js"; @@ -78,7 +77,7 @@ export const registerArtifactComparisonTool = ( left_evidence_ids: leftEvidenceIds, right_evidence_ids: rightEvidenceIds, }, - result: jsonValueSchema.parse(comparison), + result: comparison, confidence: "derived", authority: "analyst-inference", limitations: comparison.limitations, diff --git a/src/server/registerBundleComparisonTool.ts b/src/server/registerBundleComparisonTool.ts index 1a90b3e839..033f98a938 100644 --- a/src/server/registerBundleComparisonTool.ts +++ b/src/server/registerBundleComparisonTool.ts @@ -5,7 +5,6 @@ import { readImmutableEvidenceBundle } from "../application/EvidenceBundleFiles. import { toolContract } from "../contracts/toolContracts.js"; import { compareBundles } from "../domain/bundleComparison.js"; import { createEvidence } from "../domain/evidence.js"; -import { jsonValueSchema } from "../domain/jsonValue.js"; import { runDerivedOperation } from "./runDerivedOperation.js"; import { recordEvidenceSources } from "../application/investigation/recordEvidenceSources.js"; import { BUNDLE_COMPARISON_PROVIDER } from "../domain/investigationProviders.js"; @@ -82,7 +81,7 @@ export const registerBundleComparisonTool = ( right_bundle_sha256: comparison.right_bundle_sha256, record_pairs: input.record_pairs, }, - result: jsonValueSchema.parse(comparison), + result: comparison, confidence: "derived", authority: "analyst-inference", limitations: comparison.limitations, diff --git a/src/server/registerFunctionComparisonTool.ts b/src/server/registerFunctionComparisonTool.ts index 4817c183b5..5c036c4f9a 100644 --- a/src/server/registerFunctionComparisonTool.ts +++ b/src/server/registerFunctionComparisonTool.ts @@ -6,7 +6,6 @@ import { toolContract } from "../contracts/toolContracts.js"; import { createEvidence } from "../domain/evidence.js"; import { parseFunctionEvidence } from "../domain/functionDossierEvidence.js"; import { FUNCTION_COMPARISON_PROVIDER } from "../domain/comparisonEvidenceIdentity.js"; -import { jsonValueSchema } from "../domain/jsonValue.js"; import type { RecordUnknownInput } from "../domain/residualUnknown.js"; import { recordDerivedEvidence } from "./recordDerivedEvidence.js"; import { recordEvidenceSources } from "../application/investigation/recordEvidenceSources.js"; @@ -84,7 +83,7 @@ export const registerFunctionComparisonTool = ( left_evidence_id: leftEvidence.evidence_id, right_evidence_id: rightEvidence.evidence_id, }, - result: jsonValueSchema.parse(comparison), + result: comparison, confidence: "derived", authority: "analyst-inference", limitations: comparison.limitations, diff --git a/src/server/registerInvestigationTools.ts b/src/server/registerInvestigationTools.ts index 689b812e5c..dd211dcbe7 100644 --- a/src/server/registerInvestigationTools.ts +++ b/src/server/registerInvestigationTools.ts @@ -6,7 +6,6 @@ import { toolContract } from "../contracts/toolContracts.js"; import { buildCallPath } from "../domain/callPath.js"; import { findChangedBehavior } from "../domain/changedBehavior.js"; import { createEvidence } from "../domain/evidence.js"; -import { jsonValueSchema } from "../domain/jsonValue.js"; import { correlateStaticAndRuntime } from "../domain/staticRuntimeCorrelation.js"; import { comparisonClosure, @@ -88,7 +87,7 @@ const registerChangedBehavior = ( parameters: { comparison_evidence_ids: [...comparisonEvidenceIds], }, - result: jsonValueSchema.parse(result), + result, confidence: "derived", authority: "analyst-inference", limitations: result.limitations, @@ -161,7 +160,7 @@ const registerCallPath = ( start: input.start.address, goal: input.goal.address, }, - result: jsonValueSchema.parse(result), + result, confidence: "derived", authority: "analyst-inference", limitations: result.limitations, @@ -236,7 +235,7 @@ const registerStaticRuntime = ( parameters: { mapping_count: input.mappings.length, }, - result: jsonValueSchema.parse(result), + result, confidence: "inferred", authority: "analyst-inference", limitations: result.limitations, @@ -311,7 +310,7 @@ const registerReconstruction = ( ({ claim_id: id }) => id, ), }, - result: jsonValueSchema.parse(result), + result, confidence: "derived", authority: "analyst-inference", limitations: result.limitations,