FA-73851 / Feature flag rollout bucketing / Open access
Percentage rollout gate: A user whose bucket equals the limit is enabled · case 01
Rollouts expose one extra basis point of traffic, and 0 percent still enables bucket zero.
ROOT CAUSE
The gate uses bucket <= limit, treating the limit as inclusive.
VERIFIED REPAIR
Enable only buckets strictly below the basis-point limit.
Unsuccessful approach: Subtracting one from the limit fixes equality but now drops the last legitimate bucket.
Case 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].
Why this case matters
Percentage gates must be reproducible across services so the same user sees the same state everywhere.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import hashlib
N = 1
observations = []
def solve(flag, user, salt, pct):
limit = round(pct * 100)
digest = hashlib.sha1((salt + '.' + flag + '.' + user).encode()).hexdigest()
bucket = int(digest[:8], 16) % 10000
return [bucket, bucket <= limit]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('bucket exactly at limit is excluded (alice)', ['new-checkout', 'alice', 'prod', 66.65], [6665, False]),
('bucket one below limit is included (alice)', ['new-checkout', 'alice', 'prod', 66.66], [6665, True]),
('bucket exactly at limit is excluded (bob)', ['dark-mode', 'bob', 's1', 27.55], [2755, False]),
('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),
('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
('hashed user sample 1', ['search-v2', 'u55140', 's1', 100], [5052, True]),
('hashed user sample 2', ['new-checkout', 'u28082', 's1', 50], [928, True])],
[('bucket one below limit is included (alice)', ['new-checkout', 'alice', 'prod', 66.66], [6665, True]),
('bucket exactly at limit is excluded (bob)', ['dark-mode', 'bob', 's1', 27.55], [2755, False]),
('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),
('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),
('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
('hashed user sample 13', ['new-checkout', 'u70823', 'ramp-7', 31.8], [3179, True]),
('hashed user sample 23', ['new-checkout', 'u5210', 'prod', 58.78], [5878, False])],
[('bucket exactly at limit is excluded (alice)', ['new-checkout', 'alice', 'prod', 66.65], [6665, False]),
('bucket exactly at limit is excluded (bob)', ['dark-mode', 'bob', 's1', 27.55], [2755, False]),
('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),
('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),
('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
('hashed user sample 11', ['search-v2', 'u91686', 'prod', 100], [5233, True]),
('hashed user sample 40', ['fast-pay', 'u536', 'prod', 9.61], [960, True])],
[('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),
('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),
('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
('zero percent disables everyone', ['dark-mode', 'dave', 's1', 0], [4167, False]),
('hashed user sample 16', ['new-checkout', 'u25854', 'prod', 0.57], [5842, False]),
('hashed user sample 23', ['new-checkout', 'u5210', 'prod', 58.78], [5878, False]),
('hashed user sample 51', ['new-checkout', 'u15929', 'ramp-7', 98.17], [9816, True])],
[('bucket exactly at limit is excluded (alice)', ['new-checkout', 'alice', 'prod', 66.65], [6665, False]),
('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),
('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
('zero percent disables everyone', ['dark-mode', 'dave', 's1', 0], [4167, False]),
('full rollout enables everyone', ['dark-mode', 'erin', 's1', 100], [9606, True]),
('hashed user sample 21', ['new-checkout', 'u7954', 'prod', 59.72], [196, True]),
('hashed user sample 22', ['new-checkout', 'u52965', 'ramp-7', 70.89], [7088, True])]]
for label, args, expected in fixtures[N - 1]:
check(label, 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 |
|---|---|---|---|
| bucket exactly at limit is excluded (alice) | [6665, True] | [6665, False] | Failed |
| bucket one below limit is included (alice) | [6665, True] | [6665, True] | Passed |
| bucket exactly at limit is excluded (bob) | [2755, True] | [2755, False] | Failed |
| bucket one below limit is included (bob) | [2755, True] | [2755, True] | Passed |
| bucket exactly at limit is excluded (carol) | [5745, True] | [5745, False] | Failed |
| float truncation regression at 65.82 percent | [6581, True] | [6581, True] | Passed |
| hashed user sample 1 | [5052, True] | [5052, True] | Passed |
| hashed user sample 2 | [928, True] | [928, True] | Passed |
SHA-256 / 362bca2e85ffc2d7eab73548ec9259e6afc4c78608b083e0d1c45d4f8b12f509
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import hashlib
N = 1
observations = []
def solve(flag, user, salt, pct):
limit = round(pct * 100)
digest = hashlib.sha1((salt + '.' + flag + '.' + user).encode()).hexdigest()
bucket = int(digest[:8], 16) % 10000
return [bucket, bucket < limit - 1]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('bucket exactly at limit is excluded (alice)', ['new-checkout', 'alice', 'prod', 66.65], [6665, False]),
('bucket one below limit is included (alice)', ['new-checkout', 'alice', 'prod', 66.66], [6665, True]),
('bucket exactly at limit is excluded (bob)', ['dark-mode', 'bob', 's1', 27.55], [2755, False]),
('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),
('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
('hashed user sample 1', ['search-v2', 'u55140', 's1', 100], [5052, True]),
('hashed user sample 2', ['new-checkout', 'u28082', 's1', 50], [928, True])],
[('bucket one below limit is included (alice)', ['new-checkout', 'alice', 'prod', 66.66], [6665, True]),
('bucket exactly at limit is excluded (bob)', ['dark-mode', 'bob', 's1', 27.55], [2755, False]),
('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),
('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),
('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
('hashed user sample 13', ['new-checkout', 'u70823', 'ramp-7', 31.8], [3179, True]),
('hashed user sample 23', ['new-checkout', 'u5210', 'prod', 58.78], [5878, False])],
[('bucket exactly at limit is excluded (alice)', ['new-checkout', 'alice', 'prod', 66.65], [6665, False]),
('bucket exactly at limit is excluded (bob)', ['dark-mode', 'bob', 's1', 27.55], [2755, False]),
('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),
('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),
('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
('hashed user sample 11', ['search-v2', 'u91686', 'prod', 100], [5233, True]),
('hashed user sample 40', ['fast-pay', 'u536', 'prod', 9.61], [960, True])],
[('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),
('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),
('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
('zero percent disables everyone', ['dark-mode', 'dave', 's1', 0], [4167, False]),
('hashed user sample 16', ['new-checkout', 'u25854', 'prod', 0.57], [5842, False]),
('hashed user sample 23', ['new-checkout', 'u5210', 'prod', 58.78], [5878, False]),
('hashed user sample 51', ['new-checkout', 'u15929', 'ramp-7', 98.17], [9816, True])],
[('bucket exactly at limit is excluded (alice)', ['new-checkout', 'alice', 'prod', 66.65], [6665, False]),
('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),
('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
('zero percent disables everyone', ['dark-mode', 'dave', 's1', 0], [4167, False]),
('full rollout enables everyone', ['dark-mode', 'erin', 's1', 100], [9606, True]),
('hashed user sample 21', ['new-checkout', 'u7954', 'prod', 59.72], [196, True]),
('hashed user sample 22', ['new-checkout', 'u52965', 'ramp-7', 70.89], [7088, True])]]
for label, args, expected in fixtures[N - 1]:
check(label, 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 |
|---|---|---|---|
| bucket exactly at limit is excluded (alice) | [6665, False] | [6665, False] | Passed |
| bucket one below limit is included (alice) | [6665, False] | [6665, True] | Failed |
| bucket exactly at limit is excluded (bob) | [2755, False] | [2755, False] | Passed |
| bucket one below limit is included (bob) | [2755, False] | [2755, True] | Failed |
| bucket exactly at limit is excluded (carol) | [5745, False] | [5745, False] | Passed |
| float truncation regression at 65.82 percent | [6581, False] | [6581, True] | Failed |
| hashed user sample 1 | [5052, True] | [5052, True] | Passed |
| hashed user sample 2 | [928, True] | [928, True] | Passed |
SHA-256 / db0d2dac1e6e1e50d2094fefd418ab312864c8e2a497155dcd48ca2bef405a09
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import hashlib
N = 1
observations = []
def solve(flag, user, salt, pct):
limit = round(pct * 100)
digest = hashlib.sha1((salt + '.' + flag + '.' + user).encode()).hexdigest()
bucket = int(digest[:8], 16) % 10000
return [bucket, bucket < limit]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('bucket exactly at limit is excluded (alice)', ['new-checkout', 'alice', 'prod', 66.65], [6665, False]),
('bucket one below limit is included (alice)', ['new-checkout', 'alice', 'prod', 66.66], [6665, True]),
('bucket exactly at limit is excluded (bob)', ['dark-mode', 'bob', 's1', 27.55], [2755, False]),
('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),
('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
('hashed user sample 1', ['search-v2', 'u55140', 's1', 100], [5052, True]),
('hashed user sample 2', ['new-checkout', 'u28082', 's1', 50], [928, True])],
[('bucket one below limit is included (alice)', ['new-checkout', 'alice', 'prod', 66.66], [6665, True]),
('bucket exactly at limit is excluded (bob)', ['dark-mode', 'bob', 's1', 27.55], [2755, False]),
('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),
('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),
('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
('hashed user sample 13', ['new-checkout', 'u70823', 'ramp-7', 31.8], [3179, True]),
('hashed user sample 23', ['new-checkout', 'u5210', 'prod', 58.78], [5878, False])],
[('bucket exactly at limit is excluded (alice)', ['new-checkout', 'alice', 'prod', 66.65], [6665, False]),
('bucket exactly at limit is excluded (bob)', ['dark-mode', 'bob', 's1', 27.55], [2755, False]),
('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),
('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),
('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
('hashed user sample 11', ['search-v2', 'u91686', 'prod', 100], [5233, True]),
('hashed user sample 40', ['fast-pay', 'u536', 'prod', 9.61], [960, True])],
[('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),
('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),
('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
('zero percent disables everyone', ['dark-mode', 'dave', 's1', 0], [4167, False]),
('hashed user sample 16', ['new-checkout', 'u25854', 'prod', 0.57], [5842, False]),
('hashed user sample 23', ['new-checkout', 'u5210', 'prod', 58.78], [5878, False]),
('hashed user sample 51', ['new-checkout', 'u15929', 'ramp-7', 98.17], [9816, True])],
[('bucket exactly at limit is excluded (alice)', ['new-checkout', 'alice', 'prod', 66.65], [6665, False]),
('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),
('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
('zero percent disables everyone', ['dark-mode', 'dave', 's1', 0], [4167, False]),
('full rollout enables everyone', ['dark-mode', 'erin', 's1', 100], [9606, True]),
('hashed user sample 21', ['new-checkout', 'u7954', 'prod', 59.72], [196, True]),
('hashed user sample 22', ['new-checkout', 'u52965', 'ramp-7', 70.89], [7088, True])]]
for label, args, expected in fixtures[N - 1]:
check(label, 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 |
|---|---|---|---|
| bucket exactly at limit is excluded (alice) | [6665, False] | [6665, False] | Passed |
| bucket one below limit is included (alice) | [6665, True] | [6665, True] | Passed |
| bucket exactly at limit is excluded (bob) | [2755, False] | [2755, False] | Passed |
| bucket one below limit is included (bob) | [2755, True] | [2755, True] | Passed |
| bucket exactly at limit is excluded (carol) | [5745, False] | [5745, False] | Passed |
| float truncation regression at 65.82 percent | [6581, True] | [6581, True] | Passed |
| hashed user sample 1 | [5052, True] | [5052, True] | Passed |
| hashed user sample 2 | [928, True] | [928, True] | Passed |
SHA-256 / c6ae7f8e4adce96a9565e5d6e5bf61bb5aee20d516a8f88ce35ff1aa95616c4d
Verification & scope
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.
Observations recorded using Python 3.12.14 at 2026-09-29T14:48:51.329529+00:00.
Case digest / 2d5182972023e65d10194443c0833a7e01aa758cdbf78eaf2d797d3d9b16eeef