{"abstract":"A QA engineer added to an individual target list still receives the variation of a broad rule.","category":"Feature flag rollout bucketing","checks":8,"contract":"An off flag serves its off variation (reason OFF). Otherwise individual targets (checked by sorted variation name) win with reason TARGET, then rules in order, then the fallthrough. A rule matches only when the user has its attribute: op in = membership, startsWith = case-sensitive string prefix, lt = numeric less-than any value; negate inverts a present attribute result. Return [variation, reason, zero-based rule index or -1].","evaluation_group":"w2-feature-flag-rollout-bucketing-targeting-precedence","failed_approach":"Skipping targets that point at the fallthrough variation lets a rule override those targeted users.","family":"w2-feature-flag-rollout-bucketing-targeting-precedence-target-precedence","id":"FA-73891","implementations":{"attempt":{"sha256":"7d9e8b470748ffe881f5f5418f955d1cf72e72758154c3624becf7db48903643","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(flag, user):\n    if not flag.get('on'):\n        return [flag.get('off'), 'OFF', -1]\n    key = user.get('key')\n    for variation in sorted(flag.get('targets', {})):\n        if key in flag['targets'][variation] and variation != flag.get('fallthrough'):\n            return [variation, 'TARGET', -1]\n    for index, rule in enumerate(flag.get('rules', [])):\n        if rule['attr'] not in user:\n            continue\n        value = user[rule['attr']]\n        if rule['op'] == 'in':\n            hit = value in rule['values']\n        elif rule['op'] == 'startsWith':\n            hit = isinstance(value, str) and any(value.startswith(v) for v in rule['values'])\n        else:\n            hit = isinstance(value, (int, float)) and not isinstance(value, bool) and any(value < v for v in rule['values'])\n        if rule.get('negate'):\n            hit = not hit\n        if hit:\n            return [rule['variation'], 'RULE', index]\n    return [flag.get('fallthrough'), 'FALLTHROUGH', -1]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('individual target beats a matching rule',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {'v1': ['k1']},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['US'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k1', 'country': 'US'}],\n   ['v1', 'TARGET', -1]),\n  ('negated rule does not match a missing attribute',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v3',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': True, 'variation': 'v2'}]},\n    {'key': 'k2'}],\n   ['v3', 'FALLTHROUGH', -1]),\n  ('off flag serves off variation',\n   [{'on': False, 'off': 'v1', 'fallthrough': 'v2', 'targets': {}, 'rules': []}, {'key': 'k1'}],\n   ['v1', 'OFF', -1]),\n  ('second rule reports index one',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['FR'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k3', 'country': 'DE'}],\n   ['v2', 'RULE', 1]),\n  ('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('target to fallthrough variation still reports TARGET',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v2',\n     'targets': {'v2': ['k1']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [30], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 20}],\n   ['v2', 'TARGET', -1]),\n  ('targeting sample 1',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {'v1': []},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['a', 'Ann'],\n                'negate': False,\n                'variation': 'v2'},\n               {'attr': 'age', 'op': 'lt', 'values': [21, 18], 'negate': False, 'variation': 'v0'},\n               {'attr': 'age', 'op': 'lt', 'values': [18, 30], 'negate': True, 'variation': 'v2'},\n               {'attr': 'email',\n                'op': 'startsWith',\n                'values': ['a', 'Ann'],\n                'negate': False,\n                'variation': 'v2'}]},\n    {'key': 'k2', 'country': 'DE', 'age': 20, 'plan': 'team'}],\n   ['v0', 'RULE', 1]),\n  ('targeting sample 2',\n   [{'on': True, 'off': 'v1', 'fallthrough': 'v0', 'targets': {'v2': []}, 'rules': []},\n    {'key': 'k6', 'age': 40, 'plan': 'pro'}],\n   ['v0', 'FALLTHROUGH', -1])],\n [('negated rule does not match a missing attribute',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v3',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': True, 'variation': 'v2'}]},\n    {'key': 'k2'}],\n   ['v3', 'FALLTHROUGH', -1]),\n  ('off flag serves off variation',\n   [{'on': False, 'off': 'v1', 'fallthrough': 'v2', 'targets': {}, 'rules': []}, {'key': 'k1'}],\n   ['v1', 'OFF', -1]),\n  ('second rule reports index one',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['FR'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k3', 'country': 'DE'}],\n   ['v2', 'RULE', 1]),\n  ('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('rule index skips rules on absent attributes',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'age', 'op': 'lt', 'values': [21], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k5', 'age': 19}],\n   ['v2', 'RULE', 1]),\n  ('target to fallthrough variation still reports TARGET',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v2',\n     'targets': {'v2': ['k1']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [30], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 20}],\n   ['v2', 'TARGET', -1]),\n  ('targeting sample 6',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v3',\n     'targets': {},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [18, 65], 'negate': False, 'variation': 'v1'},\n               {'attr': 'plan', 'op': 'in', 'values': ['DE', 'free'], 'negate': True, 'variation': 'v2'}]},\n    {'key': 'k5', 'country': 'DE', 'plan': 'team'}],\n   ['v2', 'RULE', 1]),\n  ('targeting sample 7',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['FR', 'free'], 'negate': True, 'variation': 'v1'},\n               {'attr': 'plan', 'op': 'in', 'values': ['FR', 'US'], 'negate': False, 'variation': 'v0'}]},\n    {'key': 'k6', 'country': 'JP', 'email': 'annie', 'age': 17, 'plan': 'free'}],\n   ['v0', 'FALLTHROUGH', -1])],\n [('individual target beats a matching rule',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {'v1': ['k1']},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['US'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k1', 'country': 'US'}],\n   ['v1', 'TARGET', -1]),\n  ('off flag serves off variation',\n   [{'on': False, 'off': 'v1', 'fallthrough': 'v2', 'targets': {}, 'rules': []}, {'key': 'k1'}],\n   ['v1', 'OFF', -1]),\n  ('second rule reports index one',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['FR'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k3', 'country': 'DE'}],\n   ['v2', 'RULE', 1]),\n  ('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('rule index skips rules on absent attributes',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'age', 'op': 'lt', 'values': [21], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k5', 'age': 19}],\n   ['v2', 'RULE', 1]),\n  ('target to fallthrough variation still reports TARGET',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v2',\n     'targets': {'v2': ['k1']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [30], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 20}],\n   ['v2', 'TARGET', -1]),\n  ('targeting sample 11',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v3',\n     'targets': {'v3': ['k2'], 'v2': ['k4', 'k2']},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['qa-', 'a'],\n                'negate': False,\n                'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE', 'FR'], 'negate': True, 'variation': 'v3'},\n               {'attr': 'email',\n                'op': 'startsWith',\n                'values': ['qa-', 'a'],\n                'negate': False,\n                'variation': 'v1'}]},\n    {'key': 'k6', 'email': 'annie', 'age': 40, 'plan': 'free'}],\n   ['v1', 'RULE', 0]),\n  ('targeting sample 12',\n   [{'on': True, 'off': 'v1', 'fallthrough': 'v0', 'targets': {'v1': ['k1', 'k4'], 'v2': []}, 'rules': []},\n    {'key': 'k1', 'age': 30, 'plan': 'free'}],\n   ['v1', 'TARGET', -1])],\n [('second rule reports index one',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['FR'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k3', 'country': 'DE'}],\n   ['v2', 'RULE', 1]),\n  ('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('rule index skips rules on absent attributes',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'age', 'op': 'lt', 'values': [21], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k5', 'age': 19}],\n   ['v2', 'RULE', 1]),\n  ('target to fallthrough variation still reports TARGET',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v2',\n     'targets': {'v2': ['k1']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [30], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 20}],\n   ['v2', 'TARGET', -1]),\n  ('no rule matches uses fallthrough',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v3',\n     'targets': {'v1': ['k9']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [18], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 40}],\n   ['v3', 'FALLTHROUGH', -1]),\n  ('targeting sample 16',\n   [{'on': True, 'off': 'v0', 'fallthrough': 'v2', 'targets': {}, 'rules': []},\n    {'key': 'k5', 'age': 40, 'plan': 'free'}],\n   ['v2', 'FALLTHROUGH', -1]),\n  ('targeting sample 17',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v3',\n     'targets': {},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['ann', 'a'],\n                'negate': True,\n                'variation': 'v0'},\n               {'attr': 'plan', 'op': 'lt', 'values': [30, 18], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k6', 'country': 'JP', 'email': 'ann@x.io', 'plan': 'team'}],\n   ['v3', 'FALLTHROUGH', -1]),\n  ('targeting sample 18',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v3',\n     'targets': {'v2': []},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [21, 18], 'negate': False, 'variation': 'v0'},\n               {'attr': 'plan', 'op': 'in', 'values': ['FR', 'DE'], 'negate': False, 'variation': 'v3'},\n               {'attr': 'age', 'op': 'lt', 'values': [21, 18], 'negate': False, 'variation': 'v0'}]},\n    {'key': 'k1', 'country': 'JP', 'age': 20, 'plan': 'free'}],\n   ['v0', 'RULE', 0])],\n [('individual target beats a matching rule',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {'v1': ['k1']},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['US'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k1', 'country': 'US'}],\n   ['v1', 'TARGET', -1]),\n  ('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('rule index skips rules on absent attributes',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'age', 'op': 'lt', 'values': [21], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k5', 'age': 19}],\n   ['v2', 'RULE', 1]),\n  ('target to fallthrough variation still reports TARGET',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v2',\n     'targets': {'v2': ['k1']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [30], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 20}],\n   ['v2', 'TARGET', -1]),\n  ('no rule matches uses fallthrough',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v3',\n     'targets': {'v1': ['k9']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [18], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 40}],\n   ['v3', 'FALLTHROUGH', -1]),\n  ('prefix operand order matters',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['annie@corp'],\n                'negate': False,\n                'variation': 'v1'}]},\n    {'key': 'k2', 'email': 'annie'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('targeting sample 21',\n   [{'on': True, 'off': 'v1', 'fallthrough': 'v2', 'targets': {}, 'rules': []},\n    {'key': 'k3', 'email': 'qa-1@z.io', 'plan': 'free'}],\n   ['v2', 'FALLTHROUGH', -1]),\n  ('targeting sample 22',\n   [{'on': False, 'off': 'v0', 'fallthrough': 'v2', 'targets': {'v1': [], 'v3': ['k3']}, 'rules': []},\n    {'key': 'k6', 'country': 'DE', 'email': 'Ann@x.io', 'plan': 'team'}],\n   ['v0', 'OFF', -1])]]\nfor label, args, expected in fixtures[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":"d8067e4962f59a57abc4c22b33298dd3ada342cb62d6a371c57b9cfc86513911","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(flag, user):\n    if not flag.get('on'):\n        return [flag.get('off'), 'OFF', -1]\n    key = user.get('key')\n    for index, rule in enumerate(flag.get('rules', [])):\n        if rule['attr'] not in user:\n            continue\n        value = user[rule['attr']]\n        if rule['op'] == 'in':\n            hit = value in rule['values']\n        elif rule['op'] == 'startsWith':\n            hit = isinstance(value, str) and any(value.startswith(v) for v in rule['values'])\n        else:\n            hit = isinstance(value, (int, float)) and not isinstance(value, bool) and any(value < v for v in rule['values'])\n        if rule.get('negate'):\n            hit = not hit\n        if hit:\n            return [rule['variation'], 'RULE', index]\n    for variation in sorted(flag.get('targets', {})):\n        if key in flag['targets'][variation]:\n            return [variation, 'TARGET', -1]\n    return [flag.get('fallthrough'), 'FALLTHROUGH', -1]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('individual target beats a matching rule',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {'v1': ['k1']},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['US'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k1', 'country': 'US'}],\n   ['v1', 'TARGET', -1]),\n  ('negated rule does not match a missing attribute',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v3',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': True, 'variation': 'v2'}]},\n    {'key': 'k2'}],\n   ['v3', 'FALLTHROUGH', -1]),\n  ('off flag serves off variation',\n   [{'on': False, 'off': 'v1', 'fallthrough': 'v2', 'targets': {}, 'rules': []}, {'key': 'k1'}],\n   ['v1', 'OFF', -1]),\n  ('second rule reports index one',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['FR'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k3', 'country': 'DE'}],\n   ['v2', 'RULE', 1]),\n  ('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('target to fallthrough variation still reports TARGET',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v2',\n     'targets': {'v2': ['k1']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [30], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 20}],\n   ['v2', 'TARGET', -1]),\n  ('targeting sample 1',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {'v1': []},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['a', 'Ann'],\n                'negate': False,\n                'variation': 'v2'},\n               {'attr': 'age', 'op': 'lt', 'values': [21, 18], 'negate': False, 'variation': 'v0'},\n               {'attr': 'age', 'op': 'lt', 'values': [18, 30], 'negate': True, 'variation': 'v2'},\n               {'attr': 'email',\n                'op': 'startsWith',\n                'values': ['a', 'Ann'],\n                'negate': False,\n                'variation': 'v2'}]},\n    {'key': 'k2', 'country': 'DE', 'age': 20, 'plan': 'team'}],\n   ['v0', 'RULE', 1]),\n  ('targeting sample 2',\n   [{'on': True, 'off': 'v1', 'fallthrough': 'v0', 'targets': {'v2': []}, 'rules': []},\n    {'key': 'k6', 'age': 40, 'plan': 'pro'}],\n   ['v0', 'FALLTHROUGH', -1])],\n [('negated rule does not match a missing attribute',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v3',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': True, 'variation': 'v2'}]},\n    {'key': 'k2'}],\n   ['v3', 'FALLTHROUGH', -1]),\n  ('off flag serves off variation',\n   [{'on': False, 'off': 'v1', 'fallthrough': 'v2', 'targets': {}, 'rules': []}, {'key': 'k1'}],\n   ['v1', 'OFF', -1]),\n  ('second rule reports index one',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['FR'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k3', 'country': 'DE'}],\n   ['v2', 'RULE', 1]),\n  ('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('rule index skips rules on absent attributes',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'age', 'op': 'lt', 'values': [21], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k5', 'age': 19}],\n   ['v2', 'RULE', 1]),\n  ('target to fallthrough variation still reports TARGET',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v2',\n     'targets': {'v2': ['k1']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [30], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 20}],\n   ['v2', 'TARGET', -1]),\n  ('targeting sample 6',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v3',\n     'targets': {},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [18, 65], 'negate': False, 'variation': 'v1'},\n               {'attr': 'plan', 'op': 'in', 'values': ['DE', 'free'], 'negate': True, 'variation': 'v2'}]},\n    {'key': 'k5', 'country': 'DE', 'plan': 'team'}],\n   ['v2', 'RULE', 1]),\n  ('targeting sample 7',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['FR', 'free'], 'negate': True, 'variation': 'v1'},\n               {'attr': 'plan', 'op': 'in', 'values': ['FR', 'US'], 'negate': False, 'variation': 'v0'}]},\n    {'key': 'k6', 'country': 'JP', 'email': 'annie', 'age': 17, 'plan': 'free'}],\n   ['v0', 'FALLTHROUGH', -1])],\n [('individual target beats a matching rule',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {'v1': ['k1']},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['US'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k1', 'country': 'US'}],\n   ['v1', 'TARGET', -1]),\n  ('off flag serves off variation',\n   [{'on': False, 'off': 'v1', 'fallthrough': 'v2', 'targets': {}, 'rules': []}, {'key': 'k1'}],\n   ['v1', 'OFF', -1]),\n  ('second rule reports index one',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['FR'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k3', 'country': 'DE'}],\n   ['v2', 'RULE', 1]),\n  ('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('rule index skips rules on absent attributes',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'age', 'op': 'lt', 'values': [21], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k5', 'age': 19}],\n   ['v2', 'RULE', 1]),\n  ('target to fallthrough variation still reports TARGET',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v2',\n     'targets': {'v2': ['k1']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [30], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 20}],\n   ['v2', 'TARGET', -1]),\n  ('targeting sample 11',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v3',\n     'targets': {'v3': ['k2'], 'v2': ['k4', 'k2']},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['qa-', 'a'],\n                'negate': False,\n                'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE', 'FR'], 'negate': True, 'variation': 'v3'},\n               {'attr': 'email',\n                'op': 'startsWith',\n                'values': ['qa-', 'a'],\n                'negate': False,\n                'variation': 'v1'}]},\n    {'key': 'k6', 'email': 'annie', 'age': 40, 'plan': 'free'}],\n   ['v1', 'RULE', 0]),\n  ('targeting sample 12',\n   [{'on': True, 'off': 'v1', 'fallthrough': 'v0', 'targets': {'v1': ['k1', 'k4'], 'v2': []}, 'rules': []},\n    {'key': 'k1', 'age': 30, 'plan': 'free'}],\n   ['v1', 'TARGET', -1])],\n [('second rule reports index one',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['FR'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k3', 'country': 'DE'}],\n   ['v2', 'RULE', 1]),\n  ('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('rule index skips rules on absent attributes',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'age', 'op': 'lt', 'values': [21], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k5', 'age': 19}],\n   ['v2', 'RULE', 1]),\n  ('target to fallthrough variation still reports TARGET',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v2',\n     'targets': {'v2': ['k1']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [30], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 20}],\n   ['v2', 'TARGET', -1]),\n  ('no rule matches uses fallthrough',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v3',\n     'targets': {'v1': ['k9']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [18], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 40}],\n   ['v3', 'FALLTHROUGH', -1]),\n  ('targeting sample 16',\n   [{'on': True, 'off': 'v0', 'fallthrough': 'v2', 'targets': {}, 'rules': []},\n    {'key': 'k5', 'age': 40, 'plan': 'free'}],\n   ['v2', 'FALLTHROUGH', -1]),\n  ('targeting sample 17',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v3',\n     'targets': {},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['ann', 'a'],\n                'negate': True,\n                'variation': 'v0'},\n               {'attr': 'plan', 'op': 'lt', 'values': [30, 18], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k6', 'country': 'JP', 'email': 'ann@x.io', 'plan': 'team'}],\n   ['v3', 'FALLTHROUGH', -1]),\n  ('targeting sample 18',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v3',\n     'targets': {'v2': []},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [21, 18], 'negate': False, 'variation': 'v0'},\n               {'attr': 'plan', 'op': 'in', 'values': ['FR', 'DE'], 'negate': False, 'variation': 'v3'},\n               {'attr': 'age', 'op': 'lt', 'values': [21, 18], 'negate': False, 'variation': 'v0'}]},\n    {'key': 'k1', 'country': 'JP', 'age': 20, 'plan': 'free'}],\n   ['v0', 'RULE', 0])],\n [('individual target beats a matching rule',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {'v1': ['k1']},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['US'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k1', 'country': 'US'}],\n   ['v1', 'TARGET', -1]),\n  ('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('rule index skips rules on absent attributes',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'age', 'op': 'lt', 'values': [21], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k5', 'age': 19}],\n   ['v2', 'RULE', 1]),\n  ('target to fallthrough variation still reports TARGET',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v2',\n     'targets': {'v2': ['k1']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [30], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 20}],\n   ['v2', 'TARGET', -1]),\n  ('no rule matches uses fallthrough',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v3',\n     'targets': {'v1': ['k9']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [18], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 40}],\n   ['v3', 'FALLTHROUGH', -1]),\n  ('prefix operand order matters',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['annie@corp'],\n                'negate': False,\n                'variation': 'v1'}]},\n    {'key': 'k2', 'email': 'annie'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('targeting sample 21',\n   [{'on': True, 'off': 'v1', 'fallthrough': 'v2', 'targets': {}, 'rules': []},\n    {'key': 'k3', 'email': 'qa-1@z.io', 'plan': 'free'}],\n   ['v2', 'FALLTHROUGH', -1]),\n  ('targeting sample 22',\n   [{'on': False, 'off': 'v0', 'fallthrough': 'v2', 'targets': {'v1': [], 'v3': ['k3']}, 'rules': []},\n    {'key': 'k6', 'country': 'DE', 'email': 'Ann@x.io', 'plan': 'team'}],\n   ['v0', 'OFF', -1])]]\nfor label, args, expected in fixtures[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":"fc120fe9e2d302985b002586fc6c4ff10df61eaf7a27ecfa955f474a67b503aa","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(flag, user):\n    if not flag.get('on'):\n        return [flag.get('off'), 'OFF', -1]\n    key = user.get('key')\n    for variation in sorted(flag.get('targets', {})):\n        if key in flag['targets'][variation]:\n            return [variation, 'TARGET', -1]\n    for index, rule in enumerate(flag.get('rules', [])):\n        if rule['attr'] not in user:\n            continue\n        value = user[rule['attr']]\n        if rule['op'] == 'in':\n            hit = value in rule['values']\n        elif rule['op'] == 'startsWith':\n            hit = isinstance(value, str) and any(value.startswith(v) for v in rule['values'])\n        else:\n            hit = isinstance(value, (int, float)) and not isinstance(value, bool) and any(value < v for v in rule['values'])\n        if rule.get('negate'):\n            hit = not hit\n        if hit:\n            return [rule['variation'], 'RULE', index]\n    return [flag.get('fallthrough'), 'FALLTHROUGH', -1]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('individual target beats a matching rule',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {'v1': ['k1']},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['US'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k1', 'country': 'US'}],\n   ['v1', 'TARGET', -1]),\n  ('negated rule does not match a missing attribute',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v3',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': True, 'variation': 'v2'}]},\n    {'key': 'k2'}],\n   ['v3', 'FALLTHROUGH', -1]),\n  ('off flag serves off variation',\n   [{'on': False, 'off': 'v1', 'fallthrough': 'v2', 'targets': {}, 'rules': []}, {'key': 'k1'}],\n   ['v1', 'OFF', -1]),\n  ('second rule reports index one',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['FR'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k3', 'country': 'DE'}],\n   ['v2', 'RULE', 1]),\n  ('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('target to fallthrough variation still reports TARGET',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v2',\n     'targets': {'v2': ['k1']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [30], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 20}],\n   ['v2', 'TARGET', -1]),\n  ('targeting sample 1',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {'v1': []},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['a', 'Ann'],\n                'negate': False,\n                'variation': 'v2'},\n               {'attr': 'age', 'op': 'lt', 'values': [21, 18], 'negate': False, 'variation': 'v0'},\n               {'attr': 'age', 'op': 'lt', 'values': [18, 30], 'negate': True, 'variation': 'v2'},\n               {'attr': 'email',\n                'op': 'startsWith',\n                'values': ['a', 'Ann'],\n                'negate': False,\n                'variation': 'v2'}]},\n    {'key': 'k2', 'country': 'DE', 'age': 20, 'plan': 'team'}],\n   ['v0', 'RULE', 1]),\n  ('targeting sample 2',\n   [{'on': True, 'off': 'v1', 'fallthrough': 'v0', 'targets': {'v2': []}, 'rules': []},\n    {'key': 'k6', 'age': 40, 'plan': 'pro'}],\n   ['v0', 'FALLTHROUGH', -1])],\n [('negated rule does not match a missing attribute',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v3',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': True, 'variation': 'v2'}]},\n    {'key': 'k2'}],\n   ['v3', 'FALLTHROUGH', -1]),\n  ('off flag serves off variation',\n   [{'on': False, 'off': 'v1', 'fallthrough': 'v2', 'targets': {}, 'rules': []}, {'key': 'k1'}],\n   ['v1', 'OFF', -1]),\n  ('second rule reports index one',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['FR'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k3', 'country': 'DE'}],\n   ['v2', 'RULE', 1]),\n  ('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('rule index skips rules on absent attributes',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'age', 'op': 'lt', 'values': [21], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k5', 'age': 19}],\n   ['v2', 'RULE', 1]),\n  ('target to fallthrough variation still reports TARGET',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v2',\n     'targets': {'v2': ['k1']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [30], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 20}],\n   ['v2', 'TARGET', -1]),\n  ('targeting sample 6',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v3',\n     'targets': {},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [18, 65], 'negate': False, 'variation': 'v1'},\n               {'attr': 'plan', 'op': 'in', 'values': ['DE', 'free'], 'negate': True, 'variation': 'v2'}]},\n    {'key': 'k5', 'country': 'DE', 'plan': 'team'}],\n   ['v2', 'RULE', 1]),\n  ('targeting sample 7',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['FR', 'free'], 'negate': True, 'variation': 'v1'},\n               {'attr': 'plan', 'op': 'in', 'values': ['FR', 'US'], 'negate': False, 'variation': 'v0'}]},\n    {'key': 'k6', 'country': 'JP', 'email': 'annie', 'age': 17, 'plan': 'free'}],\n   ['v0', 'FALLTHROUGH', -1])],\n [('individual target beats a matching rule',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {'v1': ['k1']},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['US'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k1', 'country': 'US'}],\n   ['v1', 'TARGET', -1]),\n  ('off flag serves off variation',\n   [{'on': False, 'off': 'v1', 'fallthrough': 'v2', 'targets': {}, 'rules': []}, {'key': 'k1'}],\n   ['v1', 'OFF', -1]),\n  ('second rule reports index one',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['FR'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k3', 'country': 'DE'}],\n   ['v2', 'RULE', 1]),\n  ('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('rule index skips rules on absent attributes',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'age', 'op': 'lt', 'values': [21], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k5', 'age': 19}],\n   ['v2', 'RULE', 1]),\n  ('target to fallthrough variation still reports TARGET',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v2',\n     'targets': {'v2': ['k1']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [30], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 20}],\n   ['v2', 'TARGET', -1]),\n  ('targeting sample 11',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v3',\n     'targets': {'v3': ['k2'], 'v2': ['k4', 'k2']},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['qa-', 'a'],\n                'negate': False,\n                'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE', 'FR'], 'negate': True, 'variation': 'v3'},\n               {'attr': 'email',\n                'op': 'startsWith',\n                'values': ['qa-', 'a'],\n                'negate': False,\n                'variation': 'v1'}]},\n    {'key': 'k6', 'email': 'annie', 'age': 40, 'plan': 'free'}],\n   ['v1', 'RULE', 0]),\n  ('targeting sample 12',\n   [{'on': True, 'off': 'v1', 'fallthrough': 'v0', 'targets': {'v1': ['k1', 'k4'], 'v2': []}, 'rules': []},\n    {'key': 'k1', 'age': 30, 'plan': 'free'}],\n   ['v1', 'TARGET', -1])],\n [('second rule reports index one',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['FR'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'country', 'op': 'in', 'values': ['DE'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k3', 'country': 'DE'}],\n   ['v2', 'RULE', 1]),\n  ('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('rule index skips rules on absent attributes',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'age', 'op': 'lt', 'values': [21], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k5', 'age': 19}],\n   ['v2', 'RULE', 1]),\n  ('target to fallthrough variation still reports TARGET',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v2',\n     'targets': {'v2': ['k1']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [30], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 20}],\n   ['v2', 'TARGET', -1]),\n  ('no rule matches uses fallthrough',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v3',\n     'targets': {'v1': ['k9']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [18], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 40}],\n   ['v3', 'FALLTHROUGH', -1]),\n  ('targeting sample 16',\n   [{'on': True, 'off': 'v0', 'fallthrough': 'v2', 'targets': {}, 'rules': []},\n    {'key': 'k5', 'age': 40, 'plan': 'free'}],\n   ['v2', 'FALLTHROUGH', -1]),\n  ('targeting sample 17',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v3',\n     'targets': {},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['ann', 'a'],\n                'negate': True,\n                'variation': 'v0'},\n               {'attr': 'plan', 'op': 'lt', 'values': [30, 18], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k6', 'country': 'JP', 'email': 'ann@x.io', 'plan': 'team'}],\n   ['v3', 'FALLTHROUGH', -1]),\n  ('targeting sample 18',\n   [{'on': True,\n     'off': 'v1',\n     'fallthrough': 'v3',\n     'targets': {'v2': []},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [21, 18], 'negate': False, 'variation': 'v0'},\n               {'attr': 'plan', 'op': 'in', 'values': ['FR', 'DE'], 'negate': False, 'variation': 'v3'},\n               {'attr': 'age', 'op': 'lt', 'values': [21, 18], 'negate': False, 'variation': 'v0'}]},\n    {'key': 'k1', 'country': 'JP', 'age': 20, 'plan': 'free'}],\n   ['v0', 'RULE', 0])],\n [('individual target beats a matching rule',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {'v1': ['k1']},\n     'rules': [{'attr': 'country', 'op': 'in', 'values': ['US'], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k1', 'country': 'US'}],\n   ['v1', 'TARGET', -1]),\n  ('prefix match is case sensitive',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email', 'op': 'startsWith', 'values': ['ann'], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k4', 'email': 'Ann@x.io'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('rule index skips rules on absent attributes',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'plan', 'op': 'in', 'values': ['pro'], 'negate': False, 'variation': 'v1'},\n               {'attr': 'age', 'op': 'lt', 'values': [21], 'negate': False, 'variation': 'v2'}]},\n    {'key': 'k5', 'age': 19}],\n   ['v2', 'RULE', 1]),\n  ('target to fallthrough variation still reports TARGET',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v2',\n     'targets': {'v2': ['k1']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [30], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 20}],\n   ['v2', 'TARGET', -1]),\n  ('no rule matches uses fallthrough',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v3',\n     'targets': {'v1': ['k9']},\n     'rules': [{'attr': 'age', 'op': 'lt', 'values': [18], 'negate': False, 'variation': 'v1'}]},\n    {'key': 'k1', 'age': 40}],\n   ['v3', 'FALLTHROUGH', -1]),\n  ('prefix operand order matters',\n   [{'on': True,\n     'off': 'v0',\n     'fallthrough': 'v0',\n     'targets': {},\n     'rules': [{'attr': 'email',\n                'op': 'startsWith',\n                'values': ['annie@corp'],\n                'negate': False,\n                'variation': 'v1'}]},\n    {'key': 'k2', 'email': 'annie'}],\n   ['v0', 'FALLTHROUGH', -1]),\n  ('targeting sample 21',\n   [{'on': True, 'off': 'v1', 'fallthrough': 'v2', 'targets': {}, 'rules': []},\n    {'key': 'k3', 'email': 'qa-1@z.io', 'plan': 'free'}],\n   ['v2', 'FALLTHROUGH', -1]),\n  ('targeting sample 22',\n   [{'on': False, 'off': 'v0', 'fallthrough': 'v2', 'targets': {'v1': [], 'v3': ['k3']}, 'rules': []},\n    {'key': 'k6', 'country': 'DE', 'email': 'Ann@x.io', 'plan': 'team'}],\n   ['v0', 'OFF', -1])]]\nfor label, args, expected in fixtures[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 toy flag-evaluation model with a stipulated contract; it does not reproduce any vendor SDK byte for byte. 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-feature-flag-rollout-bucketing-targeting-precedence-target-precedence","generated_at":"2026-09-29T14:48:51.721403+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"Evaluation order decides whether QA allowlists, segment rules and defaults behave predictably.","repair":"Check individual targets immediately after the on/off check and before any rule.","root_cause":"The individual-target loop runs after the rule loop, so the first matching rule returns first.","sha256":"53127227d625c4431a9a0d82d908d0a130aa6c04ad437df7ebf5947e45ea0009","title":"Flag targeting precedence: Rules are evaluated before individual targets · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":41.714,"exit_code":1,"observations":[{"actual":["v1","TARGET",-1],"check":"individual target beats a matching rule","expected":["v1","TARGET",-1],"passed":true},{"actual":["v3","FALLTHROUGH",-1],"check":"negated rule does not match a missing attribute","expected":["v3","FALLTHROUGH",-1],"passed":true},{"actual":["v1","OFF",-1],"check":"off flag serves off variation","expected":["v1","OFF",-1],"passed":true},{"actual":["v2","RULE",1],"check":"second rule reports index one","expected":["v2","RULE",1],"passed":true},{"actual":["v0","FALLTHROUGH",-1],"check":"prefix match is case sensitive","expected":["v0","FALLTHROUGH",-1],"passed":true},{"actual":["v1","RULE",0],"check":"target to fallthrough variation still reports TARGET","expected":["v2","TARGET",-1],"passed":false},{"actual":["v0","RULE",1],"check":"targeting sample 1","expected":["v0","RULE",1],"passed":true},{"actual":["v0","FALLTHROUGH",-1],"check":"targeting sample 2","expected":["v0","FALLTHROUGH",-1],"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"individual target beats a matching rule\", \"actual\": [\"v1\", \"TARGET\", -1], \"expected\": [\"v1\", \"TARGET\", -1], \"passed\": true}, {\"check\": \"negated rule does not match a missing attribute\", \"actual\": [\"v3\", \"FALLTHROUGH\", -1], \"expected\": [\"v3\", \"FALLTHROUGH\", -1], \"passed\": true}, {\"check\": \"off flag serves off variation\", \"actual\": [\"v1\", \"OFF\", -1], \"expected\": [\"v1\", \"OFF\", -1], \"passed\": true}, {\"check\": \"second rule reports index one\", \"actual\": [\"v2\", \"RULE\", 1], \"expected\": [\"v2\", \"RULE\", 1], \"passed\": true}, {\"check\": \"prefix match is case sensitive\", \"actual\": [\"v0\", \"FALLTHROUGH\", -1], \"expected\": [\"v0\", \"FALLTHROUGH\", -1], \"passed\": true}, {\"check\": \"target to fallthrough variation still reports TARGET\", \"actual\": [\"v1\", \"RULE\", 0], \"expected\": [\"v2\", \"TARGET\", -1], \"passed\": false}, {\"check\": \"targeting sample 1\", \"actual\": [\"v0\", \"RULE\", 1], \"expected\": [\"v0\", \"RULE\", 1], \"passed\": true}, {\"check\": \"targeting sample 2\", \"actual\": [\"v0\", \"FALLTHROUGH\", -1], \"expected\": [\"v0\", \"FALLTHROUGH\", -1], \"passed\": true}], \"passed\": false}\n"},"broken":{"elapsed_ms":41.431,"exit_code":1,"observations":[{"actual":["v2","RULE",0],"check":"individual target beats a matching rule","expected":["v1","TARGET",-1],"passed":false},{"actual":["v3","FALLTHROUGH",-1],"check":"negated rule does not match a missing attribute","expected":["v3","FALLTHROUGH",-1],"passed":true},{"actual":["v1","OFF",-1],"check":"off flag serves off variation","expected":["v1","OFF",-1],"passed":true},{"actual":["v2","RULE",1],"check":"second rule reports index one","expected":["v2","RULE",1],"passed":true},{"actual":["v0","FALLTHROUGH",-1],"check":"prefix match is case sensitive","expected":["v0","FALLTHROUGH",-1],"passed":true},{"actual":["v1","RULE",0],"check":"target to fallthrough variation still reports TARGET","expected":["v2","TARGET",-1],"passed":false},{"actual":["v0","RULE",1],"check":"targeting sample 1","expected":["v0","RULE",1],"passed":true},{"actual":["v0","FALLTHROUGH",-1],"check":"targeting sample 2","expected":["v0","FALLTHROUGH",-1],"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"individual target beats a matching rule\", \"actual\": [\"v2\", \"RULE\", 0], \"expected\": [\"v1\", \"TARGET\", -1], \"passed\": false}, {\"check\": \"negated rule does not match a missing attribute\", \"actual\": [\"v3\", \"FALLTHROUGH\", -1], \"expected\": [\"v3\", \"FALLTHROUGH\", -1], \"passed\": true}, {\"check\": \"off flag serves off variation\", \"actual\": [\"v1\", \"OFF\", -1], \"expected\": [\"v1\", \"OFF\", -1], \"passed\": true}, {\"check\": \"second rule reports index one\", \"actual\": [\"v2\", \"RULE\", 1], \"expected\": [\"v2\", \"RULE\", 1], \"passed\": true}, {\"check\": \"prefix match is case sensitive\", \"actual\": [\"v0\", \"FALLTHROUGH\", -1], \"expected\": [\"v0\", \"FALLTHROUGH\", -1], \"passed\": true}, {\"check\": \"target to fallthrough variation still reports TARGET\", \"actual\": [\"v1\", \"RULE\", 0], \"expected\": [\"v2\", \"TARGET\", -1], \"passed\": false}, {\"check\": \"targeting sample 1\", \"actual\": [\"v0\", \"RULE\", 1], \"expected\": [\"v0\", \"RULE\", 1], \"passed\": true}, {\"check\": \"targeting sample 2\", \"actual\": [\"v0\", \"FALLTHROUGH\", -1], \"expected\": [\"v0\", \"FALLTHROUGH\", -1], \"passed\": true}], \"passed\": false}\n"},"fixed":{"elapsed_ms":42.508,"exit_code":0,"observations":[{"actual":["v1","TARGET",-1],"check":"individual target beats a matching rule","expected":["v1","TARGET",-1],"passed":true},{"actual":["v3","FALLTHROUGH",-1],"check":"negated rule does not match a missing attribute","expected":["v3","FALLTHROUGH",-1],"passed":true},{"actual":["v1","OFF",-1],"check":"off flag serves off variation","expected":["v1","OFF",-1],"passed":true},{"actual":["v2","RULE",1],"check":"second rule reports index one","expected":["v2","RULE",1],"passed":true},{"actual":["v0","FALLTHROUGH",-1],"check":"prefix match is case sensitive","expected":["v0","FALLTHROUGH",-1],"passed":true},{"actual":["v2","TARGET",-1],"check":"target to fallthrough variation still reports TARGET","expected":["v2","TARGET",-1],"passed":true},{"actual":["v0","RULE",1],"check":"targeting sample 1","expected":["v0","RULE",1],"passed":true},{"actual":["v0","FALLTHROUGH",-1],"check":"targeting sample 2","expected":["v0","FALLTHROUGH",-1],"passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"individual target beats a matching rule\", \"actual\": [\"v1\", \"TARGET\", -1], \"expected\": [\"v1\", \"TARGET\", -1], \"passed\": true}, {\"check\": \"negated rule does not match a missing attribute\", \"actual\": [\"v3\", \"FALLTHROUGH\", -1], \"expected\": [\"v3\", \"FALLTHROUGH\", -1], \"passed\": true}, {\"check\": \"off flag serves off variation\", \"actual\": [\"v1\", \"OFF\", -1], \"expected\": [\"v1\", \"OFF\", -1], \"passed\": true}, {\"check\": \"second rule reports index one\", \"actual\": [\"v2\", \"RULE\", 1], \"expected\": [\"v2\", \"RULE\", 1], \"passed\": true}, {\"check\": \"prefix match is case sensitive\", \"actual\": [\"v0\", \"FALLTHROUGH\", -1], \"expected\": [\"v0\", \"FALLTHROUGH\", -1], \"passed\": true}, {\"check\": \"target to fallthrough variation still reports TARGET\", \"actual\": [\"v2\", \"TARGET\", -1], \"expected\": [\"v2\", \"TARGET\", -1], \"passed\": true}, {\"check\": \"targeting sample 1\", \"actual\": [\"v0\", \"RULE\", 1], \"expected\": [\"v0\", \"RULE\", 1], \"passed\": true}, {\"check\": \"targeting sample 2\", \"actual\": [\"v0\", \"FALLTHROUGH\", -1], \"expected\": [\"v0\", \"FALLTHROUGH\", -1], \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}