577 lines
20 KiB
TypeScript
577 lines
20 KiB
TypeScript
import { z } from "zod";
|
|
import {
|
|
artifactInventorySummaryViewResultSchema,
|
|
machoSummaryViewResultSchema,
|
|
managedArtifactSummaryViewResultSchema,
|
|
} from "../domain/analysisView/analysisView.js";
|
|
import { evidenceBundleSummarySchema } from "../domain/evidenceRecordSummary.js";
|
|
import { BINARY_ARCHITECTURES } from "../domain/binaryTargetTypes.js";
|
|
import {
|
|
binaryArchitectureSchema,
|
|
rawBinaryEntryPointSchema,
|
|
} from "../domain/rawBinary.js";
|
|
import { nativeFunctionAnnotationsSchema } from "../domain/native/nativeFunctionAnnotations.js";
|
|
import { nativeLoadImageSchema } from "../domain/native/nativeLoadImage.js";
|
|
import { nativeUiResultSchema } from "../domain/native/nativeUiObservation.js";
|
|
import { nativeValueTraceSchema } from "../domain/native/nativeValueTrace.js";
|
|
import { nativeDataTypeSchema } from "../domain/native/nativeDataType.js";
|
|
import { nativeCallObservationResultSchema } from "../domain/native/nativeCallObservation.js";
|
|
import {
|
|
nativeInstructionSchema,
|
|
nativeCallTargetsSchema,
|
|
} from "../domain/native/nativeInstruction.js";
|
|
import { jsonValueSchema } from "../domain/jsonValue.js";
|
|
import { residualUnknownSchema } from "../domain/residualUnknown.js";
|
|
import { evidenceBundleSchema } from "../domain/evidenceBundle.js";
|
|
|
|
import { processCaptureComparisonSchema } from "../domain/process/processComparison.js";
|
|
import {
|
|
analysisBookmarkSchema,
|
|
functionInstructionWindowSchema,
|
|
referenceEdgeSchema,
|
|
unresolvedCallSchema,
|
|
analysisStringSchema,
|
|
procedureIdentitySchema,
|
|
} from "../domain/hopperValues.js";
|
|
import { nativeApiInspectionResultSchema } from "../domain/native/nativeApiBoundary.js";
|
|
import {
|
|
demangleSwiftSchema,
|
|
inspectMachoSchema,
|
|
inspectPlistSchema,
|
|
inspectSignatureSchema,
|
|
listArchitecturesSchema,
|
|
} from "../domain/native/nativeInspection.js";
|
|
import { artifactExtractionResultSchema } from "../domain/artifactGraph.js";
|
|
import { artifactInspectionOutputSchema } from "../domain/artifactInspection.js";
|
|
import { interfaceBuilderAnalysisSchema } from "../domain/apple/interfaceBuilderGraph.js";
|
|
import { dylibResolutionResultSchema } from "../domain/apple/dylibResolution.js";
|
|
import { keyedArchiveResultSchema } from "../domain/apple/keyedArchive.js";
|
|
import { appleAssetCatalogResultSchema } from "../domain/apple/appleAssetCatalog.js";
|
|
import {
|
|
managedArtifactInspectionSchema,
|
|
managedMemberInspectionSchema,
|
|
managedNativeBoundaryInspectionSchema,
|
|
} from "../domain/managed/managedArtifact.js";
|
|
import { managedMemberComparisonResultSchema } from "../domain/managed/managedMemberComparison.js";
|
|
import { managedNativeVerificationResultSchema } from "../domain/managed/managedNativeVerificationSchemas.js";
|
|
import { managedReconstructionImportResultSchema } from "../domain/managed/managedReconstruction.js";
|
|
import { managedApplicationGraphResultSchema } from "../domain/managed/managedApplicationGraph.js";
|
|
import { artifactComparisonResultSchema } from "../domain/artifactComparison.js";
|
|
import { functionComparisonResultSchema } from "../domain/functionComparisonSchemas.js";
|
|
import { bundleComparisonResultSchema } from "../domain/bundleComparison.js";
|
|
import { changedBehaviorResultSchema } from "../domain/changedBehavior.js";
|
|
import { callPathResultSchema } from "../domain/callPathSchemas.js";
|
|
import { staticRuntimeCorrelationResultSchema } from "../domain/staticRuntimeCorrelation.js";
|
|
import { reconstructionVerificationResultSchema } from "../domain/reconstructionVerificationSchemas.js";
|
|
import { analysisErrorProjectionSchema } from "./errorSchemas.js";
|
|
import { relationshipCoverageSchema } from "../domain/relationshipCoverage.js";
|
|
import { nativeDispatchMetadataResultSchema } from "../domain/native/objcSwiftMetadata.js";
|
|
import { nativeInvestigationTraceSchema } from "../domain/native/nativeInvestigationGraph.js";
|
|
import {
|
|
addressList,
|
|
addressedValue,
|
|
addressedEntry,
|
|
containingProcedureResolution,
|
|
functionDossierOutput,
|
|
graphNode,
|
|
lifecycleResultOf,
|
|
nullableText,
|
|
procedureInfoOutput,
|
|
evidenceResultOf,
|
|
segmentOutput,
|
|
sessionProvider,
|
|
symbolDiscoveryOutput,
|
|
targetFormatSchema,
|
|
targetKindSchema,
|
|
} from "./toolOutputSchemaPrimitives.js";
|
|
|
|
import { processCaptureSchema } from "../domain/process/processCapture.js";
|
|
const contextFacetSchema = z.discriminatedUnion("state", [
|
|
z.object({ state: z.literal("available"), value: jsonValueSchema }),
|
|
z.object({
|
|
state: z.literal("unavailable"),
|
|
reason: z.string(),
|
|
remediation: z.string(),
|
|
}),
|
|
]);
|
|
const bookmarkFacetSchema = z.discriminatedUnion("state", [
|
|
z.object({
|
|
state: z.literal("available"),
|
|
value: z.array(analysisBookmarkSchema),
|
|
}),
|
|
z.object({
|
|
state: z.literal("unavailable"),
|
|
reason: z.string(),
|
|
remediation: z.string(),
|
|
}),
|
|
]);
|
|
|
|
/** Exact structured-content schemas shared by direct analysis providers. */
|
|
export const officialOutputSchemas: Readonly<Record<string, z.ZodObject>> = {
|
|
annotate_native_function: evidenceResultOf(nativeFunctionAnnotationsSchema),
|
|
inspect_native_load_image: evidenceResultOf(nativeLoadImageSchema),
|
|
inspect_native_data_type: evidenceResultOf(nativeDataTypeSchema),
|
|
inspect_native_instruction: evidenceResultOf(nativeInstructionSchema),
|
|
resolve_native_call_targets: evidenceResultOf(nativeCallTargetsSchema),
|
|
address_name: evidenceResultOf(nullableText),
|
|
comment: evidenceResultOf(nullableText),
|
|
current_address: evidenceResultOf(z.string()),
|
|
current_procedure: evidenceResultOf(z.string()),
|
|
current_document: evidenceResultOf(z.string()),
|
|
goto_address: evidenceResultOf(z.string()),
|
|
inline_comment: evidenceResultOf(nullableText),
|
|
list_bookmarks: evidenceResultOf(z.array(analysisBookmarkSchema)),
|
|
list_documents: evidenceResultOf(z.array(z.string())),
|
|
list_names: evidenceResultOf(z.array(addressedValue)),
|
|
list_procedures: evidenceResultOf(z.array(addressedValue)),
|
|
list_segments: segmentOutput,
|
|
list_strings: evidenceResultOf(z.array(analysisStringSchema)),
|
|
next_address: evidenceResultOf(z.string()),
|
|
prev_address: evidenceResultOf(z.string()),
|
|
procedure_address: evidenceResultOf(z.string()),
|
|
procedure_assembly: evidenceResultOf(z.string()),
|
|
procedure_callees: evidenceResultOf(addressList),
|
|
procedure_callers: evidenceResultOf(addressList),
|
|
procedure_info: procedureInfoOutput,
|
|
read_function_instructions: evidenceResultOf(functionInstructionWindowSchema),
|
|
read_bytes: evidenceResultOf(
|
|
z.object({
|
|
address: z.string(),
|
|
requested_bytes: z.number().int().min(1),
|
|
returned_bytes: z.number().int().min(0),
|
|
bytes_hex: z.string().regex(/^(?:[a-f0-9]{2})*$/u),
|
|
complete: z.boolean(),
|
|
}),
|
|
),
|
|
address_to_file_offset: evidenceResultOf(
|
|
z.object({
|
|
address: z.string(),
|
|
file_offset: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER),
|
|
provider_file_offset: z
|
|
.number()
|
|
.int()
|
|
.min(0)
|
|
.max(Number.MAX_SAFE_INTEGER)
|
|
.exactOptional()
|
|
.describe(
|
|
"Original coordinate returned by the provider's mapping API.",
|
|
),
|
|
image_base_file_offset: z
|
|
.number()
|
|
.int()
|
|
.min(0)
|
|
.max(Number.MAX_SAFE_INTEGER)
|
|
.exactOptional()
|
|
.describe(
|
|
"File offset of the loaded image within its source container; zero for a thin executable.",
|
|
),
|
|
source_path: z
|
|
.string()
|
|
.exactOptional()
|
|
.describe(
|
|
"Observed original executable path used to verify the file mapping.",
|
|
),
|
|
}),
|
|
),
|
|
procedure_references: evidenceResultOf(
|
|
z.object({
|
|
procedure: procedureIdentitySchema,
|
|
direction: z.enum(["incoming", "outgoing"]),
|
|
reference_kinds_available: z.boolean(),
|
|
unresolved_calls: z.array(unresolvedCallSchema),
|
|
references: z.array(referenceEdgeSchema),
|
|
}),
|
|
),
|
|
procedure_pseudo_code: evidenceResultOf(nullableText),
|
|
resolve_containing_procedure: evidenceResultOf(containingProcedureResolution),
|
|
search_procedures: evidenceResultOf(
|
|
z.array(z.object({ address: z.string(), value: z.string() })),
|
|
),
|
|
search_strings: evidenceResultOf(z.array(analysisStringSchema)),
|
|
set_address_name: evidenceResultOf(z.boolean()),
|
|
set_addresses_names: evidenceResultOf(z.record(z.string(), z.boolean())),
|
|
set_bookmark: evidenceResultOf(z.boolean()),
|
|
set_comment: evidenceResultOf(z.boolean()),
|
|
set_inline_comment: evidenceResultOf(z.boolean()),
|
|
unset_bookmark: evidenceResultOf(z.boolean()),
|
|
xrefs: evidenceResultOf(addressList),
|
|
};
|
|
|
|
const literalTraceOutput = evidenceResultOf(
|
|
z.object({
|
|
query: z.string(),
|
|
search_mode: z.literal("literal"),
|
|
matches: z.array(
|
|
z.object({
|
|
type: z.enum(["string", "procedure"]),
|
|
address: z.string(),
|
|
value: z.string(),
|
|
}),
|
|
),
|
|
references: z.array(
|
|
z.object({
|
|
target_address: z.string(),
|
|
source_address: z.string(),
|
|
containing_procedure: containingProcedureResolution,
|
|
}),
|
|
),
|
|
truncated: z.boolean(),
|
|
residual_unknowns: z.array(z.string()),
|
|
}),
|
|
);
|
|
|
|
const callPathTraceOutput = evidenceResultOf(
|
|
z.object({
|
|
start: z.string(),
|
|
goal: z.string().nullable(),
|
|
direction: z.enum(["forward", "backward"]),
|
|
goal_status: z.enum(["not_requested", "reached", "not_reached", "unknown"]),
|
|
nodes: z.array(
|
|
z.object({
|
|
address: z.string(),
|
|
depth: z.number().int().min(0),
|
|
}),
|
|
),
|
|
edges: z.array(
|
|
z.object({
|
|
source_address: z.string(),
|
|
target_address: z.string(),
|
|
discovery_depth: z.number().int().min(1),
|
|
}),
|
|
),
|
|
traversal_path: z.array(z.string()),
|
|
failures: z.array(
|
|
z.object({
|
|
address: z.string(),
|
|
error: analysisErrorProjectionSchema,
|
|
}),
|
|
),
|
|
relationship_coverage: z.record(z.string(), relationshipCoverageSchema),
|
|
traversal: z.object({
|
|
nodes_visited: z.number().int().min(1),
|
|
}),
|
|
truncated: z.boolean(),
|
|
residual_unknowns: z.array(z.string()),
|
|
limitations: z.array(z.string()),
|
|
}),
|
|
);
|
|
|
|
/** Identity facts attached to one requested batch selector. */
|
|
const batchProcedureIdentity = z.discriminatedUnion("status", [
|
|
z.object({
|
|
status: z.literal("resolved"),
|
|
address: z.string().min(1).describe("Observed canonical procedure entry."),
|
|
name: z
|
|
.string()
|
|
.nullable()
|
|
.describe("Provider's entry label, or null when unavailable."),
|
|
name_error: analysisErrorProjectionSchema.optional(),
|
|
}),
|
|
z.object({
|
|
status: z.literal("unknown"),
|
|
error: analysisErrorProjectionSchema,
|
|
}),
|
|
]);
|
|
|
|
/** Exact structured-content schemas for composed analysis workflows. */
|
|
export const enhancedOutputSchemas: Readonly<Record<string, z.ZodObject>> = {
|
|
inspect_native_dispatch_metadata: evidenceResultOf(
|
|
nativeDispatchMetadataResultSchema,
|
|
),
|
|
trace_native_values: evidenceResultOf(nativeValueTraceSchema),
|
|
trace_native_ui_action: evidenceResultOf(nativeInvestigationTraceSchema),
|
|
get_objc_classes: symbolDiscoveryOutput("classes"),
|
|
get_objc_protocols: symbolDiscoveryOutput("protocols"),
|
|
batch_decompile: evidenceResultOf(
|
|
z.object({
|
|
items: z.array(
|
|
z.discriminatedUnion("status", [
|
|
z.object({
|
|
address: z
|
|
.string()
|
|
.describe("Original caller-selected symbol or address."),
|
|
procedure: batchProcedureIdentity,
|
|
status: z.literal("ok"),
|
|
pseudocode: z.string().min(1),
|
|
}),
|
|
z.object({
|
|
address: z
|
|
.string()
|
|
.describe("Original caller-selected symbol or address."),
|
|
procedure: batchProcedureIdentity,
|
|
status: z.literal("error"),
|
|
error: analysisErrorProjectionSchema,
|
|
}),
|
|
]),
|
|
),
|
|
total: z.number().int().min(0),
|
|
succeeded: z.number().int().min(0),
|
|
failed: z.number().int().min(0),
|
|
}),
|
|
),
|
|
get_call_graph: evidenceResultOf(
|
|
z.strictObject({
|
|
graph: z.record(z.string(), z.array(graphNode)),
|
|
limitations: z.array(z.string()),
|
|
}),
|
|
),
|
|
analyze_swift_types: evidenceResultOf(
|
|
z.object({
|
|
total: z.number().int().min(0),
|
|
categories: z.record(
|
|
z.string(),
|
|
z.object({
|
|
count: z.number().int().min(0),
|
|
items: z.array(
|
|
addressedEntry.extend({
|
|
mangled_names: z.array(z.string()),
|
|
}),
|
|
),
|
|
}),
|
|
),
|
|
unclassified: z.array(
|
|
addressedEntry.extend({
|
|
mangled_names: z.array(z.string()),
|
|
reason: z.enum(["category_not_decoded", "conflicting_categories"]),
|
|
}),
|
|
),
|
|
limitations: z.array(z.string()),
|
|
symbol_inventory_error: analysisErrorProjectionSchema.exactOptional(),
|
|
}),
|
|
),
|
|
find_xrefs_to_name: evidenceResultOf(
|
|
z.discriminatedUnion("status", [
|
|
z.object({
|
|
status: z.literal("resolved"),
|
|
name: z.string(),
|
|
address: z.string(),
|
|
xrefs: addressList,
|
|
}),
|
|
z.object({
|
|
status: z.literal("unresolved"),
|
|
name: z.string(),
|
|
reason: z.literal("name_not_found"),
|
|
}),
|
|
]),
|
|
),
|
|
binary_overview: evidenceResultOf(
|
|
z.object({
|
|
document: z.string(),
|
|
image_base: z.string().min(1).optional(),
|
|
segments: z.array(
|
|
z.object({
|
|
name: z.string(),
|
|
start: z.string(),
|
|
end: z.string(),
|
|
length: z.number().min(0),
|
|
image_base: z.string().exactOptional(),
|
|
address_space: z.string().exactOptional(),
|
|
}),
|
|
),
|
|
segment_count: z.number().int().min(0),
|
|
procedure_count: z.number().int().min(0),
|
|
string_count: z.number().int().min(0),
|
|
}),
|
|
),
|
|
analyze_function: functionDossierOutput,
|
|
inspect_native_api: evidenceResultOf(nativeApiInspectionResultSchema),
|
|
trace_feature: literalTraceOutput,
|
|
trace_call_path: callPathTraceOutput,
|
|
};
|
|
|
|
/** Exact Evidence schemas for provider-neutral native inspection. */
|
|
export const nativeOutputSchemas: Readonly<Record<string, z.ZodObject>> = {
|
|
observe_native_ui: evidenceResultOf(nativeUiResultSchema),
|
|
capture_native_ui_scenario: evidenceResultOf(nativeUiResultSchema),
|
|
observe_native_calls: evidenceResultOf(nativeCallObservationResultSchema),
|
|
inspect_macho: evidenceResultOf(
|
|
z.union([inspectMachoSchema, machoSummaryViewResultSchema]),
|
|
),
|
|
inspect_signature: evidenceResultOf(inspectSignatureSchema),
|
|
inspect_plist: evidenceResultOf(inspectPlistSchema),
|
|
list_architectures: evidenceResultOf(listArchitecturesSchema),
|
|
demangle_swift: evidenceResultOf(demangleSwiftSchema),
|
|
};
|
|
|
|
/** Exact Evidence schemas for provider-neutral artifact graph operations. */
|
|
export const artifactOutputSchemas: Readonly<Record<string, z.ZodObject>> = {
|
|
inspect_artifact: evidenceResultOf(
|
|
z.union([
|
|
artifactInspectionOutputSchema,
|
|
artifactInventorySummaryViewResultSchema,
|
|
]),
|
|
),
|
|
extract_artifact: evidenceResultOf(artifactExtractionResultSchema),
|
|
decode_interface_builder: evidenceResultOf(interfaceBuilderAnalysisSchema),
|
|
inspect_keyed_archive: evidenceResultOf(keyedArchiveResultSchema),
|
|
inspect_asset_catalog: evidenceResultOf(appleAssetCatalogResultSchema),
|
|
trace_dylib_resolution: evidenceResultOf(dylibResolutionResultSchema),
|
|
};
|
|
|
|
/** Exact Evidence schema for execution-free managed static analysis. */
|
|
export const managedOutputSchemas: Readonly<Record<string, z.ZodObject>> = {
|
|
inspect_managed_artifact: evidenceResultOf(
|
|
z.union([
|
|
managedArtifactInspectionSchema,
|
|
managedArtifactSummaryViewResultSchema,
|
|
]),
|
|
),
|
|
inspect_managed_members: evidenceResultOf(managedMemberInspectionSchema),
|
|
inspect_managed_native_boundaries: evidenceResultOf(
|
|
managedNativeBoundaryInspectionSchema,
|
|
),
|
|
};
|
|
|
|
/** Exact Evidence schema for provider-neutral managed workflows. */
|
|
export const managedWorkflowOutputSchemas: Readonly<
|
|
Record<string, z.ZodObject>
|
|
> = {
|
|
compare_managed_members: evidenceResultOf(
|
|
managedMemberComparisonResultSchema,
|
|
),
|
|
verify_managed_native_boundaries: evidenceResultOf(
|
|
managedNativeVerificationResultSchema,
|
|
),
|
|
import_managed_reconstruction: evidenceResultOf(
|
|
managedReconstructionImportResultSchema,
|
|
),
|
|
project_managed_application_graph: evidenceResultOf(
|
|
managedApplicationGraphResultSchema,
|
|
),
|
|
};
|
|
|
|
const lifecycleTargetFields = {
|
|
path: z.string(),
|
|
kind: targetKindSchema,
|
|
sha256: z.string().regex(/^[a-f0-9]{64}$/u),
|
|
architecture: z.enum(BINARY_ARCHITECTURES).nullable(),
|
|
};
|
|
const detectedLifecycleTargetSchema = z.object({
|
|
...lifecycleTargetFields,
|
|
format: targetFormatSchema.exclude(["raw-binary"]),
|
|
});
|
|
const rawLifecycleTargetSchema = z.object({
|
|
...lifecycleTargetFields,
|
|
format: z.literal("raw-binary"),
|
|
kind: z.literal("executable"),
|
|
architecture: binaryArchitectureSchema,
|
|
entry_point: rawBinaryEntryPointSchema.describe(
|
|
"Canonical caller-selected address where raw file offset 0 is mapped and execution is seeded.",
|
|
),
|
|
});
|
|
|
|
/** Exact structured-content schemas for target lifecycle operations. */
|
|
export const sessionOutputSchemas = {
|
|
open_binary: lifecycleResultOf(
|
|
z.discriminatedUnion("format", [
|
|
detectedLifecycleTargetSchema,
|
|
rawLifecycleTargetSchema,
|
|
]),
|
|
),
|
|
close_binary: lifecycleResultOf(
|
|
z.union([
|
|
z.null(),
|
|
z.object({
|
|
path: z.string(),
|
|
bytes: z.number().int().min(0),
|
|
primitive_entries: z
|
|
.number()
|
|
.int()
|
|
.min(0)
|
|
.describe("Retained eligible primitive query bindings."),
|
|
workflow_entries: z
|
|
.number()
|
|
.int()
|
|
.min(0)
|
|
.describe("Retained eligible composed workflow bindings."),
|
|
evidence_records: z
|
|
.number()
|
|
.int()
|
|
.min(0)
|
|
.describe(
|
|
"All retained Evidence records, including observations without replay bindings.",
|
|
),
|
|
}),
|
|
]),
|
|
),
|
|
binary_session: lifecycleResultOf(
|
|
z.union([
|
|
sessionProvider.extend({ open: z.literal(false) }),
|
|
sessionProvider.extend({
|
|
open: z.literal(true),
|
|
...detectedLifecycleTargetSchema.shape,
|
|
}),
|
|
sessionProvider.extend({
|
|
open: z.literal(true),
|
|
...rawLifecycleTargetSchema.shape,
|
|
}),
|
|
]),
|
|
),
|
|
export_evidence_bundle: lifecycleResultOf(
|
|
z.object({
|
|
path: z.string(),
|
|
bytes: z.number().int().min(0),
|
|
records: z.number().int().min(0),
|
|
unknowns: z.number().int().min(0),
|
|
}),
|
|
),
|
|
get_evidence_bundle: lifecycleResultOf(
|
|
z.union([evidenceBundleSchema, evidenceBundleSummarySchema]),
|
|
),
|
|
get_navigation_context: lifecycleResultOf(
|
|
z.object({
|
|
document: z.string(),
|
|
address: z.string(),
|
|
procedure: z.union([z.string(), z.null()]),
|
|
}),
|
|
),
|
|
inspect_address_context: lifecycleResultOf(
|
|
z.object({
|
|
address: z.string(),
|
|
document: z.string().nullable(),
|
|
name: contextFacetSchema,
|
|
procedure: contextFacetSchema,
|
|
comment: contextFacetSchema,
|
|
inline_comment: contextFacetSchema,
|
|
bookmarks: bookmarkFacetSchema,
|
|
}),
|
|
),
|
|
import_evidence_bundle: lifecycleResultOf(
|
|
z.object({
|
|
imported: z.number().int().min(0),
|
|
unknowns_added: z.number().int().min(0),
|
|
total: z.number().int().min(0),
|
|
}),
|
|
),
|
|
capture_process_scenario: evidenceResultOf(processCaptureSchema),
|
|
compare_process_captures: evidenceResultOf(processCaptureComparisonSchema),
|
|
compare_artifacts: evidenceResultOf(artifactComparisonResultSchema),
|
|
compare_functions: evidenceResultOf(functionComparisonResultSchema),
|
|
compare_bundles: evidenceResultOf(bundleComparisonResultSchema),
|
|
find_changed_behavior: evidenceResultOf(changedBehaviorResultSchema),
|
|
build_call_path: evidenceResultOf(callPathResultSchema),
|
|
correlate_static_and_runtime: evidenceResultOf(
|
|
staticRuntimeCorrelationResultSchema,
|
|
),
|
|
verify_reconstruction: evidenceResultOf(
|
|
reconstructionVerificationResultSchema,
|
|
),
|
|
list_unknowns: lifecycleResultOf(
|
|
z.object({
|
|
items: z.array(residualUnknownSchema),
|
|
total: z.number().int().min(0),
|
|
offset: z.number().int().min(0),
|
|
next_offset: z.number().int().min(0).nullable(),
|
|
}),
|
|
),
|
|
record_unknown: lifecycleResultOf(residualUnknownSchema),
|
|
update_unknown: lifecycleResultOf(residualUnknownSchema),
|
|
verify_unknown_resolution: lifecycleResultOf(
|
|
z.object({
|
|
valid: z.boolean(),
|
|
truthVerified: z.boolean(),
|
|
unknown: residualUnknownSchema,
|
|
}),
|
|
),
|
|
} satisfies Readonly<Record<string, z.ZodObject>>;
|