- Added tests to `proxyhost_service_validation_test.go` to validate fallback parsing and handle invalid hostname characters. - Introduced new tests for DNS challenge validation in `proxyhost_service_validation_test.go`. - Updated `current_spec.md` to reflect changes in testing strategy and coverage goals for PR #729. - Enhanced `Security.functional.test.tsx` to include navigation test for Notifications button. - Mocked `useNavigate` from `react-router-dom` to verify navigation behavior in Security page tests.
14 KiB
post_title, categories, tags, summary, post_date
| post_title | categories | tags | summary | post_date | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Current Spec: Raise PR #729 Patch Coverage (Backend Targeted Tests) |
|
|
Focused, test-first plan to raise PR #729 patch coverage by adding targeted backend tests for low-coverage changed files, prioritized by impact and implementation risk. | 2026-02-22 |
Active Plan: Raise PR #729 Patch Coverage (Backend)
Date: 2026-02-22 Status: Active and authoritative Scope Type: Backend patch-coverage lift via targeted tests Authority: This is the only active authoritative plan section in this file.
1) Introduction
This plan targets PR #729 patch coverage gaps from docs/reports/codecove_patch_report.md with a minimal, test-first approach.
Goal:
- Raise patch coverage by adding focused backend tests for changed files with low patch %, ordered by coverage impact first and implementation risk second.
Non-goals:
- No frontend changes.
- No broad refactors.
- No production code changes unless a branch is untestable without a tiny seam.
2) Research Findings
2.1 Patch report baseline
Current patch coverage snapshot from docs/reports/codecove_patch_report.md:
backend/internal/services/enhanced_security_notification_service.go- 13.13% (285 missing + 6 partial)
backend/internal/services/notification_service.go- 75.45% (20 missing + 7 partial)
backend/internal/api/handlers/notification_provider_handler.go- 79.22% (15 missing + 1 partial)
backend/internal/api/handlers/security_notifications.go- 83.11% (10 missing + 3 partial)
backend/internal/api/handlers/feature_flags_handler.go- 71.42% (11 missing + 1 partial)
backend/internal/services/proxyhost_service.go- 33.33% (8 missing + 4 partial)
backend/internal/api/routes/routes.go- 75.00% (2 missing + 2 partial)
backend/internal/cerberus/cerberus.go- 73.33% (2 missing + 2 partial)
backend/internal/notifications/router.go- 88.23% (2 missing)
2.2 Existing test surface (reuse-first)
Existing package tests are strong and should be extended instead of introducing new harness patterns:
- Services:
backend/internal/services/notification_service_test.gobackend/internal/services/proxyhost_service_test.gobackend/internal/services/enhanced_security_notification_service_discord_only_test.go
- Handlers:
backend/internal/api/handlers/notification_provider_handler_test.gobackend/internal/api/handlers/notification_provider_patch_coverage_test.gobackend/internal/api/handlers/security_notifications_patch_coverage_test.gobackend/internal/api/handlers/feature_flags_handler_coverage_test.gobackend/internal/api/handlers/feature_flags_blocker3_test.go
- Routes:
backend/internal/api/routes/routes_coverage_test.go
- Cerberus:
backend/internal/cerberus/cerberus_test.go
- Notifications router:
backend/internal/notifications/router_test.go
2.3 Constraints
- Test-first and minimal: backend tests only by default.
- Tiny production seam allowed only for truly unreachable branches.
- Keep branch behavior assertions deterministic and table-driven where possible.
3) Requirements (EARS)
- R1: WHEN addressing PR #729 coverage gaps, THE SYSTEM SHALL prioritize files by missing patch lines first, then by implementation risk.
- R2: WHEN adding coverage, THE SYSTEM SHALL modify or add backend test files only, unless a branch is untestable without a tiny seam.
- R3: IF a tiny seam is required, THEN THE SYSTEM SHALL keep it package-local, minimal, and solely to unlock deterministic branch testing.
- R4: WHEN tests are implemented, THE SYSTEM SHALL validate with local patch report preflight, targeted tests, backend coverage script, and patch report rerun.
- R5: WHEN planning delivery, THE SYSTEM SHALL use a single PR unless scope or rollback risk materially increases.
- R6: WHEN plan is finalized, THE SYSTEM SHALL explicitly review
.gitignore,.dockerignore,codecov.yml, andDockerfilefor required updates.
4) Technical Specification
4.1 Priority model
Priority score = Coverage impact (missing+partial lines, weighted high) + implementation risk (weighted low).
| Priority | File | Coverage Gap | Risk | Strategy |
|---|---|---|---|---|
| P0 | backend/internal/services/enhanced_security_notification_service.go |
285 + 6 | Medium | New focused coverage file + extend existing Discord-only tests |
| P1 | backend/internal/services/notification_service.go |
20 + 7 | Medium | Extend existing comprehensive service tests |
| P2 | backend/internal/api/handlers/notification_provider_handler.go |
15 + 1 | Low | Extend handler patch tests for admin/error branches |
| P2 | backend/internal/api/handlers/feature_flags_handler.go |
11 + 1 | Low | Extend coverage tests for env/db parse and transaction branches |
| P2 | backend/internal/api/handlers/security_notifications.go |
10 + 3 | Low | Extend patch tests for source-validation and dispatch-failure branches |
| P3 | backend/internal/services/proxyhost_service.go |
8 + 4 | Low | Extend validation + advanced config edge branches |
| P4 | backend/internal/api/routes/routes.go |
2 + 2 | Medium | Extend route wiring error/non-fatal paths only |
| P4 | backend/internal/cerberus/cerberus.go |
2 + 2 | Low | Extend IsEnabled/cache and fail-closed dispatch edges |
| P5 | backend/internal/notifications/router.go |
2 | Low | Add table cases for missing flags/default false |
4.2 Exact target test files to modify/create
Primary target files:
backend/internal/services/enhanced_security_notification_service_discord_only_test.go(modify)backend/internal/services/enhanced_security_notification_service_coverage_test.go(create)backend/internal/services/notification_service_test.go(modify)backend/internal/api/handlers/notification_provider_patch_coverage_test.go(modify)backend/internal/api/handlers/notification_provider_handler_test.go(modify, only if needed)backend/internal/api/handlers/security_notifications_patch_coverage_test.go(modify)backend/internal/api/handlers/feature_flags_handler_coverage_test.go(modify)backend/internal/services/proxyhost_service_test.go(modify)backend/internal/api/routes/routes_coverage_test.go(modify)backend/internal/cerberus/cerberus_test.go(modify)backend/internal/notifications/router_test.go(modify)
4.3 Branch targets per file
P0: enhanced security notification service
GetSettingsfeature-flag off/on branch behavior.- Managed provider aggregation permutations (0/1/many managed destinations).
- Gotify incomplete payload rejection path.
- Idempotent
updateManagedProviders(no save when unchanged). - Migration marker checksum no-op and disabled-flag read-only migration behavior.
- Feature defaulting matrix (
CHARON_ENV,GIN_MODE,_test_mode_marker). sendWebhookSSRF rejection + non-2xx handling.
P1: notification service
- Event filtering for security event variants (
security_waf,security_acl,security_rate_limit,security_crowdsec). - Discord URL validation error branches and non-discord fail-closed paths.
UpdateProvidermutation guards (deprecated provider type/enable cases).- Template size/timeouts and payload validation branches where uncovered.
P2: handler targets
- Notification provider handler:
CreateandUpdateblocked-code branches (discord-only, immutable legacy, cannot enable deprecated).isProviderValidationErrorclassification branches.
- Security notifications handler:
- Invalid source IP parsing, unauthorized source path, malformed payload, and accepted path with dispatch error non-fatal behavior.
- Feature flags handler:
- legacy fallback hard-false resolution branches, invalid env value warning path coverage, and unknown key ignore behavior in updates.
P3-P5: lower-line but necessary gaps
- Proxy host service: malformed forward host/path stripping and advanced config normalization failure branches.
- Routes: migration invocation/error paths and non-fatal startup behavior.
- Cerberus: feature-flag absent/false fail-closed dispatch and cache refresh branch coverage.
- Notifications router: explicit default false behavior for missing flags.
4.4 Tiny seam policy (only if required)
Allowed only when a specific branch cannot be reached with current test hooks. Potential seam examples (if needed):
- Package-level function var for ticker/sleep in route boot goroutines.
- Package-level clock helper for time-dependent branch determinism.
If introduced:
- Must be private to package.
- Must not alter runtime behavior.
- Must be documented in test file rationale and removed if later unnecessary.
5) Implementation Plan
Phase 1: Baseline and preflight
- Run local patch report preflight:
bash scripts/local-patch-report.sh
- Confirm artifacts:
test-results/local-patch-report.mdtest-results/local-patch-report.json
- Capture baseline patch gaps for the 9 target files.
Phase 2: Highest-impact tests first (P0-P1)
- Implement
enhanced_security_notification_servicebranch tests. - Implement
notification_servicegap tests. - Run targeted service tests only:
go test ./backend/internal/services -run 'Test(DiscordOnly|EnhancedSecurity|NotificationService|ProxyHostService)' -count=1
Phase 3: Handler and service gap closure (P2-P3)
- Extend handler coverage tests for notification provider, security notifications, and feature flags.
- Extend proxy host service tests for uncovered validation/normalization branches.
- Run targeted handler/service tests:
go test ./backend/internal/api/handlers -run 'Test(NotificationProvider|SecurityNotification|FeatureFlags)' -count=1go test ./backend/internal/services -run 'TestProxyHostService' -count=1
Phase 4: Wiring and security/router edges (P4-P5)
- Extend route, cerberus, and notifications router tests for remaining small branch gaps.
- Run targeted package tests:
go test ./backend/internal/api/routes -run 'TestRegister' -count=1go test ./backend/internal/cerberus -run 'TestCerberus' -count=1go test ./backend/internal/notifications -run 'TestRouter' -count=1
Phase 5: Coverage validation and rerun
- Run backend coverage script:
scripts/go-test-coverage.sh
- Re-run local patch report:
bash scripts/local-patch-report.sh
- Verify patch coverage increase and remaining uncovered lines are justified or queued.
6) Validation Workflow (Required Order)
| Step | Command | Expected Result |
|---|---|---|
| 1 | npx playwright test --project=firefox |
E2E-first compliance satisfied before unit/coverage work |
| 2 | bash scripts/local-patch-report.sh |
Local patch preflight artifacts generated (.md + .json) |
| 3 | go test targeted packages/files (phased above) |
Targeted unit validation passes and intended branches are exercised |
| 4 | scripts/go-test-coverage.sh |
Targeted coverage validation passes backend coverage gate |
| 5 | bash scripts/local-patch-report.sh |
Patch % improves for PR #729 target files |
7) PR Slicing Strategy
Decision: Single PR.
Rationale:
- All work is backend test-only and tightly coupled to one outcome (patch coverage increase for PR #729).
- Review remains tractable because changes are limited to test files.
- Rollback is low risk (test-only diff).
Contingency trigger for multi-PR split (only if needed):
- If tiny production seams become necessary in multiple packages, split into:
- PR-1: minimal seam(s) + seam tests.
- PR-2: coverage tests consuming seam(s).
8) Risk Guardrail (P0 Blast Radius)
Timebox / fallback trigger:
- If, after completing P0 + P1 and running
bash scripts/local-patch-report.sh, either of the following is true:- overall patch coverage is still
< 80%, or - combined uplift from baseline is
< +8 percentage points, THEN stop further broad branch expansion and switch to fallback mode.
- overall patch coverage is still
Fallback decision path (next-step actions):
- Freeze any additional new-branch test expansion in
P2+files. - Generate and attach latest artifacts:
test-results/local-patch-report.mdtest-results/local-patch-report.json
- Run targeted gap triage on top remaining uncovered changed lines only.
- Choose one path:
- Path A (default): add one minimal seam in highest-impact file and finish in same PR.
- Path B: split into follow-up PR for seam + residual coverage if seam scope exceeds one package or introduces rollback risk.
- Re-run
bash scripts/local-patch-report.shand proceed only if targets in Section 10 are met.
9) Config File Review Outcome
Reviewed for this plan:
.gitignore.dockerignorecodecov.ymlDockerfile
Planned updates: None (test-only backend changes do not require updates).
10) Acceptance Criteria (Measurable)
Overall patch-coverage target for this PR uplift effort:
- AC1: Overall PR patch coverage (Codecov patch view) reaches
>= 85%.
Per-file patch coverage targets (from current 9-file backend target list):
- AC2:
backend/internal/services/enhanced_security_notification_service.go>= 60% - AC3:
backend/internal/services/notification_service.go>= 90% - AC4:
backend/internal/api/handlers/notification_provider_handler.go>= 92% - AC5:
backend/internal/api/handlers/security_notifications.go>= 95% - AC6:
backend/internal/api/handlers/feature_flags_handler.go>= 90% - AC7:
backend/internal/services/proxyhost_service.go>= 75% - AC8:
backend/internal/api/routes/routes.go>= 90% - AC9:
backend/internal/cerberus/cerberus.go>= 90% - AC10:
backend/internal/notifications/router.go>= 95%
Artifact-gated pass condition:
- AC11:
bash scripts/local-patch-report.shmust generate both artifacts:test-results/local-patch-report.mdtest-results/local-patch-report.json
- AC12: The generated artifacts must show overall target (AC1) and all per-file targets (AC2-AC10) as met for this uplift effort.
Process and scope checks:
- AC13: Plan remains backend test-focused with no unrelated production changes.
- AC14:
.gitignore,.dockerignore,codecov.yml, andDockerfilereview remains recorded with no required updates for this scope.