4.3 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
| phase | plan | type | wave | depends_on | files_modified | autonomous | requirements | must_haves | |||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 10-osint-code-hosting | 05 | execute | 2 |
|
|
true |
|
|
Purpose: RECON-CODE-05. Output: pkg/recon/sources/codeberg.go + tests.
<execution_context> @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md </execution_context>
@.planning/phases/10-osint-code-hosting/10-CONTEXT.md @.planning/phases/10-osint-code-hosting/10-01-SUMMARY.md @pkg/recon/source.go @pkg/recon/sources/httpclient.go Gitea API (v1, docs: https://docs.gitea.com/api): GET /api/v1/repos/search?q=&limit=50 Response: { "data": [{ "full_name": "...", "html_url": "..." }], "ok": true } Header (optional): Authorization: tokenFor this phase we only use /repos/search — matching on repo metadata (name/description). Full-content code search is not uniformly available across Gitea instances (Codeberg has gitea "code search" enabled via Bleve index; we rely on it when present via GET /api/v1/repos/search?q=... which returns repos only. For content matching we fall back to searching each provider keyword as a query string and emitting Findings keyed to the repo html_url).
Rate: public unauth 60 req/hour → rate.Every(60 * time.Second). Burst 1. With token: 1000/hour → rate.Every(3600 * time.Millisecond). Detect via token presence.
Task 1: CodebergSource + tests pkg/recon/sources/codeberg.go, pkg/recon/sources/codeberg_test.go - Test A: Enabled always true (public API, token optional) - Test B: Sweep queries /api/v1/repos/search?q=&limit=50 for each BuildQueries entry - Test C: Decodes `{data:[{full_name,html_url}]}` and emits Finding with Source=html_url, SourceType="recon:codeberg", ProviderName from keywordIndex - Test D: With token set, Authorization header is "token "; without token, header absent - Test E: Ctx cancellation - Test F: Unauth rate limit applied when Token empty (verified via RateLimit() return) Create `pkg/recon/sources/codeberg.go`: - Struct `CodebergSource { Token, BaseURL string; Registry *providers.Registry; Limiters *recon.LimiterRegistry; client *Client }` - Default BaseURL: `https://codeberg.org` - Name "codeberg", RespectsRobots false - RateLimit(): if Token == "" return rate.Every(60*time.Second), else rate.Every(3600*time.Millisecond) - Burst 1 - Enabled always returns true - Sweep: for each query, build `base + /api/v1/repos/search?q=&limit=50`, set Authorization only when Token set, client.Do, decode, emit Findings - Compile-time assertcd /home/salva/Documents/apikey && go test ./pkg/recon/sources/ -run TestCodeberg -v -timeout 30s CodebergSource implements ReconSource, tests green for both auth modes. - `go test ./pkg/recon/sources/ -run TestCodeberg -v`Create `pkg/recon/sources/codeberg_test.go` with httptest server returning a `{data:[...],ok:true}` body. Two test cases: with token (header present) and without (header absent — use a flag inside the handler to capture).
<success_criteria> RECON-CODE-05 satisfied. </success_criteria>
After completion, create `.planning/phases/10-osint-code-hosting/10-05-SUMMARY.md`.