secreport 0.1.1

Output formatters for security findings — JSON, JSONL, SARIF, Markdown, Text
Documentation
# secreport

[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) [![Tests](https://img.shields.io/badge/tests-21%20passing-brightgreen.svg)](https://img.shields.io/badge/tests-21%20passing-brightgreen.svg) [![Crates.io](https://img.shields.io/crates/v/secreport.svg)](https://crates.io/crates/secreport)

Render security findings into text, JSON, JSONL, SARIF, and Markdown.

## Why
Every scanner outputs findings in a different shape, but operators need consistent output for dashboards, tickets, and review. `secreport` standardizes that final step with pluggable formats: text, JSON, JSONL, SARIF, and Markdown.

It accepts both the canonical `secfinding::Finding` and any type that implements `Reportable`, so you can keep custom data models while still producing unified artifacts.

## Quick Start
```rust
use secfinding::{Finding, Severity};
use secreport::{render, emit, Format};

fn main() -> std::io::Result<()> {
    let findings = vec![
        Finding::new(
            "santh-cli",
            "https://example.com/login",
            Severity::High,
            "Potential SQL injection",
            "Untrusted input reaches query context",
        ),
    ];

    let text = render(&findings, Format::Text, "demo-scan");
    emit(&text, None)
}
```

## Features
- Shared render entry points: `render` for `Finding`, `render_any` for any `Reportable` type.
- Formats: `Text`, `Json`, `Jsonl`, `Sarif`, `Markdown`.
- `emit` for stdout/file emission in one call.
- Human-friendly colorized text summaries plus severity breakdown.
- Reusable with any type implementing `Reportable`, including custom `rule_id`, CWE/CVE lists, confidence, tags, and exploit hints.

## TOML Configuration
`secreport` does not use TOML configuration.

## API Overview
- `Format`: output format selector.
- `render`: format `Vec<Finding>`.
- `render_any`: format generic `Reportable` types.
- `emit`: print to stdout or write file path.

## Examples
### 1) Produce JSON for API pipelines
```rust
use secfinding::Finding;
use secreport::{render, Format};

let findings: Vec<Finding> = Vec::new();
let json = render(&findings, Format::Json, "scanner");
println!("{}", json);
```

### 2) Build Markdown report for issue triage
```rust
use secfinding::{Finding, Severity};
use secreport::{emit, render, Format};

let findings = vec![
    Finding::new("scanner", "https://target", Severity::Critical, "RCE", "eval on tainted input")
];

let md = render(&findings, Format::Markdown, "nightly-run");
emit(&md, Some("./run-report.md")).unwrap();
```

### 3) Render your own finding type
```rust
use secreport::{render_any, Format};
use secfinding::{Reportable, Severity};

struct CustomFinding {
    target: String,
    score: f64,
}

impl Reportable for CustomFinding {
    fn scanner(&self) -> &str { "custom" }
    fn target(&self) -> &str { &self.target }
    fn severity(&self) -> Severity { if self.score > 0.8 { Severity::High } else { Severity::Low } }
    fn title(&self) -> &str { "Custom rule" }
}

let findings = vec![CustomFinding { target: "https://example.com".into(), score: 0.93 }];
let out = render_any(&findings, Format::Text, "custom-scan");
println!("{out}");
```

### 4) Run the bundled examples
```bash
cargo run --example basic
cargo run --example custom_reportable
```

## Traits
`secreport` does not define traits, but your reporting integration usually depends on `secfinding::Reportable` (rendered through `render_any`).

## Related Crates
- [secfinding]https://docs.rs/secfinding
- [scanstate]https://docs.rs/scanstate
- [codewalk]https://docs.rs/codewalk

## License
MIT, Corum Collective LLC

Docs: https://docs.rs/secreport

Santh ecosystem: https://santh.io