43 lines
1.3 KiB
Python
43 lines
1.3 KiB
Python
|
|
"""Shared front-matter reading for the register tools.
|
||
|
|
|
||
|
|
The finding files are the source of truth. Nothing here writes to them.
|
||
|
|
"""
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import pathlib
|
||
|
|
import yaml
|
||
|
|
|
||
|
|
REPO = pathlib.Path(__file__).resolve().parent.parent
|
||
|
|
FINDINGS = REPO / "findings"
|
||
|
|
NOTES = REPO / "notes"
|
||
|
|
|
||
|
|
SEVERITIES = ["critical", "high", "medium", "low"]
|
||
|
|
REVIEW_INTERVAL_DAYS = {"critical": 7, "high": 30, "medium": 90, "low": 180}
|
||
|
|
STALE_MULTIPLIER = 2
|
||
|
|
GRADED_FIELDS = ["severity", "disclosure", "escalation", "review_by", "last_reviewed"]
|
||
|
|
|
||
|
|
|
||
|
|
def load(path: pathlib.Path) -> dict:
|
||
|
|
text = path.read_text(encoding="utf-8")
|
||
|
|
if not text.startswith("---\n"):
|
||
|
|
raise ValueError(f"{path.name}: no front-matter")
|
||
|
|
_, fm, _body = text.split("---\n", 2)
|
||
|
|
data = yaml.safe_load(fm) or {}
|
||
|
|
data["_path"] = path
|
||
|
|
return data
|
||
|
|
|
||
|
|
|
||
|
|
def findings() -> list[dict]:
|
||
|
|
items = [load(p) for p in sorted(FINDINGS.glob("RISK-F-*.md"))]
|
||
|
|
return sorted(items, key=lambda f: f["id"], reverse=True)
|
||
|
|
|
||
|
|
|
||
|
|
def notes() -> list[dict]:
|
||
|
|
if not NOTES.exists():
|
||
|
|
return []
|
||
|
|
return sorted((load(p) for p in NOTES.glob("RISK-N-*.md")), key=lambda n: n["id"], reverse=True)
|
||
|
|
|
||
|
|
|
||
|
|
def sev_rank(sev: str) -> int:
|
||
|
|
return SEVERITIES.index(sev) if sev in SEVERITIES else len(SEVERITIES)
|