mirror of
https://github.com/morluto/rea.git
synced 2026-10-11 21:39:55 +00:00
refactor(firmware): group layered source and verification (#878)
This commit is contained in:
@@ -224,3 +224,20 @@ explicit downloader and fixed manifest belong to `scripts/fixtures/android/`.
|
||||
`tests/fixtures/android/`, with matching boundary and composition ownership. Real
|
||||
JADX CLI/MCP parity requires the fixed APK and existing audited JAR; synthetic
|
||||
protocol/cancellation success does not establish that engine or an unverified host.
|
||||
|
||||
## Firmware layer and verification ownership
|
||||
|
||||
Firmware workflows and their existing typed port live in
|
||||
`src/application/firmware/`, pure request/result semantics in
|
||||
`src/domain/firmware/`, and named contracts in `src/contracts/firmware/`.
|
||||
`src/firmware/` keeps producer commands, report parsing, source copies, publication
|
||||
and cleanup; `src/composition/firmware.ts` supplies a fresh typed factory.
|
||||
|
||||
The real lane belongs to `scripts/verify/firmware/analysis.mjs`; the fixture runner
|
||||
and its unchanged Python producer belong together in `scripts/fixtures/firmware/`.
|
||||
The npm command names and selected `REA_FIRMWARE_FIXTURE_ROOT` are unchanged. The
|
||||
runner retains its working-directory-relative default; the verifier retains its
|
||||
repository-root default. Both point to `_reference/firmware-integration/generated`
|
||||
when invoked through the documented npm commands. Optional ext4/Ghidra lanes keep
|
||||
their own prerequisites. Source-fixture generation and synthetic producer tests
|
||||
do not establish real Binwalk/Unblob analysis or another host's execution support.
|
||||
|
||||
@@ -429,6 +429,12 @@ unknown chunks, depth limits and extracted child digests. The optional
|
||||
Neither optional toolchain is a base-lane prerequisite. See
|
||||
[firmware analysis](firmware-analysis.md) for limits and unverified formats.
|
||||
|
||||
The real entrypoint is `scripts/verify/firmware/analysis.mjs`; the fixture runner
|
||||
and unchanged Python producer belong together in `scripts/fixtures/firmware/`.
|
||||
Producer fixtures and boundaries remain in `tests/fixtures/firmware/` and
|
||||
`tests/boundary/firmware/`. Source-fixture generation proves the runner and
|
||||
independent oracle; actual Binwalk/Unblob CLI/MCP proof requires selected tools.
|
||||
|
||||
### JavaScript source recovery
|
||||
|
||||
Build once with `npm run build:cached`, then run `npm run verify:javascript:recovery`.
|
||||
|
||||
+2
-2
@@ -140,8 +140,8 @@
|
||||
"verify:javascript:digests": "npm run build:cached && node scripts/verify-large-javascript-digests.mjs",
|
||||
"verify:application-workflows": "npm run build:cached && node scripts/verify-local-application-workflows.mjs",
|
||||
"verify:managed": "npm run build:cached && node scripts/verify-managed-conformance.mjs",
|
||||
"verify:firmware": "npm run build:cached && node scripts/verify-real-firmware.mjs",
|
||||
"fixtures:firmware": "node scripts/generate-firmware-fixtures.mjs",
|
||||
"verify:firmware": "npm run build:cached && node scripts/verify/firmware/analysis.mjs",
|
||||
"fixtures:firmware": "node scripts/fixtures/firmware/generate.mjs",
|
||||
"verify:android": "npm run build:cached && node scripts/verify/android/analysis.mjs",
|
||||
"fixtures:android": "node scripts/fixtures/android/fetch.mjs",
|
||||
"verify:agent": "npm run build:cached && node scripts/verify-agent-experience.mjs",
|
||||
|
||||
@@ -34,7 +34,7 @@ const ext4 =
|
||||
: [];
|
||||
for (const command of ext4) await exec(command, ["-V"]);
|
||||
const generated = await exec(process.env.REA_FIRMWARE_PYTHON ?? "python3", [
|
||||
fileURLToPath(new URL("./lib/generate-firmware-fixture.py", import.meta.url)),
|
||||
fileURLToPath(new URL("./generate.py", import.meta.url)),
|
||||
root,
|
||||
process.env.REA_FIRMWARE_CC ?? "cc",
|
||||
...ext4,
|
||||
@@ -43,7 +43,7 @@ const SOURCE_PATHS = {
|
||||
nativeContracts: "dist/contracts/nativeToolContracts.js",
|
||||
artifactContracts: "dist/contracts/artifactToolContracts.js",
|
||||
managedContracts: "dist/contracts/managedToolContracts.js",
|
||||
firmwareContracts: "dist/contracts/firmwareToolContracts.js",
|
||||
firmwareContracts: "dist/contracts/firmware/firmwareToolContracts.js",
|
||||
firmwareProvider: "dist/firmware/FirmwareRelease.js",
|
||||
androidContracts: "dist/contracts/android/androidToolContracts.js",
|
||||
androidProvider: "dist/android/JadxRelease.js",
|
||||
|
||||
@@ -14,12 +14,12 @@ import { fileURLToPath } from "node:url";
|
||||
import { promisify } from "node:util";
|
||||
import { Client } from "@modelcontextprotocol/client";
|
||||
import { StdioClientTransport } from "@modelcontextprotocol/client/stdio";
|
||||
import { firmwareResultSchemas } from "../dist/domain/firmwareAnalysis.js";
|
||||
import { parseEvidence } from "../dist/domain/evidence.js";
|
||||
import { hashFirmwareFile } from "../dist/firmware/FirmwareFiles.js";
|
||||
import { firmwareResultSchemas } from "../../../dist/domain/firmware/firmwareAnalysis.js";
|
||||
import { parseEvidence } from "../../../dist/domain/evidence.js";
|
||||
import { hashFirmwareFile } from "../../../dist/firmware/FirmwareFiles.js";
|
||||
|
||||
const exec = promisify(execFile);
|
||||
const repository = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
||||
const repository = resolve(dirname(fileURLToPath(import.meta.url)), "../../..");
|
||||
const entrypoint = resolve(
|
||||
process.env.REA_FIRMWARE_TEST_ENTRYPOINT ??
|
||||
join(repository, "scripts/rea.mjs"),
|
||||
+4
-4
@@ -1,10 +1,10 @@
|
||||
import type {
|
||||
AnalysisExecution,
|
||||
ExecutionOptions,
|
||||
} from "./AnalysisProvider.js";
|
||||
import type { FirmwareRequest } from "../domain/firmwareAnalysis.js";
|
||||
import type { AnalysisError } from "../domain/analysisErrorBase.js";
|
||||
import type { Result } from "../domain/result.js";
|
||||
} from "../AnalysisProvider.js";
|
||||
import type { FirmwareRequest } from "../../domain/firmware/firmwareAnalysis.js";
|
||||
import type { AnalysisError } from "../../domain/analysisErrorBase.js";
|
||||
import type { Result } from "../../domain/result.js";
|
||||
|
||||
/** File-oriented firmware engines; executable admission remains a separate operation. */
|
||||
export interface FirmwareAnalysisPort {
|
||||
+7
-7
@@ -1,18 +1,18 @@
|
||||
import type { ExecutionOptions } from "./AnalysisProvider.js";
|
||||
import type { ExecutionOptions } from "../AnalysisProvider.js";
|
||||
import type { FirmwareAnalysisPort } from "./FirmwareAnalysisPort.js";
|
||||
import {
|
||||
firmwareRequestSchema,
|
||||
type FirmwareOperation,
|
||||
} from "../domain/firmwareAnalysis.js";
|
||||
} from "../../domain/firmware/firmwareAnalysis.js";
|
||||
import {
|
||||
AnalysisCancelledError,
|
||||
AnalysisInputError,
|
||||
AnalysisOutputError,
|
||||
} from "../domain/analysisErrorCore.js";
|
||||
import type { AnalysisError } from "../domain/analysisErrorBase.js";
|
||||
import { createEvidence, type Evidence } from "../domain/evidence.js";
|
||||
import { jsonObjectSchema } from "../domain/jsonValue.js";
|
||||
import { err, ok, type Result } from "../domain/result.js";
|
||||
} from "../../domain/analysisErrorCore.js";
|
||||
import type { AnalysisError } from "../../domain/analysisErrorBase.js";
|
||||
import { createEvidence, type Evidence } from "../../domain/evidence.js";
|
||||
import { jsonObjectSchema } from "../../domain/jsonValue.js";
|
||||
import { err, ok, type Result } from "../../domain/result.js";
|
||||
|
||||
/** Shared CLI/MCP validation and Evidence composition for arbitrary firmware files. */
|
||||
export class FirmwareAnalysisService {
|
||||
@@ -1,10 +1,10 @@
|
||||
import { z } from "incur";
|
||||
import { FirmwareAnalysisService } from "../application/FirmwareAnalysisService.js";
|
||||
import { FirmwareAnalysisService } from "../application/firmware/FirmwareAnalysisService.js";
|
||||
import { createFirmwareAnalysisProvider } from "../composition/firmware.js";
|
||||
import { CLI_COMMANDS } from "../cliCommandNames.js";
|
||||
import { logCliCommand } from "../cliLogging.js";
|
||||
import { projectAnalysisError } from "../domain/analysisErrorProjection.js";
|
||||
import type { FirmwareOperation } from "../domain/firmwareAnalysis.js";
|
||||
import type { FirmwareOperation } from "../domain/firmware/firmwareAnalysis.js";
|
||||
import type { Logger } from "../logger.js";
|
||||
import type { CliInstance } from "./types.js";
|
||||
import { withCommandCancellation } from "./commandCancellation.js";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { FirmwareAnalysisPort } from "../application/FirmwareAnalysisPort.js";
|
||||
import type { FirmwareAnalysisPort } from "../application/firmware/FirmwareAnalysisPort.js";
|
||||
import type { FirmwareLauncher } from "../firmware/FirmwareCommand.js";
|
||||
import { FirmwareProvider } from "../firmware/FirmwareProvider.js";
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import { OFFICIAL_TOOL_CONTRACTS } from "./officialToolContracts.js";
|
||||
import { SESSION_TOOL_CONTRACTS } from "./sessionToolContracts.js";
|
||||
import { NATIVE_TOOL_CONTRACTS } from "./nativeToolContracts.js";
|
||||
import { ARTIFACT_TOOL_CONTRACTS } from "./artifactToolContracts.js";
|
||||
import { FIRMWARE_TOOL_CONTRACTS } from "./firmwareToolContracts.js";
|
||||
import { FIRMWARE_TOOL_CONTRACTS } from "./firmware/firmwareToolContracts.js";
|
||||
import { ANDROID_TOOL_CONTRACTS } from "./android/androidToolContracts.js";
|
||||
import { MANAGED_TOOL_CONTRACTS } from "./managedToolContracts.js";
|
||||
import { MANAGED_WORKFLOW_TOOL_CONTRACTS } from "./managedWorkflowToolContracts.js";
|
||||
|
||||
+4
-4
@@ -1,10 +1,10 @@
|
||||
import {
|
||||
firmwareInputSchemas,
|
||||
firmwareResultSchemas,
|
||||
} from "../domain/firmwareAnalysis.js";
|
||||
import type { ToolContract } from "./toolContractTypes.js";
|
||||
import { evidenceResultOf } from "./toolOutputSchemaPrimitives.js";
|
||||
import { toolContractMetadata } from "./toolEffects.js";
|
||||
} from "../../domain/firmware/firmwareAnalysis.js";
|
||||
import type { ToolContract } from "../toolContractTypes.js";
|
||||
import { evidenceResultOf } from "../toolOutputSchemaPrimitives.js";
|
||||
import { toolContractMetadata } from "../toolEffects.js";
|
||||
|
||||
/** Explicit local firmware observations and extraction, backed by caller-supplied tools. */
|
||||
export const FIRMWARE_TOOL_CONTRACTS = [
|
||||
@@ -6,7 +6,7 @@ import { SESSION_TOOL_CONTRACTS } from "./sessionToolContracts.js";
|
||||
import { TOOL_CONTRACTS } from "./toolContracts.js";
|
||||
import { ARTIFACT_TOOL_CONTRACTS } from "./artifactToolContracts.js";
|
||||
import { MANAGED_TOOL_CONTRACTS } from "./managedToolContracts.js";
|
||||
import { FIRMWARE_TOOL_CONTRACTS } from "./firmwareToolContracts.js";
|
||||
import { FIRMWARE_TOOL_CONTRACTS } from "./firmware/firmwareToolContracts.js";
|
||||
import { ANDROID_TOOL_CONTRACTS } from "./android/androidToolContracts.js";
|
||||
import { MANAGED_WORKFLOW_TOOL_CONTRACTS } from "./managedWorkflowToolContracts.js";
|
||||
import { NATIVE_TOOL_CONTRACTS } from "./nativeToolContracts.js";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { NATIVE_TOOL_CONTRACTS } from "./nativeToolContracts.js";
|
||||
import { ARTIFACT_TOOL_CONTRACTS } from "./artifactToolContracts.js";
|
||||
import { MANAGED_TOOL_CONTRACTS } from "./managedToolContracts.js";
|
||||
import { FIRMWARE_TOOL_CONTRACTS } from "./firmwareToolContracts.js";
|
||||
import { FIRMWARE_TOOL_CONTRACTS } from "./firmware/firmwareToolContracts.js";
|
||||
import { ANDROID_TOOL_CONTRACTS } from "./android/androidToolContracts.js";
|
||||
import { MANAGED_WORKFLOW_TOOL_CONTRACTS } from "./managedWorkflowToolContracts.js";
|
||||
import { BROWSER_PROVIDER_TOOL_CONTRACTS } from "./browserProviderToolContracts.js";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { z } from "zod";
|
||||
import { digestSchema } from "./digests.js";
|
||||
import { jsonValueSchema } from "./jsonValue.js";
|
||||
import { digestSchema } from "../digests.js";
|
||||
import { jsonValueSchema } from "../jsonValue.js";
|
||||
|
||||
const bytes = z.number().int().min(0).max(Number.MAX_SAFE_INTEGER);
|
||||
const range = z.strictObject({ offset: bytes, length: bytes.positive() });
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
AnalysisInputError,
|
||||
AnalysisOutputError,
|
||||
} from "../domain/analysisErrorCore.js";
|
||||
import type { FirmwareRequest } from "../domain/firmwareAnalysis.js";
|
||||
import type { FirmwareRequest } from "../domain/firmware/firmwareAnalysis.js";
|
||||
import { readBoundedFileBytes } from "../process/BoundedFileBytes.js";
|
||||
import { FIRMWARE_LIMITS } from "./FirmwareRelease.js";
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { join, isAbsolute } from "node:path";
|
||||
import { z } from "zod";
|
||||
import type { FirmwareAnalysisPort } from "../application/FirmwareAnalysisPort.js";
|
||||
import type { FirmwareAnalysisPort } from "../application/firmware/FirmwareAnalysisPort.js";
|
||||
import {
|
||||
createAnalysisExecution,
|
||||
type ExecutionOptions,
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
import {
|
||||
firmwareResultSchemas,
|
||||
type FirmwareRequest,
|
||||
} from "../domain/firmwareAnalysis.js";
|
||||
} from "../domain/firmware/firmwareAnalysis.js";
|
||||
import { AnalysisError } from "../domain/analysisErrorBase.js";
|
||||
import {
|
||||
AnalysisCancelledError,
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { z } from "zod";
|
||||
import { SafeOutputTree } from "../artifacts/SafeOutputTree.js";
|
||||
import { AnalysisOutputError } from "../domain/analysisErrorCore.js";
|
||||
import { ProviderCleanupError } from "../domain/providerCleanupError.js";
|
||||
import { firmwareResultSchemas } from "../domain/firmwareAnalysis.js";
|
||||
import { firmwareResultSchemas } from "../domain/firmware/firmwareAnalysis.js";
|
||||
import { hashFirmwareFile, type FirmwareEntry } from "./FirmwareFiles.js";
|
||||
import type { normalizeUnblobReport } from "./FirmwareReports.js";
|
||||
|
||||
|
||||
@@ -25,8 +25,8 @@ import { registerEnhancedTools } from "./registerEnhancedTools.js";
|
||||
import { registerJavaScriptRuntimeObservationTools } from "./registerJavaScriptRuntimeObservationTools.js";
|
||||
import { registerManagedTools } from "./registerManagedTools.js";
|
||||
import { registerFirmwareTools } from "./registerFirmwareTools.js";
|
||||
import { FirmwareAnalysisService } from "../application/FirmwareAnalysisService.js";
|
||||
import type { FirmwareAnalysisPort } from "../application/FirmwareAnalysisPort.js";
|
||||
import { FirmwareAnalysisService } from "../application/firmware/FirmwareAnalysisService.js";
|
||||
import type { FirmwareAnalysisPort } from "../application/firmware/FirmwareAnalysisPort.js";
|
||||
import { createFirmwareAnalysisProvider } from "../composition/firmware.js";
|
||||
import { registerAndroidTools } from "./registerAndroidTools.js";
|
||||
import { AndroidAnalysisService } from "../application/android/AndroidAnalysisService.js";
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { EvidenceWriter } from "../application/investigation/InvestigationRecordPort.js";
|
||||
import type { McpServer, ServerContext } from "@modelcontextprotocol/server";
|
||||
import type { FirmwareAnalysisService } from "../application/FirmwareAnalysisService.js";
|
||||
import type { FirmwareAnalysisService } from "../application/firmware/FirmwareAnalysisService.js";
|
||||
import { toolContract } from "../contracts/toolContracts.js";
|
||||
import type { ToolContract } from "../contracts/toolContractTypes.js";
|
||||
import type { FirmwareOperation } from "../domain/firmwareAnalysis.js";
|
||||
import type { FirmwareOperation } from "../domain/firmware/firmwareAnalysis.js";
|
||||
import type { Logger } from "../logger.js";
|
||||
import { logToolExecution } from "./toolLogging.js";
|
||||
import { toolRegistrationOptions } from "./toolRegistrationOptions.js";
|
||||
|
||||
@@ -4,8 +4,8 @@ import {
|
||||
firmwareFixture,
|
||||
assertFirmwareCleanup,
|
||||
} from "../../fixtures/firmware/provider.js";
|
||||
import { firmwareResultSchemas } from "../../../src/domain/firmwareAnalysis.js";
|
||||
import { FirmwareAnalysisService } from "../../../src/application/FirmwareAnalysisService.js";
|
||||
import { firmwareResultSchemas } from "../../../src/domain/firmware/firmwareAnalysis.js";
|
||||
import { FirmwareAnalysisService } from "../../../src/application/firmware/FirmwareAnalysisService.js";
|
||||
import { FirmwareProvider } from "../../../src/firmware/FirmwareProvider.js";
|
||||
import { projectAnalysisError } from "../../../src/domain/analysisErrorProjection.js";
|
||||
import { toolContract } from "../../../src/contracts/toolContracts.js";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Client, InMemoryTransport } from "@modelcontextprotocol/client";
|
||||
import { expect, it as test, onTestFinished } from "vitest";
|
||||
import { FIRMWARE_TOOL_CONTRACTS } from "../../../src/contracts/firmwareToolContracts.js";
|
||||
import { FIRMWARE_TOOL_CONTRACTS } from "../../../src/contracts/firmware/firmwareToolContracts.js";
|
||||
import { parseEvidence } from "../../../src/domain/evidence.js";
|
||||
import { createServer } from "../../../src/server/createServer.js";
|
||||
import { createTestBinarySession } from "../../fixtures/binarySession.js";
|
||||
|
||||
Vendored
+1
-1
@@ -3,7 +3,7 @@ import { fileURLToPath } from "node:url";
|
||||
import { access, rm, writeFile } from "node:fs/promises";
|
||||
import { expect, onTestFinished } from "vitest";
|
||||
import { createFirmwareAnalysisProvider } from "../../../src/composition/firmware.js";
|
||||
import { FirmwareAnalysisService } from "../../../src/application/FirmwareAnalysisService.js";
|
||||
import { FirmwareAnalysisService } from "../../../src/application/firmware/FirmwareAnalysisService.js";
|
||||
import { spawnOwnedProviderProcess } from "../../../src/process/ProviderProcess.js";
|
||||
import { createTestTempDirectory } from "../temporaryDirectory.js";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user