Skip to content

fix: scope posture endpoints to latest completed scan#145

Merged
Vishnu2707 merged 6 commits into
devfrom
feat/fix-clean-scan-posture
Jun 21, 2026
Merged

fix: scope posture endpoints to latest completed scan#145
Vishnu2707 merged 6 commits into
devfrom
feat/fix-clean-scan-posture

Conversation

@TFT444

@TFT444 TFT444 commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

What this fixes

Closes #139

Every dashboard endpoint was selecting the "latest scan" with this filter:

WHERE total_findings > 0 ORDER BY started_at DESC LIMIT 1

That silently skips any scan where zero findings were returned. So if your
team remediates everything and runs a clean scan the dashboard ignores it
and keeps showing the old dirty scan score stays low, compliance shows
Fails, resources and drift describe old posture. For a CSPM tool this is a
correctness bug, not a UI issue.

Root cause

Two separate problems:

  1. All five query locations used "total_findings > 0" to find the latest
    scan, excluding clean scans entirely.

  2. get_compliance_score() had no scan scope at all it ran
    "SELECT DISTINCT rule_id FROM finding" across the entire findings
    table. A rule that fired once months ago would permanently show as FAIL
    until that row was manually deleted from the database.

Fix

Replace "total_findings > 0" with "status = 'completed" at every
location. A completed scan is the correct selector for "latest real scan"
it includes clean scans (0 findings) and excludes pending, running, and
failed scans.

Scope "get_compliance_score()" to the latest completed scan so only
Current findings affect compliance status.

Files changed

File What changed
api/models/finding.py Fixed get_findings(), get_score(), get_cve_summary(), and get_compliance_score() — 4 SQL queries updated
api/routes/resources.py Latest scan filter fixed
api/routes/drift.py Latest scan filter fixed (compares two most recent completed scans)
api/routes/prioritization.py Latest scan filter fixed
docs/architecture.md Removed description of old total_findings > 0 behavior, corrected drift description
tests/test_clean_scan.py New test file — 8 tests covering the fix
.github/workflows/ci.yml Removed broken DATABASE_URL env block, added test_clean_scan.py to regression step

Behaviour after this fix

Scenario Before After
Latest scan is clean (0 findings) Dashboard shows old dirty scan Dashboard shows clean scan — score 100, findings empty
Rule remediated in latest scan Compliance still shows FAIL from old findings Compliance shows PASS
Score after clean scan Stays below 100 Returns 100
Drift after clean scan Compares stale scans Compares actual two most recent completed scans

Tests

New file tests/test_clean_scan.py — 8 tests, no real database or Azure
credentials required (pure mocks).

  • test_get_findings_uses_completed_status_not_total_findings — asserts the SQL no longer contains total_findings
  • test_get_findings_clean_scan_returns_empty_list — clean scan returns []
  • test_get_score_uses_completed_status — asserts corrected SQL
  • test_get_score_is_100_after_clean_scan — score = 100 with no findings
  • test_get_score_does_not_include_old_scan_findings — old HIGH findings do not deduct points
  • test_get_compliance_score_scopes_to_latest_scan — asserts compliance query is now scoped
  • test_get_compliance_score_all_pass_after_clean_scan — all controls PASS after clean scan
  • test_get_compliance_score_remediated_rule_shows_pass — remediated rule correctly shows PASS

All 8 pass locally.

Acceptance criteria checklist

  • GET /api/findings returns empty list when latest scan has zero findings
  • GET /api/score returns 100 for a latest clean scan
  • GET /api/compliance/<framework> marks controls PASS/FAIL using the latest scan only
  • Resources, prioritization, and drift do not show stale findings from older scans as current posture
  • Tests cover the sequence: failing scan followed by clean scan
  • Architecture docs updated to describe the corrected latest-scan behavior

Reviewers

API and Backend: Safid + Ritik (as listed in the issue)

TFT444 added 4 commits June 17, 2026 12:20
total_findings > 0 skips any scan where 0 issues were found. So after you fix all misconfigs and run a clean scan, the dashboard ignores it and keeps showing the old dirty scan. status = 'completed' picks the latest scan that finished successfully, whether it found 0 things or 100 things.
all confirmed passing locally. Zero real DB or Azure calls pure mock.
@TFT444 TFT444 self-assigned this Jun 17, 2026
Comment thread tests/test_clean_scan.py
"""Tests proving that a clean (zero-finding) completed scan is shown by posture
endpoints instead of falling back to stale data from an older scan."""

from unittest.mock import MagicMock, patch, call
Comment thread tests/test_clean_scan.py
endpoints instead of falling back to stale data from an older scan."""

from unittest.mock import MagicMock, patch, call
import pytest
Comment thread tests/test_clean_scan.py
from unittest.mock import MagicMock, patch, call
import pytest

from api.models.finding import DatabaseManager, FRAMEWORK_FILE_MAP

@ritiksah141 ritiksah141 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI is failing and beside that logic sounds good to me.

@TFT444

TFT444 commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator Author

@ritiksah141 already working on it .
Thanks for Review

@Vishnu2707 Vishnu2707 merged commit d37e8dc into dev Jun 21, 2026
3 checks passed
@Vishnu2707 Vishnu2707 deleted the feat/fix-clean-scan-posture branch June 21, 2026 23:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Latest clean scan is ignored by dashboard posture endpoints

3 participants