# Garak Report Viewer UI

A modern, lightweight frontend interface for exploring and visualizing vulnerability evaluation results from Garak `.report.jsonl` files. Built with **Vite + React + TypeScript**, this UI is designed to work directly with Garak’s `digest` outputs and enables interactive browsing, filtering, and comparison of model evaluation data.

---

## 🧩 Features

- ✅ **Digest-first design** — Loads `entry_type: "digest"` entries directly from Garak's analysis pipeline
- 🕵️ **Report overview** — Displays summaries of each report run from `index.json`
- 🌐 **Client-side bundle** — Dynamically pulls data via `window.reportsData` from `reports.js`
- 📊 **Interactive charts** — Visualizes module scores, probe metrics, detector performance, and z-scores
- 🔍 **Drilldown support** — Navigate from modules → probes → detectors, with severity indicators
- 📁 **Zero-backend deploy** — Just serve `dist/` folder + reports via static hosting
- ⚡ Built with **Vite** for fast dev startup and HMR
- Charts powered by **Apache ECharts** (`echarts-for-react` wrapper)
- Styles use CSS-in-JS or plain modules
- All state handled via React hooks

---

## 🚀 Quick Start

### 1. Clone and install dependencies

```bash
git clone https://github.com/NVIDIA/garak-report.git
cd garak-report
yarn install
# or
npm install
```

### 2. Start the dev server

```bash
yarn dev
# or
npm run dev
```

Navigate to [http://localhost:3000](http://localhost:3000) to view the interface.

---

## 📦 Build and Deploy

To generate a production build:

```bash
yarn build
# or
npm run build
```

Then deploy the `dist/` folder to any static hosting provider:

- GitHub Pages
- Netlify
- S3 + CloudFront
- Vercel

---

## 📂 Reports Folder

Garak UI expects the following files inside `/public/reports/`:

| File             | Purpose                                    |
| ---------------- | ------------------------------------------ |
| `*.report.jsonl` | Raw Garak reports (can be archived)        |
| `digest-*.json`  | Compressed, single-object digest reports   |
| `index.json`     | Index of recent runs with filename + meta  |
| `reports.js`     | Autogenerated `window.reportsData = [...]` |

To generate these:

```bash
python -m garak.analyze.report_digest --input your.report.jsonl --output public/reports/
```

Then rerun the index/digest step:

```bash
python scripts/build_report_index.py
```

(You may customize this as needed for your CI/CD flow.)

---

### 🔄 How `reports.js` Works in Local Development

`src/pages/Report.tsx` first tries to load build-time data that is injected by the Vite replacer (`__GARAK_INSERT_HERE__`).  In **production builds** this placeholder is replaced at build time with a JSON array of digest objects, so everything is bundled.

During **development** the placeholder is left empty, so the code falls back to reading

```ts
window.reportsData
```

If the dev server finds `public/reports/reports.js` it is served automatically and executed by the browser, assigning `window.reportsData = [...]` before React renders.  This lets you:

1. Drop any digest JSON (or a hand-crafted minimal sample) into `public/reports/`.
2. Generate `reports.js` by running Garak’s helper:

   ```bash
   python -m garak.analyze.aggregate_reports --input public/reports/digest*.json \
          --output public/reports/reports.js
   ```

3. Start the dev server (`yarn dev`) – the UI will pick up that global array and render immediately.

No proxy or API server is needed; just regenerate `reports.js` whenever you’ve produced new digests and refresh the browser.

---

## 🛠️ Project Structure

```
.
├── public/
│   ├── reports/               # All Garak reports and digests live here
│   ├── reports.js             # window.reportsData = [...] (generated)
│   ├── index.html             # Entry point
├── src/
│   ├── App.tsx                # Root React component
│   ├── pages/                 # Page-level UI views
│   ├── components/            # Reusable UI components (charts, tables, etc.)
│   ├── hooks/                 # Custom React hooks
│   ├── utils/                 # Report parsing, formatting, normalization
│   ├── types.ts               # Shared type definitions for reports
├── vite.config.ts             # Vite configuration
├── tsconfig.json              # TypeScript config
```

---

## 🧭 How It Works (and How to Collaborate)

This UI is designed to work hand-in-hand with [Garak](https://github.com/NVIDIA/garak), but it also supports fully standalone development. You can choose either of the following workflows depending on your goals.

---

### 🅰️ Option 1: Develop Independently (Standalone Mode)

The UI can be developed and tested without touching Garak at all. Just drop reports into the local `public/reports/` folder:

#### Steps

1. Generate a report from Garak:

   ```bash
   garak --generator hf-chat --model gpt2 --output results.report.jsonl
   ```

2. Create digest artifacts:

   ```bash
   python -m garak.analyze.report_digest results.report.jsonl --output public/reports/
   ```

3. Start the UI:
   ```bash
   yarn dev
   # or
   yarn build
   ```

✅ Great for UI-only contributors or front-end prototyping.

---

### 🅱️ Option 2: Integrated With Garak (Symlinked Dev Flow)

This method uses the static viewer path that already exists in Garak:

```
garak/garak/analyze/ui/
```

#### Steps

1. Clone and build the UI:

   ```bash
   git clone https://github.com/NVIDIA/garak-report.git
   cd garak-report
   yarn install
   yarn build
   ```

2. Replace Garak's static UI with a symlink:

   ```bash
   cd /path/to/garak
   rm -rf garak/garak/analyze/ui/index.html garak/garak/analyze/ui/assets
   ln -sfn /full/path/to/garak-report/dist/index.html garak/garak/analyze/ui/index.html
   ln -sfn /full/path/to/garak-report/dist/assets     garak/garak/analyze/ui/assets
   ```

3. Generate reports:

   ```bash
   python -m garak.analyze.report_digest results.report.jsonl --output garak/garak/analyze/ui/reports/
   ```

4. Open locally:
   ```
   file://$(pwd)/garak/garak/analyze/ui/index.html
   ```
   or
   ```bash
   cd garak/garak/analyze/ui
   python -m http.server 8080
   ```

✅ Ideal for full-stack development or contributors working on Garak core and the frontend in parallel.

---

## 🧪 Developer Notes

- Requires **Node.js 18+** (Node 20 LTS tested)
- Uses **Vite** for local dev, **TypeScript** for safety
- Charts use **Recharts**
- Styles use CSS-in-JS or plain modules
- All state handled via React hooks

### Optional: Set up pre-commit hooks

The repo uses [pre-commit](https://pre-commit.com/) for Python hooks. To add garak-report checks, append the following to `.pre-commit-config.yaml`:

```yaml
  - repo: local
    hooks:
      - id: garak-report-lint
        name: garak-report lint
        entry: bash -c 'cd garak-report && yarn lint --max-warnings=0'
        language: system
        files: ^garak-report/.*\.(ts|tsx)$
        pass_filenames: false
      - id: garak-report-typecheck
        name: garak-report typecheck
        entry: bash -c 'cd garak-report && yarn check'
        language: system
        files: ^garak-report/.*\.(ts|tsx)$
        pass_filenames: false
      - id: garak-report-test
        name: garak-report test
        entry: bash -c 'cd garak-report && yarn test'
        language: system
        files: ^garak-report/
        pass_filenames: false
```

Then install/update the hooks:

```bash
pre-commit install
```

---

## ✅ Testing & Coverage

This repo is configured with **Vitest** and V8 coverage reporting.

```bash
yarn test                # run once
yarn test --watch        # watch mode

# The default script enforces 100 % statements/lines/functions
# and prints a coverage table in the console.
```

CI (or your pre-commit hook) can simply invoke `yarn test`; the build will fail if coverage ever drops below 100 %.

---

## 🏃 Running Commands from the Monorepo Root

The UI lives in `garak-report/`, while the Python core lives in the repo root.  If you prefer to stay at the root you can delegate Yarn commands:

```bash
# one-off
yarn --cwd garak-report dev

# or create a root-level package.json with convenience scripts:
{
  "name": "garak-root",
  "private": true,
  "scripts": {
    "ui:dev": "yarn --cwd garak-report dev",
    "ui:build": "yarn --cwd garak-report build",
    "ui:test": "yarn --cwd garak-report test"
  }
}
```

---

# one-off
yarn --cwd garak-report dev

# or create a root-level package.json with convenience scripts:
{
  "name": "garak-root",
  "private": true,
  "scripts": {
    "ui:dev": "yarn --cwd garak-report dev",
    "ui:build": "yarn --cwd garak-report build",
    "ui:test": "yarn --cwd garak-report test"
  }
}
```

---

## 📄 License

This project is licensed under the [Apache License 2.0](./LICENSE.txt).  
© 2023–2025 NVIDIA Corporation
