fix(cli): route JavaScript applications from analyze

This commit is contained in:
N0zoM1z0 2026-07-21 23:42:28 +08:00
parent 5a908a03a6
commit 74965d9088
17 changed files with 227 additions and 68 deletions

View File

@ -262,7 +262,7 @@ Uninstall preserves Hopper, Node.js, evidence, captures, external evidence roots
| Inspect or decompile one part of an app from the Terminal | `rea analyze` or `rea decompile` |
| Validate, canonicalize, or compare Evidence v2 bundles | `rea evidence-import`, `rea evidence-export`, or `rea compare` |
| Run or resume a persistent two-version artifact analysis | `rea investigate-versions` |
| Map a local JavaScript/Electron application without executing it | `rea analyze-javascript-application` |
| Map a local JavaScript/Electron application without executing it | `rea analyze PATH --approved` or `rea analyze-javascript-application` |
| Reuse immutable analysis results without relaunching a provider | Pass `--snapshot /approved/path/analysis.json` to a deep-analysis command |
| Import source as historical reference | `rea import-reference-source` |
| Capture or compare controlled process behavior | `rea capture-process` or `rea compare-process-captures` |
@ -276,9 +276,16 @@ rea evidence-import /absolute/path/to/evidence/bundle.json
rea evidence-export /absolute/path/to/evidence/bundle.json /absolute/path/to/evidence/canonical.json
rea compare /absolute/path/to/evidence/left.json /absolute/path/to/evidence/right.json
rea investigate-versions /absolute/path/to/releases/v1 /absolute/path/to/releases/v2 /absolute/path/to/evidence/releases.json --yes --workspace-name releases
rea analyze /absolute/path/to/releases/app.asar --approved --json
rea analyze-javascript-application /absolute/path/to/releases/app.asar --approved --json
```
For a directory or `.asar`, generic `rea analyze` automatically selects the
static JavaScript application provider when neither `--provider` nor
`--snapshot` is supplied. The dedicated command remains available for explicit
format and resource-limit controls. Both routes require `--approved` and an
administrator-approved investigation input root.
If REA is registered with an MCP client, run approved `rea setup` while the
explicit investigation-root variable is set, then restart that client. Setup
copies this non-secret policy into the managed registration; changing the shell

View File

@ -14,14 +14,14 @@
<section class="tsd-panel">
<ul class="tsd-signatures">
<li class="">
<div class="tsd-signature tsd-anchor-link" id="argumentnode"><span class="tsd-kind-call-signature">argumentNode</span><span class="tsd-signature-symbol">(</span><br/>    <span class="tsd-kind-parameter">argument</span><span class="tsd-signature-symbol">:</span><br/>        <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ArgumentPlaceholder</span><br/>        <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">JSXNamespacedName</span><br/>        <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">SpreadElement</span><br/>        <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">Expression</span><br/>        <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">null</span><br/>        <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">undefined</span><span class="tsd-signature-symbol">,</span><br/><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Node</span><br/><span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">undefined</span><a href="#argumentnode" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></div>
<div class="tsd-signature tsd-anchor-link" id="argumentnode"><span class="tsd-kind-call-signature">argumentNode</span><span class="tsd-signature-symbol">(</span><br/>    <span class="tsd-kind-parameter">argument</span><span class="tsd-signature-symbol">:</span><br/>        <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">Expression</span><br/>        <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">SpreadElement</span><br/>        <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">JSXNamespacedName</span><br/>        <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ArgumentPlaceholder</span><br/>        <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">null</span><br/>        <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">undefined</span><span class="tsd-signature-symbol">,</span><br/><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Node</span><br/><span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">undefined</span><a href="#argumentnode" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></div>
<div class="tsd-description">
<div class="tsd-comment tsd-typography"><p>Normalize one Babel call/new argument into the inert node shared by inspectors.</p>
</div>
<div class="tsd-parameters">
<h4 class="tsd-parameters-title">Parameters</h4>
<ul class="tsd-parameter-list">
<li><span><span class="tsd-kind-parameter">argument</span>: <br/>    <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ArgumentPlaceholder</span><br/>    <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">JSXNamespacedName</span><br/>    <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">SpreadElement</span><br/>    <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">Expression</span><br/>    <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">null</span><br/>    <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">undefined</span></span></li></ul></div>
<li><span><span class="tsd-kind-parameter">argument</span>: <br/>    <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">Expression</span><br/>    <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">SpreadElement</span><br/>    <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">JSXNamespacedName</span><br/>    <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ArgumentPlaceholder</span><br/>    <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">null</span><br/>    <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">undefined</span></span></li></ul></div>
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Node</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">undefined</span></h4><aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/morluto/rea/blob/main/src/domain/javascriptStaticAnalysisHelpers.ts#L43">src/domain/javascriptStaticAnalysisHelpers.ts:43</a></li></ul></aside></div></li></ul></section></div>

View File

@ -14,7 +14,7 @@
<section class="tsd-panel">
<ul class="tsd-signatures">
<li class="">
<div class="tsd-signature tsd-anchor-link" id="endpointargument"><span class="tsd-kind-call-signature">endpointArgument</span><span class="tsd-signature-symbol">(</span><br/>    <span class="tsd-kind-parameter">name</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">,</span><br/>    <span class="tsd-kind-parameter">args</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-keyword">readonly</span> (<br/>        <span class="tsd-signature-type">ArgumentPlaceholder</span><br/>        <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">JSXNamespacedName</span><br/>        <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">SpreadElement</span><br/>        <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">Expression</span><br/>    )<span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">,</span><br/><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">undefined</span><a href="#endpointargument" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></div>
<div class="tsd-signature tsd-anchor-link" id="endpointargument"><span class="tsd-kind-call-signature">endpointArgument</span><span class="tsd-signature-symbol">(</span><br/>    <span class="tsd-kind-parameter">name</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">,</span><br/>    <span class="tsd-kind-parameter">args</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-keyword">readonly</span> (<br/>        <span class="tsd-signature-type">Expression</span><br/>        <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">SpreadElement</span><br/>        <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">JSXNamespacedName</span><br/>        <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ArgumentPlaceholder</span><br/>    )<span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">,</span><br/><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">undefined</span><a href="#endpointargument" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></div>
<div class="tsd-description">
<div class="tsd-comment tsd-typography"><p>Select the literal URL argument for recognized network callees.</p>
</div>
@ -22,7 +22,7 @@
<h4 class="tsd-parameters-title">Parameters</h4>
<ul class="tsd-parameter-list">
<li><span><span class="tsd-kind-parameter">name</span>: <span class="tsd-signature-type">string</span></span></li>
<li><span><span class="tsd-kind-parameter">args</span>: <span class="tsd-signature-keyword">readonly</span> (<span class="tsd-signature-type">ArgumentPlaceholder</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">JSXNamespacedName</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">SpreadElement</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">Expression</span>)<span class="tsd-signature-symbol">[]</span></span></li></ul></div>
<li><span><span class="tsd-kind-parameter">args</span>: <span class="tsd-signature-keyword">readonly</span> (<span class="tsd-signature-type">Expression</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">SpreadElement</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">JSXNamespacedName</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ArgumentPlaceholder</span>)<span class="tsd-signature-symbol">[]</span></span></li></ul></div>
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">undefined</span></h4><aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/morluto/rea/blob/main/src/domain/javascriptStaticAnalysisHelpers.ts#L279">src/domain/javascriptStaticAnalysisHelpers.ts:279</a></li></ul></aside></div></li></ul></section></div>

View File

@ -14,14 +14,14 @@
<section class="tsd-panel">
<ul class="tsd-signatures">
<li class="">
<div class="tsd-signature tsd-anchor-link" id="factoryrequirename"><span class="tsd-kind-call-signature">factoryRequireName</span><span class="tsd-signature-symbol">(</span><br/>    <span class="tsd-kind-parameter">factory</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">ArrowFunctionExpression</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">FunctionExpression</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ObjectMethod</span><span class="tsd-signature-symbol">,</span><br/><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">null</span><a href="#factoryrequirename" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></div>
<div class="tsd-signature tsd-anchor-link" id="factoryrequirename"><span class="tsd-kind-call-signature">factoryRequireName</span><span class="tsd-signature-symbol">(</span><br/>    <span class="tsd-kind-parameter">factory</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">FunctionExpression</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ArrowFunctionExpression</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ObjectMethod</span><span class="tsd-signature-symbol">,</span><br/><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">null</span><a href="#factoryrequirename" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></div>
<div class="tsd-description">
<div class="tsd-comment tsd-typography"><p>Read the factory-local bundler require parameter when declared.</p>
</div>
<div class="tsd-parameters">
<h4 class="tsd-parameters-title">Parameters</h4>
<ul class="tsd-parameter-list">
<li><span><span class="tsd-kind-parameter">factory</span>: <span class="tsd-signature-type">ArrowFunctionExpression</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">FunctionExpression</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ObjectMethod</span></span></li></ul></div>
<li><span><span class="tsd-kind-parameter">factory</span>: <span class="tsd-signature-type">FunctionExpression</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ArrowFunctionExpression</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ObjectMethod</span></span></li></ul></div>
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">null</span></h4><aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/morluto/rea/blob/main/src/domain/javascriptStaticAnalysisHelpers.ts#L124">src/domain/javascriptStaticAnalysisHelpers.ts:124</a></li></ul></aside></div></li></ul></section></div>

View File

@ -14,15 +14,15 @@
<section class="tsd-panel">
<ul class="tsd-signatures">
<li class="">
<div class="tsd-signature tsd-anchor-link" id="modulefactory"><span class="tsd-kind-call-signature">moduleFactory</span><span class="tsd-signature-symbol">(</span><br/>    <span class="tsd-kind-parameter">property</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">ObjectMethod</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ObjectProperty</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">SpreadElement</span><span class="tsd-signature-symbol">,</span><br/><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">ArrowFunctionExpression</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">FunctionExpression</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ObjectMethod</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">undefined</span><a href="#modulefactory" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></div>
<div class="tsd-signature tsd-anchor-link" id="modulefactory"><span class="tsd-kind-call-signature">moduleFactory</span><span class="tsd-signature-symbol">(</span><br/>    <span class="tsd-kind-parameter">property</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">SpreadElement</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ObjectMethod</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ObjectProperty</span><span class="tsd-signature-symbol">,</span><br/><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">FunctionExpression</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ArrowFunctionExpression</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ObjectMethod</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">undefined</span><a href="#modulefactory" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></div>
<div class="tsd-description">
<div class="tsd-comment tsd-typography"><p>Return a literal function factory from one module-table property.</p>
</div>
<div class="tsd-parameters">
<h4 class="tsd-parameters-title">Parameters</h4>
<ul class="tsd-parameter-list">
<li><span><span class="tsd-kind-parameter">property</span>: <span class="tsd-signature-type">ObjectMethod</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ObjectProperty</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">SpreadElement</span></span></li></ul></div>
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">ArrowFunctionExpression</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">FunctionExpression</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ObjectMethod</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">undefined</span></h4><aside class="tsd-sources">
<li><span><span class="tsd-kind-parameter">property</span>: <span class="tsd-signature-type">SpreadElement</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ObjectMethod</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ObjectProperty</span></span></li></ul></div>
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">FunctionExpression</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ArrowFunctionExpression</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ObjectMethod</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">undefined</span></h4><aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/morluto/rea/blob/main/src/domain/javascriptStaticAnalysisHelpers.ts#L93">src/domain/javascriptStaticAnalysisHelpers.ts:93</a></li></ul></aside></div></li></ul></section></div>
<div class="col-sidebar">

View File

@ -14,14 +14,14 @@
<section class="tsd-panel">
<ul class="tsd-signatures">
<li class="">
<div class="tsd-signature tsd-anchor-link" id="modulepropertyname"><span class="tsd-kind-call-signature">modulePropertyName</span><span class="tsd-signature-symbol">(</span><br/>    <span class="tsd-kind-parameter">property</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">ObjectMethod</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ObjectProperty</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">SpreadElement</span><span class="tsd-signature-symbol">,</span><br/><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><a href="#modulepropertyname" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></div>
<div class="tsd-signature tsd-anchor-link" id="modulepropertyname"><span class="tsd-kind-call-signature">modulePropertyName</span><span class="tsd-signature-symbol">(</span><br/>    <span class="tsd-kind-parameter">property</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">SpreadElement</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ObjectMethod</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ObjectProperty</span><span class="tsd-signature-symbol">,</span><br/><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><a href="#modulepropertyname" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></div>
<div class="tsd-description">
<div class="tsd-comment tsd-typography"><p>Derive a bounded literal or explicitly computed module key.</p>
</div>
<div class="tsd-parameters">
<h4 class="tsd-parameters-title">Parameters</h4>
<ul class="tsd-parameter-list">
<li><span><span class="tsd-kind-parameter">property</span>: <span class="tsd-signature-type">ObjectMethod</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ObjectProperty</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">SpreadElement</span></span></li></ul></div>
<li><span><span class="tsd-kind-parameter">property</span>: <span class="tsd-signature-type">SpreadElement</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ObjectMethod</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ObjectProperty</span></span></li></ul></div>
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">string</span></h4><aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/morluto/rea/blob/main/src/domain/javascriptStaticAnalysisHelpers.ts#L111">src/domain/javascriptStaticAnalysisHelpers.ts:111</a></li></ul></aside></div></li></ul></section></div>

View File

@ -14,7 +14,7 @@
<section class="tsd-panel">
<ul class="tsd-signatures">
<li class="">
<div class="tsd-signature tsd-anchor-link" id="endpointargument"><span class="tsd-kind-call-signature">endpointArgument</span><span class="tsd-signature-symbol">(</span><br/>    <span class="tsd-kind-parameter">name</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">,</span><br/>    <span class="tsd-kind-parameter">args</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-keyword">readonly</span> (<br/>        <span class="tsd-signature-type">ArgumentPlaceholder</span><br/>        <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">JSXNamespacedName</span><br/>        <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">SpreadElement</span><br/>        <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">Expression</span><br/>    )<span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">,</span><br/><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">undefined</span><a href="#endpointargument" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></div>
<div class="tsd-signature tsd-anchor-link" id="endpointargument"><span class="tsd-kind-call-signature">endpointArgument</span><span class="tsd-signature-symbol">(</span><br/>    <span class="tsd-kind-parameter">name</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">,</span><br/>    <span class="tsd-kind-parameter">args</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-keyword">readonly</span> (<br/>        <span class="tsd-signature-type">Expression</span><br/>        <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">SpreadElement</span><br/>        <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">JSXNamespacedName</span><br/>        <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ArgumentPlaceholder</span><br/>    )<span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">,</span><br/><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">undefined</span><a href="#endpointargument" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></div>
<div class="tsd-description">
<div class="tsd-comment tsd-typography"><p>Pick the endpoint argument for common network-call patterns.</p>
</div>
@ -22,7 +22,7 @@
<h4 class="tsd-parameters-title">Parameters</h4>
<ul class="tsd-parameter-list">
<li><span><span class="tsd-kind-parameter">name</span>: <span class="tsd-signature-type">string</span></span></li>
<li><span><span class="tsd-kind-parameter">args</span>: <span class="tsd-signature-keyword">readonly</span> (<span class="tsd-signature-type">ArgumentPlaceholder</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">JSXNamespacedName</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">SpreadElement</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">Expression</span>)<span class="tsd-signature-symbol">[]</span></span></li></ul></div>
<li><span><span class="tsd-kind-parameter">args</span>: <span class="tsd-signature-keyword">readonly</span> (<span class="tsd-signature-type">Expression</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">SpreadElement</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">JSXNamespacedName</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">ArgumentPlaceholder</span>)<span class="tsd-signature-symbol">[]</span></span></li></ul></div>
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">undefined</span></h4><aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/morluto/rea/blob/main/src/domain/webBundleAnalyzerAst.ts#L85">src/domain/webBundleAnalyzerAst.ts:85</a></li></ul></aside></div></li></ul></section></div>

File diff suppressed because one or more lines are too long

View File

@ -3,8 +3,9 @@
REA can project an operator-supplied Electron/JavaScript application directory
or ASAR into [JavaScript Application Graph v1](javascript-application-graph.md)
without executing application code. The target-free
`analyze_javascript_application` MCP tool and
`rea analyze-javascript-application` CLI command expose the same application
`analyze_javascript_application` MCP tool, dedicated
`rea analyze-javascript-application` CLI command, and generic
`rea analyze PATH --approved` directory/ASAR route expose the same application
service and return an Evidence v2 envelope containing the graph and an Electron
boundary summary.
@ -22,11 +23,18 @@ remain beneath that root after canonicalization:
```bash
export REA_INVESTIGATION_INPUT_ROOTS_JSON='["/absolute/path/to/apps"]'
rea analyze /absolute/path/to/apps/app.asar --approved --json
rea analyze-javascript-application /absolute/path/to/apps/app.asar \
--approved \
--json
```
Generic `rea analyze` selects this static provider for directories and `.asar`
paths when neither `--provider` nor `--snapshot` is supplied. Use the dedicated
command when setting explicit format or reconstruction limits. Native targets,
single JavaScript files, `.app` bundles, and explicit deep-provider or snapshot
requests retain the native deep-analysis route.
When configuring an MCP client, set the variable before approved setup so REA
copies the explicit non-secret root policy into the managed registration:

View File

@ -4,7 +4,7 @@ import { TextReader, Uint8ArrayWriter, ZipWriter } from "@zip.js/zip.js";
import { json, run } from "./lib/verify-package-core.mjs";
/** Run inventory-artifact and analyze-javascript-application against packaged fixtures. */
/** Run artifact and JavaScript application analysis against packaged fixtures. */
export async function verifyPackageArtifactAndElectron({
cli,
workspace,
@ -61,6 +61,25 @@ export async function verifyPackageArtifactAndElectron({
?.paired_renderer_transmissions !== 1
)
throw new Error("packaged JavaScript application analysis CLI failed");
const routedApplicationAnalysis = json(
await run(
cli,
["analyze", applicationRoot, "--approved", "--json"],
environment,
),
);
assertRoutedApplicationAnalysis(routedApplicationAnalysis);
return { artifactArchive };
}
const assertRoutedApplicationAnalysis = (analysis) => {
if (
analysis.operation !== "analyze_javascript_application" ||
analysis.provider?.id !== "rea-javascript-application" ||
analysis.normalized_result?.format !== "directory" ||
analysis.normalized_result?.summary?.ipc?.paired_renderer_transmissions !==
1
)
throw new Error("packaged routed JavaScript application analysis failed");
};

View File

@ -13,8 +13,9 @@ import {
PermissionRequiredError,
type AnalysisError,
} from "../domain/errors.js";
import { err, ok, type Result } from "../domain/result.js";
import type { Evidence } from "../domain/evidence.js";
import { projectInputIssues } from "../domain/inputIssueProjection.js";
import { err, ok, type Result } from "../domain/result.js";
import type { ExecutionOptions } from "./AnalysisProvider.js";
import { createJavaScriptApplicationEvidence } from "./JavaScriptApplicationEvidence.js";
import { reconstructJavaScriptArtifact } from "./JavaScriptArtifactReconstruction.js";
@ -29,7 +30,14 @@ export const analyzeJavaScriptApplication = async (
options: ExecutionOptions = {},
): Promise<Result<Evidence, AnalysisError>> => {
const parsed = analyzeJavaScriptApplicationInputSchema.safeParse(rawInput);
if (!parsed.success) return err(new AnalysisInputError(OPERATION));
if (!parsed.success)
return err(
new AnalysisInputError(
OPERATION,
undefined,
projectInputIssues(parsed.error.issues, rawInput),
),
);
return analyzeJavaScriptApplicationValidated(authority, parsed.data, options);
};

View File

@ -1,4 +1,6 @@
import { z } from "incur";
import { stat } from "node:fs/promises";
import { resolve } from "node:path";
import { runDirectAnalysis } from "../application/DirectAnalysis.js";
import { CLI_COMMANDS } from "../cliCommandNames.js";
@ -6,6 +8,7 @@ import { logCliCommand } from "../cliLogging.js";
import type { Logger } from "../logger.js";
import { directAnalysisOptions, providerSelectionOption } from "./options.js";
import type { CliInstance } from "./types.js";
import { runCliJavaScriptApplicationAnalysis } from "./javascriptApplicationAnalysis.js";
export const registerCoreAnalysisCommands = (
cli: CliInstance,
@ -38,20 +41,23 @@ const registerCoreCommands = (cli: CliInstance, logger: Logger): void => {
.describe("Load and update a local analysis snapshot"),
provider: providerSelectionOption,
});
const analyzeOptions = overviewOptions.extend({
approved: z
.boolean()
.default(false)
.describe(
"Approve static analysis when the path is a JavaScript directory or ASAR",
),
});
cli.command(CLI_COMMANDS.analyze, {
description: "Get an overview of an app",
args: z.object({
path: z.string().describe("App, program, or analysis database path"),
}),
options: overviewOptions,
options: analyzeOptions,
run: ({ args, options }) =>
logCliCommand(logger, "analyze", () =>
runDirectAnalysis(
args.path,
"binary_overview",
{ detail: options.detail, limit: options.limit },
directAnalysisOptions(logger, options.snapshot, options.provider),
),
runRoutedOverview(args.path, options, logger),
),
});
cli.command(CLI_COMMANDS.inspect, {
@ -96,6 +102,45 @@ const registerCoreCommands = (cli: CliInstance, logger: Logger): void => {
});
};
const runRoutedOverview = async (
path: string,
options: {
readonly approved: boolean;
readonly detail: "concise" | "detailed";
readonly limit: number;
readonly snapshot?: string | undefined;
readonly provider?: string | undefined;
},
logger: Logger,
) => {
if (
options.provider === undefined &&
options.snapshot === undefined &&
(await isJavaScriptApplicationPath(path))
)
return runCliJavaScriptApplicationAnalysis({
input_path: resolve(path),
approved: options.approved,
});
return runDirectAnalysis(
path,
"binary_overview",
{ detail: options.detail, limit: options.limit },
directAnalysisOptions(logger, options.snapshot, options.provider),
);
};
const isJavaScriptApplicationPath = async (path: string): Promise<boolean> => {
const lower = path.toLowerCase();
if (lower.endsWith(".asar")) return true;
if (lower.endsWith(".app")) return false;
try {
return (await stat(path)).isDirectory();
} catch {
return false;
}
};
const registerXrefsCommand = (cli: CliInstance, logger: Logger): void => {
cli.command(CLI_COMMANDS.xrefs, {
description: "List bounded references to an analyzed address",

View File

@ -0,0 +1,24 @@
import { analyzeJavaScriptApplication } from "../application/JavaScriptApplicationService.js";
import { loadConfiguredPermissionAuthority } from "../application/PermissionConfiguration.js";
import { parseConfig } from "../config.js";
import { projectAnalysisError } from "../domain/errors.js";
import type { JsonValue } from "../domain/jsonValue.js";
/** Execute the shared one-shot CLI boundary for static JavaScript analysis. */
export const runCliJavaScriptApplicationAnalysis = async (
input: unknown,
): Promise<JsonValue> => {
const config = parseConfig(process.env);
if (!config.ok) return cliError(config.error);
const authority = await loadConfiguredPermissionAuthority(config.value);
if (!authority.ok) return cliError(authority.error);
const result = await analyzeJavaScriptApplication(authority.value, input);
return result.ok ? result.value : cliError(result.error);
};
const cliError = (
error: Parameters<typeof projectAnalysisError>[0],
): JsonValue => ({
error: "JavaScript application analysis failed",
...projectAnalysisError(error),
});

View File

@ -4,7 +4,6 @@ import {
inspectElectronPage,
listElectronTargets,
} from "./application/ElectronObservationService.js";
import { analyzeJavaScriptApplication } from "./application/JavaScriptApplicationService.js";
import { reconcileJavaScriptRuntimeEvidence } from "./application/JavaScriptRuntimeReconciliationService.js";
import { loadConfiguredPermissionAuthority } from "./application/PermissionConfiguration.js";
import { CdpElectronProvider } from "./browser/CdpElectronProvider.js";
@ -14,7 +13,6 @@ import {
inspectElectronPageInputSchema,
listElectronTargetsInputSchema,
} from "./domain/electronObservation.js";
import { analyzeJavaScriptApplicationInputSchema } from "./domain/javascriptApplicationAnalysis.js";
import { AnalysisInputError, projectAnalysisError } from "./domain/errors.js";
import type { JsonValue } from "./domain/jsonValue.js";
import type { Logger } from "./logger.js";
@ -24,6 +22,7 @@ import {
electronPageInspectionOptions,
javascriptApplicationOptions,
} from "./cliObservationOptions.js";
import { runCliJavaScriptApplicationAnalysis } from "./cli/javascriptApplicationAnalysis.js";
const scopeOptions = {
allowedFileRoots: z
@ -191,42 +190,29 @@ const registerJavaScriptApplicationCommand = (
}),
options: javascriptApplicationOptions,
run: ({ args, options }) =>
logCliCommand(
logger,
CLI_COMMANDS.analyzeJavaScriptApplication,
async () => {
const context = await electronContext();
if (!context.ok) return context.error;
const parsed = analyzeJavaScriptApplicationInputSchema.safeParse({
input_path: args.path,
approved: options.approved,
format: options.format,
source_map_read_approved: options.sourceMapReadApproved,
limits: {
max_entries: options.maxEntries,
max_total_artifact_bytes: options.maxTotalArtifactBytes,
max_artifact_entry_bytes: options.maxArtifactEntryBytes,
max_compression_ratio: options.maxCompressionRatio,
max_depth: options.maxDepth,
max_path_bytes: options.maxPathBytes,
max_text_files: options.maxTextFiles,
max_total_text_bytes: options.maxTotalTextBytes,
max_text_file_bytes: options.maxTextFileBytes,
max_ast_nodes: options.maxAstNodes,
max_findings: options.maxFindings,
max_modules: options.maxModules,
max_source_map_sources: options.maxSourceMapSources,
max_parse_milliseconds: options.maxParseMilliseconds,
},
});
if (!parsed.success)
return inputError("analyze_javascript_application");
const result = await analyzeJavaScriptApplication(
context.authority,
parsed.data,
);
return result.ok ? result.value : cliError(result.error);
},
logCliCommand(logger, CLI_COMMANDS.analyzeJavaScriptApplication, () =>
runCliJavaScriptApplicationAnalysis({
input_path: args.path,
approved: options.approved,
format: options.format,
source_map_read_approved: options.sourceMapReadApproved,
limits: {
max_entries: options.maxEntries,
max_total_artifact_bytes: options.maxTotalArtifactBytes,
max_artifact_entry_bytes: options.maxArtifactEntryBytes,
max_compression_ratio: options.maxCompressionRatio,
max_depth: options.maxDepth,
max_path_bytes: options.maxPathBytes,
max_text_files: options.maxTextFiles,
max_total_text_bytes: options.maxTotalTextBytes,
max_text_file_bytes: options.maxTextFileBytes,
max_ast_nodes: options.maxAstNodes,
max_findings: options.maxFindings,
max_modules: options.maxModules,
max_source_map_sources: options.maxSourceMapSources,
max_parse_milliseconds: options.maxParseMilliseconds,
},
}),
),
});
};

View File

@ -117,6 +117,68 @@ describe("Electron CLI parity", () => {
INTEGRATION_TEST_TIMEOUT_MS,
);
it(
"routes generic approved analysis of a directory to static JavaScript",
async () => {
const root = await mkdtemp(join(tmpdir(), "rea-electron-routed-cli-"));
temporary.push(root);
await writeElectronBoundaryFixture(root);
const environment = {
...process.env,
REA_INVESTIGATION_INPUT_ROOTS_JSON: JSON.stringify([root]),
};
const analyzed = await runCli(
["analyze", root, "--approved", "--json"],
environment,
);
expect(analyzed).toMatchObject({
operation: "analyze_javascript_application",
provider: { id: "rea-javascript-application" },
normalized_result: {
input_path: root,
format: "directory",
summary: { ipc: { paired_renderer_transmissions: 4 } },
},
});
},
INTEGRATION_TEST_TIMEOUT_MS,
);
it(
"requires explicit approval before generic JavaScript analysis",
async () => {
const root = await mkdtemp(
join(tmpdir(), "rea-electron-unapproved-cli-"),
);
temporary.push(root);
await writeElectronBoundaryFixture(root);
const environment = {
...process.env,
REA_INVESTIGATION_INPUT_ROOTS_JSON: JSON.stringify([root]),
};
const denied = await runCli(["analyze", root, "--json"], environment);
expect(denied).toMatchObject({
code: "invalid_request",
details: {
operation: "analyze_javascript_application",
issues: [
{
path: ["approved"],
reason: "invalid_value",
expected: [true],
},
],
},
});
expect(denied).not.toHaveProperty("details.candidate_ids");
},
INTEGRATION_TEST_TIMEOUT_MS,
);
it(
"reads a file and returns the derived static/runtime reconciliation contract",
async () => {