docs(01-foundation): create phase 1 plan — 5 plans across 3 execution waves
Wave 0: module init + test scaffolding (01-01) Wave 1: provider registry (01-02) + storage layer (01-03) in parallel Wave 2: scan engine pipeline (01-04, depends on 01-02) Wave 3: CLI wiring + integration checkpoint (01-05, depends on all) Covers all 16 Phase 1 requirements: CORE-01 through CORE-07, STOR-01 through STOR-03, CLI-01 through CLI-05, PROV-10. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
359
.planning/phases/01-foundation/01-01-PLAN.md
Normal file
359
.planning/phases/01-foundation/01-01-PLAN.md
Normal file
@@ -0,0 +1,359 @@
|
||||
---
|
||||
phase: 01-foundation
|
||||
plan: 01
|
||||
type: execute
|
||||
wave: 0
|
||||
depends_on: []
|
||||
files_modified:
|
||||
- go.mod
|
||||
- go.sum
|
||||
- main.go
|
||||
- testdata/samples/openai_key.txt
|
||||
- testdata/samples/anthropic_key.txt
|
||||
- testdata/samples/no_keys.txt
|
||||
- pkg/providers/registry_test.go
|
||||
- pkg/storage/db_test.go
|
||||
- pkg/engine/scanner_test.go
|
||||
autonomous: true
|
||||
requirements: [CORE-01, CORE-02, CORE-03, CORE-04, CORE-05, CORE-06, CORE-07, STOR-01, STOR-02, STOR-03, CLI-01]
|
||||
|
||||
must_haves:
|
||||
truths:
|
||||
- "go.mod exists with all Phase 1 dependencies at pinned versions"
|
||||
- "go build ./... succeeds with zero errors on a fresh checkout"
|
||||
- "go test ./... -short runs without compilation errors (tests may fail — stubs are fine)"
|
||||
- "testdata/ contains files with known key patterns for scanner integration tests"
|
||||
artifacts:
|
||||
- path: "go.mod"
|
||||
provides: "Module declaration with all Phase 1 dependencies"
|
||||
contains: "module github.com/salvacybersec/keyhunter"
|
||||
- path: "main.go"
|
||||
provides: "Binary entry point under 30 lines"
|
||||
contains: "func main()"
|
||||
- path: "testdata/samples/openai_key.txt"
|
||||
provides: "Sample file with synthetic OpenAI key for scanner tests"
|
||||
- path: "pkg/providers/registry_test.go"
|
||||
provides: "Test stubs for provider loading and registry"
|
||||
- path: "pkg/storage/db_test.go"
|
||||
provides: "Test stubs for SQLite + encryption roundtrip"
|
||||
- path: "pkg/engine/scanner_test.go"
|
||||
provides: "Test stubs for pipeline stages"
|
||||
key_links:
|
||||
- from: "go.mod"
|
||||
to: "petar-dambovaliev/aho-corasick"
|
||||
via: "require directive"
|
||||
pattern: "petar-dambovaliev/aho-corasick"
|
||||
- from: "go.mod"
|
||||
to: "modernc.org/sqlite"
|
||||
via: "require directive"
|
||||
pattern: "modernc.org/sqlite"
|
||||
---
|
||||
|
||||
<objective>
|
||||
Initialize the Go module, install all Phase 1 dependencies at pinned versions, create the minimal main.go entry point, and lay down test scaffolding with testdata fixtures that every subsequent plan's tests depend on.
|
||||
|
||||
Purpose: All subsequent plans require a compiling module and test infrastructure to exist before they can add production code and make tests green. Wave 0 satisfies this bootstrap requirement.
|
||||
Output: go.mod, go.sum, main.go, pkg/*/test stubs, testdata/ fixtures.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@$HOME/.claude/get-shit-done/workflows/execute-plan.md
|
||||
@$HOME/.claude/get-shit-done/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/phases/01-foundation/01-RESEARCH.md
|
||||
@.planning/phases/01-foundation/01-VALIDATION.md
|
||||
|
||||
<interfaces>
|
||||
<!-- Module path used throughout the project -->
|
||||
Module: github.com/salvacybersec/keyhunter
|
||||
|
||||
<!-- Pinned versions from RESEARCH.md -->
|
||||
Dependencies to install:
|
||||
github.com/spf13/cobra@v1.10.2
|
||||
github.com/spf13/viper@v1.21.0
|
||||
modernc.org/sqlite@latest
|
||||
gopkg.in/yaml.v3@v3.0.1
|
||||
github.com/petar-dambovaliev/aho-corasick@latest
|
||||
github.com/panjf2000/ants/v2@v2.12.0
|
||||
golang.org/x/crypto@latest
|
||||
golang.org/x/time@latest
|
||||
github.com/charmbracelet/lipgloss@latest
|
||||
github.com/stretchr/testify@latest
|
||||
|
||||
<!-- Go version -->
|
||||
go 1.22
|
||||
|
||||
<!-- Directory structure to scaffold (from RESEARCH.md) -->
|
||||
keyhunter/
|
||||
main.go
|
||||
cmd/
|
||||
root.go (created in Plan 05)
|
||||
scan.go (created in Plan 05)
|
||||
providers.go (created in Plan 05)
|
||||
config.go (created in Plan 05)
|
||||
pkg/
|
||||
providers/ (created in Plan 02)
|
||||
engine/ (created in Plan 04)
|
||||
storage/ (created in Plan 03)
|
||||
config/ (created in Plan 05)
|
||||
output/ (created in Plan 05)
|
||||
providers/ (created in Plan 02)
|
||||
testdata/
|
||||
samples/
|
||||
</interfaces>
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto" tdd="false">
|
||||
<name>Task 1: Initialize Go module and install Phase 1 dependencies</name>
|
||||
<files>go.mod, go.sum</files>
|
||||
<read_first>
|
||||
- /home/salva/Documents/apikey/.planning/phases/01-foundation/01-RESEARCH.md (Standard Stack section — exact library versions)
|
||||
- /home/salva/Documents/apikey/CLAUDE.md (Technology Stack table — version constraints)
|
||||
</read_first>
|
||||
<action>
|
||||
Run the following commands in the project root (/home/salva/Documents/apikey):
|
||||
|
||||
```bash
|
||||
go mod init github.com/salvacybersec/keyhunter
|
||||
go get github.com/spf13/cobra@v1.10.2
|
||||
go get github.com/spf13/viper@v1.21.0
|
||||
go get modernc.org/sqlite@latest
|
||||
go get gopkg.in/yaml.v3@v3.0.1
|
||||
go get github.com/petar-dambovaliev/aho-corasick@latest
|
||||
go get github.com/panjf2000/ants/v2@v2.12.0
|
||||
go get golang.org/x/crypto@latest
|
||||
go get golang.org/x/time@latest
|
||||
go get github.com/charmbracelet/lipgloss@latest
|
||||
go get github.com/stretchr/testify@latest
|
||||
go mod tidy
|
||||
```
|
||||
|
||||
Verify the resulting go.mod contains:
|
||||
- `module github.com/salvacybersec/keyhunter`
|
||||
- `go 1.22` (or 1.22.x)
|
||||
- `github.com/spf13/cobra v1.10.2`
|
||||
- `github.com/spf13/viper v1.21.0`
|
||||
- `github.com/petar-dambovaliev/aho-corasick` (any version)
|
||||
- `github.com/panjf2000/ants/v2 v2.12.0`
|
||||
- `modernc.org/sqlite` (any v1.35.x)
|
||||
- `github.com/charmbracelet/lipgloss` (any version)
|
||||
|
||||
Do NOT add: chi, templ, telego, gocron — these are Phase 17-18 only.
|
||||
Do NOT use CGO_ENABLED=1 or mattn/go-sqlite3.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /home/salva/Documents/apikey && grep -q 'module github.com/salvacybersec/keyhunter' go.mod && grep -q 'cobra v1.10.2' go.mod && grep -q 'modernc.org/sqlite' go.mod && echo "go.mod OK"</automated>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- go.mod contains `module github.com/salvacybersec/keyhunter`
|
||||
- go.mod contains `github.com/spf13/cobra v1.10.2` (exact)
|
||||
- go.mod contains `github.com/spf13/viper v1.21.0` (exact)
|
||||
- go.mod contains `github.com/panjf2000/ants/v2 v2.12.0` (exact)
|
||||
- go.mod contains `modernc.org/sqlite` (v1.35.x)
|
||||
- go.mod contains `github.com/petar-dambovaliev/aho-corasick`
|
||||
- go.mod contains `golang.org/x/crypto`
|
||||
- go.mod contains `github.com/charmbracelet/lipgloss`
|
||||
- go.sum exists and is non-empty
|
||||
- `go mod verify` exits 0
|
||||
</acceptance_criteria>
|
||||
<done>go.mod and go.sum committed with all Phase 1 dependencies at correct versions</done>
|
||||
</task>
|
||||
|
||||
<task type="auto" tdd="false">
|
||||
<name>Task 2: Create main.go entry point and test scaffolding</name>
|
||||
<files>
|
||||
main.go,
|
||||
testdata/samples/openai_key.txt,
|
||||
testdata/samples/anthropic_key.txt,
|
||||
testdata/samples/multiple_keys.txt,
|
||||
testdata/samples/no_keys.txt,
|
||||
pkg/providers/registry_test.go,
|
||||
pkg/storage/db_test.go,
|
||||
pkg/engine/scanner_test.go
|
||||
</files>
|
||||
<read_first>
|
||||
- /home/salva/Documents/apikey/.planning/phases/01-foundation/01-VALIDATION.md (Wave 0 Requirements and Per-Task Verification Map)
|
||||
- /home/salva/Documents/apikey/.planning/phases/01-foundation/01-RESEARCH.md (Architecture Patterns, project structure diagram)
|
||||
</read_first>
|
||||
<action>
|
||||
Create the following files:
|
||||
|
||||
**main.go** (must be under 30 lines):
|
||||
```go
|
||||
package main
|
||||
|
||||
import "github.com/salvacybersec/keyhunter/cmd"
|
||||
|
||||
func main() {
|
||||
cmd.Execute()
|
||||
}
|
||||
```
|
||||
|
||||
**testdata/samples/openai_key.txt** — file containing a synthetic (non-real) OpenAI-style key for scanner integration tests:
|
||||
```
|
||||
# Test file: synthetic OpenAI key pattern
|
||||
OPENAI_API_KEY=sk-proj-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr1234
|
||||
```
|
||||
|
||||
**testdata/samples/anthropic_key.txt** — file containing a synthetic Anthropic-style key:
|
||||
```
|
||||
# Test file: synthetic Anthropic key pattern
|
||||
export ANTHROPIC_API_KEY="sk-ant-api03-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxy01234567890-ABCDE"
|
||||
```
|
||||
|
||||
**testdata/samples/multiple_keys.txt** — file with both key types:
|
||||
```
|
||||
# Multiple providers in one file
|
||||
OPENAI_API_KEY=sk-proj-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr5678
|
||||
ANTHROPIC_API_KEY=sk-ant-api03-XYZabcdefghijklmnopqrstuvwxyz01234567890ABCDEFGH-XYZAB
|
||||
```
|
||||
|
||||
**testdata/samples/no_keys.txt** — file with no keys (negative test case):
|
||||
```
|
||||
# This file contains no API keys
|
||||
# Used to verify false-positive rate is zero for clean files
|
||||
Hello world
|
||||
```
|
||||
|
||||
**pkg/providers/registry_test.go** — test stubs (will be filled by Plan 02):
|
||||
```go
|
||||
package providers_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestRegistryLoad verifies that provider YAML files are loaded from embed.FS.
|
||||
// Stub: will be implemented when registry.go exists (Plan 02).
|
||||
func TestRegistryLoad(t *testing.T) {
|
||||
t.Skip("stub — implement after registry.go exists")
|
||||
}
|
||||
|
||||
// TestProviderSchemaValidation verifies format_version and last_verified are required.
|
||||
// Stub: will be implemented when schema.go validation exists (Plan 02).
|
||||
func TestProviderSchemaValidation(t *testing.T) {
|
||||
t.Skip("stub — implement after schema.go validation exists")
|
||||
}
|
||||
|
||||
// TestAhoCorasickBuild verifies Aho-Corasick automaton builds from provider keywords.
|
||||
// Stub: will be implemented when registry builds automaton (Plan 02).
|
||||
func TestAhoCorasickBuild(t *testing.T) {
|
||||
t.Skip("stub — implement after registry AC build exists")
|
||||
}
|
||||
```
|
||||
|
||||
**pkg/storage/db_test.go** — test stubs (will be filled by Plan 03):
|
||||
```go
|
||||
package storage_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestDBOpen verifies SQLite database opens and creates schema.
|
||||
// Stub: will be implemented when db.go exists (Plan 03).
|
||||
func TestDBOpen(t *testing.T) {
|
||||
t.Skip("stub — implement after db.go exists")
|
||||
}
|
||||
|
||||
// TestEncryptDecryptRoundtrip verifies AES-256-GCM encrypt/decrypt roundtrip.
|
||||
// Stub: will be implemented when encrypt.go exists (Plan 03).
|
||||
func TestEncryptDecryptRoundtrip(t *testing.T) {
|
||||
t.Skip("stub — implement after encrypt.go exists")
|
||||
}
|
||||
|
||||
// TestArgon2KeyDerivation verifies Argon2id produces 32-byte key deterministically.
|
||||
// Stub: will be implemented when crypto.go exists (Plan 03).
|
||||
func TestArgon2KeyDerivation(t *testing.T) {
|
||||
t.Skip("stub — implement after crypto.go exists")
|
||||
}
|
||||
```
|
||||
|
||||
**pkg/engine/scanner_test.go** — test stubs (will be filled by Plan 04):
|
||||
```go
|
||||
package engine_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestShannonEntropy verifies the entropy function returns expected values.
|
||||
// Stub: will be implemented when entropy.go exists (Plan 04).
|
||||
func TestShannonEntropy(t *testing.T) {
|
||||
t.Skip("stub — implement after entropy.go exists")
|
||||
}
|
||||
|
||||
// TestKeywordPreFilter verifies Aho-Corasick pre-filter rejects files without keywords.
|
||||
// Stub: will be implemented when filter.go exists (Plan 04).
|
||||
func TestKeywordPreFilter(t *testing.T) {
|
||||
t.Skip("stub — implement after filter.go exists")
|
||||
}
|
||||
|
||||
// TestScannerPipeline verifies end-to-end scan of testdata returns expected findings.
|
||||
// Stub: will be implemented when engine.go exists (Plan 04).
|
||||
func TestScannerPipeline(t *testing.T) {
|
||||
t.Skip("stub — implement after engine.go exists")
|
||||
}
|
||||
```
|
||||
|
||||
Create the `cmd/` package directory with a minimal stub so main.go compiles:
|
||||
|
||||
**cmd/root.go** (minimal stub — will be replaced by Plan 05):
|
||||
```go
|
||||
package cmd
|
||||
|
||||
import "os"
|
||||
|
||||
// Execute is a stub. The real command tree is built in Plan 05.
|
||||
func Execute() {
|
||||
_ = os.Args
|
||||
}
|
||||
```
|
||||
|
||||
After creating all files, run `go build ./...` to confirm the module compiles.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /home/salva/Documents/apikey && go build ./... && go test ./... -short 2>&1 | grep -v "^--- SKIP" | grep -v "^SKIP" | grep -v "^ok" || true && echo "BUILD OK"</automated>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- `go build ./...` exits 0 with no errors
|
||||
- `go test ./... -short` exits 0 (all stubs skip, no failures)
|
||||
- main.go is under 30 lines
|
||||
- testdata/samples/openai_key.txt contains `sk-proj-` prefix
|
||||
- testdata/samples/anthropic_key.txt contains `sk-ant-api03-` prefix
|
||||
- testdata/samples/no_keys.txt contains no key patterns
|
||||
- pkg/providers/registry_test.go, pkg/storage/db_test.go, pkg/engine/scanner_test.go each exist with skip-based stubs
|
||||
- cmd/root.go exists so `go build ./...` compiles
|
||||
</acceptance_criteria>
|
||||
<done>Module compiles, test stubs exist, testdata fixtures created. Subsequent plans can now add production code and make tests green.</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
After both tasks:
|
||||
- `cd /home/salva/Documents/apikey && go build ./...` exits 0
|
||||
- `go test ./... -short` exits 0
|
||||
- `grep -r 'sk-proj-' testdata/` finds the OpenAI test fixture
|
||||
- `grep -r 'sk-ant-api03-' testdata/` finds the Anthropic test fixture
|
||||
- go.mod has all required dependencies at specified versions
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- go.mod initialized with module path `github.com/salvacybersec/keyhunter` and Go 1.22
|
||||
- All 10 Phase 1 dependencies installed at correct versions
|
||||
- main.go under 30 lines, compiles successfully
|
||||
- 3 test stub files exist (providers, storage, engine)
|
||||
- 4 testdata fixture files exist (openai key, anthropic key, multiple keys, no keys)
|
||||
- `go build ./...` and `go test ./... -short` both exit 0
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/01-foundation/01-01-SUMMARY.md` following the summary template.
|
||||
</output>
|
||||
Reference in New Issue
Block a user