Merge remote-tracking branch 'origin/main' into fix/managed-comparison-undecoded-signatures
# Conflicts: # docs/product-catalog.json # docs/verification/managed-conformance-manifest.json # skills/reverse-engineer-anything/SKILL.md # src/generatedMcpToolCatalog.ts
This commit is contained in:
commit
767c6c9a95
|
|
@ -244,15 +244,41 @@ jobs:
|
|||
if: github.event_name == 'push' || needs.changes.outputs.package == 'true'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 2
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-14]
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
platform: linux
|
||||
architecture: x64
|
||||
- os: ubuntu-24.04-arm
|
||||
platform: linux
|
||||
architecture: arm64
|
||||
- os: macos-14
|
||||
platform: darwin
|
||||
architecture: arm64
|
||||
- os: macos-15-intel
|
||||
platform: darwin
|
||||
architecture: x64
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 20
|
||||
env:
|
||||
NODE_OPTIONS: "--max-old-space-size=1024"
|
||||
UV_THREADPOOL_SIZE: "2"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: .nvmrc
|
||||
cache: npm
|
||||
- name: Verify native runtime identity
|
||||
env:
|
||||
EXPECTED_CI_PLATFORM: ${{ matrix.platform }}
|
||||
EXPECTED_CI_ARCHITECTURE: ${{ matrix.architecture }}
|
||||
run: >-
|
||||
node -e "const assert = require('node:assert/strict');
|
||||
assert.equal(process.platform, process.env.EXPECTED_CI_PLATFORM);
|
||||
assert.equal(process.arch, process.env.EXPECTED_CI_ARCHITECTURE);
|
||||
console.log(JSON.stringify({ platform: process.platform, architecture: process.arch, node: process.version }));"
|
||||
- run: npm ci
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
|
|
@ -318,16 +344,44 @@ jobs:
|
|||
if: github.event_name == 'push' || needs.changes.outputs.code == 'true'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 2
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
platform: linux
|
||||
architecture: x64
|
||||
- os: ubuntu-24.04-arm
|
||||
platform: linux
|
||||
architecture: arm64
|
||||
- os: macos-14
|
||||
platform: darwin
|
||||
architecture: arm64
|
||||
- os: macos-15-intel
|
||||
platform: darwin
|
||||
architecture: x64
|
||||
- os: windows-latest
|
||||
platform: win32
|
||||
architecture: x64
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 10
|
||||
env:
|
||||
NODE_OPTIONS: "--max-old-space-size=1024"
|
||||
UV_THREADPOOL_SIZE: "2"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: .nvmrc
|
||||
cache: npm
|
||||
- name: Verify native runtime identity
|
||||
env:
|
||||
EXPECTED_CI_PLATFORM: ${{ matrix.platform }}
|
||||
EXPECTED_CI_ARCHITECTURE: ${{ matrix.architecture }}
|
||||
run: >-
|
||||
node -e "const assert = require('node:assert/strict');
|
||||
assert.equal(process.platform, process.env.EXPECTED_CI_PLATFORM);
|
||||
assert.equal(process.arch, process.env.EXPECTED_CI_ARCHITECTURE);
|
||||
console.log(JSON.stringify({ platform: process.platform, architecture: process.arch, node: process.version }));"
|
||||
- run: npm ci
|
||||
- name: Verify real Node Inspector discovery and observation
|
||||
run: npm run verify:inspector
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ on:
|
|||
- ".github/workflows/real-javascript-recovery.yml"
|
||||
- "src/javascript/recovery/**"
|
||||
- "src/domain/javascript*.ts"
|
||||
- "src/application/JavaScriptRecovery*.ts"
|
||||
- "src/application/javascript/JavaScriptRecovery*.ts"
|
||||
- "src/composition/javascriptRecovery.ts"
|
||||
- "src/contracts/javascriptRecoveryToolContracts.ts"
|
||||
- "src/cli/javascriptRecoveryCommands.ts"
|
||||
|
|
@ -22,8 +22,7 @@ on:
|
|||
- "scripts/rea.mjs"
|
||||
- "src/process/**"
|
||||
- "src/artifacts/SafeOutputTree.ts"
|
||||
- "scripts/verify-javascript-recovery.mjs"
|
||||
- "scripts/lib/javascript-recovery-*.mjs"
|
||||
- "scripts/verify/javascript/recovery.mjs"
|
||||
- "scripts/fixtures/javascript-recovery/**"
|
||||
- "third_party/wakaru"
|
||||
- "package.json"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
name: Real website source-map verification
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/real-web-source-map.yml"
|
||||
- "scripts/verify-browser-source-maps.mjs"
|
||||
- "scripts/lib/browser-source-map-e2e.mjs"
|
||||
- "scripts/fixtures/browser-source-map-site.mjs"
|
||||
- "src/javascript/sourceMaps/**"
|
||||
- "src/browser/assets/**"
|
||||
- "src/domain/webSource*.ts"
|
||||
- "src/domain/webScript*.ts"
|
||||
- "src/application/WebSourceLocation*.ts"
|
||||
- "src/application/ValidateSelectedWebScript.ts"
|
||||
- "src/composition/webSourceLocations.ts"
|
||||
- "src/server/registerWebSourceLocationTool.ts"
|
||||
- "src/server/createServer.ts"
|
||||
- "src/contracts/webScriptToolContracts.ts"
|
||||
- "src/process/**"
|
||||
- "src/cli/webSourceLocationCommands.ts"
|
||||
- "src/cli.ts"
|
||||
- "src/artifacts/readStableArtifact.ts"
|
||||
- "package.json"
|
||||
- "package-lock.json"
|
||||
workflow_dispatch:
|
||||
permissions:
|
||||
contents: read
|
||||
concurrency:
|
||||
group: real-web-source-map-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
env:
|
||||
HUSKY: "0"
|
||||
jobs:
|
||||
real-web-source-map:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 24
|
||||
cache: npm
|
||||
- run: npm ci
|
||||
- name: Install the pinned compiler into an isolated fixture directory
|
||||
run: npm install --prefix "$RUNNER_TEMP/rea-web-source-map-compiler" --no-audit --no-fund --package-lock=false esbuild@0.25.10
|
||||
- run: npm run verify:browser:source-maps
|
||||
env:
|
||||
REA_BROWSER_EXECUTABLE: /usr/bin/google-chrome
|
||||
REA_BROWSER_NO_SANDBOX: "true"
|
||||
REA_WEB_SOURCE_MAP_COMPILER: ${{ runner.temp }}/rea-web-source-map-compiler/node_modules/esbuild/lib/main.js
|
||||
11
README.md
11
README.md
|
|
@ -411,7 +411,7 @@ See [native investigation](docs/native-investigation.md) for keyed archives, ins
|
|||
| Browser observation | 9 | page structure, network metadata, scripts, source maps, WebMCP discovery, screenshots, and capture comparisons |
|
||||
| Electron analysis | 5 | renderer observation, static app mapping, and static/runtime reconciliation |
|
||||
| JavaScript runtime | 2 | Node/Electron Inspector target discovery, script locations, and execution-context events |
|
||||
| Application workflows | 12 | captured website script export; Android/Apple inventory projections; cross-layer feature traces, build comparisons, historical source mapping, static return-shape comparison, and reconstruction checks |
|
||||
| Application workflows | 13 | captured website script export; Android/Apple inventory projections; cross-layer feature traces, build comparisons, historical source mapping, static return-shape comparison, and reconstruction checks |
|
||||
| Workspace and observation | 21 | sessions, evidence bundles, navigation context, process/artifact/function comparisons, and open-question tracking |
|
||||
|
||||
The public interface describes what the agent is trying to learn. Providers decide how to answer. macOS utilities handle common semantic inspection without launching Hopper; Hopper handles deeper native analysis; the process harness records direct behavioral captures.
|
||||
|
|
@ -436,6 +436,11 @@ Static Android APK inspection is verified on Linux with headless JADX; see [Andr
|
|||
`rea trace-web-module-imports`, preserving query/fragment identity and optional
|
||||
import-map context. Requires caller-supplied Chromium via
|
||||
`REA_BROWSER_EXECUTABLE`; see [module relationships](docs/website-module-trace.md).
|
||||
|
||||
- **Source locations:** Trace one retained website script point through a selected
|
||||
local source map with `rea trace-web-source-location`. See
|
||||
[captured website source locations](docs/web-source-location.md) for byte
|
||||
identities, embedded original content and coverage limits.
|
||||
Recover readable modules from selected local bundles with
|
||||
`recover_javascript_sources` / `rea recover-javascript-sources`, then pass
|
||||
the returned `analysis_input` to static analysis. This optional Linux x64
|
||||
|
|
@ -810,3 +815,7 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and contribution ch
|
|||
<img alt="REA GitHub star history" src="https://api.star-history.com/chart?repos=morluto/rea&type=date" />
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
## Disclaimer
|
||||
|
||||
REA provides tools for lawful reverse-engineering research, analysis, and reconstruction. You are responsible for obtaining any required authorization and complying with applicable laws. The project does not endorse illegal or unauthorized use.
|
||||
|
|
|
|||
|
|
@ -223,7 +223,7 @@ rea setup
|
|||
| مراقبة المتصفح | 9 | بنية الصفحات وبيانات الشبكة والبرامج النصية وخرائط المصدر واكتشاف WebMCP والصور ومقارنة الالتقاط |
|
||||
| تحليل Electron | 5 | مراقبة العارضين وخريطة التطبيق الثابتة والمواءمة بين نتائج الثبات والتشغيل |
|
||||
| وقت تشغيل JavaScript | 2 | اكتشاف أهداف Node/Electron Inspector ومواضع البرامج وأحداث سياقات التنفيذ |
|
||||
| سير عمل التطبيقات | 12 | تصدير النصوص البرمجية الملتقطة، تتبع الميزات عبر الطبقات ومقارنة الإصدارات ومواءمة المصدر التاريخي ومقارنة أشكال القيم المعادة والتحقق من إعادة الإنشاء |
|
||||
| سير عمل التطبيقات | 13 | تصدير النصوص البرمجية الملتقطة، تتبع الميزات عبر الطبقات ومقارنة الإصدارات ومواءمة المصدر التاريخي ومقارنة أشكال القيم المعادة والتحقق من إعادة الإنشاء |
|
||||
| مساحة العمل والملاحظة | 21 | الجلسات وحزم الأدلة وسياق التنقل ومقارنة العمليات والمخرجات والدوال وتسجيل الأسئلة غير المحسومة |
|
||||
|
||||
## خطة العمل
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ REA は手順 1〜5 のバイナリ解析を処理し、手順 6 はエージェ
|
|||
| ブラウザー観察 | 9 | ページ構成、ネットワークメタデータ、スクリプト、ソースマップ、WebMCP 検出、スクリーンショット、キャプチャ比較 |
|
||||
| Electron 解析 | 5 | レンダラー観察、静的アプリマッピング、静的/実行時結果の対応付け |
|
||||
| JavaScript 実行時 | 2 | Node/Electron Inspector 対象の検出、スクリプト位置、実行コンテキストイベント |
|
||||
| アプリワークフロー | 12 | 取得した Web スクリプトのエクスポート、層をまたぐ機能トレース、ビルド比較、履歴ソース対応、静的戻り値形状の比較、再実装検証 |
|
||||
| アプリワークフロー | 13 | 取得した Web スクリプトのエクスポート、層をまたぐ機能トレース、ビルド比較、履歴ソース対応、静的戻り値形状の比較、再実装検証 |
|
||||
| ワークスペースと観察 | 21 | セッション、証跡バンドル、ナビゲーション文脈、プロセス・成果物・関数比較、未解決事項の記録 |
|
||||
|
||||
## ロードマップ
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ REA는 1–5단계의 바이너리 분석을 처리합니다. 6단계는 에이
|
|||
| 브라우저 관찰 | 9 | 페이지 구조, 네트워크 메타데이터, 스크립트, 소스 맵, WebMCP 탐색, 스크린샷, 캡처 비교 |
|
||||
| Electron 분석 | 5 | 렌더러 관찰, 정적 앱 매핑, 정적·런타임 결과 연결 |
|
||||
| JavaScript 런타임 | 2 | Node/Electron Inspector 대상 탐색, 스크립트 위치, 실행 컨텍스트 이벤트 |
|
||||
| 앱 워크플로 | 12 | 캡처한 웹 스크립트 내보내기, 계층 간 기능 추적, 빌드 비교, 히스토리 소스 매핑, 정적 반환 구조 비교, 재구현 검증 |
|
||||
| 앱 워크플로 | 13 | 캡처한 웹 스크립트 내보내기, 계층 간 기능 추적, 빌드 비교, 히스토리 소스 매핑, 정적 반환 구조 비교, 재구현 검증 |
|
||||
| 작업 공간과 관찰 | 21 | 세션, 근거 번들, 탐색 컨텍스트, 프로세스·아티팩트·함수 비교, 미해결 항목 기록 |
|
||||
|
||||
## 로드맵
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ REA 负责第 1–5 步中的二进制分析。第 6 步由智能体使用其常
|
|||
| 浏览器观察 | 9 | 页面结构、网络元数据、脚本、来源映射、WebMCP 发现、截图与捕获比较 |
|
||||
| Electron 分析 | 5 | 渲染进程观察、静态应用映射、静态/运行时结果关联 |
|
||||
| JavaScript 运行时 | 2 | Node/Electron Inspector 目标发现、脚本位置与执行上下文事件 |
|
||||
| 应用工作流 | 12 | 捕获的网站脚本导出、跨层功能追踪、构建比较、历史源码映射、静态返回结构比较与重建验证 |
|
||||
| 应用工作流 | 13 | 捕获的网站脚本导出、跨层功能追踪、构建比较、历史源码映射、静态返回结构比较与重建验证 |
|
||||
| 工作区与观察 | 21 | 会话、证据包、导航上下文、进程/产物/函数比较与待解决问题跟踪 |
|
||||
|
||||
## 路线图
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ graph TD
|
|||
IDA_MCP["External ida-pro-mcp<br/>GUI proxy or database supervisor<br/>upstream installation and engine lifecycle"]
|
||||
AUX["src/artifacts/ + src/native/<br/>disjoint artifact and native capabilities"]
|
||||
BROWSER["src/browser/<br/>CDP / Playwright capture<br/>captured scripts and native module resolution"]
|
||||
JS_CODEC["src/javascript/sourceMaps/<br/>pinned upstream map codec<br/>owned heap-limited Node process, complete point evidence"]
|
||||
INSPECTOR["src/inspector/<br/>passive V8 Inspector discovery and capture<br/>script and target locations"]
|
||||
DOTNET["src/dotnet/<br/>Managed static metadata provider<br/>PE/CLI metadata inventory, members, IL"]
|
||||
FIRMWARE["src/firmware/<br/>Binwalk / Unblob adapters<br/>owned processes, report normalization, private extraction"]
|
||||
|
|
@ -95,6 +96,9 @@ graph TD
|
|||
SERVER --> CONTRACTS
|
||||
SERVER --> APP
|
||||
APP --> BROWSER
|
||||
APP -->|source-map codec port| JS_CODEC
|
||||
JS_CODEC --> PROCESS
|
||||
JS_CODEC --> DOMAIN
|
||||
APP -->|runtime observation port| INSPECTOR
|
||||
INSPECTOR -->|shared CDP and file-location helpers| BROWSER
|
||||
INSPECTOR --> DOMAIN
|
||||
|
|
|
|||
|
|
@ -225,6 +225,49 @@ explicit downloader and fixed manifest belong to `scripts/fixtures/android/`.
|
|||
JADX CLI/MCP parity requires the fixed APK and existing audited JAR; synthetic
|
||||
protocol/cancellation success does not establish that engine or an unverified host.
|
||||
|
||||
## Deep-provider source declarations
|
||||
|
||||
Hopper, Ghidra and IDA declare their implemented analyst operations in their
|
||||
own `*ProviderCapabilities.ts` modules. Hopper's inventory is typed against the
|
||||
existing direct-operation contracts; Ghidra reuses its inventory/function adapter
|
||||
operations; IDA retains its read-only operation family. Frozen operation arrays
|
||||
feed the existing capability builders without importing generated catalog data.
|
||||
|
||||
The catalog generator reads these source declarations and joins operation names
|
||||
to canonical `TOOL_CONTRACTS`. A missing contract identifies the declaring provider
|
||||
and operation. Public schemas and descriptions remain owned by contracts; the
|
||||
declarations describe implementation coverage. Provider adapters must not consume
|
||||
the generated MCP catalog that is derived from them. The resolved module guard
|
||||
checks this edge while admitting canonical source contracts, generated package
|
||||
metadata and the existing application snapshot-cache consumer.
|
||||
|
||||
Exact provider effects and lifecycle differences remain in their adapters:
|
||||
Hopper's GUI and mutation effects, Ghidra's experimental Windows authority and
|
||||
mutation restrictions, and IDA's attached/headless effects and live observations.
|
||||
This source increment introduces no common provider lifecycle or new interface.
|
||||
|
||||
## JavaScript application ownership
|
||||
|
||||
`src/application/javascript/` owns JavaScript/Electron artifact analysis and
|
||||
graph projection, feature/version/export/source comparisons, runtime Evidence
|
||||
and reconciliation, observation ports, and source recovery workflows. Pure
|
||||
analysis and public schemas keep their existing domain/contract ownership;
|
||||
shared artifact inventory, investigation records and execution types remain
|
||||
shared. CLI, MCP and production factories import the owning workflow directly.
|
||||
|
||||
`scripts/verify/javascript/` groups application-workflow, runtime-reconciliation,
|
||||
large-digest and real-recovery entrypoints. Their existing npm commands retain
|
||||
their invocation semantics. Recovery fixture compilation lives beside its
|
||||
unchanged sources under `scripts/fixtures/javascript-recovery/`. Its default
|
||||
REA entrypoint still resolves to `scripts/rea.mjs`. Managed conformance imports
|
||||
the relocated compiled workflow; owning CI source filters follow the new paths.
|
||||
|
||||
This application move preserves the current directory/ASAR reader boundary,
|
||||
including root/nested byte checks, UTF-8 diagnostics, cancellation and owned
|
||||
close. Reader selection requires a separately traced increment. Runtime ports
|
||||
retain their distinct Inspector, passive Electron and active Electron effects;
|
||||
shipped Electron hooks remain at their existing provider boundary.
|
||||
|
||||
## Binary application ownership
|
||||
|
||||
`src/application/binary/` owns the active session, deep-provider registry and
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
"skill_version": "26"
|
||||
},
|
||||
"tools": {
|
||||
"total": 130,
|
||||
"total": 131,
|
||||
"families": [
|
||||
{
|
||||
"id": "direct",
|
||||
|
|
@ -179,7 +179,7 @@
|
|||
{
|
||||
"id": "application",
|
||||
"surface": "application-workflow",
|
||||
"count": 12,
|
||||
"count": 13,
|
||||
"tools": [
|
||||
"build_reconstruction_obligation_ledger",
|
||||
"compare_application_versions",
|
||||
|
|
@ -192,7 +192,8 @@
|
|||
"recover_javascript_sources",
|
||||
"trace_application_feature",
|
||||
"trace_javascript_semantics",
|
||||
"trace_web_module_imports"
|
||||
"trace_web_module_imports",
|
||||
"trace_web_source_location"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -471,7 +472,11 @@
|
|||
"id": "rea-web-script-export",
|
||||
"name": "REA captured script export",
|
||||
"version": "1",
|
||||
"capabilities": ["export_web_scripts", "trace_web_module_imports"]
|
||||
"capabilities": [
|
||||
"export_web_scripts",
|
||||
"trace_web_module_imports",
|
||||
"trace_web_source_location"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "unblob",
|
||||
|
|
@ -561,7 +566,7 @@
|
|||
}
|
||||
],
|
||||
"cli": {
|
||||
"primary_count": 85,
|
||||
"primary_count": 86,
|
||||
"commands": [
|
||||
"address-to-file-offset",
|
||||
"analyze",
|
||||
|
|
@ -644,6 +649,7 @@
|
|||
"trace-native-ui-action",
|
||||
"trace-native-values",
|
||||
"trace-web-module-imports",
|
||||
"trace-web-source-location",
|
||||
"uninstall",
|
||||
"update",
|
||||
"verify-managed-native-boundaries",
|
||||
|
|
@ -658,15 +664,15 @@
|
|||
},
|
||||
"runtime_catalog": {
|
||||
"counts": {
|
||||
"cli_commands": 85,
|
||||
"mcp_tools": 130,
|
||||
"cli_commands": 86,
|
||||
"mcp_tools": 131,
|
||||
"mcp_prompts": 6
|
||||
},
|
||||
"digests": {
|
||||
"tools_sha256": "4d67b3d567f690604e29dae3c76d4bdfc7d9a332745302dd27af328642118c66",
|
||||
"tools_sha256": "f31ac36f25f54a9a5fbc157855849fac5361c67373d8b4bb070cf8171bf833c1",
|
||||
"prompts_sha256": "ef2de8814390b340623c32001610aa2709d90bed51537b6e562ab3abf144ab4d",
|
||||
"combined_sha256": "ca2f454e044d0095736974fa078383989ab848e420fcebb6127d2c6869c47f1c",
|
||||
"providers_sha256": "67251a90abf28e1cd9020cf68f579bf2460922d90dc113798a391039279db009"
|
||||
"combined_sha256": "f07ae6f3910102f58197c86e34e1f06b3cc1f3bf341faa140b4fa2ff65182764",
|
||||
"providers_sha256": "a7d885531ee25d42c51385444faec544d34cd7eba6250a7dc75c4faedd4454a3"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ requires unresolved table bounds or case mappings to remain visible as
|
|||
residual unknowns.
|
||||
|
||||
`npm run verify:inspector` requires the supported Node.js runtime and installed
|
||||
REA dependencies. CI runs it on Linux and Windows. It starts owned loopback
|
||||
REA dependencies. CI runs it on Linux and macOS x64/arm64 and Windows x64. It starts owned loopback
|
||||
Node Inspector fixtures and verifies discovery and passive observation through
|
||||
the CLI and stdio MCP, including special filenames, unresolved discovery
|
||||
locations, and independently resolved loaded scripts. Double-quote filenames
|
||||
|
|
@ -312,6 +312,30 @@ Keep the provider-specific acceptance path independent from optional
|
|||
cross-compilers. Cross-format failures belong to the cross-format lane and must
|
||||
not make native host acceptance unavailable.
|
||||
|
||||
## Native platform baseline in CI
|
||||
|
||||
CI exercises the pinned Node.js runtime on native hosted runners:
|
||||
|
||||
| Host | Runner | Baseline checks |
|
||||
| --------------------- | ------------------ | ---------------------------------------------------------------------------------------- |
|
||||
| Linux x64 | `ubuntu-latest` | Installed package and real Node Inspector CLI/MCP |
|
||||
| Linux arm64 (aarch64) | `ubuntu-24.04-arm` | Installed package and real Node Inspector CLI/MCP |
|
||||
| macOS arm64 | `macos-14` | Installed package and real Node Inspector CLI/MCP |
|
||||
| macOS x64 | `macos-15-intel` | Installed package and real Node Inspector CLI/MCP |
|
||||
| Windows x64 | `windows-latest` | Curated capabilities, native controls, installed package and real Node Inspector CLI/MCP |
|
||||
|
||||
Package and Inspector matrices assert the actual Node platform/architecture
|
||||
before verification and record those values with the Node version. Each matrix
|
||||
runs at most two jobs concurrently with explicit timeouts and Node heap/thread
|
||||
limits. Package checks cover installation, CLI/MCP discovery, target-free
|
||||
analysis, configuration backups/recovery, Evidence and owned lifecycle; Inspector
|
||||
checks execute source-owned loopback targets and special filename cases.
|
||||
|
||||
These native baseline checks complement the Linux source-test shards and the
|
||||
separate Apple-artifact and real-provider lanes. Actual Hopper, Ghidra, IDA,
|
||||
browser and managed-tool claims require their corresponding verification lanes.
|
||||
Runner labels follow the [GitHub hosted-runner reference](https://docs.github.com/en/actions/reference/runners/github-hosted-runners).
|
||||
|
||||
## Developer commands
|
||||
|
||||
Use source feedback while editing, explicit boundary checks for the changed
|
||||
|
|
@ -462,3 +486,25 @@ and compares a finite set of known fixture results. It does not establish
|
|||
arbitrary recovered-application equivalence. CI installs these prerequisites only
|
||||
in `.github/workflows/real-javascript-recovery.yml`; the existing `real-browser`
|
||||
lane uses real Chrome for browser capture and website workflows.
|
||||
|
||||
### Captured website source-map lane
|
||||
|
||||
`npm run verify:browser:source-maps` checks actual Chromium capture/export and
|
||||
source-map point tracing through CLI and stdio MCP. It requires absolute
|
||||
`REA_BROWSER_EXECUTABLE` and `REA_WEB_SOURCE_MAP_COMPILER` pointing to esbuild
|
||||
0.25.10's `lib/main.js` in a caller-owned isolated installation. Preflight reports
|
||||
missing prerequisites for this lane. The compiler is used only to generate the
|
||||
source-owned fixture. No Hopper, Ghidra or application dependency installation
|
||||
is required.
|
||||
|
||||
```bash
|
||||
REA_BROWSER_EXECUTABLE=/absolute/path/to/chromium \
|
||||
REA_WEB_SOURCE_MAP_COMPILER=/absolute/path/to/fixture-tools/node_modules/esbuild/lib/main.js \
|
||||
npm run verify:browser:source-maps
|
||||
```
|
||||
|
||||
`scripts/verify-browser-source-maps.mjs /absolute/path/to/installed/rea.mjs`
|
||||
checks an installed package after building the verifier dependencies. The separate
|
||||
conditional `real-web-source-map` CI job supplies Chrome and an isolated pinned
|
||||
fixture compiler; static/unit checks do not acquire a browser. See
|
||||
[the source location guide](web-source-location.md) for the verified decoder profile.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"manifest_id": "ecm_4e3e927be6545a5328c9e1c523da2504d22f1fae7b3d71ddc6c20e0c6faf34c3",
|
||||
"manifest_id": "ecm_5705edecb5c3c4e48c75eba9c8a83a8dfaee8b8aec9f2f3eb9a7196d619a1e15",
|
||||
"verifier": {
|
||||
"id": "rea-managed-conformance",
|
||||
"version": "1"
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
"skill_digests": [
|
||||
{
|
||||
"skill_id": "reverse-engineer-anything",
|
||||
"sha256": "7f689acab3357db8f73aeaf4030e58a1b0c488dfe5a5c3238ce3bb5bcb119bd6"
|
||||
"sha256": "f37629a65c061591aedf33ba52c38838dd0ccad3e7819a5e36ec640888133030"
|
||||
}
|
||||
],
|
||||
"claims": [
|
||||
|
|
|
|||
|
|
@ -0,0 +1,97 @@
|
|||
# Captured website source locations
|
||||
|
||||
`trace_web_source_location` maps one selected position in a script retained by
|
||||
`export_web_scripts` through one explicitly paired local source map. The shared
|
||||
CLI/MCP workflow verifies actual manifest, script and map byte identities and
|
||||
returns the original position and embedded source inline. It acquires no browser,
|
||||
fetches no URL and executes no application code.
|
||||
|
||||
```bash
|
||||
rea trace-web-source-location \
|
||||
/analysis/scripts/manifest.json 0 \
|
||||
/analysis/app.js.map 'https://example.test/maps/app.js.map?v=7#context' \
|
||||
1 25 --json
|
||||
```
|
||||
|
||||
The six positional arguments select the manifest, zero-based script index,
|
||||
absolute map path, absolute map URL context, one-based generated line and
|
||||
zero-based UTF-16 column. The MCP arguments are:
|
||||
|
||||
```json
|
||||
{
|
||||
"manifest_path": "/analysis/scripts/manifest.json",
|
||||
"script_index": 0,
|
||||
"source_map": {
|
||||
"path": "/analysis/app.js.map",
|
||||
"url": "https://example.test/maps/app.js.map?v=7#context"
|
||||
},
|
||||
"generated_position": { "line": 1, "column": 25 }
|
||||
}
|
||||
```
|
||||
|
||||
The URL supplies the context for resolving `sources` and `sourceRoot`; it is not
|
||||
an instruction to fetch. Absolute virtual or file contexts can be selected as
|
||||
well. The map/script association is caller-selected: a declaration or local map
|
||||
does not prove deployment authenticity or execution. Use
|
||||
[import tracing](website-module-trace.md) to inspect outgoing native module edges.
|
||||
|
||||
## Meaning of the evidence
|
||||
|
||||
Lookup follows the greatest generated position less than or equal to the
|
||||
selected point, across lines, and returns **every** segment at that position.
|
||||
It includes generated-only mappings. This follows
|
||||
[ECMA-426 GetOriginalPositions](https://tc39.es/ecma426/#sec-getoriginalpositions),
|
||||
with one-based lines in REA's public contract. A point result does not establish
|
||||
coverage of a source range, execution or UI causality.
|
||||
|
||||
Mapped entries preserve the raw source name/root, section path, section-local
|
||||
source index and flattened index. Duplicate URLs remain distinct, including
|
||||
entries with different embedded contents. Missing source names retain a null
|
||||
resolved URL. Original coordinates outside embedded text retain the reported
|
||||
coordinates and a null offset.
|
||||
|
||||
Embedded content hashes identify the UTF-8 encoding of the decoded
|
||||
`sourcesContent` string, including its line endings. They do not identify an
|
||||
independently captured original file. Raw map text is retained in Evidence's
|
||||
`raw_result`, including unknown extensions; these extensions are not interpreted.
|
||||
Capture context and source Evidence links accompany independently verified
|
||||
selected file identities.
|
||||
|
||||
## Adapter and resource boundaries
|
||||
|
||||
The adapter uses the locked upstream
|
||||
[`@jridgewell/trace-mapping` 0.3.31](https://github.com/jridgewell/trace-mapping)
|
||||
without modifying its code. It validates map/VLQ structure before allocation,
|
||||
normalizes nested indexed offsets before upstream flattening, checks section
|
||||
boundaries and indexes, and retains raw declaration identity. It supports regular
|
||||
maps and inline indexed sections. External section URLs return an actionable
|
||||
unsupported-profile error. This is a defined decoder profile, not a claim to
|
||||
implement every current source-map extension.
|
||||
|
||||
One owned Node subprocess decodes the map. Its private request directory is
|
||||
removed before success is returned. Only this child's inherited `NODE_OPTIONS`
|
||||
is removed; explicit V8 flags set a 192 MiB old-generation and 8 MiB semi-space
|
||||
budget, one V8 worker and a 20-second deadline. Reported actual V8 heap limits
|
||||
are checked. These are heap limits, not an aggregate process RSS limit. Cleanup
|
||||
may extend the deadline and an unconfirmed cleanup overrides success with
|
||||
`cleanup_incomplete` and the owning operation/resources.
|
||||
|
||||
Complete evidence is bounded by a 4 MiB map, 32 MiB codec reply, 262144 decoded
|
||||
rows/segments and 64 nested section levels. Exceeding a budget returns an explicit
|
||||
failure, without partial results. The existing 32 MiB manifest and 16 MiB selected
|
||||
script boundaries also apply. No global toolchain or browser configuration changes
|
||||
are made.
|
||||
|
||||
## Verification
|
||||
|
||||
Focused tests cover duplicate mappings, indexed offsets/overlap/local indexes,
|
||||
32-bit VLQ overflow, nullable content, UTF-16/CRLF positions, immutable artifact
|
||||
identity, cancellation, late output closure, cleanup failures, SDK schemas and
|
||||
public CLI behavior. The actual codec process is exercised on the test host.
|
||||
|
||||
The optional `verify:browser:source-maps` lane compiles a source-owned TypeScript
|
||||
fixture with isolated esbuild 0.25.10, serves it to real Chromium, captures and
|
||||
exports the actual response, then checks the original compiler point and exact
|
||||
retained content through CLI and stdio MCP. It can target an installed package.
|
||||
Only this lane requires Chromium and the fixture compiler. Linux x64 is the real
|
||||
workflow covered by the dedicated CI job; other host workflows remain unverified.
|
||||
11
package.json
11
package.json
|
|
@ -136,9 +136,9 @@
|
|||
"verify:browser:network": "npm run build:cached && node scripts/verify-browser-network.mjs",
|
||||
"verify:electron": "npm run build:cached && node scripts/verify-real-electron.mjs",
|
||||
"verify:inspector": "npm run build:cached && node scripts/verify/inspector/runtime-observation.mjs",
|
||||
"verify:javascript-runtime": "npm run build:cached && node scripts/verify-local-javascript-runtime.mjs",
|
||||
"verify:javascript:digests": "npm run build:cached && node scripts/verify-large-javascript-digests.mjs",
|
||||
"verify:application-workflows": "npm run build:cached && node scripts/verify-local-application-workflows.mjs",
|
||||
"verify:javascript-runtime": "npm run build:cached && node scripts/verify/javascript/runtime-observation.mjs",
|
||||
"verify:javascript:digests": "npm run build:cached && node scripts/verify/javascript/digests.mjs",
|
||||
"verify:application-workflows": "npm run build:cached && node scripts/verify/javascript/application-workflows.mjs",
|
||||
"verify:managed": "npm run build:cached && node scripts/verify-managed-conformance.mjs",
|
||||
"verify:firmware": "npm run build:cached && node scripts/verify/firmware/analysis.mjs",
|
||||
"fixtures:firmware": "node scripts/fixtures/firmware/generate.mjs",
|
||||
|
|
@ -179,8 +179,9 @@
|
|||
"verify:browser:scripts": "npm run build:cached && node scripts/verify-browser-scripts.mjs",
|
||||
"verify:browser:modules": "npm run build:cached && node scripts/verify-browser-modules.mjs",
|
||||
"verify:test-discovery": "node scripts/verify-test-discovery.mjs",
|
||||
"verify:javascript:recovery": "node scripts/verify-javascript-recovery.mjs",
|
||||
"verify:module-boundaries": "node scripts/verify-module-boundaries.mjs"
|
||||
"verify:javascript:recovery": "node scripts/verify/javascript/recovery.mjs",
|
||||
"verify:module-boundaries": "node scripts/verify-module-boundaries.mjs",
|
||||
"verify:browser:source-maps": "npm run build:cached && node scripts/verify-browser-source-maps.mjs"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{cjs,cts,js,jsx,mjs,mts,ts,tsx}": [
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
import { createServer } from "node:http";
|
||||
import { pathToFileURL } from "node:url";
|
||||
import { access } from "node:fs/promises";
|
||||
import { isAbsolute } from "node:path";
|
||||
|
||||
/** Generate a real compiler map and serve only source-owned fixture code. */
|
||||
export async function startBrowserSourceMapSite() {
|
||||
const command = process.env.REA_WEB_SOURCE_MAP_COMPILER;
|
||||
if (!command || !isAbsolute(command))
|
||||
throw new Error(
|
||||
"verify:browser:source-maps requires absolute REA_WEB_SOURCE_MAP_COMPILER pointing to isolated esbuild 0.25.10 lib/main.js",
|
||||
);
|
||||
await access(command);
|
||||
const compiler = await import(pathToFileURL(command).href);
|
||||
if (compiler.version !== "0.25.10")
|
||||
throw new Error(`Expected esbuild 0.25.10; observed ${compiler.version}`);
|
||||
const original =
|
||||
'// 🎋 UTF-16 and CRLF fixture\r\nfunction boot(): void {\r\n const marker: string = "source-map proof";\r\n document.body.dataset.ready = marker;\r\n}\r\nboot();\r\n';
|
||||
const compiled = await compiler
|
||||
.transform(original, {
|
||||
loader: "ts",
|
||||
sourcefile: "../src/fixture.ts?v=7#original",
|
||||
sourcemap: "external",
|
||||
minify: true,
|
||||
format: "iife",
|
||||
target: "es2022",
|
||||
})
|
||||
.finally(() => compiler.stop());
|
||||
const token = '"source-map proof"';
|
||||
const generatedOffset = compiled.code.indexOf(token);
|
||||
const originalOffset = original.indexOf(token);
|
||||
if (generatedOffset < 0 || originalOffset < 0)
|
||||
throw new Error("Compiler fixture marker missing");
|
||||
const position = textPosition(compiled.code, generatedOffset);
|
||||
const originalPosition = textPosition(original, originalOffset);
|
||||
let mapRequests = 0;
|
||||
const server = createServer((request, response) => {
|
||||
if (request.url === "/")
|
||||
return response
|
||||
.writeHead(200, { "Content-Type": "text/html" })
|
||||
.end('<body><script src="/app.js?build=7"></script></body>');
|
||||
if (request.url === "/app.js?build=7")
|
||||
return response
|
||||
.writeHead(200, { "Content-Type": "text/javascript" })
|
||||
.end(compiled.code);
|
||||
if (request.url?.startsWith("/maps/app.js.map")) {
|
||||
mapRequests += 1;
|
||||
return response
|
||||
.writeHead(200, { "Content-Type": "application/json" })
|
||||
.end(compiled.map);
|
||||
}
|
||||
response.writeHead(404).end("Unselected");
|
||||
});
|
||||
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
|
||||
const address = server.address();
|
||||
if (!address || typeof address === "string")
|
||||
throw new Error("Source map fixture has no TCP address");
|
||||
return {
|
||||
origin: `http://127.0.0.1:${address.port}`,
|
||||
original,
|
||||
generated: compiled.code,
|
||||
map: compiled.map,
|
||||
position,
|
||||
originalPosition,
|
||||
originalOffset,
|
||||
mapRequests: () => mapRequests,
|
||||
compiler: { id: "esbuild", version: compiler.version },
|
||||
close: () =>
|
||||
new Promise((resolve, reject) =>
|
||||
server.close((error) => (error ? reject(error) : resolve())),
|
||||
),
|
||||
};
|
||||
}
|
||||
const textPosition = (text, offset) => {
|
||||
const preceding = text.slice(0, offset).split(/\r\n?|\n|\u2028|\u2029/u);
|
||||
return { line: preceding.length, column: preceding.at(-1).length };
|
||||
};
|
||||
|
|
@ -17,9 +17,7 @@ export async function buildRecoveryFixtures(root, prefix) {
|
|||
throw new Error(
|
||||
"Fixture compilers must be esbuild 0.25.10 and webpack 5.101.3",
|
||||
);
|
||||
const source = fileURLToPath(
|
||||
new URL("../fixtures/javascript-recovery/entry.mjs", import.meta.url),
|
||||
);
|
||||
const source = fileURLToPath(new URL("./entry.mjs", import.meta.url));
|
||||
const webpackOutput = join(root, "webpack");
|
||||
await mkdir(webpackOutput);
|
||||
await new Promise((resolve, reject) => {
|
||||
|
|
@ -50,9 +48,7 @@ export async function buildRecoveryFixtures(root, prefix) {
|
|||
});
|
||||
// One self-contained source fixture avoids unresolved imports in the oracle.
|
||||
const helperSource = await readFile(
|
||||
fileURLToPath(
|
||||
new URL("../fixtures/javascript-recovery/helpers.mjs", import.meta.url),
|
||||
),
|
||||
fileURLToPath(new URL("./helpers.mjs", import.meta.url)),
|
||||
"utf8",
|
||||
);
|
||||
const plain = await esbuild.transform(
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
import assert from "node:assert/strict";
|
||||
import { execFile } from "node:child_process";
|
||||
import { createHash } from "node:crypto";
|
||||
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { promisify } from "node:util";
|
||||
import { Client } from "@modelcontextprotocol/client";
|
||||
import { StdioClientTransport } from "@modelcontextprotocol/client/stdio";
|
||||
import { parseEvidence } from "../../dist/domain/evidence.js";
|
||||
import { webSourceLocationResultSchema } from "../../dist/domain/webSourceLocation.js";
|
||||
import { startBrowserSourceMapSite } from "../fixtures/browser-source-map-site.mjs";
|
||||
import { mcpTextValue } from "./mcp-verifier-results.mjs";
|
||||
|
||||
/** Verify real Chrome capture → export → original compiler point through packaged CLI/MCP. */
|
||||
export async function verifyBrowserSourceMap(
|
||||
executable,
|
||||
entrypoint = fileURLToPath(new URL("../rea.mjs", import.meta.url)),
|
||||
) {
|
||||
const site = await startBrowserSourceMapSite();
|
||||
const root = await mkdtemp(join(tmpdir(), "rea-browser-source-map-"));
|
||||
const env = {
|
||||
...process.env,
|
||||
REA_LOG_LEVEL: "silent",
|
||||
HOPPER_LAUNCHER_PATH: "/rea-unconfigured-provider/hopper",
|
||||
};
|
||||
const cli = async (...args) => {
|
||||
const { stdout } = await promisify(execFile)(
|
||||
process.execPath,
|
||||
[entrypoint, ...args, "--json"],
|
||||
{ env, timeout: 45000, maxBuffer: 16 * 1024 * 1024 },
|
||||
);
|
||||
return parseEvidence(JSON.parse(stdout));
|
||||
};
|
||||
const transport = new StdioClientTransport({
|
||||
command: process.execPath,
|
||||
args: [entrypoint, "mcp"],
|
||||
env,
|
||||
stderr: "pipe",
|
||||
});
|
||||
const client = new Client({ name: "source-map-real-e2e", version: "1" });
|
||||
try {
|
||||
const capture = await cli(
|
||||
"capture-browser-scenario",
|
||||
JSON.stringify({
|
||||
browser: { mode: "launch", executable_path: executable },
|
||||
start_url: { url: site.origin },
|
||||
actions: [
|
||||
{
|
||||
step_id: "ready",
|
||||
action: "wait_for",
|
||||
locator: {
|
||||
kind: "css",
|
||||
selector: '[data-ready="source-map proof"]',
|
||||
},
|
||||
state: "visible",
|
||||
timeout_ms: 10000,
|
||||
},
|
||||
],
|
||||
capture: { network: { response_body: true } },
|
||||
}),
|
||||
);
|
||||
const capturePath = join(root, "capture.json");
|
||||
await writeFile(capturePath, JSON.stringify(capture));
|
||||
const exported = await cli(
|
||||
"export-web-scripts",
|
||||
capturePath,
|
||||
join(root, "export"),
|
||||
);
|
||||
const manifest = exported.normalized_result;
|
||||
const manifestBytes = await readFile(manifest.manifest.path);
|
||||
const identity = {
|
||||
sha256: sha(manifestBytes),
|
||||
bytes: manifestBytes.length,
|
||||
};
|
||||
const scriptIndex = manifest.scripts.findIndex(
|
||||
(script) => script.url === `${site.origin}/app.js?build=7`,
|
||||
);
|
||||
assert.ok(
|
||||
scriptIndex >= 0,
|
||||
"Actual browser capture omitted compiled source",
|
||||
);
|
||||
const mapPath = join(root, "app.js.map");
|
||||
await writeFile(mapPath, site.map);
|
||||
const before = site.mapRequests();
|
||||
await client.connect(transport);
|
||||
let expected;
|
||||
for (const context of [
|
||||
site.origin,
|
||||
site.origin.replace("://", "://selected-user:selected-value@"),
|
||||
]) {
|
||||
const input = {
|
||||
manifest_path: manifest.manifest.path,
|
||||
script_index: scriptIndex,
|
||||
source_map: {
|
||||
path: mapPath,
|
||||
url: `${context}/maps/app.js.map?v=7#context`,
|
||||
},
|
||||
generated_position: site.position,
|
||||
};
|
||||
expected = await assertPublicPair(cli, client, {
|
||||
site,
|
||||
input,
|
||||
capture,
|
||||
identity,
|
||||
});
|
||||
}
|
||||
assert.equal(
|
||||
site.mapRequests(),
|
||||
before,
|
||||
"Point tracing fetched the selected map URL",
|
||||
);
|
||||
return {
|
||||
compiler: site.compiler,
|
||||
generated_sha256: sha(site.generated),
|
||||
source_map_sha256: sha(site.map),
|
||||
original_sha256: sha(site.original),
|
||||
public_cli: true,
|
||||
public_stdio_mcp: true,
|
||||
actual_chrome_capture: true,
|
||||
source_map_refetch: false,
|
||||
original_point: site.originalPosition,
|
||||
codec: expected.engine,
|
||||
runtime: expected.runtime,
|
||||
selected_inert_userinfo_context_preserved: true,
|
||||
public_point_cases: 4,
|
||||
};
|
||||
} finally {
|
||||
await client.close();
|
||||
await transport.close();
|
||||
await site.close();
|
||||
await rm(root, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
function assertPoint(evidence, { site, input, capture, identity }) {
|
||||
const result = webSourceLocationResultSchema.parse(
|
||||
evidence.normalized_result,
|
||||
);
|
||||
assert.equal(result.manifest.sha256, identity.sha256);
|
||||
assert.equal(result.manifest.bytes, identity.bytes);
|
||||
assert.equal(result.source.bytes, Buffer.byteLength(site.generated));
|
||||
assert.equal(result.source.sha256, sha(site.generated));
|
||||
assert.equal(result.source_map.sha256, sha(site.map));
|
||||
assert.equal(result.source_map.url, input.source_map.url);
|
||||
assert.equal(result.manifest.source_evidence_id, capture.evidence_id);
|
||||
assert.equal(result.execution, "unknown");
|
||||
assert.equal(result.source_authenticity, "unknown");
|
||||
assert.equal(result.matches.length, 1);
|
||||
const match = result.matches[0];
|
||||
assert.equal(match.state, "mapped");
|
||||
assert.deepEqual(match.original_position, {
|
||||
...site.originalPosition,
|
||||
offset: site.originalOffset,
|
||||
content_position: "verified-in-embedded-text",
|
||||
});
|
||||
assert.equal(
|
||||
match.resolved_url,
|
||||
new URL("../src/fixture.ts?v=7#original", input.source_map.url).href,
|
||||
);
|
||||
assert.equal(match.content.state, "embedded");
|
||||
assert.equal(match.content.text, site.original);
|
||||
assert.equal(match.content.utf8_sha256, sha(site.original));
|
||||
assert.ok(result.runtime.v8_heap_limit_bytes <= 256 * 1024 * 1024);
|
||||
assert.deepEqual(evidence.raw_result, { source_map_text: site.map });
|
||||
return result;
|
||||
}
|
||||
const sha = (text) => createHash("sha256").update(text).digest("hex");
|
||||
|
||||
async function assertPublicPair(cli, client, oracle) {
|
||||
const { input } = oracle;
|
||||
const evidence = await cli(
|
||||
"trace-web-source-location",
|
||||
input.manifest_path,
|
||||
String(input.script_index),
|
||||
input.source_map.path,
|
||||
input.source_map.url,
|
||||
String(input.generated_position.line),
|
||||
String(input.generated_position.column),
|
||||
);
|
||||
const expected = assertPoint(evidence, oracle);
|
||||
const response = await client.callTool({
|
||||
name: "trace_web_source_location",
|
||||
arguments: input,
|
||||
});
|
||||
assert.notEqual(response.isError, true, mcpTextValue(response));
|
||||
const mcpEvidence = parseEvidence(
|
||||
JSON.parse(mcpTextValue(response)).evidence,
|
||||
);
|
||||
assert.deepEqual(assertPoint(mcpEvidence, oracle), expected);
|
||||
assert.equal(evidence.parameters.source_map.url, input.source_map.url);
|
||||
return expected;
|
||||
}
|
||||
|
|
@ -96,6 +96,21 @@ export const toolFamilyCatalog = (sources) => {
|
|||
|
||||
/** Build provider identities with their sorted capability names. */
|
||||
export const providerCatalog = (sources) => {
|
||||
const contractsByName = new Map(
|
||||
sources.toolContracts.TOOL_CONTRACTS.map((contract) => [
|
||||
contract.name,
|
||||
contract,
|
||||
]),
|
||||
);
|
||||
const declaredContracts = (providerId, operations) =>
|
||||
operations.map((operation) => {
|
||||
const contract = contractsByName.get(operation);
|
||||
if (contract === undefined)
|
||||
throw new TypeError(
|
||||
`Provider ${providerId} declares an unknown analyst operation: ${operation}`,
|
||||
);
|
||||
return contract;
|
||||
});
|
||||
const {
|
||||
applicationContracts,
|
||||
reconciliationContracts,
|
||||
|
|
@ -105,15 +120,21 @@ export const providerCatalog = (sources) => {
|
|||
return [
|
||||
{
|
||||
identity: sources.hopperProvider.HOPPER_PROVIDER_IDENTITY,
|
||||
contracts: sources.hopperProvider.HOPPER_PROVIDER_TOOL_CONTRACTS,
|
||||
contracts: declaredContracts(
|
||||
"hopper",
|
||||
sources.hopperProvider.HOPPER_OPERATIONS,
|
||||
),
|
||||
},
|
||||
{
|
||||
identity: sources.ghidraProvider.GHIDRA_PROVIDER_IDENTITY,
|
||||
contracts: sources.ghidraProvider.GHIDRA_PROVIDER_TOOL_CONTRACTS,
|
||||
contracts: declaredContracts(
|
||||
"ghidra",
|
||||
sources.ghidraProvider.GHIDRA_OPERATIONS,
|
||||
),
|
||||
},
|
||||
{
|
||||
identity: sources.idaProvider.IDA_PROVIDER_IDENTITY,
|
||||
contracts: sources.idaProvider.IDA_PROVIDER_TOOL_CONTRACTS,
|
||||
contracts: declaredContracts("ida", sources.idaProvider.IDA_OPERATIONS),
|
||||
},
|
||||
{
|
||||
identity: sources.nativeProvider.NATIVE_MACOS_PROVIDER_IDENTITY,
|
||||
|
|
|
|||
|
|
@ -59,8 +59,8 @@ const SOURCE_PATHS = {
|
|||
"dist/contracts/javascriptRecoveryToolContracts.js",
|
||||
javascriptRecoveryProvider: "dist/javascript/recovery/WakaruRelease.js",
|
||||
supportedClients: "dist/application/SupportedClients.js",
|
||||
hopperProvider: "dist/hopper/HopperProvider.js",
|
||||
ghidraProvider: "dist/ghidra/GhidraProvider.js",
|
||||
hopperProvider: "dist/hopper/HopperProviderCapabilities.js",
|
||||
ghidraProvider: "dist/ghidra/GhidraProviderCapabilities.js",
|
||||
idaProvider: "dist/ida/IdaProviderCapabilities.js",
|
||||
nativeProvider: "dist/native/NativeMacOSProviderMetadata.js",
|
||||
artifactProviders: "dist/application/InvestigationProviders.js",
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { parseBinaryTarget } from "../../dist/application/BinaryTargetResolver.j
|
|||
import { inspectManagedArtifactBytes } from "../../dist/dotnet/ManagedArtifactInspector.js";
|
||||
import { inspectManagedMembersBytes } from "../../dist/dotnet/ManagedMemberInspector.js";
|
||||
import { projectManagedApplicationGraphEvidence } from "../../dist/application/ManagedApplicationGraphService.js";
|
||||
import { traceApplicationFeatureEvidence } from "../../dist/application/JavaScriptApplicationWorkflowService.js";
|
||||
import { traceApplicationFeatureEvidence } from "../../dist/application/javascript/JavaScriptApplicationWorkflowService.js";
|
||||
import { createEvidence } from "../../dist/domain/evidence.js";
|
||||
import { MANAGED_STATIC_PROVIDER } from "../../dist/application/InvestigationProviders.js";
|
||||
import {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ export interface ModuleBoundaryViolation {
|
|||
readonly boundary:
|
||||
| "pure-layer"
|
||||
| "application-composition"
|
||||
| "provider-construction";
|
||||
| "provider-construction"
|
||||
| "provider-generated-catalog";
|
||||
}
|
||||
|
||||
/** Check resolved source ownership, including type imports and reexports. */
|
||||
|
|
|
|||
|
|
@ -13,6 +13,13 @@ const MIGRATED_PROVIDER_ROOTS = new Set([
|
|||
"inspector",
|
||||
"javascript",
|
||||
]);
|
||||
const PROVIDER_ROOTS = new Set([
|
||||
...MIGRATED_PROVIDER_ROOTS,
|
||||
"artifacts",
|
||||
"browser",
|
||||
"dotnet",
|
||||
"native",
|
||||
]);
|
||||
|
||||
const repositoryPath = (root, path) =>
|
||||
relative(root, path).replaceAll("\\", "/");
|
||||
|
|
@ -53,6 +60,11 @@ const failedBoundary = (file, target) => {
|
|||
if (!file.startsWith("src/") || !target.startsWith("src/")) return undefined;
|
||||
const layer = file.split("/")[1];
|
||||
const targetLayer = target.split("/")[1];
|
||||
if (
|
||||
PROVIDER_ROOTS.has(layer) &&
|
||||
/^src\/generatedMcpToolCatalog\.(?:js|ts)$/u.test(target)
|
||||
)
|
||||
return "provider-generated-catalog";
|
||||
if (PURE_LAYERS.has(layer)) {
|
||||
if (
|
||||
(/^src\/[^/]+\//u.test(target) && !PURE_LAYERS.has(targetLayer)) ||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env node
|
||||
import { access } from "node:fs/promises";
|
||||
import { isAbsolute } from "node:path";
|
||||
import { verifyBrowserSourceMap } from "./lib/browser-source-map-e2e.mjs";
|
||||
import { createVerifierRun, completeVerifierRun } from "./lib/verifier-run.mjs";
|
||||
const executable = process.env.REA_BROWSER_EXECUTABLE;
|
||||
if (!executable || !isAbsolute(executable))
|
||||
throw new Error(
|
||||
"verify:browser:source-maps requires absolute REA_BROWSER_EXECUTABLE pointing to caller-supplied Chromium",
|
||||
);
|
||||
await access(executable);
|
||||
const run = createVerifierRun();
|
||||
const proof = await verifyBrowserSourceMap(executable, process.argv[2]);
|
||||
process.stdout.write(
|
||||
`${JSON.stringify({ ...proof, verifier_run: await completeVerifierRun(run), verified: true })}\n`,
|
||||
);
|
||||
|
|
@ -10,7 +10,7 @@ import { compareManagedMemberPaths } from "../dist/application/ManagedMemberComp
|
|||
import { verifyManagedNativeBoundariesEvidence } from "../dist/application/ManagedNativeVerificationService.js";
|
||||
import { importManagedReconstructionEvidence } from "../dist/application/ManagedReconstructionService.js";
|
||||
import { projectManagedApplicationGraphEvidence } from "../dist/application/ManagedApplicationGraphService.js";
|
||||
import { traceApplicationFeatureEvidence } from "../dist/application/JavaScriptApplicationWorkflowService.js";
|
||||
import { traceApplicationFeatureEvidence } from "../dist/application/javascript/JavaScriptApplicationWorkflowService.js";
|
||||
import { MANAGED_STATIC_PROVIDER } from "../dist/application/InvestigationProviders.js";
|
||||
import { createEvidence } from "../dist/domain/evidence.js";
|
||||
import {
|
||||
|
|
|
|||
|
|
@ -3,16 +3,19 @@
|
|||
import { realpath } from "node:fs/promises";
|
||||
import { parseArgs } from "node:util";
|
||||
|
||||
import { analyzeJavaScriptApplication } from "../dist/application/JavaScriptApplicationService.js";
|
||||
import { analyzeJavaScriptApplication } from "../../../dist/application/javascript/JavaScriptApplicationService.js";
|
||||
import {
|
||||
compareApplicationVersionsEvidence,
|
||||
compareJavaScriptExportShapesEvidence,
|
||||
traceApplicationFeatureEvidence,
|
||||
} from "../dist/application/JavaScriptApplicationWorkflowService.js";
|
||||
import { applicationVersionComparisonResultSchema } from "../dist/domain/javascriptApplicationVersionComparisonSchemas.js";
|
||||
import { applicationFeatureTraceResultSchema } from "../dist/domain/javascriptFeatureTraceSchemas.js";
|
||||
import { javaScriptExportShapeComparisonResultSchema } from "../dist/domain/javascriptExportShapeComparisonSchemas.js";
|
||||
import { completeVerifierRun, createVerifierRun } from "./lib/verifier-run.mjs";
|
||||
} from "../../../dist/application/javascript/JavaScriptApplicationWorkflowService.js";
|
||||
import { applicationVersionComparisonResultSchema } from "../../../dist/domain/javascriptApplicationVersionComparisonSchemas.js";
|
||||
import { applicationFeatureTraceResultSchema } from "../../../dist/domain/javascriptFeatureTraceSchemas.js";
|
||||
import { javaScriptExportShapeComparisonResultSchema } from "../../../dist/domain/javascriptExportShapeComparisonSchemas.js";
|
||||
import {
|
||||
completeVerifierRun,
|
||||
createVerifierRun,
|
||||
} from "../../lib/verifier-run.mjs";
|
||||
|
||||
const verifierRun = createVerifierRun();
|
||||
|
||||
|
|
@ -4,8 +4,11 @@ import assert from "node:assert/strict";
|
|||
import { constants } from "node:buffer";
|
||||
import { createHash } from "node:crypto";
|
||||
|
||||
import { canonicalDigest } from "../dist/domain/comparisonSemantics.js";
|
||||
import { createEvidence, parseEvidence } from "../dist/domain/evidence.js";
|
||||
import { canonicalDigest } from "../../../dist/domain/comparisonSemantics.js";
|
||||
import {
|
||||
createEvidence,
|
||||
parseEvidence,
|
||||
} from "../../../dist/domain/evidence.js";
|
||||
|
||||
// This opt-in check crosses the actual engine string limit; keep it outside
|
||||
// routine source tests. Build first, then run this script with the local Node.
|
||||
|
|
@ -9,10 +9,10 @@ import { fileURLToPath } from "node:url";
|
|||
import { promisify } from "node:util";
|
||||
import { Client } from "@modelcontextprotocol/client";
|
||||
import { StdioClientTransport } from "@modelcontextprotocol/client/stdio";
|
||||
import { parseEvidence } from "../dist/domain/evidence.js";
|
||||
import { javascriptRecoveryResultSchema } from "../dist/domain/javascriptRecovery.js";
|
||||
import { buildRecoveryFixtures } from "./lib/javascript-recovery-fixtures.mjs";
|
||||
import { mcpTextValue } from "./lib/mcp-verifier-results.mjs";
|
||||
import { parseEvidence } from "../../../dist/domain/evidence.js";
|
||||
import { javascriptRecoveryResultSchema } from "../../../dist/domain/javascriptRecovery.js";
|
||||
import { buildRecoveryFixtures } from "../../fixtures/javascript-recovery/build.mjs";
|
||||
import { mcpTextValue } from "../../lib/mcp-verifier-results.mjs";
|
||||
|
||||
const OFFICIAL_BINARY_SHA256 =
|
||||
"e8c7ca052974604197389f6ace7464e4dd24dce64e2730971521bd6606ec9c9e";
|
||||
|
|
@ -21,7 +21,7 @@ if (!process.env.REA_WAKARU_COMMAND)
|
|||
"Provide REA_WAKARU_COMMAND for the official Wakaru 1.13.0 Linux x64 binary",
|
||||
);
|
||||
const entrypoint =
|
||||
process.argv[2] ?? fileURLToPath(new URL("./rea.mjs", import.meta.url));
|
||||
process.argv[2] ?? fileURLToPath(new URL("../../rea.mjs", import.meta.url));
|
||||
const root = await mkdtemp(join(tmpdir(), "rea-real-recovery-"));
|
||||
const environment = { ...process.env, REA_LOG_LEVEL: "silent" };
|
||||
const transport = new StdioClientTransport({
|
||||
|
|
@ -3,9 +3,12 @@
|
|||
import { readFile, realpath } from "node:fs/promises";
|
||||
import { parseArgs } from "node:util";
|
||||
|
||||
import { analyzeJavaScriptApplication } from "../dist/application/JavaScriptApplicationService.js";
|
||||
import { reconcileJavaScriptRuntimeEvidence } from "../dist/application/JavaScriptRuntimeReconciliationService.js";
|
||||
import { completeVerifierRun, createVerifierRun } from "./lib/verifier-run.mjs";
|
||||
import { analyzeJavaScriptApplication } from "../../../dist/application/javascript/JavaScriptApplicationService.js";
|
||||
import { reconcileJavaScriptRuntimeEvidence } from "../../../dist/application/javascript/JavaScriptRuntimeReconciliationService.js";
|
||||
import {
|
||||
completeVerifierRun,
|
||||
createVerifierRun,
|
||||
} from "../../lib/verifier-run.mjs";
|
||||
|
||||
const verifierRun = createVerifierRun();
|
||||
|
||||
|
|
@ -3,8 +3,8 @@ name: reverse-engineer-anything
|
|||
description: Reverse engineer native, managed, Electron/JavaScript, packaged, firmware, and browser targets with REA. Use shipped-artifact or requested runtime evidence to explain features, compare versions, decompile code, or guide a reconstruction. Skip REA for ordinary source-repository architecture analysis.
|
||||
metadata:
|
||||
version: "26"
|
||||
tool_count: 130
|
||||
catalog_digest: "ca2f454e044d0095736974fa078383989ab848e420fcebb6127d2c6869c47f1c"
|
||||
tool_count: 131
|
||||
catalog_digest: "f07ae6f3910102f58197c86e34e1f06b3cc1f3bf341faa140b4fa2ff65182764"
|
||||
---
|
||||
|
||||
# REA
|
||||
|
|
|
|||
|
|
@ -12,9 +12,10 @@ import { execFile } from "node:child_process";
|
|||
import { extname, isAbsolute, join, resolve } from "node:path";
|
||||
import { promisify } from "node:util";
|
||||
|
||||
import { parse as parsePlist } from "plist";
|
||||
import { z } from "zod";
|
||||
|
||||
import { isPathWithinRoot } from "../domain/localPath.js";
|
||||
import { parseXmlPropertyList } from "../domain/propertyListKeys.js";
|
||||
import { BinaryTargetError } from "../domain/configurationErrors.js";
|
||||
import type { BinaryTarget } from "../domain/binaryTargetTypes.js";
|
||||
import { err, ok, type Result } from "../domain/result.js";
|
||||
|
|
@ -268,21 +269,15 @@ const resolveAppBundle = async (
|
|||
|
||||
/** Decode the top-level executable name with an XML parser, not a pattern. */
|
||||
const parseXmlPlistExecutable = (plist: string): string => {
|
||||
const value = parsePlist(plist);
|
||||
const executable =
|
||||
typeof value === "object" &&
|
||||
value !== null &&
|
||||
!Array.isArray(value) &&
|
||||
!(value instanceof Date) &&
|
||||
!(value instanceof Uint8Array) &&
|
||||
Object.hasOwn(value, "CFBundleExecutable")
|
||||
? value.CFBundleExecutable
|
||||
: undefined;
|
||||
if (typeof executable !== "string")
|
||||
throw new Error("CFBundleExecutable is missing");
|
||||
return executable;
|
||||
// An unrelated `__proto__` entry must not make the bundle unreadable.
|
||||
const { value } = parseXmlPropertyList(plist);
|
||||
const executable = executableEntrySchema.safeParse(value);
|
||||
if (!executable.success) throw new Error("CFBundleExecutable is missing");
|
||||
return executable.data.CFBundleExecutable;
|
||||
};
|
||||
|
||||
const executableEntrySchema = z.looseObject({ CFBundleExecutable: z.string() });
|
||||
|
||||
const readBinaryPlistExecutable = async (plistPath: string): Promise<string> =>
|
||||
// `-n` strips only the newline plutil appends; it requires macOS 12+.
|
||||
(
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { createHash } from "node:crypto";
|
||||
import { parse, parseBinary } from "plist";
|
||||
import { parseBinary } from "plist";
|
||||
|
||||
import { DirectoryArtifactReader } from "../artifacts/DirectoryArtifactReader.js";
|
||||
import { parseXmlPropertyList } from "../domain/propertyListKeys.js";
|
||||
import {
|
||||
decodeNibArchive,
|
||||
type NibArchiveDocument,
|
||||
|
|
@ -373,6 +374,6 @@ const decodePlist = (bytes: Buffer): JsonValue => {
|
|||
const parsed =
|
||||
bytes.subarray(0, 8).toString("ascii") === "bplist00"
|
||||
? parseBinary(bytes)
|
||||
: parse(bytes.toString("utf8"));
|
||||
: parseXmlPropertyList(bytes.toString("utf8")).value;
|
||||
return jsonValueSchema.parse(parsed);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import type { BrowserObservationPort } from "./BrowserObservationPort.js";
|
||||
import type { BrowserScenarioCapturePort } from "./BrowserScenarioCapturePort.js";
|
||||
import type { ElectronObservationPort } from "./ElectronObservationPort.js";
|
||||
import type { ElectronActiveObservationPort } from "./ElectronActiveObservationPort.js";
|
||||
import type { JavaScriptRuntimeObservationPort } from "./JavaScriptRuntimeObservationPort.js";
|
||||
import type { ElectronObservationPort } from "./javascript/ElectronObservationPort.js";
|
||||
import type { ElectronActiveObservationPort } from "./javascript/ElectronActiveObservationPort.js";
|
||||
import type { JavaScriptRuntimeObservationPort } from "./javascript/JavaScriptRuntimeObservationPort.js";
|
||||
import { AnalysisCapabilityUnavailableError } from "../domain/analysisErrorCore.js";
|
||||
|
||||
/** Existing observation ports loaded independently at MCP startup. */
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import type {
|
|||
ReconstructionObligation,
|
||||
ReviewedReconstructionObligation,
|
||||
} from "../domain/reconstructionObligationLedgerSchemas.js";
|
||||
import { parseApplicationGraphEvidence } from "./JavaScriptApplicationEvidenceGraph.js";
|
||||
import { parseApplicationGraphEvidence } from "./javascript/JavaScriptApplicationEvidenceGraph.js";
|
||||
import {
|
||||
applicationObligationPolicy,
|
||||
semanticObligationPolicy,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
import { createHash } from "node:crypto";
|
||||
import type { AnalysisError } from "../domain/analysisErrorBase.js";
|
||||
import { AnalysisOutputError } from "../domain/analysisErrorCore.js";
|
||||
import { err, ok, type Result } from "../domain/result.js";
|
||||
import type {
|
||||
SelectedWebScriptArtifacts,
|
||||
SelectedWebScriptInput,
|
||||
} from "../domain/webScriptArtifacts.js";
|
||||
import type { ExportedWebScript } from "../domain/webScriptExport.js";
|
||||
|
||||
/** Bind actual source text to the selected manifest entry before analysis. */
|
||||
export const validateSelectedWebScript = (
|
||||
input: SelectedWebScriptInput,
|
||||
data: SelectedWebScriptArtifacts,
|
||||
operation: string,
|
||||
): Result<ExportedWebScript, AnalysisError> => {
|
||||
const selected = data.manifest.scripts[input.script_index];
|
||||
if (
|
||||
selected === undefined ||
|
||||
selected.content.state !== "exported" ||
|
||||
selected.content.sha256 !== data.sourceFile.sha256 ||
|
||||
selected.content.bytes !== data.sourceFile.bytes ||
|
||||
Buffer.byteLength(data.source) !== data.sourceFile.bytes ||
|
||||
createHash("sha256").update(data.source, "utf8").digest("hex") !==
|
||||
data.sourceFile.sha256 ||
|
||||
data.manifestFile.path !== input.manifest_path
|
||||
)
|
||||
return err(
|
||||
new AnalysisOutputError(
|
||||
operation,
|
||||
"Artifact port changed the selected script/source identity.",
|
||||
),
|
||||
);
|
||||
return ok(selected);
|
||||
};
|
||||
|
||||
/** Carry reported capture context alongside independently verified manifest bytes. */
|
||||
export const capturedWebManifestIdentity = (
|
||||
data: SelectedWebScriptArtifacts,
|
||||
) => ({
|
||||
...data.manifestFile,
|
||||
reported_output_directory: data.manifest.output_directory,
|
||||
capture_sha256: data.manifest.capture_sha256,
|
||||
capture_path: data.manifest.capture_path,
|
||||
capture_kind: data.manifest.capture_kind,
|
||||
capture_completeness: data.manifest.capture_completeness,
|
||||
source_evidence_id: data.manifest.source_evidence_id,
|
||||
});
|
||||
|
|
@ -6,18 +6,13 @@ import type {
|
|||
WebModuleResolution,
|
||||
WebModuleTraceInput,
|
||||
} from "../domain/webModuleTrace.js";
|
||||
import type { webScriptExportManifestSchema } from "../domain/webScriptExport.js";
|
||||
import type { z } from "zod";
|
||||
import type { SelectedWebScriptArtifacts } from "../domain/webScriptArtifacts.js";
|
||||
import type { ExecutionOptions } from "./AnalysisProvider.js";
|
||||
|
||||
type JsonObject = Record<string, JsonValue>;
|
||||
|
||||
/** Verified selected source and capture metadata; provider protocols stay outside. */
|
||||
export interface WebModuleArtifacts {
|
||||
readonly manifest: z.output<typeof webScriptExportManifestSchema>;
|
||||
readonly manifestFile: WebModuleFile;
|
||||
readonly sourceFile: WebModuleFile;
|
||||
readonly source: string;
|
||||
export interface WebModuleArtifacts extends SelectedWebScriptArtifacts {
|
||||
readonly importMap: {
|
||||
readonly file: WebModuleFile;
|
||||
readonly baseUrl: string;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { isAbsolute } from "node:path";
|
||||
import { createHash } from "node:crypto";
|
||||
import { z } from "zod";
|
||||
import type { AnalysisError } from "../domain/analysisErrorBase.js";
|
||||
import {
|
||||
|
|
@ -24,7 +23,11 @@ import {
|
|||
type WebModuleResolution,
|
||||
type WebModuleTraceResult,
|
||||
} from "../domain/webModuleTrace.js";
|
||||
import { webScriptExportManifestSchema } from "../domain/webScriptExport.js";
|
||||
import { selectedWebScriptArtifactsSchema } from "../domain/webScriptArtifacts.js";
|
||||
import {
|
||||
capturedWebManifestIdentity,
|
||||
validateSelectedWebScript,
|
||||
} from "./ValidateSelectedWebScript.js";
|
||||
import type { ExecutionOptions } from "./AnalysisProvider.js";
|
||||
import type {
|
||||
WebModuleArtifactPort,
|
||||
|
|
@ -33,11 +36,7 @@ import type {
|
|||
} from "./WebModulePorts.js";
|
||||
|
||||
const OPERATION = "trace_web_module_imports";
|
||||
const artifactsSchema = z.strictObject({
|
||||
manifest: webScriptExportManifestSchema,
|
||||
manifestFile: webModuleFileSchema,
|
||||
sourceFile: webModuleFileSchema,
|
||||
source: z.string(),
|
||||
const artifactsSchema = selectedWebScriptArtifactsSchema.extend({
|
||||
importMap: z
|
||||
.strictObject({
|
||||
file: webModuleFileSchema,
|
||||
|
|
@ -125,23 +124,9 @@ export class WebModuleTraceService {
|
|||
"Artifact port changed the selected import-map identity/context.",
|
||||
),
|
||||
);
|
||||
const selected = data.manifest.scripts[input.script_index];
|
||||
if (
|
||||
selected === undefined ||
|
||||
selected.content.state !== "exported" ||
|
||||
selected.content.sha256 !== data.sourceFile.sha256 ||
|
||||
selected.content.bytes !== data.sourceFile.bytes ||
|
||||
Buffer.byteLength(data.source) !== data.sourceFile.bytes ||
|
||||
createHash("sha256").update(data.source, "utf8").digest("hex") !==
|
||||
data.sourceFile.sha256 ||
|
||||
data.manifestFile.path !== input.manifest_path
|
||||
)
|
||||
return err(
|
||||
new AnalysisOutputError(
|
||||
OPERATION,
|
||||
"Artifact port did not bind the selected source and manifest identities.",
|
||||
),
|
||||
);
|
||||
const bound = validateSelectedWebScript(input, data, OPERATION);
|
||||
if (!bound.ok) return bound;
|
||||
const selected = bound.value;
|
||||
const importerUrl = input.importer_url ?? selected.url;
|
||||
const importerAdmission = admitContext(importerUrl, ["importer_url"]);
|
||||
if (!importerAdmission.ok) return importerAdmission;
|
||||
|
|
@ -215,15 +200,7 @@ export class WebModuleTraceService {
|
|||
});
|
||||
}
|
||||
const normalized = webModuleTraceResultSchema.safeParse({
|
||||
manifest: {
|
||||
...data.manifestFile,
|
||||
reported_output_directory: data.manifest.output_directory,
|
||||
capture_sha256: data.manifest.capture_sha256,
|
||||
capture_path: data.manifest.capture_path,
|
||||
capture_kind: data.manifest.capture_kind,
|
||||
capture_completeness: data.manifest.capture_completeness,
|
||||
source_evidence_id: data.manifest.source_evidence_id,
|
||||
},
|
||||
manifest: capturedWebManifestIdentity(data),
|
||||
source: {
|
||||
...data.sourceFile,
|
||||
script_index: input.script_index,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
import type { AnalysisError } from "../domain/analysisErrorBase.js";
|
||||
import type { Result } from "../domain/result.js";
|
||||
import type {
|
||||
SelectedWebScriptArtifacts,
|
||||
SelectedWebScriptInput,
|
||||
} from "../domain/webScriptArtifacts.js";
|
||||
import type { ExecutionOptions } from "./AnalysisProvider.js";
|
||||
|
||||
/** Read the caller-selected capture export and verify the selected source identity. */
|
||||
export interface WebScriptArtifactPort {
|
||||
load(
|
||||
input: SelectedWebScriptInput,
|
||||
options?: ExecutionOptions,
|
||||
): Promise<Result<SelectedWebScriptArtifacts, AnalysisError>>;
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
import type { AnalysisError } from "../domain/analysisErrorBase.js";
|
||||
import type { Result } from "../domain/result.js";
|
||||
import type {
|
||||
WebSourceLocationInput,
|
||||
WebSourceMapReport,
|
||||
} from "../domain/webSourceLocation.js";
|
||||
import type { SelectedWebScriptArtifacts } from "../domain/webScriptArtifacts.js";
|
||||
import type { z } from "zod";
|
||||
import type { webArtifactFileSchema } from "../domain/webScriptArtifacts.js";
|
||||
import type { ExecutionOptions } from "./AnalysisProvider.js";
|
||||
|
||||
/** Actual selected source and local map bytes; no provider URL fetching. */
|
||||
export interface WebSourceLocationArtifacts extends SelectedWebScriptArtifacts {
|
||||
readonly sourceMap: {
|
||||
readonly file: z.output<typeof webArtifactFileSchema>;
|
||||
readonly url: string;
|
||||
readonly text: string;
|
||||
};
|
||||
}
|
||||
|
||||
/** Replaceable artifact acquisition boundary for a caller-selected pairing. */
|
||||
export interface WebSourceLocationArtifactPort {
|
||||
load(
|
||||
input: WebSourceLocationInput,
|
||||
options?: ExecutionOptions,
|
||||
): Promise<Result<WebSourceLocationArtifacts, AnalysisError>>;
|
||||
}
|
||||
|
||||
/** Replaceable codec receives map data and one explicit generated point. */
|
||||
export interface WebSourceMapPort {
|
||||
trace(
|
||||
input: {
|
||||
readonly text: string;
|
||||
readonly path: string;
|
||||
readonly url: string;
|
||||
readonly position: WebSourceLocationInput["generated_position"];
|
||||
},
|
||||
options?: ExecutionOptions,
|
||||
): Promise<Result<WebSourceMapReport, AnalysisError>>;
|
||||
}
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
import { expect, it } from "vitest";
|
||||
import {
|
||||
webSourceLocationArgs as args,
|
||||
webSourceLocationFixture,
|
||||
webSourceMapDecoderFixture as decoder,
|
||||
} from "../../tests/fixtures/webSourceLocation.js";
|
||||
import { projectAnalysisError } from "../domain/analysisErrorProjection.js";
|
||||
import { ok } from "../domain/result.js";
|
||||
import { webSourceLocationResultSchema } from "../domain/webSourceLocation.js";
|
||||
import { WebSourceLocationService } from "./WebSourceLocationService.js";
|
||||
import type { WebSourceMapPort } from "./WebSourceLocationPorts.js";
|
||||
|
||||
const service = (data = webSourceLocationFixture(), port = decoder) =>
|
||||
new WebSourceLocationService({ load: () => Promise.resolve(ok(data)) }, port);
|
||||
it("joins byte identity and historical capture context while keeping selected authenticity/execution unknown", async () => {
|
||||
const data = webSourceLocationFixture();
|
||||
data.manifest.source_evidence_id = `ev_${"a".repeat(64)}`;
|
||||
const response = await service(data).trace(args);
|
||||
if (!response.ok) throw response.error;
|
||||
const result = webSourceLocationResultSchema.parse(
|
||||
response.value.normalized_result,
|
||||
);
|
||||
expect(result).toMatchObject({
|
||||
source: { sha256: data.sourceFile.sha256 },
|
||||
source_map: {
|
||||
association: "caller-selected",
|
||||
sha256: data.sourceMap.file.sha256,
|
||||
},
|
||||
matches: [{ state: "mapped", content: { text: "original" } }],
|
||||
execution: "unknown",
|
||||
source_authenticity: "unknown",
|
||||
});
|
||||
expect(response.value.raw_result).toEqual({
|
||||
source_map_text: data.sourceMap.text,
|
||||
});
|
||||
});
|
||||
it.each([
|
||||
{ ...args, manifest_path: "relative.json" },
|
||||
{ ...args, script_index: -1 },
|
||||
{ ...args, source_map: { ...args.source_map, path: "relative.map" } },
|
||||
{ ...args, source_map: { ...args.source_map, url: "relative.map" } },
|
||||
{ ...args, generated_position: { line: 0, column: 0 } },
|
||||
])(
|
||||
"rejects invalid selected context before acquiring artifacts: %j",
|
||||
async (input) => {
|
||||
const response = await new WebSourceLocationService(
|
||||
{
|
||||
load: () => {
|
||||
throw new Error("must not acquire");
|
||||
},
|
||||
},
|
||||
decoder,
|
||||
).trace(input);
|
||||
if (response.ok) throw new Error("expected invalid input");
|
||||
expect(projectAnalysisError(response.error).code).toBe("invalid_request");
|
||||
},
|
||||
);
|
||||
it.each([
|
||||
"file:///analysis/app.map",
|
||||
"webpack:///bundle/app.map",
|
||||
"https://selected-user:selected-value@app.test/maps/app.map",
|
||||
])(
|
||||
"retains an absolute inert map context without fetching: %s",
|
||||
async (url) => {
|
||||
const fixture = webSourceLocationFixture();
|
||||
const data = { ...fixture, sourceMap: { ...fixture.sourceMap, url } };
|
||||
const response = await service(data).trace({
|
||||
...args,
|
||||
source_map: { ...args.source_map, url },
|
||||
});
|
||||
if (!response.ok) throw response.error;
|
||||
expect(
|
||||
webSourceLocationResultSchema.parse(response.value.normalized_result)
|
||||
.url_context,
|
||||
).toBe(url);
|
||||
},
|
||||
);
|
||||
it.each(["source", "map", "map-path", "map-url"])(
|
||||
"rejects changed artifact identity before decoding: %s",
|
||||
async (variant) => {
|
||||
const fixture = webSourceLocationFixture();
|
||||
const data = {
|
||||
...fixture,
|
||||
source: variant === "source" ? "different" : fixture.source,
|
||||
sourceMap: { ...fixture.sourceMap },
|
||||
};
|
||||
if (variant === "map") data.sourceMap.text += " ";
|
||||
if (variant === "map-path") data.sourceMap.file.path = "/other.map";
|
||||
if (variant === "map-url") data.sourceMap.url = "https://other.test/";
|
||||
const response = await service(data, {
|
||||
trace: () => {
|
||||
throw new Error("must not decode");
|
||||
},
|
||||
}).trace(args);
|
||||
if (response.ok) throw new Error("expected changed identity failure");
|
||||
expect(response.error._tag).toBe("AnalysisOutputError");
|
||||
},
|
||||
);
|
||||
it.each(["digest", "url", "point"])(
|
||||
"rejects changed codec identity: %s",
|
||||
async (variant) => {
|
||||
const port: WebSourceMapPort = {
|
||||
trace: async (input) => {
|
||||
const decoded = await decoder.trace(input);
|
||||
if (!decoded.ok) return decoded;
|
||||
const report = decoded.value;
|
||||
if (variant === "digest") report.source_map_sha256 = "f".repeat(64);
|
||||
if (variant === "url") report.url_context = "https://other.test/";
|
||||
if (variant === "point") report.lookup.requested.column += 1;
|
||||
return Promise.resolve(ok(report));
|
||||
},
|
||||
};
|
||||
const response = await service(undefined, port).trace(args);
|
||||
if (response.ok) throw new Error("expected changed codec identity failure");
|
||||
expect(response.error._tag).toBe("AnalysisOutputError");
|
||||
},
|
||||
);
|
||||
it("rejects a generated point outside retained text before decoding", async () => {
|
||||
const response = await service(undefined, {
|
||||
trace: () => {
|
||||
throw new Error("must not decode");
|
||||
},
|
||||
}).trace({ ...args, generated_position: { line: 2, column: 0 } });
|
||||
if (response.ok) throw new Error("expected invalid point");
|
||||
expect(projectAnalysisError(response.error)).toMatchObject({
|
||||
code: "invalid_request",
|
||||
details: { issues: [{ message: expect.stringContaining("outside") }] },
|
||||
});
|
||||
});
|
||||
it("honors cancellation both before acquisition and across decoder completion", async () => {
|
||||
const first = new AbortController();
|
||||
first.abort();
|
||||
const response = await new WebSourceLocationService(
|
||||
{
|
||||
load: () => {
|
||||
throw new Error("must not acquire");
|
||||
},
|
||||
},
|
||||
decoder,
|
||||
).trace(args, { signal: first.signal });
|
||||
expect(response.ok).toBe(false);
|
||||
const controller = new AbortController();
|
||||
const late = await service(undefined, {
|
||||
trace: (input) => {
|
||||
controller.abort();
|
||||
return decoder.trace(input);
|
||||
},
|
||||
}).trace(args, { signal: controller.signal });
|
||||
if (late.ok) throw new Error("expected cancellation");
|
||||
expect(late.error._tag).toBe("AnalysisCancelledError");
|
||||
});
|
||||
|
|
@ -0,0 +1,239 @@
|
|||
import { createHash } from "node:crypto";
|
||||
import { isAbsolute } from "node:path";
|
||||
import { z } from "zod";
|
||||
import type { AnalysisError } from "../domain/analysisErrorBase.js";
|
||||
import {
|
||||
AnalysisCancelledError,
|
||||
AnalysisInputError,
|
||||
AnalysisOutputError,
|
||||
} from "../domain/analysisErrorCore.js";
|
||||
import { createEvidence, type Evidence } from "../domain/evidence.js";
|
||||
import { projectInputIssues } from "../domain/inputIssueProjection.js";
|
||||
import { jsonObjectSchema } from "../domain/jsonValue.js";
|
||||
import { err, ok, type Result } from "../domain/result.js";
|
||||
import {
|
||||
selectedWebScriptArtifactsSchema,
|
||||
webArtifactFileSchema,
|
||||
} from "../domain/webScriptArtifacts.js";
|
||||
import {
|
||||
WEB_SOURCE_MAP_LIMITS,
|
||||
webSourceLocationInputSchema,
|
||||
webSourceLocationResultSchema,
|
||||
webSourceMapReportSchema,
|
||||
type WebSourceLocationInput,
|
||||
type WebSourceMapReport,
|
||||
} from "../domain/webSourceLocation.js";
|
||||
import { webSourceOffset } from "../domain/webSourcePosition.js";
|
||||
import type { ExecutionOptions } from "./AnalysisProvider.js";
|
||||
import {
|
||||
capturedWebManifestIdentity,
|
||||
validateSelectedWebScript,
|
||||
} from "./ValidateSelectedWebScript.js";
|
||||
import type {
|
||||
WebSourceLocationArtifactPort,
|
||||
WebSourceMapPort,
|
||||
} from "./WebSourceLocationPorts.js";
|
||||
|
||||
const OPERATION = "trace_web_source_location";
|
||||
const artifactsSchema = selectedWebScriptArtifactsSchema.extend({
|
||||
sourceMap: z.strictObject({
|
||||
file: webArtifactFileSchema,
|
||||
url: z.string().min(1),
|
||||
text: z.string(),
|
||||
}),
|
||||
});
|
||||
const LIMITATIONS = [
|
||||
"The source/map pairing and source-map URL context are caller-selected. Deployment authenticity and execution remain unknown.",
|
||||
"Capture metadata and its Evidence reference are historical context; this trace independently verifies only the selected manifest, script and map bytes.",
|
||||
"Source names and sourceRoot are reported declarations. Resolved URLs are derived by the pinned upstream codec; no original source is fetched or executed.",
|
||||
"Embedded source hashes identify the UTF-8 encoding of decoded sourcesContent text, not an independently retained original file. Missing or out-of-range original content positions remain explicit.",
|
||||
"Lookup returns all segments at the greatest generated position not greater than the selected point, including earlier lines and generated-only segments. A mapped point does not establish an executed range or UI causality.",
|
||||
"Regular maps and inline indexed sections are supported. External section URLs are unsupported; unknown extensions are retained in raw map text and are not interpreted.",
|
||||
"Complete evidence has a 4 MiB map, 32 MiB reply, 262144 decoded rows/segments and 64-level section budget. The owned codec has a 20-second deadline, 192 MiB old-generation heap and one V8 worker; cleanup may extend the deadline. V8 heap limits do not establish aggregate RSS limits.",
|
||||
];
|
||||
|
||||
/** Join verified captured bytes with an explicitly selected source-map point. */
|
||||
export class WebSourceLocationService {
|
||||
constructor(
|
||||
readonly artifacts: WebSourceLocationArtifactPort,
|
||||
readonly decoder: WebSourceMapPort,
|
||||
) {}
|
||||
|
||||
/** Shared CLI/MCP workflow preserves raw declarations and every equal-position match. */
|
||||
async trace(
|
||||
rawInput: unknown,
|
||||
options?: ExecutionOptions,
|
||||
): Promise<Result<Evidence, AnalysisError>> {
|
||||
if (options?.signal?.aborted)
|
||||
return err(new AnalysisCancelledError(OPERATION));
|
||||
const parsed = webSourceLocationInputSchema.safeParse(rawInput);
|
||||
if (!parsed.success)
|
||||
return err(
|
||||
new AnalysisInputError(
|
||||
OPERATION,
|
||||
{ cause: parsed.error },
|
||||
projectInputIssues(parsed.error.issues, rawInput),
|
||||
),
|
||||
);
|
||||
const input = parsed.data;
|
||||
const admitted = admitContext(input);
|
||||
if (!admitted.ok) return admitted;
|
||||
const loaded = await this.artifacts.load(input, options);
|
||||
if (!loaded.ok) return loaded;
|
||||
const verified = artifactsSchema.safeParse(loaded.value);
|
||||
if (!verified.success)
|
||||
return invalidOutput(
|
||||
"Artifact port returned malformed source/map evidence.",
|
||||
);
|
||||
const data = verified.data;
|
||||
const bound = validateSelectedWebScript(input, data, OPERATION);
|
||||
if (!bound.ok) return bound;
|
||||
const map = data.sourceMap;
|
||||
const pairing = verifyPairing(input, data);
|
||||
if (!pairing.ok) return pairing;
|
||||
const generatedOffset = pairing.value;
|
||||
if (options?.signal?.aborted)
|
||||
return err(new AnalysisCancelledError(OPERATION));
|
||||
const traced = await this.decoder.trace(
|
||||
{
|
||||
text: map.text,
|
||||
path: map.file.path,
|
||||
url: map.url,
|
||||
position: input.generated_position,
|
||||
},
|
||||
options,
|
||||
);
|
||||
if (!traced.ok) return traced;
|
||||
const report = verifyReport(input, map.file.sha256, traced.value);
|
||||
if (!report.ok) return report;
|
||||
if (options?.signal?.aborted)
|
||||
return err(new AnalysisCancelledError(OPERATION));
|
||||
const normalized = webSourceLocationResultSchema.safeParse({
|
||||
...report.value,
|
||||
manifest: capturedWebManifestIdentity(data),
|
||||
source: {
|
||||
...data.sourceFile,
|
||||
script_index: input.script_index,
|
||||
script: bound.value,
|
||||
},
|
||||
source_map: { ...map.file, url: map.url, association: "caller-selected" },
|
||||
generated_offset: generatedOffset,
|
||||
source_authenticity: "unknown",
|
||||
execution: "unknown",
|
||||
limitations: LIMITATIONS,
|
||||
});
|
||||
if (!normalized.success) return invalidOutput(normalized.error.message);
|
||||
return ok(
|
||||
createEvidence(
|
||||
{
|
||||
path: data.sourceFile.path,
|
||||
sha256: data.sourceFile.sha256,
|
||||
format: "file",
|
||||
},
|
||||
{
|
||||
id: "rea-web-source-location",
|
||||
name: "REA captured source-map point trace",
|
||||
version: "1",
|
||||
},
|
||||
{
|
||||
operation: OPERATION,
|
||||
parameters: jsonObjectSchema.parse(input),
|
||||
result: normalized.data,
|
||||
rawResult: { source_map_text: map.text },
|
||||
confidence: "derived",
|
||||
authority: "historical-reference",
|
||||
limitations: LIMITATIONS,
|
||||
locations: [
|
||||
data.sourceFile.path,
|
||||
data.manifestFile.path,
|
||||
map.file.path,
|
||||
].map((path) => ({ kind: "artifact-path", path })),
|
||||
evidenceLinks:
|
||||
data.manifest.source_evidence_id === null
|
||||
? []
|
||||
: [data.manifest.source_evidence_id],
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
const invalidOutput = (message: string): Result<never, AnalysisError> =>
|
||||
err(new AnalysisOutputError(OPERATION, message));
|
||||
const invalid = (
|
||||
path: readonly string[],
|
||||
message: string,
|
||||
): Result<never, AnalysisError> =>
|
||||
err(
|
||||
new AnalysisInputError(OPERATION, undefined, [
|
||||
{ path, reason: "invalid_format", message },
|
||||
]),
|
||||
);
|
||||
|
||||
const admitContext = (
|
||||
input: WebSourceLocationInput,
|
||||
): Result<null, AnalysisError> => {
|
||||
for (const [path, value] of [
|
||||
["manifest_path", input.manifest_path],
|
||||
["source_map.path", input.source_map.path],
|
||||
] as const)
|
||||
if (!isAbsolute(value))
|
||||
return invalid(
|
||||
path.split("."),
|
||||
"Expected an absolute filesystem path on this host.",
|
||||
);
|
||||
if (!URL.canParse(input.source_map.url))
|
||||
return invalid(
|
||||
["source_map", "url"],
|
||||
"Expected an absolute source-map URL context. Select its deployment context explicitly; no URL is fetched.",
|
||||
);
|
||||
return ok(null);
|
||||
};
|
||||
|
||||
const verifyPairing = (
|
||||
input: WebSourceLocationInput,
|
||||
data: z.output<typeof artifactsSchema>,
|
||||
): Result<number, AnalysisError> => {
|
||||
const map = data.sourceMap;
|
||||
if (
|
||||
map.file.path !== input.source_map.path ||
|
||||
map.url !== input.source_map.url ||
|
||||
Buffer.byteLength(map.text) !== map.file.bytes ||
|
||||
createHash("sha256").update(map.text).digest("hex") !== map.file.sha256 ||
|
||||
map.file.bytes > WEB_SOURCE_MAP_LIMITS.mapBytes
|
||||
)
|
||||
return invalidOutput(
|
||||
"Artifact port changed the selected source-map byte identity or URL context.",
|
||||
);
|
||||
const generatedOffset = webSourceOffset(
|
||||
data.source,
|
||||
input.generated_position,
|
||||
);
|
||||
if (generatedOffset === undefined)
|
||||
return invalid(
|
||||
["generated_position"],
|
||||
"Selected generated position is outside the retained script text (one-based lines; zero-based UTF-16 columns).",
|
||||
);
|
||||
return ok(generatedOffset);
|
||||
};
|
||||
|
||||
const verifyReport = (
|
||||
input: WebSourceLocationInput,
|
||||
sha256: string,
|
||||
value: unknown,
|
||||
): Result<WebSourceMapReport, AnalysisError> => {
|
||||
const report = webSourceMapReportSchema.safeParse(value);
|
||||
if (!report.success)
|
||||
return invalidOutput(
|
||||
"Codec port returned malformed source-map point evidence.",
|
||||
);
|
||||
if (
|
||||
report.data.source_map_sha256 !== sha256 ||
|
||||
report.data.url_context !== input.source_map.url ||
|
||||
report.data.lookup.requested.line !== input.generated_position.line ||
|
||||
report.data.lookup.requested.column !== input.generated_position.column
|
||||
)
|
||||
return invalidOutput(
|
||||
"Codec port changed the selected map, URL context or generated point.",
|
||||
);
|
||||
return ok(report.data);
|
||||
};
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
import { canonicalDigest } from "../domain/comparisonSemantics.js";
|
||||
import type { ProviderIdentity } from "./AnalysisProvider.js";
|
||||
import type { Evidence, EvidenceObservation } from "../domain/evidence.js";
|
||||
import { createEvidence } from "../domain/evidence.js";
|
||||
import { canonicalDigest } from "../../domain/comparisonSemantics.js";
|
||||
import type { ProviderIdentity } from "../AnalysisProvider.js";
|
||||
import type { Evidence, EvidenceObservation } from "../../domain/evidence.js";
|
||||
import { createEvidence } from "../../domain/evidence.js";
|
||||
import type {
|
||||
ElectronActiveObservationInput,
|
||||
ElectronActiveObservationResult,
|
||||
} from "../domain/electronActiveObservation.js";
|
||||
import { jsonValueSchema } from "../domain/jsonValue.js";
|
||||
} from "../../domain/electronActiveObservation.js";
|
||||
import { jsonValueSchema } from "../../domain/jsonValue.js";
|
||||
|
||||
type CanonicalElectronActiveObservationInput =
|
||||
ElectronActiveObservationInput & {
|
||||
|
|
@ -1,10 +1,13 @@
|
|||
import type { ExecutionOptions, ProviderIdentity } from "./AnalysisProvider.js";
|
||||
import type { AnalysisError } from "../domain/analysisErrorBase.js";
|
||||
import type {
|
||||
ExecutionOptions,
|
||||
ProviderIdentity,
|
||||
} from "../AnalysisProvider.js";
|
||||
import type { AnalysisError } from "../../domain/analysisErrorBase.js";
|
||||
import type {
|
||||
ElectronActiveObservationInput,
|
||||
ElectronActiveObservationResult,
|
||||
} from "../domain/electronActiveObservation.js";
|
||||
import type { Result } from "../domain/result.js";
|
||||
} from "../../domain/electronActiveObservation.js";
|
||||
import type { Result } from "../../domain/result.js";
|
||||
|
||||
/** Provider-neutral boundary for owned Electron runtime experiments. */
|
||||
export interface ElectronActiveObservationPort {
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
import { dirname } from "node:path";
|
||||
import { realpath } from "node:fs/promises";
|
||||
|
||||
import type { ExecutionOptions } from "./AnalysisProvider.js";
|
||||
import type { ExecutionOptions } from "../AnalysisProvider.js";
|
||||
import type { ElectronActiveObservationPort } from "./ElectronActiveObservationPort.js";
|
||||
import {
|
||||
AnalysisCapabilityUnavailableError,
|
||||
AnalysisInputError,
|
||||
} from "../domain/analysisErrorCore.js";
|
||||
import { type AnalysisError } from "../domain/analysisErrorBase.js";
|
||||
import type { Evidence } from "../domain/evidence.js";
|
||||
import type { ElectronActiveObservationInput } from "../domain/electronActiveObservation.js";
|
||||
import { err, type Result } from "../domain/result.js";
|
||||
} from "../../domain/analysisErrorCore.js";
|
||||
import { type AnalysisError } from "../../domain/analysisErrorBase.js";
|
||||
import type { Evidence } from "../../domain/evidence.js";
|
||||
import type { ElectronActiveObservationInput } from "../../domain/electronActiveObservation.js";
|
||||
import { err, type Result } from "../../domain/result.js";
|
||||
import { createElectronActiveEvidence } from "./ElectronActiveEvidence.js";
|
||||
|
||||
const OPERATION = "capture_electron_scenario" as const;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import { compareCodePoints } from "../domain/canonicalOrdering.js";
|
||||
import type { ElectronIpcFinding } from "../domain/electronStaticAnalysisTypes.js";
|
||||
import type { ElectronBoundarySummary } from "../domain/javascriptApplicationAnalysis.js";
|
||||
import { compareCodePoints } from "../../domain/canonicalOrdering.js";
|
||||
import type { ElectronIpcFinding } from "../../domain/electronStaticAnalysisTypes.js";
|
||||
import type { ElectronBoundarySummary } from "../../domain/javascriptApplicationAnalysis.js";
|
||||
import type { JavaScriptArtifactAnalysis } from "./JavaScriptArtifactAnalysisTypes.js";
|
||||
import type { JavaScriptArtifactFile } from "./JavaScriptArtifactFiles.js";
|
||||
import { resolveArtifactPathByContext } from "./JavaScriptArtifactPathResolution.js";
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import type { ApplicationNode } from "../domain/javascriptApplicationGraph.js";
|
||||
import { sha256Text } from "../domain/javascriptStaticAnalysisHelpers.js";
|
||||
import type { JavaScriptSourceRange } from "../domain/javascriptStaticAnalysisTypes.js";
|
||||
import type { ApplicationNode } from "../../domain/javascriptApplicationGraph.js";
|
||||
import { sha256Text } from "../../domain/javascriptStaticAnalysisHelpers.js";
|
||||
import type { JavaScriptSourceRange } from "../../domain/javascriptStaticAnalysisTypes.js";
|
||||
import type { JavaScriptArtifactFile } from "./JavaScriptArtifactFiles.js";
|
||||
import type {
|
||||
JavaScriptArtifactGraphContext,
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import type { ApplicationNode } from "../domain/javascriptApplicationGraph.js";
|
||||
import type { ElectronSenderValidationFinding } from "../domain/electronStaticAnalysisTypes.js";
|
||||
import type { ApplicationNode } from "../../domain/javascriptApplicationGraph.js";
|
||||
import type { ElectronSenderValidationFinding } from "../../domain/electronStaticAnalysisTypes.js";
|
||||
import type { JavaScriptArtifactFile } from "./JavaScriptArtifactFiles.js";
|
||||
import {
|
||||
artifactLocalIdentity,
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import type { ElectronNativeAddonBindingFinding } from "../domain/electronStaticAnalysisTypes.js";
|
||||
import type { ElectronNativeAddonBindingFinding } from "../../domain/electronStaticAnalysisTypes.js";
|
||||
import type { JavaScriptArtifactFile } from "./JavaScriptArtifactFiles.js";
|
||||
import {
|
||||
javascriptAnalysisCoverage,
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
import type { ApplicationNode } from "../domain/javascriptApplicationGraph.js";
|
||||
import type { ApplicationNode } from "../../domain/javascriptApplicationGraph.js";
|
||||
import type {
|
||||
ElectronBrowserWindowFinding,
|
||||
ElectronContextBridgeFinding,
|
||||
ElectronUtilityProcessFinding,
|
||||
} from "../domain/electronStaticAnalysisTypes.js";
|
||||
} from "../../domain/electronStaticAnalysisTypes.js";
|
||||
import type { JavaScriptArtifactFile } from "./JavaScriptArtifactFiles.js";
|
||||
import {
|
||||
artifactLocalIdentity,
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
import type { ProviderIdentity } from "./AnalysisProvider.js";
|
||||
import type { ProviderIdentity } from "../AnalysisProvider.js";
|
||||
import {
|
||||
createEvidence,
|
||||
type Evidence,
|
||||
type EvidenceObservation,
|
||||
} from "../domain/evidence.js";
|
||||
import { jsonValueSchema } from "../domain/jsonValue.js";
|
||||
} from "../../domain/evidence.js";
|
||||
import { jsonValueSchema } from "../../domain/jsonValue.js";
|
||||
import type {
|
||||
ElectronPageInspection,
|
||||
ElectronTargetList,
|
||||
InspectElectronPageInput,
|
||||
ListElectronTargetsInput,
|
||||
} from "../domain/electronObservation.js";
|
||||
} from "../../domain/electronObservation.js";
|
||||
|
||||
type ElectronOperation = "list_electron_targets" | "inspect_electron_page";
|
||||
|
||||
|
|
@ -1,12 +1,15 @@
|
|||
import type { ExecutionOptions, ProviderIdentity } from "./AnalysisProvider.js";
|
||||
import type { AnalysisError } from "../domain/analysisErrorBase.js";
|
||||
import type {
|
||||
ExecutionOptions,
|
||||
ProviderIdentity,
|
||||
} from "../AnalysisProvider.js";
|
||||
import type { AnalysisError } from "../../domain/analysisErrorBase.js";
|
||||
import type {
|
||||
ElectronPageInspection,
|
||||
ElectronTargetList,
|
||||
InspectElectronPageInput,
|
||||
ListElectronTargetsInput,
|
||||
} from "../domain/electronObservation.js";
|
||||
import type { Result } from "../domain/result.js";
|
||||
} from "../../domain/electronObservation.js";
|
||||
import type { Result } from "../../domain/result.js";
|
||||
|
||||
/** Provider-neutral boundary for root-confined Electron file-page observation. */
|
||||
export interface ElectronObservationPort {
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
import type { ExecutionOptions } from "./AnalysisProvider.js";
|
||||
import type { ExecutionOptions } from "../AnalysisProvider.js";
|
||||
import type { ElectronObservationPort } from "./ElectronObservationPort.js";
|
||||
import type { Evidence } from "../domain/evidence.js";
|
||||
import type { Evidence } from "../../domain/evidence.js";
|
||||
import type {
|
||||
InspectElectronPageInput,
|
||||
ListElectronTargetsInput,
|
||||
} from "../domain/electronObservation.js";
|
||||
import { AnalysisCapabilityUnavailableError } from "../domain/analysisErrorCore.js";
|
||||
import { type AnalysisError } from "../domain/analysisErrorBase.js";
|
||||
import { err, ok, type Result } from "../domain/result.js";
|
||||
} from "../../domain/electronObservation.js";
|
||||
import { AnalysisCapabilityUnavailableError } from "../../domain/analysisErrorCore.js";
|
||||
import { type AnalysisError } from "../../domain/analysisErrorBase.js";
|
||||
import { err, ok, type Result } from "../../domain/result.js";
|
||||
import { createElectronEvidence } from "./ElectronEvidence.js";
|
||||
|
||||
/** List local file pages exposed by the explicitly selected endpoint. */
|
||||
|
|
@ -5,11 +5,11 @@ import { Ajv2020 } from "ajv/dist/2020.js";
|
|||
import { expect, it } from "vitest";
|
||||
import { z } from "zod";
|
||||
|
||||
import { createTestTempDirectory } from "../../tests/fixtures/temporaryDirectory.js";
|
||||
import { javascriptApplicationAnalysisResultSchema } from "../domain/javascriptApplicationAnalysis.js";
|
||||
import { matchJavaScriptApplicationVersions } from "../domain/javascriptApplicationVersionKeys.js";
|
||||
import { findApplicationFeatureSeeds } from "../domain/javascriptFeatureSeed.js";
|
||||
import { traceApplicationFeatureInputSchema } from "../domain/javascriptFeatureTraceSchemas.js";
|
||||
import { createTestTempDirectory } from "../../../tests/fixtures/temporaryDirectory.js";
|
||||
import { javascriptApplicationAnalysisResultSchema } from "../../domain/javascriptApplicationAnalysis.js";
|
||||
import { matchJavaScriptApplicationVersions } from "../../domain/javascriptApplicationVersionKeys.js";
|
||||
import { findApplicationFeatureSeeds } from "../../domain/javascriptFeatureSeed.js";
|
||||
import { traceApplicationFeatureInputSchema } from "../../domain/javascriptFeatureTraceSchemas.js";
|
||||
import { analyzeJavaScriptApplication } from "./JavaScriptApplicationService.js";
|
||||
|
||||
const analyzeSource = async (
|
||||
|
|
@ -2,13 +2,13 @@ import {
|
|||
createEvidence,
|
||||
type Evidence,
|
||||
type EvidenceObservation,
|
||||
} from "../domain/evidence.js";
|
||||
} from "../../domain/evidence.js";
|
||||
import type {
|
||||
AnalyzeJavaScriptApplicationInput,
|
||||
JavaScriptApplicationAnalysisResult,
|
||||
} from "../domain/javascriptApplicationAnalysis.js";
|
||||
import { jsonValueSchema } from "../domain/jsonValue.js";
|
||||
import { JAVASCRIPT_APPLICATION_PROVIDER } from "./InvestigationProviders.js";
|
||||
} from "../../domain/javascriptApplicationAnalysis.js";
|
||||
import { jsonValueSchema } from "../../domain/jsonValue.js";
|
||||
import { JAVASCRIPT_APPLICATION_PROVIDER } from "../InvestigationProviders.js";
|
||||
|
||||
/** Create Evidence for one deterministic local JavaScript application graph. */
|
||||
export const createJavaScriptApplicationEvidence = (
|
||||
|
|
@ -2,17 +2,17 @@ import {
|
|||
JAVASCRIPT_APPLICATION_PROVIDER,
|
||||
JAVASCRIPT_RUNTIME_RECONCILIATION_PROVIDER,
|
||||
MANAGED_WORKFLOW_PROVIDER,
|
||||
} from "./InvestigationProviders.js";
|
||||
import { parseEvidence, type Evidence } from "../domain/evidence.js";
|
||||
} from "../InvestigationProviders.js";
|
||||
import { parseEvidence, type Evidence } from "../../domain/evidence.js";
|
||||
import {
|
||||
analyzeJavaScriptApplicationInputSchema,
|
||||
javascriptApplicationAnalysisResultSchema,
|
||||
type JavaScriptApplicationAnalysisResult,
|
||||
} from "../domain/javascriptApplicationAnalysis.js";
|
||||
import type { JavaScriptApplicationGraph } from "../domain/javascriptApplicationGraph.js";
|
||||
import type { JavaScriptSemanticGraph } from "../domain/javascriptSemanticGraph.js";
|
||||
import { javascriptRuntimeReconciliationResultSchema } from "../domain/javascriptRuntimeReconciliationSchemas.js";
|
||||
import { managedApplicationGraphResultSchema } from "../domain/managedApplicationGraph.js";
|
||||
} from "../../domain/javascriptApplicationAnalysis.js";
|
||||
import type { JavaScriptApplicationGraph } from "../../domain/javascriptApplicationGraph.js";
|
||||
import type { JavaScriptSemanticGraph } from "../../domain/javascriptSemanticGraph.js";
|
||||
import { javascriptRuntimeReconciliationResultSchema } from "../../domain/javascriptRuntimeReconciliationSchemas.js";
|
||||
import { managedApplicationGraphResultSchema } from "../../domain/managedApplicationGraph.js";
|
||||
|
||||
/** Supported immutable source for an application-level graph workflow. */
|
||||
export interface ApplicationGraphEvidenceSource {
|
||||
|
|
@ -4,8 +4,8 @@ import { join } from "node:path";
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { z } from "zod";
|
||||
|
||||
import { createTestTempDirectory } from "../../tests/fixtures/temporaryDirectory.js";
|
||||
import { projectAnalysisError } from "../domain/analysisErrorProjection.js";
|
||||
import { createTestTempDirectory } from "../../../tests/fixtures/temporaryDirectory.js";
|
||||
import { projectAnalysisError } from "../../domain/analysisErrorProjection.js";
|
||||
import { analyzeJavaScriptApplication } from "./JavaScriptApplicationService.js";
|
||||
|
||||
describe("JavaScript application failure diagnostics", () => {
|
||||
|
|
@ -1,24 +1,24 @@
|
|||
import { z } from "zod";
|
||||
|
||||
import { ArtifactReaderFailure } from "../artifacts/ArtifactReader.js";
|
||||
import { ArtifactReaderFailure } from "../../artifacts/ArtifactReader.js";
|
||||
import {
|
||||
analyzeJavaScriptApplicationInputSchema,
|
||||
javascriptApplicationAnalysisResultSchema,
|
||||
} from "../domain/javascriptApplicationAnalysis.js";
|
||||
} from "../../domain/javascriptApplicationAnalysis.js";
|
||||
import {
|
||||
AnalysisInputError,
|
||||
AnalysisOutputError,
|
||||
} from "../domain/analysisErrorCore.js";
|
||||
import { ArtifactOperationError } from "../domain/artifactOperationError.js";
|
||||
import { type AnalysisError } from "../domain/analysisErrorBase.js";
|
||||
import type { Evidence } from "../domain/evidence.js";
|
||||
import { projectInputIssues } from "../domain/inputIssueProjection.js";
|
||||
import { err, ok, type Result } from "../domain/result.js";
|
||||
import { ProviderAdapterError } from "../domain/providerAdapterError.js";
|
||||
import type { ExecutionOptions } from "./AnalysisProvider.js";
|
||||
} from "../../domain/analysisErrorCore.js";
|
||||
import { ArtifactOperationError } from "../../domain/artifactOperationError.js";
|
||||
import { type AnalysisError } from "../../domain/analysisErrorBase.js";
|
||||
import type { Evidence } from "../../domain/evidence.js";
|
||||
import { projectInputIssues } from "../../domain/inputIssueProjection.js";
|
||||
import { err, ok, type Result } from "../../domain/result.js";
|
||||
import { ProviderAdapterError } from "../../domain/providerAdapterError.js";
|
||||
import type { ExecutionOptions } from "../AnalysisProvider.js";
|
||||
import { createJavaScriptApplicationEvidence } from "./JavaScriptApplicationEvidence.js";
|
||||
import { reconstructJavaScriptArtifact } from "./JavaScriptArtifactReconstruction.js";
|
||||
import { JAVASCRIPT_APPLICATION_PROVIDER } from "./InvestigationProviders.js";
|
||||
import { JAVASCRIPT_APPLICATION_PROVIDER } from "../InvestigationProviders.js";
|
||||
|
||||
const OPERATION = "analyze_javascript_application" as const;
|
||||
|
||||
|
|
@ -3,8 +3,8 @@ import { join } from "node:path";
|
|||
|
||||
import { expect, it } from "vitest";
|
||||
|
||||
import { createTestTempDirectory } from "../../tests/fixtures/temporaryDirectory.js";
|
||||
import { javascriptApplicationAnalysisResultSchema } from "../domain/javascriptApplicationAnalysis.js";
|
||||
import { createTestTempDirectory } from "../../../tests/fixtures/temporaryDirectory.js";
|
||||
import { javascriptApplicationAnalysisResultSchema } from "../../domain/javascriptApplicationAnalysis.js";
|
||||
import { analyzeJavaScriptApplication } from "./JavaScriptApplicationService.js";
|
||||
|
||||
const graphIdentities = async (source: string) => {
|
||||
|
|
@ -2,14 +2,14 @@ import {
|
|||
createEvidence,
|
||||
type Evidence,
|
||||
type EvidenceObservation,
|
||||
} from "../domain/evidence.js";
|
||||
import type { ApplicationVersionComparisonResult } from "../domain/javascriptApplicationVersionComparisonSchemas.js";
|
||||
import type { JavaScriptExportShapeComparisonResult } from "../domain/javascriptExportShapeComparisonSchemas.js";
|
||||
import type { ApplicationFeatureTraceResult } from "../domain/javascriptFeatureTraceSchemas.js";
|
||||
import type { JavaScriptSemanticTraceResult } from "../domain/javascriptSemanticTraceSchemas.js";
|
||||
import { jsonValueSchema } from "../domain/jsonValue.js";
|
||||
import type { SourceToBundleComparisonResult } from "../domain/sourceToBundleComparisonSchemas.js";
|
||||
import { JAVASCRIPT_APPLICATION_WORKFLOW_PROVIDER } from "./InvestigationProviders.js";
|
||||
} from "../../domain/evidence.js";
|
||||
import type { ApplicationVersionComparisonResult } from "../../domain/javascriptApplicationVersionComparisonSchemas.js";
|
||||
import type { JavaScriptExportShapeComparisonResult } from "../../domain/javascriptExportShapeComparisonSchemas.js";
|
||||
import type { ApplicationFeatureTraceResult } from "../../domain/javascriptFeatureTraceSchemas.js";
|
||||
import type { JavaScriptSemanticTraceResult } from "../../domain/javascriptSemanticTraceSchemas.js";
|
||||
import { jsonValueSchema } from "../../domain/jsonValue.js";
|
||||
import type { SourceToBundleComparisonResult } from "../../domain/sourceToBundleComparisonSchemas.js";
|
||||
import { JAVASCRIPT_APPLICATION_WORKFLOW_PROVIDER } from "../InvestigationProviders.js";
|
||||
|
||||
/** Create derived Evidence for one bounded application-graph feature trace. */
|
||||
export const createApplicationFeatureTraceEvidence = (
|
||||
|
|
@ -3,19 +3,19 @@ import { z } from "zod";
|
|||
import {
|
||||
AnalysisInputError,
|
||||
AnalysisProtocolError,
|
||||
} from "../domain/analysisErrorCore.js";
|
||||
import { type AnalysisError } from "../domain/analysisErrorBase.js";
|
||||
import type { Evidence } from "../domain/evidence.js";
|
||||
import { projectInputIssues } from "../domain/inputIssueProjection.js";
|
||||
import { compareJavaScriptApplicationVersions } from "../domain/javascriptApplicationVersionComparison.js";
|
||||
import { compareApplicationVersionsInputSchema } from "../domain/javascriptApplicationVersionComparisonSchemas.js";
|
||||
import { compareJavaScriptExportShapes } from "../domain/javascriptExportShapeComparison.js";
|
||||
import { compareJavaScriptExportShapesInputSchema } from "../domain/javascriptExportShapeComparisonSchemas.js";
|
||||
import { traceApplicationFeature } from "../domain/javascriptFeatureTrace.js";
|
||||
import { traceApplicationFeatureInputSchema } from "../domain/javascriptFeatureTraceSchemas.js";
|
||||
import { err, ok, type Result } from "../domain/result.js";
|
||||
import { compareSourceToBundle } from "../domain/sourceToBundleComparison.js";
|
||||
import { compareSourceToBundleInputSchema } from "../domain/sourceToBundleComparisonSchemas.js";
|
||||
} from "../../domain/analysisErrorCore.js";
|
||||
import { type AnalysisError } from "../../domain/analysisErrorBase.js";
|
||||
import type { Evidence } from "../../domain/evidence.js";
|
||||
import { projectInputIssues } from "../../domain/inputIssueProjection.js";
|
||||
import { compareJavaScriptApplicationVersions } from "../../domain/javascriptApplicationVersionComparison.js";
|
||||
import { compareApplicationVersionsInputSchema } from "../../domain/javascriptApplicationVersionComparisonSchemas.js";
|
||||
import { compareJavaScriptExportShapes } from "../../domain/javascriptExportShapeComparison.js";
|
||||
import { compareJavaScriptExportShapesInputSchema } from "../../domain/javascriptExportShapeComparisonSchemas.js";
|
||||
import { traceApplicationFeature } from "../../domain/javascriptFeatureTrace.js";
|
||||
import { traceApplicationFeatureInputSchema } from "../../domain/javascriptFeatureTraceSchemas.js";
|
||||
import { err, ok, type Result } from "../../domain/result.js";
|
||||
import { compareSourceToBundle } from "../../domain/sourceToBundleComparison.js";
|
||||
import { compareSourceToBundleInputSchema } from "../../domain/sourceToBundleComparisonSchemas.js";
|
||||
import {
|
||||
parseApplicationGraphEvidence,
|
||||
parseNativeApplicationEvidence,
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
import { createHash } from "node:crypto";
|
||||
|
||||
import { analyzeParsedJavaScriptStaticSource } from "../domain/javascriptStaticAnalysis.js";
|
||||
import { analyzeParsedJavaScriptSemantics } from "../domain/javascriptSemanticAnalysis.js";
|
||||
import { parseJavaScriptSource } from "../domain/javascriptSourceParser.js";
|
||||
import { hasValidSourceMapContents } from "../domain/sourceMapContents.js";
|
||||
import { flattenSourceMapLeaves } from "../domain/sourceMapEnvelope.js";
|
||||
import { analyzeParsedJavaScriptStaticSource } from "../../domain/javascriptStaticAnalysis.js";
|
||||
import { analyzeParsedJavaScriptSemantics } from "../../domain/javascriptSemanticAnalysis.js";
|
||||
import { parseJavaScriptSource } from "../../domain/javascriptSourceParser.js";
|
||||
import { hasValidSourceMapContents } from "../../domain/sourceMapContents.js";
|
||||
import { flattenSourceMapLeaves } from "../../domain/sourceMapEnvelope.js";
|
||||
import type {
|
||||
JavaScriptSourceRange,
|
||||
JavaScriptSourcePoint,
|
||||
JavaScriptStaticAnalysis,
|
||||
} from "../domain/javascriptStaticAnalysisTypes.js";
|
||||
import { failedJavaScriptStaticAnalysis } from "../domain/javascriptStaticAnalysisHelpers.js";
|
||||
} from "../../domain/javascriptStaticAnalysisTypes.js";
|
||||
import { failedJavaScriptStaticAnalysis } from "../../domain/javascriptStaticAnalysisHelpers.js";
|
||||
import type {
|
||||
JavaScriptArtifactFile,
|
||||
JavaScriptArtifactFileSet,
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import type {
|
||||
JavaScriptSourceRange,
|
||||
JavaScriptStaticAnalysis,
|
||||
} from "../domain/javascriptStaticAnalysisTypes.js";
|
||||
import type { JavaScriptSemanticIr } from "../domain/javascriptSemanticIr.js";
|
||||
} from "../../domain/javascriptStaticAnalysisTypes.js";
|
||||
import type { JavaScriptSemanticIr } from "../../domain/javascriptSemanticIr.js";
|
||||
import type { JavaScriptArtifactFile } from "./JavaScriptArtifactFiles.js";
|
||||
|
||||
interface JavaScriptStructuredObservation {
|
||||
|
|
@ -2,20 +2,20 @@ import { createHash } from "node:crypto";
|
|||
import { isAbsolute } from "node:path";
|
||||
import type { Readable } from "node:stream";
|
||||
|
||||
import { compareCodePoints } from "../domain/canonicalOrdering.js";
|
||||
import { AsarArtifactReader } from "../artifacts/AsarArtifactReader.js";
|
||||
import { compareCodePoints } from "../../domain/canonicalOrdering.js";
|
||||
import { AsarArtifactReader } from "../../artifacts/AsarArtifactReader.js";
|
||||
import {
|
||||
ArtifactPathRegistry,
|
||||
normalizeArtifactPath,
|
||||
} from "../artifacts/ArtifactPaths.js";
|
||||
} from "../../artifacts/ArtifactPaths.js";
|
||||
import {
|
||||
ArtifactReaderFailure,
|
||||
type ArtifactEntry,
|
||||
type ArtifactReader,
|
||||
} from "../artifacts/ArtifactReader.js";
|
||||
import { streamChunkToBuffer } from "../artifacts/StreamBytes.js";
|
||||
import { hashReadable } from "./ArtifactInventory/hash.js";
|
||||
import type { ArtifactInventorySnapshot } from "./ArtifactInventory.js";
|
||||
} from "../../artifacts/ArtifactReader.js";
|
||||
import { streamChunkToBuffer } from "../../artifacts/StreamBytes.js";
|
||||
import { hashReadable } from "../ArtifactInventory/hash.js";
|
||||
import type { ArtifactInventorySnapshot } from "../ArtifactInventory.js";
|
||||
|
||||
/** Relevant file categories projected from the complete artifact inventory. */
|
||||
export type JavaScriptArtifactFileKind =
|
||||
|
|
@ -3,7 +3,7 @@ import {
|
|||
createJavaScriptApplicationNode,
|
||||
type ApplicationEdge,
|
||||
type ApplicationNode,
|
||||
} from "../domain/javascriptApplicationGraph.js";
|
||||
} from "../../domain/javascriptApplicationGraph.js";
|
||||
|
||||
/** Deduplicate graph entities while retaining distinct evidence observations. */
|
||||
export class JavaScriptArtifactGraphAccumulator {
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import type { ArtifactInventorySnapshot } from "./ArtifactInventory.js";
|
||||
import type { ArtifactInventorySnapshot } from "../ArtifactInventory.js";
|
||||
import {
|
||||
createJavaScriptApplicationGraph,
|
||||
type JavaScriptApplicationGraph,
|
||||
} from "../domain/javascriptApplicationGraph.js";
|
||||
} from "../../domain/javascriptApplicationGraph.js";
|
||||
import type { JavaScriptArtifactAnalysis } from "./JavaScriptArtifactAnalysisTypes.js";
|
||||
import type { JavaScriptArtifactFileSet } from "./JavaScriptArtifactFiles.js";
|
||||
import { JavaScriptArtifactGraphAccumulator } from "./JavaScriptArtifactGraphAccumulator.js";
|
||||
|
|
@ -19,7 +19,7 @@ import {
|
|||
import {
|
||||
completeApplicationCoverage,
|
||||
partialApplicationCoverage,
|
||||
} from "../domain/javascriptApplicationEvidenceSchemas.js";
|
||||
} from "../../domain/javascriptApplicationEvidenceSchemas.js";
|
||||
import {
|
||||
addJavaScriptArtifactContainers,
|
||||
addJavaScriptArtifactFiles,
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import type { ApplicationNode } from "../domain/javascriptApplicationGraph.js";
|
||||
import type { JavaScriptBundlerRegistration } from "../domain/javascriptStaticAnalysisTypes.js";
|
||||
import type { ApplicationNode } from "../../domain/javascriptApplicationGraph.js";
|
||||
import type { JavaScriptBundlerRegistration } from "../../domain/javascriptStaticAnalysisTypes.js";
|
||||
import type { JavaScriptArtifactFile } from "./JavaScriptArtifactFiles.js";
|
||||
import {
|
||||
addAstContainsEdge,
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
import type { ArtifactInventorySnapshot } from "./ArtifactInventory.js";
|
||||
import type { ArtifactInventorySnapshot } from "../ArtifactInventory.js";
|
||||
import {
|
||||
completeApplicationCoverage,
|
||||
partialApplicationCoverage,
|
||||
type ApplicationGraphEvidence,
|
||||
} from "../domain/javascriptApplicationEvidenceSchemas.js";
|
||||
import type { ApplicationNode } from "../domain/javascriptApplicationGraph.js";
|
||||
import type { JavaScriptSourceRange } from "../domain/javascriptStaticAnalysisTypes.js";
|
||||
} from "../../domain/javascriptApplicationEvidenceSchemas.js";
|
||||
import type { ApplicationNode } from "../../domain/javascriptApplicationGraph.js";
|
||||
import type { JavaScriptSourceRange } from "../../domain/javascriptStaticAnalysisTypes.js";
|
||||
import type { JavaScriptArtifactAnalysis } from "./JavaScriptArtifactAnalysisTypes.js";
|
||||
import type {
|
||||
JavaScriptArtifactFile,
|
||||
|
|
@ -6,7 +6,7 @@ import {
|
|||
type JavaScriptArtifactGraphContext,
|
||||
} from "./JavaScriptArtifactGraphContext.js";
|
||||
import { artifactObservationEvidence } from "./JavaScriptArtifactGraphEvidence.js";
|
||||
import { completeApplicationCoverage } from "../domain/javascriptApplicationEvidenceSchemas.js";
|
||||
import { completeApplicationCoverage } from "../../domain/javascriptApplicationEvidenceSchemas.js";
|
||||
import { resolveArtifactPathByContext } from "./JavaScriptArtifactPathResolution.js";
|
||||
|
||||
/** Project HTML renderer entrypoints and their local script assets. */
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import type { ApplicationGraphEvidence } from "../domain/javascriptApplicationEvidenceSchemas.js";
|
||||
import type { JavaScriptSourceRange } from "../domain/javascriptStaticAnalysisTypes.js";
|
||||
import type { ApplicationGraphEvidence } from "../../domain/javascriptApplicationEvidenceSchemas.js";
|
||||
import type { JavaScriptSourceRange } from "../../domain/javascriptStaticAnalysisTypes.js";
|
||||
|
||||
const EXTRACTOR = {
|
||||
name: "rea-javascript-artifact-reconstruction",
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import type { ApplicationNode } from "../domain/javascriptApplicationGraph.js";
|
||||
import type { JavaScriptStaticAnalysis } from "../domain/javascriptStaticAnalysisTypes.js";
|
||||
import type { ApplicationNode } from "../../domain/javascriptApplicationGraph.js";
|
||||
import type { JavaScriptStaticAnalysis } from "../../domain/javascriptStaticAnalysisTypes.js";
|
||||
import type { JavaScriptArtifactFile } from "./JavaScriptArtifactFiles.js";
|
||||
import {
|
||||
addStaticInferenceEdge,
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import type { ArtifactInventorySnapshot } from "./ArtifactInventory.js";
|
||||
import type { ApplicationNode } from "../domain/javascriptApplicationGraph.js";
|
||||
import { completeApplicationCoverage } from "../domain/javascriptApplicationEvidenceSchemas.js";
|
||||
import type { ArtifactInventorySnapshot } from "../ArtifactInventory.js";
|
||||
import type { ApplicationNode } from "../../domain/javascriptApplicationGraph.js";
|
||||
import { completeApplicationCoverage } from "../../domain/javascriptApplicationEvidenceSchemas.js";
|
||||
import type { JavaScriptArtifactAnalysis } from "./JavaScriptArtifactAnalysisTypes.js";
|
||||
import type {
|
||||
JavaScriptArtifactContainer,
|
||||
|
|
@ -6,8 +6,8 @@ import {
|
|||
} from "./JavaScriptArtifactPathResolution.js";
|
||||
import type { JavaScriptArtifactFile } from "./JavaScriptArtifactFiles.js";
|
||||
import { artifactLocalIdentity } from "./JavaScriptArtifactGraphContext.js";
|
||||
import { applicationNodeIdentitySchema } from "../domain/javascriptApplicationEvidenceSchemas.js";
|
||||
import { analyzeJavaScriptStaticSource } from "../domain/javascriptStaticAnalysis.js";
|
||||
import { applicationNodeIdentitySchema } from "../../domain/javascriptApplicationEvidenceSchemas.js";
|
||||
import { analyzeJavaScriptStaticSource } from "../../domain/javascriptStaticAnalysis.js";
|
||||
|
||||
describe("artifact-local graph identity", () => {
|
||||
it("preserves complete long namespace and key values", () => {
|
||||
|
|
@ -7,7 +7,7 @@ import {
|
|||
hasScheme,
|
||||
looksExternal,
|
||||
stripQueryAndFragment,
|
||||
} from "../domain/artifactPathSyntax.js";
|
||||
} from "../../domain/artifactPathSyntax.js";
|
||||
|
||||
type ArtifactPathResolutionContext =
|
||||
| "package-entrypoint"
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
import { lstat, realpath } from "node:fs/promises";
|
||||
|
||||
import { AsarArtifactReader } from "../artifacts/AsarArtifactReader.js";
|
||||
import { AsarArtifactReader } from "../../artifacts/AsarArtifactReader.js";
|
||||
import {
|
||||
ArtifactReaderFailure,
|
||||
type ArtifactReader,
|
||||
} from "../artifacts/ArtifactReader.js";
|
||||
import { DirectoryArtifactReader } from "../artifacts/DirectoryArtifactReader.js";
|
||||
import type { JavaScriptApplicationGraph } from "../domain/javascriptApplicationGraph.js";
|
||||
import type { JavaScriptSemanticGraph } from "../domain/javascriptSemanticGraph.js";
|
||||
import type { ElectronBoundarySummary } from "../domain/javascriptApplicationAnalysis.js";
|
||||
} from "../../artifacts/ArtifactReader.js";
|
||||
import { DirectoryArtifactReader } from "../../artifacts/DirectoryArtifactReader.js";
|
||||
import type { JavaScriptApplicationGraph } from "../../domain/javascriptApplicationGraph.js";
|
||||
import type { JavaScriptSemanticGraph } from "../../domain/javascriptSemanticGraph.js";
|
||||
import type { ElectronBoundarySummary } from "../../domain/javascriptApplicationAnalysis.js";
|
||||
import { analyzeJavaScriptArtifactFiles } from "./JavaScriptArtifactAnalysis.js";
|
||||
import { readJavaScriptArtifactFiles } from "./JavaScriptArtifactFiles.js";
|
||||
import { buildJavaScriptArtifactGraph } from "./JavaScriptArtifactGraphBuilder.js";
|
||||
|
|
@ -16,7 +16,7 @@ import {
|
|||
javascriptArtifactReconstructionInputSchema,
|
||||
type JavaScriptArtifactReconstructionInput,
|
||||
} from "./JavaScriptArtifactReconstructionInput.js";
|
||||
import { scanCanonicalArtifactInventory } from "./ArtifactInventory.js";
|
||||
import { scanCanonicalArtifactInventory } from "../ArtifactInventory.js";
|
||||
import { summarizeElectronBoundaries } from "./ElectronBoundaryAnalysis.js";
|
||||
import { buildJavaScriptSemanticGraph } from "./JavaScriptSemanticGraphBuilder.js";
|
||||
|
||||
|
|
@ -5,9 +5,9 @@ import { fileURLToPath, pathToFileURL } from "node:url";
|
|||
import { parseExpression } from "@babel/parser";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { createTestTempDirectory } from "../../tests/fixtures/temporaryDirectory.js";
|
||||
import { javascriptApplicationAnalysisResultSchema } from "../domain/javascriptApplicationAnalysis.js";
|
||||
import { staticPath } from "../domain/javascriptStaticAnalysisHelpers.js";
|
||||
import { createTestTempDirectory } from "../../../tests/fixtures/temporaryDirectory.js";
|
||||
import { javascriptApplicationAnalysisResultSchema } from "../../domain/javascriptApplicationAnalysis.js";
|
||||
import { staticPath } from "../../domain/javascriptStaticAnalysisHelpers.js";
|
||||
import { analyzeJavaScriptApplication } from "./JavaScriptApplicationService.js";
|
||||
|
||||
const urlCases = [
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { compareCodePoints } from "../domain/canonicalOrdering.js";
|
||||
import { compareCodePoints } from "../../domain/canonicalOrdering.js";
|
||||
import type { JavaScriptJsonModuleObservation } from "./JavaScriptArtifactAnalysisTypes.js";
|
||||
import type { JavaScriptArtifactFile } from "./JavaScriptArtifactFiles.js";
|
||||
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
import { posix } from "node:path";
|
||||
|
||||
import { compareCodePoints } from "../domain/canonicalOrdering.js";
|
||||
import type { ApplicationNode } from "../domain/javascriptApplicationGraph.js";
|
||||
import { compareCodePoints } from "../../domain/canonicalOrdering.js";
|
||||
import type { ApplicationNode } from "../../domain/javascriptApplicationGraph.js";
|
||||
import {
|
||||
completeApplicationCoverage,
|
||||
partialApplicationCoverage,
|
||||
} from "../domain/javascriptApplicationEvidenceSchemas.js";
|
||||
} from "../../domain/javascriptApplicationEvidenceSchemas.js";
|
||||
import type {
|
||||
JavaScriptModuleOrigin,
|
||||
JavaScriptSemanticIr,
|
||||
JavaScriptSemanticModuleLink,
|
||||
} from "../domain/javascriptSemanticIr.js";
|
||||
} from "../../domain/javascriptSemanticIr.js";
|
||||
import type { JavaScriptArtifactFile } from "./JavaScriptArtifactFiles.js";
|
||||
import {
|
||||
addAstContainsEdge,
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import type { AnalysisError } from "../domain/analysisErrorBase.js";
|
||||
import type { JavaScriptRecoveryInput } from "../domain/javascriptRecovery.js";
|
||||
import type { Result } from "../domain/result.js";
|
||||
import type { AnalysisError } from "../../domain/analysisErrorBase.js";
|
||||
import type { JavaScriptRecoveryInput } from "../../domain/javascriptRecovery.js";
|
||||
import type { Result } from "../../domain/result.js";
|
||||
import type {
|
||||
AnalysisExecution,
|
||||
ExecutionOptions,
|
||||
} from "./AnalysisProvider.js";
|
||||
} from "../AnalysisProvider.js";
|
||||
|
||||
/** Typed boundary for upstream source recovery without exposing its protocol. */
|
||||
export interface JavaScriptRecoveryPort {
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { AnalysisCapabilityUnavailableError } from "../domain/analysisErrorCore.js";
|
||||
import { err, ok } from "../domain/result.js";
|
||||
import { AnalysisCapabilityUnavailableError } from "../../domain/analysisErrorCore.js";
|
||||
import { err, ok } from "../../domain/result.js";
|
||||
import type {
|
||||
JavaScriptRecoveryInput,
|
||||
JavaScriptRecoveryResult,
|
||||
} from "../domain/javascriptRecovery.js";
|
||||
import { createAnalysisExecution } from "./AnalysisProvider.js";
|
||||
} from "../../domain/javascriptRecovery.js";
|
||||
import { createAnalysisExecution } from "../AnalysisProvider.js";
|
||||
import { JavaScriptRecoveryService } from "./JavaScriptRecoveryService.js";
|
||||
|
||||
const artifact = { path: "/tmp/bundle.js", sha256: "a".repeat(64), bytes: 20 };
|
||||
|
|
@ -4,17 +4,17 @@ import {
|
|||
AnalysisCancelledError,
|
||||
AnalysisInputError,
|
||||
AnalysisOutputError,
|
||||
} from "../domain/analysisErrorCore.js";
|
||||
import type { AnalysisError } from "../domain/analysisErrorBase.js";
|
||||
import { createEvidence, type Evidence } from "../domain/evidence.js";
|
||||
} from "../../domain/analysisErrorCore.js";
|
||||
import type { AnalysisError } from "../../domain/analysisErrorBase.js";
|
||||
import { createEvidence, type Evidence } from "../../domain/evidence.js";
|
||||
import {
|
||||
javascriptRecoveryInputSchema,
|
||||
javascriptRecoveryResultSchema,
|
||||
} from "../domain/javascriptRecovery.js";
|
||||
import { jsonObjectSchema } from "../domain/jsonValue.js";
|
||||
import { projectInputIssues } from "../domain/inputIssueProjection.js";
|
||||
import { err, ok, type Result } from "../domain/result.js";
|
||||
import type { ExecutionOptions } from "./AnalysisProvider.js";
|
||||
} from "../../domain/javascriptRecovery.js";
|
||||
import { jsonObjectSchema } from "../../domain/jsonValue.js";
|
||||
import { projectInputIssues } from "../../domain/inputIssueProjection.js";
|
||||
import { err, ok, type Result } from "../../domain/result.js";
|
||||
import type { ExecutionOptions } from "../AnalysisProvider.js";
|
||||
import type { JavaScriptRecoveryPort } from "./JavaScriptRecoveryPort.js";
|
||||
|
||||
const OPERATION = "recover_javascript_sources";
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { analyzeJavaScriptSemantics } from "../domain/javascriptSemanticAnalysis.js";
|
||||
import { completeApplicationCoverage } from "../domain/javascriptApplicationEvidenceSchemas.js";
|
||||
import { analyzeJavaScriptSemantics } from "../../domain/javascriptSemanticAnalysis.js";
|
||||
import { completeApplicationCoverage } from "../../domain/javascriptApplicationEvidenceSchemas.js";
|
||||
import { projectJavaScriptExportReturnShapes } from "./JavaScriptReturnShapeProjection.js";
|
||||
|
||||
const projectReturns = (body: string) => {
|
||||
|
|
@ -1,15 +1,15 @@
|
|||
import { jsonObjectSchema, jsonValueSchema } from "../domain/jsonValue.js";
|
||||
import { jsonObjectSchema, jsonValueSchema } from "../../domain/jsonValue.js";
|
||||
import {
|
||||
partialApplicationCoverage,
|
||||
truncatedApplicationCoverage,
|
||||
} from "../domain/javascriptApplicationEvidenceSchemas.js";
|
||||
} from "../../domain/javascriptApplicationEvidenceSchemas.js";
|
||||
import type {
|
||||
JavaScriptSemanticIr,
|
||||
JavaScriptSemanticCallable,
|
||||
JavaScriptSemanticModuleLink,
|
||||
} from "../domain/javascriptSemanticIr.js";
|
||||
import { flattenSemanticReturnValue } from "../domain/javascriptSemanticReturns.js";
|
||||
import type { JavaScriptSourceRange } from "../domain/javascriptStaticAnalysisTypes.js";
|
||||
} from "../../domain/javascriptSemanticIr.js";
|
||||
import { flattenSemanticReturnValue } from "../../domain/javascriptSemanticReturns.js";
|
||||
import type { JavaScriptSourceRange } from "../../domain/javascriptStaticAnalysisTypes.js";
|
||||
import type { JavaScriptArtifactGraphCoverage } from "./JavaScriptArtifactGraphContext.js";
|
||||
|
||||
export interface JavaScriptReturnShapeProjection {
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
import type { ProviderIdentity } from "./AnalysisProvider.js";
|
||||
import type { ProviderIdentity } from "../AnalysisProvider.js";
|
||||
import {
|
||||
createEvidence,
|
||||
type Evidence,
|
||||
type EvidenceObservation,
|
||||
} from "../domain/evidence.js";
|
||||
import { jsonValueSchema } from "../domain/jsonValue.js";
|
||||
} from "../../domain/evidence.js";
|
||||
import { jsonValueSchema } from "../../domain/jsonValue.js";
|
||||
import type {
|
||||
JavaScriptRuntimeObservation,
|
||||
JavaScriptRuntimeTargetList,
|
||||
ListJavaScriptRuntimeTargetsInput,
|
||||
ObserveJavaScriptRuntimeInput,
|
||||
} from "../domain/javascriptRuntimeObservation.js";
|
||||
} from "../../domain/javascriptRuntimeObservation.js";
|
||||
|
||||
type RuntimeObservationOperation =
|
||||
| "list_javascript_runtime_targets"
|
||||
|
|
@ -1,12 +1,15 @@
|
|||
import type { ExecutionOptions, ProviderIdentity } from "./AnalysisProvider.js";
|
||||
import type {
|
||||
ExecutionOptions,
|
||||
ProviderIdentity,
|
||||
} from "../AnalysisProvider.js";
|
||||
import type {
|
||||
JavaScriptRuntimeObservation,
|
||||
JavaScriptRuntimeTargetList,
|
||||
ListJavaScriptRuntimeTargetsInput,
|
||||
ObserveJavaScriptRuntimeInput,
|
||||
} from "../domain/javascriptRuntimeObservation.js";
|
||||
import type { AnalysisError } from "../domain/analysisErrorBase.js";
|
||||
import type { Result } from "../domain/result.js";
|
||||
} from "../../domain/javascriptRuntimeObservation.js";
|
||||
import type { AnalysisError } from "../../domain/analysisErrorBase.js";
|
||||
import type { Result } from "../../domain/result.js";
|
||||
|
||||
/** Provider-neutral boundary for passive Node/Electron Inspector observation. */
|
||||
export interface JavaScriptRuntimeObservationPort {
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
import type { ExecutionOptions } from "./AnalysisProvider.js";
|
||||
import type { ExecutionOptions } from "../AnalysisProvider.js";
|
||||
import type { JavaScriptRuntimeObservationPort } from "./JavaScriptRuntimeObservationPort.js";
|
||||
import { createJavaScriptRuntimeObservationEvidence } from "./JavaScriptRuntimeObservationEvidence.js";
|
||||
import type { Evidence } from "../domain/evidence.js";
|
||||
import { AnalysisCapabilityUnavailableError } from "../domain/analysisErrorCore.js";
|
||||
import { type AnalysisError } from "../domain/analysisErrorBase.js";
|
||||
import type { Evidence } from "../../domain/evidence.js";
|
||||
import { AnalysisCapabilityUnavailableError } from "../../domain/analysisErrorCore.js";
|
||||
import { type AnalysisError } from "../../domain/analysisErrorBase.js";
|
||||
import type {
|
||||
ListJavaScriptRuntimeTargetsInput,
|
||||
ObserveJavaScriptRuntimeInput,
|
||||
} from "../domain/javascriptRuntimeObservation.js";
|
||||
import { err, ok, type Result } from "../domain/result.js";
|
||||
} from "../../domain/javascriptRuntimeObservation.js";
|
||||
import { err, ok, type Result } from "../../domain/result.js";
|
||||
|
||||
/** List targets exposed by the explicitly selected loopback Inspector. */
|
||||
export const listJavaScriptRuntimeTargets = async (
|
||||
|
|
@ -2,13 +2,13 @@ import {
|
|||
createEvidence,
|
||||
type Evidence,
|
||||
type EvidenceObservation,
|
||||
} from "../domain/evidence.js";
|
||||
} from "../../domain/evidence.js";
|
||||
import type {
|
||||
JavaScriptRuntimeReconciliationResult,
|
||||
ReconcileJavaScriptRuntimeInput,
|
||||
} from "../domain/javascriptRuntimeReconciliationSchemas.js";
|
||||
import { jsonValueSchema } from "../domain/jsonValue.js";
|
||||
import { JAVASCRIPT_RUNTIME_RECONCILIATION_PROVIDER } from "./InvestigationProviders.js";
|
||||
} from "../../domain/javascriptRuntimeReconciliationSchemas.js";
|
||||
import { jsonValueSchema } from "../../domain/jsonValue.js";
|
||||
import { JAVASCRIPT_RUNTIME_RECONCILIATION_PROVIDER } from "../InvestigationProviders.js";
|
||||
|
||||
/** Create derived Evidence for one exact set of static/runtime inputs. */
|
||||
export const createJavaScriptRuntimeReconciliationEvidence = (
|
||||
|
|
@ -4,13 +4,13 @@ import { z } from "zod";
|
|||
import {
|
||||
AnalysisInputError,
|
||||
AnalysisProtocolError,
|
||||
} from "../domain/analysisErrorCore.js";
|
||||
import { type AnalysisError } from "../domain/analysisErrorBase.js";
|
||||
import type { Evidence } from "../domain/evidence.js";
|
||||
import { projectInputIssues } from "../domain/inputIssueProjection.js";
|
||||
import { reconcileJavaScriptRuntime } from "../domain/javascriptRuntimeReconciliation.js";
|
||||
import { reconcileJavaScriptRuntimeInputSchema } from "../domain/javascriptRuntimeReconciliationSchemas.js";
|
||||
import { err, ok, type Result } from "../domain/result.js";
|
||||
} from "../../domain/analysisErrorCore.js";
|
||||
import { type AnalysisError } from "../../domain/analysisErrorBase.js";
|
||||
import type { Evidence } from "../../domain/evidence.js";
|
||||
import { projectInputIssues } from "../../domain/inputIssueProjection.js";
|
||||
import { reconcileJavaScriptRuntime } from "../../domain/javascriptRuntimeReconciliation.js";
|
||||
import { reconcileJavaScriptRuntimeInputSchema } from "../../domain/javascriptRuntimeReconciliationSchemas.js";
|
||||
import { err, ok, type Result } from "../../domain/result.js";
|
||||
import { createJavaScriptRuntimeReconciliationEvidence } from "./JavaScriptRuntimeReconciliationEvidence.js";
|
||||
|
||||
const OPERATION = "reconcile_javascript_runtime" as const;
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
import { createJavaScriptSemanticGraphUnknown } from "../domain/javascriptSemanticGraph.js";
|
||||
import type { JavaScriptSemanticGraphNode } from "../domain/javascriptSemanticGraph.js";
|
||||
import { createJavaScriptSemanticGraphUnknown } from "../../domain/javascriptSemanticGraph.js";
|
||||
import type { JavaScriptSemanticGraphNode } from "../../domain/javascriptSemanticGraph.js";
|
||||
import type {
|
||||
JavaScriptSemanticEventOperation,
|
||||
JavaScriptSemanticTimerOperation,
|
||||
} from "../domain/javascriptSemanticIr.js";
|
||||
} from "../../domain/javascriptSemanticIr.js";
|
||||
import {
|
||||
addSemanticGraphNode,
|
||||
addSemanticGraphRelation,
|
||||
|
|
@ -3,8 +3,8 @@ import { expect, it } from "vitest";
|
|||
import { buildJavaScriptSemanticGraph } from "./JavaScriptSemanticGraphBuilder.js";
|
||||
import type { JavaScriptArtifactAnalysis } from "./JavaScriptArtifactAnalysisTypes.js";
|
||||
import type { JavaScriptArtifactFile } from "./JavaScriptArtifactFiles.js";
|
||||
import { queryJavaScriptSemanticGraph } from "../domain/javascriptSemanticQuery.js";
|
||||
import { analyzeJavaScriptSemantics } from "../domain/javascriptSemanticAnalysis.js";
|
||||
import { queryJavaScriptSemanticGraph } from "../../domain/javascriptSemanticQuery.js";
|
||||
import { analyzeJavaScriptSemantics } from "../../domain/javascriptSemanticAnalysis.js";
|
||||
|
||||
const SHA256 = "a".repeat(64);
|
||||
const GRAPH_ID = `jag_${"b".repeat(64)}`;
|
||||
|
|
@ -2,17 +2,17 @@ import {
|
|||
createJavaScriptSemanticGraph,
|
||||
type JavaScriptSemanticGraph,
|
||||
type JavaScriptSemanticGraphNode,
|
||||
} from "../domain/javascriptSemanticGraph.js";
|
||||
} from "../../domain/javascriptSemanticGraph.js";
|
||||
import {
|
||||
JAVASCRIPT_SEMANTIC_RELATION_FAMILIES,
|
||||
JAVASCRIPT_SEMANTIC_RELATION_FAMILY,
|
||||
} from "../domain/javascriptSemanticGraphSchemas.js";
|
||||
} from "../../domain/javascriptSemanticGraphSchemas.js";
|
||||
import type {
|
||||
JavaScriptSemanticCallArgument,
|
||||
JavaScriptSemanticIr,
|
||||
} from "../domain/javascriptSemanticIr.js";
|
||||
import { sourceRangesEqual as rangesEqual } from "../domain/javascriptStaticAnalysisHelpers.js";
|
||||
import type { JavaScriptApplicationGraph } from "../domain/javascriptApplicationGraph.js";
|
||||
} from "../../domain/javascriptSemanticIr.js";
|
||||
import { sourceRangesEqual as rangesEqual } from "../../domain/javascriptStaticAnalysisHelpers.js";
|
||||
import type { JavaScriptApplicationGraph } from "../../domain/javascriptApplicationGraph.js";
|
||||
import type { JavaScriptArtifactAnalysis } from "./JavaScriptArtifactAnalysisTypes.js";
|
||||
import type { JavaScriptArtifactFile } from "./JavaScriptArtifactFiles.js";
|
||||
import {
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
import { createJavaScriptSemanticGraphUnknown } from "../domain/javascriptSemanticGraph.js";
|
||||
import type { JavaScriptSemanticGraphNode } from "../domain/javascriptSemanticGraph.js";
|
||||
import { createJavaScriptSemanticGraphUnknown } from "../../domain/javascriptSemanticGraph.js";
|
||||
import type { JavaScriptSemanticGraphNode } from "../../domain/javascriptSemanticGraph.js";
|
||||
import type {
|
||||
JavaScriptSemanticChildProcessInteraction,
|
||||
JavaScriptSemanticChildProcessSpawn,
|
||||
} from "../domain/javascriptSemanticIr.js";
|
||||
} from "../../domain/javascriptSemanticIr.js";
|
||||
import {
|
||||
addSemanticGraphNode,
|
||||
addSemanticGraphRelation,
|
||||
|
|
@ -1,17 +1,17 @@
|
|||
import type { JavaScriptApplicationGraph } from "../domain/javascriptApplicationGraph.js";
|
||||
import type { JsonValue } from "../domain/jsonValue.js";
|
||||
import { javascriptDisplayText } from "../domain/javascriptAstValues.js";
|
||||
import type { JavaScriptApplicationGraph } from "../../domain/javascriptApplicationGraph.js";
|
||||
import type { JsonValue } from "../../domain/jsonValue.js";
|
||||
import { javascriptDisplayText } from "../../domain/javascriptAstValues.js";
|
||||
import {
|
||||
createJavaScriptSemanticGraphNode,
|
||||
createJavaScriptSemanticGraphRelation,
|
||||
type JavaScriptSemanticGraphNode,
|
||||
} from "../domain/javascriptSemanticGraph.js";
|
||||
import type { ApplicationGraphEvidence } from "../domain/javascriptApplicationEvidenceSchemas.js";
|
||||
} from "../../domain/javascriptSemanticGraph.js";
|
||||
import type { ApplicationGraphEvidence } from "../../domain/javascriptApplicationEvidenceSchemas.js";
|
||||
import type {
|
||||
JavaScriptSemanticGraphRelation,
|
||||
JavaScriptSemanticGraphUnknown,
|
||||
} from "../domain/javascriptSemanticGraphSchemas.js";
|
||||
import type { JavaScriptSourceRange } from "../domain/javascriptStaticAnalysisTypes.js";
|
||||
} from "../../domain/javascriptSemanticGraphSchemas.js";
|
||||
import type { JavaScriptSourceRange } from "../../domain/javascriptStaticAnalysisTypes.js";
|
||||
import type { JavaScriptArtifactFile } from "./JavaScriptArtifactFiles.js";
|
||||
import {
|
||||
inferredSemanticEvidence,
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import { createJavaScriptSemanticGraphUnknown } from "../domain/javascriptSemanticGraph.js";
|
||||
import type { JavaScriptSemanticGraphNode } from "../domain/javascriptSemanticGraph.js";
|
||||
import { createJavaScriptSemanticGraphUnknown } from "../../domain/javascriptSemanticGraph.js";
|
||||
import type { JavaScriptSemanticGraphNode } from "../../domain/javascriptSemanticGraph.js";
|
||||
import type {
|
||||
JavaScriptSemanticBoundaryOperation,
|
||||
JavaScriptSemanticConfigurationOperation,
|
||||
JavaScriptSemanticRequestOperation,
|
||||
} from "../domain/javascriptSemanticIr.js";
|
||||
} from "../../domain/javascriptSemanticIr.js";
|
||||
import {
|
||||
addSemanticGraphNode,
|
||||
addSemanticGraphRelation,
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import type { ApplicationGraphEvidence } from "../domain/javascriptApplicationEvidenceSchemas.js";
|
||||
import type { JavaScriptSemanticGraphNode } from "../domain/javascriptSemanticGraph.js";
|
||||
import type { JavaScriptSourceRange } from "../domain/javascriptStaticAnalysisTypes.js";
|
||||
import type { ApplicationGraphEvidence } from "../../domain/javascriptApplicationEvidenceSchemas.js";
|
||||
import type { JavaScriptSemanticGraphNode } from "../../domain/javascriptSemanticGraph.js";
|
||||
import type { JavaScriptSourceRange } from "../../domain/javascriptStaticAnalysisTypes.js";
|
||||
import type { JavaScriptArtifactFile } from "./JavaScriptArtifactFiles.js";
|
||||
|
||||
const INFERENCE_LIMITATION =
|
||||
|
|
@ -2,8 +2,8 @@ import {
|
|||
createJavaScriptSemanticFingerprint,
|
||||
type JavaScriptSemanticGraph,
|
||||
type JavaScriptSemanticGraphNode,
|
||||
} from "../domain/javascriptSemanticGraph.js";
|
||||
import type { JavaScriptSemanticIr } from "../domain/javascriptSemanticIr.js";
|
||||
} from "../../domain/javascriptSemanticGraph.js";
|
||||
import type { JavaScriptSemanticIr } from "../../domain/javascriptSemanticIr.js";
|
||||
import type { JavaScriptArtifactFile } from "./JavaScriptArtifactFiles.js";
|
||||
import { observedSemanticEvidence } from "./JavaScriptSemanticGraphEvidence.js";
|
||||
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import { createJavaScriptSemanticGraphUnknown } from "../domain/javascriptSemanticGraph.js";
|
||||
import type { JavaScriptSemanticGraphNode } from "../domain/javascriptSemanticGraph.js";
|
||||
import type { JavaScriptSemanticIr } from "../domain/javascriptSemanticIr.js";
|
||||
import { sourceRangesEqual } from "../domain/javascriptStaticAnalysisHelpers.js";
|
||||
import type { JavaScriptSourceRange } from "../domain/javascriptStaticAnalysisTypes.js";
|
||||
import { createJavaScriptSemanticGraphUnknown } from "../../domain/javascriptSemanticGraph.js";
|
||||
import type { JavaScriptSemanticGraphNode } from "../../domain/javascriptSemanticGraph.js";
|
||||
import type { JavaScriptSemanticIr } from "../../domain/javascriptSemanticIr.js";
|
||||
import { sourceRangesEqual } from "../../domain/javascriptStaticAnalysisHelpers.js";
|
||||
import type { JavaScriptSourceRange } from "../../domain/javascriptStaticAnalysisTypes.js";
|
||||
import type { JavaScriptArtifactFile } from "./JavaScriptArtifactFiles.js";
|
||||
import {
|
||||
addSemanticGraphNode,
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue