refactor(providers): use canonical artifact and managed identities

This commit is contained in:
morluto 2026-10-10 00:48:36 +08:00
parent 1b73b5ab4b
commit 87f0051496
6 changed files with 40 additions and 56 deletions

View File

@ -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 = {

View File

@ -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,

View File

@ -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,

View File

@ -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 } =

View File

@ -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,
}),
);
}
}

View File

@ -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,