FAILURE MAP
← Case archive

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.

Verified by executionVariant 1 · 8 checks per implementationDownload source bundle ↓JSON ↗

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 fixtureActualExpectedOutcome
fee oracle 025002250Failed
fee oracle 113001050Failed
fee oracle 2700700Passed
fee oracle 323002300Passed
fee oracle 4300300Passed
fee oracle 526002600Passed
fee oracle 6800800Passed
fee oracle 7650550Failed

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 fixtureActualExpectedOutcome
fee oracle 022502250Passed
fee oracle 110501050Passed
fee oracle 2700700Passed
fee oracle 323002300Passed
fee oracle 4300300Passed
fee oracle 527002600Failed
fee oracle 6800800Passed
fee oracle 7900550Failed

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