{"abstract":"A client retrying exactly when told the ban ends is still refused.","category":"Rate limiter algorithms","checks":7,"contract":"Input {threshold, window_s, ban_s, events [[t, ok]]} with nondecreasing t. While t < ban end every event is \"banned\" and ignored. Failures are kept for window_s seconds (f > t - window_s). When the kept failures reach threshold the key is banned until t + ban_s * 2^strikes, strikes increments and the failure log is cleared; the event reports \"ban-until-<end>\". Otherwise failures report \"fail\" and successes \"ok\". Return the per-event results.","evaluation_group":"w2-rate_limiter_algorithms-penalty-box","failed_approach":"Measuring the ban from its end time extends every ban by another base period.","family":"w2-rate_limiter_algorithms-penalty-box-ban-end","id":"FA-73601","implementations":{"attempt":{"sha256":"cbd0ec44c57cb1d2f612d743b941fdcf47757fab710254c9296add38150f7352","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(x):\n    th = x['threshold']\n    Wn = x['window_s']\n    base = x['ban_s']\n    fails = []\n    until = None\n    strikes = 0\n    out = []\n    for t, ok in x['events']:\n        if until is not None and t - until < base:\n            out.append('banned')\n            continue\n        if ok:\n            out.append('ok')\n            continue\n        fails = [f for f in fails if f > t - Wn] + [t]\n        if len(fails) >= th:\n            until = t + base * 2 ** strikes\n            strikes += 1\n            fails = []\n            out.append('ban-until-%d' % until)\n        else:\n            out.append('fail')\n    return out\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\ncases = [[['ban and escalate',\n   {'ban_s': 10,\n    'events': [[0, False],\n               [1, False],\n               [2, False],\n               [5, False],\n               [12, False],\n               [13, False],\n               [14, False],\n               [31, False],\n               [40, True]],\n    'threshold': 3,\n    'window_s': 60},\n   ['fail', 'fail', 'ban-until-12', 'banned', 'fail', 'fail', 'ban-until-34', 'banned', 'ok']],\n  ['third ban escalates',\n   {'ban_s': 10,\n    'events': [[0, False], [10, False], [30, False], [65, True], [71, True]],\n    'threshold': 1,\n    'window_s': 5},\n   ['ban-until-10', 'ban-until-30', 'ban-until-70', 'banned', 'ok']],\n  ['ban end instant',\n   {'ban_s': 20,\n    'events': [[0, False], [1, False], [20, True], [21, True], [23, False]],\n    'threshold': 2,\n    'window_s': 30},\n   ['fail', 'ban-until-21', 'banned', 'ok', 'fail']],\n  ['window prune boundary',\n   {'ban_s': 5,\n    'events': [[0, False], [10, False], [12, False], [30, False]],\n    'threshold': 2,\n    'window_s': 10},\n   ['fail', 'fail', 'ban-until-17', 'fail']],\n  ['failures cleared by ban',\n   {'ban_s': 5,\n    'events': [[0, False], [1, False], [2, False], [7, False], [9, False], [10, True]],\n    'threshold': 3,\n    'window_s': 100},\n   ['fail', 'fail', 'ban-until-7', 'fail', 'fail', 'ok']],\n  ['banned failures ignored',\n   {'ban_s': 10,\n    'events': [[0, False], [1, False], [5, False], [6, False], [11, False], [13, True]],\n    'threshold': 2,\n    'window_s': 100},\n   ['fail', 'ban-until-11', 'banned', 'banned', 'fail', 'ok']],\n  ['random attempts',\n   {'ban_s': 15,\n    'events': [[10, False],\n               [13, False],\n               [16, False],\n               [20, False],\n               [52, False],\n               [53, False],\n               [57, False],\n               [74, False],\n               [80, False],\n               [87, False],\n               [106, False],\n               [115, True],\n               [116, False],\n               [119, True]],\n    'threshold': 3,\n    'window_s': 20},\n   ['fail',\n    'fail',\n    'ban-until-31',\n    'banned',\n    'fail',\n    'fail',\n    'ban-until-87',\n    'banned',\n    'banned',\n    'fail',\n    'fail',\n    'ok',\n    'fail',\n    'ok']]],\n [['ban and escalate',\n   {'ban_s': 10,\n    'events': [[0, False],\n               [1, False],\n               [2, False],\n               [5, False],\n               [12, False],\n               [13, False],\n               [14, False],\n               [32, False],\n               [40, True]],\n    'threshold': 3,\n    'window_s': 60},\n   ['fail', 'fail', 'ban-until-12', 'banned', 'fail', 'fail', 'ban-until-34', 'banned', 'ok']],\n  ['third ban escalates',\n   {'ban_s': 10,\n    'events': [[0, False], [10, False], [30, False], [65, True], [72, True]],\n    'threshold': 1,\n    'window_s': 5},\n   ['ban-until-10', 'ban-until-30', 'ban-until-70', 'banned', 'ok']],\n  ['ban end instant',\n   {'ban_s': 20,\n    'events': [[0, False], [1, False], [20, True], [21, True], [24, False]],\n    'threshold': 2,\n    'window_s': 30},\n   ['fail', 'ban-until-21', 'banned', 'ok', 'fail']],\n  ['window prune boundary',\n   {'ban_s': 5,\n    'events': [[0, False], [10, False], [13, False], [30, False]],\n    'threshold': 2,\n    'window_s': 10},\n   ['fail', 'fail', 'ban-until-18', 'fail']],\n  ['failures cleared by ban',\n   {'ban_s': 5,\n    'events': [[0, False], [1, False], [2, False], [7, False], [10, False], [11, True]],\n    'threshold': 3,\n    'window_s': 100},\n   ['fail', 'fail', 'ban-until-7', 'fail', 'fail', 'ok']],\n  ['banned failures ignored',\n   {'ban_s': 10,\n    'events': [[0, False], [1, False], [5, False], [6, False], [11, False], [14, True]],\n    'threshold': 2,\n    'window_s': 100},\n   ['fail', 'ban-until-11', 'banned', 'banned', 'fail', 'ok']],\n  ['random attempts',\n   {'ban_s': 15,\n    'events': [[0, False],\n               [23, False],\n               [25, True],\n               [34, False],\n               [35, False],\n               [49, False],\n               [49, True],\n               [60, False],\n               [71, False],\n               [83, False],\n               [87, False],\n               [87, False],\n               [89, False],\n               [117, False]],\n    'threshold': 3,\n    'window_s': 20},\n   ['fail',\n    'fail',\n    'ok',\n    'fail',\n    'ban-until-50',\n    'banned',\n    'banned',\n    'fail',\n    'fail',\n    'fail',\n    'ban-until-117',\n    'banned',\n    'banned',\n    'fail']]],\n [['ban and escalate',\n   {'ban_s': 10,\n    'events': [[0, False],\n               [1, False],\n               [2, False],\n               [5, False],\n               [12, False],\n               [13, False],\n               [14, False],\n               [33, False],\n               [40, True]],\n    'threshold': 3,\n    'window_s': 60},\n   ['fail', 'fail', 'ban-until-12', 'banned', 'fail', 'fail', 'ban-until-34', 'banned', 'ok']],\n  ['third ban escalates',\n   {'ban_s': 10,\n    'events': [[0, False], [10, False], [30, False], [65, True], [73, True]],\n    'threshold': 1,\n    'window_s': 5},\n   ['ban-until-10', 'ban-until-30', 'ban-until-70', 'banned', 'ok']],\n  ['ban end instant',\n   {'ban_s': 20,\n    'events': [[0, False], [1, False], [20, True], [21, True], [25, False]],\n    'threshold': 2,\n    'window_s': 30},\n   ['fail', 'ban-until-21', 'banned', 'ok', 'fail']],\n  ['window prune boundary',\n   {'ban_s': 5,\n    'events': [[0, False], [10, False], [14, False], [30, False]],\n    'threshold': 2,\n    'window_s': 10},\n   ['fail', 'fail', 'ban-until-19', 'fail']],\n  ['failures cleared by ban',\n   {'ban_s': 5,\n    'events': [[0, False], [1, False], [2, False], [7, False], [11, False], [12, True]],\n    'threshold': 3,\n    'window_s': 100},\n   ['fail', 'fail', 'ban-until-7', 'fail', 'fail', 'ok']],\n  ['banned failures ignored',\n   {'ban_s': 10,\n    'events': [[0, False], [1, False], [5, False], [6, False], [11, False], [15, True]],\n    'threshold': 2,\n    'window_s': 100},\n   ['fail', 'ban-until-11', 'banned', 'banned', 'fail', 'ok']],\n  ['random attempts',\n   {'ban_s': 15,\n    'events': [[8, False],\n               [30, False],\n               [30, False],\n               [39, True],\n               [44, False],\n               [45, True],\n               [47, False],\n               [58, True],\n               [78, False],\n               [78, False],\n               [82, False],\n               [90, False],\n               [107, False],\n               [119, False]],\n    'threshold': 3,\n    'window_s': 20},\n   ['fail',\n    'fail',\n    'fail',\n    'ok',\n    'ban-until-59',\n    'banned',\n    'banned',\n    'banned',\n    'fail',\n    'fail',\n    'ban-until-112',\n    'banned',\n    'banned',\n    'fail']]],\n [['ban and escalate',\n   {'ban_s': 10,\n    'events': [[0, False],\n               [1, False],\n               [2, False],\n               [5, False],\n               [12, False],\n               [13, False],\n               [14, False],\n               [34, False],\n               [40, True]],\n    'threshold': 3,\n    'window_s': 60},\n   ['fail', 'fail', 'ban-until-12', 'banned', 'fail', 'fail', 'ban-until-34', 'fail', 'ok']],\n  ['third ban escalates',\n   {'ban_s': 10,\n    'events': [[0, False], [10, False], [30, False], [65, True], [74, True]],\n    'threshold': 1,\n    'window_s': 5},\n   ['ban-until-10', 'ban-until-30', 'ban-until-70', 'banned', 'ok']],\n  ['ban end instant',\n   {'ban_s': 20,\n    'events': [[0, False], [1, False], [20, True], [21, True], [26, False]],\n    'threshold': 2,\n    'window_s': 30},\n   ['fail', 'ban-until-21', 'banned', 'ok', 'fail']],\n  ['window prune boundary',\n   {'ban_s': 5,\n    'events': [[0, False], [10, False], [15, False], [30, False]],\n    'threshold': 2,\n    'window_s': 10},\n   ['fail', 'fail', 'ban-until-20', 'fail']],\n  ['failures cleared by ban',\n   {'ban_s': 5,\n    'events': [[0, False], [1, False], [2, False], [7, False], [12, False], [13, True]],\n    'threshold': 3,\n    'window_s': 100},\n   ['fail', 'fail', 'ban-until-7', 'fail', 'fail', 'ok']],\n  ['banned failures ignored',\n   {'ban_s': 10,\n    'events': [[0, False], [1, False], [5, False], [6, False], [11, False], [16, True]],\n    'threshold': 2,\n    'window_s': 100},\n   ['fail', 'ban-until-11', 'banned', 'banned', 'fail', 'ok']],\n  ['random attempts',\n   {'ban_s': 15,\n    'events': [[6, False],\n               [17, False],\n               [25, False],\n               [51, False],\n               [52, True],\n               [68, True],\n               [78, True],\n               [79, False],\n               [86, True],\n               [90, False],\n               [92, True],\n               [96, False],\n               [100, False],\n               [110, False]],\n    'threshold': 3,\n    'window_s': 20},\n   ['fail',\n    'fail',\n    'ban-until-40',\n    'fail',\n    'ok',\n    'ok',\n    'ok',\n    'fail',\n    'ok',\n    'fail',\n    'ok',\n    'ban-until-126',\n    'banned',\n    'banned']]],\n [['ban and escalate',\n   {'ban_s': 10,\n    'events': [[0, False],\n               [1, False],\n               [2, False],\n               [5, False],\n               [12, False],\n               [13, False],\n               [14, False],\n               [35, False],\n               [40, True]],\n    'threshold': 3,\n    'window_s': 60},\n   ['fail', 'fail', 'ban-until-12', 'banned', 'fail', 'fail', 'ban-until-34', 'fail', 'ok']],\n  ['third ban escalates',\n   {'ban_s': 10,\n    'events': [[0, False], [10, False], [30, False], [65, True], [75, True]],\n    'threshold': 1,\n    'window_s': 5},\n   ['ban-until-10', 'ban-until-30', 'ban-until-70', 'banned', 'ok']],\n  ['ban end instant',\n   {'ban_s': 20,\n    'events': [[0, False], [1, False], [20, True], [21, True], [27, False]],\n    'threshold': 2,\n    'window_s': 30},\n   ['fail', 'ban-until-21', 'banned', 'ok', 'fail']],\n  ['window prune boundary',\n   {'ban_s': 5,\n    'events': [[0, False], [10, False], [16, False], [30, False]],\n    'threshold': 2,\n    'window_s': 10},\n   ['fail', 'fail', 'ban-until-21', 'fail']],\n  ['failures cleared by ban',\n   {'ban_s': 5,\n    'events': [[0, False], [1, False], [2, False], [7, False], [13, False], [14, True]],\n    'threshold': 3,\n    'window_s': 100},\n   ['fail', 'fail', 'ban-until-7', 'fail', 'fail', 'ok']],\n  ['banned failures ignored',\n   {'ban_s': 10,\n    'events': [[0, False], [1, False], [5, False], [6, False], [11, False], [17, True]],\n    'threshold': 2,\n    'window_s': 100},\n   ['fail', 'ban-until-11', 'banned', 'banned', 'fail', 'ok']],\n  ['random attempts',\n   {'ban_s': 15,\n    'events': [[11, True],\n               [15, True],\n               [29, False],\n               [39, False],\n               [45, False],\n               [45, False],\n               [46, False],\n               [50, True],\n               [54, False],\n               [56, False],\n               [58, True],\n               [60, False],\n               [83, False],\n               [92, False]],\n    'threshold': 3,\n    'window_s': 20},\n   ['ok',\n    'ok',\n    'fail',\n    'fail',\n    'ban-until-60',\n    'banned',\n    'banned',\n    'banned',\n    'banned',\n    'banned',\n    'banned',\n    'fail',\n    'fail',\n    'fail']]]]\nfor label, args, expected in cases[N - 1]:\n    check(label, solve(args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"broken":{"sha256":"42fd5ccfefaf9692a865f2f6c855f4e014a09290057417afdb9daa09d3475eb2","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(x):\n    th = x['threshold']\n    Wn = x['window_s']\n    base = x['ban_s']\n    fails = []\n    until = None\n    strikes = 0\n    out = []\n    for t, ok in x['events']:\n        if until is not None and t <= until:\n            out.append('banned')\n            continue\n        if ok:\n            out.append('ok')\n            continue\n        fails = [f for f in fails if f > t - Wn] + [t]\n        if len(fails) >= th:\n            until = t + base * 2 ** strikes\n            strikes += 1\n            fails = []\n            out.append('ban-until-%d' % until)\n        else:\n            out.append('fail')\n    return out\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\ncases = [[['ban and escalate',\n   {'ban_s': 10,\n    'events': [[0, False],\n               [1, False],\n               [2, False],\n               [5, False],\n               [12, False],\n               [13, False],\n               [14, False],\n               [31, False],\n               [40, True]],\n    'threshold': 3,\n    'window_s': 60},\n   ['fail', 'fail', 'ban-until-12', 'banned', 'fail', 'fail', 'ban-until-34', 'banned', 'ok']],\n  ['third ban escalates',\n   {'ban_s': 10,\n    'events': [[0, False], [10, False], [30, False], [65, True], [71, True]],\n    'threshold': 1,\n    'window_s': 5},\n   ['ban-until-10', 'ban-until-30', 'ban-until-70', 'banned', 'ok']],\n  ['ban end instant',\n   {'ban_s': 20,\n    'events': [[0, False], [1, False], [20, True], [21, True], [23, False]],\n    'threshold': 2,\n    'window_s': 30},\n   ['fail', 'ban-until-21', 'banned', 'ok', 'fail']],\n  ['window prune boundary',\n   {'ban_s': 5,\n    'events': [[0, False], [10, False], [12, False], [30, False]],\n    'threshold': 2,\n    'window_s': 10},\n   ['fail', 'fail', 'ban-until-17', 'fail']],\n  ['failures cleared by ban',\n   {'ban_s': 5,\n    'events': [[0, False], [1, False], [2, False], [7, False], [9, False], [10, True]],\n    'threshold': 3,\n    'window_s': 100},\n   ['fail', 'fail', 'ban-until-7', 'fail', 'fail', 'ok']],\n  ['banned failures ignored',\n   {'ban_s': 10,\n    'events': [[0, False], [1, False], [5, False], [6, False], [11, False], [13, True]],\n    'threshold': 2,\n    'window_s': 100},\n   ['fail', 'ban-until-11', 'banned', 'banned', 'fail', 'ok']],\n  ['random attempts',\n   {'ban_s': 15,\n    'events': [[10, False],\n               [13, False],\n               [16, False],\n               [20, False],\n               [52, False],\n               [53, False],\n               [57, False],\n               [74, False],\n               [80, False],\n               [87, False],\n               [106, False],\n               [115, True],\n               [116, False],\n               [119, True]],\n    'threshold': 3,\n    'window_s': 20},\n   ['fail',\n    'fail',\n    'ban-until-31',\n    'banned',\n    'fail',\n    'fail',\n    'ban-until-87',\n    'banned',\n    'banned',\n    'fail',\n    'fail',\n    'ok',\n    'fail',\n    'ok']]],\n [['ban and escalate',\n   {'ban_s': 10,\n    'events': [[0, False],\n               [1, False],\n               [2, False],\n               [5, False],\n               [12, False],\n               [13, False],\n               [14, False],\n               [32, False],\n               [40, True]],\n    'threshold': 3,\n    'window_s': 60},\n   ['fail', 'fail', 'ban-until-12', 'banned', 'fail', 'fail', 'ban-until-34', 'banned', 'ok']],\n  ['third ban escalates',\n   {'ban_s': 10,\n    'events': [[0, False], [10, False], [30, False], [65, True], [72, True]],\n    'threshold': 1,\n    'window_s': 5},\n   ['ban-until-10', 'ban-until-30', 'ban-until-70', 'banned', 'ok']],\n  ['ban end instant',\n   {'ban_s': 20,\n    'events': [[0, False], [1, False], [20, True], [21, True], [24, False]],\n    'threshold': 2,\n    'window_s': 30},\n   ['fail', 'ban-until-21', 'banned', 'ok', 'fail']],\n  ['window prune boundary',\n   {'ban_s': 5,\n    'events': [[0, False], [10, False], [13, False], [30, False]],\n    'threshold': 2,\n    'window_s': 10},\n   ['fail', 'fail', 'ban-until-18', 'fail']],\n  ['failures cleared by ban',\n   {'ban_s': 5,\n    'events': [[0, False], [1, False], [2, False], [7, False], [10, False], [11, True]],\n    'threshold': 3,\n    'window_s': 100},\n   ['fail', 'fail', 'ban-until-7', 'fail', 'fail', 'ok']],\n  ['banned failures ignored',\n   {'ban_s': 10,\n    'events': [[0, False], [1, False], [5, False], [6, False], [11, False], [14, True]],\n    'threshold': 2,\n    'window_s': 100},\n   ['fail', 'ban-until-11', 'banned', 'banned', 'fail', 'ok']],\n  ['random attempts',\n   {'ban_s': 15,\n    'events': [[0, False],\n               [23, False],\n               [25, True],\n               [34, False],\n               [35, False],\n               [49, False],\n               [49, True],\n               [60, False],\n               [71, False],\n               [83, False],\n               [87, False],\n               [87, False],\n               [89, False],\n               [117, False]],\n    'threshold': 3,\n    'window_s': 20},\n   ['fail',\n    'fail',\n    'ok',\n    'fail',\n    'ban-until-50',\n    'banned',\n    'banned',\n    'fail',\n    'fail',\n    'fail',\n    'ban-until-117',\n    'banned',\n    'banned',\n    'fail']]],\n [['ban and escalate',\n   {'ban_s': 10,\n    'events': [[0, False],\n               [1, False],\n               [2, False],\n               [5, False],\n               [12, False],\n               [13, False],\n               [14, False],\n               [33, False],\n               [40, True]],\n    'threshold': 3,\n    'window_s': 60},\n   ['fail', 'fail', 'ban-until-12', 'banned', 'fail', 'fail', 'ban-until-34', 'banned', 'ok']],\n  ['third ban escalates',\n   {'ban_s': 10,\n    'events': [[0, False], [10, False], [30, False], [65, True], [73, True]],\n    'threshold': 1,\n    'window_s': 5},\n   ['ban-until-10', 'ban-until-30', 'ban-until-70', 'banned', 'ok']],\n  ['ban end instant',\n   {'ban_s': 20,\n    'events': [[0, False], [1, False], [20, True], [21, True], [25, False]],\n    'threshold': 2,\n    'window_s': 30},\n   ['fail', 'ban-until-21', 'banned', 'ok', 'fail']],\n  ['window prune boundary',\n   {'ban_s': 5,\n    'events': [[0, False], [10, False], [14, False], [30, False]],\n    'threshold': 2,\n    'window_s': 10},\n   ['fail', 'fail', 'ban-until-19', 'fail']],\n  ['failures cleared by ban',\n   {'ban_s': 5,\n    'events': [[0, False], [1, False], [2, False], [7, False], [11, False], [12, True]],\n    'threshold': 3,\n    'window_s': 100},\n   ['fail', 'fail', 'ban-until-7', 'fail', 'fail', 'ok']],\n  ['banned failures ignored',\n   {'ban_s': 10,\n    'events': [[0, False], [1, False], [5, False], [6, False], [11, False], [15, True]],\n    'threshold': 2,\n    'window_s': 100},\n   ['fail', 'ban-until-11', 'banned', 'banned', 'fail', 'ok']],\n  ['random attempts',\n   {'ban_s': 15,\n    'events': [[8, False],\n               [30, False],\n               [30, False],\n               [39, True],\n               [44, False],\n               [45, True],\n               [47, False],\n               [58, True],\n               [78, False],\n               [78, False],\n               [82, False],\n               [90, False],\n               [107, False],\n               [119, False]],\n    'threshold': 3,\n    'window_s': 20},\n   ['fail',\n    'fail',\n    'fail',\n    'ok',\n    'ban-until-59',\n    'banned',\n    'banned',\n    'banned',\n    'fail',\n    'fail',\n    'ban-until-112',\n    'banned',\n    'banned',\n    'fail']]],\n [['ban and escalate',\n   {'ban_s': 10,\n    'events': [[0, False],\n               [1, False],\n               [2, False],\n               [5, False],\n               [12, False],\n               [13, False],\n               [14, False],\n               [34, False],\n               [40, True]],\n    'threshold': 3,\n    'window_s': 60},\n   ['fail', 'fail', 'ban-until-12', 'banned', 'fail', 'fail', 'ban-until-34', 'fail', 'ok']],\n  ['third ban escalates',\n   {'ban_s': 10,\n    'events': [[0, False], [10, False], [30, False], [65, True], [74, True]],\n    'threshold': 1,\n    'window_s': 5},\n   ['ban-until-10', 'ban-until-30', 'ban-until-70', 'banned', 'ok']],\n  ['ban end instant',\n   {'ban_s': 20,\n    'events': [[0, False], [1, False], [20, True], [21, True], [26, False]],\n    'threshold': 2,\n    'window_s': 30},\n   ['fail', 'ban-until-21', 'banned', 'ok', 'fail']],\n  ['window prune boundary',\n   {'ban_s': 5,\n    'events': [[0, False], [10, False], [15, False], [30, False]],\n    'threshold': 2,\n    'window_s': 10},\n   ['fail', 'fail', 'ban-until-20', 'fail']],\n  ['failures cleared by ban',\n   {'ban_s': 5,\n    'events': [[0, False], [1, False], [2, False], [7, False], [12, False], [13, True]],\n    'threshold': 3,\n    'window_s': 100},\n   ['fail', 'fail', 'ban-until-7', 'fail', 'fail', 'ok']],\n  ['banned failures ignored',\n   {'ban_s': 10,\n    'events': [[0, False], [1, False], [5, False], [6, False], [11, False], [16, True]],\n    'threshold': 2,\n    'window_s': 100},\n   ['fail', 'ban-until-11', 'banned', 'banned', 'fail', 'ok']],\n  ['random attempts',\n   {'ban_s': 15,\n    'events': [[6, False],\n               [17, False],\n               [25, False],\n               [51, False],\n               [52, True],\n               [68, True],\n               [78, True],\n               [79, False],\n               [86, True],\n               [90, False],\n               [92, True],\n               [96, False],\n               [100, False],\n               [110, False]],\n    'threshold': 3,\n    'window_s': 20},\n   ['fail',\n    'fail',\n    'ban-until-40',\n    'fail',\n    'ok',\n    'ok',\n    'ok',\n    'fail',\n    'ok',\n    'fail',\n    'ok',\n    'ban-until-126',\n    'banned',\n    'banned']]],\n [['ban and escalate',\n   {'ban_s': 10,\n    'events': [[0, False],\n               [1, False],\n               [2, False],\n               [5, False],\n               [12, False],\n               [13, False],\n               [14, False],\n               [35, False],\n               [40, True]],\n    'threshold': 3,\n    'window_s': 60},\n   ['fail', 'fail', 'ban-until-12', 'banned', 'fail', 'fail', 'ban-until-34', 'fail', 'ok']],\n  ['third ban escalates',\n   {'ban_s': 10,\n    'events': [[0, False], [10, False], [30, False], [65, True], [75, True]],\n    'threshold': 1,\n    'window_s': 5},\n   ['ban-until-10', 'ban-until-30', 'ban-until-70', 'banned', 'ok']],\n  ['ban end instant',\n   {'ban_s': 20,\n    'events': [[0, False], [1, False], [20, True], [21, True], [27, False]],\n    'threshold': 2,\n    'window_s': 30},\n   ['fail', 'ban-until-21', 'banned', 'ok', 'fail']],\n  ['window prune boundary',\n   {'ban_s': 5,\n    'events': [[0, False], [10, False], [16, False], [30, False]],\n    'threshold': 2,\n    'window_s': 10},\n   ['fail', 'fail', 'ban-until-21', 'fail']],\n  ['failures cleared by ban',\n   {'ban_s': 5,\n    'events': [[0, False], [1, False], [2, False], [7, False], [13, False], [14, True]],\n    'threshold': 3,\n    'window_s': 100},\n   ['fail', 'fail', 'ban-until-7', 'fail', 'fail', 'ok']],\n  ['banned failures ignored',\n   {'ban_s': 10,\n    'events': [[0, False], [1, False], [5, False], [6, False], [11, False], [17, True]],\n    'threshold': 2,\n    'window_s': 100},\n   ['fail', 'ban-until-11', 'banned', 'banned', 'fail', 'ok']],\n  ['random attempts',\n   {'ban_s': 15,\n    'events': [[11, True],\n               [15, True],\n               [29, False],\n               [39, False],\n               [45, False],\n               [45, False],\n               [46, False],\n               [50, True],\n               [54, False],\n               [56, False],\n               [58, True],\n               [60, False],\n               [83, False],\n               [92, False]],\n    'threshold': 3,\n    'window_s': 20},\n   ['ok',\n    'ok',\n    'fail',\n    'fail',\n    'ban-until-60',\n    'banned',\n    'banned',\n    'banned',\n    'banned',\n    'banned',\n    'banned',\n    'fail',\n    'fail',\n    'fail']]]]\nfor label, args, expected in cases[N - 1]:\n    check(label, solve(args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"fixed":{"sha256":"a85b760b01d176918edfe5266592a16ed76089f21492a4e80dce604d33d858da","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(x):\n    th = x['threshold']\n    Wn = x['window_s']\n    base = x['ban_s']\n    fails = []\n    until = None\n    strikes = 0\n    out = []\n    for t, ok in x['events']:\n        if until is not None and t < until:\n            out.append('banned')\n            continue\n        if ok:\n            out.append('ok')\n            continue\n        fails = [f for f in fails if f > t - Wn] + [t]\n        if len(fails) >= th:\n            until = t + base * 2 ** strikes\n            strikes += 1\n            fails = []\n            out.append('ban-until-%d' % until)\n        else:\n            out.append('fail')\n    return out\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\ncases = [[['ban and escalate',\n   {'ban_s': 10,\n    'events': [[0, False],\n               [1, False],\n               [2, False],\n               [5, False],\n               [12, False],\n               [13, False],\n               [14, False],\n               [31, False],\n               [40, True]],\n    'threshold': 3,\n    'window_s': 60},\n   ['fail', 'fail', 'ban-until-12', 'banned', 'fail', 'fail', 'ban-until-34', 'banned', 'ok']],\n  ['third ban escalates',\n   {'ban_s': 10,\n    'events': [[0, False], [10, False], [30, False], [65, True], [71, True]],\n    'threshold': 1,\n    'window_s': 5},\n   ['ban-until-10', 'ban-until-30', 'ban-until-70', 'banned', 'ok']],\n  ['ban end instant',\n   {'ban_s': 20,\n    'events': [[0, False], [1, False], [20, True], [21, True], [23, False]],\n    'threshold': 2,\n    'window_s': 30},\n   ['fail', 'ban-until-21', 'banned', 'ok', 'fail']],\n  ['window prune boundary',\n   {'ban_s': 5,\n    'events': [[0, False], [10, False], [12, False], [30, False]],\n    'threshold': 2,\n    'window_s': 10},\n   ['fail', 'fail', 'ban-until-17', 'fail']],\n  ['failures cleared by ban',\n   {'ban_s': 5,\n    'events': [[0, False], [1, False], [2, False], [7, False], [9, False], [10, True]],\n    'threshold': 3,\n    'window_s': 100},\n   ['fail', 'fail', 'ban-until-7', 'fail', 'fail', 'ok']],\n  ['banned failures ignored',\n   {'ban_s': 10,\n    'events': [[0, False], [1, False], [5, False], [6, False], [11, False], [13, True]],\n    'threshold': 2,\n    'window_s': 100},\n   ['fail', 'ban-until-11', 'banned', 'banned', 'fail', 'ok']],\n  ['random attempts',\n   {'ban_s': 15,\n    'events': [[10, False],\n               [13, False],\n               [16, False],\n               [20, False],\n               [52, False],\n               [53, False],\n               [57, False],\n               [74, False],\n               [80, False],\n               [87, False],\n               [106, False],\n               [115, True],\n               [116, False],\n               [119, True]],\n    'threshold': 3,\n    'window_s': 20},\n   ['fail',\n    'fail',\n    'ban-until-31',\n    'banned',\n    'fail',\n    'fail',\n    'ban-until-87',\n    'banned',\n    'banned',\n    'fail',\n    'fail',\n    'ok',\n    'fail',\n    'ok']]],\n [['ban and escalate',\n   {'ban_s': 10,\n    'events': [[0, False],\n               [1, False],\n               [2, False],\n               [5, False],\n               [12, False],\n               [13, False],\n               [14, False],\n               [32, False],\n               [40, True]],\n    'threshold': 3,\n    'window_s': 60},\n   ['fail', 'fail', 'ban-until-12', 'banned', 'fail', 'fail', 'ban-until-34', 'banned', 'ok']],\n  ['third ban escalates',\n   {'ban_s': 10,\n    'events': [[0, False], [10, False], [30, False], [65, True], [72, True]],\n    'threshold': 1,\n    'window_s': 5},\n   ['ban-until-10', 'ban-until-30', 'ban-until-70', 'banned', 'ok']],\n  ['ban end instant',\n   {'ban_s': 20,\n    'events': [[0, False], [1, False], [20, True], [21, True], [24, False]],\n    'threshold': 2,\n    'window_s': 30},\n   ['fail', 'ban-until-21', 'banned', 'ok', 'fail']],\n  ['window prune boundary',\n   {'ban_s': 5,\n    'events': [[0, False], [10, False], [13, False], [30, False]],\n    'threshold': 2,\n    'window_s': 10},\n   ['fail', 'fail', 'ban-until-18', 'fail']],\n  ['failures cleared by ban',\n   {'ban_s': 5,\n    'events': [[0, False], [1, False], [2, False], [7, False], [10, False], [11, True]],\n    'threshold': 3,\n    'window_s': 100},\n   ['fail', 'fail', 'ban-until-7', 'fail', 'fail', 'ok']],\n  ['banned failures ignored',\n   {'ban_s': 10,\n    'events': [[0, False], [1, False], [5, False], [6, False], [11, False], [14, True]],\n    'threshold': 2,\n    'window_s': 100},\n   ['fail', 'ban-until-11', 'banned', 'banned', 'fail', 'ok']],\n  ['random attempts',\n   {'ban_s': 15,\n    'events': [[0, False],\n               [23, False],\n               [25, True],\n               [34, False],\n               [35, False],\n               [49, False],\n               [49, True],\n               [60, False],\n               [71, False],\n               [83, False],\n               [87, False],\n               [87, False],\n               [89, False],\n               [117, False]],\n    'threshold': 3,\n    'window_s': 20},\n   ['fail',\n    'fail',\n    'ok',\n    'fail',\n    'ban-until-50',\n    'banned',\n    'banned',\n    'fail',\n    'fail',\n    'fail',\n    'ban-until-117',\n    'banned',\n    'banned',\n    'fail']]],\n [['ban and escalate',\n   {'ban_s': 10,\n    'events': [[0, False],\n               [1, False],\n               [2, False],\n               [5, False],\n               [12, False],\n               [13, False],\n               [14, False],\n               [33, False],\n               [40, True]],\n    'threshold': 3,\n    'window_s': 60},\n   ['fail', 'fail', 'ban-until-12', 'banned', 'fail', 'fail', 'ban-until-34', 'banned', 'ok']],\n  ['third ban escalates',\n   {'ban_s': 10,\n    'events': [[0, False], [10, False], [30, False], [65, True], [73, True]],\n    'threshold': 1,\n    'window_s': 5},\n   ['ban-until-10', 'ban-until-30', 'ban-until-70', 'banned', 'ok']],\n  ['ban end instant',\n   {'ban_s': 20,\n    'events': [[0, False], [1, False], [20, True], [21, True], [25, False]],\n    'threshold': 2,\n    'window_s': 30},\n   ['fail', 'ban-until-21', 'banned', 'ok', 'fail']],\n  ['window prune boundary',\n   {'ban_s': 5,\n    'events': [[0, False], [10, False], [14, False], [30, False]],\n    'threshold': 2,\n    'window_s': 10},\n   ['fail', 'fail', 'ban-until-19', 'fail']],\n  ['failures cleared by ban',\n   {'ban_s': 5,\n    'events': [[0, False], [1, False], [2, False], [7, False], [11, False], [12, True]],\n    'threshold': 3,\n    'window_s': 100},\n   ['fail', 'fail', 'ban-until-7', 'fail', 'fail', 'ok']],\n  ['banned failures ignored',\n   {'ban_s': 10,\n    'events': [[0, False], [1, False], [5, False], [6, False], [11, False], [15, True]],\n    'threshold': 2,\n    'window_s': 100},\n   ['fail', 'ban-until-11', 'banned', 'banned', 'fail', 'ok']],\n  ['random attempts',\n   {'ban_s': 15,\n    'events': [[8, False],\n               [30, False],\n               [30, False],\n               [39, True],\n               [44, False],\n               [45, True],\n               [47, False],\n               [58, True],\n               [78, False],\n               [78, False],\n               [82, False],\n               [90, False],\n               [107, False],\n               [119, False]],\n    'threshold': 3,\n    'window_s': 20},\n   ['fail',\n    'fail',\n    'fail',\n    'ok',\n    'ban-until-59',\n    'banned',\n    'banned',\n    'banned',\n    'fail',\n    'fail',\n    'ban-until-112',\n    'banned',\n    'banned',\n    'fail']]],\n [['ban and escalate',\n   {'ban_s': 10,\n    'events': [[0, False],\n               [1, False],\n               [2, False],\n               [5, False],\n               [12, False],\n               [13, False],\n               [14, False],\n               [34, False],\n               [40, True]],\n    'threshold': 3,\n    'window_s': 60},\n   ['fail', 'fail', 'ban-until-12', 'banned', 'fail', 'fail', 'ban-until-34', 'fail', 'ok']],\n  ['third ban escalates',\n   {'ban_s': 10,\n    'events': [[0, False], [10, False], [30, False], [65, True], [74, True]],\n    'threshold': 1,\n    'window_s': 5},\n   ['ban-until-10', 'ban-until-30', 'ban-until-70', 'banned', 'ok']],\n  ['ban end instant',\n   {'ban_s': 20,\n    'events': [[0, False], [1, False], [20, True], [21, True], [26, False]],\n    'threshold': 2,\n    'window_s': 30},\n   ['fail', 'ban-until-21', 'banned', 'ok', 'fail']],\n  ['window prune boundary',\n   {'ban_s': 5,\n    'events': [[0, False], [10, False], [15, False], [30, False]],\n    'threshold': 2,\n    'window_s': 10},\n   ['fail', 'fail', 'ban-until-20', 'fail']],\n  ['failures cleared by ban',\n   {'ban_s': 5,\n    'events': [[0, False], [1, False], [2, False], [7, False], [12, False], [13, True]],\n    'threshold': 3,\n    'window_s': 100},\n   ['fail', 'fail', 'ban-until-7', 'fail', 'fail', 'ok']],\n  ['banned failures ignored',\n   {'ban_s': 10,\n    'events': [[0, False], [1, False], [5, False], [6, False], [11, False], [16, True]],\n    'threshold': 2,\n    'window_s': 100},\n   ['fail', 'ban-until-11', 'banned', 'banned', 'fail', 'ok']],\n  ['random attempts',\n   {'ban_s': 15,\n    'events': [[6, False],\n               [17, False],\n               [25, False],\n               [51, False],\n               [52, True],\n               [68, True],\n               [78, True],\n               [79, False],\n               [86, True],\n               [90, False],\n               [92, True],\n               [96, False],\n               [100, False],\n               [110, False]],\n    'threshold': 3,\n    'window_s': 20},\n   ['fail',\n    'fail',\n    'ban-until-40',\n    'fail',\n    'ok',\n    'ok',\n    'ok',\n    'fail',\n    'ok',\n    'fail',\n    'ok',\n    'ban-until-126',\n    'banned',\n    'banned']]],\n [['ban and escalate',\n   {'ban_s': 10,\n    'events': [[0, False],\n               [1, False],\n               [2, False],\n               [5, False],\n               [12, False],\n               [13, False],\n               [14, False],\n               [35, False],\n               [40, True]],\n    'threshold': 3,\n    'window_s': 60},\n   ['fail', 'fail', 'ban-until-12', 'banned', 'fail', 'fail', 'ban-until-34', 'fail', 'ok']],\n  ['third ban escalates',\n   {'ban_s': 10,\n    'events': [[0, False], [10, False], [30, False], [65, True], [75, True]],\n    'threshold': 1,\n    'window_s': 5},\n   ['ban-until-10', 'ban-until-30', 'ban-until-70', 'banned', 'ok']],\n  ['ban end instant',\n   {'ban_s': 20,\n    'events': [[0, False], [1, False], [20, True], [21, True], [27, False]],\n    'threshold': 2,\n    'window_s': 30},\n   ['fail', 'ban-until-21', 'banned', 'ok', 'fail']],\n  ['window prune boundary',\n   {'ban_s': 5,\n    'events': [[0, False], [10, False], [16, False], [30, False]],\n    'threshold': 2,\n    'window_s': 10},\n   ['fail', 'fail', 'ban-until-21', 'fail']],\n  ['failures cleared by ban',\n   {'ban_s': 5,\n    'events': [[0, False], [1, False], [2, False], [7, False], [13, False], [14, True]],\n    'threshold': 3,\n    'window_s': 100},\n   ['fail', 'fail', 'ban-until-7', 'fail', 'fail', 'ok']],\n  ['banned failures ignored',\n   {'ban_s': 10,\n    'events': [[0, False], [1, False], [5, False], [6, False], [11, False], [17, True]],\n    'threshold': 2,\n    'window_s': 100},\n   ['fail', 'ban-until-11', 'banned', 'banned', 'fail', 'ok']],\n  ['random attempts',\n   {'ban_s': 15,\n    'events': [[11, True],\n               [15, True],\n               [29, False],\n               [39, False],\n               [45, False],\n               [45, False],\n               [46, False],\n               [50, True],\n               [54, False],\n               [56, False],\n               [58, True],\n               [60, False],\n               [83, False],\n               [92, False]],\n    'threshold': 3,\n    'window_s': 20},\n   ['ok',\n    'ok',\n    'fail',\n    'fail',\n    'ban-until-60',\n    'banned',\n    'banned',\n    'banned',\n    'banned',\n    'banned',\n    'banned',\n    'fail',\n    'fail',\n    'fail']]]]\nfor label, args, expected in cases[N - 1]:\n    check(label, solve(args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"}},"limitations":"A deterministic, bounded teaching model with stipulated constants and pre-hashed or explicitly hashed inputs; it is not a production implementation and makes no claim of conformance to any library or paper beyond the stated contract. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.","method":"Deterministic executable model with adversarial boundary fixtures.","provenance":{"created_by":"Failure Map","dependencies":"Python standard library","family":"w2-rate_limiter_algorithms-penalty-box-ban-end","generated_at":"2026-09-29T14:48:49.095248+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"Login and abuse throttles escalate bans after repeated failures; window, escalation and log-reset rules decide whether attackers are slowed and legitimate users recover.","repair":"Lift the ban at t == end.","root_cause":"The ban check uses t <= end.","sha256":"58ab7d23a8f2dd3d3cc94fb7e0ea1c65eb31cf3ecde62ea436bb75bf950b2699","title":"Escalating failure penalty box: ban still active at its end instant · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":39.558,"exit_code":1,"observations":[{"actual":["fail","fail","ban-until-12","banned","banned","banned","banned","fail","ok"],"check":"ban and escalate","expected":["fail","fail","ban-until-12","banned","fail","fail","ban-until-34","banned","ok"],"passed":false},{"actual":["ban-until-10","banned","ban-until-50","ok","ok"],"check":"third ban escalates","expected":["ban-until-10","ban-until-30","ban-until-70","banned","ok"],"passed":false},{"actual":["fail","ban-until-21","banned","banned","banned"],"check":"ban end instant","expected":["fail","ban-until-21","banned","ok","fail"],"passed":false},{"actual":["fail","fail","ban-until-17","fail"],"check":"window prune boundary","expected":["fail","fail","ban-until-17","fail"],"passed":true},{"actual":["fail","fail","ban-until-7","banned","banned","banned"],"check":"failures cleared by ban","expected":["fail","fail","ban-until-7","fail","fail","ok"],"passed":false},{"actual":["fail","ban-until-11","banned","banned","banned","banned"],"check":"banned failures ignored","expected":["fail","ban-until-11","banned","banned","fail","ok"],"passed":false},{"actual":["fail","fail","ban-until-31","banned","fail","fail","ban-until-87","banned","banned","banned","fail","ok","fail","ok"],"check":"random attempts","expected":["fail","fail","ban-until-31","banned","fail","fail","ban-until-87","banned","banned","fail","fail","ok","fail","ok"],"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"ban and escalate\", \"actual\": [\"fail\", \"fail\", \"ban-until-12\", \"banned\", \"banned\", \"banned\", \"banned\", \"fail\", \"ok\"], \"expected\": [\"fail\", \"fail\", \"ban-until-12\", \"banned\", \"fail\", \"fail\", \"ban-until-34\", \"banned\", \"ok\"], \"passed\": false}, {\"check\": \"third ban escalates\", \"actual\": [\"ban-until-10\", \"banned\", \"ban-until-50\", \"ok\", \"ok\"], \"expected\": [\"ban-until-10\", \"ban-until-30\", \"ban-until-70\", \"banned\", \"ok\"], \"passed\": false}, {\"check\": \"ban end instant\", \"actual\": [\"fail\", \"ban-until-21\", \"banned\", \"banned\", \"banned\"], \"expected\": [\"fail\", \"ban-until-21\", \"banned\", \"ok\", \"fail\"], \"passed\": false}, {\"check\": \"window prune boundary\", \"actual\": [\"fail\", \"fail\", \"ban-until-17\", \"fail\"], \"expected\": [\"fail\", \"fail\", \"ban-until-17\", \"fail\"], \"passed\": true}, {\"check\": \"failures cleared by ban\", \"actual\": [\"fail\", \"fail\", \"ban-until-7\", \"banned\", \"banned\", \"banned\"], \"expected\": [\"fail\", \"fail\", \"ban-until-7\", \"fail\", \"fail\", \"ok\"], \"passed\": false}, {\"check\": \"banned failures ignored\", \"actual\": [\"fail\", \"ban-until-11\", \"banned\", \"banned\", \"banned\", \"banned\"], \"expected\": [\"fail\", \"ban-until-11\", \"banned\", \"banned\", \"fail\", \"ok\"], \"passed\": false}, {\"check\": \"random attempts\", \"actual\": [\"fail\", \"fail\", \"ban-until-31\", \"banned\", \"fail\", \"fail\", \"ban-until-87\", \"banned\", \"banned\", \"banned\", \"fail\", \"ok\", \"fail\", \"ok\"], \"expected\": [\"fail\", \"fail\", \"ban-until-31\", \"banned\", \"fail\", \"fail\", \"ban-until-87\", \"banned\", \"banned\", \"fail\", \"fail\", \"ok\", \"fail\", \"ok\"], \"passed\": false}], \"passed\": false}\n"},"broken":{"elapsed_ms":40.696,"exit_code":1,"observations":[{"actual":["fail","fail","ban-until-12","banned","banned","fail","fail","ban-until-51","banned"],"check":"ban and escalate","expected":["fail","fail","ban-until-12","banned","fail","fail","ban-until-34","banned","ok"],"passed":false},{"actual":["ban-until-10","banned","ban-until-50","ok","ok"],"check":"third ban escalates","expected":["ban-until-10","ban-until-30","ban-until-70","banned","ok"],"passed":false},{"actual":["fail","ban-until-21","banned","banned","fail"],"check":"ban end instant","expected":["fail","ban-until-21","banned","ok","fail"],"passed":false},{"actual":["fail","fail","ban-until-17","fail"],"check":"window prune boundary","expected":["fail","fail","ban-until-17","fail"],"passed":true},{"actual":["fail","fail","ban-until-7","banned","fail","ok"],"check":"failures cleared by ban","expected":["fail","fail","ban-until-7","fail","fail","ok"],"passed":false},{"actual":["fail","ban-until-11","banned","banned","banned","ok"],"check":"banned failures ignored","expected":["fail","ban-until-11","banned","banned","fail","ok"],"passed":false},{"actual":["fail","fail","ban-until-31","banned","fail","fail","ban-until-87","banned","banned","banned","fail","ok","fail","ok"],"check":"random attempts","expected":["fail","fail","ban-until-31","banned","fail","fail","ban-until-87","banned","banned","fail","fail","ok","fail","ok"],"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"ban and escalate\", \"actual\": [\"fail\", \"fail\", \"ban-until-12\", \"banned\", \"banned\", \"fail\", \"fail\", \"ban-until-51\", \"banned\"], \"expected\": [\"fail\", \"fail\", \"ban-until-12\", \"banned\", \"fail\", \"fail\", \"ban-until-34\", \"banned\", \"ok\"], \"passed\": false}, {\"check\": \"third ban escalates\", \"actual\": [\"ban-until-10\", \"banned\", \"ban-until-50\", \"ok\", \"ok\"], \"expected\": [\"ban-until-10\", \"ban-until-30\", \"ban-until-70\", \"banned\", \"ok\"], \"passed\": false}, {\"check\": \"ban end instant\", \"actual\": [\"fail\", \"ban-until-21\", \"banned\", \"banned\", \"fail\"], \"expected\": [\"fail\", \"ban-until-21\", \"banned\", \"ok\", \"fail\"], \"passed\": false}, {\"check\": \"window prune boundary\", \"actual\": [\"fail\", \"fail\", \"ban-until-17\", \"fail\"], \"expected\": [\"fail\", \"fail\", \"ban-until-17\", \"fail\"], \"passed\": true}, {\"check\": \"failures cleared by ban\", \"actual\": [\"fail\", \"fail\", \"ban-until-7\", \"banned\", \"fail\", \"ok\"], \"expected\": [\"fail\", \"fail\", \"ban-until-7\", \"fail\", \"fail\", \"ok\"], \"passed\": false}, {\"check\": \"banned failures ignored\", \"actual\": [\"fail\", \"ban-until-11\", \"banned\", \"banned\", \"banned\", \"ok\"], \"expected\": [\"fail\", \"ban-until-11\", \"banned\", \"banned\", \"fail\", \"ok\"], \"passed\": false}, {\"check\": \"random attempts\", \"actual\": [\"fail\", \"fail\", \"ban-until-31\", \"banned\", \"fail\", \"fail\", \"ban-until-87\", \"banned\", \"banned\", \"banned\", \"fail\", \"ok\", \"fail\", \"ok\"], \"expected\": [\"fail\", \"fail\", \"ban-until-31\", \"banned\", \"fail\", \"fail\", \"ban-until-87\", \"banned\", \"banned\", \"fail\", \"fail\", \"ok\", \"fail\", \"ok\"], \"passed\": false}], \"passed\": false}\n"},"fixed":{"elapsed_ms":39.488,"exit_code":0,"observations":[{"actual":["fail","fail","ban-until-12","banned","fail","fail","ban-until-34","banned","ok"],"check":"ban and escalate","expected":["fail","fail","ban-until-12","banned","fail","fail","ban-until-34","banned","ok"],"passed":true},{"actual":["ban-until-10","ban-until-30","ban-until-70","banned","ok"],"check":"third ban escalates","expected":["ban-until-10","ban-until-30","ban-until-70","banned","ok"],"passed":true},{"actual":["fail","ban-until-21","banned","ok","fail"],"check":"ban end instant","expected":["fail","ban-until-21","banned","ok","fail"],"passed":true},{"actual":["fail","fail","ban-until-17","fail"],"check":"window prune boundary","expected":["fail","fail","ban-until-17","fail"],"passed":true},{"actual":["fail","fail","ban-until-7","fail","fail","ok"],"check":"failures cleared by ban","expected":["fail","fail","ban-until-7","fail","fail","ok"],"passed":true},{"actual":["fail","ban-until-11","banned","banned","fail","ok"],"check":"banned failures ignored","expected":["fail","ban-until-11","banned","banned","fail","ok"],"passed":true},{"actual":["fail","fail","ban-until-31","banned","fail","fail","ban-until-87","banned","banned","fail","fail","ok","fail","ok"],"check":"random attempts","expected":["fail","fail","ban-until-31","banned","fail","fail","ban-until-87","banned","banned","fail","fail","ok","fail","ok"],"passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"ban and escalate\", \"actual\": [\"fail\", \"fail\", \"ban-until-12\", \"banned\", \"fail\", \"fail\", \"ban-until-34\", \"banned\", \"ok\"], \"expected\": [\"fail\", \"fail\", \"ban-until-12\", \"banned\", \"fail\", \"fail\", \"ban-until-34\", \"banned\", \"ok\"], \"passed\": true}, {\"check\": \"third ban escalates\", \"actual\": [\"ban-until-10\", \"ban-until-30\", \"ban-until-70\", \"banned\", \"ok\"], \"expected\": [\"ban-until-10\", \"ban-until-30\", \"ban-until-70\", \"banned\", \"ok\"], \"passed\": true}, {\"check\": \"ban end instant\", \"actual\": [\"fail\", \"ban-until-21\", \"banned\", \"ok\", \"fail\"], \"expected\": [\"fail\", \"ban-until-21\", \"banned\", \"ok\", \"fail\"], \"passed\": true}, {\"check\": \"window prune boundary\", \"actual\": [\"fail\", \"fail\", \"ban-until-17\", \"fail\"], \"expected\": [\"fail\", \"fail\", \"ban-until-17\", \"fail\"], \"passed\": true}, {\"check\": \"failures cleared by ban\", \"actual\": [\"fail\", \"fail\", \"ban-until-7\", \"fail\", \"fail\", \"ok\"], \"expected\": [\"fail\", \"fail\", \"ban-until-7\", \"fail\", \"fail\", \"ok\"], \"passed\": true}, {\"check\": \"banned failures ignored\", \"actual\": [\"fail\", \"ban-until-11\", \"banned\", \"banned\", \"fail\", \"ok\"], \"expected\": [\"fail\", \"ban-until-11\", \"banned\", \"banned\", \"fail\", \"ok\"], \"passed\": true}, {\"check\": \"random attempts\", \"actual\": [\"fail\", \"fail\", \"ban-until-31\", \"banned\", \"fail\", \"fail\", \"ban-until-87\", \"banned\", \"banned\", \"fail\", \"fail\", \"ok\", \"fail\", \"ok\"], \"expected\": [\"fail\", \"fail\", \"ban-until-31\", \"banned\", \"fail\", \"fail\", \"ban-until-87\", \"banned\", \"banned\", \"fail\", \"fail\", \"ok\", \"fail\", \"ok\"], \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}