# Scanner Runtime Evidence (Node) ## Purpose Optional, air-gap-friendly runtime capture for Node workloads to enrich dependency graphs with observed imports/loads. Produces append-only NDJSON that the Node analyzer ingests as `node:runtime-*` records. ## Capture hooks - **CJS**: `runtime-hooks/runtime-require-hook.js` - Usage: `SCANNER_NODE_RUNTIME_OUT= SCANNER_NODE_ROOT= node -r ./runtime-require-hook.js app.js` - **ESM**: `runtime-hooks/runtime-esm-loader.mjs` - Usage: `SCANNER_NODE_RUNTIME_OUT= SCANNER_NODE_ROOT= node --experimental-loader=./runtime-esm-loader.mjs app.mjs` ## Output format (NDJSON) Each line is a JSON object: - `type`: `edge` | `component` - `from` / `to`: module specifiers (scrubbed relative to `SCANNER_NODE_ROOT` when possible) - `reason`: e.g., `runtime-import`, `runtime-require`, `runtime-load` - `loaderId`: arbitrary string; hashed to SHA-256 during ingestion - `path`: component path for `component` records ## Ingestion rules - File name defaults to `node-runtime-evidence.ndjson` in the scan root; override with `SCANNER_NODE_RUNTIME_EVIDENCE`. - Paths are scrubbed relative to the analyzer `rootPath`; absolute paths outside root remain absolute. - Loader IDs are SHA-256 hashed before storage (`loaderId.sha256`). - Evidence is tagged as `node:runtime-edge` or `node:runtime-component` with derived evidence from the reason/locators. ## Determinism & safety - Append-only writes; no network access. - Stable hashing, stable ordering during ingestion (sorted by `componentKey`). - Path scrubbing prevents leakage of host-specific prefixes when root-relative. ## When to use - Debugging dynamic imports/require resolutions. - Environments with heavy plugin loading where static analysis is insufficient.