---
phase: 15-osint_forums_collaboration_log_aggregators
plan: 04
type: execute
wave: 2
depends_on:
  - 15-01
  - 15-02
  - 15-03
files_modified:
  - pkg/recon/sources/register.go
  - pkg/recon/sources/register_test.go
  - pkg/recon/sources/integration_test.go
  - cmd/recon.go
autonomous: true
requirements:
  - RECON-FORUM-01
  - RECON-FORUM-02
  - RECON-FORUM-03
  - RECON-FORUM-04
  - RECON-FORUM-05
  - RECON-FORUM-06
  - RECON-COLLAB-01
  - RECON-COLLAB-02
  - RECON-COLLAB-03
  - RECON-COLLAB-04
  - RECON-LOG-01
  - RECON-LOG-02
  - RECON-LOG-03
must_haves:
  truths:
    - "RegisterAll wires all 15 new Phase 15 sources onto the engine (67 total)"
    - "cmd/recon.go reads any new Phase 15 credentials from viper/env and passes to SourcesConfig"
    - "Integration test confirms all 67 sources are registered and forum/collab/log sources produce findings"
  artifacts:
    - path: "pkg/recon/sources/register.go"
      provides: "RegisterAll extended with 15 Phase 15 sources"
      contains: "Phase 15"
    - path: "pkg/recon/sources/register_test.go"
      provides: "Updated test expecting 67 sources"
      contains: "67"
  key_links:
    - from: "pkg/recon/sources/register.go"
      to: "pkg/recon/sources/stackoverflow.go"
      via: "engine.Register(&StackOverflowSource{})"
      pattern: "StackOverflowSource"
    - from: "pkg/recon/sources/register.go"
      to: "pkg/recon/sources/elasticsearch.go"
      via: "engine.Register(&ElasticsearchSource{})"
      pattern: "ElasticsearchSource"
    - from: "cmd/recon.go"
      to: "pkg/recon/sources/register.go"
      via: "sources.RegisterAll(engine, cfg)"
      pattern: "RegisterAll"
---

<objective>
Wire all 15 Phase 15 sources into RegisterAll, update cmd/recon.go for any new credentials, update register_test.go to expect 67 sources, and add integration test coverage.

Purpose: Complete Phase 15 by connecting all new sources to the engine and verifying end-to-end registration.
Output: Updated register.go, register_test.go, integration_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
@.planning/STATE.md
@pkg/recon/sources/register.go
@pkg/recon/sources/register_test.go
@cmd/recon.go

<interfaces>
From pkg/recon/sources/register.go (current state):
```go
type SourcesConfig struct {
    // ... existing fields for Phase 10-14 ...
    Registry *providers.Registry
    Limiters *recon.LimiterRegistry
}

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

New Phase 15 source types to register (all credentialless — no new SourcesConfig fields needed):
```go
// Forum sources (Plan 15-01):
&StackOverflowSource{Registry: reg, Limiters: lim}
&RedditSource{Registry: reg, Limiters: lim}
&HackerNewsSource{Registry: reg, Limiters: lim}
&DiscordSource{Registry: reg, Limiters: lim}
&SlackSource{Registry: reg, Limiters: lim}
&DevToSource{Registry: reg, Limiters: lim}

// Collaboration sources (Plan 15-02):
&TrelloSource{Registry: reg, Limiters: lim}
&NotionSource{Registry: reg, Limiters: lim}
&ConfluenceSource{Registry: reg, Limiters: lim}
&GoogleDocsSource{Registry: reg, Limiters: lim}

// Log aggregator sources (Plan 15-03):
&ElasticsearchSource{Registry: reg, Limiters: lim}
&GrafanaSource{Registry: reg, Limiters: lim}
&SentrySource{Registry: reg, Limiters: lim}
&KibanaSource{Registry: reg, Limiters: lim}
&SplunkSource{Registry: reg, Limiters: lim}
```
</interfaces>
</context>

<tasks>

<task type="auto">
  <name>Task 1: Wire RegisterAll + update register_test.go</name>
  <files>
    pkg/recon/sources/register.go
    pkg/recon/sources/register_test.go
  </files>
  <action>
Extend RegisterAll in register.go to register all 15 Phase 15 sources. Add a comment block:

```go
// Phase 15: Forum sources (credentialless).
engine.Register(&StackOverflowSource{Registry: reg, Limiters: lim})
engine.Register(&RedditSource{Registry: reg, Limiters: lim})
engine.Register(&HackerNewsSource{Registry: reg, Limiters: lim})
engine.Register(&DiscordSource{Registry: reg, Limiters: lim})
engine.Register(&SlackSource{Registry: reg, Limiters: lim})
engine.Register(&DevToSource{Registry: reg, Limiters: lim})

// Phase 15: Collaboration sources (credentialless).
engine.Register(&TrelloSource{Registry: reg, Limiters: lim})
engine.Register(&NotionSource{Registry: reg, Limiters: lim})
engine.Register(&ConfluenceSource{Registry: reg, Limiters: lim})
engine.Register(&GoogleDocsSource{Registry: reg, Limiters: lim})

// Phase 15: Log aggregator sources (credentialless).
engine.Register(&ElasticsearchSource{Registry: reg, Limiters: lim})
engine.Register(&GrafanaSource{Registry: reg, Limiters: lim})
engine.Register(&SentrySource{Registry: reg, Limiters: lim})
engine.Register(&KibanaSource{Registry: reg, Limiters: lim})
engine.Register(&SplunkSource{Registry: reg, Limiters: lim})
```

Update the RegisterAll doc comment to say "67 sources total" (52 + 15).

All Phase 15 sources are credentialless, so NO new SourcesConfig fields are needed. Do NOT modify SourcesConfig.

Update register_test.go:
- Rename test to TestRegisterAll_WiresAllSixtySevenSources
- Add all 15 new source names to the `want` slice in alphabetical order: "confluence", "devto", "discord", "elasticsearch", "googledocs", "grafana", "hackernews", "kibana", "notion", "reddit", "sentry", "slack", "splunk", "stackoverflow", "trello"
- Update count test to expect 67: `if n := len(eng.List()); n != 67`
  </action>
  <verify>
    <automated>cd /home/salva/Documents/apikey && go test ./pkg/recon/sources/ -run "TestRegisterAll" -count=1 -v</automated>
  </verify>
  <done>RegisterAll registers 67 sources, register_test.go passes with full alphabetical name list</done>
</task>

<task type="auto">
  <name>Task 2: Integration test + cmd/recon.go update</name>
  <files>
    pkg/recon/sources/integration_test.go
    cmd/recon.go
  </files>
  <action>
**cmd/recon.go**: No new SourcesConfig fields needed (all Phase 15 sources are credentialless). However, update any source count comments in cmd/recon.go if they reference "52 sources" to say "67 sources".

**integration_test.go**: Add a test function TestPhase15_ForumCollabLogSources that:
1. Creates httptest servers for at least 3 representative sources (stackoverflow, trello, elasticsearch).
2. Registers those sources with BaseURL pointed at the test servers.
3. Calls Sweep on each, collects findings from the channel.
4. Asserts at least one finding per source with correct SourceType.

The test servers should return mock JSON responses that contain API key patterns (e.g., `sk-proj-ABCDEF1234567890` in a Stack Overflow answer body, a Trello card description, and an Elasticsearch document _source).

Follow the existing integration_test.go patterns for httptest setup and assertion style.
  </action>
  <verify>
    <automated>cd /home/salva/Documents/apikey && go test ./pkg/recon/sources/ -run "TestPhase15" -count=1 -v</automated>
  </verify>
  <done>Integration test passes confirming Phase 15 sources produce findings from mock servers; cmd/recon.go updated</done>
</task>

</tasks>

<verification>
cd /home/salva/Documents/apikey && go build ./... && go vet ./...
cd /home/salva/Documents/apikey && go test ./pkg/recon/sources/ -run "TestRegisterAll|TestPhase15" -count=1
cd /home/salva/Documents/apikey && go test ./pkg/recon/sources/ -count=1
</verification>

<success_criteria>
- RegisterAll registers exactly 67 sources (52 existing + 15 new)
- All source names appear in alphabetical order in register_test.go
- Integration test confirms representative Phase 15 sources produce findings
- Full test suite passes: go test ./pkg/recon/sources/ -count=1
- go build ./... compiles cleanly
</success_criteria>

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