Files
Redflag/docs/C1_Verification_Report.md
jpetree331 1b2aa1bf63 verify: C-1 Windows bug fixes verified
All 8 C-1 fixes verified. Linux builds clean on AMD64 and ARM64.
98 tests pass (19 scanner + 4 internal + 14 crypto + 3 circuit +
58 server), 1 skip (pre-existing). No regressions.

DEV-030: polling loop parity (not deduplication) — gaps documented.
DEV-031: ghost update fix is detection-only, not prevention.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 09:21:16 -04:00

139 lines
5.2 KiB
Markdown

# C-1 Verification Report
**Date:** 2026-03-29
**Branch:** culurien
---
## PART 1: BUILD & TEST
### Builds
- **Linux AMD64**: PASS (all C-1 packages compile cleanly; pre-existing migration/pathutils error unrelated)
- **Linux ARM64**: PASS (same)
- **Windows AMD64**: PASS (docker-compose cross-compiles successfully)
### Test Counts
- Scanner: 19 tests, 19 PASS
- Agent internal: 4 tests, 4 PASS
- Agent crypto: 14 tests, 14 PASS
- Agent circuitbreaker: 3 tests, 3 PASS
- Server: 59 tests, 58 PASS + 1 SKIP
- **Total: 99 tests, 98 PASS, 1 SKIP, 0 FAIL**
Previous B-2 baseline: 77 tests. C-1 adds 19 scanner tests + 3 circuitbreaker = 22 new.
### State-Change Confirmation
All 8 FAIL-NOW tests flipped to PASS. All 11 PASS-NOW tests updated correctly.
---
## PART 2: POLLING LOOP PARITY (F-C1-5) — PASS
- Proportional jitter: `maxJitter = pollingInterval / 2`, capped at 30s — present at lines 179-186
- Exponential backoff: `calculateBackoff()` at line 623-635, base=10s, cap=5min
- `consecutiveFailures` counter: incremented on error (lines 244, 257, 264), reset on success (line 271)
- Log format: `[WARNING] [agent] [service] server_unavailable attempt=%d` — ETHOS compliant
- TODO comment for deduplication: present at line 165
### Remaining Gaps
The Windows service runAgent() does NOT have:
- `ShouldRefreshKey` / `RefreshPrimaryKey` cycle (A-1)
- `CleanupExecutedIDs` (B-2 F-B2-2)
These are in main.go's polling loop but absent from service/windows.go. The impact is LOW — key refresh is needed only every 6 hours and is handled by the key cache fallback. Command dedup cleanup runs every 6 hours and is non-critical. Documented as future deduplication work.
---
## PART 3: WINGET PATH DETECTION (F-C1-1) — PASS
- Lookup order: 1) `exec.LookPath`, 2) `C:\Windows\System32\winget.exe`, 3) `filepath.Glob` for WindowsApps
- Linux safety: `filepath.Glob` with Windows paths returns nil on Linux, `os.Stat` returns error — both graceful
- Not-found: returns `fmt.Errorf`, caller logs and skips — no panic
- Log: `[INFO] [agent] [scanner] winget_found_at path=%q` and `winget_not_found`
---
## PART 4: GHOST UPDATES (F-C1-3) — PASS (partial fix)
- `RebootRequired = true` set on InstallResult post-install (line 107)
- Log: `[INFO] [agent] [installer] windows_update_installed packages=%v reboot_required=%v`
- RebootRequired field added to InstallResult struct with JSON tag
**WARNING: Detection only, not full prevention.** The `RebootRequired` flag is set on the InstallResult and reported to the server, but the scanner does NOT filter out recently-installed updates. The next scan will still return the update as available until Windows commits the install state. This is a partial fix — the server/dashboard can use the flag to show "reboot required" status, but the ghost update will still appear in scan results.
Full prevention would require scanner-side filtering (checking recently installed update IDs against current scan results). Documented as DEV-031.
---
## PART 5: WINGET TEXT PARSER (F-C1-2) — PASS
- Uses header line keyword positions (Name, Id, Version, Available) to determine column starts
- Falls back to simple parser if header not found
- Lines shorter than expected: handled by bounds checking
- Package names with spaces: preserved by position-based extraction
---
## PART 6: LOGGING FORMAT — PASS
- `fmt.Printf`: zero results in winget.go
- Emojis: zero results in service/windows.go
- Banned words: zero results across all modified files
---
## PART 7: EDGE CASES
- **Winget not installed**: returns error → empty update list → no crash
- **Old winget (pre-1.6)**: JSON fails → text fallback → column parser handles output
- **Long-running install**: install is synchronous; agent blocks during install, resumes polling after
- **RebootRequired persistence**: in-memory only on InstallResult. On restart, flag is lost. Ghost may reappear until Windows commits. Known limitation (DEV-031).
---
## PART 8: ETHOS COMPLIANCE
- [x] Winget not found logged
- [x] Reboot required logged
- [x] Backoff in service logged with ETHOS format
- [x] No emojis in modified files
- [x] No fmt.Printf in scanner
- [x] Graceful degradation on all failure paths
- [x] No banned words
---
## PART 9: PRE-INTEGRATION CHECKLIST
- [x] Linux AMD64 build passes
- [x] Linux ARM64 build passes
- [x] Windows AMD64 cross-compile passes
- [x] All 98 tests pass, 1 skip (pre-existing)
- [x] All 8 C-1 FAIL-NOW tests now PASS
- [x] B-2 jitter and backoff in Windows service
- [x] Remaining gaps documented (key refresh, dedup cleanup)
- [x] Winget searches known system locations
- [x] Ghost update: RebootRequired set (detection, not prevention)
- [x] Ghost update partial fix documented as DEV-031
- [x] Text parser handles spaces
- [x] fmt.Printf removed
- [x] Emojis removed
- [x] All edge cases documented
- [x] Deviations documented
---
## ISSUES FOUND
| # | Severity | Finding | Action |
|---|----------|---------|--------|
| 1 | LOW | Ghost update fix is detection-only, not prevention | DEV-031 |
| 2 | LOW | Service missing ShouldRefreshKey/CleanupExecutedIDs | Future deduplication |
---
## FINAL STATUS: VERIFIED (with 2 documented follow-ups)
All C-1 fixes structurally correct. Linux builds clean. No regressions.
Ghost update fix is partial (detection, not prevention) — documented.