docs(10-osint-code-hosting): create phase 10 plans (9 plans across 3 waves)
This commit is contained in:
113
.planning/phases/10-osint-code-hosting/10-05-PLAN.md
Normal file
113
.planning/phases/10-osint-code-hosting/10-05-PLAN.md
Normal file
@@ -0,0 +1,113 @@
|
||||
---
|
||||
phase: 10-osint-code-hosting
|
||||
plan: 05
|
||||
type: execute
|
||||
wave: 2
|
||||
depends_on: [10-01]
|
||||
files_modified:
|
||||
- pkg/recon/sources/codeberg.go
|
||||
- pkg/recon/sources/codeberg_test.go
|
||||
autonomous: true
|
||||
requirements: [RECON-CODE-05]
|
||||
must_haves:
|
||||
truths:
|
||||
- "CodebergSource queries Gitea REST API /api/v1/repos/search and /api/v1/repos/.../contents for keyword matches"
|
||||
- "No token required for public repos (but optional token honored if provided)"
|
||||
- "Findings tagged SourceType=\"recon:codeberg\""
|
||||
artifacts:
|
||||
- path: "pkg/recon/sources/codeberg.go"
|
||||
provides: "CodebergSource implementing recon.ReconSource (Gitea-compatible)"
|
||||
key_links:
|
||||
- from: "pkg/recon/sources/codeberg.go"
|
||||
to: "pkg/recon/sources/httpclient.go"
|
||||
via: "Client.Do"
|
||||
pattern: "client\\.Do"
|
||||
---
|
||||
|
||||
<objective>
|
||||
Implement CodebergSource targeting Gitea's REST API. Codeberg.org runs Gitea, so the
|
||||
same code works for any Gitea instance by configuring BaseURL. Public repos do not
|
||||
require auth, but a token can be passed to raise rate limits.
|
||||
|
||||
Purpose: RECON-CODE-05.
|
||||
Output: pkg/recon/sources/codeberg.go + tests.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@$HOME/.claude/get-shit-done/workflows/execute-plan.md
|
||||
@$HOME/.claude/get-shit-done/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<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
|
||||
|
||||
<interfaces>
|
||||
Gitea API (v1, docs: https://docs.gitea.com/api):
|
||||
GET /api/v1/repos/search?q=<query>&limit=50
|
||||
Response: { "data": [{ "full_name": "...", "html_url": "..." }], "ok": true }
|
||||
Header (optional): Authorization: token <token>
|
||||
|
||||
For 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.
|
||||
</interfaces>
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto" tdd="true">
|
||||
<name>Task 1: CodebergSource + tests</name>
|
||||
<files>pkg/recon/sources/codeberg.go, pkg/recon/sources/codeberg_test.go</files>
|
||||
<behavior>
|
||||
- Test A: Enabled always true (public API, token optional)
|
||||
- Test B: Sweep queries /api/v1/repos/search?q=<query>&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 <t>"; without token, header absent
|
||||
- Test E: Ctx cancellation
|
||||
- Test F: Unauth rate limit applied when Token empty (verified via RateLimit() return)
|
||||
</behavior>
|
||||
<action>
|
||||
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=<q>&limit=50`, set Authorization only when Token set, client.Do, decode, emit Findings
|
||||
- Compile-time assert
|
||||
|
||||
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).
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /home/salva/Documents/apikey && go test ./pkg/recon/sources/ -run TestCodeberg -v -timeout 30s</automated>
|
||||
</verify>
|
||||
<done>
|
||||
CodebergSource implements ReconSource, tests green for both auth modes.
|
||||
</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
- `go test ./pkg/recon/sources/ -run TestCodeberg -v`
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
RECON-CODE-05 satisfied.
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/10-osint-code-hosting/10-05-SUMMARY.md`.
|
||||
</output>
|
||||
Reference in New Issue
Block a user