From 87f0051496aff1b05ab24d6b63f79884f4ca9b8f Mon Sep 17 00:00:00 2001 From: morluto <76467478+morluto@users.noreply.github.com> Date: Sat, 10 Oct 2026 00:48:36 +0800 Subject: [PATCH] refactor(providers): use canonical artifact and managed identities --- src/application/InvestigationProviders.ts | 8 +++--- src/artifacts/ArtifactProvider.ts | 28 +++++++++---------- src/artifacts/ArtifactProviderMetadata.ts | 11 ++------ src/composition/auxiliaryAnalysisProviders.ts | 16 +++++------ src/dotnet/ManagedStaticProvider.ts | 22 ++++++++------- src/dotnet/ManagedStaticProviderMetadata.ts | 11 ++------ 6 files changed, 40 insertions(+), 56 deletions(-) diff --git a/src/application/InvestigationProviders.ts b/src/application/InvestigationProviders.ts index 03d705252..4861272a0 100644 --- a/src/application/InvestigationProviders.ts +++ b/src/application/InvestigationProviders.ts @@ -24,18 +24,18 @@ export const workflowAnalysisProfile = ( }); /** Provider identity for deterministic artifact inventories. */ -export const ARTIFACT_GRAPH_PROVIDER = { +export const ARTIFACT_GRAPH_PROVIDER = Object.freeze({ id: "rea-artifact-graph", name: "REA safe artifact graph provider", version: "1", -} as const; +} as const); /** Provider identity for execution-free managed PE/CLI analysis. */ -export const MANAGED_STATIC_PROVIDER = { +export const MANAGED_STATIC_PROVIDER = Object.freeze({ id: "rea-dotnet-static", name: "REA managed static analysis provider", version: "1", -} as const; +} as const); /** Provider identity for deterministic managed-code comparison workflows. */ export const MANAGED_WORKFLOW_PROVIDER = { diff --git a/src/artifacts/ArtifactProvider.ts b/src/artifacts/ArtifactProvider.ts index e4b514a4f..fe5d24ef0 100644 --- a/src/artifacts/ArtifactProvider.ts +++ b/src/artifacts/ArtifactProvider.ts @@ -33,10 +33,8 @@ import type { JsonValue } from "../domain/jsonValue.js"; import { interfaceBuilderLimitsSchema } from "../domain/apple/interfaceBuilderGraph.js"; import { err, ok, type Result } from "../domain/result.js"; import { ArtifactReaderFailure } from "./ArtifactReader.js"; -import { - ARTIFACT_PROVIDER_IDENTITY as IDENTITY, - artifactCapabilities, -} from "./ArtifactProviderMetadata.js"; +import { artifactCapabilities } from "./ArtifactProviderMetadata.js"; +import { ARTIFACT_GRAPH_PROVIDER } from "../application/InvestigationProviders.js"; import { createEvidence } from "../domain/evidence.js"; import { createArtifactInspection } from "../domain/artifactInspection.js"; @@ -56,7 +54,7 @@ export class ArtifactProvider implements AnalysisProvider { } identity(): ProviderIdentity { - return IDENTITY; + return ARTIFACT_GRAPH_PROVIDER; } capabilities(): readonly CapabilityDescriptor[] { @@ -81,11 +79,11 @@ class ArtifactClient implements AnalysisClient { options?: ExecutionOptions, ) { if (operation === "health") - return ok(createAnalysisExecution(null, IDENTITY)); + return ok(createAnalysisExecution(null, ARTIFACT_GRAPH_PROVIDER)); if (!isArtifactOperation(operation)) return err( new AnalysisCapabilityUnavailableError( - IDENTITY.id, + ARTIFACT_GRAPH_PROVIDER.id, operation, "Operation is not implemented by artifact graph provider.", ), @@ -113,7 +111,7 @@ class ArtifactClient implements AnalysisClient { ...(options?.signal === undefined ? {} : { signal: options.signal }), }); return ok( - createAnalysisExecution(result, IDENTITY, { + createAnalysisExecution(result, ARTIFACT_GRAPH_PROVIDER, { limitations: result.limitations, locations: result.documents.map(({ relative_path: path }) => ({ kind: "artifact-path" as const, @@ -166,7 +164,7 @@ class ArtifactClient implements AnalysisClient { `Active archive digest changed: expected ${this.target.sha256}, observed ${result.archive_sha256}`, ); return ok( - createAnalysisExecution(result, IDENTITY, { + createAnalysisExecution(result, ARTIFACT_GRAPH_PROVIDER, { limitations: result.limitations, locations: [{ kind: "artifact-path", path: result.archive_path }], }), @@ -189,7 +187,7 @@ class ArtifactClient implements AnalysisClient { options?.signal, ); return ok( - createAnalysisExecution(result, IDENTITY, { + createAnalysisExecution(result, ARTIFACT_GRAPH_PROVIDER, { rawResult: null, limitations: result.limitations, subject: subjectFor( @@ -206,7 +204,7 @@ class ArtifactClient implements AnalysisClient { const parsed = artifactInventoryInputSchema.parse(parameters); const result = await this.inventory(parsed, options); return ok( - createAnalysisExecution(result, IDENTITY, { + createAnalysisExecution(result, ARTIFACT_GRAPH_PROVIDER, { rawResult: null, limitations: result.limitations, subject: subjectFor( @@ -262,7 +260,7 @@ class ArtifactClient implements AnalysisClient { ...(options?.signal === undefined ? {} : { signal: options.signal }), }); return ok( - createAnalysisExecution(result, IDENTITY, { + createAnalysisExecution(result, ARTIFACT_GRAPH_PROVIDER, { limitations: result.limitations, locations: result.catalogs.map(({ path }) => ({ kind: "artifact-path" as const, @@ -296,7 +294,7 @@ class ArtifactClient implements AnalysisClient { ...(options?.signal === undefined ? {} : { signal: options.signal }), }); return ok( - createAnalysisExecution(result, IDENTITY, { + createAnalysisExecution(result, ARTIFACT_GRAPH_PROVIDER, { limitations: result.limitations, locations: result.images.map(({ path }) => ({ kind: "artifact-path" as const, @@ -329,7 +327,7 @@ class ArtifactClient implements AnalysisClient { kind: "artifact-path" as const, path, })); - const inventoryEvidence = createEvidence(subject, IDENTITY, { + const inventoryEvidence = createEvidence(subject, ARTIFACT_GRAPH_PROVIDER, { operation: "inventory_artifact", parameters: inventoryParameters, result: inventory, @@ -345,7 +343,7 @@ class ArtifactClient implements AnalysisClient { message: "inventory substep completed", }); return ok( - createAnalysisExecution(result, IDENTITY, { + createAnalysisExecution(result, ARTIFACT_GRAPH_PROVIDER, { rawResult: null, limitations: result.limitations, subject, diff --git a/src/artifacts/ArtifactProviderMetadata.ts b/src/artifacts/ArtifactProviderMetadata.ts index aa36eeaf4..dc138f94d 100644 --- a/src/artifacts/ArtifactProviderMetadata.ts +++ b/src/artifacts/ArtifactProviderMetadata.ts @@ -1,14 +1,7 @@ -import type { - CapabilityDescriptor, - ProviderIdentity, -} from "../application/AnalysisProvider.js"; +import type { CapabilityDescriptor } from "../application/AnalysisProvider.js"; import { ARTIFACT_GRAPH_PROVIDER } from "../application/InvestigationProviders.js"; import { ARTIFACT_ANALYSIS_OPERATIONS } from "../contracts/artifactToolContracts.js"; -/** Identity of artifact inventory and owned extraction observations. */ -export const ARTIFACT_PROVIDER_IDENTITY: ProviderIdentity = Object.freeze( - ARTIFACT_GRAPH_PROVIDER, -); /** Declare artifact coverage without constructing readers or acquiring resources. */ export const artifactCapabilities = ( platform: NodeJS.Platform = process.platform, @@ -16,7 +9,7 @@ export const artifactCapabilities = ( Object.freeze( ARTIFACT_ANALYSIS_OPERATIONS.map((operation) => { const common = { - provider: ARTIFACT_PROVIDER_IDENTITY, + provider: ARTIFACT_GRAPH_PROVIDER, operation, effects: Object.freeze({ mutatesArtifact: false, diff --git a/src/composition/auxiliaryAnalysisProviders.ts b/src/composition/auxiliaryAnalysisProviders.ts index 7e6b797b4..c094b6d9f 100644 --- a/src/composition/auxiliaryAnalysisProviders.ts +++ b/src/composition/auxiliaryAnalysisProviders.ts @@ -1,13 +1,11 @@ import { snapshotEnvironment } from "../process/snapshotEnvironment.js"; import type { LazyAnalysisProvider } from "../application/binary/LazyAnalysisProvider.js"; +import { artifactCapabilities } from "../artifacts/ArtifactProviderMetadata.js"; import { - ARTIFACT_PROVIDER_IDENTITY, - artifactCapabilities, -} from "../artifacts/ArtifactProviderMetadata.js"; -import { - MANAGED_STATIC_PROVIDER_IDENTITY, - managedStaticCapabilities, -} from "../dotnet/ManagedStaticProviderMetadata.js"; + ARTIFACT_GRAPH_PROVIDER, + MANAGED_STATIC_PROVIDER, +} from "../application/InvestigationProviders.js"; +import { managedStaticCapabilities } from "../dotnet/ManagedStaticProviderMetadata.js"; import { NATIVE_MACOS_PROVIDER_IDENTITY, nativeMacOSCapabilities, @@ -25,7 +23,7 @@ export const auxiliaryAnalysisProviderDeclarations = ( const environment = snapshotEnvironment(selectedEnvironment, platform); return [ { - identity: ARTIFACT_PROVIDER_IDENTITY, + identity: ARTIFACT_GRAPH_PROVIDER, capabilities: artifactCapabilities(platform), load: async () => { const { ArtifactProvider } = @@ -43,7 +41,7 @@ export const auxiliaryAnalysisProviderDeclarations = ( }, }, { - identity: MANAGED_STATIC_PROVIDER_IDENTITY, + identity: MANAGED_STATIC_PROVIDER, capabilities: managedStaticCapabilities(), load: async () => { const { ManagedStaticProvider } = diff --git a/src/dotnet/ManagedStaticProvider.ts b/src/dotnet/ManagedStaticProvider.ts index 60c75b8f9..68f0c0696 100644 --- a/src/dotnet/ManagedStaticProvider.ts +++ b/src/dotnet/ManagedStaticProvider.ts @@ -11,10 +11,8 @@ import { type ExecutionOptions, type ProviderIdentity, } from "../application/AnalysisProvider.js"; -import { - MANAGED_STATIC_PROVIDER_IDENTITY as IDENTITY, - managedStaticCapabilities, -} from "./ManagedStaticProviderMetadata.js"; +import { managedStaticCapabilities } from "./ManagedStaticProviderMetadata.js"; +import { MANAGED_STATIC_PROVIDER } from "../application/InvestigationProviders.js"; import { MANAGED_TOOL_CONTRACTS, managedTargetInputSchema, @@ -46,7 +44,7 @@ export class ManagedStaticProvider implements AnalysisProvider { managedStaticCapabilities(); identity(): ProviderIdentity { - return IDENTITY; + return MANAGED_STATIC_PROVIDER; } capabilities(): readonly CapabilityDescriptor[] { @@ -69,11 +67,11 @@ class ManagedStaticClient implements AnalysisClient { options?: ExecutionOptions, ) { if (operation === "health") - return ok(createAnalysisExecution(null, IDENTITY)); + return ok(createAnalysisExecution(null, MANAGED_STATIC_PROVIDER)); if (!isManagedOperation(operation)) return err( new AnalysisCapabilityUnavailableError( - IDENTITY.id, + MANAGED_STATIC_PROVIDER.id, operation, "Operation is not implemented by the managed static provider.", ), @@ -81,7 +79,7 @@ class ManagedStaticClient implements AnalysisClient { if (this.target.format !== "pe") return err( new AnalysisCapabilityUnavailableError( - IDENTITY.id, + MANAGED_STATIC_PROVIDER.id, operation, `Managed static triage requires a PE target; observed ${this.target.format}.`, ), @@ -111,7 +109,7 @@ class ManagedStaticClient implements AnalysisClient { this.target, ); return ok( - createAnalysisExecution(result, IDENTITY, { + createAnalysisExecution(result, MANAGED_STATIC_PROVIDER, { rawResult: null, limitations: result.limitations, subject: this.target, @@ -121,7 +119,11 @@ class ManagedStaticClient implements AnalysisClient { } catch (cause: unknown) { if (options?.signal?.aborted === true) return err(new AnalysisCancelledError(operation)); - return err(new ProviderAdapterError(IDENTITY.id, operation, { cause })); + return err( + new ProviderAdapterError(MANAGED_STATIC_PROVIDER.id, operation, { + cause, + }), + ); } } diff --git a/src/dotnet/ManagedStaticProviderMetadata.ts b/src/dotnet/ManagedStaticProviderMetadata.ts index 04b412828..a346cee5c 100644 --- a/src/dotnet/ManagedStaticProviderMetadata.ts +++ b/src/dotnet/ManagedStaticProviderMetadata.ts @@ -1,23 +1,16 @@ -import type { - CapabilityDescriptor, - ProviderIdentity, -} from "../application/AnalysisProvider.js"; +import type { CapabilityDescriptor } from "../application/AnalysisProvider.js"; import { MANAGED_STATIC_PROVIDER } from "../application/InvestigationProviders.js"; import { MANAGED_TOOL_CONTRACTS, type ManagedToolName, } from "../contracts/managed/managedToolContracts.js"; -/** Identity of execution-free managed metadata observations. */ -export const MANAGED_STATIC_PROVIDER_IDENTITY: ProviderIdentity = Object.freeze( - MANAGED_STATIC_PROVIDER, -); /** Declare managed metadata coverage without opening or loading an assembly. */ export const managedStaticCapabilities = (): readonly CapabilityDescriptor[] => Object.freeze( MANAGED_TOOL_CONTRACTS.map((contract) => Object.freeze({ - provider: MANAGED_STATIC_PROVIDER_IDENTITY, + provider: MANAGED_STATIC_PROVIDER, operation: contract.name, available: true as const, reason: null,