---
phase: 16-osint-threat-intel-mobile-dns-api-marketplaces
plan: 04
type: execute
wave: 2
depends_on: [16-01, 16-02, 16-03]
files_modified:
  - pkg/recon/sources/register.go
  - pkg/recon/sources/register_test.go
  - cmd/recon.go
autonomous: true
requirements: [RECON-INTEL-01, RECON-INTEL-02, RECON-INTEL-03, RECON-MOBILE-01, RECON-DNS-01, RECON-DNS-02, RECON-API-01, RECON-API-02]

must_haves:
  truths:
    - "RegisterAll registers all 9 Phase 16 sources (76 total)"
    - "cmd/recon.go populates SourcesConfig with VT, IX, SecurityTrails credentials from env/viper"
    - "Integration test proves all 76 sources are registered and the 9 new ones are present"
  artifacts:
    - path: "pkg/recon/sources/register.go"
      provides: "RegisterAll with 76 sources (67 + 9 Phase 16)"
      contains: "VirusTotalSource"
    - path: "cmd/recon.go"
      provides: "buildReconEngine with Phase 16 credential wiring"
      contains: "VirusTotalAPIKey"
  key_links:
    - from: "pkg/recon/sources/register.go"
      to: "pkg/recon/sources/virustotal.go"
      via: "engine.Register(&VirusTotalSource{...})"
      pattern: "VirusTotalSource"
    - from: "cmd/recon.go"
      to: "pkg/recon/sources/register.go"
      via: "sources.RegisterAll(e, cfg)"
      pattern: "sources\\.RegisterAll"
---

<objective>
Wire all 9 Phase 16 sources into RegisterAll and cmd/recon.go, bringing total from 67 to 76 sources. Add integration test validating the complete source catalog.

Purpose: Complete the last OSINT phase by connecting all new sources to the engine so `keyhunter recon list` shows 76 sources and `keyhunter recon full` sweeps them all.
Output: Updated register.go, register_test.go, cmd/recon.go
</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
@pkg/recon/sources/register.go
@cmd/recon.go
</context>

<interfaces>
From pkg/recon/sources/register.go (current):
```go
type SourcesConfig struct {
    // ... existing fields through CircleCIToken ...
    Registry *providers.Registry
    Limiters *recon.LimiterRegistry
}

func RegisterAll(engine *recon.Engine, cfg SourcesConfig) { ... } // 67 sources
```

From cmd/recon.go (current):
```go
func buildReconEngine() *recon.Engine {
    cfg := sources.SourcesConfig{
        // ... existing credential bindings ...
    }
    sources.RegisterAll(e, cfg)
}
```
</interfaces>

<tasks>

<task type="auto">
  <name>Task 1: Extend SourcesConfig, RegisterAll, and cmd/recon.go</name>
  <files>pkg/recon/sources/register.go, cmd/recon.go</files>
  <action>
Add new fields to SourcesConfig in register.go:

```go
// Phase 16: Threat intel, DNS, and API marketplace tokens.
VirusTotalAPIKey    string
IntelligenceXAPIKey string
SecurityTrailsAPIKey string
```

Add Phase 16 registrations to RegisterAll, after the Phase 15 block:

```go
// Phase 16: Threat intelligence sources.
engine.Register(&VirusTotalSource{
    APIKey:   cfg.VirusTotalAPIKey,
    Registry: reg,
    Limiters: lim,
})
engine.Register(&IntelligenceXSource{
    APIKey:   cfg.IntelligenceXAPIKey,
    Registry: reg,
    Limiters: lim,
})
engine.Register(&URLhausSource{
    Registry: reg,
    Limiters: lim,
})

// Phase 16: Mobile and DNS sources.
engine.Register(&APKMirrorSource{
    Registry: reg,
    Limiters: lim,
})
engine.Register(&CrtShSource{
    Registry: reg,
    Limiters: lim,
})
engine.Register(&SecurityTrailsSource{
    APIKey:   cfg.SecurityTrailsAPIKey,
    Registry: reg,
    Limiters: lim,
})

// Phase 16: API marketplace sources (credentialless).
engine.Register(&PostmanSource{
    Registry: reg,
    Limiters: lim,
})
engine.Register(&SwaggerHubSource{
    Registry: reg,
    Limiters: lim,
})
engine.Register(&RapidAPISource{
    Registry: reg,
    Limiters: lim,
})
```

Update RegisterAll doc comment to say "76 sources total" and mention Phase 16.

In cmd/recon.go buildReconEngine(), add the three credential fields to the SourcesConfig literal:

```go
VirusTotalAPIKey:    firstNonEmpty(os.Getenv("VIRUSTOTAL_API_KEY"), viper.GetString("recon.virustotal.api_key")),
IntelligenceXAPIKey: firstNonEmpty(os.Getenv("INTELLIGENCEX_API_KEY"), viper.GetString("recon.intelligencex.api_key")),
SecurityTrailsAPIKey: firstNonEmpty(os.Getenv("SECURITYTRAILS_API_KEY"), viper.GetString("recon.securitytrails.api_key")),
```
  </action>
  <verify>
    <automated>cd /home/salva/Documents/apikey && go build ./cmd/... && go vet ./pkg/recon/sources/ ./cmd/...</automated>
  </verify>
  <done>RegisterAll registers 76 sources, cmd/recon.go wires VT/IX/SecurityTrails credentials from env/viper, project compiles cleanly</done>
</task>

<task type="auto">
  <name>Task 2: Integration test for 76-source catalog</name>
  <files>pkg/recon/sources/register_test.go</files>
  <action>
Update or create register_test.go with an integration test that validates:

1. TestRegisterAll_SourceCount: Create a SourcesConfig with a test Registry (providers.NewRegistryFromProviders with one dummy provider) and a LimiterRegistry. Call RegisterAll on a fresh engine. Assert engine.List() returns exactly 76 names. If count differs, print the actual list for debugging.

2. TestRegisterAll_Phase16Sources: Assert the following 9 names are present in engine.List(): "virustotal", "intelligencex", "urlhaus", "apkmirror", "crtsh", "securitytrails", "postman", "swaggerhub", "rapidapi".

3. TestRegisterAll_CredentialGating: Register with empty SourcesConfig (no API keys). For each source via engine.Get(), call Enabled(recon.Config{}). Assert:
   - virustotal, intelligencex, securitytrails: Enabled == false (credential-gated)
   - urlhaus, apkmirror, crtsh, postman, swaggerhub, rapidapi: Enabled == true (credentialless)

Follow the existing test pattern from prior phases. Use testify/assert if already used in the file, otherwise use stdlib testing.
  </action>
  <verify>
    <automated>cd /home/salva/Documents/apikey && go test ./pkg/recon/sources/ -run "TestRegisterAll" -count=1 -v</automated>
  </verify>
  <done>Integration test confirms 76 registered sources, all 9 Phase 16 sources present, credential gating correct for VT/IX/SecurityTrails vs credentialless sources</done>
</task>

</tasks>

<verification>
Full build and test:
```bash
cd /home/salva/Documents/apikey && go build ./cmd/... && go test ./pkg/recon/sources/ -run "TestRegisterAll" -count=1 -v
```
</verification>

<success_criteria>
- RegisterAll registers 76 sources (67 existing + 9 new)
- cmd/recon.go reads VIRUSTOTAL_API_KEY, INTELLIGENCEX_API_KEY, SECURITYTRAILS_API_KEY from env/viper
- Integration test passes confirming source count, names, and credential gating
- `go build ./cmd/...` succeeds with no errors
</success_criteria>

<output>
After completion, create `.planning/phases/16-osint_threat_intel_mobile_dns_api_marketplaces/16-04-SUMMARY.md`
</output>
