Phases

Phase 1 — Scanning and Scoring

Architecture decisions behind the scanning and scoring engine, with 86 tests.

Status: ✅ Complete
Delivered: March 2026
PyPI tag: Not yet published (git install only)


What Was Built

Phase 1 established the core framework — the scanner architecture, the 24 check implementations, and the scoring engine. Everything built in later phases sits on top of this foundation.

Core Architecture

The six-module pipeline was designed from the start:

Scanners → Checks → Scoring → Storage → Reporting → Remediation

The key architectural decision was to separate data collection (scanners) from security evaluation (checks). Every check is a pure Python function that accepts a scanner object and returns a CheckResult. This means:

  • Every check is independently unit-testable with a mock scanner
  • No network connections are made during testing
  • Adding a new check requires writing one function and one test — no framework changes

The 24 Checks

All 24 checks were implemented and mapped to OWASP Top 10:2025 categories using a four-criterion selection process:

  1. Externally detectable without agent access
  2. Targets configuration, not runtime vulnerabilities
  3. Maps to at least one OWASP Top 10:2025 category
  4. Has an automatable remediation pathway The checks were selected after reviewing OWASP guidance, NCSC education sector advisories, and CIS benchmarks for Docker and Linux hosts.

Scoring Engine

The priority formula was designed to rank fixes by effort versus impact rather than severity alone:

priority_score = (severity_score × impact_weight) ÷ effort_score

This produces the Day 1 / Day 7 / Day 30 remediation roadmap — the feature that most distinguishes StackSentry from tools that return unordered findings lists.

Grade Scale

GradeScoreRationale
A≥90%Even well-maintained systems have outstanding items
B80–89%Good posture with minor gaps
C70–79%Material risk — one in three checks failing
D60–69%Significant gaps requiring prompt action
F<60%Majority of checks failing

The scale is deliberately conservative — a 70% pass rate in security means real, unacceptable risk in a production context.

PDF Reporting

The ReportLab-based PDF generator produced a 14-section report including executive summary, OWASP heatmap, attack path detection, and the 30-day simulation roadmap.

The --profile flag introduced audience-adaptive narrative framing — the same OWASP finding described differently for a student, a DevOps engineer, a penetration tester, and a CTO.


Technical Decisions Made in Phase 1

Python 3.10+ only — match statements and dataclasses with __post_init__ were used throughout the scoring engine. The minimum version was chosen deliberately rather than supporting older Pythons.

requests for HTTP — considered httpx for async scanning but chose requests for simplicity. Multi-check scanning does not benefit significantly from async at 24 checks.

CheckResult as a frozen dataclass — making CheckResult immutable prevents accidental mutation of findings during report generation, which caused subtle bugs in early prototypes.

SQLite for history — no separate database server required. The single-user CLI model makes a file-based database the right choice.


Phase 1 Test Suite

tests/test_branch_logic.py   — 31 tests  (PASS/FAIL/WARN branching per check)
tests/test_scan_result.py    — 20 tests  (scoring, grades, OWASP aggregation)
tests/test_guards.py         — 35 tests  (guard clause behaviour)

Total at Phase 1 completion: 86 tests, all passing.