Metadata-Version: 2.4
Name: whyq
Version: 0.1.0
Summary: Translate any security/IaC tool's output file into human language — offline, no cluster, one grammar across tools
Author: Keita Higaki
License: MIT
Project-URL: Homepage, https://github.com/higakikeita/whyq
Project-URL: Issues, https://github.com/higakikeita/whyq/issues
Keywords: security,trivy,falco,explain,iac,cli
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Security
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# whyq

[![CI](https://github.com/higakikeita/whyq/actions/workflows/ci.yml/badge.svg)](https://github.com/higakikeita/whyq/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Python 3.9+](https://img.shields.io/badge/python-3.9%2B-blue.svg)](pyproject.toml)
[![Zero dependencies](https://img.shields.io/badge/dependencies-0-brightgreen.svg)](whyq.py)

> **The artifact translator.** You already ran the scanner — whyq explains the file it left behind, offline, one grammar across every tool.

`whyq explain <file>` reads a security/IaC tool's **output file** — `trivy.json` and `falco.json` today, plan JSON next — and returns six things for every finding:

| 何が (what) | なぜ (why) | 危険度 (severity) | まず確認 (check) | 修正 (fix) | 参考 (refs) |
|---|---|---|---|---|---|

```bash
$ trivy image --format json -o scan.json app:latest
$ whyq explain scan.json
```

```
■ openssl: possible denial of service in X.509 name checks  [HIGH]  (CVE-2024-6119)
  何が:   libssl3 — vulnerability
  なぜ:   A known vulnerability affects libssl3 3.0.2-0ubuntu1.15. A fixed version
          (3.0.2-0ubuntu1.18) is available, so this is actionable now.
  確認:   Confirm libssl3 is actually reachable in your runtime path, and check
          whether the installed version is really in use.
  修正:   remedify <scan.json>   (OS-package remediation is remedify's job)
  参考:   https://avd.aquasec.com/nvd/cve-2024-6119
```

## Where whyq sits: detect → **understand** → fix

whyq is the *understanding* layer of a three-part story about **contextualizing detection**:

```
detect ──────────►  understand  ──────────►  fix
(tfdrift, trivy,     (whyq)                   (remedify)
 falco, sysdig…)     what/why/severity        distro-aware
                     /check/fix/refs          remediation commands
```

- **[tfdrift-falco](https://github.com/higakikeita/tfdrift-falco)** and other scanners *detect*.
- **whyq** turns their raw output into something a human can act on.
- **[remedify](https://github.com/higakikeita/remedify)** owns the last mile — the exact, OS-specific fix command.

whyq deliberately does **not** re-implement OS-package remediation. When a finding is an OS-package vulnerability, its `修正` field hands off to remedify. whyq stays the cross-tool *understanding* layer; remedify owns vuln→fix. The `--format json` output is shaped so remedify (and CI) can consume it directly.

## Why not k8sgpt / HolmesGPT?

The space isn't empty, but the wedge is real and narrow:

- **k8sgpt** reads a **live Kubernetes cluster**. It can't read a file you already have.
- **HolmesGPT** **connects** to your alert sources and investigates autonomously — a heavy agent.
- **whyq** reads the **artifact already sitting on your disk**. No cluster, no connection, no SaaS — and **one grammar across tools** (trivy → falco → plan JSON → …), not a single domain.

"Light / local / no-SaaS / brew" is not the flag here — k8sgpt already owns that. whyq's flag is one thing: **artifact translator, cross-tool.**

## Quick start

```bash
# zero-install (stdlib only, no dependencies)
git clone https://github.com/higakikeita/whyq && cd whyq
python3 whyq.py explain examples/trivy.json

# machine-readable (remedify-ready / CI)
python3 whyq.py explain scan.json --format json
python3 whyq.py explain scan.json --min-severity HIGH
```

## LLM: BYO-key, and honest about it

Turning a finding into good prose (`なぜ` / `まず確認`) benefits from an LLM — so whyq will **not** claim "no SaaS" unconditionally. Instead:

- **Default is offline.** With no flag, whyq uses deterministic templates. **Nothing leaves your machine.**
- **Opt in explicitly** with your own key/model — data goes only where you point it:

```bash
whyq explain scan.json --llm anthropic          # uses $ANTHROPIC_API_KEY
whyq explain scan.json --llm ollama:llama3.2     # fully local, no key
```

The deterministic half — parse, severity, fix command, references — never touches the LLM and is regression-tested. Only the prose is model-generated. That keeps the audit trail intact ("the deterministic tool computes, the AI explains").

## Supported inputs

| Tool | Status |
|---|---|
| Trivy JSON (vulnerabilities · misconfigurations · secrets) | ✅ |
| Falco JSON / JSONL (runtime events; MITRE ATT&CK tags → refs) | ✅ |
| Terraform plan JSON | planned |

A scan finding and a runtime event — two different tools, two different domains — land in the **same normalized shape** and flow through the **same six-field output**. That is the cross-tool wedge, not a slogan:

```bash
whyq explain trivy.json     # vulnerabilities & misconfig
whyq explain falco.json     # runtime events (JSONL, as Falco writes it)
```

Adding a format is a parser plus a detector — the normalized finding and every output path stay the same.

## Development

```bash
python3 -m unittest discover tests -v
```

The deterministic core is pinned by regression tests; the LLM layer is mocked. See [`tests/`](tests/).

## License

MIT — see [LICENSE](LICENSE).
