123 lines
5.6 KiB
Markdown
123 lines
5.6 KiB
Markdown
---
|
|
phase: 06-output-reporting
|
|
plan: 05
|
|
subsystem: cli
|
|
tags: [cobra, cli, clipboard, sqlite, keys-management]
|
|
|
|
requires:
|
|
- phase: 06-output-reporting
|
|
provides: "formatter registry (json/csv), storage query layer, verify package"
|
|
provides:
|
|
- "keyhunter keys list/show/export/copy/delete/verify subcommand tree"
|
|
- "cmd/keys.go with openDBWithKey + storageToEngine helpers"
|
|
- "atomic file-write pattern for exports (.tmp + os.Rename, 0600)"
|
|
affects: [07-import-hooks, 18-dashboard]
|
|
|
|
tech-stack:
|
|
added: []
|
|
patterns:
|
|
- "cmd.OutOrStdout for hermetic Cobra subcommand tests"
|
|
- "viper-first, env fallback, config default for database.path + passphrase"
|
|
|
|
key-files:
|
|
created:
|
|
- cmd/keys.go
|
|
- cmd/keys_test.go
|
|
- .planning/phases/06-output-reporting/06-05-SUMMARY.md
|
|
modified:
|
|
- cmd/stubs.go
|
|
|
|
key-decisions:
|
|
- "SARIF export is intentionally rejected by keys export (scan-only per context)"
|
|
- "keys show is always unmasked (KEYS-02) — no --unmask flag"
|
|
- "keys verify updates findings table inline via db.SQL().Exec rather than adding a storage helper"
|
|
- "Tests invoke RunE directly with cmd.SetOut buffers — no os.Stdout redirection needed"
|
|
|
|
patterns-established:
|
|
- "openDBWithKey(): mirrors scan.go's DB-open + loadOrCreateEncKey sequence so every keys subcommand shares one path"
|
|
- "storageToEngine(): bridge between storage.Finding and engine.Finding for formatter reuse"
|
|
|
|
requirements-completed: [KEYS-01, KEYS-02, KEYS-03, KEYS-04, KEYS-05, KEYS-06]
|
|
|
|
duration: 4min
|
|
completed: 2026-04-05
|
|
---
|
|
|
|
# Phase 06 Plan 05: Keys Command Tree Summary
|
|
|
|
**keyhunter keys list/show/export/copy/delete/verify wired to the Plan-04 query layer and the Plans 01-03 formatter registry, replacing the Phase-1 stub.**
|
|
|
|
## Performance
|
|
|
|
- **Duration:** ~4 min
|
|
- **Started:** 2026-04-05T20:35:50Z
|
|
- **Completed:** 2026-04-05T20:39:40Z
|
|
- **Tasks:** 2
|
|
- **Files modified:** 3 (cmd/keys.go, cmd/keys_test.go, cmd/stubs.go)
|
|
|
|
## Accomplishments
|
|
|
|
- Six-subcommand `keys` tree: list, show, export, copy, delete, verify
|
|
- list supports `--provider`, tri-state `--verified` (via `Flag().Changed`), `--limit`, `--unmask`
|
|
- show always unmasked with sorted verify metadata rendering (KEYS-02)
|
|
- export reuses `output.Get("json"|"csv")`, atomic `.tmp` + rename on `--output`, stdout otherwise
|
|
- copy uses `atotto/clipboard` with masked confirmation line
|
|
- delete prompts on stdin unless `--yes`; cancelled paths print "Cancelled."
|
|
- verify re-runs `HTTPVerifier.VerifyAll` against the stored row, updates `findings.verify_*` in place, re-renders
|
|
- Seven integration tests (`TestKeysList_*`, `TestKeysShow_*`, `TestKeysExport_*`, `TestKeysDelete_WithYes`) exercise the full happy and miss paths against a temp-file SQLite DB; copy + verify intentionally skipped (clipboard headless / network)
|
|
|
|
## Task Commits
|
|
|
|
1. **Task 1: Implement keys command tree** — `06594af` (feat)
|
|
2. **Task 2: Integration tests for keys list/show/export/delete** — `e2394ec` (test)
|
|
|
|
## Files Created/Modified
|
|
|
|
- `cmd/keys.go` (created) — 350+ LOC, six subcommands plus `openDBWithKey`, `storageToEngine`, `renderFinding`, `parseID` helpers, `init()` wiring flags and AddCommand
|
|
- `cmd/keys_test.go` (created) — seedKeysDB helper plus 7 tests using `cmd.SetOut` + RunE invocation
|
|
- `cmd/stubs.go` (modified) — removed the `keysCmd` placeholder, left a pointer comment so no duplicate declaration exists with `cmd/keys.go`
|
|
|
|
## Decisions Made
|
|
|
|
- **SARIF rejected by keys export**: context gathered for Plan 06 explicitly scopes SARIF to the scan command. `keys export --format=sarif` returns a clear error mentioning scan-only.
|
|
- **verify updates via raw UPDATE**: rather than adding a `db.UpdateFindingVerify` helper (not requested anywhere else), the implementation uses `db.SQL().Exec` inline with JSON-marshaled metadata. Easy to promote to a helper later if a second caller appears.
|
|
- **Tests call RunE directly**: avoids mutating `rootCmd.SetArgs` global state and gives each test a clean output buffer. Matches `cmd/scan_test.go`'s lightweight style.
|
|
- **Passphrase resolution order**: `viper("encryption.passphrase")` → `KEYHUNTER_PASSPHRASE` env → `config.Load().Passphrase`. This makes test setup trivial (`t.Setenv`) while preserving production semantics.
|
|
|
|
## Deviations from Plan
|
|
|
|
None — plan executed exactly as written. Minor optional cleanups applied:
|
|
|
|
- The plan suggested using `output.ColorsEnabled(os.Stdout)` for list output; the implemented list renderer is plain text (no color) to keep tests deterministic and output grep-friendly. Color support can be added later without API changes.
|
|
- All `fmt.Fprintln` calls use `cmd.OutOrStdout()` / `cmd.ErrOrStderr()` from the start, which the plan flagged as an acceptable mid-task refactor during Task 2. Doing it in Task 1 kept both tasks clean.
|
|
|
|
## Issues Encountered
|
|
|
|
None. First `go build ./...` and first `go test ./...` both passed without adjustment.
|
|
|
|
## User Setup Required
|
|
|
|
None — no external services introduced.
|
|
|
|
## Next Phase Readiness
|
|
|
|
- All of KEYS-01..06 satisfied; keys tree is production-ready and under test
|
|
- Import/hook work in Phase 7 can reuse `openDBWithKey` and `storageToEngine`
|
|
- Dashboard work (Phase 18) can share `renderFinding`'s field ordering for HTML detail views
|
|
- Follow-up: promote the inline `verify` UPDATE to a `db.UpdateFindingVerify` helper if/when a second caller appears
|
|
|
|
## Self-Check: PASSED
|
|
|
|
- `cmd/keys.go` exists
|
|
- `cmd/keys_test.go` exists
|
|
- Stub removed from `cmd/stubs.go`
|
|
- Commits `06594af`, `e2394ec` present in `git log`
|
|
- `go build ./...` green
|
|
- `go test ./... -count=1` green (all packages)
|
|
- `go run . keys --help` lists six subcommands
|
|
|
|
---
|
|
*Phase: 06-output-reporting*
|
|
*Plan: 05*
|
|
*Completed: 2026-04-05*
|