v1.1.2 — Response-shape fuzz + property-testing hardening
[1.1.2] - 2026-07-03
Fixed — deep-audit round 3: response-shape fuzz + property-based testing
Round 2 fuzzed tool INPUTS; round 3 fuzzed what CallRail sends BACK
(2,891 calls with structurally-valid-but-garbage-typed responses) and
brought hypothesis property testing to invariants no prior round had
mechanically verified.
Response-shape hardening (182 fuzz failures, 8 roots)
paginate()now yields only dict items. A malformed collection
containing strings/ints/nulls crashed all six paginate-consuming
tools (call_summary,usage_summary,compare_periods,
spam_detector,search_calls_by_number,bulk_update_calls) with
raw AttributeError onitem.get(). Non-dict items are skipped with
a warning.call_eligibility_check— wrong-typedutm_source/source/
source_namecrashed.lower(); now safely coerced.search_calls_by_number— non-stringcustomer_phone_numberin
a call record crashed_digits_only; now skipped.
Hypothesis findings (property-based, permanent in
tests/test_properties.py)
_date_windowOverflowError — reachable in production. A
valid-format ancient end_date (e.g. "0001-01-01") minus a large
dayslookback lands before year 1, whichdatecannot represent —
list_calls(days=36500, end_date="0001-01-01")crashed with a raw
OverflowError despite the 36500-day cap. Now clamped to date.min.- Money invariant now machine-verified: per-company cost shares in
usage_summarysum toestimated_cycle_totalexactly (cent-level)
across 120 randomized fleets per run. - Also pinned:
_safe_pathcan never emit a dot-segment or unencoded
reserved char for ANY input;_parse_retry_afteralways lands in
[0, 60] and finite;_is_toll_freeand_date_windoware total
functions over garbage.
Added — tests
tests/test_properties.py— 6 hypothesis property suites.- 4 targeted regressions (ancient end_date, paginate non-dict skip,
wrong-typed eligibility fields, non-string phone field). - Tests 385 → 395.