diff --git a/README.md b/README.md
index faaca5732..7468dd181 100644
--- a/README.md
+++ b/README.md
@@ -164,7 +164,7 @@ Additional tools and host support depend on the target:
| Target | What REA returns | Requirements and guide |
| ---------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
-| Native binaries | Pseudocode, assembly, strings, symbols, calls and references | Hopper, Ghidra or IDA; [native analysis](https://rea.tools/guides/native/) |
+| Native binaries | Pseudocode, assembly, strings, symbols, calls and references | Hopper, Ghidra or IDA; [native analysis](docs/native-investigation.md) |
| Offline ELF layout | Sections, segments, original symbols/relocations and static mitigation candidates | Caller-supplied pwntools on Linux x64; [binary diagnostics](docs/binary-diagnostics.md) |
| Go binaries | Embedded compiler version, modules, replacements and build settings | Built-in static ELF/PE/thin Mach-O inspection; no Go installation required |
| Rust binaries | Embedded cargo-auditable crate names, versions, sources and dependency edges | Built-in static ELF/PE/thin Mach-O inspection; [Rust binaries](docs/rust-binaries.md) |
@@ -172,8 +172,8 @@ Additional tools and host support depend on the target:
| EVM bytecode | Dispatch selectors, byte offsets, inferred arguments and mutability | Local raw/hex carrier on Linux x64; [offline EVM guide](docs/evm-bytecode.md) |
| SQLite databases | Tables, columns, indexes, views, triggers and selected ordinary-table rows | Local database/WAL snapshot; Node.js 24.x >=24.15 or 26+ with native SQLite limits |
| Recorded Linux crashes | Raw notes, every recorded thread's registers/signals and optional mapping candidates | Caller-supplied pwntools on Linux x64; optional GDB/pwndbg; [recorded crashes](docs/recorded-crashes.md) |
-| JavaScript / Electron | Modules, imports, source maps, routes, IPC and native add-on relationships | Node.js and npm; Linux: procps-compatible `ps`; [application analysis](https://rea.tools/guides/javascript/) |
-| Websites | Page structure, scripts, network observations and requested screenshots | A Chrome-family browser; [browser analysis](https://rea.tools/guides/browser/) |
+| JavaScript / Electron | Modules, imports, source maps, routes, IPC and native add-on relationships | Node.js and npm; Linux: procps-compatible `ps`; [application analysis](docs/javascript-application-workflows.md) |
+| Websites | Page structure, scripts, network observations and requested screenshots | A Chrome-family browser; [browser analysis](docs/browser-observation.md) |
| Saved network captures | Requests, responses, exposed payloads and source locations | HAR or Fiddler Everywhere SAZ; mitmdump on Linux for native mitmproxy; [capture guide](docs/web-network-captures.md) |
| .NET assemblies | Metadata, CIL instructions, declared native dependencies and build comparisons | None (static only); [managed-code guide](docs/managed-code-analysis.md) |
| Android APKs | Manifest declarations, classes, decompiled methods and references | Headless JADX and a full JDK on Linux/macOS/Windows x64; [Android guide](docs/android-analysis.md) |
diff --git a/docs/client-verification.md b/docs/client-verification.md
index 38d0bf399..575cc61d2 100644
--- a/docs/client-verification.md
+++ b/docs/client-verification.md
@@ -377,6 +377,11 @@ Such a stall leaves the initial page unloaded with empty or placeholder CDP URLs
it does not establish permission to capture that page. See
[the keyring diagnosis](https://github.com/morluto/rea/issues/1384#issuecomment-6093781686).
+On Windows, browser verifier lanes that launch an owned fixture require a
+standard, non-elevated caller token. They inspect the verifier caller before
+allocating fixture resources and refuse elevated or unobservable tokens; they do
+not change caller authority or claim to inspect the browser process token.
+
`verify:browser` also captures a source-owned noise canvas as a real PNG above
8 MiB through the CLI and stdio MCP, with complete byte/digest parity and real PNG
decoding. Its SDK client explicitly permits the larger inline JSON response;
diff --git a/docs/installation.md b/docs/installation.md
index 9b8543070..a833ee3d4 100644
--- a/docs/installation.md
+++ b/docs/installation.md
@@ -325,7 +325,8 @@ selected engine. See [provider selection](cli.md#choose-a-provider).
On Linux, REA's shared process supervisor requires a procps-compatible `ps`
on REA's `PATH` for ownership checks before launching a child. Ghidra, JADX,
firmware tools and static JavaScript/Electron analysis use these checks.
-Install `procps` or put another procps-compatible `ps` on `PATH` before
+Install your distribution's `procps` or `procps-ng` package, or put another
+procps-compatible `ps` on `PATH` before
running those workflows. A missing or incompatible command causes a refusal
before the supervised child starts.
diff --git a/docs/readme/README_ar.md b/docs/readme/README_ar.md
index 46283a4af..70f3016ca 100644
--- a/docs/readme/README_ar.md
+++ b/docs/readme/README_ar.md
@@ -137,13 +137,13 @@ npx rea-agents@latest setup
| الهدف | ما يعيده REA | المتطلبات والدليل |
| ------------------------------- | ---------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
-| الملفات الثنائية للشيفرة الأصلية | شيفرة شبه برمجية، وتعليمات تجميع، وسلاسل نصية، ورموز، واستدعاءات، ومراجع | Hopper أو Ghidra أو IDA؛ [تحليل الشيفرة الأصلية](https://rea.tools/ar/guides/native/) |
+| الملفات الثنائية للشيفرة الأصلية | شيفرة شبه برمجية، وتعليمات تجميع، وسلاسل نصية، ورموز، واستدعاءات، ومراجع | Hopper أو Ghidra أو IDA؛ [تحليل الشيفرة الأصلية](../native-investigation.md) |
| بنية ELF دون تشغيل | الأقسام والمقاطع والرموز ومعلومات إعادة التموضع الأصلية، وآليات الحماية المحتملة المستدلّ عليها بالفحص الثابت | pwntools يوفّره المستدعي على Linux x64؛ [تشخيص الملفات الثنائية](../binary-diagnostics.md) |
| شيفرة EVM البايتية | محددات التوجيه، وإزاحات البايتات، والمعاملات المستنتجة، وقابلية تغيير الحالة | مدخل محلي يحمل بايتات خامًا أو تمثيلًا سداسيًا عشريًا على Linux x64؛ [دليل EVM دون تشغيل](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| أعطال Linux المسجّلة | سجلات note الخام، ومسجّلات المعالج/الإشارات لكل خيط مسجّل، وترشيحات اختيارية لخرائط الذاكرة | pwntools يوفّره المستدعي على Linux x64؛ GDB/pwndbg اختياريان؛ [الأعطال المسجّلة](../recorded-crashes.md) |
-| JavaScript / Electron | الوحدات، وعمليات الاستيراد، وخرائط المصدر، والمسارات، وIPC، وعلاقات إضافات الشيفرة الأصلية | Node.js وnpm؛ [تحليل التطبيقات](https://rea.tools/ar/guides/javascript/) |
-| المواقع | بنية الصفحة، والسكربتات، وملاحظات الشبكة، ولقطات الشاشة المطلوبة | متصفح من عائلة Chrome؛ [تحليل المتصفح](https://rea.tools/ar/guides/browser/) |
+| JavaScript / Electron | الوحدات، وعمليات الاستيراد، وخرائط المصدر، والمسارات، وIPC، وعلاقات إضافات الشيفرة الأصلية | Node.js وnpm؛ [تحليل التطبيقات](../javascript-application-workflows.md) |
+| المواقع | بنية الصفحة، والسكربتات، وملاحظات الشبكة، ولقطات الشاشة المطلوبة | متصفح من عائلة Chrome؛ [تحليل المتصفح](../browser-observation.md) |
| تسجيلات الشبكة المحفوظة | الطلبات، والاستجابات، ومحتويات الحمولة المتاحة، ومواضعها في المصدر | HAR؛ وmitmdump على Linux لتسجيلات mitmproxy بصيغتها الأصلية؛ [دليل تسجيلات الشبكة](../web-network-captures.md) |
| التقاط الحزم | نقاط النهاية وDNS وTLS SNI وتوزيع البروتوكولات وطلبات HTTP | tshark وcapinfos يوفّرهما المُستدعي؛ [دليل pcap](../pcap-analysis.md) |
| تجميعات .NET | البيانات الوصفية، وتعليمات CIL، واعتماديات الشيفرة الأصلية المعلنة، ومقارنات البناء | فحص ثابت؛ [دليل الشيفرة المُدارة](../managed-code-analysis.md) |
diff --git a/docs/readme/README_de.md b/docs/readme/README_de.md
index 27ba4a83b..c05a9da76 100644
--- a/docs/readme/README_de.md
+++ b/docs/readme/README_de.md
@@ -137,13 +137,13 @@ REA benötigt Node.js 22.x (>=22.19), 24.x (>=24.11) oder 26+ sowie npm. Zusätz
| Ziel | Was REA zurückgibt | Voraussetzungen und Anleitung |
| ----------------------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
-| Native Binärdateien | Pseudocode, Assemblercode, Zeichenketten, Symbole, Aufrufe und Verweise | Hopper, Ghidra oder IDA; [native Analyse](https://rea.tools/de/guides/native/) |
+| Native Binärdateien | Pseudocode, Assemblercode, Zeichenketten, Symbole, Aufrufe und Verweise | Hopper, Ghidra oder IDA; [native Analyse](../native-investigation.md) |
| Offline-ELF-Struktur | Sektionen, Segmente, ursprüngliche Symbole/Relokationen und mögliche Schutzmaßnahmen aus statischer Analyse | Vom Aufrufer bereitgestelltes pwntools unter Linux x64; [Binärdiagnostik](../binary-diagnostics.md) |
| EVM-Bytecode | Dispatch-Selektoren, Byte-Offsets, abgeleitete Argumente und Veränderbarkeit des Zustands | Lokale Eingabe mit Rohbytes oder Hexdarstellung unter Linux x64; [Offline-EVM-Leitfaden](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| Aufgezeichnete Linux-Abstürze | Unverarbeitete Note-Einträge, Register/Signale aller aufgezeichneten Threads und optionale Zuordnungskandidaten | Vom Aufrufer bereitgestelltes pwntools unter Linux x64; optional GDB/pwndbg; [aufgezeichnete Abstürze](../recorded-crashes.md) |
-| JavaScript / Electron | Module, Imports, Source Maps, Routen, IPC und Beziehungen zu nativen Add-ons | Node.js und npm; [Anwendungsanalyse](https://rea.tools/de/guides/javascript/) |
-| Websites | Seitenstruktur, Skripte, Netzwerkbeobachtungen und angeforderte Screenshots | Ein Browser aus der Chrome-Familie; [Browseranalyse](https://rea.tools/de/guides/browser/) |
+| JavaScript / Electron | Module, Imports, Source Maps, Routen, IPC und Beziehungen zu nativen Add-ons | Node.js und npm; [Anwendungsanalyse](../javascript-application-workflows.md) |
+| Websites | Seitenstruktur, Skripte, Netzwerkbeobachtungen und angeforderte Screenshots | Ein Browser aus der Chrome-Familie; [Browseranalyse](../browser-observation.md) |
| Gespeicherte Netzwerkaufzeichnungen | Anfragen, Antworten, zugängliche Nutzdaten und Quellpositionen | HAR; mitmdump unter Linux für Aufzeichnungen im nativen mitmproxy-Format; [Leitfaden zu Netzwerkaufzeichnungen](../web-network-captures.md) |
| Paketerfassungen | Endpunkte, DNS, TLS SNI, Protokollverteilung und HTTP-Anfragen | Vom Aufrufer bereitgestellte tshark- und capinfos-Binaries; [pcap-Leitfaden](../pcap-analysis.md) |
| .NET-Assemblies | Metadaten, CIL-Anweisungen, deklarierte native Abhängigkeiten und Build-Vergleiche | Statische Untersuchung; [Leitfaden für verwalteten Code](../managed-code-analysis.md) |
diff --git a/docs/readme/README_el.md b/docs/readme/README_el.md
index 9fc5b2d0a..59b5fb6b7 100644
--- a/docs/readme/README_el.md
+++ b/docs/readme/README_el.md
@@ -141,7 +141,7 @@ npx rea-agents@latest setup
| Στόχος | Τι επιστρέφει το REA | Απαιτήσεις και οδηγός |
| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
-| Δυαδικά αρχεία με κώδικα μηχανής | Ψευδοκώδικα, κώδικα assembly, συμβολοσειρές, σύμβολα, κλήσεις και αναφορές | Hopper, Ghidra ή IDA· [ανάλυση κώδικα μηχανής](https://rea.tools/guides/native/) |
+| Δυαδικά αρχεία με κώδικα μηχανής | Ψευδοκώδικα, κώδικα assembly, συμβολοσειρές, σύμβολα, κλήσεις και αναφορές | Hopper, Ghidra ή IDA· [ανάλυση κώδικα μηχανής](../native-investigation.md) |
| Δομή ELF χωρίς εκτέλεση | Ενότητες, τμήματα, αρχικά σύμβολα/εγγραφές μετεγκατάστασης και ενδείξεις πιθανών μέτρων προστασίας από στατική ανάλυση | pwntools που παρέχει ο χρήστης σε Linux x64· [διαγνωστικά δυαδικών αρχείων](../binary-diagnostics.md) |
| Δυαδικά αρχεία Go | Ενσωματωμένη έκδοση μεταγλωττιστή, modules, αντικαταστάσεις και ρυθμίσεις μεταγλώττισης | Ενσωματωμένη στατική εξέταση ELF/PE/thin Mach-O· δεν απαιτείται εγκατάσταση του Go |
| Δυαδικά αρχεία Rust | Ενσωματωμένα ονόματα, εκδόσεις, πηγές και σχέσεις εξάρτησης των crates από το cargo-auditable | Ενσωματωμένη στατική εξέταση ELF/PE/thin Mach-O· [δυαδικά αρχεία Rust](../rust-binaries.md) |
@@ -149,8 +149,8 @@ npx rea-agents@latest setup
| Bytecode EVM | Selectors επιλογής συνάρτησης, μετατοπίσεις σε bytes, εκτιμώμενα ορίσματα και δυνατότητα μεταβολής της κατάστασης | Τοπική είσοδος σε ακατέργαστα bytes ή δεκαεξαδική μορφή σε Linux x64· [οδηγός EVM χωρίς εκτέλεση](../evm-bytecode.md) |
| Βάσεις δεδομένων SQLite | Πίνακες, στήλες, ευρετήρια, όψεις, triggers και επιλεγμένες γραμμές κανονικών πινάκων | Τοπικό στιγμιότυπο βάσης δεδομένων/WAL· Node.js 24.x >=24.15 ή 26+ με εγγενή όρια SQLite |
| Καταγεγραμμένες καταρρεύσεις στο Linux | Ακατέργαστες εγγραφές notes, καταχωρητές/σήματα κάθε καταγεγραμμένου νήματος και προαιρετικές πιθανές αντιστοιχίσεις μνήμης | pwntools που παρέχει ο χρήστης σε Linux x64· προαιρετικά GDB/pwndbg· [καταγεγραμμένες καταρρεύσεις](../recorded-crashes.md) |
-| JavaScript / Electron | Modules, εισαγωγές, source maps, διαδρομές, IPC και σχέσεις με πρόσθετα κώδικα μηχανής | Node.js και npm· [ανάλυση εφαρμογών](https://rea.tools/guides/javascript/) |
-| Ιστότοποι | Δομή σελίδων, scripts, παρατηρήσεις δικτύου και ζητούμενα στιγμιότυπα οθόνης | Πρόγραμμα περιήγησης της οικογένειας Chrome· [ανάλυση μέσω προγράμματος περιήγησης](https://rea.tools/guides/browser/) |
+| JavaScript / Electron | Modules, εισαγωγές, source maps, διαδρομές, IPC και σχέσεις με πρόσθετα κώδικα μηχανής | Node.js και npm· [ανάλυση εφαρμογών](../javascript-application-workflows.md) |
+| Ιστότοποι | Δομή σελίδων, scripts, παρατηρήσεις δικτύου και ζητούμενα στιγμιότυπα οθόνης | Πρόγραμμα περιήγησης της οικογένειας Chrome· [ανάλυση μέσω προγράμματος περιήγησης](../browser-observation.md) |
| Αποθηκευμένες καταγραφές δικτύου | Αιτήματα, αποκρίσεις, διαθέσιμα δεδομένα φορτίου και θέσεις στην πηγή | HAR ή SAZ του Fiddler Everywhere· mitmdump σε Linux για την εγγενή μορφή mitmproxy· [οδηγός καταγραφών](../web-network-captures.md) |
| Assemblies .NET | Μεταδεδομένα, εντολές CIL, δηλωμένες εξαρτήσεις από κώδικα μηχανής και συγκρίσεις builds | Καμία πρόσθετη απαίτηση (μόνο στατική ανάλυση)· [οδηγός διαχειριζόμενου κώδικα](../managed-code-analysis.md) |
| APK Android | Δηλώσεις manifest, κλάσεις, απομεταγλωττισμένες μέθοδοι και αναφορές | JADX χωρίς γραφικό περιβάλλον και πλήρες JDK σε Linux/macOS/Windows x64· [οδηγός Android](../android-analysis.md) |
diff --git a/docs/readme/README_es.md b/docs/readme/README_es.md
index c143d97a7..7a7294c64 100644
--- a/docs/readme/README_es.md
+++ b/docs/readme/README_es.md
@@ -137,13 +137,13 @@ REA requiere Node.js 22.x (>=22.19), 24.x (>=24.11) o 26+, además de npm. Las h
| Objetivo | Qué devuelve REA | Requisitos y guía |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
-| Binarios nativos | Pseudocódigo, ensamblador, cadenas, símbolos, llamadas y referencias | Hopper, Ghidra o IDA; [análisis nativo](https://rea.tools/es/guides/native/) |
+| Binarios nativos | Pseudocódigo, ensamblador, cadenas, símbolos, llamadas y referencias | Hopper, Ghidra o IDA; [análisis nativo](../native-investigation.md) |
| Estructura ELF sin ejecutar | Secciones, segmentos, símbolos/reubicaciones originales y posibles medidas de mitigación detectadas mediante análisis estático | pwntools proporcionado por quien llama, en Linux x64; [diagnóstico de binarios](../binary-diagnostics.md) |
| Bytecode EVM | Selectores de despacho, desplazamientos en bytes, argumentos inferidos y mutabilidad | Entrada local con bytes sin procesar o representación hexadecimal, en Linux x64; [guía de EVM sin ejecutar](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| Fallos de Linux registrados | Registros note sin procesar, registros/señales de cada hilo registrado y posibles correspondencias de memoria opcionales | pwntools proporcionado por quien llama, en Linux x64; GDB/pwndbg opcionales; [fallos registrados](../recorded-crashes.md) |
-| JavaScript / Electron | Módulos, importaciones, mapas de código fuente, rutas, IPC y relaciones con complementos nativos | Node.js y npm; [análisis de aplicaciones](https://rea.tools/es/guides/javascript/) |
-| Sitios web | Estructura de la página, scripts, observaciones de red y capturas de pantalla solicitadas | Un navegador de la familia Chrome; [análisis del navegador](https://rea.tools/es/guides/browser/) |
+| JavaScript / Electron | Módulos, importaciones, mapas de código fuente, rutas, IPC y relaciones con complementos nativos | Node.js y npm; [análisis de aplicaciones](../javascript-application-workflows.md) |
+| Sitios web | Estructura de la página, scripts, observaciones de red y capturas de pantalla solicitadas | Un navegador de la familia Chrome; [análisis del navegador](../browser-observation.md) |
| Capturas de red guardadas | Solicitudes, respuestas, contenido accesible de las cargas útiles y ubicaciones de origen | HAR; mitmdump en Linux para capturas en formato nativo de mitmproxy; [guía de capturas](../web-network-captures.md) |
| Capturas de paquetes | Endpoints, DNS, TLS SNI, distribución de protocolos y solicitudes HTTP | tshark y capinfos suministrados por el autor de la llamada; [guía pcap](../pcap-analysis.md) |
| Ensamblados .NET | Metadatos, instrucciones CIL, dependencias nativas declaradas y comparaciones de compilaciones | Inspección estática; [guía de código administrado](../managed-code-analysis.md) |
diff --git a/docs/readme/README_fa.md b/docs/readme/README_fa.md
index 219df1cbd..5ac57024e 100644
--- a/docs/readme/README_fa.md
+++ b/docs/readme/README_fa.md
@@ -129,13 +129,13 @@ REA به Node.js 22.x (>=22.19)، 24.x (>=24.11) یا 26+، بههمراه np
| هدف | خروجی REA | پیشنیازها و راهنما |
| ---------------------- | ----------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
-| باینریهای بومی | شبهکد، اسمبلی، رشتهها، نمادها، فراخوانیها و ارجاعات | Hopper، Ghidra یا IDA؛ [تحلیل بومی](https://rea.tools/fa/guides/native/) |
+| باینریهای بومی | شبهکد، اسمبلی، رشتهها، نمادها، فراخوانیها و ارجاعات | Hopper، Ghidra یا IDA؛ [تحلیل بومی](../native-investigation.md) |
| ساختار ELF آفلاین | بخشها، سگمنتها، نمادها و relocationهای اصلی و گزینههای احتمالی کاهش آسیبپذیری ایستا | pwntools تأمینشده توسط فراخواننده روی Linux x64؛ [تشخیص باینری](../binary-diagnostics.md) |
| بایتکد EVM | selectorهای dispatch، offsetهای بایتی، آرگومانهای استنباطشده و قابلیت تغییر وضعیت | دادهٔ خام/hex محلی روی Linux x64؛ [راهنمای EVM آفلاین](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| کرشهای ثبتشدهٔ لینوکس | یادداشتهای خام، رجیسترها/سیگنالهای تمام threadهای ثبتشده و گزینههای احتمالی نگاشت | pwntools تأمینشده توسط فراخواننده روی Linux x64؛ GDB/pwndbg اختیاری؛ [کرشهای ثبتشده](../recorded-crashes.md) |
-| JavaScript / Electron | ماژولها، importها، source mapها، مسیرها، IPC و ارتباط افزونههای بومی | Node.js و npm؛ [تحلیل برنامه](https://rea.tools/fa/guides/javascript/) |
-| وبسایتها | ساختار صفحه، اسکریپتها، مشاهدات شبکه و اسکرینشاتهای درخواستی | مرورگر مبتنی بر Chrome؛ [تحلیل مرورگر](https://rea.tools/fa/guides/browser/) |
+| JavaScript / Electron | ماژولها، importها، source mapها، مسیرها، IPC و ارتباط افزونههای بومی | Node.js و npm؛ [تحلیل برنامه](../javascript-application-workflows.md) |
+| وبسایتها | ساختار صفحه، اسکریپتها، مشاهدات شبکه و اسکرینشاتهای درخواستی | مرورگر مبتنی بر Chrome؛ [تحلیل مرورگر](../browser-observation.md) |
| دادههای ضبطشدهٔ شبکه | درخواستها، پاسخها، payloadهای آشکارشده و مکان آنها در منبع | HAR؛ ابزار mitmdump در لینوکس برای ضبطهای بومی mitmproxy؛ [راهنمای ضبط شبکه](../web-network-captures.md) |
| اسمبلیهای .NET | فراداده، دستورالعملهای CIL، وابستگیهای بومی اعلامشده و مقایسهٔ buildها | بررسی ایستا؛ [راهنمای کد مدیریتشده](../managed-code-analysis.md) |
| فایلهای APK اندروید | تعاریف Manifest، کلاسها، متدهای دیکامپایلشده و ارجاعات | JADX بدون رابط گرافیکی و JDK کامل در Linux/macOS/Windows x64؛ [راهنمای اندروید](../android-analysis.md) |
diff --git a/docs/readme/README_fr.md b/docs/readme/README_fr.md
index d8e2998c6..07747ca4a 100644
--- a/docs/readme/README_fr.md
+++ b/docs/readme/README_fr.md
@@ -140,14 +140,14 @@ REA nécessite Node.js 22.x (>=22.19), 24.x (>=24.11) ou 26+, ainsi que npm. Les
| Cible | Ce que REA renvoie | Prérequis et guide |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
-| Binaires natifs | Pseudo-code, assembleur, chaînes, symboles, appels et références | Hopper, Ghidra ou IDA ; [analyse native](https://rea.tools/fr/guides/native/) |
+| Binaires natifs | Pseudo-code, assembleur, chaînes, symboles, appels et références | Hopper, Ghidra ou IDA ; [analyse native](../native-investigation.md) |
| Structure ELF hors ligne | Sections, segments, symboles et relocations d'origine, et protections statiques candidates | pwntools fourni par l'utilisateur sous Linux x64 ; [diagnostics binaires](../binary-diagnostics.md) |
| Artefact WASM | Validation, sections, formes WAT exactes d'import/export et WAT décodé | WABT 1.0.42 fourni par l'utilisateur ; `inspect_wasm_artifact` |
| Bytecode EVM | Sélecteurs de dispatch, offsets en octets, arguments inférés et mutabilité | Fichier local brut ou hexadécimal sous Linux x64 ; [guide EVM hors ligne](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| Crashs Linux enregistrés | Notes brutes, registres et signaux de chaque thread enregistré, et correspondances de mappings facultatives | pwntools fourni par l'utilisateur sous Linux x64 ; GDB/pwndbg en option ; [crashs enregistrés](../recorded-crashes.md) |
-| JavaScript / Electron | Modules, imports, source maps, routes, IPC et relations avec les modules natifs | Node.js et npm ; [analyse d'applications](https://rea.tools/fr/guides/javascript/) |
-| Sites web | Structure des pages, scripts, observations réseau et captures d'écran demandées | Un navigateur de la famille Chrome ; [analyse du navigateur](https://rea.tools/fr/guides/browser/) |
+| JavaScript / Electron | Modules, imports, source maps, routes, IPC et relations avec les modules natifs | Node.js et npm ; [analyse d'applications](../javascript-application-workflows.md) |
+| Sites web | Structure des pages, scripts, observations réseau et captures d'écran demandées | Un navigateur de la famille Chrome ; [analyse du navigateur](../browser-observation.md) |
| Captures réseau enregistrées | Requêtes, réponses, payloads exposés et emplacements dans le code source | HAR ; mitmdump sous Linux pour les captures mitmproxy natives ; [guide des captures](../web-network-captures.md) |
| Captures de paquets | Points de terminaison, DNS, TLS SNI, distribution des protocoles et requêtes HTTP | tshark et capinfos fournis par l'appelant ; [guide pcap](../pcap-analysis.md) |
| Assemblys .NET | Métadonnées, instructions CIL, dépendances natives déclarées et comparaisons de builds | Inspection statique ; [guide du code managé](../managed-code-analysis.md) |
diff --git a/docs/readme/README_id.md b/docs/readme/README_id.md
index 4f0aff5bc..5bd1d268c 100644
--- a/docs/readme/README_id.md
+++ b/docs/readme/README_id.md
@@ -143,14 +143,14 @@ Alat tambahan dan dukungan sistem host bergantung pada target yang dianalisis:
| Target | Hasil yang diberikan REA | Persyaratan dan panduan |
| -------------------------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
-| Biner native | Pseudocode, assembly, string, simbol, pemanggilan, dan referensi | Hopper, Ghidra, atau IDA; [analisis native](https://rea.tools/id/guides/native/) |
+| Biner native | Pseudocode, assembly, string, simbol, pemanggilan, dan referensi | Hopper, Ghidra, atau IDA; [analisis native](../native-investigation.md) |
| Tata letak ELF offline | Bagian, segmen, simbol/relokasi asli, dan kandidat mitigasi statis | pwntools yang disediakan pemanggil pada Linux x64; [diagnostik biner](../binary-diagnostics.md) |
| Artefak WASM | Validasi, bagian, bentuk WAT import/ekspor yang tepat, dan WAT yang didekode | WABT 1.0.42 yang disediakan pemanggil; `inspect_wasm_artifact` |
| Bytecode EVM | Selector dispatch, offset byte, argumen yang disimpulkan, dan sifat mutabilitas | Pembawa data raw/hex lokal; [panduan EVM offline](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| Crash Linux yang direkam | Catatan mentah, register/sinyal setiap thread yang direkam, dan kandidat pemetaan opsional | pwntools yang disediakan pemanggil; GDB/pwndbg opsional; [crash yang direkam](../recorded-crashes.md) |
-| JavaScript / Electron | Modul, impor, source map, rute, IPC, dan hubungan add-on native | Node.js dan npm; [analisis aplikasi](https://rea.tools/id/guides/javascript/) |
-| Situs web | Struktur halaman, skrip, pengamatan jaringan, dan tangkapan layar yang diminta | Peramban berbasis Chrome; [analisis peramban](https://rea.tools/id/guides/browser/) |
+| JavaScript / Electron | Modul, impor, source map, rute, IPC, dan hubungan add-on native | Node.js dan npm; [analisis aplikasi](../javascript-application-workflows.md) |
+| Situs web | Struktur halaman, skrip, pengamatan jaringan, dan tangkapan layar yang diminta | Peramban berbasis Chrome; [analisis peramban](../browser-observation.md) |
| Rekaman jaringan tersimpan | Permintaan, respons, payload yang terekspos, dan lokasi sumber | HAR; mitmdump di Linux untuk rekaman native mitmproxy; [panduan rekaman](../web-network-captures.md) |
| Capturan paket | Endpoint, DNS, TLS SNI, distribusi protokol, dan permintaan HTTP | tshark dan capinfos buatan pemanggil; [panduan pcap](../pcap-analysis.md) |
| Assembly .NET | Metadata, instruksi CIL, dependensi native yang dideklarasikan, dan perbandingan build | Tidak ada (hanya analisis statis); [panduan kode terkelola](../managed-code-analysis.md) |
diff --git a/docs/readme/README_it.md b/docs/readme/README_it.md
index 2b9cf10ef..c3baa70b5 100644
--- a/docs/readme/README_it.md
+++ b/docs/readme/README_it.md
@@ -140,14 +140,14 @@ REA richiede Node.js 22.x (>=22.19), 24.x (>=24.11) o 26+, oltre a npm. Strument
| Obiettivo | Cosa restituisce REA | Requisiti e guida |
| ---------------------------- | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
-| Binari nativi | Pseudocodice, assembly, stringhe, simboli, chiamate e riferimenti | Hopper, Ghidra o IDA; [analisi nativa](https://rea.tools/it/guides/native/) |
+| Binari nativi | Pseudocodice, assembly, stringhe, simboli, chiamate e riferimenti | Hopper, Ghidra o IDA; [analisi nativa](../native-investigation.md) |
| Layout ELF offline | Sezioni, segmenti, simboli/relocazioni originali e candidati mitigazioni statiche | pwntools fornito dal chiamante su Linux x64; [diagnostica binaria](../binary-diagnostics.md) |
| Artefatto WASM | Convalida, sezioni, forme WAT di import/export esatte e WAT decodificato | WABT 1.0.42 fornito dal chiamante; `inspect_wasm_artifact` |
| Bytecode EVM | Selettori di dispatch, offset dei byte, argomenti inferiti e mutabilità | Carrier raw/hex locale; [guida EVM offline](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| Crash Linux registrati | Note grezze, registri/segnai di ogni thread registrato e candidati mapping opzionali | pwntools fornito dal chiamante; GDB/pwndbg opzionale; [crash registrati](../recorded-crashes.md) |
-| JavaScript / Electron | Moduli, import, source map, route, IPC e relazioni con add-on nativi | Node.js e npm; [analisi delle applicazioni](https://rea.tools/it/guides/javascript/) |
-| Siti web | Struttura della pagina, script, osservazioni di rete e screenshot richiesti | Un browser della famiglia Chrome; [analisi browser](https://rea.tools/it/guides/browser/) |
+| JavaScript / Electron | Moduli, import, source map, route, IPC e relazioni con add-on nativi | Node.js e npm; [analisi delle applicazioni](../javascript-application-workflows.md) |
+| Siti web | Struttura della pagina, script, osservazioni di rete e screenshot richiesti | Un browser della famiglia Chrome; [analisi browser](../browser-observation.md) |
| Acquisizioni di rete salvate | Richieste, risposte, payload esposti e posizioni sorgente | HAR; mitmdump su Linux per acquisizioni mitmproxy native; [guida alle acquisizioni](../web-network-captures.md) |
| Captured di pacchetti | Endpoint, DNS, TLS SNI, distribuzione dei protocolli e richieste HTTP | tshark e capinfos forniti dal chiamante; [guida pcap](../pcap-analysis.md) |
| Assembly .NET | Metadati, istruzioni CIL, dipendenze native dichiarate e confronti di build | Nessuno (solo statico); [guida managed-code](../managed-code-analysis.md) |
diff --git a/docs/readme/README_ja.md b/docs/readme/README_ja.md
index 7ba09b8cb..fda3a1169 100644
--- a/docs/readme/README_ja.md
+++ b/docs/readme/README_ja.md
@@ -137,13 +137,13 @@ REA には Node.js 22.x(>=22.19)、24.x(>=24.11)、または 26+ と npm
| 対象 | REA が返すもの | 要件とガイド |
| -------------------------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
-| ネイティブバイナリ | 疑似コード、アセンブリ、文字列、シンボル、呼び出し、参照 | Hopper、Ghidra、または IDA;[ネイティブ分析](https://rea.tools/ja/guides/native/) |
+| ネイティブバイナリ | 疑似コード、アセンブリ、文字列、シンボル、呼び出し、参照 | Hopper、Ghidra、または IDA;[ネイティブ分析](../native-investigation.md) |
| オフライン ELF レイアウト | セクション、セグメント、元のシンボル/再配置情報、静的解析によるセキュリティ対策の候補 | Linux x64 で利用者が用意する pwntools;[バイナリ診断](../binary-diagnostics.md) |
| EVM バイトコード | ディスパッチセレクター、バイトオフセット、推定された引数と状態変更の可否 | Linux x64 上のローカルの生バイト/16 進数の入力ファイル;[オフライン EVM ガイド](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| 記録済みの Linux クラッシュ | 生の note レコード、記録された全スレッドのレジスター/シグナル、任意のマッピング候補 | Linux x64 で利用者が用意する pwntools;GDB/pwndbg は任意;[記録済みクラッシュ](../recorded-crashes.md) |
-| JavaScript / Electron | モジュール、インポート、ソースマップ、ルート、IPC、ネイティブアドオンの関係 | Node.js と npm;[アプリケーション分析](https://rea.tools/ja/guides/javascript/) |
-| ウェブサイト | ページ構造、スクリプト、ネットワークの観測結果、依頼されたスクリーンショット | Chrome 系ブラウザー;[ブラウザー分析](https://rea.tools/ja/guides/browser/) |
+| JavaScript / Electron | モジュール、インポート、ソースマップ、ルート、IPC、ネイティブアドオンの関係 | Node.js と npm;[アプリケーション分析](../javascript-application-workflows.md) |
+| ウェブサイト | ページ構造、スクリプト、ネットワークの観測結果、依頼されたスクリーンショット | Chrome 系ブラウザー;[ブラウザー分析](../browser-observation.md) |
| 保存済みのネットワークキャプチャ | リクエスト、レスポンス、取得可能なペイロード、ソース内の位置 | HAR;mitmproxy ネイティブ形式のキャプチャには Linux 上の mitmdump;[キャプチャガイド](../web-network-captures.md) |
| パケットキャプチャ | エンドポイント、DNS、TLS SNI、プロトコル分布、HTTPリクエスト | 呼び出し側が用意した tshark と capinfos;[pcapガイド](../pcap-analysis.md) |
| .NET アセンブリ | メタデータ、CIL 命令、宣言されたネイティブ依存関係、ビルドの比較 | 静的な検査;[マネージドコードのガイド](../managed-code-analysis.md) |
diff --git a/docs/readme/README_ko.md b/docs/readme/README_ko.md
index 1a89ae96d..d5ca2c8d9 100644
--- a/docs/readme/README_ko.md
+++ b/docs/readme/README_ko.md
@@ -139,7 +139,7 @@ REA에는 Node.js 22.x(>=22.19), 24.x(>=24.11) 또는 26+와 npm이 필요합니
| 대상 | REA가 반환하는 내용 | 요구 사항 및 가이드 |
| --------------------- | ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
-| 네이티브 바이너리 | 의사 코드, 어셈블리, 문자열, 심볼, 호출, 참조 | Hopper, Ghidra 또는 IDA; [네이티브 분석](https://rea.tools/ko/guides/native/) |
+| 네이티브 바이너리 | 의사 코드, 어셈블리, 문자열, 심볼, 호출, 참조 | Hopper, Ghidra 또는 IDA; [네이티브 분석](../native-investigation.md) |
| 오프라인 ELF 레이아웃 | 섹션, 세그먼트, 원본 심볼/재배치 정보, 정적 분석으로 얻은 보안 완화 기법 후보 | Linux x64에서 호출자가 제공하는 pwntools; [바이너리 진단](../binary-diagnostics.md) |
| Go 바이너리 | 내장된 컴파일러 버전, 모듈, `replace` 지시어, 빌드 설정 | REA 내장 ELF/PE/thin Mach-O 정적 검사; Go 설치 불필요 |
| Rust 바이너리 | cargo-auditable이 내장한 크레이트 이름, 버전, 소스, 의존성 관계 | REA 내장 ELF/PE/thin Mach-O 정적 검사; [Rust 바이너리](../rust-binaries.md) |
@@ -147,8 +147,8 @@ REA에는 Node.js 22.x(>=22.19), 24.x(>=24.11) 또는 26+와 npm이 필요합니
| EVM 바이트코드 | 디스패치 선택자, 바이트 오프셋, 추론한 인자와 상태 변경 가능 여부 | Linux x64의 로컬 원시 바이트/16진수 입력 파일; [오프라인 EVM 가이드](../evm-bytecode.md) |
| SQLite 데이터베이스 | 테이블, 열, 인덱스, 뷰, 트리거, 선택한 일반 테이블의 행 | 로컬 데이터베이스/WAL 스냅샷; Node.js 24.15 이상의 24.x 또는 26 이상(네이티브 SQLite 한도 적용) |
| 기록된 Linux 크래시 | 원시 note 레코드, 기록된 모든 스레드의 레지스터/시그널, 선택적 매핑 후보 | Linux x64에서 호출자가 제공하는 pwntools; GDB/pwndbg는 선택 사항; [기록된 크래시](../recorded-crashes.md) |
-| JavaScript / Electron | 모듈, 임포트, 소스 맵, 라우트, IPC, 네이티브 애드온 관계 | Node.js와 npm; [애플리케이션 분석](https://rea.tools/ko/guides/javascript/) |
-| 웹사이트 | 페이지 구조, 스크립트, 네트워크 관찰 결과, 요청한 스크린샷 | Chrome 계열 브라우저; [브라우저 분석](https://rea.tools/ko/guides/browser/) |
+| JavaScript / Electron | 모듈, 임포트, 소스 맵, 라우트, IPC, 네이티브 애드온 관계 | Node.js와 npm; [애플리케이션 분석](../javascript-application-workflows.md) |
+| 웹사이트 | 페이지 구조, 스크립트, 네트워크 관찰 결과, 요청한 스크린샷 | Chrome 계열 브라우저; [브라우저 분석](../browser-observation.md) |
| 저장된 네트워크 캡처 | 요청, 응답, 접근 가능한 페이로드, 소스 위치 | HAR 또는 Fiddler Everywhere SAZ; mitmproxy 네이티브 캡처에는 Linux의 mitmdump; [캡처 가이드](../web-network-captures.md) |
| .NET 어셈블리 | 메타데이터, CIL 명령, 선언된 네이티브 의존성, 빌드 비교 | 별도 도구 불필요(정적 검사만); [관리 코드 가이드](../managed-code-analysis.md) |
| Android APK | 매니페스트 선언, 클래스, 디컴파일된 메서드, 참조 | Linux/macOS/Windows x64의 헤드리스 JADX와 전체 JDK; [Android 가이드](../android-analysis.md) |
diff --git a/docs/readme/README_pl.md b/docs/readme/README_pl.md
index 8482a886e..be6eed89c 100644
--- a/docs/readme/README_pl.md
+++ b/docs/readme/README_pl.md
@@ -137,13 +137,13 @@ REA wymaga Node.js 22.x (>=22.19), 24.x (>=24.11) lub 26+ oraz npm. Dodatkowe na
| Cel | Co zwraca REA | Wymagania i przewodnik |
| --------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
-| Natywne pliki binarne | Pseudokod, kod asemblera, ciągi znaków, symbole, wywołania i odwołania | Hopper, Ghidra lub IDA; [analiza kodu natywnego](https://rea.tools/pl/guides/native/) |
+| Natywne pliki binarne | Pseudokod, kod asemblera, ciągi znaków, symbole, wywołania i odwołania | Hopper, Ghidra lub IDA; [analiza kodu natywnego](../native-investigation.md) |
| Układ pliku ELF w trybie offline | Sekcje, segmenty, oryginalne symbole/relokacje i potencjalne mechanizmy zabezpieczeń wskazane przez analizę statyczną | pwntools dostarczone przez użytkownika w systemie Linux x64; [diagnostyka plików binarnych](../binary-diagnostics.md) |
| Kod bajtowy EVM | Selektory wywołań, przesunięcia bajtowe, wywnioskowane argumenty i mutowalność | Lokalny plik z surowymi bajtami lub zapisem szesnastkowym w systemie Linux x64; [przewodnik EVM offline](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| Zarejestrowane awarie systemu Linux | Surowe rekordy note, rejestry/sygnały każdego zarejestrowanego wątku i opcjonalni kandydaci na mapowania | pwntools dostarczone przez użytkownika w systemie Linux x64; opcjonalnie GDB/pwndbg; [zarejestrowane awarie](../recorded-crashes.md) |
-| JavaScript / Electron | Moduły, importy, mapy źródeł, trasy, IPC i powiązania z natywnymi dodatkami | Node.js i npm; [analiza aplikacji](https://rea.tools/pl/guides/javascript/) |
-| Strony internetowe | Struktura strony, skrypty, obserwacje sieciowe i zamówione zrzuty ekranu | Przeglądarka z rodziny Chrome; [analiza w przeglądarce](https://rea.tools/pl/guides/browser/) |
+| JavaScript / Electron | Moduły, importy, mapy źródeł, trasy, IPC i powiązania z natywnymi dodatkami | Node.js i npm; [analiza aplikacji](../javascript-application-workflows.md) |
+| Strony internetowe | Struktura strony, skrypty, obserwacje sieciowe i zamówione zrzuty ekranu | Przeglądarka z rodziny Chrome; [analiza w przeglądarce](../browser-observation.md) |
| Zapisane przechwycenia ruchu sieciowego | Żądania, odpowiedzi, dostępne dane przesyłane i lokalizacje źródłowe | HAR; mitmdump w systemie Linux dla natywnych przechwyceń mitmproxy; [przewodnik przechwytywania](../web-network-captures.md) |
| Przechwytywanie pakietów | Punkty końcowe, DNS, TLS SNI, dystrybucja protokołów i żądania HTTP | Dostarczone przez wywołującego tshark i capinfos; [przewodnik pcap](../pcap-analysis.md) |
| Zestawy .NET | Metadane, instrukcje CIL, zadeklarowane zależności natywne i porównania kompilacji | Analiza statyczna; [przewodnik kodu zarządzanego](../managed-code-analysis.md) |
diff --git a/docs/readme/README_pt-BR.md b/docs/readme/README_pt-BR.md
index a3bcb68dd..86ae8d161 100644
--- a/docs/readme/README_pt-BR.md
+++ b/docs/readme/README_pt-BR.md
@@ -137,13 +137,13 @@ O REA requer Node.js 22.x (>=22.19), 24.x (>=24.11) ou 26+, além do npm. As fer
| Alvo | O que o REA retorna | Requisitos e guia |
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
-| Binários nativos | Pseudocódigo, assembly, strings, símbolos, chamadas e referências | Hopper, Ghidra ou IDA; [análise nativa](https://rea.tools/pt-BR/guides/native/) |
+| Binários nativos | Pseudocódigo, assembly, strings, símbolos, chamadas e referências | Hopper, Ghidra ou IDA; [análise nativa](../native-investigation.md) |
| Estrutura ELF sem execução | Seções, segmentos, símbolos/relocações originais e possíveis mecanismos de mitigação identificados por análise estática | pwntools fornecido pelo chamador no Linux x64; [diagnóstico de binários](../binary-diagnostics.md) |
| Bytecode EVM | Seletores de despacho, offsets de bytes, argumentos inferidos e mutabilidade | Entrada local com bytes brutos ou representação hexadecimal no Linux x64; [guia de EVM sem execução](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| Falhas do Linux registradas | Registros note brutos, registradores/sinais de cada thread registrada e candidatos opcionais a mapeamentos | pwntools fornecido pelo chamador no Linux x64; GDB/pwndbg opcionais; [falhas registradas](../recorded-crashes.md) |
-| JavaScript / Electron | Módulos, importações, source maps, rotas, IPC e relações com complementos nativos | Node.js e npm; [análise de aplicativos](https://rea.tools/pt-BR/guides/javascript/) |
-| Sites | Estrutura da página, scripts, observações de rede e capturas de tela solicitadas | Um navegador da família Chrome; [análise do navegador](https://rea.tools/pt-BR/guides/browser/) |
+| JavaScript / Electron | Módulos, importações, source maps, rotas, IPC e relações com complementos nativos | Node.js e npm; [análise de aplicativos](../javascript-application-workflows.md) |
+| Sites | Estrutura da página, scripts, observações de rede e capturas de tela solicitadas | Um navegador da família Chrome; [análise do navegador](../browser-observation.md) |
| Capturas de rede salvas | Requisições, respostas, payloads acessíveis e localizações de origem | HAR; mitmdump no Linux para capturas no formato nativo do mitmproxy; [guia de capturas](../web-network-captures.md) |
| Capturas de pacotes | Endpoints, DNS, TLS SNI, distribuição de protocolos e requisições HTTP | tshark e capinfos fornecidos pelo chamador; [guia pcap](../pcap-analysis.md) |
| Assemblies .NET | Metadados, instruções CIL, dependências nativas declaradas e comparações de builds | Inspeção estática; [guia de código gerenciado](../managed-code-analysis.md) |
diff --git a/docs/readme/README_ru.md b/docs/readme/README_ru.md
index ad280b553..f5f27c28b 100644
--- a/docs/readme/README_ru.md
+++ b/docs/readme/README_ru.md
@@ -137,13 +137,13 @@ REA требует Node.js 22.x (>=22.19), 24.x (>=24.11) или 26+, а так
| Цель | Что возвращает REA | Требования и руководство |
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
-| Нативные бинарные файлы | Псевдокод, ассемблер, строки, символы, вызовы и ссылки | Hopper, Ghidra или IDA; [нативный анализ](https://rea.tools/ru/guides/native/) |
+| Нативные бинарные файлы | Псевдокод, ассемблер, строки, символы, вызовы и ссылки | Hopper, Ghidra или IDA; [нативный анализ](../native-investigation.md) |
| Структура ELF без запуска | Секции, сегменты, исходные символы/релокации и возможные механизмы защиты по данным статического анализа | pwntools, предоставленный вызывающей стороной, в Linux x64; [диагностика бинарных файлов](../binary-diagnostics.md) |
| Байт-код EVM | Селекторы диспетчеризации, смещения байтов, предполагаемые аргументы и изменяемость состояния | Локальные необработанные байты или шестнадцатеричное представление в Linux x64; [руководство по EVM без запуска](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| Записанные сбои Linux | Необработанные записи note, регистры/сигналы каждого записанного потока и необязательные кандидаты сопоставления с памятью | pwntools, предоставленный вызывающей стороной, в Linux x64; необязательные GDB/pwndbg; [записанные сбои](../recorded-crashes.md) |
-| JavaScript / Electron | Модули, импорты, карты исходного кода, маршруты, IPC и связи с нативными дополнениями | Node.js и npm; [анализ приложений](https://rea.tools/ru/guides/javascript/) |
-| Сайты | Структура страницы, скрипты, наблюдения за сетью и запрошенные снимки экрана | Браузер семейства Chrome; [анализ браузера](https://rea.tools/ru/guides/browser/) |
+| JavaScript / Electron | Модули, импорты, карты исходного кода, маршруты, IPC и связи с нативными дополнениями | Node.js и npm; [анализ приложений](../javascript-application-workflows.md) |
+| Сайты | Структура страницы, скрипты, наблюдения за сетью и запрошенные снимки экрана | Браузер семейства Chrome; [анализ браузера](../browser-observation.md) |
| Сохранённые сетевые захваты | Запросы, ответы, доступные полезные данные и позиции в источнике | HAR; mitmdump в Linux для захватов в собственном формате mitmproxy; [руководство по сетевым захватам](../web-network-captures.md) |
| Сборки .NET | Метаданные, инструкции CIL, объявленные нативные зависимости и сравнения сборок | Статическое исследование; [руководство по управляемому коду](../managed-code-analysis.md) |
| Android APK | Объявления манифеста, классы, декомпилированные методы и ссылки | JADX без графического интерфейса и полный JDK в Linux/macOS/Windows x64; [руководство по Android](../android-analysis.md) |
diff --git a/docs/readme/README_th.md b/docs/readme/README_th.md
index bee9939c8..cab3b0136 100644
--- a/docs/readme/README_th.md
+++ b/docs/readme/README_th.md
@@ -137,13 +137,13 @@ REA ต้องใช้ Node.js 22.x (>=22.19), 24.x (>=24.11) หรือ 26
| เป้าหมาย | สิ่งที่ REA ส่งกลับ | ข้อกำหนดและคู่มือ |
| ---------------------------- | ------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
-| ไบนารีเนทีฟ | โค้ดเทียม แอสเซมบลี สตริง สัญลักษณ์ การเรียก และการอ้างอิง | Hopper, Ghidra หรือ IDA; [การวิเคราะห์เนทีฟ](https://rea.tools/th/guides/native/) |
+| ไบนารีเนทีฟ | โค้ดเทียม แอสเซมบลี สตริง สัญลักษณ์ การเรียก และการอ้างอิง | Hopper, Ghidra หรือ IDA; [การวิเคราะห์เนทีฟ](../native-investigation.md) |
| โครงสร้าง ELF แบบออฟไลน์ | เซกชัน เซกเมนต์ สัญลักษณ์/รีโลเคชันต้นฉบับ และตัวเลือกกลไกป้องกันที่พบจากการวิเคราะห์แบบสถิต | pwntools ที่ผู้ใช้จัดเตรียมบน Linux x64; [การวินิจฉัยไบนารี](../binary-diagnostics.md) |
| ไบต์โค้ด EVM | ตัวเลือกฟังก์ชันสำหรับการเรียก ออฟเซ็ตไบต์ อาร์กิวเมนต์และความสามารถในการเปลี่ยนสถานะที่อนุมานได้ | ไฟล์บนเครื่องที่มีไบต์ดิบหรือข้อมูลเลขฐานสิบหกบน Linux x64; [คู่มือ EVM แบบออฟไลน์](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| ข้อมูลการแครชของ Linux ที่บันทึกไว้ | ระเบียน note ดิบ รีจิสเตอร์/สัญญาณของทุกเธรดที่บันทึกไว้ และตัวเลือกการแมปเพิ่มเติม | pwntools ที่ผู้ใช้จัดเตรียมบน Linux x64; เลือกใช้ GDB/pwndbg เพิ่มเติมได้; [การแครชที่บันทึกไว้](../recorded-crashes.md) |
-| JavaScript / Electron | โมดูล การนำเข้า ซอร์สแมป เส้นทาง IPC และความสัมพันธ์กับส่วนเสริมเนทีฟ | Node.js และ npm; [การวิเคราะห์แอปพลิเคชัน](https://rea.tools/th/guides/javascript/) |
-| เว็บไซต์ | โครงสร้างหน้า สคริปต์ ข้อมูลเครือข่ายที่สังเกตได้ และภาพหน้าจอที่ร้องขอ | เบราว์เซอร์ในตระกูล Chrome; [การวิเคราะห์ผ่านเบราว์เซอร์](https://rea.tools/th/guides/browser/) |
+| JavaScript / Electron | โมดูล การนำเข้า ซอร์สแมป เส้นทาง IPC และความสัมพันธ์กับส่วนเสริมเนทีฟ | Node.js และ npm; [การวิเคราะห์แอปพลิเคชัน](../javascript-application-workflows.md) |
+| เว็บไซต์ | โครงสร้างหน้า สคริปต์ ข้อมูลเครือข่ายที่สังเกตได้ และภาพหน้าจอที่ร้องขอ | เบราว์เซอร์ในตระกูล Chrome; [การวิเคราะห์ผ่านเบราว์เซอร์](../browser-observation.md) |
| ข้อมูลเครือข่ายที่บันทึกไว้ | คำขอ คำตอบ เพย์โหลดที่ปรากฏ และตำแหน่งต้นทาง | HAR; mitmdump บน Linux สำหรับข้อมูลที่บันทึกในรูปแบบเนทีฟของ mitmproxy; [คู่มือการบันทึกข้อมูล](../web-network-captures.md) |
| การจับแพ็กเก็ต | จุดเชื่อมต่อ, DNS, TLS SNI, การกระจายโปรโตคอล และคำขอ HTTP | tshark และ capinfos ที่ผู้เรียกจัดเตรียม; [คู่มือ pcap](../pcap-analysis.md) |
| แอสเซมบลี .NET | เมทาดาทา คำสั่ง CIL การพึ่งพาเนทีฟที่ประกาศไว้ และการเปรียบเทียบผลการบิลด์ | การตรวจสอบแบบสถิต; [คู่มือโค้ดแบบจัดการ](../managed-code-analysis.md) |
diff --git a/docs/readme/README_tr.md b/docs/readme/README_tr.md
index f612c1a98..47ca49b71 100644
--- a/docs/readme/README_tr.md
+++ b/docs/readme/README_tr.md
@@ -139,7 +139,7 @@ REA; Node.js 22.x (>=22.19), 24.x (>=24.11) veya 26+ ve npm gerektirir. Ek araç
| Hedef | REA'nın döndürdükleri | Gereksinimler ve rehber |
| --------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
-| Yerel makine kodu içeren ikili dosyalar | Sözde kod, assembly kodu, dizeler, semboller, çağrılar ve referanslar | Hopper, Ghidra veya IDA; [yerel kod analizi](https://rea.tools/tr/guides/native/) |
+| Yerel makine kodu içeren ikili dosyalar | Sözde kod, assembly kodu, dizeler, semboller, çağrılar ve referanslar | Hopper, Ghidra veya IDA; [yerel kod analizi](../native-investigation.md) |
| Çevrimdışı ELF yapısı | Bölümler, segmentler, özgün semboller/yeniden konumlandırmalar ve statik analizden olası güvenlik önlemleri | Linux x64 üzerinde çağıranın sağladığı pwntools; [ikili dosya tanılama](../binary-diagnostics.md) |
| Go ikili dosyaları | Gömülü compiler sürümü, modüller, replacement'lar ve build ayarları | Yerleşik statik ELF/PE/thin Mach-O incelemesi; Go kurulumu gerekmez |
| Rust ikili dosyaları | Gömülü cargo-auditable crate adları, sürümleri, kaynakları ve bağımlılık ilişkileri | Yerleşik statik ELF/PE/thin Mach-O incelemesi; [Rust ikili dosyaları](../rust-binaries.md) |
@@ -147,8 +147,8 @@ REA; Node.js 22.x (>=22.19), 24.x (>=24.11) veya 26+ ve npm gerektirir. Ek araç
| EVM bayt kodu | Yönlendirme seçicileri, bayt ofsetleri, çıkarımla belirlenen argümanlar ve durum değiştirilebilirliği | Linux x64 üzerinde yerel ham bayt/onaltılık girdi; [çevrimdışı EVM rehberi](../evm-bytecode.md) |
| SQLite veritabanları | Tablolar, sütunlar, index'ler, view'lar, trigger'lar ve seçilen sıradan tablo satırları | Yerel database/WAL snapshot'ı; native SQLite sınırlarıyla Node.js 24.x >=24.15 veya 26+ |
| Kaydedilmiş Linux çökmeleri | Ham note kayıtları, kaydedilen her iş parçacığının yazmaçları/sinyalleri ve isteğe bağlı eşleme adayları | Linux x64 üzerinde çağıranın sağladığı pwntools; isteğe bağlı GDB/pwndbg; [kaydedilmiş çökmeler](../recorded-crashes.md) |
-| JavaScript / Electron | Modüller, içe aktarmalar, kaynak haritaları, rotalar, IPC ve yerel eklenti ilişkileri | Node.js ve npm; [uygulama analizi](https://rea.tools/tr/guides/javascript/) |
-| Web siteleri | Sayfa yapısı, betikler, ağ gözlemleri ve istenen ekran görüntüleri | Chrome ailesinden bir tarayıcı; [tarayıcı analizi](https://rea.tools/tr/guides/browser/) |
+| JavaScript / Electron | Modüller, içe aktarmalar, kaynak haritaları, rotalar, IPC ve yerel eklenti ilişkileri | Node.js ve npm; [uygulama analizi](../javascript-application-workflows.md) |
+| Web siteleri | Sayfa yapısı, betikler, ağ gözlemleri ve istenen ekran görüntüleri | Chrome ailesinden bir tarayıcı; [tarayıcı analizi](../browser-observation.md) |
| Kaydedilmiş ağ yakalamaları | İstekler, yanıtlar, erişilebilir yük içerikleri ve kaynak konumları | HAR veya Fiddler Everywhere SAZ; Linux'ta native mitmproxy için mitmdump; [ağ yakalama rehberi](../web-network-captures.md) |
| .NET derlemeleri | Meta veriler, CIL talimatları, bildirilmiş yerel bağımlılıklar ve derleme karşılaştırmaları | Statik inceleme; [yönetilen kod rehberi](../managed-code-analysis.md) |
| Android APK'leri | Manifest bildirimleri, sınıflar, tersine derlenmiş metotlar ve referanslar | Linux/macOS/Windows x64 üzerinde arayüzsüz JADX ve tam bir JDK; [Android rehberi](../android-analysis.md) |
diff --git a/docs/readme/README_uk.md b/docs/readme/README_uk.md
index 6995e2ed7..b8610ec99 100644
--- a/docs/readme/README_uk.md
+++ b/docs/readme/README_uk.md
@@ -137,13 +137,13 @@ REA потребує Node.js 22.x (>=22.19), 24.x (>=24.11) або 26+, а та
| Ціль | Що повертає REA | Вимоги й посібник |
| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
-| Нативні бінарні файли | Псевдокод, асемблерний код, рядки, символи, виклики й посилання | Hopper, Ghidra або IDA; [нативний аналіз](https://rea.tools/uk/guides/native/) |
+| Нативні бінарні файли | Псевдокод, асемблерний код, рядки, символи, виклики й посилання | Hopper, Ghidra або IDA; [нативний аналіз](../native-investigation.md) |
| Структура ELF без запуску | Секції, сегменти, початкові символи/релокації та можливі захисні механізми за даними статичного аналізу | pwntools, наданий стороною, що викликає інструмент, у Linux x64; [діагностика бінарних файлів](../binary-diagnostics.md) |
| Байт-код EVM | Селектори диспетчеризації, зміщення байтів, виведені припущення про аргументи та змінюваність стану | Локальні необроблені байти або шістнадцяткове представлення у Linux x64; [посібник EVM без запуску](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| Записані аварійні завершення в Linux | Необроблені записи note, регістри/сигнали кожного записаного потоку й необов'язкові кандидати зіставлення пам'яті | pwntools, наданий стороною, що викликає інструмент, у Linux x64; необов'язкові GDB/pwndbg; [записані аварійні завершення](../recorded-crashes.md) |
-| JavaScript / Electron | Модулі, імпорти, карти вихідного коду, маршрути, IPC і зв'язки з нативними доповненнями | Node.js і npm; [аналіз застосунків](https://rea.tools/uk/guides/javascript/) |
-| Сайти | Структура сторінки, скрипти, мережеві спостереження й запитані знімки екрана | Браузер сімейства Chrome; [аналіз браузера](https://rea.tools/uk/guides/browser/) |
+| JavaScript / Electron | Модулі, імпорти, карти вихідного коду, маршрути, IPC і зв'язки з нативними доповненнями | Node.js і npm; [аналіз застосунків](../javascript-application-workflows.md) |
+| Сайти | Структура сторінки, скрипти, мережеві спостереження й запитані знімки екрана | Браузер сімейства Chrome; [аналіз браузера](../browser-observation.md) |
| Збережені мережеві захоплення | Запити, відповіді, доступні корисні дані та місця в джерелі | HAR; mitmdump у Linux для захоплень у власному форматі mitmproxy; [посібник мережевих захоплень](../web-network-captures.md) |
| Захоплення пакетів | Кінцеві точки, DNS, TLS SNI, розподіл протоколів та HTTP-запити | Надані викликаючою стороною tshark та capinfos; [підручник pcap](../pcap-analysis.md) |
| Збірки .NET | Метадані, інструкції CIL, оголошені нативні залежності й порівняння збірок | Статична перевірка; [посібник керованого коду](../managed-code-analysis.md) |
diff --git a/docs/readme/README_vi.md b/docs/readme/README_vi.md
index 83391e056..0d63d2323 100644
--- a/docs/readme/README_vi.md
+++ b/docs/readme/README_vi.md
@@ -137,13 +137,13 @@ REA yêu cầu Node.js 22.x (>=22.19), 24.x (>=24.11) hoặc 26+, cùng với np
| Mục tiêu | REA trả về gì | Yêu cầu và hướng dẫn |
| ----------------------------- | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
-| Tệp nhị phân mã máy | Mã giả, hợp ngữ, chuỗi, ký hiệu, lời gọi và tham chiếu | Hopper, Ghidra hoặc IDA; [phân tích mã máy](https://rea.tools/vi/guides/native/) |
+| Tệp nhị phân mã máy | Mã giả, hợp ngữ, chuỗi, ký hiệu, lời gọi và tham chiếu | Hopper, Ghidra hoặc IDA; [phân tích mã máy](../native-investigation.md) |
| Bố cục ELF ngoại tuyến | Các section, segment, ký hiệu/thông tin tái định vị gốc và các biện pháp giảm thiểu có thể có từ phân tích tĩnh | pwntools do bên gọi cung cấp trên Linux x64; [chẩn đoán tệp nhị phân](../binary-diagnostics.md) |
| Bytecode EVM | Bộ chọn điều phối, độ lệch byte, tham số suy luận và khả năng thay đổi trạng thái | Đầu vào cục bộ chứa byte thô hoặc dạng thập lục phân trên Linux x64; [hướng dẫn EVM ngoại tuyến](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| Sự cố Linux đã ghi lại | Bản ghi note thô, thanh ghi/tín hiệu của mọi luồng được ghi lại và các ứng viên ánh xạ tùy chọn | pwntools do bên gọi cung cấp trên Linux x64; GDB/pwndbg tùy chọn; [sự cố đã ghi lại](../recorded-crashes.md) |
-| JavaScript / Electron | Mô-đun, các khai báo import, source map, tuyến, IPC và quan hệ với tiện ích mở rộng mã máy | Node.js và npm; [phân tích ứng dụng](https://rea.tools/vi/guides/javascript/) |
-| Trang web | Cấu trúc trang, script, quan sát mạng và ảnh chụp màn hình được yêu cầu | Trình duyệt thuộc họ Chrome; [phân tích trình duyệt](https://rea.tools/vi/guides/browser/) |
+| JavaScript / Electron | Mô-đun, các khai báo import, source map, tuyến, IPC và quan hệ với tiện ích mở rộng mã máy | Node.js và npm; [phân tích ứng dụng](../javascript-application-workflows.md) |
+| Trang web | Cấu trúc trang, script, quan sát mạng và ảnh chụp màn hình được yêu cầu | Trình duyệt thuộc họ Chrome; [phân tích trình duyệt](../browser-observation.md) |
| Bản ghi lưu lượng mạng đã lưu | Yêu cầu, phản hồi, payload có thể truy cập và vị trí nguồn | HAR; mitmdump trên Linux cho bản ghi định dạng gốc của mitmproxy; [hướng dẫn bản ghi mạng](../web-network-captures.md) |
| Bắt gói tin | Điểm cuối, DNS, TLS SNI, phân bố giao thức và yêu cầu HTTP | tshark và capinfos do nơi gọi cung cấp; [hướng dẫn pcap](../pcap-analysis.md) |
| Assembly .NET | Siêu dữ liệu, lệnh CIL, các phụ thuộc mã máy được khai báo và so sánh bản dựng | Kiểm tra tĩnh; [hướng dẫn mã được quản lý](../managed-code-analysis.md) |
diff --git a/docs/readme/README_zh-TW.md b/docs/readme/README_zh-TW.md
index f88d33faa..736b43d31 100644
--- a/docs/readme/README_zh-TW.md
+++ b/docs/readme/README_zh-TW.md
@@ -139,15 +139,15 @@ REA 需要 Node.js 22.x(>=22.19)、24.x(>=24.11)或 26+,以及 npm。
| 目標 | REA 返回的內容 | 要求與指南 |
| --------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
-| 原生二進位檔案 | 偽程式碼、組合語言、字串、符號、呼叫和引用 | Hopper、Ghidra 或 IDA;[原生分析](https://rea.tools/zh-TW/guides/native/) |
+| 原生二進位檔案 | 偽程式碼、組合語言、字串、符號、呼叫和引用 | Hopper、Ghidra 或 IDA;[原生分析](../native-investigation.md) |
| 離線 ELF 佈局 | 節、段、原始符號/重定位資訊及靜態防護機制候選項 | Linux x64 上由呼叫方提供的 pwntools;[二進位診斷](../binary-diagnostics.md) |
| Go 二進位檔案 | 內嵌編譯器版本、模組、替換項和建置設定 | 內建靜態 ELF/PE/thin Mach-O 檢查;無需安裝 Go |
| WASM 工件 | 驗證、節、精確的匯入/匯出 WAT 形式及解碼後的 WAT | 呼叫方提供的 WABT 1.0.42;`inspect_wasm_artifact` |
| EVM 位元組碼 | 分派選擇器、位元組偏移、推斷的參數和狀態可變性 | Linux x64 上的本地原始位元組/十六進位輸入載體;[離線 EVM 指南](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| 已記錄的 Linux 崩潰 | 原始 note 記錄、每個已記錄執行緒的暫存器/訊號及可選的對映候選項 | Linux x64 上由呼叫方提供的 pwntools;可選的 GDB/pwndbg;[已記錄崩潰](../recorded-crashes.md) |
-| JavaScript / Electron | 模組、匯入、source map、路由、IPC 和原生附加元件關係 | Node.js 和 npm;[應用分析](https://rea.tools/zh-TW/guides/javascript/) |
-| 網站 | 頁面結構、腳本、網路觀察結果和按請求獲取的螢幕擷取畫面 | Chrome 系瀏覽器;[瀏覽器分析](https://rea.tools/zh-TW/guides/browser/) |
+| JavaScript / Electron | 模組、匯入、source map、路由、IPC 和原生附加元件關係 | Node.js 和 npm;[應用分析](../javascript-application-workflows.md) |
+| 網站 | 頁面結構、腳本、網路觀察結果和按請求獲取的螢幕擷取畫面 | Chrome 系瀏覽器;[瀏覽器分析](../browser-observation.md) |
| 已保存的網路擷取 | 請求、回應、可訪問的酬載和來源位置 | HAR;原生 mitmproxy 擷取需要 Linux 上的 mitmdump;[擷取指南](../web-network-captures.md) |
| 封包擷取 | 端點、DNS、TLS SNI、通訊協定分佈和 HTTP 請求 | 呼叫端提供的 tshark 和 capinfos;[pcap 指南](../pcap-analysis.md) |
| .NET 程式集 | 中繼資料、CIL 指令、聲明的原生依賴和建置對比 | 靜態檢查;[托管程式碼指南](../managed-code-analysis.md) |
diff --git a/docs/readme/README_zh.md b/docs/readme/README_zh.md
index 93c598a20..fc93d0983 100644
--- a/docs/readme/README_zh.md
+++ b/docs/readme/README_zh.md
@@ -139,15 +139,15 @@ REA 需要 Node.js 22.x(>=22.19)、24.x(>=24.11)或 26+,以及 npm。
| 目标 | REA 返回的内容 | 要求与指南 |
| --------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
-| 原生二进制文件 | 伪代码、汇编、字符串、符号、调用和引用 | Hopper、Ghidra 或 IDA;[原生分析](https://rea.tools/zh-CN/guides/native/) |
+| 原生二进制文件 | 伪代码、汇编、字符串、符号、调用和引用 | Hopper、Ghidra 或 IDA;[原生分析](../native-investigation.md) |
| 离线 ELF 布局 | 节、段、原始符号/重定位信息及静态防护机制候选项 | Linux x64 上由调用方提供的 pwntools;[二进制诊断](../binary-diagnostics.md) |
| Go 二进制文件 | 内嵌编译器版本、模块、替换项和构建设置 | 内置静态 ELF/PE/thin Mach-O 检查;无需安装 Go |
| WASM 工件 | 验证、节、精确的导入/导出 WAT 形式及解码后的 WAT | 调用方提供的 WABT 1.0.42;`inspect_wasm_artifact` |
| EVM 字节码 | 分派选择器、字节偏移、推断的参数和状态可变性 | Linux x64 上的本地原始字节/十六进制输入载体;[离线 EVM 指南](../evm-bytecode.md) |
| Rust binaries | Embedded cargo-auditable dependency list | [Rust binaries](../rust-binaries.md) |
| 已记录的 Linux 崩溃 | 原始 note 记录、每个已记录线程的寄存器/信号及可选的映射候选项 | Linux x64 上由调用方提供的 pwntools;可选的 GDB/pwndbg;[已记录崩溃](../recorded-crashes.md) |
-| JavaScript / Electron | 模块、导入、source map、路由、IPC 和原生扩展关系 | Node.js 和 npm;[应用分析](https://rea.tools/zh-CN/guides/javascript/) |
-| 网站 | 页面结构、脚本、网络观察结果和按请求获取的截图 | Chrome 系浏览器;[浏览器分析](https://rea.tools/zh-CN/guides/browser/) |
+| JavaScript / Electron | 模块、导入、source map、路由、IPC 和原生扩展关系 | Node.js 和 npm;[应用分析](../javascript-application-workflows.md) |
+| 网站 | 页面结构、脚本、网络观察结果和按请求获取的截图 | Chrome 系浏览器;[浏览器分析](../browser-observation.md) |
| 已保存的网络捕获 | 请求、响应、可访问的载荷和来源位置 | HAR;原生 mitmproxy 捕获需要 Linux 上的 mitmdump;[捕获指南](../web-network-captures.md) |
| 数据包捕获 | 端点、DNS、TLS SNI、协议分布和 HTTP 请求 | 调用方提供的 tshark 和 capinfos;[pcap 指南](../pcap-analysis.md) |
| .NET 程序集 | 元数据、CIL 指令、声明的原生依赖和构建对比 | 静态检查;[托管代码指南](../managed-code-analysis.md) |
diff --git a/licenses/npm-dependencies.txt b/licenses/npm-dependencies.txt
index 794d5287e..5026b01ff 100644
--- a/licenses/npm-dependencies.txt
+++ b/licenses/npm-dependencies.txt
@@ -2,7 +2,7 @@ REA npm dependency inventory
Prepared from the root package-lock.json; refresh this inventory when locked dependencies change.
License identifiers are upstream lockfile declarations, not a legal assessment.
Runtime includes transitive and optional platform packages; development includes build, test and website tooling.
-Locked package entries: 719; runtime: 175.
+Locked package entries: 721; runtime: 177.
Full runtime copyright/license/NOTICE texts: npm-runtime-notices.txt.
@algolia/abtesting@1.25.0 | development | MIT
@@ -3000,6 +3000,11 @@ safer-buffer@2.1.2 | development | MIT
Package: https://www.npmjs.com/package/safer-buffer/v/2.1.2
Archive: https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz
Integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
+saxes@6.0.0 | runtime | ISC
+ Lockfile path: node_modules/saxes
+ Package: https://www.npmjs.com/package/saxes/v/6.0.0
+ Archive: https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz
+ Integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==
search-insights@2.17.3 | development | MIT
Lockfile path: node_modules/search-insights
Package: https://www.npmjs.com/package/search-insights/v/2.17.3
@@ -3580,6 +3585,11 @@ xmlbuilder@15.1.1 | runtime | MIT
Package: https://www.npmjs.com/package/xmlbuilder/v/15.1.1
Archive: https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz
Integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==
+xmlchars@2.2.0 | runtime | MIT
+ Lockfile path: node_modules/xmlchars
+ Package: https://www.npmjs.com/package/xmlchars/v/2.2.0
+ Archive: https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz
+ Integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
yaml@2.9.0 | runtime | ISC
Lockfile path: node_modules/yaml
Package: https://www.npmjs.com/package/yaml/v/2.9.0
diff --git a/licenses/npm-runtime-notices.txt b/licenses/npm-runtime-notices.txt
index a2032f7a7..81adcd9ab 100644
--- a/licenses/npm-runtime-notices.txt
+++ b/licenses/npm-runtime-notices.txt
@@ -1,7 +1,7 @@
REA third-party npm runtime copyright, license and NOTICE texts
Collected from integrity-verified locked npm archives. Release-specific supplements and upstream notice gaps are identified in their entries.
External engines are separately obtained; see THIRD_PARTY_NOTICES.md.
-Runtime dependency fingerprint (SHA-256): b0d0151958456c6e72c5720af80d783893be88a7b4c9a409db8505296fe10bd9
+Runtime dependency fingerprint (SHA-256): 49b181923ab240c68c64d35ecdd8f93cb5cd516c765f2282d0e0eca0bcadd13e
===== @babel/helper-string-parser@8.0.6 =====
Declared license: MIT
@@ -8441,3 +8441,108 @@ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
+
+===== saxes@6.0.0 =====
+Declared license: ISC
+Archive: https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz
+Integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==
+Scope: npm runtime dependency, including optional platform packages.
+
+The locked npm archive omits LICENSE; preserved from the matching v6.0.0 upstream tag.
+Source: https://raw.githubusercontent.com/lddubeau/saxes/v6.0.0/LICENSE
+SHA-256: 0fac2374380621b22e6b50451057721a9c52935b02d16d106a9f04897f061d0e
+
+--- upstream LICENSE ---
+
+The ISC License
+
+Copyright (c) Contributors
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+====
+
+The following license is the one that governed sax, from which saxes
+was forked. Isaac Schlueter is not *directly* involved with saxes so
+don't go bugging him for saxes issues.
+
+The ISC License
+
+Copyright (c) Isaac Z. Schlueter and Contributors
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+====
+
+`String.fromCodePoint` by Mathias Bynens is no longer used, but it can
+still be found in old commits. It was once used according to terms of
+MIT License, as follows:
+
+ Copyright Mathias Bynens
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+===== xmlchars@2.2.0 =====
+Declared license: MIT
+Archive: https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz
+Integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
+Scope: npm runtime dependency, including optional platform packages.
+
+--- package/LICENSE ---
+
+Copyright Louis-Dominique Dubeau and contributors to xmlchars
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/package-lock.json b/package-lock.json
index 48764a796..62d4e8f48 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -38,6 +38,7 @@
"pino": "10.4.0",
"playwright-core": "1.58.2",
"plist": "5.0.0",
+ "saxes": "6.0.0",
"semver": "7.8.5",
"smol-toml": "1.9.0",
"stream-chain": "4.2.6",
@@ -8672,6 +8673,18 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/saxes": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz",
+ "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==",
+ "license": "ISC",
+ "dependencies": {
+ "xmlchars": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=v12.22.7"
+ }
+ },
"node_modules/search-insights": {
"version": "2.17.3",
"resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.3.tgz",
@@ -10585,6 +10598,12 @@
"node": ">=8.0"
}
},
+ "node_modules/xmlchars": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
+ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
+ "license": "MIT"
+ },
"node_modules/yaml": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz",
diff --git a/package.json b/package.json
index 45e73afc0..c60c1fa99 100644
--- a/package.json
+++ b/package.json
@@ -341,6 +341,7 @@
"pino": "10.4.0",
"playwright-core": "1.58.2",
"plist": "5.0.0",
+ "saxes": "6.0.0",
"semver": "7.8.5",
"smol-toml": "1.9.0",
"stream-chain": "4.2.6",
diff --git a/scripts/fixtures/browser-verifier-site.d.mts b/scripts/fixtures/browser-verifier-site.d.mts
new file mode 100644
index 000000000..75827f3d3
--- /dev/null
+++ b/scripts/fixtures/browser-verifier-site.d.mts
@@ -0,0 +1,7 @@
+export interface BrowserVerifierSite {
+ readonly origin: string;
+ triggerSessionNavigation(): void;
+ close(): Promise;
+}
+
+export function startBrowserVerifierSite(): Promise;
diff --git a/scripts/fixtures/browser-verifier-site.mjs b/scripts/fixtures/browser-verifier-site.mjs
index 059a63599..40281bc64 100644
--- a/scripts/fixtures/browser-verifier-site.mjs
+++ b/scripts/fixtures/browser-verifier-site.mjs
@@ -184,11 +184,13 @@ export async function startBrowserVerifierSite() {
async close() {
for (const client of webSockets.clients) client.terminate();
await new Promise((resolve) => webSockets.close(resolve));
- await new Promise((resolve, reject) =>
+ const serverClosed = new Promise((resolve, reject) =>
server.close((error) =>
error === undefined ? resolve() : reject(error),
),
);
+ server.closeAllConnections();
+ await serverClosed;
},
};
}
diff --git a/scripts/lib/browser-module-e2e.mjs b/scripts/lib/browser-module-e2e.mjs
index 2bb656adb..5c6a154f3 100644
--- a/scripts/lib/browser-module-e2e.mjs
+++ b/scripts/lib/browser-module-e2e.mjs
@@ -14,36 +14,42 @@ import { webModuleTraceResultSchema } from "../../dist/domain/webModuleTrace.js"
import { NativeModuleResolver } from "../../dist/browser/modules/NativeModuleResolver.js";
import { startBrowserModuleSite } from "../fixtures/browser-module-site.mjs";
import { mcpTextValue } from "./mcp-verifier-results.mjs";
+import { closeRuntimeFixtureResources } from "./browser-runtime-fixture-lifecycle.mjs";
/** Check native URL resolution against an independently loaded module graph through CLI/MCP. */
export async function verifyBrowserModules(
executable,
entrypoint = fileURLToPath(new URL("../rea.mjs", import.meta.url)),
) {
- const site = await startBrowserModuleSite();
- const root = await mkdtemp(join(tmpdir(), "rea-browser-modules-"));
- const env = {
- ...process.env,
- REA_LOG_LEVEL: "silent",
- REA_BROWSER_EXECUTABLE: executable,
- 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: "module-real-e2e", version: "1" });
+ let site;
+ let root;
+ let transport;
+ let client;
+ let primaryError;
try {
+ site = await startBrowserModuleSite();
+ root = await mkdtemp(join(tmpdir(), "rea-browser-modules-"));
+ const env = {
+ ...process.env,
+ REA_LOG_LEVEL: "silent",
+ REA_BROWSER_EXECUTABLE: executable,
+ 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));
+ };
+ transport = new StdioClientTransport({
+ command: process.execPath,
+ args: [entrypoint, "mcp"],
+ env,
+ stderr: "pipe",
+ });
+ client = new Client({ name: "module-real-e2e", version: "1" });
const oracle = await loadingOracle(executable, site);
const scenario = {
browser: { mode: "launch", executable_path: executable },
@@ -298,11 +304,17 @@ export async function verifyBrowserModules(
map_identity_verified: true,
implicit_refetches: 0,
};
+ } catch (cause) {
+ primaryError = cause;
+ throw cause;
} finally {
- await client.close();
- await transport.close();
- await site.close();
- await rm(root, { recursive: true, force: true });
+ const cleanup = [];
+ if (client !== undefined) cleanup.push(() => client.close());
+ if (transport !== undefined) cleanup.push(() => transport.close());
+ if (site !== undefined) cleanup.push(() => site.close());
+ if (root !== undefined)
+ cleanup.push(() => rm(root, { recursive: true, force: true }));
+ await closeRuntimeFixtureResources(cleanup, primaryError);
}
}
diff --git a/scripts/lib/browser-network-e2e.mjs b/scripts/lib/browser-network-e2e.mjs
index 4cf369f63..33aad95c7 100644
--- a/scripts/lib/browser-network-e2e.mjs
+++ b/scripts/lib/browser-network-e2e.mjs
@@ -14,6 +14,7 @@ import {
} from "../fixtures/browser-network-site.mjs";
import { assertBrowserNetworkEvidence } from "./browser-network-assertions.mjs";
import { scenarioProfiles } from "./browser-scenario-verifier.mjs";
+import { closeRuntimeFixtureResources } from "./browser-runtime-fixture-lifecycle.mjs";
/** Exercise selected network content through real CLI and stdio MCP, one browser at a time. */
export async function verifyBrowserNetworkEvidence(
@@ -21,9 +22,14 @@ export async function verifyBrowserNetworkEvidence(
entrypoint = fileURLToPath(new URL("../rea.mjs", import.meta.url)),
attachment,
) {
- const site = await startBrowserNetworkSite();
- const profilesBefore = await scenarioProfiles();
+ let site;
+ let profilesBefore;
+ let transport;
+ let client;
+ let primaryError;
try {
+ site = await startBrowserNetworkSite();
+ profilesBefore = await scenarioProfiles();
const scenario = browserScenarioSchema.parse({
browser: { mode: "launch", executable_path: executable },
start_url: { url: site.origin },
@@ -97,58 +103,50 @@ export async function verifyBrowserNetworkEvidence(
() => assertBrowserNetworkEvidence(swapped, site.origin),
/associated with a different same-URL request/,
);
- const transport = new StdioClientTransport({
+ transport = new StdioClientTransport({
command: process.execPath,
args: [entrypoint, "mcp"],
env,
stderr: "pipe",
});
- const client = new Client({ name: "network-real-e2e", version: "1" });
+ client = new Client({ name: "network-real-e2e", version: "1" });
let mcpProof;
- try {
- await client.connect(transport);
- const result = await client.callTool(
- { name: "capture_browser_scenario", arguments: scenario },
+ await client.connect(transport);
+ const result = await client.callTool(
+ { name: "capture_browser_scenario", arguments: scenario },
+ { timeout: 60_000 },
+ );
+ assert.notEqual(result.isError, true, JSON.stringify(result));
+ const evidence = parseEvidence(result.structuredContent);
+ mcpProof = assertBrowserNetworkEvidence(
+ browserScenarioCaptureSchema.parse(evidence.normalized_result),
+ site.origin,
+ );
+ if (attachment !== undefined) {
+ const connectedScenario = browserScenarioSchema.parse({
+ ...scenario,
+ browser: { mode: "connect", ...attachment },
+ });
+ const connected = await client.callTool(
+ { name: "capture_browser_scenario", arguments: connectedScenario },
{ timeout: 60_000 },
);
- assert.notEqual(result.isError, true, JSON.stringify(result));
- const evidence = parseEvidence(result.structuredContent);
- mcpProof = assertBrowserNetworkEvidence(
- browserScenarioCaptureSchema.parse(evidence.normalized_result),
- site.origin,
- );
- if (attachment !== undefined) {
- const connectedScenario = browserScenarioSchema.parse({
- ...scenario,
- browser: { mode: "connect", ...attachment },
- });
- const connected = await client.callTool(
- { name: "capture_browser_scenario", arguments: connectedScenario },
- { timeout: 60_000 },
- );
- assert.notEqual(connected.isError, true, JSON.stringify(connected));
- const connectedEvidence = parseEvidence(connected.structuredContent);
- assert.deepEqual(
- assertBrowserNetworkEvidence(
- browserScenarioCaptureSchema.parse(
- connectedEvidence.normalized_result,
- ),
- site.origin,
- "disconnected-external",
+ assert.notEqual(connected.isError, true, JSON.stringify(connected));
+ const connectedEvidence = parseEvidence(connected.structuredContent);
+ assert.deepEqual(
+ assertBrowserNetworkEvidence(
+ browserScenarioCaptureSchema.parse(
+ connectedEvidence.normalized_result,
),
- cliProof,
- );
- assert.ok(
- (await fetch(`${attachment.cdp_endpoint}/json/version`)).ok,
- "Network capture closed the external browser",
- );
- }
- } finally {
- try {
- await client.close();
- } finally {
- await transport.close();
- }
+ site.origin,
+ "disconnected-external",
+ ),
+ cliProof,
+ );
+ assert.ok(
+ (await fetch(`${attachment.cdp_endpoint}/json/version`)).ok,
+ "Network capture closed the external browser",
+ );
}
assert.deepEqual(mcpProof, cliProof);
for (const path of [
@@ -180,7 +178,14 @@ export async function verifyBrowserNetworkEvidence(
profile_cleanup: true,
connected_network_verified: attachment !== undefined,
};
+ } catch (cause) {
+ primaryError = cause;
+ throw cause;
} finally {
- await site.close();
+ const cleanup = [];
+ if (client !== undefined) cleanup.push(() => client.close());
+ if (transport !== undefined) cleanup.push(() => transport.close());
+ if (site !== undefined) cleanup.push(() => site.close());
+ await closeRuntimeFixtureResources(cleanup, primaryError);
}
}
diff --git a/scripts/lib/browser-runtime-e2e.mjs b/scripts/lib/browser-runtime-e2e.mjs
index b35cde09a..78d9d4615 100644
--- a/scripts/lib/browser-runtime-e2e.mjs
+++ b/scripts/lib/browser-runtime-e2e.mjs
@@ -14,6 +14,7 @@ import { parseEvidence } from "../../dist/domain/evidence.js";
import { webExecutionSchema } from "../../dist/domain/webExecution.js";
import { webEventListenersSchema } from "../../dist/domain/webEventListeners.js";
import { startBrowserRuntimeSite } from "../fixtures/browser-runtime-site.mjs";
+import { requireOrdinaryWindowsVerifierCaller } from "./windows-ordinary-user-verifier.mjs";
import { mcpTextValue } from "./mcp-verifier-results.mjs";
import {
startRuntimeFixtureBrowser,
@@ -37,6 +38,7 @@ export async function verifyBrowserRuntime(
executable,
entrypoint = fileURLToPath(new URL("../rea.mjs", import.meta.url)),
) {
+ await requireOrdinaryWindowsVerifierCaller();
await access(executable);
const site = await startBrowserRuntimeSite();
let fixture;
diff --git a/scripts/lib/browser-runtime-fixture-lifecycle.mjs b/scripts/lib/browser-runtime-fixture-lifecycle.mjs
index 88a76e573..78709646d 100644
--- a/scripts/lib/browser-runtime-fixture-lifecycle.mjs
+++ b/scripts/lib/browser-runtime-fixture-lifecycle.mjs
@@ -12,9 +12,11 @@ import {
BROWSER_DEVTOOLS_STARTUP_TIMEOUT_MS,
waitForBrowserDevtoolsPort,
} from "../../dist/browser/BrowserProcessStartup.js";
+import { requireOrdinaryWindowsVerifierCaller } from "./windows-ordinary-user-verifier.mjs";
/** Launch the synthetic fixture browser and await CDP in its own verified process group. */
export async function startRuntimeFixtureBrowser(executable, origin) {
+ await requireOrdinaryWindowsVerifierCaller();
const profile = await mkdtemp(join(tmpdir(), "rea-real-web-runtime-"));
let owned;
try {
diff --git a/scripts/lib/browser-script-export-e2e.mjs b/scripts/lib/browser-script-export-e2e.mjs
index 17fe25551..ce1599e17 100644
--- a/scripts/lib/browser-script-export-e2e.mjs
+++ b/scripts/lib/browser-script-export-e2e.mjs
@@ -15,6 +15,7 @@ import {
assertExportedScriptAnalysis,
} from "./browser-script-export-assertions.mjs";
import { mcpTextValue } from "./mcp-verifier-results.mjs";
+import { closeRuntimeFixtureResources } from "./browser-runtime-fixture-lifecycle.mjs";
/** Verify capture → export → existing analysis through real CLI and stdio MCP. */
export async function verifyBrowserScriptExport(
@@ -22,24 +23,29 @@ export async function verifyBrowserScriptExport(
entrypoint = fileURLToPath(new URL("../rea.mjs", import.meta.url)),
attachment,
) {
- const site = await startBrowserScriptSite();
- const root = await mkdtemp(join(tmpdir(), "rea-browser-script-export-"));
- const env = {
- ...process.env,
- REA_LOG_LEVEL: "silent",
- HOPPER_LAUNCHER_PATH: "/rea-unconfigured-provider/hopper",
- };
- const cli = exportCli(entrypoint, env);
- const scenario = scriptCaptureScenario(executable, site.origin);
- const save = (name, capture) => saveCapture(root, name, capture);
- const transport = new StdioClientTransport({
- command: process.execPath,
- args: [entrypoint, "mcp"],
- env,
- stderr: "pipe",
- });
- const client = new Client({ name: "web-script-real-e2e", version: "1" });
+ let site;
+ let root;
+ let transport;
+ let client;
+ let primaryError;
try {
+ site = await startBrowserScriptSite();
+ root = await mkdtemp(join(tmpdir(), "rea-browser-script-export-"));
+ const env = {
+ ...process.env,
+ REA_LOG_LEVEL: "silent",
+ HOPPER_LAUNCHER_PATH: "/rea-unconfigured-provider/hopper",
+ };
+ const cli = exportCli(entrypoint, env);
+ const scenario = scriptCaptureScenario(executable, site.origin);
+ const save = (name, capture) => saveCapture(root, name, capture);
+ transport = new StdioClientTransport({
+ command: process.execPath,
+ args: [entrypoint, "mcp"],
+ env,
+ stderr: "pipe",
+ });
+ client = new Client({ name: "web-script-real-e2e", version: "1" });
const cliCapture = await cli(
"capture-browser-scenario",
JSON.stringify(scenario),
@@ -103,11 +109,17 @@ export async function verifyBrowserScriptExport(
query_variants_isolated: true,
implicit_refetches: 0,
};
+ } catch (cause) {
+ primaryError = cause;
+ throw cause;
} finally {
- await client.close();
- await transport.close();
- await site.close();
- await rm(root, { recursive: true, force: true });
+ const cleanup = [];
+ if (client !== undefined) cleanup.push(() => client.close());
+ if (transport !== undefined) cleanup.push(() => transport.close());
+ if (site !== undefined) cleanup.push(() => site.close());
+ if (root !== undefined)
+ cleanup.push(() => rm(root, { recursive: true, force: true }));
+ await closeRuntimeFixtureResources(cleanup, primaryError);
}
}
diff --git a/scripts/lib/browser-source-map-e2e.mjs b/scripts/lib/browser-source-map-e2e.mjs
index efd12e648..635dcb5e6 100644
--- a/scripts/lib/browser-source-map-e2e.mjs
+++ b/scripts/lib/browser-source-map-e2e.mjs
@@ -12,35 +12,41 @@ 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";
+import { closeRuntimeFixtureResources } from "./browser-runtime-fixture-lifecycle.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" });
+ let site;
+ let root;
+ let transport;
+ let client;
+ let primaryError;
try {
+ site = await startBrowserSourceMapSite();
+ 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));
+ };
+ transport = new StdioClientTransport({
+ command: process.execPath,
+ args: [entrypoint, "mcp"],
+ env,
+ stderr: "pipe",
+ });
+ client = new Client({ name: "source-map-real-e2e", version: "1" });
const capture = await cli(
"capture-browser-scenario",
JSON.stringify({
@@ -126,11 +132,17 @@ export async function verifyBrowserSourceMap(
selected_inert_userinfo_context_preserved: true,
public_point_cases: 4,
};
+ } catch (cause) {
+ primaryError = cause;
+ throw cause;
} finally {
- await client.close();
- await transport.close();
- await site.close();
- await rm(root, { recursive: true, force: true });
+ const cleanup = [];
+ if (client !== undefined) cleanup.push(() => client.close());
+ if (transport !== undefined) cleanup.push(() => transport.close());
+ if (site !== undefined) cleanup.push(() => site.close());
+ if (root !== undefined)
+ cleanup.push(() => rm(root, { recursive: true, force: true }));
+ await closeRuntimeFixtureResources(cleanup, primaryError);
}
}
function assertPoint(evidence, { site, input, capture, identity }) {
diff --git a/scripts/lib/real-hopper-owner-exit.mjs b/scripts/lib/real-hopper-owner-exit.mjs
index 300b35ada..ff59b9586 100644
--- a/scripts/lib/real-hopper-owner-exit.mjs
+++ b/scripts/lib/real-hopper-owner-exit.mjs
@@ -10,6 +10,7 @@ import { verifyNoTokenOwnedProcesses } from "../../dist/process/ProcessOwnership
import {
observeProcessStartIdentity,
signalProcessWithStartIdentity,
+ systemProcessOwnershipHost,
} from "../../dist/process/ProcessOwnershipObservation.js";
import { startUnrelatedHopperSentinel } from "./unrelated-hopper-sentinel.mjs";
import {
@@ -31,6 +32,11 @@ export async function verifyLinuxHopperOwnerExit({
const outcomes = [];
try {
for (const mode of ["graceful", "SIGKILL"]) {
+ const baseline = await systemProcessOwnershipHost.captureBaseline?.();
+ assert.ok(
+ baseline,
+ "Could not capture pre-launch process ownership baseline",
+ );
const transport = new StdioClientTransport({
command: serverCommand,
args: serverArgs,
@@ -47,6 +53,18 @@ export async function verifyLinuxHopperOwnerExit({
assert.ok(ownerPid !== null);
const owner = await observeProcessStartIdentity(ownerPid);
assert.equal(owner?.state, "readable");
+ const ownerProcess = (
+ await systemProcessOwnershipHost.listProcesses()
+ ).find(({ pid }) => pid === ownerPid);
+ assert.ok(
+ ownerProcess,
+ "Could not observe the launched MCP process group",
+ );
+ assert.equal(typeof ownerProcess.processGroupId, "number");
+ const relation = {
+ leaderPid: ownerPid,
+ processGroupId: ownerProcess.processGroupId,
+ };
requireMcpLifecycleResult(
await client.callTool(
{
@@ -75,7 +93,17 @@ export async function verifyLinuxHopperOwnerExit({
const runId = status.analysis_run?.run_id;
assert.equal(typeof runId, "string");
assert.equal(status.analysis_provider_binding?.provider.id, "hopper");
- assert.equal((await verifyNoTokenOwnedProcesses(runId)).cleaned, false);
+ assert.equal(
+ (
+ await verifyNoTokenOwnedProcesses(
+ runId,
+ systemProcessOwnershipHost,
+ baseline,
+ relation,
+ )
+ ).cleaned,
+ false,
+ );
if (mode === "graceful") await client.close();
else {
assert.equal(
@@ -90,7 +118,12 @@ export async function verifyLinuxHopperOwnerExit({
const deadline = Date.now() + 10_000;
let cleanup;
do {
- cleanup = await verifyNoTokenOwnedProcesses(runId);
+ cleanup = await verifyNoTokenOwnedProcesses(
+ runId,
+ systemProcessOwnershipHost,
+ baseline,
+ relation,
+ );
if (cleanup.cleaned) break;
await delay(100);
} while (Date.now() < deadline);
diff --git a/scripts/lib/verifier-run.d.mts b/scripts/lib/verifier-run.d.mts
index 1e9d41324..9b8a71668 100644
--- a/scripts/lib/verifier-run.d.mts
+++ b/scripts/lib/verifier-run.d.mts
@@ -39,3 +39,8 @@ export function createVerifierRun(): VerifierRunStart;
export function completeVerifierRun(
run: VerifierRunStart,
): Promise;
+
+/** Require positive process-lineage evidence before claiming cleanup complete. */
+export function assertVerifierCleanupComplete(
+ processLineage: VerifierProcessLineage,
+): void;
diff --git a/scripts/lib/verifier-run.mjs b/scripts/lib/verifier-run.mjs
index 0b8f08919..23d8edbbf 100644
--- a/scripts/lib/verifier-run.mjs
+++ b/scripts/lib/verifier-run.mjs
@@ -33,6 +33,16 @@ export const completeVerifierRun = async (run) => {
};
};
+/** Require positive process-lineage evidence before claiming cleanup complete. */
+export const assertVerifierCleanupComplete = (processLineage) => {
+ if (processLineage.status !== "verified")
+ throw new Error(
+ `Verifier cleanup could not be verified: ${processLineage.reason}`,
+ );
+ if (processLineage.descendants.length !== 0)
+ throw new Error("Owned descendants survived verifier cleanup");
+};
+
const observeVerifierLineage = async (run, observedAt) => {
if (process.platform === "win32")
return unavailableLineage(
diff --git a/scripts/lib/windows-ordinary-user-verifier.d.mts b/scripts/lib/windows-ordinary-user-verifier.d.mts
new file mode 100644
index 000000000..2fde877f1
--- /dev/null
+++ b/scripts/lib/windows-ordinary-user-verifier.d.mts
@@ -0,0 +1,4 @@
+export declare const assertOrdinaryWindowsVerifierCaller: (
+ token: unknown,
+) => void;
+export declare const requireOrdinaryWindowsVerifierCaller: () => Promise;
diff --git a/scripts/lib/windows-ordinary-user-verifier.mjs b/scripts/lib/windows-ordinary-user-verifier.mjs
new file mode 100644
index 000000000..496a429da
--- /dev/null
+++ b/scripts/lib/windows-ordinary-user-verifier.mjs
@@ -0,0 +1,40 @@
+/** Require fixture verifiers on Windows to use the caller's ordinary-user token. */
+export const assertOrdinaryWindowsVerifierCaller = (token) => {
+ if (
+ typeof token !== "object" ||
+ token === null ||
+ !("administrator" in token) ||
+ !("elevated" in token) ||
+ token.administrator !== false ||
+ token.elevated !== false
+ ) {
+ const integrity =
+ typeof token === "object" &&
+ token !== null &&
+ "integrityLevel" in token &&
+ Number.isSafeInteger(token.integrityLevel)
+ ? ` (integrity level ${String(token.integrityLevel)})`
+ : "";
+ throw new Error(
+ "Windows browser verifier requires an ordinary, non-elevated user token" +
+ `${integrity}. Rerun it from a standard-user Windows session; the verifier will not change caller authority.`,
+ );
+ }
+};
+
+/** Observe the native caller token before a Windows browser fixture allocates resources. */
+export const requireOrdinaryWindowsVerifierCaller = async () => {
+ if (process.platform !== "win32") return;
+ let token;
+ try {
+ const { requireWindowsNativeAuthority } =
+ await import("../../dist/windows/WindowsNativeLoader.js");
+ token = requireWindowsNativeAuthority().call("process_caller_token", []);
+ } catch (cause) {
+ throw new Error(
+ "Windows browser verifier could not observe its caller token; use the verified Windows x64 native artifact and rerun from a standard-user session.",
+ { cause },
+ );
+ }
+ assertOrdinaryWindowsVerifierCaller(token);
+};
diff --git a/scripts/verify-browser-dom-destinations.mjs b/scripts/verify-browser-dom-destinations.mjs
index 31b5d1e17..78ee670cb 100644
--- a/scripts/verify-browser-dom-destinations.mjs
+++ b/scripts/verify-browser-dom-destinations.mjs
@@ -6,15 +6,21 @@ import { join } from "node:path";
import { chromium } from "playwright-core";
import { startBrowserVerifierSite } from "./fixtures/browser-verifier-site.mjs";
import { verifyBrowserDomDestinations } from "./lib/browser-dom-destinations-e2e.mjs";
+import { closeRuntimeFixtureResources } from "./lib/browser-runtime-fixture-lifecycle.mjs";
+import { requireOrdinaryWindowsVerifierCaller } from "./lib/windows-ordinary-user-verifier.mjs";
const executable = process.env.REA_BROWSER_EXECUTABLE;
if (!executable)
throw new Error("verify:browser:dom requires REA_BROWSER_EXECUTABLE");
-const profile = await mkdtemp(join(tmpdir(), "rea-browser-dom-"));
-const site = await startBrowserVerifierSite();
+await requireOrdinaryWindowsVerifierCaller();
+let profile;
+let site;
let context;
let report;
+let primaryError;
try {
+ profile = await mkdtemp(join(tmpdir(), "rea-browser-dom-"));
+ site = await startBrowserVerifierSite();
context = await chromium.launchPersistentContext(profile, {
executablePath: executable,
headless: true,
@@ -50,9 +56,15 @@ try {
native_oracle: true,
verified: true,
};
+} catch (cause) {
+ primaryError = cause;
+ throw cause;
} finally {
- await context?.close();
- await site.close();
- await rm(profile, { recursive: true, force: true });
+ const cleanup = [];
+ if (context !== undefined) cleanup.push(() => context.close());
+ if (site !== undefined) cleanup.push(() => site.close());
+ if (profile !== undefined)
+ cleanup.push(() => rm(profile, { recursive: true, force: true }));
+ await closeRuntimeFixtureResources(cleanup, primaryError);
}
process.stdout.write(`${JSON.stringify(report)}\n`);
diff --git a/scripts/verify-browser-modules.mjs b/scripts/verify-browser-modules.mjs
index 23f2f9a76..df195938e 100644
--- a/scripts/verify-browser-modules.mjs
+++ b/scripts/verify-browser-modules.mjs
@@ -2,12 +2,14 @@
import { access } from "node:fs/promises";
import { verifyBrowserModules } from "./lib/browser-module-e2e.mjs";
import { createVerifierRun, completeVerifierRun } from "./lib/verifier-run.mjs";
+import { requireOrdinaryWindowsVerifierCaller } from "./lib/windows-ordinary-user-verifier.mjs";
const executable = process.env.REA_BROWSER_EXECUTABLE;
if (!executable)
throw new Error(
"verify:browser:modules requires REA_BROWSER_EXECUTABLE for caller-supplied Chromium",
);
+await requireOrdinaryWindowsVerifierCaller();
await access(executable);
const run = createVerifierRun();
const proof = await verifyBrowserModules(executable, process.argv[2]);
diff --git a/scripts/verify-browser-network.mjs b/scripts/verify-browser-network.mjs
index f7fa0222b..d7c0200da 100644
--- a/scripts/verify-browser-network.mjs
+++ b/scripts/verify-browser-network.mjs
@@ -2,12 +2,14 @@
import { access } from "node:fs/promises";
import { verifyBrowserNetworkEvidence } from "./lib/browser-network-e2e.mjs";
import { createVerifierRun, completeVerifierRun } from "./lib/verifier-run.mjs";
+import { requireOrdinaryWindowsVerifierCaller } from "./lib/windows-ordinary-user-verifier.mjs";
const executable = process.env.REA_BROWSER_EXECUTABLE;
if (executable === undefined || executable === "")
throw new Error(
"verify:browser:network requires REA_BROWSER_EXECUTABLE pointing to an installed Chrome-family browser",
);
+await requireOrdinaryWindowsVerifierCaller();
await access(executable);
const run = createVerifierRun();
const proof = await verifyBrowserNetworkEvidence(executable, process.argv[2]);
diff --git a/scripts/verify-browser-scripts.mjs b/scripts/verify-browser-scripts.mjs
index 30fba281b..0c5661379 100644
--- a/scripts/verify-browser-scripts.mjs
+++ b/scripts/verify-browser-scripts.mjs
@@ -2,12 +2,14 @@
import { access } from "node:fs/promises";
import { verifyBrowserScriptExport } from "./lib/browser-script-export-e2e.mjs";
import { createVerifierRun, completeVerifierRun } from "./lib/verifier-run.mjs";
+import { requireOrdinaryWindowsVerifierCaller } from "./lib/windows-ordinary-user-verifier.mjs";
const executable = process.env.REA_BROWSER_EXECUTABLE;
if (executable === undefined || executable === "")
throw new Error(
"verify:browser:scripts requires REA_BROWSER_EXECUTABLE pointing to an installed Chrome-family browser",
);
+await requireOrdinaryWindowsVerifierCaller();
await access(executable);
const run = createVerifierRun();
const proof = await verifyBrowserScriptExport(executable, process.argv[2]);
diff --git a/scripts/verify-browser-source-maps.mjs b/scripts/verify-browser-source-maps.mjs
index a8b53e504..a4e7c2a26 100644
--- a/scripts/verify-browser-source-maps.mjs
+++ b/scripts/verify-browser-source-maps.mjs
@@ -4,6 +4,9 @@ import { isAbsolute } from "node:path";
import { verifyBrowserSourceMap } from "./lib/browser-source-map-e2e.mjs";
import { verifyBrowserNestedSourceMaps } from "./lib/browser-nested-source-map-e2e.mjs";
import { createVerifierRun, completeVerifierRun } from "./lib/verifier-run.mjs";
+import { requireOrdinaryWindowsVerifierCaller } from "./lib/windows-ordinary-user-verifier.mjs";
+
+await requireOrdinaryWindowsVerifierCaller();
const executable = process.env.REA_BROWSER_EXECUTABLE;
if (!executable || !isAbsolute(executable))
throw new Error(
diff --git a/scripts/verify-package-setup.d.mts b/scripts/verify-package-setup.d.mts
index 2c7244291..d6f0ce53e 100644
--- a/scripts/verify-package-setup.d.mts
+++ b/scripts/verify-package-setup.d.mts
@@ -4,3 +4,6 @@ export function assertClientConfig(
configPath: string,
original: Uint8Array,
): Promise;
+
+/** Return true only when stty output positively reports canonical input and echo. */
+export function terminalModesRestored(termios: unknown): boolean;
diff --git a/scripts/verify-package-setup.mjs b/scripts/verify-package-setup.mjs
index 44f28c142..ad23548cb 100644
--- a/scripts/verify-package-setup.mjs
+++ b/scripts/verify-package-setup.mjs
@@ -22,6 +22,12 @@ import {
import { parse as parseJsonc } from "jsonc-parser";
import { skillReferenceIssues } from "./lib/docs-facts.mjs";
+export const terminalModesRestored = (termios) => {
+ if (typeof termios !== "string") return false;
+ const modes = new Set(termios.trim().split(/\s+/u));
+ return modes.has("icanon") && modes.has("echo");
+};
+
const OPENCODE_ORIGINAL = `{
// OpenCode preferences must survive setup.
"model": "provider/model",
@@ -131,8 +137,7 @@ const verifyInteractiveSetup = async ({
childResult?.status !== 0 ||
!output.includes("\u001b[?25h") ||
(process.platform !== "win32" &&
- (!childResult.termios?.includes("icanon") ||
- !childResult.termios?.includes("echo"))) ||
+ !terminalModesRestored(childResult.termios)) ||
!output.includes("No changes were made.")
) {
finish(
diff --git a/scripts/verify-real-browser.mjs b/scripts/verify-real-browser.mjs
index 3f793d82c..28c53067a 100644
--- a/scripts/verify-real-browser.mjs
+++ b/scripts/verify-real-browser.mjs
@@ -39,6 +39,8 @@ import {
verifyScenarioFailureEvidence,
} from "./lib/browser-scenario-verifier.mjs";
import { completeVerifierRun, createVerifierRun } from "./lib/verifier-run.mjs";
+import { closeRuntimeFixtureResources } from "./lib/browser-runtime-fixture-lifecycle.mjs";
+import { requireOrdinaryWindowsVerifierCaller } from "./lib/windows-ordinary-user-verifier.mjs";
import { verifyLargeScreenshotE2e } from "./lib/browser-screenshot-e2e.mjs";
import { verifyPopupEventCoverage } from "./lib/browser-popup-e2e.mjs";
import { verifyBrowserNetworkEvidence } from "./lib/browser-network-e2e.mjs";
@@ -58,13 +60,17 @@ process.env.REA_BROWSER_VERIFIER_SECRET = SCENARIO_SECRET_VALUE;
process.env.REA_BROWSER_VERIFIER_URL = SCENARIO_URL_SECRET_VALUE;
const verifierRun = createVerifierRun();
+await requireOrdinaryWindowsVerifierCaller();
const executable = await browserExecutable();
-const profile = await mkdtemp(join(tmpdir(), "rea-real-browser-"));
-const site = await startBrowserVerifierSite();
+let profile;
+let site;
let browser;
let pageProxy;
let report;
+let verificationError;
try {
+ profile = await mkdtemp(join(tmpdir(), "rea-real-browser-"));
+ site = await startBrowserVerifierSite();
browser = spawn(
executable,
[
@@ -409,19 +415,39 @@ try {
scenarioServiceWorkers,
verified: true,
};
+} catch (cause) {
+ verificationError = cause;
+ throw cause;
} finally {
- process.stderr.write("Browser verifier cleanup: closing page proxy\n");
- if (pageProxy !== undefined) await pageProxy.close();
- process.stderr.write("Browser verifier cleanup: stopping owned Chrome\n");
- if (browser !== undefined) await stopProcess(browser);
- process.stderr.write("Browser verifier cleanup: closing fixture site\n");
- await site.close();
- await rm(profile, {
- recursive: true,
- force: true,
- maxRetries: 10,
- retryDelay: 100,
- });
+ const cleanup = [];
+ if (pageProxy !== undefined) {
+ cleanup.push(async () => {
+ process.stderr.write("Browser verifier cleanup: closing page proxy\n");
+ await pageProxy.close();
+ });
+ }
+ if (browser !== undefined) {
+ cleanup.push(async () => {
+ process.stderr.write("Browser verifier cleanup: stopping owned Chrome\n");
+ await stopProcess(browser);
+ });
+ }
+ if (site !== undefined) {
+ cleanup.push(async () => {
+ process.stderr.write("Browser verifier cleanup: closing fixture site\n");
+ await site.close();
+ });
+ }
+ if (profile !== undefined)
+ cleanup.push(() =>
+ rm(profile, {
+ recursive: true,
+ force: true,
+ maxRetries: 10,
+ retryDelay: 100,
+ }),
+ );
+ await closeRuntimeFixtureResources(cleanup, verificationError);
}
process.stdout.write(
`${JSON.stringify({
diff --git a/scripts/verify-real-ghidra-dos.mjs b/scripts/verify-real-ghidra-dos.mjs
index 50a014d0a..b212a018d 100644
--- a/scripts/verify-real-ghidra-dos.mjs
+++ b/scripts/verify-real-ghidra-dos.mjs
@@ -24,7 +24,11 @@ import {
} from "../dist/domain/hopperValues.js";
import { inspectGhidraInstallation } from "../dist/ghidra/GhidraInstallation.js";
import { buildDosMzFixture } from "../tests/conformance/ghidra/dos-mz-fixture.mjs";
-import { createVerifierRun, completeVerifierRun } from "./lib/verifier-run.mjs";
+import {
+ assertVerifierCleanupComplete,
+ createVerifierRun,
+ completeVerifierRun,
+} from "./lib/verifier-run.mjs";
import { verifyGhidraAddressBoundaries } from "./lib/real-ghidra-address-boundaries.mjs";
// This lane intentionally has no game paths, binary seeds or compiler dependency.
@@ -479,12 +483,7 @@ try {
}
assert.ok(report, "No DOS proof report was produced");
const verifierRun = await completeVerifierRun(run);
-if (verifierRun.process_lineage.status === "verified")
- assert.deepEqual(
- verifierRun.process_lineage.descendants,
- [],
- "Owned descendants survived verifier cleanup",
- );
+assertVerifierCleanupComplete(verifierRun.process_lineage);
process.stdout.write(
`${JSON.stringify({ verifier_run: verifierRun, ...report, cleanup: "complete" })}\n`,
);
diff --git a/scripts/verify-wasm-artifact.mjs b/scripts/verify-wasm-artifact.mjs
index 5123d3400..c05952118 100644
--- a/scripts/verify-wasm-artifact.mjs
+++ b/scripts/verify-wasm-artifact.mjs
@@ -2,8 +2,16 @@
import assert from "node:assert/strict";
import { execFile } from "node:child_process";
import { createHash } from "node:crypto";
-import { mkdir, readFile, writeFile, readdir } from "node:fs/promises";
+import {
+ mkdir,
+ mkdtemp,
+ readFile,
+ readdir,
+ rm,
+ writeFile,
+} from "node:fs/promises";
import { isAbsolute, join } from "node:path";
+import { tmpdir } from "node:os";
import { fileURLToPath } from "node:url";
import { promisify } from "node:util";
import { Client } from "@modelcontextprotocol/client";
@@ -51,11 +59,32 @@ const tool = (name, args, cwd) =>
const sha256 = (value) => createHash("sha256").update(value).digest("hex");
const run = createVerifierRun();
const root = await PrivateRuntimeRoot.create({ prefix: "rea-wabt-verifier-" });
+// Keep provider scratch outside the leased private input root. On Windows the
+// root's retained DELETE handle blocks child temp creation beneath that root.
+let childTempRoot;
+try {
+ childTempRoot = await mkdtemp(join(tmpdir(), "rea-wabt-child-temp-"));
+} catch (cause) {
+ try {
+ await root.close();
+ } catch (cleanupCause) {
+ throw new AggregateError(
+ [cause, cleanupCause],
+ "Could not allocate verifier temp space or release its private root.",
+ );
+ }
+ throw cause;
+}
const client = new Client({ name: "wabt-artifact-verifier", version: "1" });
const transport = new StdioClientTransport({
command: process.execPath,
args: [entrypoint, "mcp"],
- env: { ...environment, TMPDIR: root.path, TMP: root.path, TEMP: root.path },
+ env: {
+ ...environment,
+ TMPDIR: childTempRoot,
+ TMP: childTempRoot,
+ TEMP: childTempRoot,
+ },
stderr: "pipe",
});
let cases = 0;
@@ -95,9 +124,9 @@ try {
{
env: {
...environment,
- TMPDIR: root.path,
- TMP: root.path,
- TEMP: root.path,
+ TMPDIR: childTempRoot,
+ TMP: childTempRoot,
+ TEMP: childTempRoot,
},
timeout: 120_000,
maxBuffer: 64 * 1024 * 1024,
@@ -388,13 +417,26 @@ try {
}
try {
assert.ok(
- !(await readdir(root.path)).some((name) => name.startsWith("rea-wabt-")),
+ !(await readdir(childTempRoot)).some((name) =>
+ name.startsWith("rea-wabt-"),
+ ),
"Provider workspace leaked",
);
+} catch (cause) {
+ failures.push(cause);
+}
+// Each directory is an independent owner. Attempt every cleanup even if a
+// residue assertion or another owner's close fails, retaining every error.
+try {
await root.close();
} catch (cause) {
failures.push(cause);
}
+try {
+ await rm(childTempRoot, { recursive: true, force: true });
+} catch (cause) {
+ failures.push(cause);
+}
if (failures.length > 0)
throw new AggregateError(failures, "WABT real-tool verification failed.");
console.log(
diff --git a/src/application/analysisView/AnalysisViewService.test.ts b/src/application/analysisView/AnalysisViewService.test.ts
index 10258d3f9..b4421f80a 100644
--- a/src/application/analysisView/AnalysisViewService.test.ts
+++ b/src/application/analysisView/AnalysisViewService.test.ts
@@ -24,7 +24,6 @@ import { EvidenceIntegrityError } from "../../domain/evidenceErrors.js";
import { err, ok } from "../../domain/result.js";
import { EvidenceLedger } from "../investigation/EvidenceLedger.js";
import { WEB_NETWORK_CAPTURE_LIMITS } from "../../domain/webNetworkCapture.js";
-import { inspectAnalysisViewInputSchema } from "../../domain/analysisView/analysisView.js";
it.each(["/fixtures/unknown.exe", ""])(
"preserves recorded empty native identity fields: path=%j",
@@ -433,26 +432,39 @@ it("refuses an object-dense borrowed capture before making a full schema clone",
expect(ledger.forAnalysis(parent.evidence_id)).toBe(borrowed);
});
-it("borrows inline Evidence until admission without invoking nested accessors", () => {
- let accessed = false;
- const evidence = {
- get normalized_result() {
- accessed = true;
- throw new Error("Evidence must be admitted before parsing");
- },
- };
- const input = {
- source: { kind: "inline", evidence },
- view: { kind: "api-surface" },
- };
- const parsed = inspectAnalysisViewInputSchema.parse(input);
- if (parsed.source.kind !== "inline") throw new Error("Expected inline input");
- expect(parsed.source.evidence).toBe(evidence);
- expect(inspectAnalysisView(input)).toMatchObject({
- ok: false,
- error: { _tag: "AnalysisInputError" },
- });
- expect(accessed).toBe(false);
+it("rejects accessor-backed inline Evidence before all view projections", () => {
+ const views = [
+ { kind: "summary" },
+ { kind: "capture" },
+ { kind: "api-surface" },
+ ] as const;
+ for (const view of views) {
+ let accessed = false;
+ const evidence = {
+ get normalized_result() {
+ accessed = true;
+ throw new Error("Evidence accessor must not be invoked");
+ },
+ };
+ const result = inspectAnalysisView({
+ source: { kind: "inline", evidence },
+ view,
+ });
+ expect(result).toMatchObject({
+ ok: false,
+ error: { _tag: "AnalysisInputError" },
+ });
+ expect(accessed).toBe(false);
+ }
+
+ const parent = analysisViewCaptureEvidence();
+ for (const view of views)
+ expect(
+ inspectAnalysisView({
+ source: { kind: "inline", evidence: parent },
+ view,
+ }).ok,
+ ).toBe(true);
});
it("keeps inline-envelope admission live alongside capture validation and grouping", () => {
diff --git a/src/application/analysisView/AnalysisViewService.ts b/src/application/analysisView/AnalysisViewService.ts
index f12033ee0..4e68dd868 100644
--- a/src/application/analysisView/AnalysisViewService.ts
+++ b/src/application/analysisView/AnalysisViewService.ts
@@ -5,7 +5,10 @@ import type { EvidenceLookup } from "../EvidenceInputResolver.js";
import { resolveEvidenceInput } from "../EvidenceInputResolver.js";
import type { EvidenceWriter } from "../investigation/InvestigationRecordPort.js";
import type { AnalysisError } from "../../domain/analysisErrorBase.js";
-import { AnalysisCapabilityUnavailableError } from "../../domain/analysisErrorCore.js";
+import {
+ AnalysisCapabilityUnavailableError,
+ AnalysisInputError,
+} from "../../domain/analysisErrorCore.js";
import { analysisInputErrorFromIssues } from "../../domain/inputIssueProjection.js";
import { EvidenceIntegrityError } from "../../domain/evidenceErrors.js";
import {
@@ -159,6 +162,18 @@ const resolveAnalysisViewSource = (
): Result => {
if (source.kind === "retained-evidence")
return resolveEvidenceInput(source, lookup);
+ const invalidDataPath = inlineEvidenceInvalidDataPath(source.evidence);
+ if (invalidDataPath !== undefined)
+ return err(
+ new AnalysisInputError(INSPECT_ANALYSIS_VIEW_OPERATION, undefined, [
+ {
+ path: ["source", "evidence", ...invalidDataPath],
+ reason: "invalid_type",
+ message:
+ "Inline Evidence must contain plain JSON data properties without accessors or cycles.",
+ },
+ ]),
+ );
try {
return ok(parseEvidence(source.evidence));
} catch (cause: unknown) {
@@ -185,6 +200,53 @@ const resolveAnalysisViewSource = (
}
};
+/** Reject non-JSON object behavior before Zod reads caller-owned Evidence. */
+const inlineEvidenceInvalidDataPath = (
+ root: unknown,
+): readonly (string | number)[] | undefined => {
+ const active = new Set