FA-68686 / Toll and parking fee computation / Open access
Merchant parking validations: only the largest flat validation applies · case 01
Merchant parking validations returns a wrong result when only the largest flat validation applies.
ROOT CAUSE
Flat validations are treated like percentages and not summed.
THE FAILURE
Flat validations are treated like percentages and not summed.
Unsuccessful approach: Refusing flat validations when a percentage applies is a combinability rule the contract does not have.
Case contract
Input {minutes (single day), validations: [[free_min|pct|flat, value]], hourly, daily_max, max_free_min}. Free minutes from all validations are summed, capped at max_free_min and deducted from the stay before rating. The fee is started hours * hourly capped at daily_max. Only the largest percentage validation applies (discount floored to cents), then all flat validations are subtracted, never below zero.
Why this case matters
Fee engines bill customers in integer cents; a wrong boundary, rounding stage or cap scope silently over- or under-charges.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
free = min(x['max_free_min'], sum(v for k, v in x['validations'] if k == 'free_min'))
bill = max(0, x['minutes'] - free)
fee = min(x['daily_max'], -(-bill // 60) * x['hourly'])
pcts = [v for k, v in x['validations'] if k == 'pct']
if pcts:
fee -= fee * max(pcts) // 100
flat = max([0] + [v for k, v in x['validations'] if k == 'flat'])
return max(0, fee - flat)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'minutes': 552, 'validations': [['flat', 250], ['flat', 500], ['free_min', 15], ['free_min', 15]], 'hourly': 350, 'daily_max': 3000, 'max_free_min': 120}, 2250), ({'minutes': 839, 'validations': [['flat', 250], ['free_min', 60], ['flat', 500]], 'hourly': 200, 'daily_max': 1800, 'max_free_min': 120}, 1050), ({'minutes': 95, 'validations': [['free_min', 30]], 'hourly': 350, 'daily_max': 2400, 'max_free_min': 120}, 700), ({'minutes': 977, 'validations': [['flat', 100]], 'hourly': 300, 'daily_max': 2400, 'max_free_min': 180}, 2300), ({'minutes': 150, 'validations': [['free_min', 60], ['free_min', 60], ['free_min', 60]], 'hourly': 300, 'daily_max': 2400, 'max_free_min': 120}, 300), ({'minutes': 1179, 'validations': [['pct', 10], ['flat', 100]], 'hourly': 200, 'daily_max': 3000, 'max_free_min': 180}, 2600), ({'minutes': 226, 'validations': [], 'hourly': 200, 'daily_max': 1800, 'max_free_min': 180}, 800), ({'minutes': 200, 'validations': [['pct', 25], ['pct', 10], ['flat', 100], ['flat', 250]], 'hourly': 300, 'daily_max': 2400, 'max_free_min': 120}, 550)], [({'minutes': 200, 'validations': [['pct', 25], ['pct', 10], ['flat', 100], ['flat', 250]], 'hourly': 300, 'daily_max': 2400, 'max_free_min': 120}, 550), ({'minutes': 753, 'validations': [['flat', 500], ['free_min', 90], ['free_min', 30], ['flat', 250]], 'hourly': 300, 'daily_max': 1800, 'max_free_min': 60}, 1050), ({'minutes': 780, 'validations': [], 'hourly': 350, 'daily_max': 2400, 'max_free_min': 180}, 2400), ({'minutes': 150, 'validations': [['free_min', 60], ['free_min', 60], ['free_min', 60]], 'hourly': 300, 'daily_max': 2400, 'max_free_min': 120}, 300), ({'minutes': 945, 'validations': [['free_min', 60], ['pct', 50], ['free_min', 30]], 'hourly': 200, 'daily_max': 2400, 'max_free_min': 60}, 1200), ({'minutes': 590, 'validations': [['pct', 10], ['flat', 250], ['flat', 500], ['pct', 50]], 'hourly': 200, 'daily_max': 3000, 'max_free_min': 120}, 250), ({'minutes': 738, 'validations': [['free_min', 30], ['free_min', 120], ['flat', 100], ['free_min', 120]], 'hourly': 350, 'daily_max': 2400, 'max_free_min': 120}, 2300), ({'minutes': 95, 'validations': [['free_min', 30]], 'hourly': 350, 'daily_max': 2400, 'max_free_min': 120}, 700)], [({'minutes': 761, 'validations': [['free_min', 90], ['flat', 100], ['free_min', 30], ['flat', 500]], 'hourly': 300, 'daily_max': 2400, 'max_free_min': 120}, 1800), ({'minutes': 745, 'validations': [['flat', 100], ['free_min', 90], ['flat', 250], ['pct', 25]], 'hourly': 350, 'daily_max': 2400, 'max_free_min': 60}, 1450), ({'minutes': 200, 'validations': [['pct', 25], ['pct', 10], ['flat', 100], ['flat', 250]], 'hourly': 300, 'daily_max': 2400, 'max_free_min': 120}, 550), ({'minutes': 1258, 'validations': [], 'hourly': 350, 'daily_max': 3000, 'max_free_min': 60}, 3000), ({'minutes': 1149, 'validations': [], 'hourly': 300, 'daily_max': 2400, 'max_free_min': 60}, 2400), ({'minutes': 1112, 'validations': [['flat', 100], ['pct', 10]], 'hourly': 350, 'daily_max': 3000, 'max_free_min': 60}, 2600), ({'minutes': 150, 'validations': [['free_min', 60], ['free_min', 60], ['free_min', 60]], 'hourly': 300, 'daily_max': 2400, 'max_free_min': 120}, 300), ({'minutes': 95, 'validations': [['free_min', 30]], 'hourly': 350, 'daily_max': 2400, 'max_free_min': 120}, 700)], [({'minutes': 150, 'validations': [['free_min', 60], ['free_min', 60], ['free_min', 60]], 'hourly': 300, 'daily_max': 2400, 'max_free_min': 120}, 300), ({'minutes': 1372, 'validations': [['pct', 10], ['flat', 250], ['flat', 500], ['free_min', 60]], 'hourly': 350, 'daily_max': 3000, 'max_free_min': 60}, 1950), ({'minutes': 95, 'validations': [['free_min', 30]], 'hourly': 350, 'daily_max': 2400, 'max_free_min': 120}, 700), ({'minutes': 814, 'validations': [['free_min', 90], ['pct', 50]], 'hourly': 300, 'daily_max': 1800, 'max_free_min': 120}, 900), ({'minutes': 200, 'validations': [['pct', 25], ['pct', 10], ['flat', 100], ['flat', 250]], 'hourly': 300, 'daily_max': 2400, 'max_free_min': 120}, 550), ({'minutes': 1395, 'validations': [['flat', 250], ['free_min', 90], ['free_min', 90], ['flat', 500]], 'hourly': 300, 'daily_max': 2400, 'max_free_min': 120}, 1650), ({'minutes': 158, 'validations': [['flat', 250], ['free_min', 90], ['free_min', 30], ['pct', 10]], 'hourly': 200, 'daily_max': 3000, 'max_free_min': 120}, 0), ({'minutes': 592, 'validations': [['free_min', 15], ['flat', 250]], 'hourly': 350, 'daily_max': 3000, 'max_free_min': 180}, 2750)], [({'minutes': 542, 'validations': [['free_min', 30], ['pct', 25], ['flat', 100], ['pct', 10]], 'hourly': 350, 'daily_max': 2400, 'max_free_min': 120}, 1700), ({'minutes': 1169, 'validations': [['flat', 250], ['flat', 100]], 'hourly': 300, 'daily_max': 3000, 'max_free_min': 180}, 2650), ({'minutes': 150, 'validations': [['free_min', 60], ['free_min', 60], ['free_min', 60]], 'hourly': 300, 'daily_max': 2400, 'max_free_min': 120}, 300), ({'minutes': 1262, 'validations': [['flat', 100], ['free_min', 90], ['flat', 250]], 'hourly': 200, 'daily_max': 2400, 'max_free_min': 180}, 2050), ({'minutes': 200, 'validations': [['pct', 25], ['pct', 10], ['flat', 100], ['flat', 250]], 'hourly': 300, 'daily_max': 2400, 'max_free_min': 120}, 550), ({'minutes': 593, 'validations': [['flat', 100]], 'hourly': 350, 'daily_max': 2400, 'max_free_min': 180}, 2300), ({'minutes': 95, 'validations': [['free_min', 30]], 'hourly': 350, 'daily_max': 2400, 'max_free_min': 120}, 700), ({'minutes': 1364, 'validations': [['free_min', 60], ['pct', 10]], 'hourly': 200, 'daily_max': 3000, 'max_free_min': 120}, 2700)]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check('fee oracle' + ' %d' % i, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| fee oracle 0 | 2500 | 2250 | Failed |
| fee oracle 1 | 1300 | 1050 | Failed |
| fee oracle 2 | 700 | 700 | Passed |
| fee oracle 3 | 2300 | 2300 | Passed |
| fee oracle 4 | 300 | 300 | Passed |
| fee oracle 5 | 2600 | 2600 | Passed |
| fee oracle 6 | 800 | 800 | Passed |
| fee oracle 7 | 650 | 550 | Failed |
SHA-256 / 9b2b3b9e29fd4315bb99e856a5e3c4cde7ad1a1a5bbfb2493bf06216f4ff80bc
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
free = min(x['max_free_min'], sum(v for k, v in x['validations'] if k == 'free_min'))
bill = max(0, x['minutes'] - free)
fee = min(x['daily_max'], -(-bill // 60) * x['hourly'])
pcts = [v for k, v in x['validations'] if k == 'pct']
if pcts:
fee -= fee * max(pcts) // 100
flat = sum(v for k, v in x['validations'] if k == 'flat') if not pcts else 0
return max(0, fee - flat)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'minutes': 552, 'validations': [['flat', 250], ['flat', 500], ['free_min', 15], ['free_min', 15]], 'hourly': 350, 'daily_max': 3000, 'max_free_min': 120}, 2250), ({'minutes': 839, 'validations': [['flat', 250], ['free_min', 60], ['flat', 500]], 'hourly': 200, 'daily_max': 1800, 'max_free_min': 120}, 1050), ({'minutes': 95, 'validations': [['free_min', 30]], 'hourly': 350, 'daily_max': 2400, 'max_free_min': 120}, 700), ({'minutes': 977, 'validations': [['flat', 100]], 'hourly': 300, 'daily_max': 2400, 'max_free_min': 180}, 2300), ({'minutes': 150, 'validations': [['free_min', 60], ['free_min', 60], ['free_min', 60]], 'hourly': 300, 'daily_max': 2400, 'max_free_min': 120}, 300), ({'minutes': 1179, 'validations': [['pct', 10], ['flat', 100]], 'hourly': 200, 'daily_max': 3000, 'max_free_min': 180}, 2600), ({'minutes': 226, 'validations': [], 'hourly': 200, 'daily_max': 1800, 'max_free_min': 180}, 800), ({'minutes': 200, 'validations': [['pct', 25], ['pct', 10], ['flat', 100], ['flat', 250]], 'hourly': 300, 'daily_max': 2400, 'max_free_min': 120}, 550)], [({'minutes': 200, 'validations': [['pct', 25], ['pct', 10], ['flat', 100], ['flat', 250]], 'hourly': 300, 'daily_max': 2400, 'max_free_min': 120}, 550), ({'minutes': 753, 'validations': [['flat', 500], ['free_min', 90], ['free_min', 30], ['flat', 250]], 'hourly': 300, 'daily_max': 1800, 'max_free_min': 60}, 1050), ({'minutes': 780, 'validations': [], 'hourly': 350, 'daily_max': 2400, 'max_free_min': 180}, 2400), ({'minutes': 150, 'validations': [['free_min', 60], ['free_min', 60], ['free_min', 60]], 'hourly': 300, 'daily_max': 2400, 'max_free_min': 120}, 300), ({'minutes': 945, 'validations': [['free_min', 60], ['pct', 50], ['free_min', 30]], 'hourly': 200, 'daily_max': 2400, 'max_free_min': 60}, 1200), ({'minutes': 590, 'validations': [['pct', 10], ['flat', 250], ['flat', 500], ['pct', 50]], 'hourly': 200, 'daily_max': 3000, 'max_free_min': 120}, 250), ({'minutes': 738, 'validations': [['free_min', 30], ['free_min', 120], ['flat', 100], ['free_min', 120]], 'hourly': 350, 'daily_max': 2400, 'max_free_min': 120}, 2300), ({'minutes': 95, 'validations': [['free_min', 30]], 'hourly': 350, 'daily_max': 2400, 'max_free_min': 120}, 700)], [({'minutes': 761, 'validations': [['free_min', 90], ['flat', 100], ['free_min', 30], ['flat', 500]], 'hourly': 300, 'daily_max': 2400, 'max_free_min': 120}, 1800), ({'minutes': 745, 'validations': [['flat', 100], ['free_min', 90], ['flat', 250], ['pct', 25]], 'hourly': 350, 'daily_max': 2400, 'max_free_min': 60}, 1450), ({'minutes': 200, 'validations': [['pct', 25], ['pct', 10], ['flat', 100], ['flat', 250]], 'hourly': 300, 'daily_max': 2400, 'max_free_min': 120}, 550), ({'minutes': 1258, 'validations': [], 'hourly': 350, 'daily_max': 3000, 'max_free_min': 60}, 3000), ({'minutes': 1149, 'validations': [], 'hourly': 300, 'daily_max': 2400, 'max_free_min': 60}, 2400), ({'minutes': 1112, 'validations': [['flat', 100], ['pct', 10]], 'hourly': 350, 'daily_max': 3000, 'max_free_min': 60}, 2600), ({'minutes': 150, 'validations': [['free_min', 60], ['free_min', 60], ['free_min', 60]], 'hourly': 300, 'daily_max': 2400, 'max_free_min': 120}, 300), ({'minutes': 95, 'validations': [['free_min', 30]], 'hourly': 350, 'daily_max': 2400, 'max_free_min': 120}, 700)], [({'minutes': 150, 'validations': [['free_min', 60], ['free_min', 60], ['free_min', 60]], 'hourly': 300, 'daily_max': 2400, 'max_free_min': 120}, 300), ({'minutes': 1372, 'validations': [['pct', 10], ['flat', 250], ['flat', 500], ['free_min', 60]], 'hourly': 350, 'daily_max': 3000, 'max_free_min': 60}, 1950), ({'minutes': 95, 'validations': [['free_min', 30]], 'hourly': 350, 'daily_max': 2400, 'max_free_min': 120}, 700), ({'minutes': 814, 'validations': [['free_min', 90], ['pct', 50]], 'hourly': 300, 'daily_max': 1800, 'max_free_min': 120}, 900), ({'minutes': 200, 'validations': [['pct', 25], ['pct', 10], ['flat', 100], ['flat', 250]], 'hourly': 300, 'daily_max': 2400, 'max_free_min': 120}, 550), ({'minutes': 1395, 'validations': [['flat', 250], ['free_min', 90], ['free_min', 90], ['flat', 500]], 'hourly': 300, 'daily_max': 2400, 'max_free_min': 120}, 1650), ({'minutes': 158, 'validations': [['flat', 250], ['free_min', 90], ['free_min', 30], ['pct', 10]], 'hourly': 200, 'daily_max': 3000, 'max_free_min': 120}, 0), ({'minutes': 592, 'validations': [['free_min', 15], ['flat', 250]], 'hourly': 350, 'daily_max': 3000, 'max_free_min': 180}, 2750)], [({'minutes': 542, 'validations': [['free_min', 30], ['pct', 25], ['flat', 100], ['pct', 10]], 'hourly': 350, 'daily_max': 2400, 'max_free_min': 120}, 1700), ({'minutes': 1169, 'validations': [['flat', 250], ['flat', 100]], 'hourly': 300, 'daily_max': 3000, 'max_free_min': 180}, 2650), ({'minutes': 150, 'validations': [['free_min', 60], ['free_min', 60], ['free_min', 60]], 'hourly': 300, 'daily_max': 2400, 'max_free_min': 120}, 300), ({'minutes': 1262, 'validations': [['flat', 100], ['free_min', 90], ['flat', 250]], 'hourly': 200, 'daily_max': 2400, 'max_free_min': 180}, 2050), ({'minutes': 200, 'validations': [['pct', 25], ['pct', 10], ['flat', 100], ['flat', 250]], 'hourly': 300, 'daily_max': 2400, 'max_free_min': 120}, 550), ({'minutes': 593, 'validations': [['flat', 100]], 'hourly': 350, 'daily_max': 2400, 'max_free_min': 180}, 2300), ({'minutes': 95, 'validations': [['free_min', 30]], 'hourly': 350, 'daily_max': 2400, 'max_free_min': 120}, 700), ({'minutes': 1364, 'validations': [['free_min', 60], ['pct', 10]], 'hourly': 200, 'daily_max': 3000, 'max_free_min': 120}, 2700)]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check('fee oracle' + ' %d' % i, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| fee oracle 0 | 2250 | 2250 | Passed |
| fee oracle 1 | 1050 | 1050 | Passed |
| fee oracle 2 | 700 | 700 | Passed |
| fee oracle 3 | 2300 | 2300 | Passed |
| fee oracle 4 | 300 | 300 | Passed |
| fee oracle 5 | 2700 | 2600 | Failed |
| fee oracle 6 | 800 | 800 | Passed |
| fee oracle 7 | 900 | 550 | Failed |
SHA-256 / 28560fad134de5fd0ee6f0916a80245c2ff72c299b6a0ac42de385f6df4efe14
HELD IN THE MEMBER ARCHIVE
The verified repair and its recorded checks are member-only.
This mechanism has 8 recorded checks per implementation. The open-access tier publishes the failure and the unsuccessful fix; the repaired source that passes every check, and the observations that prove it, are available to members.
Every case sharing this mechanism uses the same contract and the same repair, so this one record is held back for all of them.
Member access is invitation-based. Sign in with your invited account to inspect the repair.
Sign in to the archive ↗Verification & scope
A deterministic, bounded toy model with a stipulated contract; it makes no claim of conformance to any agency manual or standard. 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.
Observations recorded using Python 3.12.14 at 2026-09-29T14:48:04.523411+00:00.
Case digest / e070d8b07581aed0c47af98de6d2138204c6c91342bf43df3db2cc46bae1cc30