mirror of
https://github.com/morluto/rea.git
synced 2026-11-08 08:11:31 -10:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ec9339b4b |
No files matched your search
@@ -20,12 +20,16 @@ export const collectNativeSymbols = (
|
||||
readonly symbols: readonly NativeSymbol[];
|
||||
readonly accepted: number;
|
||||
readonly unsupported: number;
|
||||
readonly partialExports: boolean;
|
||||
readonly exportLimitations: readonly string[];
|
||||
readonly moduleFormatsByEvidenceId: ReadonlyMap<string, string | null>;
|
||||
} => {
|
||||
const symbols: NativeSymbol[] = [];
|
||||
const moduleFormatsByEvidenceId = new Map<string, string | null>();
|
||||
let accepted = 0;
|
||||
let unsupported = 0;
|
||||
let partialExports = false;
|
||||
const exportLimitations: string[] = [];
|
||||
for (const observation of observations) {
|
||||
moduleFormatsByEvidenceId.set(
|
||||
observation.evidence.evidence_id,
|
||||
@@ -36,9 +40,23 @@ export const collectNativeSymbols = (
|
||||
} else {
|
||||
accepted += 1;
|
||||
symbols.push(...observation.symbols);
|
||||
if (observation.exportCoverage !== undefined) {
|
||||
if (!observation.exportCoverage.exhaustive) partialExports = true;
|
||||
for (const limitation of observation.exportCoverage.limitations)
|
||||
exportLimitations.push(
|
||||
`Native export Evidence ${observation.evidence.evidence_id}: ${limitation}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return { symbols, accepted, unsupported, moduleFormatsByEvidenceId };
|
||||
return {
|
||||
symbols,
|
||||
accepted,
|
||||
unsupported,
|
||||
partialExports,
|
||||
exportLimitations,
|
||||
moduleFormatsByEvidenceId,
|
||||
};
|
||||
};
|
||||
|
||||
/** P/Invoke resolves a Mach-O export through dlsym, which names it without the symbol-table prefix. */
|
||||
@@ -516,6 +534,8 @@ interface VerificationResultInput {
|
||||
readonly symbols: readonly NativeSymbol[];
|
||||
readonly accepted: number;
|
||||
readonly unsupported: number;
|
||||
readonly partialExports: boolean;
|
||||
readonly exportLimitations: readonly string[];
|
||||
};
|
||||
readonly pinvokeImports: readonly PinvokeVerification[];
|
||||
readonly nativeObservationCount: number;
|
||||
@@ -540,7 +560,9 @@ export const buildVerificationResult = ({
|
||||
).length;
|
||||
const coverage: ManagedNativeVerificationResult["coverage"] = {
|
||||
status:
|
||||
managed.coverage.state === "complete" && native.unsupported === 0
|
||||
managed.coverage.state === "complete" &&
|
||||
native.unsupported === 0 &&
|
||||
!native.partialExports
|
||||
? "complete-within-inputs"
|
||||
: "partial",
|
||||
};
|
||||
@@ -594,6 +616,10 @@ export const buildVerificationResult = ({
|
||||
: [
|
||||
"Some native Evidence operations were unsupported by this workflow.",
|
||||
]),
|
||||
...(native.partialExports
|
||||
? ["Some native export inventories are not exhaustive."]
|
||||
: []),
|
||||
...native.exportLimitations,
|
||||
],
|
||||
};
|
||||
};
|
||||
@@ -34,6 +34,11 @@ export interface ManagedNativeObservationFacts {
|
||||
readonly evidence: Evidence;
|
||||
readonly symbols: readonly NativeSymbol[];
|
||||
readonly supported: boolean;
|
||||
/** Coverage of an export inventory; function observations are targeted. */
|
||||
readonly exportCoverage?: {
|
||||
readonly exhaustive: boolean;
|
||||
readonly limitations: readonly string[];
|
||||
};
|
||||
}
|
||||
|
||||
const inputFailure = (
|
||||
@@ -62,6 +67,10 @@ const readNativeObservation = (
|
||||
return ok({
|
||||
evidence,
|
||||
supported: true,
|
||||
exportCoverage: {
|
||||
exhaustive: payload.value.exports.exhaustive,
|
||||
limitations: payload.value.exports.limitations,
|
||||
},
|
||||
symbols: payload.value.exports.items.map((symbol) => ({
|
||||
evidence_id: evidence.evidence_id,
|
||||
operation: evidence.operation,
|
||||
|
||||
@@ -176,6 +176,63 @@ it("records a residual question for partial verification with zero item counts",
|
||||
expect(harness.session.listUnknowns()).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("retains partial native export coverage after an observed match", async () => {
|
||||
const harness = await createApplicationMcpHarness({
|
||||
session: createTestBinarySession(() => {
|
||||
throw new Error("No provider needed");
|
||||
}),
|
||||
});
|
||||
onTestFinished(harness.close);
|
||||
const original = MANAGED_NATIVE_VERIFICATION_EXAMPLE.native_observations[0];
|
||||
if (original === undefined || original.subject === null)
|
||||
throw new Error("Managed verification example is missing native Evidence");
|
||||
const report = inspectMachoSchema.parse(original.normalized_result);
|
||||
const native = createEvidence(
|
||||
{
|
||||
path: original.subject.local_path!,
|
||||
sha256: original.subject.digest.sha256,
|
||||
format: original.subject.format,
|
||||
},
|
||||
original.provider,
|
||||
{
|
||||
operation: "inspect_macho",
|
||||
parameters: original.parameters,
|
||||
result: {
|
||||
...report,
|
||||
exports: {
|
||||
...report.exports,
|
||||
exhaustive: false,
|
||||
limitations: ["Export inventory may be incomplete."],
|
||||
},
|
||||
},
|
||||
rawResult: null,
|
||||
},
|
||||
);
|
||||
const response = await harness.client.callTool({
|
||||
name: "verify_managed_native_boundaries",
|
||||
arguments: {
|
||||
managed_boundaries:
|
||||
MANAGED_NATIVE_VERIFICATION_EXAMPLE.managed_boundaries,
|
||||
native_observations: [native],
|
||||
},
|
||||
});
|
||||
expect(response.isError, JSON.stringify(response.content)).not.toBe(true);
|
||||
const evidence = parseEvidence(response.structuredContent);
|
||||
const result = managedNativeVerificationResultSchema.parse(
|
||||
evidence.normalized_result,
|
||||
);
|
||||
expect(result.summary).toMatchObject({
|
||||
verified: 1,
|
||||
unresolved: 0,
|
||||
contradicted: 0,
|
||||
});
|
||||
expect(result.coverage.status).toBe("partial");
|
||||
expect(result.limitations).toContainEqual(
|
||||
expect.stringContaining("Export inventory may be incomplete."),
|
||||
);
|
||||
expect(harness.session.listUnknowns()).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("records distinct unresolved managed boundary checks and makes exact replay idempotent", async () => {
|
||||
const harness = await createApplicationMcpHarness({
|
||||
session: createTestBinarySession(() => {
|
||||
|
||||
Reference in new issue
Block a user