{"abstract":"Users land in different buckets than every other SDK computes for the same flag.","category":"Feature flag rollout bucketing","checks":8,"contract":"bucket = int(first 8 hex digits of sha1(salt + \".\" + flag + \".\" + user), 16) % 10000; the rollout percentage pct has at most two decimals and becomes a basis-point limit round(pct * 100); the user is enabled iff bucket < limit. Return [bucket, enabled].","contract_signature":"flag, user, salt, pct","evaluation_group":"w2-feature-flag-rollout-bucketing-percentage-gate","failed_approach":"Dropping the separators keeps the flag before the user but still hashes a different string.","family":"w2-feature-flag-rollout-bucketing-percentage-gate-hash-key-order","id":"FA-73841","implementations":{"attempt":{"sha256":"1a045c3b6dd24695b6ccd8ccc1c39aedd01c9484253725c1898dd9ca115e8532","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport hashlib\nN = 1\nobservations = []\ndef solve(flag, user, salt, pct):\n    limit = round(pct * 100)\n    digest = hashlib.sha1((salt + flag + user).encode()).hexdigest()\n    bucket = int(digest[:8], 16) % 10000\n    return [bucket, bucket < limit]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('bucket exactly at limit is excluded (alice)', ['new-checkout', 'alice', 'prod', 66.65], [6665, False]),\n  ('bucket one below limit is included (alice)', ['new-checkout', 'alice', 'prod', 66.66], [6665, True]),\n  ('bucket exactly at limit is excluded (bob)', ['dark-mode', 'bob', 's1', 27.55], [2755, False]),\n  ('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),\n  ('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),\n  ('half rollout control', ['search-v2', 'grace', 'ramp-7', 50], [3372, True]),\n  ('hashed user sample 1', ['search-v2', 'u55140', 's1', 100], [5052, True]),\n  ('hashed user sample 2', ['new-checkout', 'u28082', 's1', 50], [928, True])],\n [('bucket one below limit is included (alice)', ['new-checkout', 'alice', 'prod', 66.66], [6665, True]),\n  ('bucket exactly at limit is excluded (bob)', ['dark-mode', 'bob', 's1', 27.55], [2755, False]),\n  ('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),\n  ('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),\n  ('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),\n  ('zero percent disables everyone', ['dark-mode', 'dave', 's1', 0], [4167, False]),\n  ('half rollout control', ['search-v2', 'grace', 'ramp-7', 50], [3372, True]),\n  ('hashed user sample 6', ['new-checkout', 'u58886', 'ramp-7', 50.31], [3873, True])],\n [('bucket exactly at limit is excluded (bob)', ['dark-mode', 'bob', 's1', 27.55], [2755, False]),\n  ('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),\n  ('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),\n  ('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),\n  ('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),\n  ('hashed user sample 4', ['fast-pay', 'u43705', 'ramp-7', 32.8], [187, True]),\n  ('hashed user sample 11', ['search-v2', 'u91686', 'prod', 100], [5233, True]),\n  ('hashed user sample 12', ['search-v2', 'u3012', 'prod', 62.02], [6201, True])],\n [('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),\n  ('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),\n  ('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),\n  ('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),\n  ('zero percent disables everyone', ['dark-mode', 'dave', 's1', 0], [4167, False]),\n  ('hashed user sample 11', ['search-v2', 'u91686', 'prod', 100], [5233, True]),\n  ('hashed user sample 16', ['new-checkout', 'u25854', 'prod', 0.57], [5842, False]),\n  ('hashed user sample 17', ['search-v2', 'u90753', 'prod', 0], [9423, False])],\n [('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),\n  ('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),\n  ('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),\n  ('zero percent disables everyone', ['dark-mode', 'dave', 's1', 0], [4167, False]),\n  ('full rollout enables everyone', ['dark-mode', 'erin', 's1', 100], [9606, True]),\n  ('hashed user sample 18', ['dark-mode', 'u52498', 'prod', 39.33], [2698, True]),\n  ('hashed user sample 21', ['new-checkout', 'u7954', 'prod', 59.72], [196, True]),\n  ('hashed user sample 22', ['new-checkout', 'u52965', 'ramp-7', 70.89], [7088, True])]]\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":"d78f7485b7a1094ded598d47996ba5eabc8e6182f6eb7a1d51dcc17cf721f58b","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport hashlib\nN = 1\nobservations = []\ndef solve(flag, user, salt, pct):\n    limit = round(pct * 100)\n    digest = hashlib.sha1((salt + '.' + user + '.' + flag).encode()).hexdigest()\n    bucket = int(digest[:8], 16) % 10000\n    return [bucket, bucket < limit]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('bucket exactly at limit is excluded (alice)', ['new-checkout', 'alice', 'prod', 66.65], [6665, False]),\n  ('bucket one below limit is included (alice)', ['new-checkout', 'alice', 'prod', 66.66], [6665, True]),\n  ('bucket exactly at limit is excluded (bob)', ['dark-mode', 'bob', 's1', 27.55], [2755, False]),\n  ('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),\n  ('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),\n  ('half rollout control', ['search-v2', 'grace', 'ramp-7', 50], [3372, True]),\n  ('hashed user sample 1', ['search-v2', 'u55140', 's1', 100], [5052, True]),\n  ('hashed user sample 2', ['new-checkout', 'u28082', 's1', 50], [928, True])],\n [('bucket one below limit is included (alice)', ['new-checkout', 'alice', 'prod', 66.66], [6665, True]),\n  ('bucket exactly at limit is excluded (bob)', ['dark-mode', 'bob', 's1', 27.55], [2755, False]),\n  ('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),\n  ('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),\n  ('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),\n  ('zero percent disables everyone', ['dark-mode', 'dave', 's1', 0], [4167, False]),\n  ('half rollout control', ['search-v2', 'grace', 'ramp-7', 50], [3372, True]),\n  ('hashed user sample 6', ['new-checkout', 'u58886', 'ramp-7', 50.31], [3873, True])],\n [('bucket exactly at limit is excluded (bob)', ['dark-mode', 'bob', 's1', 27.55], [2755, False]),\n  ('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),\n  ('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),\n  ('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),\n  ('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),\n  ('hashed user sample 4', ['fast-pay', 'u43705', 'ramp-7', 32.8], [187, True]),\n  ('hashed user sample 11', ['search-v2', 'u91686', 'prod', 100], [5233, True]),\n  ('hashed user sample 12', ['search-v2', 'u3012', 'prod', 62.02], [6201, True])],\n [('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),\n  ('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),\n  ('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),\n  ('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),\n  ('zero percent disables everyone', ['dark-mode', 'dave', 's1', 0], [4167, False]),\n  ('hashed user sample 11', ['search-v2', 'u91686', 'prod', 100], [5233, True]),\n  ('hashed user sample 16', ['new-checkout', 'u25854', 'prod', 0.57], [5842, False]),\n  ('hashed user sample 17', ['search-v2', 'u90753', 'prod', 0], [9423, False])],\n [('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),\n  ('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),\n  ('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),\n  ('zero percent disables everyone', ['dark-mode', 'dave', 's1', 0], [4167, False]),\n  ('full rollout enables everyone', ['dark-mode', 'erin', 's1', 100], [9606, True]),\n  ('hashed user sample 18', ['dark-mode', 'u52498', 'prod', 39.33], [2698, True]),\n  ('hashed user sample 21', ['new-checkout', 'u7954', 'prod', 59.72], [196, True]),\n  ('hashed user sample 22', ['new-checkout', 'u52965', 'ramp-7', 70.89], [7088, True])]]\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-percentage-gate-hash-key-order","generated_at":"2026-09-29T14:48:51.329641+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"Percentage gates must be reproducible across services so the same user sees the same state everywhere.","root_cause":"The hashed string is built as salt.user.flag instead of salt.flag.user.","sha256":"b03bb0d0e04a509c3f8738ffd923ccd9c329432a183705c91a306f41405cde54","title":"Percentage rollout gate: User and flag swap places in the hash key · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verified":true,"visibility":"public","verification":{"attempt":{"elapsed_ms":42.07,"exit_code":1,"observations":[{"actual":[564,true],"check":"bucket exactly at limit is excluded (alice)","expected":[6665,false],"passed":false},{"actual":[564,true],"check":"bucket one below limit is included (alice)","expected":[6665,true],"passed":false},{"actual":[5311,false],"check":"bucket exactly at limit is excluded (bob)","expected":[2755,false],"passed":false},{"actual":[5311,false],"check":"bucket one below limit is included (bob)","expected":[2755,true],"passed":false},{"actual":[9588,false],"check":"bucket exactly at limit is excluded (carol)","expected":[5745,false],"passed":false},{"actual":[3776,true],"check":"half rollout control","expected":[3372,true],"passed":false},{"actual":[15,true],"check":"hashed user sample 1","expected":[5052,true],"passed":false},{"actual":[3822,true],"check":"hashed user sample 2","expected":[928,true],"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"bucket exactly at limit is excluded (alice)\", \"actual\": [564, true], \"expected\": [6665, false], \"passed\": false}, {\"check\": \"bucket one below limit is included (alice)\", \"actual\": [564, true], \"expected\": [6665, true], \"passed\": false}, {\"check\": \"bucket exactly at limit is excluded (bob)\", \"actual\": [5311, false], \"expected\": [2755, false], \"passed\": false}, {\"check\": \"bucket one below limit is included (bob)\", \"actual\": [5311, false], \"expected\": [2755, true], \"passed\": false}, {\"check\": \"bucket exactly at limit is excluded (carol)\", \"actual\": [9588, false], \"expected\": [5745, false], \"passed\": false}, {\"check\": \"half rollout control\", \"actual\": [3776, true], \"expected\": [3372, true], \"passed\": false}, {\"check\": \"hashed user sample 1\", \"actual\": [15, true], \"expected\": [5052, true], \"passed\": false}, {\"check\": \"hashed user sample 2\", \"actual\": [3822, true], \"expected\": [928, true], \"passed\": false}], \"passed\": false}\n"},"broken":{"elapsed_ms":41.889,"exit_code":1,"observations":[{"actual":[2177,true],"check":"bucket exactly at limit is excluded (alice)","expected":[6665,false],"passed":false},{"actual":[2177,true],"check":"bucket one below limit is included (alice)","expected":[6665,true],"passed":false},{"actual":[1447,true],"check":"bucket exactly at limit is excluded (bob)","expected":[2755,false],"passed":false},{"actual":[1447,true],"check":"bucket one below limit is included (bob)","expected":[2755,true],"passed":false},{"actual":[7258,false],"check":"bucket exactly at limit is excluded (carol)","expected":[5745,false],"passed":false},{"actual":[3565,true],"check":"half rollout control","expected":[3372,true],"passed":false},{"actual":[5720,true],"check":"hashed user sample 1","expected":[5052,true],"passed":false},{"actual":[7578,false],"check":"hashed user sample 2","expected":[928,true],"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"bucket exactly at limit is excluded (alice)\", \"actual\": [2177, true], \"expected\": [6665, false], \"passed\": false}, {\"check\": \"bucket one below limit is included (alice)\", \"actual\": [2177, true], \"expected\": [6665, true], \"passed\": false}, {\"check\": \"bucket exactly at limit is excluded (bob)\", \"actual\": [1447, true], \"expected\": [2755, false], \"passed\": false}, {\"check\": \"bucket one below limit is included (bob)\", \"actual\": [1447, true], \"expected\": [2755, true], \"passed\": false}, {\"check\": \"bucket exactly at limit is excluded (carol)\", \"actual\": [7258, false], \"expected\": [5745, false], \"passed\": false}, {\"check\": \"half rollout control\", \"actual\": [3565, true], \"expected\": [3372, true], \"passed\": false}, {\"check\": \"hashed user sample 1\", \"actual\": [5720, true], \"expected\": [5052, true], \"passed\": false}, {\"check\": \"hashed user sample 2\", \"actual\": [7578, false], \"expected\": [928, true], \"passed\": false}], \"passed\": false}\n"}},"member_only":{"stages":["fixed"],"fields":["implementations.fixed","verification.fixed","harness","repair"],"note":"The verified repair, its recorded checks, the repair description, and the scoring harness are available to members."}}