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>
139 lines
5.2 KiB
Markdown
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.
|