mirror of
https://github.com/morluto/rea.git
synced 2026-11-12 01:41:21 +00:00
feat(analysis): make resource budgets recoverable across CLI and MCP (#9706)
* refactor(analysis): centralize resource budgets and recovery facts * feat(analysis): expose ASAR and Ghidra runtime admission controls * feat(artifacts): expose reader admission and preserve limited recognition * feat(javascript): expose recoverable semantic precision budgets * feat(web): add recoverable source-map budgets and compact retained views * feat(web): make historical capture decoding budgets recoverable * fix(desktop): enforce selected view policies across capture and export * feat(runtime): make Frida and LLDB retention budgets selectable * feat(native): expose diagnostic budgets and preserve exhaustion causes * feat(managed): expose recoverable snapshot and representation budgets * feat(metadata): make Go and Rust inspection budgets recoverable * feat(wasm): expose representation and producer admissions * feat(evm): expose per-call worker resource budgets * feat(android): make resource and string-pool omissions recoverable * feat(producers): expose command and recorded-capture budgets * docs(analysis): record recovery contracts and integrated validation * fix(docs): link calibration oracle from published verification pages * fix(docs): restore desktop task anchors and receipt links * test(analysis): align fixtures with selectable budget contracts * fix(analysis): remove source-location projector dependency cycle * test(analysis): refresh budget recovery and verifier regressions * test(analysis): preserve format and publication recovery expectations * test(windows): align conformance with owned runtime admission * fix(desktop): preserve selected alias kinds in exported state * test(analysis): align provider fixtures with recoverable budgets * test(desktop): validate emitted alias metadata structurally * fix(ghidra): classify bounded Windows endpoint refusals * test(cli): assert selectable artifact admission recovery * fix(cli): preserve capture provenance in environment builds
This commit is contained in:
1 parent
55b6d2ca20
commit
cb4e5cfbff
515 files changed
+21066
-3637
No files matched your search
@@ -90,6 +90,9 @@ const parameters = (
|
||||
input: AnalyzeJavaScriptApplicationInput,
|
||||
): EvidenceObservation["parameters"] => ({
|
||||
input_path: input.input_path,
|
||||
...(input.semantic_precision === undefined
|
||||
? {}
|
||||
: { semantic_precision: input.semantic_precision }),
|
||||
format: input.format,
|
||||
integrity_policy: input.integrity_policy,
|
||||
...(input.max_semantic_nodes === undefined
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
ASAR_HEADER_ADMISSION_SETTING,
|
||||
parseAsarHeaderAdmission,
|
||||
} from "../../config/asarHeaderAdmission.js";
|
||||
import { parseAsarListingAdmission } from "../../config/asarListingAdmission.js";
|
||||
import { z } from "zod";
|
||||
|
||||
import { ArtifactReaderFailure } from "../../artifacts/ArtifactReader.js";
|
||||
@@ -69,12 +70,22 @@ export const analyzeJavaScriptApplicationValidated = async (
|
||||
options.environment?.[ASAR_HEADER_ADMISSION_SETTING],
|
||||
);
|
||||
if (!asarHeaderAdmission.ok) return asarHeaderAdmission;
|
||||
const listingAdmission = parseAsarListingAdmission(
|
||||
options.environment?.REA_ASAR_MAX_LISTING_BYTES,
|
||||
);
|
||||
if (!listingAdmission.ok) return listingAdmission;
|
||||
const overrides = options.settings?.().overrides;
|
||||
const header = overrides?.["asar.max_header_bytes"];
|
||||
const acceptedAdmission =
|
||||
header === undefined
|
||||
const listing = overrides?.["asar.max_listing_bytes"];
|
||||
const acceptedAdmission = {
|
||||
...(header === undefined
|
||||
? asarHeaderAdmission.value
|
||||
: { maximumBytes: header, source: "runtime" as const };
|
||||
: { maximumBytes: header, source: "runtime" as const }),
|
||||
listing:
|
||||
listing === undefined
|
||||
? listingAdmission.value
|
||||
: { maximumBytes: listing, source: "runtime" as const },
|
||||
};
|
||||
let reconstructed: JavaScriptArtifactReconstructionResult | undefined;
|
||||
let result: JavaScriptApplicationAnalysisResult | undefined;
|
||||
let evidence: Evidence | undefined;
|
||||
|
||||
@@ -317,7 +317,9 @@ const graphCoverage = (context: JavaScriptArtifactGraphContext) => {
|
||||
const limits = [
|
||||
...new Map(
|
||||
[
|
||||
...semanticResourceLimitCoverage(resourceLimits),
|
||||
...semanticResourceBounds(context).flatMap(({ limit, precision }) =>
|
||||
semanticResourceLimitCoverage([limit], precision),
|
||||
),
|
||||
...executionLimits,
|
||||
...(inlineScriptsTruncated
|
||||
? [HTML_INLINE_SCRIPT_LOCATION_COVERAGE_LIMIT]
|
||||
@@ -340,17 +342,24 @@ const graphCoverage = (context: JavaScriptArtifactGraphContext) => {
|
||||
return completeApplicationCoverage();
|
||||
};
|
||||
|
||||
const semanticResourceBounds = (context: JavaScriptArtifactGraphContext) => [
|
||||
...new Map(
|
||||
context.analysis.files.flatMap(({ semantic }) =>
|
||||
semantic === null
|
||||
? []
|
||||
: semanticCoverageResourceLimits(semantic.ir.coverage).map((limit) => {
|
||||
const fact = { limit, precision: semantic.ir.coverage.precision };
|
||||
return [JSON.stringify(fact), fact] as const;
|
||||
}),
|
||||
),
|
||||
).values(),
|
||||
];
|
||||
|
||||
const semanticResourceLimits = (
|
||||
context: JavaScriptArtifactGraphContext,
|
||||
): JavaScriptSemanticResourceLimit[] =>
|
||||
[
|
||||
...new Set(
|
||||
context.analysis.files.flatMap(({ semantic }) =>
|
||||
semantic === null
|
||||
? []
|
||||
: semanticCoverageResourceLimits(semantic.ir.coverage),
|
||||
),
|
||||
),
|
||||
...new Set(semanticResourceBounds(context).map(({ limit }) => limit)),
|
||||
].sort();
|
||||
|
||||
const graphLimitations = (
|
||||
@@ -426,7 +435,9 @@ const graphLimitations = (
|
||||
"Sender, frame, URL, and origin checks are observations only; REA does not claim that they enforce a complete authorization policy.",
|
||||
]
|
||||
: []),
|
||||
...semanticResourceLimits(context).map(semanticResourceLimitReason),
|
||||
...semanticResourceBounds(context).map(({ limit, precision }) =>
|
||||
semanticResourceLimitReason(limit, precision),
|
||||
),
|
||||
...(context.analysis.files.some(
|
||||
({ javascript }) =>
|
||||
(javascript?.electron.native_addon_bindings.length ?? 0) > 0,
|
||||
|
||||
@@ -182,6 +182,9 @@ export const reconstructJavaScriptArtifact = async (
|
||||
: { fileNodes: input.max_semantic_nodes_per_file }),
|
||||
});
|
||||
const sourceLimits = {
|
||||
...(input.semantic_precision === undefined
|
||||
? {}
|
||||
: { semanticPrecision: input.semantic_precision }),
|
||||
heapMb:
|
||||
input.max_heap_mb ??
|
||||
overrides?.["javascript.max_heap_mb"] ??
|
||||
|
||||
@@ -518,7 +518,11 @@ const relationshipEvidence = (
|
||||
limitations: [
|
||||
...input.semantic.ir.limitations,
|
||||
...semanticCoverageResourceLimits(input.semantic.ir.coverage).map(
|
||||
semanticResourceLimitReason,
|
||||
(limit) =>
|
||||
semanticResourceLimitReason(
|
||||
limit,
|
||||
input.semantic.ir.coverage.precision,
|
||||
),
|
||||
),
|
||||
...limitations,
|
||||
],
|
||||
@@ -531,7 +535,10 @@ const semanticCoverage = (
|
||||
if (semantic.ir.coverage.status === "complete" && resourceLimits.length === 0)
|
||||
return completeApplicationCoverage();
|
||||
return partialApplicationCoverage(
|
||||
semanticResourceLimitCoverage(resourceLimits),
|
||||
semanticResourceLimitCoverage(
|
||||
resourceLimits,
|
||||
semantic.ir.coverage.precision,
|
||||
),
|
||||
semantic.ir.coverage.omittedCount,
|
||||
);
|
||||
};
|
||||
|
||||
@@ -723,15 +723,17 @@ const projectFileResourceLimits = (
|
||||
family: "data-flow",
|
||||
relation_kinds: ["defines"],
|
||||
reason: "resource-limit",
|
||||
detail: semanticResourceLimitReason(limit),
|
||||
detail: semanticResourceLimitReason(limit, context.ir.coverage.precision),
|
||||
candidate_node_ids: [],
|
||||
evidence: {
|
||||
...unknownSemanticEvidence(context.file, null),
|
||||
coverage: partialApplicationCoverage(
|
||||
semanticResourceLimitCoverage([limit]),
|
||||
semanticResourceLimitCoverage([limit], context.ir.coverage.precision),
|
||||
null,
|
||||
),
|
||||
limitations: [semanticResourceLimitReason(limit)],
|
||||
limitations: [
|
||||
semanticResourceLimitReason(limit, context.ir.coverage.precision),
|
||||
],
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -859,15 +861,17 @@ function* createCallSiteNodes(
|
||||
family: "call-flow",
|
||||
relation_kinds: ["argument-to-parameter"],
|
||||
reason: "resource-limit",
|
||||
detail: semanticResourceLimitReason(limit),
|
||||
detail: semanticResourceLimitReason(limit, ir.coverage.precision),
|
||||
candidate_node_ids: [],
|
||||
evidence: {
|
||||
...unknownSemanticEvidence(file, call.location),
|
||||
coverage: partialApplicationCoverage(
|
||||
semanticResourceLimitCoverage([limit]),
|
||||
semanticResourceLimitCoverage([limit], ir.coverage.precision),
|
||||
null,
|
||||
),
|
||||
limitations: [semanticResourceLimitReason(limit)],
|
||||
limitations: [
|
||||
semanticResourceLimitReason(limit, ir.coverage.precision),
|
||||
],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ it("cancels actual call-path work while its first seed indexes a long block", as
|
||||
).rejects.toMatchObject({ reason: "cancelled", cause: reason });
|
||||
expect(work.next()).toEqual({ done: true, value: undefined });
|
||||
expect(accumulator.ipc).toEqual([]);
|
||||
expect(accumulator.electronCallPathLimitReached).toBeUndefined();
|
||||
expect(accumulator.electronCallPathLimits).toBeUndefined();
|
||||
|
||||
// A new analysis owns a new index and can still complete the same source.
|
||||
const completed = createJavaScriptAnalysisAccumulator(source.length);
|
||||
@@ -57,5 +57,5 @@ it("cancels actual call-path work while its first seed indexes a long block", as
|
||||
),
|
||||
),
|
||||
).toContainEqual(expect.objectContaining({ entry: "first", conditions: [] }));
|
||||
expect(completed.electronCallPathLimitReached).toBeUndefined();
|
||||
expect(completed.electronCallPathLimits).toBeUndefined();
|
||||
});
|
||||
Reference in new issue
Block a user