docs(06): output formats and key management context
This commit is contained in:
99
.planning/phases/06-output-reporting/06-CONTEXT.md
Normal file
99
.planning/phases/06-output-reporting/06-CONTEXT.md
Normal file
@@ -0,0 +1,99 @@
|
||||
# Phase 6: Output, Reporting & Key Management - Context
|
||||
|
||||
**Gathered:** 2026-04-05
|
||||
**Status:** Ready for planning
|
||||
**Mode:** Auto-generated
|
||||
|
||||
<domain>
|
||||
## Phase Boundary
|
||||
|
||||
Two related capabilities:
|
||||
1. **Scan output formats**: table (default, colored, masked), JSON, SARIF 2.1.0, CSV. `--unmask` reveals full keys. Proper exit codes for CI/CD.
|
||||
2. **Key management commands**: `keyhunter keys list/show/export/copy/delete` for lifecycle operations on stored keys.
|
||||
|
||||
</domain>
|
||||
|
||||
<decisions>
|
||||
## Implementation Decisions
|
||||
|
||||
### Output Formats (OUT-01..06)
|
||||
- **Extend pkg/output/** with: `json.go`, `sarif.go`, `csv.go`, keeping `table.go` from Phase 1/5
|
||||
- **Format registry**: `output.Formatter` interface with `Format(findings []Finding, w io.Writer) error`
|
||||
- **Selection**: `--output=table|json|sarif|csv` flag on scan command (default: table)
|
||||
- **Masking**: `MaskKey()` is default; `--unmask` passes a flag down to the formatter
|
||||
- **Colors**: lipgloss for table format only (already in use), strip colors when stdout isn't a TTY (detect via `isatty`)
|
||||
|
||||
### Exit Codes (OUT-06)
|
||||
- **0**: no findings
|
||||
- **1**: findings detected
|
||||
- **2**: scan error
|
||||
- Set via `os.Exit(code)` at end of scan command. Use `cobra.Command.SilenceUsage = true` on error to avoid duplicate usage message.
|
||||
|
||||
### SARIF 2.1.0
|
||||
- **Implementation**: custom structs (no library per CLAUDE.md — ~200 lines). schema at https://docs.oasis-open.org/sarif/sarif/v2.1.0/
|
||||
- **Fields**: `$schema`, `version: "2.1.0"`, `runs[].tool.driver.{name, version, rules[]}`, `runs[].results[]` with `ruleId, level, message, locations[{physicalLocation.{artifactLocation.uri, region.{startLine, startColumn, endLine, endColumn}}}]`
|
||||
- **Rule**: one rule per provider (ruleId = provider name)
|
||||
- **Level mapping**: confidence high → error, medium → warning, low → note
|
||||
|
||||
### Key Management (KEYS-01..06)
|
||||
- **New command tree**: `keyhunter keys <subcommand>` in cmd/keys.go (replace existing stub)
|
||||
- `list` — table of all stored findings, masked by default, `--unmask` for full, `--provider=openai` filter, `--verified` filter
|
||||
- `show <id>` — full detail for one finding (unmasked), including verify metadata
|
||||
- `export --format=json|csv [--output=file]` — dump findings to file/stdout
|
||||
- `copy <id>` — copy plaintext key to clipboard via atotto/clipboard (already imported)
|
||||
- `delete <id>` — remove from findings table, with `--yes` to skip confirm
|
||||
- **ID**: use SQLite rowid (integer). Display in list output.
|
||||
|
||||
### Findings DB Query Layer
|
||||
- New `pkg/storage/queries.go` — `ListFindings(filters Filters) ([]Finding, error)`, `GetFinding(id int) (*Finding, error)`, `DeleteFinding(id int) error`
|
||||
- Filter struct: `Provider string, Verified *bool, Since time.Time`
|
||||
- Pagination: `Limit, Offset` fields (default unlimited for v1)
|
||||
|
||||
### Output Package Layout
|
||||
```
|
||||
pkg/output/
|
||||
formatter.go — Formatter interface + Registry
|
||||
table.go — existing, refactor to implement Formatter
|
||||
json.go — NEW — JSON output (uses encoding/json)
|
||||
sarif.go — NEW — SARIF 2.1.0 output
|
||||
csv.go — NEW — CSV output (uses encoding/csv)
|
||||
colors.go — NEW — isatty detection, color stripping
|
||||
```
|
||||
|
||||
</decisions>
|
||||
|
||||
<code_context>
|
||||
## Existing Code Insights
|
||||
|
||||
### Reusable Assets
|
||||
- pkg/output/table.go — existing, extend to Formatter interface
|
||||
- pkg/storage/findings.go — existing CRUD
|
||||
- pkg/engine/finding.go — extended with verify fields in Phase 5
|
||||
- pkg/engine/finding.go MaskKey() — already defined
|
||||
- cmd/stubs.go — `keys` is currently a stub, replace with real command tree
|
||||
|
||||
### Dependencies to add
|
||||
- `github.com/mattn/go-isatty` — for TTY detection
|
||||
|
||||
</code_context>
|
||||
|
||||
<specifics>
|
||||
## Specific Ideas
|
||||
|
||||
- JSON output should include full Finding struct (all fields)
|
||||
- CSV header row: id,provider,confidence,key_masked,source,line,detected_at,verified,verify_status
|
||||
- SARIF should include the scan binary version (extract from cmd/root.go version constant)
|
||||
- Keys export to file should use atomic write (write to temp then rename)
|
||||
- Delete should show confirmation: "Delete finding #42 (openai, sk-proj-***abc)? [y/N]"
|
||||
|
||||
</specifics>
|
||||
|
||||
<deferred>
|
||||
## Deferred Ideas
|
||||
|
||||
- Per-finding tags/labels — not in scope
|
||||
- Bulk operations (delete all from provider X) — add a --provider filter, but no bulk delete
|
||||
- Export to cloud storage (S3, GCS) — out of scope
|
||||
- HTML report format — defer to dashboard phase
|
||||
|
||||
</deferred>
|
||||
Reference in New Issue
Block a user