feat: add forensic redaction controls
This commit is contained in:
@@ -15,6 +15,7 @@ from app.services.forensic_persistence import (
|
||||
forensic_report_to_dict,
|
||||
save_forensic_report,
|
||||
)
|
||||
from app.services.forensic_redaction import get_forensic_redaction_policy
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -88,7 +89,8 @@ async def upload_forensic_report(
|
||||
try:
|
||||
content = await file.read()
|
||||
_validate_upload(file, content)
|
||||
parsed = ForensicParser.parse_bytes(content)
|
||||
redaction_policy = get_forensic_redaction_policy(db)
|
||||
parsed = ForensicParser.parse_bytes(content, redaction_policy=redaction_policy)
|
||||
if forensic_report_exists(db, parsed["report_id"]):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_409_CONFLICT,
|
||||
@@ -148,12 +150,18 @@ async def list_forensic_reports(
|
||||
.all()
|
||||
)
|
||||
total_pages = (total + page_size - 1) // page_size if total else 0
|
||||
redaction_policy = get_forensic_redaction_policy(db)
|
||||
return ForensicListResponse(
|
||||
total=total,
|
||||
page=page,
|
||||
page_size=page_size,
|
||||
total_pages=total_pages,
|
||||
reports=[ForensicReportResponse(**forensic_report_to_dict(row)) for row in rows],
|
||||
reports=[
|
||||
ForensicReportResponse(
|
||||
**forensic_report_to_dict(row, redaction_policy=redaction_policy)
|
||||
)
|
||||
for row in rows
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -174,4 +182,5 @@ async def get_forensic_report(
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND, detail="Forensic report not found"
|
||||
)
|
||||
return ForensicReportResponse(**forensic_report_to_dict(row))
|
||||
redaction_policy = get_forensic_redaction_policy(db)
|
||||
return ForensicReportResponse(**forensic_report_to_dict(row, redaction_policy=redaction_policy))
|
||||
|
||||
@@ -8,6 +8,7 @@ in the ``settings`` database table. Settings are organised into categories:
|
||||
- ``dmarc`` – Default DMARC policy, percentage, etc.
|
||||
- ``dns`` – Default DNS resolver, Cloudflare DoH toggle.
|
||||
- ``cloudflare`` – Cloudflare API token and Zone ID.
|
||||
- ``forensics`` – Forensic report privacy and retention controls.
|
||||
- ``notifications`` – Future alerting/notification settings.
|
||||
"""
|
||||
|
||||
@@ -121,6 +122,21 @@ SETTING_DEFAULTS: List[Dict[str, Any]] = [
|
||||
"value_type": "string",
|
||||
"category": "cloudflare",
|
||||
},
|
||||
# ── Forensics ────────────────────────────────────────────────────────────
|
||||
{
|
||||
"key": "forensics.redaction_mode",
|
||||
"value": "balanced",
|
||||
"description": "Forensic report email-address redaction mode: balanced, domain_only, or strict",
|
||||
"value_type": "string",
|
||||
"category": "forensics",
|
||||
},
|
||||
{
|
||||
"key": "forensics.redact_long_tokens_enabled",
|
||||
"value": "true",
|
||||
"description": "Redact long opaque tokens in forensic report metadata",
|
||||
"value_type": "boolean",
|
||||
"category": "forensics",
|
||||
},
|
||||
# ── Notifications ─────────────────────────────────────────────────────────
|
||||
{
|
||||
"key": "notifications.apprise_enabled",
|
||||
@@ -312,7 +328,7 @@ def _audit_value_for_setting(key: str, value: Optional[str]) -> Optional[str]:
|
||||
|
||||
|
||||
def _should_audit_setting(key: str) -> bool:
|
||||
return key.startswith("notifications.")
|
||||
return key.startswith(("notifications.", "forensics."))
|
||||
|
||||
|
||||
def _audit_setting_change(
|
||||
|
||||
Reference in New Issue
Block a user