From 6e4535c1011f1982e9ab07b7ebcd600c19cd494d Mon Sep 17 00:00:00 2001 From: Ysopwnable <161784452+N0zoM1z0@users.noreply.github.com> Date: Thu, 8 Oct 2026 05:51:14 +0800 Subject: [PATCH] refactor(artifacts): move inventory and extraction into provider owners (#1032) --- docs/architecture.mermaid | 2 +- docs/capability-migration.md | 24 +++++++++ scripts/lib/module-boundaries.mjs | 2 + scripts/verify-package-mcp.mjs | 33 ++++++++++-- .../ArtifactExtractionDestination.ts | 0 .../JavaScriptArtifactGraphBuilder.ts | 2 +- .../JavaScriptArtifactGraphContext.ts | 2 +- .../JavaScriptArtifactGraphStructure.ts | 2 +- .../JavaScriptArtifactReconstruction.ts | 2 +- src/artifacts/ArtifactProvider.ts | 6 +-- .../extraction}/ArtifactExtraction.ts | 22 ++++---- .../ArtifactGraphConstruction.test.ts | 0 .../inventory}/ArtifactGraphConstruction.ts | 10 ++-- .../inventory}/ArtifactInventory.ts | 12 ++--- .../inventory}/classify.ts | 4 +- .../inventory}/policy.ts | 0 .../inventory}/reader.ts | 12 ++--- .../inventory}/scanCanonical.ts | 6 +-- .../inventory}/scanReader.ts | 10 ++-- .../inventory}/types.ts | 0 src/cli/artifactCommands.ts | 2 +- src/server/registerEvidenceTools.ts | 2 +- .../artifactComparisonSummary.test.ts | 2 +- .../artifactDirectoryIdentity.test.ts | 2 +- .../artifactInventoryEntryOrder.test.ts | 2 +- .../artifactInventorySnapshot.test.ts | 2 +- .../filesystem/artifactMzInventory.test.ts | 6 +-- .../asarInventoryContainment.test.ts | 2 +- .../filesystem/asarInventoryFreshness.test.ts | 2 +- .../asarStreamingAllocation.test.ts | 2 +- .../javascriptArtifactContentIdentity.test.ts | 2 +- .../javascriptArtifactReconstruction.test.ts | 2 +- .../boundary/filesystem/zipDetection.test.ts | 2 +- .../artifactComparison.test.ts | 2 +- .../javascriptArtifactReconstruction.test.ts | 2 +- tests/evaluation/moduleBoundaries.test.ts | 53 ++++++++++--------- 36 files changed, 147 insertions(+), 91 deletions(-) rename src/application/{ => artifacts}/ArtifactExtractionDestination.ts (100%) rename src/{application => artifacts/extraction}/ArtifactExtraction.ts (92%) rename src/{application => artifacts/inventory}/ArtifactGraphConstruction.test.ts (100%) rename src/{application => artifacts/inventory}/ArtifactGraphConstruction.ts (97%) rename src/{application => artifacts/inventory}/ArtifactInventory.ts (75%) rename src/{application/ArtifactInventory => artifacts/inventory}/classify.ts (88%) rename src/{application/ArtifactInventory => artifacts/inventory}/policy.ts (100%) rename src/{application/ArtifactInventory => artifacts/inventory}/reader.ts (74%) rename src/{application/ArtifactInventory => artifacts/inventory}/scanCanonical.ts (98%) rename src/{application/ArtifactInventory => artifacts/inventory}/scanReader.ts (96%) rename src/{application/ArtifactInventory => artifacts/inventory}/types.ts (100%) diff --git a/docs/architecture.mermaid b/docs/architecture.mermaid index f4835fdb2..b4fc6c5b0 100644 --- a/docs/architecture.mermaid +++ b/docs/architecture.mermaid @@ -30,7 +30,7 @@ graph TD GHIDRA["src/ghidra/
Ghidra discovery, profile & function analysis
snapshot, Unix/Windows transport, bounded lifecycle"] IDA["src/ida/
Upstream MCP contract adaptation
live GUI binding or owned headless database"] IDA_MCP["External ida-pro-mcp
GUI proxy or database supervisor
upstream installation and engine lifecycle"] - AUX["src/artifacts/ + src/native/
disjoint artifact and native capabilities"] + AUX["src/artifacts/ + src/native/
artifact inventory and extraction
format readers and native capabilities"] BROWSER["src/browser/
CDP / Playwright capture
captured scripts and native module resolution
execution/: coverage, listener and source attribution"] JS_CODEC["src/javascript/sourceMaps/
pinned upstream map codec
owned heap-limited Node process, complete point evidence"] INSPECTOR["src/inspector/
passive V8 Inspector discovery and capture
script and target locations"] diff --git a/docs/capability-migration.md b/docs/capability-migration.md index e38761e73..1a757dd82 100644 --- a/docs/capability-migration.md +++ b/docs/capability-migration.md @@ -385,6 +385,30 @@ claims. Actual Swift/Xcode, assetutil, native NIB, bundle signing and DMG lifecy claims require the real Apple lane. Native binary API/value-flow semantics and shared cross-domain contract aggregates keep their separate owners. +## Artifact inventory and extraction ownership + +`src/artifacts/inventory/` owns format classification, reader selection, inventory +policy, canonical scanning and artifact graph construction. The shared artifact +provider and JavaScript reconstruction workflow consume this owner. Snapshot +semantics remain in `src/domain/artifactInventorySnapshot.ts`. + +`src/artifacts/extraction/` owns member selection, integrity checks and transactional +materialization through the existing readers and safe output tree. Reader cleanup, +cancellation, rollback, archive containment and caller-visible results retain their +existing behavior. Acquisition guards reject imports from these producer owners +into application workflows, production composition or CLI/MCP adapters. + +`src/application/artifacts/ArtifactExtractionDestination.ts` owns the caller's +default temporary output-root choice for both CLI and MCP. The adapters pass this +destination to the existing provider operation; format handling and member writes +remain in the artifact owner. + +Add format-specific acquisition behavior beside the inventory readers and exercise +its actual producer representation in filesystem boundary tests. Add caller +workflow behavior in the application owner and verify both adapters. The installed +package lane checks inventory identity and extraction through CLI and MCP; the +real Apple bundle lane separately establishes DMG mount and detach behavior. + ## Binary production composition closure `src/composition/binary.ts` is the shared production owner for deep candidate diff --git a/scripts/lib/module-boundaries.mjs b/scripts/lib/module-boundaries.mjs index 05b12b85f..b50050d79 100644 --- a/scripts/lib/module-boundaries.mjs +++ b/scripts/lib/module-boundaries.mjs @@ -78,6 +78,8 @@ const failedBoundary = (file, target) => { if ( (file.startsWith("src/artifacts/javascript/") || file.startsWith("src/artifacts/apple/") || + file.startsWith("src/artifacts/inventory/") || + file.startsWith("src/artifacts/extraction/") || /^src\/artifacts\/ArtifactHash\.(?:js|ts)$/u.test(file)) && (["application", "composition", "server", "cli", "main"].includes( targetLayer, diff --git a/scripts/verify-package-mcp.mjs b/scripts/verify-package-mcp.mjs index a4831d825..3b5be1b5d 100644 --- a/scripts/verify-package-mcp.mjs +++ b/scripts/verify-package-mcp.mjs @@ -2,6 +2,7 @@ import assert from "node:assert/strict"; import { join } from "node:path"; import { execFile } from "node:child_process"; import { promisify } from "node:util"; +import { readFile, rm } from "node:fs/promises"; import { Client } from "@modelcontextprotocol/client"; import { StdioClientTransport } from "@modelcontextprotocol/client/stdio"; @@ -167,6 +168,7 @@ const verifyMcpInlineArtifactEvidence = async ( mcpOptions, ); assert.notEqual(opened.isError, true, JSON.stringify(opened)); + let outputRoot; try { const inspected = await client.callTool( { name: "inspect_artifact", arguments: {} }, @@ -212,12 +214,35 @@ const verifyMcpInlineArtifactEvidence = async ( evidence, ); } - } finally { - const closed = await client.callTool( - { name: "close_binary", arguments: {} }, + const extracted = await client.callTool( + { name: "extract_artifact", arguments: {} }, mcpOptions, ); - assert.notEqual(closed.isError, true, JSON.stringify(closed)); + assert.notEqual(extracted.isError, true, JSON.stringify(extracted)); + const extraction = parseEvidence(extracted.structuredContent?.evidence); + assert.deepEqual( + extraction.normalized_result, + extracted.structuredContent?.result, + ); + const materialized = extracted.structuredContent?.result; + assert.equal(typeof materialized?.output_root, "string"); + outputRoot = materialized.output_root; + assert.equal(materialized.containment_verified, true); + assert.equal( + await readFile(join(outputRoot, "app/main.js"), "utf8"), + "main();", + ); + } finally { + try { + const closed = await client.callTool( + { name: "close_binary", arguments: {} }, + mcpOptions, + ); + assert.notEqual(closed.isError, true, JSON.stringify(closed)); + } finally { + if (outputRoot !== undefined) + await rm(outputRoot, { recursive: true, force: true }); + } } }; diff --git a/src/application/ArtifactExtractionDestination.ts b/src/application/artifacts/ArtifactExtractionDestination.ts similarity index 100% rename from src/application/ArtifactExtractionDestination.ts rename to src/application/artifacts/ArtifactExtractionDestination.ts diff --git a/src/application/javascript/JavaScriptArtifactGraphBuilder.ts b/src/application/javascript/JavaScriptArtifactGraphBuilder.ts index 6af56f1a7..49f317270 100644 --- a/src/application/javascript/JavaScriptArtifactGraphBuilder.ts +++ b/src/application/javascript/JavaScriptArtifactGraphBuilder.ts @@ -1,4 +1,4 @@ -import type { ArtifactInventorySnapshot } from "../ArtifactInventory.js"; +import type { ArtifactInventorySnapshot } from "../../artifacts/inventory/ArtifactInventory.js"; import { createJavaScriptApplicationGraph, type JavaScriptApplicationGraph, diff --git a/src/application/javascript/JavaScriptArtifactGraphContext.ts b/src/application/javascript/JavaScriptArtifactGraphContext.ts index 8e398bc77..291dfa46f 100644 --- a/src/application/javascript/JavaScriptArtifactGraphContext.ts +++ b/src/application/javascript/JavaScriptArtifactGraphContext.ts @@ -1,4 +1,4 @@ -import type { ArtifactInventorySnapshot } from "../ArtifactInventory.js"; +import type { ArtifactInventorySnapshot } from "../../artifacts/inventory/ArtifactInventory.js"; import { completeApplicationCoverage, partialApplicationCoverage, diff --git a/src/application/javascript/JavaScriptArtifactGraphStructure.ts b/src/application/javascript/JavaScriptArtifactGraphStructure.ts index 7a135fdea..039659f89 100644 --- a/src/application/javascript/JavaScriptArtifactGraphStructure.ts +++ b/src/application/javascript/JavaScriptArtifactGraphStructure.ts @@ -1,4 +1,4 @@ -import type { ArtifactInventorySnapshot } from "../ArtifactInventory.js"; +import type { ArtifactInventorySnapshot } from "../../artifacts/inventory/ArtifactInventory.js"; import type { ApplicationNode } from "../../domain/javascript/javascriptApplicationGraph.js"; import { completeApplicationCoverage } from "../../domain/javascript/javascriptApplicationEvidenceSchemas.js"; import type { JavaScriptArtifactAnalysis } from "./JavaScriptArtifactAnalysisTypes.js"; diff --git a/src/application/javascript/JavaScriptArtifactReconstruction.ts b/src/application/javascript/JavaScriptArtifactReconstruction.ts index 0be85beb5..7f14c7898 100644 --- a/src/application/javascript/JavaScriptArtifactReconstruction.ts +++ b/src/application/javascript/JavaScriptArtifactReconstruction.ts @@ -12,7 +12,7 @@ import { javascriptArtifactReconstructionInputSchema, type JavaScriptArtifactReconstructionInput, } from "./JavaScriptArtifactReconstructionInput.js"; -import { scanCanonicalArtifactInventory } from "../ArtifactInventory.js"; +import { scanCanonicalArtifactInventory } from "../../artifacts/inventory/ArtifactInventory.js"; import { summarizeElectronBoundaries } from "./ElectronBoundaryAnalysis.js"; import { buildJavaScriptSemanticGraph } from "./JavaScriptSemanticGraphBuilder.js"; import type { ProgressReporter } from "../ProgressReporter.js"; diff --git a/src/artifacts/ArtifactProvider.ts b/src/artifacts/ArtifactProvider.ts index 54d9d3826..8d4885f48 100644 --- a/src/artifacts/ArtifactProvider.ts +++ b/src/artifacts/ArtifactProvider.ts @@ -9,8 +9,8 @@ import { } from "../application/AnalysisProvider.js"; import { inspectBundleKeyedArchive } from "./apple/KeyedArchiveReader.js"; import { basename, dirname } from "node:path"; -import { inventoryArtifact } from "../application/ArtifactInventory.js"; -import { extractArtifact } from "../application/ArtifactExtraction.js"; +import { inventoryArtifact } from "./inventory/ArtifactInventory.js"; +import { extractArtifact } from "./extraction/ArtifactExtraction.js"; import { analyzeInterfaceBuilderBundle } from "./apple/InterfaceBuilderAnalysis.js"; import { analyzeAppleAssetCatalogs } from "./apple/AppleAssetCatalogAnalysis.js"; import { @@ -33,7 +33,7 @@ import { } from "./ArtifactProviderMetadata.js"; import { createEvidence } from "../domain/evidence.js"; import { createArtifactInspection } from "../domain/artifactInspection.js"; -import { resolveArtifactIntegrityPolicy } from "../application/ArtifactInventory/policy.js"; +import { resolveArtifactIntegrityPolicy } from "./inventory/policy.js"; /** Read-only inventory and exclusively owned extraction provider. */ export class ArtifactProvider implements AnalysisProvider { diff --git a/src/application/ArtifactExtraction.ts b/src/artifacts/extraction/ArtifactExtraction.ts similarity index 92% rename from src/application/ArtifactExtraction.ts rename to src/artifacts/extraction/ArtifactExtraction.ts index 7fc20dae9..57e8a0066 100644 --- a/src/application/ArtifactExtraction.ts +++ b/src/artifacts/extraction/ArtifactExtraction.ts @@ -1,29 +1,29 @@ import { lstat, realpath } from "node:fs/promises"; -import { canonicalDigest } from "../domain/comparisonSemantics.js"; -import { AsarArtifactReader } from "../artifacts/AsarArtifactReader.js"; +import { canonicalDigest } from "../../domain/comparisonSemantics.js"; +import { AsarArtifactReader } from "../AsarArtifactReader.js"; import { ArtifactPathRegistry, normalizeArtifactPath, -} from "../artifacts/ArtifactPaths.js"; +} from "../ArtifactPaths.js"; import { ArtifactReaderFailure, type ArtifactEntry, type ArtifactReader, -} from "../artifacts/ArtifactReader.js"; -import { DirectoryArtifactReader } from "../artifacts/DirectoryArtifactReader.js"; -import { SafeOutputTree } from "../artifacts/SafeOutputTree.js"; -import { ZipArtifactReader } from "../artifacts/ZipArtifactReader.js"; -import { MachOSliceArtifactReader } from "../artifacts/MachOSliceArtifactReader.js"; +} from "../ArtifactReader.js"; +import { DirectoryArtifactReader } from "../DirectoryArtifactReader.js"; +import { SafeOutputTree } from "../SafeOutputTree.js"; +import { ZipArtifactReader } from "../ZipArtifactReader.js"; +import { MachOSliceArtifactReader } from "../MachOSliceArtifactReader.js"; import { artifactExtractionResultSchema, type ArtifactExtractionResult, type ArtifactGraphManifest, type ArtifactNode, type ArtifactOccurrence, -} from "../domain/artifactGraph.js"; -import type { BinaryTarget } from "../domain/binaryTarget.js"; -import { scanArtifactInventory } from "./ArtifactInventory.js"; +} from "../../domain/artifactGraph.js"; +import type { BinaryTarget } from "../../domain/binaryTarget.js"; +import { scanArtifactInventory } from "../inventory/ArtifactInventory.js"; /** Local extraction input with the output root chosen by the adapter. */ export interface ArtifactExtractionInput { diff --git a/src/application/ArtifactGraphConstruction.test.ts b/src/artifacts/inventory/ArtifactGraphConstruction.test.ts similarity index 100% rename from src/application/ArtifactGraphConstruction.test.ts rename to src/artifacts/inventory/ArtifactGraphConstruction.test.ts diff --git a/src/application/ArtifactGraphConstruction.ts b/src/artifacts/inventory/ArtifactGraphConstruction.ts similarity index 97% rename from src/application/ArtifactGraphConstruction.ts rename to src/artifacts/inventory/ArtifactGraphConstruction.ts index 187d5d677..a0d1d5e1c 100644 --- a/src/application/ArtifactGraphConstruction.ts +++ b/src/artifacts/inventory/ArtifactGraphConstruction.ts @@ -1,13 +1,13 @@ -import { canonicalDigest } from "../domain/comparisonSemantics.js"; -import type { ArtifactEntry } from "../artifacts/ArtifactReader.js"; +import { canonicalDigest } from "../../domain/comparisonSemantics.js"; +import type { ArtifactEntry } from "../ArtifactReader.js"; import type { ArtifactCommand, ArtifactEdge, ArtifactNode, ArtifactOccurrence, -} from "../domain/artifactGraph.js"; -import { zipPackageFormatForPath } from "../domain/zipPackageFormat.js"; -import { mzWindowsHeaderOffset, parseDosMzHeader } from "../domain/dosMz.js"; +} from "../../domain/artifactGraph.js"; +import { zipPackageFormatForPath } from "../../domain/zipPackageFormat.js"; +import { mzWindowsHeaderOffset, parseDosMzHeader } from "../../domain/dosMz.js"; /** Mutable internal occurrence used until root-bound IDs are known. */ export interface MutableOccurrence { diff --git a/src/application/ArtifactInventory.ts b/src/artifacts/inventory/ArtifactInventory.ts similarity index 75% rename from src/application/ArtifactInventory.ts rename to src/artifacts/inventory/ArtifactInventory.ts index a7b5b181f..3b121766b 100644 --- a/src/application/ArtifactInventory.ts +++ b/src/artifacts/inventory/ArtifactInventory.ts @@ -3,22 +3,22 @@ import { realpath } from "node:fs/promises"; import { artifactInventoryResultSchema, type ArtifactInventoryResult, -} from "../domain/artifactGraph.js"; -import { abortIfNeeded } from "../artifacts/ArtifactHash.js"; -import { scanCanonicalArtifactInventory } from "./ArtifactInventory/scanCanonical.js"; +} from "../../domain/artifactGraph.js"; +import { abortIfNeeded } from "../ArtifactHash.js"; +import { scanCanonicalArtifactInventory } from "./scanCanonical.js"; import type { ArtifactIntegrityPolicy, ArtifactInventoryOptions, ArtifactInventorySnapshot, -} from "./ArtifactInventory/types.js"; +} from "./types.js"; -export { scanCanonicalArtifactInventory } from "./ArtifactInventory/scanCanonical.js"; +export { scanCanonicalArtifactInventory } from "./scanCanonical.js"; export type { ArtifactIntegrityPolicy, ArtifactInventoryOptions, ArtifactInventorySnapshot, -} from "./ArtifactInventory/types.js"; +} from "./types.js"; /** Inventory one local artifact and return every graph collection inline. */ export const inventoryArtifact = async ( diff --git a/src/application/ArtifactInventory/classify.ts b/src/artifacts/inventory/classify.ts similarity index 88% rename from src/application/ArtifactInventory/classify.ts rename to src/artifacts/inventory/classify.ts index 36e953712..421772346 100644 --- a/src/application/ArtifactInventory/classify.ts +++ b/src/artifacts/inventory/classify.ts @@ -1,7 +1,7 @@ import { open } from "node:fs/promises"; -import { classifyArtifactContent } from "../ArtifactGraphConstruction.js"; -import { ARTIFACT_CLASSIFICATION_PREFIX_BYTES } from "../../artifacts/ArtifactHash.js"; +import { classifyArtifactContent } from "./ArtifactGraphConstruction.js"; +import { ARTIFACT_CLASSIFICATION_PREFIX_BYTES } from "../ArtifactHash.js"; import type { ArtifactNode } from "../../domain/artifactGraph.js"; import { hasZipSignature, diff --git a/src/application/ArtifactInventory/policy.ts b/src/artifacts/inventory/policy.ts similarity index 100% rename from src/application/ArtifactInventory/policy.ts rename to src/artifacts/inventory/policy.ts diff --git a/src/application/ArtifactInventory/reader.ts b/src/artifacts/inventory/reader.ts similarity index 74% rename from src/application/ArtifactInventory/reader.ts rename to src/artifacts/inventory/reader.ts index f593acba0..18a0b2769 100644 --- a/src/application/ArtifactInventory/reader.ts +++ b/src/artifacts/inventory/reader.ts @@ -1,9 +1,9 @@ -import { AsarArtifactReader } from "../../artifacts/AsarArtifactReader.js"; -import type { ArtifactReader } from "../../artifacts/ArtifactReader.js"; -import { DirectoryArtifactReader } from "../../artifacts/DirectoryArtifactReader.js"; -import { MachOSliceArtifactReader } from "../../artifacts/MachOSliceArtifactReader.js"; -import { NativeDmgArtifactReader } from "../../artifacts/NativeDmgArtifactReader.js"; -import { ZipArtifactReader } from "../../artifacts/ZipArtifactReader.js"; +import { AsarArtifactReader } from "../AsarArtifactReader.js"; +import type { ArtifactReader } from "../ArtifactReader.js"; +import { DirectoryArtifactReader } from "../DirectoryArtifactReader.js"; +import { MachOSliceArtifactReader } from "../MachOSliceArtifactReader.js"; +import { NativeDmgArtifactReader } from "../NativeDmgArtifactReader.js"; +import { ZipArtifactReader } from "../ZipArtifactReader.js"; import type { ArtifactNode } from "../../domain/artifactGraph.js"; export const createReader = async ( diff --git a/src/application/ArtifactInventory/scanCanonical.ts b/src/artifacts/inventory/scanCanonical.ts similarity index 98% rename from src/application/ArtifactInventory/scanCanonical.ts rename to src/artifacts/inventory/scanCanonical.ts index b02005394..2a746343d 100644 --- a/src/application/ArtifactInventory/scanCanonical.ts +++ b/src/artifacts/inventory/scanCanonical.ts @@ -5,7 +5,7 @@ import type { Stats } from "node:fs"; import { ArtifactReaderFailure, type ArtifactReader, -} from "../../artifacts/ArtifactReader.js"; +} from "../ArtifactReader.js"; import { artifactInventoryResultSchema, type ArtifactInventoryResult, @@ -20,10 +20,10 @@ import { rekeyOccurrences, rootOccurrenceFor, type MutableOccurrence, -} from "../ArtifactGraphConstruction.js"; +} from "./ArtifactGraphConstruction.js"; import { canonicalDigest } from "../../domain/comparisonSemantics.js"; import { classifyRoot } from "./classify.js"; -import { hashReadable, type HashResult } from "../../artifacts/ArtifactHash.js"; +import { hashReadable, type HashResult } from "../ArtifactHash.js"; import { createReader, inventoryLimitations } from "./reader.js"; import { scanReader, diff --git a/src/application/ArtifactInventory/scanReader.ts b/src/artifacts/inventory/scanReader.ts similarity index 96% rename from src/application/ArtifactInventory/scanReader.ts rename to src/artifacts/inventory/scanReader.ts index fe24fe408..136f527b4 100644 --- a/src/application/ArtifactInventory/scanReader.ts +++ b/src/artifacts/inventory/scanReader.ts @@ -3,13 +3,13 @@ import { isAbsolute } from "node:path"; import { ArtifactPathRegistry, normalizeArtifactPath, -} from "../../artifacts/ArtifactPaths.js"; +} from "../ArtifactPaths.js"; import { ArtifactReaderFailure, type ArtifactEntry, type ArtifactReader, -} from "../../artifacts/ArtifactReader.js"; -import { AsarArtifactReader } from "../../artifacts/AsarArtifactReader.js"; +} from "../ArtifactReader.js"; +import { AsarArtifactReader } from "../AsarArtifactReader.js"; import type { ArtifactNode } from "../../domain/artifactGraph.js"; import { classifyArtifactContent, @@ -17,12 +17,12 @@ import { createOccurrence, nearestParent, type MutableOccurrence, -} from "../ArtifactGraphConstruction.js"; +} from "./ArtifactGraphConstruction.js"; import { STRICT_INTEGRITY_POLICY, type ArtifactIntegrityPolicy, } from "./types.js"; -import { hashReadable } from "../../artifacts/ArtifactHash.js"; +import { hashReadable } from "../ArtifactHash.js"; export interface PendingIntegrityContradiction { readonly logicalPath: string; diff --git a/src/application/ArtifactInventory/types.ts b/src/artifacts/inventory/types.ts similarity index 100% rename from src/application/ArtifactInventory/types.ts rename to src/artifacts/inventory/types.ts diff --git a/src/cli/artifactCommands.ts b/src/cli/artifactCommands.ts index 4681608e0..6dc93f7ec 100644 --- a/src/cli/artifactCommands.ts +++ b/src/cli/artifactCommands.ts @@ -1,7 +1,7 @@ import { z } from "incur"; import { runProviderAnalysis } from "../composition/directAnalysis.js"; -import { createArtifactExtractionDestination } from "../application/ArtifactExtractionDestination.js"; +import { createArtifactExtractionDestination } from "../application/artifacts/ArtifactExtractionDestination.js"; import { logCliCommand } from "../cliLogging.js"; import { CLI_COMMANDS } from "../cliCommandNames.js"; import type { Logger } from "../logger.js"; diff --git a/src/server/registerEvidenceTools.ts b/src/server/registerEvidenceTools.ts index e906bd862..be678179b 100644 --- a/src/server/registerEvidenceTools.ts +++ b/src/server/registerEvidenceTools.ts @@ -14,7 +14,7 @@ import { mcpProgressReporter } from "./mcpProgress.js"; import { logToolExecution } from "./toolLogging.js"; import { toolRegistrationOptions } from "./toolRegistrationOptions.js"; import { toCallToolResult } from "./toolResult.js"; -import { createArtifactExtractionDestination } from "../application/ArtifactExtractionDestination.js"; +import { createArtifactExtractionDestination } from "../application/artifacts/ArtifactExtractionDestination.js"; interface EvidenceToolRegistration { readonly logger: Logger; diff --git a/tests/boundary/filesystem/artifactComparisonSummary.test.ts b/tests/boundary/filesystem/artifactComparisonSummary.test.ts index 597af1a89..7879f96aa 100644 --- a/tests/boundary/filesystem/artifactComparisonSummary.test.ts +++ b/tests/boundary/filesystem/artifactComparisonSummary.test.ts @@ -3,7 +3,7 @@ import { join } from "node:path"; import { describe, expect, it } from "vitest"; -import { inventoryArtifact } from "../../../src/application/ArtifactInventory.js"; +import { inventoryArtifact } from "../../../src/artifacts/inventory/ArtifactInventory.js"; import { compareArtifacts } from "../../../src/domain/artifactComparison.js"; import { createEvidence } from "../../../src/domain/evidence.js"; import { jsonValueSchema } from "../../../src/domain/jsonValue.js"; diff --git a/tests/boundary/filesystem/artifactDirectoryIdentity.test.ts b/tests/boundary/filesystem/artifactDirectoryIdentity.test.ts index bcd1542c4..e87794869 100644 --- a/tests/boundary/filesystem/artifactDirectoryIdentity.test.ts +++ b/tests/boundary/filesystem/artifactDirectoryIdentity.test.ts @@ -5,7 +5,7 @@ import { TextReader, Uint8ArrayWriter, ZipWriter } from "@zip.js/zip.js"; import { describe, expect, it } from "vitest"; import { canonicalDigest } from "../../../src/domain/comparisonSemantics.js"; -import { inventoryArtifact } from "../../../src/application/ArtifactInventory.js"; +import { inventoryArtifact } from "../../../src/artifacts/inventory/ArtifactInventory.js"; import { compareArtifacts } from "../../../src/domain/artifactComparison.js"; import type { ArtifactInventoryResult } from "../../../src/domain/artifactGraph.js"; import { createEvidence } from "../../../src/domain/evidence.js"; diff --git a/tests/boundary/filesystem/artifactInventoryEntryOrder.test.ts b/tests/boundary/filesystem/artifactInventoryEntryOrder.test.ts index ba7add1b4..6d106e335 100644 --- a/tests/boundary/filesystem/artifactInventoryEntryOrder.test.ts +++ b/tests/boundary/filesystem/artifactInventoryEntryOrder.test.ts @@ -4,7 +4,7 @@ import { join } from "node:path"; import { createPackage } from "@electron/asar"; import { describe, expect, it } from "vitest"; -import { inventoryArtifact } from "../../../src/application/ArtifactInventory.js"; +import { inventoryArtifact } from "../../../src/artifacts/inventory/ArtifactInventory.js"; import { artifactOccurrenceAt, artifactParentPaths, diff --git a/tests/boundary/filesystem/artifactInventorySnapshot.test.ts b/tests/boundary/filesystem/artifactInventorySnapshot.test.ts index 5feec925f..bd0201d67 100644 --- a/tests/boundary/filesystem/artifactInventorySnapshot.test.ts +++ b/tests/boundary/filesystem/artifactInventorySnapshot.test.ts @@ -5,7 +5,7 @@ import { describe, expect, it } from "vitest"; import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; -import { scanArtifactInventory } from "../../../src/application/ArtifactInventory.js"; +import { scanArtifactInventory } from "../../../src/artifacts/inventory/ArtifactInventory.js"; describe("artifact inventory snapshot", () => { it("retains the complete scan after the source directory changes", async () => { diff --git a/tests/boundary/filesystem/artifactMzInventory.test.ts b/tests/boundary/filesystem/artifactMzInventory.test.ts index d1ae2ef1d..c3fd44005 100644 --- a/tests/boundary/filesystem/artifactMzInventory.test.ts +++ b/tests/boundary/filesystem/artifactMzInventory.test.ts @@ -3,10 +3,10 @@ import { join } from "node:path"; import { describe, expect, it } from "vitest"; -import { classifyArtifactContent } from "../../../src/application/ArtifactGraphConstruction.js"; -import { classifyRoot } from "../../../src/application/ArtifactInventory/classify.js"; +import { classifyArtifactContent } from "../../../src/artifacts/inventory/ArtifactGraphConstruction.js"; +import { classifyRoot } from "../../../src/artifacts/inventory/classify.js"; import { ARTIFACT_CLASSIFICATION_PREFIX_BYTES } from "../../../src/artifacts/ArtifactHash.js"; -import { scanCanonicalArtifactInventory } from "../../../src/application/ArtifactInventory/scanCanonical.js"; +import { scanCanonicalArtifactInventory } from "../../../src/artifacts/inventory/scanCanonical.js"; import { targetFormatSchema } from "../../../src/contracts/toolOutputSchemaPrimitives.js"; import { artifactInventoryResultSchema } from "../../../src/domain/artifactGraph.js"; import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; diff --git a/tests/boundary/filesystem/asarInventoryContainment.test.ts b/tests/boundary/filesystem/asarInventoryContainment.test.ts index 703fa9f8a..6e1f02133 100644 --- a/tests/boundary/filesystem/asarInventoryContainment.test.ts +++ b/tests/boundary/filesystem/asarInventoryContainment.test.ts @@ -11,7 +11,7 @@ import { } from "@zip.js/zip.js"; import { describe, expect, it } from "vitest"; -import { inventoryArtifact } from "../../../src/application/ArtifactInventory.js"; +import { inventoryArtifact } from "../../../src/artifacts/inventory/ArtifactInventory.js"; import { artifactOccurrenceAt, artifactParentPaths, diff --git a/tests/boundary/filesystem/asarInventoryFreshness.test.ts b/tests/boundary/filesystem/asarInventoryFreshness.test.ts index 4d0932935..91cdc81b6 100644 --- a/tests/boundary/filesystem/asarInventoryFreshness.test.ts +++ b/tests/boundary/filesystem/asarInventoryFreshness.test.ts @@ -5,7 +5,7 @@ import { buffer } from "node:stream/consumers"; import { createPackage, listPackage, uncache } from "@electron/asar"; import { describe, expect, it } from "vitest"; -import { inventoryArtifact } from "../../../src/application/ArtifactInventory.js"; +import { inventoryArtifact } from "../../../src/artifacts/inventory/ArtifactInventory.js"; import { AsarArtifactReader } from "../../../src/artifacts/AsarArtifactReader.js"; import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; diff --git a/tests/boundary/filesystem/asarStreamingAllocation.test.ts b/tests/boundary/filesystem/asarStreamingAllocation.test.ts index 6a5fac5e4..630091584 100644 --- a/tests/boundary/filesystem/asarStreamingAllocation.test.ts +++ b/tests/boundary/filesystem/asarStreamingAllocation.test.ts @@ -14,7 +14,7 @@ import { Readable } from "node:stream"; import { buffer } from "node:stream/consumers"; import { createPackageWithOptions } from "@electron/asar"; import { describe, expect, it } from "vitest"; -import { scanArtifactInventory } from "../../../src/application/ArtifactInventory.js"; +import { scanArtifactInventory } from "../../../src/artifacts/inventory/ArtifactInventory.js"; import { AsarArtifactReader } from "../../../src/artifacts/AsarArtifactReader.js"; import { closeAsarHandle, diff --git a/tests/boundary/filesystem/javascriptArtifactContentIdentity.test.ts b/tests/boundary/filesystem/javascriptArtifactContentIdentity.test.ts index da79929f7..1871e59c5 100644 --- a/tests/boundary/filesystem/javascriptArtifactContentIdentity.test.ts +++ b/tests/boundary/filesystem/javascriptArtifactContentIdentity.test.ts @@ -4,7 +4,7 @@ import { join } from "node:path"; import { createPackage } from "@electron/asar"; import { describe, expect, it } from "vitest"; -import { scanArtifactInventory } from "../../../src/application/ArtifactInventory.js"; +import { scanArtifactInventory } from "../../../src/artifacts/inventory/ArtifactInventory.js"; import { readJavaScriptArtifactFiles } from "../../../src/artifacts/javascript/JavaScriptArtifactFiles.js"; import { AsarArtifactReader } from "../../../src/artifacts/AsarArtifactReader.js"; import { DirectoryArtifactReader } from "../../../src/artifacts/DirectoryArtifactReader.js"; diff --git a/tests/boundary/filesystem/javascriptArtifactReconstruction.test.ts b/tests/boundary/filesystem/javascriptArtifactReconstruction.test.ts index cfab06c6b..3df383e7a 100644 --- a/tests/boundary/filesystem/javascriptArtifactReconstruction.test.ts +++ b/tests/boundary/filesystem/javascriptArtifactReconstruction.test.ts @@ -8,7 +8,7 @@ import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; import { readJavaScriptArtifactFiles } from "../../../src/artifacts/javascript/JavaScriptArtifactFiles.js"; import { reconstructJavaScriptArtifact } from "../../../src/application/javascript/JavaScriptArtifactReconstruction.js"; -import { scanArtifactInventory } from "../../../src/application/ArtifactInventory.js"; +import { scanArtifactInventory } from "../../../src/artifacts/inventory/ArtifactInventory.js"; import { type ArtifactEntry, type ArtifactReader, diff --git a/tests/boundary/filesystem/zipDetection.test.ts b/tests/boundary/filesystem/zipDetection.test.ts index a983da496..8ab81112a 100644 --- a/tests/boundary/filesystem/zipDetection.test.ts +++ b/tests/boundary/filesystem/zipDetection.test.ts @@ -3,7 +3,7 @@ import { join } from "node:path"; import { describe, expect, it } from "vitest"; -import { classifyRoot } from "../../../src/application/ArtifactInventory/classify.js"; +import { classifyRoot } from "../../../src/artifacts/inventory/classify.js"; import { parseBinaryTarget } from "../../../src/application/BinaryTargetResolver.js"; import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; diff --git a/tests/composition/analysis-sessions/artifactComparison.test.ts b/tests/composition/analysis-sessions/artifactComparison.test.ts index 36fbfaf52..a3850df20 100644 --- a/tests/composition/analysis-sessions/artifactComparison.test.ts +++ b/tests/composition/analysis-sessions/artifactComparison.test.ts @@ -6,7 +6,7 @@ import { describe, expect, it } from "vitest"; import { fragmentInventoryEvidence } from "../../fixtures/artifactEvidence.js"; import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; -import { inventoryArtifact } from "../../../src/application/ArtifactInventory.js"; +import { inventoryArtifact } from "../../../src/artifacts/inventory/ArtifactInventory.js"; import { artifactInventoryResultSchema } from "../../../src/domain/artifactGraph.js"; import { artifactComparisonResultSchema, diff --git a/tests/composition/javascript-applications/javascriptArtifactReconstruction.test.ts b/tests/composition/javascript-applications/javascriptArtifactReconstruction.test.ts index d4d60e83b..7dad88ab9 100644 --- a/tests/composition/javascript-applications/javascriptArtifactReconstruction.test.ts +++ b/tests/composition/javascript-applications/javascriptArtifactReconstruction.test.ts @@ -7,7 +7,7 @@ import { expect, it } from "vitest"; import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; import { reconstructJavaScriptArtifact } from "../../../src/application/javascript/JavaScriptArtifactReconstruction.js"; -import { scanArtifactInventory } from "../../../src/application/ArtifactInventory.js"; +import { scanArtifactInventory } from "../../../src/artifacts/inventory/ArtifactInventory.js"; import { parseJavaScriptApplicationGraph } from "../../../src/domain/javascript/javascriptApplicationGraph.js"; import { javascriptApplicationAnalysisResultSchema } from "../../../src/domain/javascript/javascriptApplicationAnalysis.js"; import { createJavaScriptSemanticGraph } from "../../../src/domain/javascript/javascriptSemanticGraph.js"; diff --git a/tests/evaluation/moduleBoundaries.test.ts b/tests/evaluation/moduleBoundaries.test.ts index 37c008492..c9b1a25c8 100644 --- a/tests/evaluation/moduleBoundaries.test.ts +++ b/tests/evaluation/moduleBoundaries.test.ts @@ -76,7 +76,7 @@ describe("incremental module import boundaries", () => { ["src/contracts/probe.ts", "../composition/android.js", false], [ "src/artifacts/javascript/probe.ts", - "../../application/ArtifactInventory.js", + "../../application/javascript/JavaScriptArtifactReconstruction.js", false, ], [ @@ -87,7 +87,7 @@ describe("incremental module import boundaries", () => { ["src/artifacts/javascript/probe.ts", "../../cli.js", false], [ "src/artifacts/ArtifactHash.ts", - "../application/ArtifactInventory/hash.js", + "../application/artifacts/ArtifactExtractionDestination.js", false, ], [ @@ -111,11 +111,7 @@ describe("incremental module import boundaries", () => { "../../artifacts/javascript/JavaScriptArtifactReader.js", true, ], - [ - "src/application/ArtifactInventory/probe.ts", - "../../artifacts/AsarArtifactReader.js", - true, - ], + ["src/artifacts/inventory/probe.ts", "../AsarArtifactReader.js", true], ["src/domain/probe.test.ts", "../composition/firmware.js", false], ["src/application/probe.ts", "../android/JadxProvider.js", false], ["src/application/probe.ts", "../composition/android.js", false], @@ -329,21 +325,30 @@ describe("test lane import boundaries", () => { }); }); -describe("Apple artifact producer ownership", () => { - it.each([ - ["../../application/Workflow.js", false], - ["../../composition/android.js", false], - ["../../cli.js", false], - ["../../domain/apple/plistValue.js", true], - ["../DirectoryArtifactReader.js", true], - ])("checks the producer dependency %s", (dependency, allowed) => { - const violations = inspectModuleBoundaries( - "src/artifacts/apple/probe.ts", - `import type { Value } from ${JSON.stringify(dependency)};`, - process.cwd(), - ); +describe.each(["apple", "inventory", "extraction"])( + "%s artifact producer ownership", + (owner) => { + it.each([ + ["../../application/Workflow.js", false], + ["../../composition/android.js", false], + ["../../cli.js", false], + ["../../server/registerEvidenceTools.js", false], + ["../../main.ts", false], + ["../../domain/apple/plistValue.js", true], + ["../../domain/artifactInventorySnapshot.js", true], + ["../../contracts/artifactGraph.js", true], + ["../DirectoryArtifactReader.js", true], + ["../ArtifactHash.js", true], + ])("checks the producer dependency %s", (dependency, allowed) => { + const violations = inspectModuleBoundaries( + `src/artifacts/${owner}/probe.ts`, + `import type { Value } from ${JSON.stringify(dependency)};`, + process.cwd(), + ); - expect(violations.length === 0).toBe(allowed); - if (!allowed) expect(violations[0]?.boundary).toBe("artifact-acquisition"); - }); -}); + expect(violations.length === 0).toBe(allowed); + if (!allowed) + expect(violations[0]?.boundary).toBe("artifact-acquisition"); + }); + }, +);