refactor(managed): derive verification declaration facts from their owner

This commit is contained in:
morluto committed 2026-10-22 10:19:16 +08:00
1 parent 306ca984bc
commit 81ab0ddc95
3 files changed
+46 -21

No files matched your search

+1 -1
View File
@@ -277,7 +277,7 @@ const managedModuleReferenceSchema = z.object({
name: z.string(),
});
const managedNativeImportSchema = z.object({
export const managedNativeImportSchema = z.object({
token: managedMetadataTokenSchema,
row_offset: offsetSchema,
mapping_flags: z.number().int().min(0).max(0xffff),
@@ -4,7 +4,7 @@ import { emptyArraySchema } from "../emptyArraySchema.js";
import { evidenceSchema } from "../evidence.js";
import {
cliMetadataGuidSchema,
managedMetadataTokenSchema,
managedNativeImportSchema,
} from "./managedArtifact.js";
import { digestSchema } from "../digests.js";
import { prefixedDigestSchema } from "../digests.js";
@@ -24,27 +24,26 @@ const nativeSymbolSchema = z.strictObject({
export type NativeSymbol = z.infer<typeof nativeSymbolSchema>;
const verifiedManagedDeclarationSchema = managedNativeImportSchema
.pick({
token: true,
member_token: true,
member_name: true,
import_name: true,
import_scope_name: true,
no_mangle: true,
char_set: true,
call_convention: true,
})
.extend({
import_name: z.string().min(1),
declaration_verification: managedNativeImportSchema.shape.verification,
})
.strict();
const pinvokeVerificationContextShape = {
item_id: prefixedDigestSchema("mnv_pinvoke"),
managed: z.strictObject({
token: managedMetadataTokenSchema,
member_token: managedMetadataTokenSchema.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"),
}),
managed: verifiedManagedDeclarationSchema,
evidence_links: z.array(evidenceIdSchema).min(1),
limitations: z.array(textSchema),
};
@@ -6,6 +6,7 @@ import { createEvidence } from "../../../../src/domain/evidence.js";
import {
managedNativeVerificationInputSchema,
managedNativeVerificationResultSchema,
pinvokeVerificationSchema,
} from "../../../../src/domain/managed/managedNativeVerificationSchemas.js";
import { managedNativeBoundaryInspectionSchema } from "../../../../src/domain/managed/managedArtifact.js";
import { inspectMachoSchema } from "../../../../src/domain/native/nativeInspection.js";
@@ -89,6 +90,31 @@ const inputWithImportScope = (scope: string | null) => {
};
};
it("keeps empty import names readable in managed Evidence but invalid in verification output", () => {
const input = exampleInput();
const parsed = managedNativeBoundaryInspectionSchema.parse(
input.managed_boundaries.normalized_result,
);
const declaration = parsed.pinvoke_imports[0];
if (declaration === undefined) throw new Error("missing P/Invoke example");
const historicalBoundary = managedNativeBoundaryInspectionSchema.parse({
...parsed,
pinvoke_imports: [{ ...declaration, import_name: "" }],
});
expect(historicalBoundary.pinvoke_imports[0]?.import_name).toBe("");
const verification = verifyManagedNativeBoundaries(input).pinvoke_imports[0];
if (verification === undefined)
throw new Error("missing verification result");
expect(
pinvokeVerificationSchema.safeParse({
...verification,
managed: { ...verification.managed, import_name: "" },
}).success,
).toBe(false);
});
describe("managed/native boundary Evidence identity", () => {
it("rejects managed boundary Evidence whose subject digest differs from its artifact", () => {
const input = exampleInput();