14 KiB
Executable File
Patch Coverage Remediation Plan (Codecov) — Backend
Created: 2026-01-09
Note: This plan was moved from
docs/plans/current_spec.mdto keep the current plan focused on security remediation.
Goal
Restore Codecov patch coverage to green by ensuring 100% of modified lines are executed by tests.
- Codecov patch coverage: 92.93866%
- Reported missing patch lines: ~99
Hard constraints:
- Do not lower Codecov thresholds.
- Fix with targeted tests (only add micro “test hooks” if absolutely unavoidable).
Scope (two workstreams; both in-scope)
Workstream A (required): Patch coverage fixes for 10 backend files
This workstream fixes Codecov patch coverage by adding targeted tests (and only minimal seams if unavoidable) for the following backend files:
- backend/internal/api/handlers/plugin_handler.go
- backend/internal/api/handlers/encryption_handler.go
- backend/internal/api/handlers/credential_handler.go
- backend/internal/api/handlers/settings_handler.go
- backend/internal/api/handlers/crowdsec_handler.go
- backend/internal/api/handlers/proxy_host_handler.go
- backend/internal/api/handlers/security_handler.go
- backend/internal/caddy/config.go
- backend/internal/caddy/client.go
- backend/internal/api/handlers/testdb.go (special: ignored in
.codecov.ymlbut may still show up)
Workstream B (required): Prevention updates (instructions + agent files)
This workstream updates the following files to ensure future production-code changes include the patch-coverage triage + tests needed to keep Codecov patch coverage green:
- .github/instructions/testing.instructions.md
- .github/instructions/copilot-instructions.md
- .github/instructions/taming-copilot.instructions.md
- .github/agents/Backend_Dev.agent.md
- .github/agents/QA_Security.agent.md
- .github/agents/Supervisor.agent.md
- .github/agents/Frontend_Dev.agent.md (only if frontend changes are involved; otherwise leave untouched)
Non-goals:
- No unrelated refactors.
- No new integration tests requiring external services.
Missing Files Table (copy from Codecov patch report)
Codecov “Patch” view is the source of truth. Paste the exact missing/partial line ranges into this table.
Note: Codecov “Patch” view is the source of truth. This table is only for tracking what you copied from Codecov and what test you’ll add.
| File | Missing patch line ranges (Codecov) | Partial patch line ranges (Codecov) | Primary test strategy |
|---|---|---|---|
| backend/internal/api/handlers/plugin_handler.go | (paste) | (paste) | Gin handler tests (httptest) to hit error + warn-but-200 branches |
| backend/internal/api/handlers/encryption_handler.go | (paste) | (paste) | Handler tests for rotate/validate error + success branches |
| backend/internal/api/handlers/credential_handler.go | (paste) | (paste) | Handler tests for parse/notfound/service-error branches |
| backend/internal/api/handlers/settings_handler.go | (paste) | (paste) | Handler tests for URL test/SSRF + “reachable=false” mapping |
| backend/internal/api/handlers/crowdsec_handler.go | (paste) | (paste) | Handler tests using httptest.Server to force non-200/non-JSON branches |
| backend/internal/api/handlers/proxy_host_handler.go | (paste) | (paste) | Handler tests for JSON type coercion and invalid payload validation |
| backend/internal/api/handlers/security_handler.go | (paste) | (paste) | Handler tests for effective-status branches + validation branches |
| backend/internal/caddy/config.go | (paste) | (paste) | Unit tests for helper branches + config generation edge cases |
| backend/internal/caddy/client.go | (paste) | (paste) | Unit tests for HTTP non-200 + endpoint/parse branches |
| backend/internal/api/handlers/testdb.go | (paste) | (paste) | Prefer moving helpers into *_test.go; else fix ignore/path mismatch |
Why patch coverage missed (common patterns)
Patch coverage misses are usually caused by newly-changed lines being in branches that existing tests don’t naturally hit:
- Error-only branches (DB errors, JSON decode failures, upstream non-200)
- “Warn but succeed” flows (HTTP 200 with a warning field)
- JSON type coercion (e.g.,
map[string]anydecoding numbers vs strings) - Env-driven branches (missing
t.Setenvin tests) - Codecov ignore/path normalization mismatch (repo-relative path vs module path in coverprofile)
Handling partial (yellow) patch lines
Partial patch lines (yellow) usually mean the line executed, but not all branches associated with that line did.
Common causes:
- Short-circuit boolean logic (e.g.,
a && b,a || b) where tests only exercise one side. - Multi-branch conditionals (
if/else if/else,switch) where only one case is hit. - Error wrapping/logging paths that run only when an upstream returns an error.
Guidance:
- Treat yellow lines like “missing branch coverage”, not “missing statement coverage”.
- Write the smallest additional test that triggers the unhit branch (invalid input, not-found, service error, upstream non-200, etc.).
- Prefer deterministic seams:
httptest.Serverfor upstream failures; fake services/mocks for DB/service errors; explicitt.Setenvfor env-driven branches.
How to locate exact missing lines in Codecov (triage)
- Open the PR in GitHub.
- Open the Codecov check details (“Details” / “View report”).
- Switch to Patch (not Project).
- Filter to the 10 scoped files.
- For each file, copy the exact missing (red) and partial (yellow) line ranges.
- Map each range to a minimal test that executes the branch.
Local assist (for understanding branches; Codecov still authoritative):
- Run VS Code task: Test: Backend with Coverage.
- View coverage HTML:
go tool cover -html=backend/coverage.txt.
Remediation Plan (tight, test-first)
- Extract missing patch line ranges from Codecov and fill the table above.
- For each missing range:
- Identify the branch (if/switch/early return) causing it.
- Add the shortest test that executes it.
- Re-run VS Code task Test: Backend with Coverage.
- Confirm Codecov patch view is green (100% patch coverage).
Per-File Testing Strategy (scoped)
Only add tests that hit the lines Codecov marks missing.
1) backend/internal/api/handlers/plugin_handler.go
- Prioritize handler tests that cover:
- invalid
:idparsing → 400 - not found → 404
- DB update failures → 500
- loader reload/load failures (often warn-but-200) → assert response body, not just status
- invalid
2) backend/internal/api/handlers/encryption_handler.go
- Add/extend tests to cover:
- request bind/validation errors → 400
- service-layer failures → 500
- success path + any new audit/log branches
3) backend/internal/api/handlers/credential_handler.go
- Add/extend tests to cover:
- invalid ID parse → 400
- not found → 404
- create/update invalid provider / credential validation failures (where applicable)
- “test credentials” endpoint: service error mapping
4) backend/internal/api/handlers/settings_handler.go
- Add/extend tests to cover:
- invalid URL input → 400
- SSRF-blocked / unreachable cases that return 200 but set
reachable=false - network failures and how they’re represented in the response
5) backend/internal/api/handlers/crowdsec_handler.go
- Use
httptest.Serverto deterministically cover:- upstream non-200 responses
- upstream non-JSON responses
- query param forwarding (capture server request URL)
6) backend/internal/api/handlers/proxy_host_handler.go
- Add/extend tests that submit JSON payloads exercising type coercion:
- wrong types (string vs number) → 400
- boundary values (negative ports, missing required fields)
- normalization branches (if Codecov points to them)
7) backend/internal/api/handlers/security_handler.go
- Add/extend tests to cover:
- effective-status branch selection (settings vs DB vs defaults)
- validation branches (IP/CIDR parsing, enum validation, etc.)
8) backend/internal/caddy/config.go
- Prefer helper-level unit tests (cheaper and more targeted) to cover:
- header normalization helpers
- CSP/security header composition
- CIDR parsing and bypass list validation
- skip/empty branches (e.g., “missing provider config → skip policy”)
9) backend/internal/caddy/client.go
- Add/extend tests for:
- endpoint validation failures
- HTTP non-200 response branches
- parse/marshal error branches (only if Codecov points to them)
10) backend/internal/api/handlers/testdb.go (special)
If Codecov patch view includes this file:
What’s happening:
.codecov.ymlcurrently ignoresbackend/internal/api/handlers/testdb.go, but Go coverprofiles can report paths as module-import paths (example frombackend/coverage.txt):github.com/Wikid82/charon/backend/internal/.../testdb.go.- If Codecov is matching against the coverprofile path form, the repo-relative ignore may not apply.
Make it actionable:
- Confirm what path form the coverprofile is using:
grep -n "testdb.go" backend/coverage.txt
- If the result is a module/import-path form (example:
github.com/Wikid82/charon/backend/internal/api/handlers/testdb.go), add one additional ignore entry to.codecov.ymlso it matches what Codecov is actually seeing.
- Minimal, explicit (exact repo/module path):
"**/github.com/Wikid82/charon/backend/internal/api/handlers/testdb.go" - More resilient (still narrow):
"**/github.com/**/backend/internal/api/handlers/testdb.go"
Note:
- Do not add
"**/backend/internal/api/handlers/testdb.go"unless it’s missing; the repo-relative ignore is already present.
Why this is minimal:
.codecov.ymlalready ignores the repo-relative path, but ignore matching can fail if Codecov consumes coverprofile paths that include the module/import prefix.- Only add the extra ignore if the grep confirms the import-path form is present.
Preferred approach (in order):
- Move test-only helpers into a
_test.gofile.
- Caution: this is only safe if no other packages’ tests import those helpers. Anything in
*_test.gocannot be imported by other packages.
- Otherwise, keep the helper in non-test code but rely on
.codecov.ymlignores that match the coverprofile path form.
Prevention: required instruction/agent updates (diff-style)
These are the minimal guardrails to prevent future patch-coverage regressions.
A) .github/instructions/testing.instructions.md
@@
## 3. Coverage & Completion
* **Coverage Gate:** A task is not "Complete" until a coverage report is generated.
* **Threshold Compliance:** You must compare the final coverage percentage against the project's threshold (Default: 85% unless specified otherwise). If coverage drops, you must identify the "uncovered lines" and add targeted tests.
+* **Patch Coverage Gate (Codecov):** If production code is modified, Codecov **patch coverage must be 100%** for the modified lines. Do not relax thresholds; add targeted tests.
+* **Patch Triage Requirement:** Plans must include the exact missing/partial patch line ranges copied from Codecov’s **Patch** view.
B) .github/instructions/taming-copilot.instructions.md
@@
## Surgical Code Modification
- **Focus on the Core Request**: Generate code that directly addresses the user's request, without adding extra features or handling edge cases that were not mentioned.
+ **Focus on the Core Request**: Generate code that directly addresses the user's request, without adding extra features or handling edge cases that were not mentioned.
+ **Spec Hygiene**: When asked to update a plan/spec file, do not append unrelated/archived plans; keep it strictly scoped to the current task.
C) .github/instructions/copilot-instructions.md
@@
3. **Coverage Testing** (MANDATORY - Non-negotiable):
- - **MANDATORY**: Patch coverage must cover 100% of new/modified code. This prevents CodeCov Report failing CI.
+ - **MANDATORY**: Patch coverage must cover 100% of modified lines (Codecov Patch view must be green). If patch coverage fails, add targeted tests for the missing patch line ranges.
D) .github/agents/Backend_Dev.agent.md
@@
3. **Verification (Definition of Done)**:
@@
- - **Coverage (MANDATORY)**: Run the coverage script explicitly. This is NOT run by pre-commit automatically.
+ - **Coverage (MANDATORY)**: Run the coverage task/script explicitly and confirm Codecov patch view is green for modified lines.
E) .github/agents/Frontend_Dev.agent.md (only if frontend changes are involved)
@@
3. **Verification (Quality Gates)**:
@@
- **Gate 3: Coverage (MANDATORY)**:
@@
- **MANDATORY**: Patch coverage must cover 100% of new/modified code. This prevents CodeCov Report failing CI.
+ - If patch coverage fails, identify missing patch line ranges in Codecov Patch view and add targeted tests.
F) .github/agents/QA_Security.agent.md
@@
- - When creating tests, if there are folders that don't require testing make sure to update `.codecov.yml` to exclude them from coverage reports or this throws off the difference between local and CI coverage.
+ - Prefer fixing patch coverage with tests. Only adjust `.codecov.yml` ignores when code is truly non-production (e.g., test-only helpers), and document why.
G) .github/agents/Supervisor.agent.md
@@
- - **Plan Completeness**: Does the plan cover all edge cases? Are there any missing components or unclear requirements?
+ - **Plan Completeness**: Does the plan cover all edge cases? Are there any missing components or unclear requirements?
+ - **Patch Coverage Completeness**: If coverage is in scope, does the plan include Codecov Patch missing/partial line ranges and the exact tests needed to execute them?
Validation Checklist (patch-coverage scope)
Required vs optional alignment:
- Required for this plan to be considered complete: Workstream A + Workstream B changes landed.
- This validation checklist is intentionally focused on Workstream A (patch coverage remediation). For additional repo-wide Definition of Done items, follow
.github/instructions/copilot-instructions.md. - Workstream B validation is “diff applied + reviewer confirmation” (it doesn’t impact Go patch coverage directly).
Run these tasks in order:
- Test: Backend with Coverage
- Pass criteria: task succeeds;
backend/coverage.txtgenerated; zero failing tests. - Outcome criteria: Codecov patch status becomes green (100% patch coverage).
- Lint: Pre-commit (All Files) (optional; general DoD)
- Pass criteria: all hooks pass.