# EventLens-Public EventLens is a local/self-hosted Windows Event Log incident reconstruction tool. It turns a real `.evtx` export into normalized evidence, deterministic incident windows and a readable timeline that helps answer: **what happened, in what order, and which records are probably related?** ![EventLens demo overview](docs/assets/eventlens-demo-overview.png) ## What it solves Windows event logs are detailed but difficult to scan during an incident. EventLens provides a bounded workflow: ```text EVTX upload -> size/resource gate -> normalize -> deterministic correlation -> timeline/evidence inspector -> redacted export ``` It preserves source evidence, makes every grouping explainable, and keeps the analysis local. ## Product boundary EventLens is deliberately not a SIEM, a full Windows Event Viewer replacement, a cloud platform or an AI product. It has no database, authentication, telemetry, background worker, cloud account or LLM requirement. It focuses on one compact job: reconstructing a bounded incident story from Windows event records. ## v1.0.6 capabilities - Parses real EVTX in memory with the Rust-backed `evtx` engine. - Enforces a 50 MiB file cap plus a receive-level request cap, 100,000-event cap, cooperative 8-second parse budget and bounded normalized output. - Reports `complete`, `partial` or `failed` parser status with stable issue codes, retained/skipped metrics and export metadata. - Normalizes System, EventData and UserData into a stable evidence contract; unreliable timestamps remain explicit and are never converted to epoch evidence. - Correlates provider/channel-scoped startup, shutdown, service, DNS, authentication and crash patterns using stable rule IDs, incident IDs and evidence event IDs. - Keeps unmatched warning/error evidence visible and compresses repeated signatures without deleting source events. - Supports drag/drop, search, category/level/provider filters, informational-noise suppression, incident focus and ±1/5/15/60-minute evidence windows. - Shows the rule, reason, time window and exact evidence IDs behind each incident. - Exports semantically equivalent JSON and Markdown in the browser. Redaction is enabled by default and previews host, identity, e-mail, IP, path and source-name replacement counts before export. - Uses `no-store` responses, security headers, bounded parse concurrency, sanitized source names and no intentional upload persistence. - Virtualizes large timelines so a 100,000-event analysis does not create 100,000 DOM rows. - Includes a deterministic demo fixture plus a pinned-hash public real-EVTX qualification fixture in CI and Playwright. - Provides five functional workspaces over the same in-memory analysis: Analysis overview, Timeline investigation, Hunting facets, Reports/export and local-only Settings. - Preserves workspace navigation and browser hash history without persisting event data; each workspace has an explicit empty state when no analysis is loaded. - Uses a responsive, keyboard-accessible shell with shared event filters, a virtualized timeline and an evidence inspector that remains available from Hunting results. - Ships one local, canonical evidence-lens mark across the top bar, browser favicon, touch/app icons and web manifest; it makes no network request and carries no tracking. - Keeps investigation orientation visible across Analysis, Timeline, Hunting and Reports with a compact source/completeness/evidence context strip and export-readiness summary. - Gives the existing browser-local preferences a dedicated, keyboard-accessible Settings workspace: native radio-backed option cards, a semantic export-redaction switch, explicit autosave feedback, a privacy boundary and a one-click preference reset. - Keeps source identity in one shared context strip, promotes parser completeness/skipped-record metrics in Analysis and reserves first-use guidance for the deterministic demo. ## Privacy and security Event logs can contain usernames, hostnames, IP addresses, e-mail addresses, executable paths and application-specific data. EventLens: - processes uploads only for the current request and closes the multipart handle; - never renders raw XML as markup and escapes untrusted values through React rendering; - bounds input size, parser records, fields, strings, normalized output and parse time; - bounds request bytes independently of `Content-Length` and admits only a small number of concurrent parses; - does not log event contents or write an application database; - previews best-effort redaction of hosts, identities (including domain accounts, SIDs and machine accounts), e-mails, IPv4/IPv6, Windows/UNC paths and source filenames before export. Redaction is a privacy aid, not a formal DLP engine. Review an export before sharing it. See [SECURITY.md](SECURITY.md) and [docs/PRIVACY.md](docs/PRIVACY.md). ## Portfolio walkthrough 1. Open the deployed instance or start EventLens locally. 2. Select **Load demo** for a deterministic six-event walkthrough. 3. Review the source/completeness summary in **Analysis** and select an incident. 4. Investigate the linked evidence in **Timeline** with search, facets, focus and time windows. 5. Use **Hunting** for combined event-ID, provider, category, level, host and incident-membership searches. 6. Review the redaction preview and download JSON or Markdown from **Reports**. 7. Adjust UTC/local timestamps, density and default local preferences in **Settings**. ![Redaction and export preview](docs/assets/eventlens-redaction-export.png) ## Run locally Backend (locked dependencies): ```bash cd backend python -m pip install uv==0.10.0 python -m uv sync --locked --extra dev python -m uv run --locked --extra dev uvicorn app.main:app --reload --port 8000 ``` Frontend: ```bash cd frontend npm ci npm test npm run lint npm run build npm run dev ``` The development UI uses `http://127.0.0.1:8000` for the API. Set `VITE_API_BASE_URL` when the API runs elsewhere. In a production image the UI and API are same-origin. ## Docker ```bash docker compose up --build ``` Open [http://localhost:1252](http://localhost:1252). The production image uses digest-pinned base images, `npm ci`, `backend/uv.lock`, a non-root runtime user, dropped Linux capabilities, a read-only root filesystem and a bounded `/tmp` tmpfs. The health endpoint is [http://localhost:1252/health](http://localhost:1252/health); its `revision` is the exact injected build SHA (`local` for an unlabelled development build). For an Unraid DockerMan-managed Compose deployment, the compose metadata publishes the WebUI URL and serves the durable canonical icon locally at `/eventlens-icon-512.png` through `net.unraid.docker.webui` and `net.unraid.docker.icon`. A broker-managed deployment must preserve those service labels for DockerMan to import them; EventLens does not claim DockerMan lifecycle ownership. ## Analyze your first event log Start with the deterministic demo to learn the timeline, filters and report controls without uploading incident data. For a real investigation, load an authorized EVTX file, inspect the parser's completion status, narrow the time window and review the original evidence behind a correlation before exporting a report. An empty filtered timeline does not establish that nothing happened. Check the selected interval, event filters and parse/truncation status. Review redacted exports before sharing them: best-effort redaction is not a guarantee that every identifying value has been removed. ## Validation The release gates are reproducible from a clean checkout: ```bash cd backend python -m uv sync --locked --extra dev python -m uv run --locked --extra dev pytest -q -W error::DeprecationWarning python -m uv run --locked --extra dev ruff check . python -m uv run --locked --extra dev pip-audit --strict cd ../frontend npm ci npm test npm run lint npm run build npx playwright install chromium npm run test:e2e npm audit --audit-level=moderate ``` The private canonical repository maintains its own validation and deployment workflows. This public snapshot includes the application and reproducible tests; it does not include private infrastructure automation or deployment evidence. ## Deployment and access Compose publishes port 1252 on all host interfaces. For local use, change the mapping to `127.0.0.1:1252:8000`. There is no built-in authentication; use network isolation and an authenticated HTTPS reverse proxy before allowing other users to upload sensitive evidence. Configure the build revision via `GITEA_COMMIT_SHA` when reproducible deployment identity is needed. The screenshots show the deterministic bundled demo, not a real incident or an uploaded customer log. ## Limitations - Correlation describes temporal/semantic relationships supported by evidence; it does not prove causality. - Rules are intentionally small and Windows-focused. Custom rules, hunting queries, alerting and retention are outside the product boundary. - The EVTX parser and browser analysis are bounded for safety; partial parses surface issues instead of pretending completeness. - Redaction is best-effort and application-specific values may still contain sensitive data. - A real Windows EVTX file is required for parser analysis; the bundled demo intentionally bypasses only the raw parser step. ## License No project-wide license file is included in this repository. Publishing the source does not grant an open-source license. Normal copyright restrictions and the applicable terms for individual third-party components remain in effect. ## Public source distribution The private canonical repository remains the development source. Reviewed snapshots are synchronized automatically to `EventLens-Public` after changes reach its default branch. The public export contains application source, dependency locks, generic deployment examples and selected demo visuals; private Git history, infrastructure workflows and operational records are excluded. `PUBLIC_SOURCE_MANIFEST.json` identifies the exact source revision and file hashes.