fix(sla-monitor): count only business hours in SLA elapsed-time calc

_business_minutes_elapsed clamped each weekday span to midnight instead
of BH_END, and never applied BH_START, so overnight hours (17:00-08:00)
were counted as business time. BH_START/BH_END were defined but unused
in the calculation. A ticket opened Fri 16:00 and evaluated Mon 10:00
scored 1080 min instead of the correct 180 min (6x overcount), flipping
a tier-1 breach into a false tier-2 page.

Clamp each weekday to the [BH_START, BH_END) window and only accrue the
overlap with [since, now); weekends remain excluded. Holidays are still
unhandled (pre-existing, separate gap).

Found by the daily scanner (agentic, CWE-440); proof-or-kill confirmed.
This commit is contained in:
Adam Moussa 2026-07-13 13:16:30 -04:00
parent 4506e3cbf7
commit d06f5bd2f2
No known key found for this signature in database

View file

@ -185,11 +185,17 @@ def _business_minutes_elapsed(since_utc, now_utc):
while current < now:
if current.weekday() < 5:
end_of_day = (current + timedelta(days=1)).replace(
hour=0, minute=0, second=0, microsecond=0
# Count only the business-hours window [BH_START, BH_END) on this
# weekday. Clamp the day's span to the portion that overlaps
# [current, now); overnight hours (BH_END..next BH_START) are excluded.
day_start = current.replace(
hour=BH_START, minute=0, second=0, microsecond=0
)
day_end = min(end_of_day, now)
total += (day_end - current).total_seconds() / 60
day_close = current.replace(hour=BH_END, minute=0, second=0, microsecond=0)
span_start = max(current, day_start)
span_end = min(day_close, now)
if span_end > span_start:
total += (span_end - span_start).total_seconds() / 60
current = (current + timedelta(days=1)).replace(
hour=0, minute=0, second=0, microsecond=0