- Added tests for transient SQLite errors in emergency_handler_test.go. - Introduced validation tests for provider errors in notification_provider_handler_validation_test.go. - Implemented helper tests for settings handling in settings_handler_helpers_test.go. - Expanded backup_handler_test.go to include SQLite database setup and validation. - Improved system_permissions_handler_test.go with additional path repair tests. - Updated backup_service_test.go to ensure proper database handling and error checks during backup operations. - Refined import_handler_test.go with additional session validation tests.
199 lines
8.7 KiB
Markdown
199 lines
8.7 KiB
Markdown
# PR #666 Patch Coverage Recovery Spec (Approval-Ready)
|
|
|
|
Date: 2026-02-16
|
|
Owner: Planning Agent
|
|
Status: Draft for Supervisor approval (single coherent plan)
|
|
|
|
## 1) Scope Decision (Unified)
|
|
|
|
### In Scope
|
|
- Backend unit-test additions only, targeting changed patch lines in backend handlers/services/utils.
|
|
- Minimum-risk posture: prioritize test-only additions in files already touched by PR #666 before opening any new test surface.
|
|
- Coverage validation using current backend coverage task/script.
|
|
|
|
### Out of Scope
|
|
- E2E/Playwright, integration, frontend, Docker, and security scan remediation.
|
|
|
|
### E2E Decision for this task
|
|
- E2E is explicitly **out-of-scope** for this patch-coverage remediation.
|
|
- Rationale: target metric is Codecov patch lines on backend changes; E2E adds runtime risk/cycle time without direct line-level patch closure.
|
|
|
|
### Scope Reconciliation with Current Implementation (PR #666)
|
|
Confirmed already touched backend test files:
|
|
- `backend/internal/api/handlers/import_handler_test.go`
|
|
- `backend/internal/api/handlers/settings_handler_helpers_test.go`
|
|
- `backend/internal/api/handlers/emergency_handler_test.go`
|
|
- `backend/internal/services/backup_service_test.go`
|
|
- `backend/internal/api/handlers/backup_handler_test.go`
|
|
- `backend/internal/api/handlers/system_permissions_handler_test.go`
|
|
- `backend/internal/api/handlers/notification_provider_handler_validation_test.go`
|
|
|
|
Optional/deferred (not yet touched in current remediation pass):
|
|
- `backend/internal/util/permissions_test.go`
|
|
- `backend/internal/services/notification_service_json_test.go`
|
|
- `backend/internal/services/backup_service_rehydrate_test.go`
|
|
- `backend/internal/api/handlers/security_handler_coverage_test.go`
|
|
|
|
## 2) Single Source of Truth for Success
|
|
|
|
Authoritative success metric:
|
|
- **Codecov PR patch status (`lines`)** is the source of truth for this task.
|
|
|
|
Relationship to `codecov.yml`:
|
|
- `coverage.status.patch.default.target: 100%` and `required: false` means patch status is advisory in CI.
|
|
- For this plan, we set an internal quality gate: **patch lines >= 85%** (minimum), preferred **>= 87%** buffer.
|
|
- Local script output (`go tool cover`) remains diagnostic; pass/fail is decided by Codecov patch `lines` after upload.
|
|
|
|
## 3) Feasibility Math and Coverage-Line Budget
|
|
|
|
Given baseline:
|
|
- Patch coverage = `60.84011%`
|
|
- Missing patch lines = `578`
|
|
|
|
Derived totals:
|
|
- Let total patch lines = `T`
|
|
- `578 = T * (1 - 0.6084011)` => `T ≈ 1476`
|
|
- Currently covered lines `C0 = 1476 - 578 = 898`
|
|
|
|
Required for >=85%:
|
|
- `C85 = ceil(0.85 * 1476) = 1255`
|
|
- Additional covered lines required: `1255 - 898 = 357`
|
|
|
|
Budget by phase (line-coverage gain target):
|
|
|
|
| Phase | Target line gain | Cumulative gain target | Stop/Go threshold |
|
|
|---|---:|---:|---|
|
|
| Phase 1 | +220 | +220 | Stop if <+170; re-scope before Phase 2 |
|
|
| Phase 2 | +100 | +320 | Stop if <+70; activate residual plan |
|
|
| Phase 3 (residual closure) | +45 | +365 | Must reach >=+357 total |
|
|
|
|
Notes:
|
|
- Planned total gain `+365` gives `+8` lines safety over minimum `+357`.
|
|
- If patch denominator changes due to rebase/new touched lines, recompute budget before continuing.
|
|
|
|
## 4) Target Files/Functions (Concise, Specific)
|
|
|
|
Primary hotspots (Phase 1 focus, aligned to touched tests first):
|
|
- `backend/internal/api/handlers/system_permissions_handler.go`
|
|
- `RepairPermissions`, `repairPath`, `normalizePath`, `pathHasSymlink`, `isWithinAllowlist`, `mapRepairErrorCode`
|
|
- `backend/internal/services/backup_service.go`
|
|
- `RestoreBackup`, `extractDatabaseFromBackup`, `unzipWithSkip`, `RehydrateLiveDatabase`, `GetAvailableSpace`
|
|
- `backend/internal/api/handlers/settings_handler.go`
|
|
- `UpdateSetting`, `PatchConfig`, `validateAdminWhitelist`, `syncAdminWhitelistWithDB`
|
|
- `backend/internal/api/handlers/import_handler.go`
|
|
- `GetStatus`, `Upload`, `Commit`, `Cancel`, `safeJoin`
|
|
- `backend/internal/api/handlers/backup_handler.go`
|
|
- `Restore`, `isSQLiteTransientRehydrateError`
|
|
- `backend/internal/api/handlers/emergency_handler.go`
|
|
- `SecurityReset`, `disableAllSecurityModules`, `upsertSettingWithRetry`
|
|
- `backend/internal/api/handlers/notification_provider_handler.go`
|
|
- `isProviderValidationError`, provider validation branches
|
|
|
|
Secondary hotspots (Phase 2 focus, optional/deferred expansion):
|
|
- `backend/internal/api/handlers/security_handler.go` (`GetStatus`, `latestConfigApplyState`)
|
|
- `backend/internal/util/permissions.go` (`CheckPathPermissions`, `MapSaveErrorCode`, `MapDiagnosticErrorCode`)
|
|
- `backend/internal/services/notification_service.go` (`sendJSONPayload`, `TestProvider`, `RenderTemplate`)
|
|
|
|
## 5) Execution Phases with Strict Stop/Go and De-Scoping Rules
|
|
|
|
### Phase 0 - Baseline Lock
|
|
Actions:
|
|
- Run `Test: Backend with Coverage` task (`.github/skills/scripts/skill-runner.sh test-backend-coverage`).
|
|
- Record baseline patch lines from Codecov PR view and local artifact `backend/coverage.txt`.
|
|
|
|
Go gate:
|
|
- Baseline captured and denominator confirmed.
|
|
|
|
Stop gate:
|
|
- If patch denominator changed by >5% from 1476, pause and recompute budgets before coding.
|
|
|
|
### Phase 1 - High-yield branch closure
|
|
Actions:
|
|
- Extend existing tests only in:
|
|
- `backend/internal/api/handlers/system_permissions_handler_test.go`
|
|
- `backend/internal/services/backup_service_test.go`
|
|
- `backend/internal/api/handlers/backup_handler_test.go`
|
|
- `backend/internal/api/handlers/emergency_handler_test.go`
|
|
- `backend/internal/api/handlers/settings_handler_helpers_test.go`
|
|
- `backend/internal/api/handlers/import_handler_test.go`
|
|
- `backend/internal/api/handlers/notification_provider_handler_validation_test.go`
|
|
|
|
Go gate:
|
|
- Achieve >= `+170` covered patch lines and no failing backend tests.
|
|
|
|
Stop gate:
|
|
- If < `+170`, do not proceed; re-scope to only highest delta-per-test functions.
|
|
|
|
### Phase 2 - Secondary branch fill
|
|
Actions:
|
|
- Extend tests in:
|
|
- `backend/internal/api/handlers/security_handler_coverage_test.go`
|
|
- `backend/internal/util/permissions_test.go`
|
|
- `backend/internal/services/backup_service_rehydrate_test.go`
|
|
- `backend/internal/services/notification_service_json_test.go`
|
|
|
|
Go gate:
|
|
- Additional >= `+70` covered patch lines in this phase.
|
|
|
|
Stop gate:
|
|
- If < `+70`, skip low-yield areas and move directly to residual-line closure.
|
|
|
|
### Phase 3 - Residual-line closure (minimum-risk)
|
|
Actions:
|
|
- Work only uncovered/partial lines still shown in Codecov patch details.
|
|
- Add narrow table-driven tests to existing files; no new harness/framework.
|
|
|
|
Go gate:
|
|
- Reach total >= `+357` covered lines and patch >=85%.
|
|
|
|
Stop gate:
|
|
- If a residual branch requires production refactor, de-scope it and log as follow-up.
|
|
|
|
### Global de-scope rules (all phases)
|
|
- No production code changes unless a test proves a correctness bug.
|
|
- No new test framework, no integration/E2E expansion, no unrelated cleanup.
|
|
- No edits outside targeted backend test and directly related helper files.
|
|
|
|
## 6) Current Tasks/Scripts (Deprecated references removed)
|
|
|
|
Use these current commands/tasks only:
|
|
- Backend coverage (preferred): `Test: Backend with Coverage`
|
|
- command: `.github/skills/scripts/skill-runner.sh test-backend-coverage`
|
|
- Equivalent direct script: `bash scripts/go-test-coverage.sh`
|
|
- Optional backend unit quick check: `Test: Backend Unit Tests`
|
|
- command: `.github/skills/scripts/skill-runner.sh test-backend-unit`
|
|
|
|
Deprecated tasks are explicitly out-of-plan (for this work):
|
|
- `Security: CodeQL Go Scan (DEPRECATED)`
|
|
- `Security: CodeQL JS Scan (DEPRECATED)`
|
|
|
|
## 7) Residual Uncovered Lines Handling (Beyond hotspot table)
|
|
|
|
After each phase, run a residual triage loop:
|
|
1. Export remaining uncovered/partial patch lines from Codecov patch detail.
|
|
2. Classify each residual line into one of:
|
|
- `validation/error mapping`
|
|
- `permission/role guard`
|
|
- `fallback/retry`
|
|
- `low-value defensive log/telemetry`
|
|
3. Apply closure rule:
|
|
- First three classes: add targeted tests in existing suite.
|
|
- Last class: close only if deterministic and cheap; otherwise de-scope with rationale.
|
|
4. Maintain a residual ledger in the PR description:
|
|
- line(s), owning function, planned test, status (`closed`/`de-scoped`), reason.
|
|
|
|
Exit condition:
|
|
- No unclassified residual lines remain.
|
|
- Any de-scoped residual lines have explicit follow-up items.
|
|
|
|
## 8) Acceptance Criteria (Unified)
|
|
|
|
1. One coherent plan only (this document), no conflicting statuses.
|
|
2. E2E explicitly out-of-scope for this patch-coverage task.
|
|
3. Success is measured by Codecov patch `lines`; local statement output is diagnostic only.
|
|
4. Feasibility math and phase budgets remain explicit and tracked against actual deltas.
|
|
5. All phase stop/go gates enforced; de-scope rules followed.
|
|
6. Only current tasks/scripts are referenced.
|
|
7. Residual uncovered lines are either closed with tests or formally de-scoped with follow-up.
|
|
8. Scope remains reconciled with touched files first; deferred files are only pulled in if phase gates require expansion.
|