fix(backend): validate inputs and add boundary guards in database feedback
Closed
BR
8h ago+370+370+012345678901234567890123456789-16-16-01234567890123456789
Summary
Hardens backend/database/feedback.py and backend/routers/mobile_feedback.py with rigorous input validation, whitespace normalization, and boundary guards:
- Deterministic Coordinate Normalization:
- Strips
uidandtarget_idbefore database write operations. - Refuses empty, non-string, or blank whitespace inputs.
record_feedback_event: logs a warning and returnsNoneby default (best-effort, preserving caller flow), and raises descriptiveValueErrorwhenraise_on_error=True.
- Strips
- Hash Normalization Parity:
_idempotent_event_idandrecord_feedback_event_idempotentnormalize and stripuidandfeedback_idprior to computing the SHA-256 digest, ensuring identical idempotent keys regardless of client whitespace variance.
- Safe Fetch & Parsing Boundary Guards:
get_feedback_event: safely validatesevent_idstring and returnsNoneimmediately if blank/invalid without firing an invalid document path query.get_report: validatesdatestring and returnsNoneimmediately if blank/invalid.save_report: validates thatreportis a validFeedbackReportinstance with a non-empty date string.list_negative_events: rejects non-datetime arguments or inverted datetime ranges (start_at > end_at), and returns an empty list forlimit <= 0.list_report_dates: returns empty list forlimit <= 0and safely handles client transport exceptions.
- Router Error Mapping:
- In
backend/routers/mobile_feedback.py, catches database-levelValueErrorand converts toHTTPException(status_code=400, detail=str(exc)).
- In
Invariants & Failure-Class
- Product invariants affected: none
- Failure-Class: none
How it was verified
Hermetic unit tests executed via pytest:
$env:PYTHONPATH="backend"
python -m pytest tests/unit/test_database_feedback_resilience.py tests/unit/test_feedback_report.py
Results:
tests/unit/test_database_feedback_resilience.py: 40/40 passed (0.08s)tests/unit/test_feedback_report.py: 20/20 passed (0.16s)- Total: 60 passed in 2.29s (100% passing, hermetic mocks, 0 external network dependencies).