feat(mcp)!: require Evidence for managed reconstruction
This commit is contained in:
parent
fd08025dcd
commit
d36af5d0f7
|
|
@ -25,9 +25,16 @@ export const importManagedReconstructionEvidence = (
|
|||
const parsed = managedReconstructionImportInputSchema.safeParse(rawInput);
|
||||
if (!parsed.success)
|
||||
return err(new AnalysisInputError(OPERATION, { cause: parsed.error }));
|
||||
return importManagedReconstructionEvidenceValidated(parsed.data);
|
||||
};
|
||||
|
||||
/** Import reconstruction from input parsed by a trusted adapter. */
|
||||
export const importManagedReconstructionEvidenceValidated = (
|
||||
input: ManagedReconstructionImportInput,
|
||||
): Result<Evidence, AnalysisError> => {
|
||||
try {
|
||||
const result = importManagedReconstruction(parsed.data);
|
||||
return ok(createManagedReconstructionEvidence(parsed.data, result));
|
||||
const result = importManagedReconstruction(input);
|
||||
return ok(createManagedReconstructionEvidence(input, result));
|
||||
} catch (cause: unknown) {
|
||||
return err(
|
||||
cause instanceof TypeError || cause instanceof z.ZodError
|
||||
|
|
|
|||
|
|
@ -39,6 +39,12 @@ export const managedRuntimeCorrelationReferenceInputSchema =
|
|||
.omit({ static_members: true })
|
||||
.extend({ static_members_evidence_id: managedEvidenceIdSchema });
|
||||
|
||||
/** MCP reference for importing reconstruction against session Evidence. */
|
||||
export const managedReconstructionReferenceInputSchema =
|
||||
managedReconstructionImportInputSchema
|
||||
.omit({ static_members: true })
|
||||
.extend({ static_members_evidence_id: managedEvidenceIdSchema });
|
||||
|
||||
const comparisonOutputSchema =
|
||||
managedWorkflowOutputSchemas.compare_managed_members;
|
||||
if (comparisonOutputSchema === undefined)
|
||||
|
|
@ -82,21 +88,22 @@ export const MANAGED_WORKFLOW_TOOL_CONTRACTS = [
|
|||
},
|
||||
{
|
||||
name: "import_managed_reconstruction",
|
||||
...toolContractMetadata("import_managed_reconstruction"),
|
||||
description:
|
||||
"Import decompiler-produced managed reconstruction against authenticated inspect_managed_members Evidence. The workflow locks each method to artifact SHA-256, MVID, metadata token, signature hash, and normalized IL hash, records the decompiler identity and options, and marks C# or pseudocode as analyst inference rather than canonical byte observation.",
|
||||
kind: "application",
|
||||
inputSchema: managedReconstructionImportInputSchema,
|
||||
inputSchema: managedReconstructionReferenceInputSchema,
|
||||
outputSchema: reconstructionOutputSchema,
|
||||
annotations: {
|
||||
readOnlyHint: true,
|
||||
destructiveHint: false,
|
||||
idempotentHint: true,
|
||||
openWorldHint: false,
|
||||
},
|
||||
examples: [
|
||||
{
|
||||
title: "Import a decompiler reconstruction for one managed method",
|
||||
input: MANAGED_RECONSTRUCTION_IMPORT_EXAMPLE,
|
||||
input: {
|
||||
static_members_evidence_id:
|
||||
MANAGED_RECONSTRUCTION_IMPORT_EXAMPLE.static_members.evidence_id,
|
||||
decompiler: MANAGED_RECONSTRUCTION_IMPORT_EXAMPLE.decompiler,
|
||||
methods: MANAGED_RECONSTRUCTION_IMPORT_EXAMPLE.methods,
|
||||
notes: MANAGED_RECONSTRUCTION_IMPORT_EXAMPLE.notes,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ export const TOOL_EFFECTS: Readonly<Record<string, ToolEffects>> = {
|
|||
inspect_managed_members: evidence,
|
||||
inspect_managed_native_boundaries: evidence,
|
||||
compare_managed_members: sessionEvidence,
|
||||
import_managed_reconstruction: sessionEvidence,
|
||||
plan_managed_runtime_correlation: sessionEvidence,
|
||||
list_browser_targets: browserEvidence,
|
||||
inspect_web_page: browserEvidence,
|
||||
|
|
|
|||
|
|
@ -2,18 +2,18 @@ import type { McpServer } from "@modelcontextprotocol/server";
|
|||
|
||||
import type { BinarySessionPort } from "../application/BinarySession.js";
|
||||
import { compareManagedMembersEvidenceValidated } from "../application/ManagedMemberComparisonService.js";
|
||||
import { importManagedReconstructionEvidence } from "../application/ManagedReconstructionService.js";
|
||||
import { importManagedReconstructionEvidenceValidated } from "../application/ManagedReconstructionService.js";
|
||||
import {
|
||||
planManagedRuntimeCorrelationEvidenceValidated,
|
||||
type ManagedRuntimeCorrelationDependencies,
|
||||
} from "../application/ManagedRuntimeCorrelationService.js";
|
||||
import {
|
||||
compareManagedMembersReferenceInputSchema,
|
||||
managedReconstructionReferenceInputSchema,
|
||||
managedRuntimeCorrelationReferenceInputSchema,
|
||||
MANAGED_WORKFLOW_TOOL_CONTRACTS,
|
||||
} from "../contracts/managedWorkflowToolContracts.js";
|
||||
import { managedMemberComparisonResultSchema } from "../domain/managedMemberComparison.js";
|
||||
import { managedReconstructionImportInputSchema } from "../domain/managedReconstruction.js";
|
||||
import type { Evidence } from "../domain/evidence.js";
|
||||
import type { EvidenceIntegrityError } from "../domain/errors.js";
|
||||
import type { Result } from "../domain/result.js";
|
||||
|
|
@ -120,11 +120,33 @@ export const registerManagedWorkflowTools = (
|
|||
reconstructionContract.name,
|
||||
toolRegistrationOptions(reconstructionContract),
|
||||
async (input) => {
|
||||
const parsed = managedReconstructionImportInputSchema.parse(input);
|
||||
const parsedInput = safeParseToolInput(
|
||||
managedReconstructionReferenceInputSchema,
|
||||
input,
|
||||
reconstructionContract.name,
|
||||
);
|
||||
if (!parsedInput.ok)
|
||||
return toCallToolResult(parsedInput, reconstructionContract);
|
||||
const resolved = resolveManagedEvidence(options.session, [
|
||||
parsedInput.value.static_members_evidence_id,
|
||||
]);
|
||||
if (!resolved.ok)
|
||||
return toCallToolResult(resolved, reconstructionContract);
|
||||
const staticMembers = resolved.value[0];
|
||||
if (staticMembers === undefined)
|
||||
throw new TypeError(
|
||||
"Managed reconstruction Evidence resolution failed",
|
||||
);
|
||||
const {
|
||||
static_members_evidence_id: _staticMembersEvidenceId,
|
||||
...referencedInput
|
||||
} = parsedInput.value;
|
||||
const parsed = { ...referencedInput, static_members: staticMembers };
|
||||
const result = await logToolExecution(
|
||||
options.logger,
|
||||
reconstructionContract.name,
|
||||
() => Promise.resolve(importManagedReconstructionEvidence(parsed)),
|
||||
() =>
|
||||
Promise.resolve(importManagedReconstructionEvidenceValidated(parsed)),
|
||||
);
|
||||
if (!result.ok) return toCallToolResult(result, reconstructionContract);
|
||||
const recordedSource = options.recordEvidence?.(parsed.static_members);
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ describe("managed artifact MCP tools", () => {
|
|||
await client.callTool({
|
||||
name: "import_managed_reconstruction",
|
||||
arguments: {
|
||||
static_members: members,
|
||||
static_members_evidence_id: members.evidence_id,
|
||||
decompiler: {
|
||||
name: "ilspycmd",
|
||||
version: "9.1.0.7988",
|
||||
|
|
|
|||
Loading…
Reference in New Issue