{"abstract":"Requests rejected by the minute limit also exhaust the per-second allowance.","category":"Rate limiter algorithms","checks":6,"contract":"Input {per_second, per_minute, requests [t_ms]} with nondecreasing t. Second windows are t div 1000 and minute windows t div 60000, each resetting its own counter only when its own window changes. The second limit is checked first (\"deny-second\"), then the minute limit (\"deny-minute\"); only admitted requests are counted, in both windows. Return [decisions, second count, minute count].","evaluation_group":"w2-rate_limiter_algorithms-dual-window","failed_approach":"Counting the denial in the minute window inflates the reported usage.","family":"w2-rate_limiter_algorithms-dual-window-minute-deny-charge","id":"FA-73806","implementations":{"attempt":{"sha256":"2517925a551e771ab1cd2d761231c11c0cd1f27c93bb6e24100e3abb7e2db512","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(x):\n    ls, lm = x['per_second'], x['per_minute']\n    sw = mw = None\n    sc = mc = 0\n    out = []\n    for t in x['requests']:\n        s, m = t // 1000, t // 60000\n        if s != sw:\n            sw, sc = s, 0\n        if m != mw:\n            mw, mc = m, 0\n        if sc >= ls:\n            out.append('deny-second')\n        elif mc >= lm:\n            mc += 1\n            out.append('deny-minute')\n        else:\n            sc += 1\n            mc += 1\n            out.append('allow')\n    return [out, sc, mc]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\ncases = [[['minute budget spans seconds',\n   {'per_minute': 5, 'per_second': 2, 'requests': [0, 1, 1000, 1001, 2000, 2001, 3001, 59999]},\n   [['allow', 'allow', 'allow', 'allow', 'allow', 'deny-minute', 'deny-minute', 'deny-minute'],\n    0,\n    5]],\n  ['second limit inside minute',\n   {'per_minute': 10, 'per_second': 1, 'requests': [0, 10, 20, 1001, 1010]},\n   [['allow', 'deny-second', 'deny-second', 'allow', 'deny-second'], 1, 2]],\n  ['minute rollover',\n   {'per_minute': 3, 'per_second': 3, 'requests': [59000, 59001, 59002, 59500, 60001, 60001]},\n   [['allow', 'allow', 'allow', 'deny-second', 'allow', 'allow'], 2, 2]],\n  ['both exhausted reports second',\n   {'per_minute': 1, 'per_second': 1, 'requests': [0, 1, 1001, 1001]},\n   [['allow', 'deny-second', 'deny-minute', 'deny-minute'], 0, 1]],\n  ['minute denials keep second budget',\n   {'per_minute': 2, 'per_second': 2, 'requests': [0, 1000, 2000, 2001, 2003, 60000, 60001, 60002]},\n   [['allow',\n     'allow',\n     'deny-minute',\n     'deny-minute',\n     'deny-minute',\n     'allow',\n     'allow',\n     'deny-second'],\n    2,\n    2]],\n  ['random traffic',\n   {'per_minute': 6,\n    'per_second': 2,\n    'requests': [1062,\n                 8418,\n                 9273,\n                 34515,\n                 47777,\n                 65888,\n                 67598,\n                 89351,\n                 103730,\n                 110167,\n                 110678,\n                 120637,\n                 122553,\n                 128547]},\n   [['allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow'],\n    1,\n    3]]],\n [['minute budget spans seconds',\n   {'per_minute': 5, 'per_second': 2, 'requests': [0, 1, 1000, 1001, 2000, 2001, 3002, 59999]},\n   [['allow', 'allow', 'allow', 'allow', 'allow', 'deny-minute', 'deny-minute', 'deny-minute'],\n    0,\n    5]],\n  ['second limit inside minute',\n   {'per_minute': 10, 'per_second': 1, 'requests': [0, 10, 20, 1002, 1010]},\n   [['allow', 'deny-second', 'deny-second', 'allow', 'deny-second'], 1, 2]],\n  ['minute rollover',\n   {'per_minute': 3, 'per_second': 3, 'requests': [59000, 59001, 59002, 59500, 60002, 60001]},\n   [['allow', 'allow', 'allow', 'deny-second', 'allow', 'allow'], 2, 2]],\n  ['both exhausted reports second',\n   {'per_minute': 1, 'per_second': 1, 'requests': [0, 1, 1002, 1001]},\n   [['allow', 'deny-second', 'deny-minute', 'deny-minute'], 0, 1]],\n  ['minute denials keep second budget',\n   {'per_minute': 2, 'per_second': 2, 'requests': [0, 1000, 2000, 2001, 2004, 60000, 60001, 60002]},\n   [['allow',\n     'allow',\n     'deny-minute',\n     'deny-minute',\n     'deny-minute',\n     'allow',\n     'allow',\n     'deny-second'],\n    2,\n    2]],\n  ['random traffic',\n   {'per_minute': 6,\n    'per_second': 2,\n    'requests': [4406,\n                 11048,\n                 15610,\n                 37272,\n                 37553,\n                 45326,\n                 49676,\n                 64905,\n                 66877,\n                 80916,\n                 104479,\n                 105515,\n                 113188,\n                 115762]},\n   [['allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'deny-minute',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'deny-minute'],\n    0,\n    6]]],\n [['minute budget spans seconds',\n   {'per_minute': 5, 'per_second': 2, 'requests': [0, 1, 1000, 1001, 2000, 2001, 3003, 59999]},\n   [['allow', 'allow', 'allow', 'allow', 'allow', 'deny-minute', 'deny-minute', 'deny-minute'],\n    0,\n    5]],\n  ['second limit inside minute',\n   {'per_minute': 10, 'per_second': 1, 'requests': [0, 10, 20, 1003, 1010]},\n   [['allow', 'deny-second', 'deny-second', 'allow', 'deny-second'], 1, 2]],\n  ['minute rollover',\n   {'per_minute': 3, 'per_second': 3, 'requests': [59000, 59001, 59002, 59500, 60003, 60001]},\n   [['allow', 'allow', 'allow', 'deny-second', 'allow', 'allow'], 2, 2]],\n  ['both exhausted reports second',\n   {'per_minute': 1, 'per_second': 1, 'requests': [0, 1, 1003, 1001]},\n   [['allow', 'deny-second', 'deny-minute', 'deny-minute'], 0, 1]],\n  ['minute denials keep second budget',\n   {'per_minute': 2, 'per_second': 2, 'requests': [0, 1000, 2000, 2001, 2005, 60000, 60001, 60002]},\n   [['allow',\n     'allow',\n     'deny-minute',\n     'deny-minute',\n     'deny-minute',\n     'allow',\n     'allow',\n     'deny-second'],\n    2,\n    2]],\n  ['random traffic',\n   {'per_minute': 6,\n    'per_second': 2,\n    'requests': [12496,\n                 13001,\n                 16785,\n                 17435,\n                 41410,\n                 44765,\n                 45872,\n                 51289,\n                 69195,\n                 73570,\n                 101381,\n                 106192,\n                 110461,\n                 126847]},\n   [['allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'deny-minute',\n     'deny-minute',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow'],\n    1,\n    1]]],\n [['minute budget spans seconds',\n   {'per_minute': 5, 'per_second': 2, 'requests': [0, 1, 1000, 1001, 2000, 2001, 3004, 59999]},\n   [['allow', 'allow', 'allow', 'allow', 'allow', 'deny-minute', 'deny-minute', 'deny-minute'],\n    0,\n    5]],\n  ['second limit inside minute',\n   {'per_minute': 10, 'per_second': 1, 'requests': [0, 10, 20, 1004, 1010]},\n   [['allow', 'deny-second', 'deny-second', 'allow', 'deny-second'], 1, 2]],\n  ['minute rollover',\n   {'per_minute': 3, 'per_second': 3, 'requests': [59000, 59001, 59002, 59500, 60004, 60001]},\n   [['allow', 'allow', 'allow', 'deny-second', 'allow', 'allow'], 2, 2]],\n  ['both exhausted reports second',\n   {'per_minute': 1, 'per_second': 1, 'requests': [0, 1, 1004, 1001]},\n   [['allow', 'deny-second', 'deny-minute', 'deny-minute'], 0, 1]],\n  ['minute denials keep second budget',\n   {'per_minute': 2, 'per_second': 2, 'requests': [0, 1000, 2000, 2001, 2006, 60000, 60001, 60002]},\n   [['allow',\n     'allow',\n     'deny-minute',\n     'deny-minute',\n     'deny-minute',\n     'allow',\n     'allow',\n     'deny-second'],\n    2,\n    2]],\n  ['random traffic',\n   {'per_minute': 6,\n    'per_second': 2,\n    'requests': [35872,\n                 47171,\n                 57795,\n                 66404,\n                 69658,\n                 83185,\n                 86836,\n                 87855,\n                 88307,\n                 96707,\n                 97802,\n                 102613,\n                 119928,\n                 129412]},\n   [['allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'deny-minute',\n     'deny-minute',\n     'deny-minute',\n     'deny-minute',\n     'allow'],\n    1,\n    1]]],\n [['minute budget spans seconds',\n   {'per_minute': 5, 'per_second': 2, 'requests': [0, 1, 1000, 1001, 2000, 2001, 3005, 59999]},\n   [['allow', 'allow', 'allow', 'allow', 'allow', 'deny-minute', 'deny-minute', 'deny-minute'],\n    0,\n    5]],\n  ['second limit inside minute',\n   {'per_minute': 10, 'per_second': 1, 'requests': [0, 10, 20, 1005, 1010]},\n   [['allow', 'deny-second', 'deny-second', 'allow', 'deny-second'], 1, 2]],\n  ['minute rollover',\n   {'per_minute': 3, 'per_second': 3, 'requests': [59000, 59001, 59002, 59500, 60005, 60001]},\n   [['allow', 'allow', 'allow', 'deny-second', 'allow', 'allow'], 2, 2]],\n  ['both exhausted reports second',\n   {'per_minute': 1, 'per_second': 1, 'requests': [0, 1, 1005, 1001]},\n   [['allow', 'deny-second', 'deny-minute', 'deny-minute'], 0, 1]],\n  ['minute denials keep second budget',\n   {'per_minute': 2, 'per_second': 2, 'requests': [0, 1000, 2000, 2001, 2007, 60000, 60001, 60002]},\n   [['allow',\n     'allow',\n     'deny-minute',\n     'deny-minute',\n     'deny-minute',\n     'allow',\n     'allow',\n     'deny-second'],\n    2,\n    2]],\n  ['random traffic',\n   {'per_minute': 6,\n    'per_second': 2,\n    'requests': [2584,\n                 8339,\n                 26804,\n                 29473,\n                 39448,\n                 51111,\n                 57796,\n                 65951,\n                 70268,\n                 73982,\n                 76067,\n                 80339,\n                 81264,\n                 102821]},\n   [['allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'deny-minute',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'deny-minute'],\n    0,\n    6]]]]\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":"14eac88067bdb9b9fe9ebb9b33e0e4ddf501b4d47cef4b3e5493cbeac6b95818","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(x):\n    ls, lm = x['per_second'], x['per_minute']\n    sw = mw = None\n    sc = mc = 0\n    out = []\n    for t in x['requests']:\n        s, m = t // 1000, t // 60000\n        if s != sw:\n            sw, sc = s, 0\n        if m != mw:\n            mw, mc = m, 0\n        if sc >= ls:\n            out.append('deny-second')\n        elif mc >= lm:\n            sc += 1\n            out.append('deny-minute')\n        else:\n            sc += 1\n            mc += 1\n            out.append('allow')\n    return [out, sc, mc]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\ncases = [[['minute budget spans seconds',\n   {'per_minute': 5, 'per_second': 2, 'requests': [0, 1, 1000, 1001, 2000, 2001, 3001, 59999]},\n   [['allow', 'allow', 'allow', 'allow', 'allow', 'deny-minute', 'deny-minute', 'deny-minute'],\n    0,\n    5]],\n  ['second limit inside minute',\n   {'per_minute': 10, 'per_second': 1, 'requests': [0, 10, 20, 1001, 1010]},\n   [['allow', 'deny-second', 'deny-second', 'allow', 'deny-second'], 1, 2]],\n  ['minute rollover',\n   {'per_minute': 3, 'per_second': 3, 'requests': [59000, 59001, 59002, 59500, 60001, 60001]},\n   [['allow', 'allow', 'allow', 'deny-second', 'allow', 'allow'], 2, 2]],\n  ['both exhausted reports second',\n   {'per_minute': 1, 'per_second': 1, 'requests': [0, 1, 1001, 1001]},\n   [['allow', 'deny-second', 'deny-minute', 'deny-minute'], 0, 1]],\n  ['minute denials keep second budget',\n   {'per_minute': 2, 'per_second': 2, 'requests': [0, 1000, 2000, 2001, 2003, 60000, 60001, 60002]},\n   [['allow',\n     'allow',\n     'deny-minute',\n     'deny-minute',\n     'deny-minute',\n     'allow',\n     'allow',\n     'deny-second'],\n    2,\n    2]],\n  ['random traffic',\n   {'per_minute': 6,\n    'per_second': 2,\n    'requests': [1062,\n                 8418,\n                 9273,\n                 34515,\n                 47777,\n                 65888,\n                 67598,\n                 89351,\n                 103730,\n                 110167,\n                 110678,\n                 120637,\n                 122553,\n                 128547]},\n   [['allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow'],\n    1,\n    3]]],\n [['minute budget spans seconds',\n   {'per_minute': 5, 'per_second': 2, 'requests': [0, 1, 1000, 1001, 2000, 2001, 3002, 59999]},\n   [['allow', 'allow', 'allow', 'allow', 'allow', 'deny-minute', 'deny-minute', 'deny-minute'],\n    0,\n    5]],\n  ['second limit inside minute',\n   {'per_minute': 10, 'per_second': 1, 'requests': [0, 10, 20, 1002, 1010]},\n   [['allow', 'deny-second', 'deny-second', 'allow', 'deny-second'], 1, 2]],\n  ['minute rollover',\n   {'per_minute': 3, 'per_second': 3, 'requests': [59000, 59001, 59002, 59500, 60002, 60001]},\n   [['allow', 'allow', 'allow', 'deny-second', 'allow', 'allow'], 2, 2]],\n  ['both exhausted reports second',\n   {'per_minute': 1, 'per_second': 1, 'requests': [0, 1, 1002, 1001]},\n   [['allow', 'deny-second', 'deny-minute', 'deny-minute'], 0, 1]],\n  ['minute denials keep second budget',\n   {'per_minute': 2, 'per_second': 2, 'requests': [0, 1000, 2000, 2001, 2004, 60000, 60001, 60002]},\n   [['allow',\n     'allow',\n     'deny-minute',\n     'deny-minute',\n     'deny-minute',\n     'allow',\n     'allow',\n     'deny-second'],\n    2,\n    2]],\n  ['random traffic',\n   {'per_minute': 6,\n    'per_second': 2,\n    'requests': [4406,\n                 11048,\n                 15610,\n                 37272,\n                 37553,\n                 45326,\n                 49676,\n                 64905,\n                 66877,\n                 80916,\n                 104479,\n                 105515,\n                 113188,\n                 115762]},\n   [['allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'deny-minute',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'deny-minute'],\n    0,\n    6]]],\n [['minute budget spans seconds',\n   {'per_minute': 5, 'per_second': 2, 'requests': [0, 1, 1000, 1001, 2000, 2001, 3003, 59999]},\n   [['allow', 'allow', 'allow', 'allow', 'allow', 'deny-minute', 'deny-minute', 'deny-minute'],\n    0,\n    5]],\n  ['second limit inside minute',\n   {'per_minute': 10, 'per_second': 1, 'requests': [0, 10, 20, 1003, 1010]},\n   [['allow', 'deny-second', 'deny-second', 'allow', 'deny-second'], 1, 2]],\n  ['minute rollover',\n   {'per_minute': 3, 'per_second': 3, 'requests': [59000, 59001, 59002, 59500, 60003, 60001]},\n   [['allow', 'allow', 'allow', 'deny-second', 'allow', 'allow'], 2, 2]],\n  ['both exhausted reports second',\n   {'per_minute': 1, 'per_second': 1, 'requests': [0, 1, 1003, 1001]},\n   [['allow', 'deny-second', 'deny-minute', 'deny-minute'], 0, 1]],\n  ['minute denials keep second budget',\n   {'per_minute': 2, 'per_second': 2, 'requests': [0, 1000, 2000, 2001, 2005, 60000, 60001, 60002]},\n   [['allow',\n     'allow',\n     'deny-minute',\n     'deny-minute',\n     'deny-minute',\n     'allow',\n     'allow',\n     'deny-second'],\n    2,\n    2]],\n  ['random traffic',\n   {'per_minute': 6,\n    'per_second': 2,\n    'requests': [12496,\n                 13001,\n                 16785,\n                 17435,\n                 41410,\n                 44765,\n                 45872,\n                 51289,\n                 69195,\n                 73570,\n                 101381,\n                 106192,\n                 110461,\n                 126847]},\n   [['allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'deny-minute',\n     'deny-minute',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow'],\n    1,\n    1]]],\n [['minute budget spans seconds',\n   {'per_minute': 5, 'per_second': 2, 'requests': [0, 1, 1000, 1001, 2000, 2001, 3004, 59999]},\n   [['allow', 'allow', 'allow', 'allow', 'allow', 'deny-minute', 'deny-minute', 'deny-minute'],\n    0,\n    5]],\n  ['second limit inside minute',\n   {'per_minute': 10, 'per_second': 1, 'requests': [0, 10, 20, 1004, 1010]},\n   [['allow', 'deny-second', 'deny-second', 'allow', 'deny-second'], 1, 2]],\n  ['minute rollover',\n   {'per_minute': 3, 'per_second': 3, 'requests': [59000, 59001, 59002, 59500, 60004, 60001]},\n   [['allow', 'allow', 'allow', 'deny-second', 'allow', 'allow'], 2, 2]],\n  ['both exhausted reports second',\n   {'per_minute': 1, 'per_second': 1, 'requests': [0, 1, 1004, 1001]},\n   [['allow', 'deny-second', 'deny-minute', 'deny-minute'], 0, 1]],\n  ['minute denials keep second budget',\n   {'per_minute': 2, 'per_second': 2, 'requests': [0, 1000, 2000, 2001, 2006, 60000, 60001, 60002]},\n   [['allow',\n     'allow',\n     'deny-minute',\n     'deny-minute',\n     'deny-minute',\n     'allow',\n     'allow',\n     'deny-second'],\n    2,\n    2]],\n  ['random traffic',\n   {'per_minute': 6,\n    'per_second': 2,\n    'requests': [35872,\n                 47171,\n                 57795,\n                 66404,\n                 69658,\n                 83185,\n                 86836,\n                 87855,\n                 88307,\n                 96707,\n                 97802,\n                 102613,\n                 119928,\n                 129412]},\n   [['allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'deny-minute',\n     'deny-minute',\n     'deny-minute',\n     'deny-minute',\n     'allow'],\n    1,\n    1]]],\n [['minute budget spans seconds',\n   {'per_minute': 5, 'per_second': 2, 'requests': [0, 1, 1000, 1001, 2000, 2001, 3005, 59999]},\n   [['allow', 'allow', 'allow', 'allow', 'allow', 'deny-minute', 'deny-minute', 'deny-minute'],\n    0,\n    5]],\n  ['second limit inside minute',\n   {'per_minute': 10, 'per_second': 1, 'requests': [0, 10, 20, 1005, 1010]},\n   [['allow', 'deny-second', 'deny-second', 'allow', 'deny-second'], 1, 2]],\n  ['minute rollover',\n   {'per_minute': 3, 'per_second': 3, 'requests': [59000, 59001, 59002, 59500, 60005, 60001]},\n   [['allow', 'allow', 'allow', 'deny-second', 'allow', 'allow'], 2, 2]],\n  ['both exhausted reports second',\n   {'per_minute': 1, 'per_second': 1, 'requests': [0, 1, 1005, 1001]},\n   [['allow', 'deny-second', 'deny-minute', 'deny-minute'], 0, 1]],\n  ['minute denials keep second budget',\n   {'per_minute': 2, 'per_second': 2, 'requests': [0, 1000, 2000, 2001, 2007, 60000, 60001, 60002]},\n   [['allow',\n     'allow',\n     'deny-minute',\n     'deny-minute',\n     'deny-minute',\n     'allow',\n     'allow',\n     'deny-second'],\n    2,\n    2]],\n  ['random traffic',\n   {'per_minute': 6,\n    'per_second': 2,\n    'requests': [2584,\n                 8339,\n                 26804,\n                 29473,\n                 39448,\n                 51111,\n                 57796,\n                 65951,\n                 70268,\n                 73982,\n                 76067,\n                 80339,\n                 81264,\n                 102821]},\n   [['allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'deny-minute',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'deny-minute'],\n    0,\n    6]]]]\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":"249c4e2d1f111bba686a8a7437e3e994f711b586a147e9419ae887c2a1817a25","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(x):\n    ls, lm = x['per_second'], x['per_minute']\n    sw = mw = None\n    sc = mc = 0\n    out = []\n    for t in x['requests']:\n        s, m = t // 1000, t // 60000\n        if s != sw:\n            sw, sc = s, 0\n        if m != mw:\n            mw, mc = m, 0\n        if sc >= ls:\n            out.append('deny-second')\n        elif mc >= lm:\n            out.append('deny-minute')\n        else:\n            sc += 1\n            mc += 1\n            out.append('allow')\n    return [out, sc, mc]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\ncases = [[['minute budget spans seconds',\n   {'per_minute': 5, 'per_second': 2, 'requests': [0, 1, 1000, 1001, 2000, 2001, 3001, 59999]},\n   [['allow', 'allow', 'allow', 'allow', 'allow', 'deny-minute', 'deny-minute', 'deny-minute'],\n    0,\n    5]],\n  ['second limit inside minute',\n   {'per_minute': 10, 'per_second': 1, 'requests': [0, 10, 20, 1001, 1010]},\n   [['allow', 'deny-second', 'deny-second', 'allow', 'deny-second'], 1, 2]],\n  ['minute rollover',\n   {'per_minute': 3, 'per_second': 3, 'requests': [59000, 59001, 59002, 59500, 60001, 60001]},\n   [['allow', 'allow', 'allow', 'deny-second', 'allow', 'allow'], 2, 2]],\n  ['both exhausted reports second',\n   {'per_minute': 1, 'per_second': 1, 'requests': [0, 1, 1001, 1001]},\n   [['allow', 'deny-second', 'deny-minute', 'deny-minute'], 0, 1]],\n  ['minute denials keep second budget',\n   {'per_minute': 2, 'per_second': 2, 'requests': [0, 1000, 2000, 2001, 2003, 60000, 60001, 60002]},\n   [['allow',\n     'allow',\n     'deny-minute',\n     'deny-minute',\n     'deny-minute',\n     'allow',\n     'allow',\n     'deny-second'],\n    2,\n    2]],\n  ['random traffic',\n   {'per_minute': 6,\n    'per_second': 2,\n    'requests': [1062,\n                 8418,\n                 9273,\n                 34515,\n                 47777,\n                 65888,\n                 67598,\n                 89351,\n                 103730,\n                 110167,\n                 110678,\n                 120637,\n                 122553,\n                 128547]},\n   [['allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow'],\n    1,\n    3]]],\n [['minute budget spans seconds',\n   {'per_minute': 5, 'per_second': 2, 'requests': [0, 1, 1000, 1001, 2000, 2001, 3002, 59999]},\n   [['allow', 'allow', 'allow', 'allow', 'allow', 'deny-minute', 'deny-minute', 'deny-minute'],\n    0,\n    5]],\n  ['second limit inside minute',\n   {'per_minute': 10, 'per_second': 1, 'requests': [0, 10, 20, 1002, 1010]},\n   [['allow', 'deny-second', 'deny-second', 'allow', 'deny-second'], 1, 2]],\n  ['minute rollover',\n   {'per_minute': 3, 'per_second': 3, 'requests': [59000, 59001, 59002, 59500, 60002, 60001]},\n   [['allow', 'allow', 'allow', 'deny-second', 'allow', 'allow'], 2, 2]],\n  ['both exhausted reports second',\n   {'per_minute': 1, 'per_second': 1, 'requests': [0, 1, 1002, 1001]},\n   [['allow', 'deny-second', 'deny-minute', 'deny-minute'], 0, 1]],\n  ['minute denials keep second budget',\n   {'per_minute': 2, 'per_second': 2, 'requests': [0, 1000, 2000, 2001, 2004, 60000, 60001, 60002]},\n   [['allow',\n     'allow',\n     'deny-minute',\n     'deny-minute',\n     'deny-minute',\n     'allow',\n     'allow',\n     'deny-second'],\n    2,\n    2]],\n  ['random traffic',\n   {'per_minute': 6,\n    'per_second': 2,\n    'requests': [4406,\n                 11048,\n                 15610,\n                 37272,\n                 37553,\n                 45326,\n                 49676,\n                 64905,\n                 66877,\n                 80916,\n                 104479,\n                 105515,\n                 113188,\n                 115762]},\n   [['allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'deny-minute',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'deny-minute'],\n    0,\n    6]]],\n [['minute budget spans seconds',\n   {'per_minute': 5, 'per_second': 2, 'requests': [0, 1, 1000, 1001, 2000, 2001, 3003, 59999]},\n   [['allow', 'allow', 'allow', 'allow', 'allow', 'deny-minute', 'deny-minute', 'deny-minute'],\n    0,\n    5]],\n  ['second limit inside minute',\n   {'per_minute': 10, 'per_second': 1, 'requests': [0, 10, 20, 1003, 1010]},\n   [['allow', 'deny-second', 'deny-second', 'allow', 'deny-second'], 1, 2]],\n  ['minute rollover',\n   {'per_minute': 3, 'per_second': 3, 'requests': [59000, 59001, 59002, 59500, 60003, 60001]},\n   [['allow', 'allow', 'allow', 'deny-second', 'allow', 'allow'], 2, 2]],\n  ['both exhausted reports second',\n   {'per_minute': 1, 'per_second': 1, 'requests': [0, 1, 1003, 1001]},\n   [['allow', 'deny-second', 'deny-minute', 'deny-minute'], 0, 1]],\n  ['minute denials keep second budget',\n   {'per_minute': 2, 'per_second': 2, 'requests': [0, 1000, 2000, 2001, 2005, 60000, 60001, 60002]},\n   [['allow',\n     'allow',\n     'deny-minute',\n     'deny-minute',\n     'deny-minute',\n     'allow',\n     'allow',\n     'deny-second'],\n    2,\n    2]],\n  ['random traffic',\n   {'per_minute': 6,\n    'per_second': 2,\n    'requests': [12496,\n                 13001,\n                 16785,\n                 17435,\n                 41410,\n                 44765,\n                 45872,\n                 51289,\n                 69195,\n                 73570,\n                 101381,\n                 106192,\n                 110461,\n                 126847]},\n   [['allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'deny-minute',\n     'deny-minute',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow'],\n    1,\n    1]]],\n [['minute budget spans seconds',\n   {'per_minute': 5, 'per_second': 2, 'requests': [0, 1, 1000, 1001, 2000, 2001, 3004, 59999]},\n   [['allow', 'allow', 'allow', 'allow', 'allow', 'deny-minute', 'deny-minute', 'deny-minute'],\n    0,\n    5]],\n  ['second limit inside minute',\n   {'per_minute': 10, 'per_second': 1, 'requests': [0, 10, 20, 1004, 1010]},\n   [['allow', 'deny-second', 'deny-second', 'allow', 'deny-second'], 1, 2]],\n  ['minute rollover',\n   {'per_minute': 3, 'per_second': 3, 'requests': [59000, 59001, 59002, 59500, 60004, 60001]},\n   [['allow', 'allow', 'allow', 'deny-second', 'allow', 'allow'], 2, 2]],\n  ['both exhausted reports second',\n   {'per_minute': 1, 'per_second': 1, 'requests': [0, 1, 1004, 1001]},\n   [['allow', 'deny-second', 'deny-minute', 'deny-minute'], 0, 1]],\n  ['minute denials keep second budget',\n   {'per_minute': 2, 'per_second': 2, 'requests': [0, 1000, 2000, 2001, 2006, 60000, 60001, 60002]},\n   [['allow',\n     'allow',\n     'deny-minute',\n     'deny-minute',\n     'deny-minute',\n     'allow',\n     'allow',\n     'deny-second'],\n    2,\n    2]],\n  ['random traffic',\n   {'per_minute': 6,\n    'per_second': 2,\n    'requests': [35872,\n                 47171,\n                 57795,\n                 66404,\n                 69658,\n                 83185,\n                 86836,\n                 87855,\n                 88307,\n                 96707,\n                 97802,\n                 102613,\n                 119928,\n                 129412]},\n   [['allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'deny-minute',\n     'deny-minute',\n     'deny-minute',\n     'deny-minute',\n     'allow'],\n    1,\n    1]]],\n [['minute budget spans seconds',\n   {'per_minute': 5, 'per_second': 2, 'requests': [0, 1, 1000, 1001, 2000, 2001, 3005, 59999]},\n   [['allow', 'allow', 'allow', 'allow', 'allow', 'deny-minute', 'deny-minute', 'deny-minute'],\n    0,\n    5]],\n  ['second limit inside minute',\n   {'per_minute': 10, 'per_second': 1, 'requests': [0, 10, 20, 1005, 1010]},\n   [['allow', 'deny-second', 'deny-second', 'allow', 'deny-second'], 1, 2]],\n  ['minute rollover',\n   {'per_minute': 3, 'per_second': 3, 'requests': [59000, 59001, 59002, 59500, 60005, 60001]},\n   [['allow', 'allow', 'allow', 'deny-second', 'allow', 'allow'], 2, 2]],\n  ['both exhausted reports second',\n   {'per_minute': 1, 'per_second': 1, 'requests': [0, 1, 1005, 1001]},\n   [['allow', 'deny-second', 'deny-minute', 'deny-minute'], 0, 1]],\n  ['minute denials keep second budget',\n   {'per_minute': 2, 'per_second': 2, 'requests': [0, 1000, 2000, 2001, 2007, 60000, 60001, 60002]},\n   [['allow',\n     'allow',\n     'deny-minute',\n     'deny-minute',\n     'deny-minute',\n     'allow',\n     'allow',\n     'deny-second'],\n    2,\n    2]],\n  ['random traffic',\n   {'per_minute': 6,\n    'per_second': 2,\n    'requests': [2584,\n                 8339,\n                 26804,\n                 29473,\n                 39448,\n                 51111,\n                 57796,\n                 65951,\n                 70268,\n                 73982,\n                 76067,\n                 80339,\n                 81264,\n                 102821]},\n   [['allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'deny-minute',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'allow',\n     'deny-minute'],\n    0,\n    6]]]]\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-dual-window-minute-deny-charge","generated_at":"2026-09-29T14:48:50.875104+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"Public APIs commonly publish several simultaneous limits; coupling their resets or charging denied requests to one of them breaks the published contract.","repair":"Do not count denied requests in any window.","root_cause":"The deny-minute branch increments the second counter.","sha256":"b2f379ce51827ca720183de3d97b210162c6e25cb6e5ee5d2f7e98c4475f111e","title":"Combined per-second and per-minute fixed windows: minute denial consumes the second budget · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":41.229,"exit_code":1,"observations":[{"actual":[["allow","allow","allow","allow","allow","deny-minute","deny-minute","deny-minute"],0,8],"check":"minute budget spans seconds","expected":[["allow","allow","allow","allow","allow","deny-minute","deny-minute","deny-minute"],0,5],"passed":false},{"actual":[["allow","deny-second","deny-second","allow","deny-second"],1,2],"check":"second limit inside minute","expected":[["allow","deny-second","deny-second","allow","deny-second"],1,2],"passed":true},{"actual":[["allow","allow","allow","deny-second","allow","allow"],2,2],"check":"minute rollover","expected":[["allow","allow","allow","deny-second","allow","allow"],2,2],"passed":true},{"actual":[["allow","deny-second","deny-minute","deny-minute"],0,3],"check":"both exhausted reports second","expected":[["allow","deny-second","deny-minute","deny-minute"],0,1],"passed":false},{"actual":[["allow","allow","deny-minute","deny-minute","deny-minute","allow","allow","deny-second"],2,2],"check":"minute denials keep second budget","expected":[["allow","allow","deny-minute","deny-minute","deny-minute","allow","allow","deny-second"],2,2],"passed":true},{"actual":[["allow","allow","allow","allow","allow","allow","allow","allow","allow","allow","allow","allow","allow","allow"],1,3],"check":"random traffic","expected":[["allow","allow","allow","allow","allow","allow","allow","allow","allow","allow","allow","allow","allow","allow"],1,3],"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"minute budget spans seconds\", \"actual\": [[\"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"deny-minute\", \"deny-minute\", \"deny-minute\"], 0, 8], \"expected\": [[\"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"deny-minute\", \"deny-minute\", \"deny-minute\"], 0, 5], \"passed\": false}, {\"check\": \"second limit inside minute\", \"actual\": [[\"allow\", \"deny-second\", \"deny-second\", \"allow\", \"deny-second\"], 1, 2], \"expected\": [[\"allow\", \"deny-second\", \"deny-second\", \"allow\", \"deny-second\"], 1, 2], \"passed\": true}, {\"check\": \"minute rollover\", \"actual\": [[\"allow\", \"allow\", \"allow\", \"deny-second\", \"allow\", \"allow\"], 2, 2], \"expected\": [[\"allow\", \"allow\", \"allow\", \"deny-second\", \"allow\", \"allow\"], 2, 2], \"passed\": true}, {\"check\": \"both exhausted reports second\", \"actual\": [[\"allow\", \"deny-second\", \"deny-minute\", \"deny-minute\"], 0, 3], \"expected\": [[\"allow\", \"deny-second\", \"deny-minute\", \"deny-minute\"], 0, 1], \"passed\": false}, {\"check\": \"minute denials keep second budget\", \"actual\": [[\"allow\", \"allow\", \"deny-minute\", \"deny-minute\", \"deny-minute\", \"allow\", \"allow\", \"deny-second\"], 2, 2], \"expected\": [[\"allow\", \"allow\", \"deny-minute\", \"deny-minute\", \"deny-minute\", \"allow\", \"allow\", \"deny-second\"], 2, 2], \"passed\": true}, {\"check\": \"random traffic\", \"actual\": [[\"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\"], 1, 3], \"expected\": [[\"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\"], 1, 3], \"passed\": true}], \"passed\": false}\n"},"broken":{"elapsed_ms":40.6,"exit_code":1,"observations":[{"actual":[["allow","allow","allow","allow","allow","deny-minute","deny-minute","deny-minute"],1,5],"check":"minute budget spans seconds","expected":[["allow","allow","allow","allow","allow","deny-minute","deny-minute","deny-minute"],0,5],"passed":false},{"actual":[["allow","deny-second","deny-second","allow","deny-second"],1,2],"check":"second limit inside minute","expected":[["allow","deny-second","deny-second","allow","deny-second"],1,2],"passed":true},{"actual":[["allow","allow","allow","deny-second","allow","allow"],2,2],"check":"minute rollover","expected":[["allow","allow","allow","deny-second","allow","allow"],2,2],"passed":true},{"actual":[["allow","deny-second","deny-minute","deny-second"],1,1],"check":"both exhausted reports second","expected":[["allow","deny-second","deny-minute","deny-minute"],0,1],"passed":false},{"actual":[["allow","allow","deny-minute","deny-minute","deny-second","allow","allow","deny-second"],2,2],"check":"minute denials keep second budget","expected":[["allow","allow","deny-minute","deny-minute","deny-minute","allow","allow","deny-second"],2,2],"passed":false},{"actual":[["allow","allow","allow","allow","allow","allow","allow","allow","allow","allow","allow","allow","allow","allow"],1,3],"check":"random traffic","expected":[["allow","allow","allow","allow","allow","allow","allow","allow","allow","allow","allow","allow","allow","allow"],1,3],"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"minute budget spans seconds\", \"actual\": [[\"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"deny-minute\", \"deny-minute\", \"deny-minute\"], 1, 5], \"expected\": [[\"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"deny-minute\", \"deny-minute\", \"deny-minute\"], 0, 5], \"passed\": false}, {\"check\": \"second limit inside minute\", \"actual\": [[\"allow\", \"deny-second\", \"deny-second\", \"allow\", \"deny-second\"], 1, 2], \"expected\": [[\"allow\", \"deny-second\", \"deny-second\", \"allow\", \"deny-second\"], 1, 2], \"passed\": true}, {\"check\": \"minute rollover\", \"actual\": [[\"allow\", \"allow\", \"allow\", \"deny-second\", \"allow\", \"allow\"], 2, 2], \"expected\": [[\"allow\", \"allow\", \"allow\", \"deny-second\", \"allow\", \"allow\"], 2, 2], \"passed\": true}, {\"check\": \"both exhausted reports second\", \"actual\": [[\"allow\", \"deny-second\", \"deny-minute\", \"deny-second\"], 1, 1], \"expected\": [[\"allow\", \"deny-second\", \"deny-minute\", \"deny-minute\"], 0, 1], \"passed\": false}, {\"check\": \"minute denials keep second budget\", \"actual\": [[\"allow\", \"allow\", \"deny-minute\", \"deny-minute\", \"deny-second\", \"allow\", \"allow\", \"deny-second\"], 2, 2], \"expected\": [[\"allow\", \"allow\", \"deny-minute\", \"deny-minute\", \"deny-minute\", \"allow\", \"allow\", \"deny-second\"], 2, 2], \"passed\": false}, {\"check\": \"random traffic\", \"actual\": [[\"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\"], 1, 3], \"expected\": [[\"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\"], 1, 3], \"passed\": true}], \"passed\": false}\n"},"fixed":{"elapsed_ms":40.095,"exit_code":0,"observations":[{"actual":[["allow","allow","allow","allow","allow","deny-minute","deny-minute","deny-minute"],0,5],"check":"minute budget spans seconds","expected":[["allow","allow","allow","allow","allow","deny-minute","deny-minute","deny-minute"],0,5],"passed":true},{"actual":[["allow","deny-second","deny-second","allow","deny-second"],1,2],"check":"second limit inside minute","expected":[["allow","deny-second","deny-second","allow","deny-second"],1,2],"passed":true},{"actual":[["allow","allow","allow","deny-second","allow","allow"],2,2],"check":"minute rollover","expected":[["allow","allow","allow","deny-second","allow","allow"],2,2],"passed":true},{"actual":[["allow","deny-second","deny-minute","deny-minute"],0,1],"check":"both exhausted reports second","expected":[["allow","deny-second","deny-minute","deny-minute"],0,1],"passed":true},{"actual":[["allow","allow","deny-minute","deny-minute","deny-minute","allow","allow","deny-second"],2,2],"check":"minute denials keep second budget","expected":[["allow","allow","deny-minute","deny-minute","deny-minute","allow","allow","deny-second"],2,2],"passed":true},{"actual":[["allow","allow","allow","allow","allow","allow","allow","allow","allow","allow","allow","allow","allow","allow"],1,3],"check":"random traffic","expected":[["allow","allow","allow","allow","allow","allow","allow","allow","allow","allow","allow","allow","allow","allow"],1,3],"passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"minute budget spans seconds\", \"actual\": [[\"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"deny-minute\", \"deny-minute\", \"deny-minute\"], 0, 5], \"expected\": [[\"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"deny-minute\", \"deny-minute\", \"deny-minute\"], 0, 5], \"passed\": true}, {\"check\": \"second limit inside minute\", \"actual\": [[\"allow\", \"deny-second\", \"deny-second\", \"allow\", \"deny-second\"], 1, 2], \"expected\": [[\"allow\", \"deny-second\", \"deny-second\", \"allow\", \"deny-second\"], 1, 2], \"passed\": true}, {\"check\": \"minute rollover\", \"actual\": [[\"allow\", \"allow\", \"allow\", \"deny-second\", \"allow\", \"allow\"], 2, 2], \"expected\": [[\"allow\", \"allow\", \"allow\", \"deny-second\", \"allow\", \"allow\"], 2, 2], \"passed\": true}, {\"check\": \"both exhausted reports second\", \"actual\": [[\"allow\", \"deny-second\", \"deny-minute\", \"deny-minute\"], 0, 1], \"expected\": [[\"allow\", \"deny-second\", \"deny-minute\", \"deny-minute\"], 0, 1], \"passed\": true}, {\"check\": \"minute denials keep second budget\", \"actual\": [[\"allow\", \"allow\", \"deny-minute\", \"deny-minute\", \"deny-minute\", \"allow\", \"allow\", \"deny-second\"], 2, 2], \"expected\": [[\"allow\", \"allow\", \"deny-minute\", \"deny-minute\", \"deny-minute\", \"allow\", \"allow\", \"deny-second\"], 2, 2], \"passed\": true}, {\"check\": \"random traffic\", \"actual\": [[\"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\"], 1, 3], \"expected\": [[\"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\", \"allow\"], 1, 3], \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}