keyhunter dorks list/info/export/run/add/delete command tree
Injectable newGitHubExecutor seam for cmd tests
GITHUB_TOKEN env var bound to viper.dorks.github.token
phase-09-osint
phase-10-shodan
phase-17-scheduler
added
patterns
Package-level executor factory var as test injection seam
Embedded+custom dork merge via internal dorkRow helper
text/tabwriter for CLI table output (no lipgloss yet for dorks)
created
modified
cmd/dorks.go
cmd/dorks_test.go
cmd/stubs.go
Flag reuse: dorks list and dorks run share dorksFilterSource/Category vars since they never run concurrently — simplifies test reset
initDorksDB skips encryption key derivation: dorks CLI only touches plaintext custom_dorks, not the encrypted findings table
dorks run wraps ErrSourceNotImplemented with friendly 'coming Phase 9-16' message instead of bare error
newGitHubExecutor exposed as package var (not method) so tests can swap without touching dorksRunCmd internals
Injectable executor factory: var newFooExecutor = func() Executor { ... } for mocking in cmd tests
resetDorksFlags helper called from setupDorksTest + between sequential rootCmd.Execute() calls
DORK-03
DORK-04
~35min
2026-04-05
Phase 8 Plan 06: Dorks CLI Command Tree Summary
Full Cobra command tree (list/info/export/run/add/delete) replacing the Phase-8 stub, wiring Registry + custom_dorks + GitHubExecutor through an injectable factory seam for testability.
Performance
Duration: ~35 min
Tasks: 2
Files modified: 3 (1 created in commit 1, 1 created in commit 2, 1 edited)
Accomplishments
Replaced cmd/stubs.go dorks stub with a six-verb subcommand tree
Merged embedded Registry dorks with user-authored custom_dorks in list + export (custom rows prefixed with *)
Added --source/--category filtering to both list and run
Wired dorks run to dorks.Runner with GitHub live execution, friendly ErrSourceNotImplemented messaging for other sources, and an ErrMissingAuth hint that points users at GITHUB_TOKEN
Added validation to dorks add: source must be in dorks.ValidSources, category in dorks.ValidCategories, dork id must not collide with an embedded id
Delete refuses embedded ids with a clear error
Bound GITHUB_TOKEN -> dorks.github.token via viper.BindEnv in the dorks init()
11 end-to-end cmd tests covering every branch, passing against an in-memory SQLite temp DB
cmd/dorks.go - Full dorks Cobra command tree, flag declarations, initDorksDB helper, newGitHubExecutor injection seam, init() wiring
cmd/dorks_test.go - 11 tests: list filtering, add persistence + marker, invalid source rejection, embedded id collision, embedded delete refusal, custom delete, shodan not-implemented, github missing-token hint, fake-executor run path, yaml export merge, info for both origins
cmd/stubs.go - Removed dorksCmd stub declaration (kept notImplemented helper and other stubs)
Decisions Made
Skip encryption in initDorksDB: The dorks CLI only reads/writes custom_dorks, which stores plaintext metadata. Forcing users through the encryption-key derivation path that openDBWithKey uses would add a passphrase prompt for commands that don't need it. initDorksDB deliberately calls storage.Open directly.
tabwriter over lipgloss: Phase 8 plan lists lipgloss as a "nice to have" for the dorks table; the current pkg/output table helpers are keyed to findings, not dorks. Used stdlib text/tabwriter to keep Phase 8 self-contained. A future refactor can swap to lipgloss alongside a shared Table type.
Package-level executor factory var: var newGitHubExecutor = func() dorks.Executor { ... }. Tests swap it; production code reads it. Avoids forcing the Runner to accept a factory injection or the cmd struct to carry a builder field.
Shared filter flag vars between list and run: dorksFilterSource/dorksFilterCategory are reused across subcommands. Cobra runs one subcommand per invocation, so sharing is safe; resetDorksFlags in the test helper guarantees clean state.
Deviations from Plan
None significant. Minor adjustments made inline during implementation:
[Inline adjustment] renderDork signature switched to io.Writer after initial draft used a structural interface. Single-line fix before the first build.
[Inline adjustment] sort key used rows[i].Dork.Source not rows[i].Source — dorkRow wraps Dork rather than embedding it, so the field path goes through .Dork. Caught by go build on the first run and fixed immediately.
Both were typo-class fixes inside Task 1, pre-commit. Neither required new infrastructure or plan changes.
Issues Encountered
None. All 11 tests passed on first run after the two trivial compile fixes above; no retries, no flakes.
Self-Check: PASSED
Files verified to exist:
cmd/dorks.go — FOUND
cmd/dorks_test.go — FOUND
Commits verified in git log:
b7934ce feat(08-06): add dorks list/info/export commands — FOUND
c281c96 feat(08-06): add dorks run/add/delete with injectable executor — FOUND
Build + tests:
go build ./... — PASS
go test ./cmd/... ./pkg/dorks/... ./pkg/storage/... — PASS
go test ./... — PASS (entire workspace green)
User Setup Required
None for tests. For live keyhunter dorks run --source=github ..., users must export GITHUB_TOKEN with public_repo scope, or run keyhunter config set dorks.github.token <pat>.
Next Phase Readiness
DORK-03 and DORK-04 requirements satisfied
Plan 08-07 (guardrail/E2E tests) unblocked — the CLI surface it exercises now exists
Phase 9-16 OSINT sources can plug into the dispatcher by registering executors with dorks.Runner; the friendly "coming Phase 9-16" message transparently disappears as each one lands