import { z } from "zod"; import { emptyArraySchema } from "./emptyArraySchema.js"; import { evidenceSchema } from "./evidence.js"; import { cliMetadataGuidSchema } from "./managedArtifact.js"; import { digestSchema } from "./../domain/digests.js"; import { prefixedDigestSchema } from "./../domain/digests.js"; const evidenceIdSchema = prefixedDigestSchema("ev"); const tokenSchema = z.string().regex(/^0x[0-9a-f]{8}$/u); const textSchema = z.string().min(1); const nativeSymbolSchema = z.strictObject({ evidence_id: evidenceIdSchema, operation: z.string().min(1), name: z.string().min(1), address: z.string().nullable(), module_name: z.string().nullable(), module_path: z.string().nullable(), source: z.enum(["macho-export", "function-dossier"]), }); export type NativeSymbol = z.infer; const pinvokeVerificationContextShape = { item_id: prefixedDigestSchema("mnv_pinvoke"), managed: z.strictObject({ token: tokenSchema, member_token: tokenSchema.nullable(), member_name: z.string().nullable(), import_name: z.string().min(1), import_scope_name: z.string().nullable(), no_mangle: z.boolean(), char_set: z.enum(["not-specified", "ansi", "unicode", "auto", "unknown"]), call_convention: z.enum([ "not-specified", "winapi", "cdecl", "stdcall", "thiscall", "fastcall", "unknown", ]), declaration_verification: z.literal("managed-declaration-only"), }), evidence_links: z.array(evidenceIdSchema).min(1), limitations: z.array(textSchema), }; const observedCandidatesSchema = z .tuple([nativeSymbolSchema]) .rest(nativeSymbolSchema); export const pinvokeVerificationSchema = z.discriminatedUnion("status", [ z.strictObject({ ...pinvokeVerificationContextShape, status: z.literal("verified"), basis: z.enum(["exact-export-name", "exact-function-name"]), confidence: z.literal("observed"), matched_native: nativeSymbolSchema, candidates: observedCandidatesSchema, }), z.strictObject({ ...pinvokeVerificationContextShape, status: z.literal("inferred"), basis: z.literal("decorated-name-candidate"), confidence: z.literal("inferred"), matched_native: nativeSymbolSchema, candidates: observedCandidatesSchema, }), z.strictObject({ ...pinvokeVerificationContextShape, status: z.literal("unresolved"), basis: z.enum(["no-native-candidate", "unsupported-native-evidence"]), confidence: z.literal("unknown"), matched_native: z.null(), candidates: emptyArraySchema, }), z.strictObject({ ...pinvokeVerificationContextShape, status: z.literal("contradicted"), basis: z.literal("module-mismatch"), confidence: z.literal("unknown"), matched_native: nativeSymbolSchema, candidates: observedCandidatesSchema, }), ]); export type PinvokeVerification = z.infer; /** Authenticated managed boundary Evidence plus native observations. */ export const managedNativeVerificationInputSchema = z .strictObject({ managed_boundaries: evidenceSchema, native_observations: z.array(evidenceSchema).min(1), }) .superRefine((input, context) => { const ids = new Set(); for (const [index, evidence] of input.native_observations.entries()) { if (evidence.evidence_id === input.managed_boundaries.evidence_id) { context.addIssue({ code: "custom", path: ["native_observations", index], message: "Native observation Evidence must be distinct from managed boundary Evidence", }); } if (ids.has(evidence.evidence_id)) { context.addIssue({ code: "custom", path: ["native_observations", index], message: "Native observation Evidence IDs must be unique", }); } ids.add(evidence.evidence_id); } }); export type ManagedNativeVerificationInput = z.infer< typeof managedNativeVerificationInputSchema >; const verificationCoverageSchema = z.strictObject({ status: z.enum(["complete-within-inputs", "partial"]), }); /** Provider-neutral managed/native verification result. */ export const managedNativeVerificationResultSchema = z .strictObject({ verification_id: prefixedDigestSchema("mnv"), algorithm: z.strictObject({ name: z.literal("rea-managed-native-verification"), token_identity: z.literal("build-local"), token_to_address_mapping: z.literal("not-inferred"), }), managed_boundary: z.strictObject({ evidence_id: evidenceIdSchema, artifact_sha256: digestSchema, artifact_path: z.string().min(1), mvid: cliMetadataGuidSchema.nullable(), metadata_status: z.enum(["absent", "complete", "partial", "malformed"]), pinvoke_imports_total: z.number().int().min(0), native_implementations_total: z.number().int().min(0), coverage_state: z.enum(["complete", "partial", "unavailable"]), }), native_observations: z.strictObject({ total: z.number().int().min(1), accepted: z.number().int().min(0), unsupported: z.number().int().min(0), symbols: z.number().int().min(0), }), summary: z.strictObject({ verified: z.number().int().min(0), inferred: z.number().int().min(0), unresolved: z.number().int().min(0), contradicted: z.number().int().min(0), native_body_unresolved: z.number().int().min(0), }), pinvoke_imports: z.array(pinvokeVerificationSchema), native_implementations: z.strictObject({ unresolved: z.number().int().min(0), reason: textSchema, }), coverage: verificationCoverageSchema, evidence_links: z.array(evidenceIdSchema).min(2), limitations: z.array(textSchema), }) .superRefine((result, context) => { const observedNativeCount = result.native_observations.accepted + result.native_observations.unsupported; if (observedNativeCount !== result.native_observations.total) context.addIssue({ code: "custom", path: ["native_observations"], message: "Native observation counts must account for the total input", }); for (const status of [ "verified", "inferred", "unresolved", "contradicted", ] as const) if ( result.summary[status] !== result.pinvoke_imports.filter((item) => item.status === status).length ) context.addIssue({ code: "custom", path: ["summary", status], message: `P/Invoke ${status} count must match the item results`, }); if ( result.summary.native_body_unresolved !== result.native_implementations.unresolved ) context.addIssue({ code: "custom", path: ["summary", "native_body_unresolved"], message: "Native body summary must match unresolved implementations", }); }); export type ManagedNativeVerificationResult = z.infer< typeof managedNativeVerificationResultSchema >;