FA-73976 / Feature flag rollout bucketing / Open access
Bucketing attribute selection: Fractional floats are truncated into identities · case 01
Values 2.5 and 2 collapse into the same bucketing identity.
ROOT CAUSE
The non-integral check is missing, so int() truncates any float.
VERIFIED REPAIR
Treat floats with a fractional part as unbucketable.
Unsuccessful approach: Rounding instead of truncating still invents an identity for a fractional value.
Case contract
The bucketing identity is user[bucket_by] when bucket_by is non-empty and present, else user["key"]. Booleans, None and non-scalar values are unbucketable -> [None, 0]; integral floats use their integer form, other floats are unbucketable; ints and strings are used verbatim via str(). Return [identity, crc32(flag_key + "." + salt + "." + identity) % 100000].
Why this case matters
Bucketing by organisation or device keeps whole accounts in one variant; the identity must be stable.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import zlib
N = 1
observations = []
def solve(flag_key, salt, user, bucket_by):
if bucket_by and bucket_by in user:
value = user[bucket_by]
else:
value = user.get('key')
if isinstance(value, bool) or value is None:
return [None, 0]
if isinstance(value, float):
value = int(value)
if not isinstance(value, (int, str)):
return [None, 0]
ident = str(value)
return [ident, zlib.crc32((flag_key + '.' + salt + '.' + ident).encode()) % 100000]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('boolean attribute is unbucketable', ['new-nav', 'a', {'key': 'u1', 'org': True}, 'org'], [None, 0]),
('integral float bucketed as integer', ['new-nav', 'a', {'key': 'u1', 'org': 5.0}, 'org'], ['5', 7520]),
('integral float matches integer identity', ['new-nav', 'a', {'key': 'u1', 'org': 5}, 'org'], ['5', 7520]),
('missing bucket attribute falls back to key', ['new-nav', 'a', {'key': 'u1'}, 'org'], ['u1', 4562]),
('zero attribute is a real identity', ['bulk-edit', 'b', {'key': 'u2', 'org': 0}, 'org'], ['0', 47112]),
('fractional float is unbucketable', ['new-nav', 'a', {'key': 'u1', 'org': 2.5}, 'org'], [None, 0]),
('identity sample 1', ['new-nav', 'b', {'key': '05', 'org': '', 'team': 5.0}, 'team'], ['5', 56729]),
('identity sample 2', ['new-nav', 'b', {'key': 'u1', 'org': '05', 'team': [1]}, 'org'], ['05', 58693])],
[('integral float bucketed as integer', ['new-nav', 'a', {'key': 'u1', 'org': 5.0}, 'org'], ['5', 7520]),
('integral float matches integer identity', ['new-nav', 'a', {'key': 'u1', 'org': 5}, 'org'], ['5', 7520]),
('missing bucket attribute falls back to key', ['new-nav', 'a', {'key': 'u1'}, 'org'], ['u1', 4562]),
('zero attribute is a real identity', ['bulk-edit', 'b', {'key': 'u2', 'org': 0}, 'org'], ['0', 47112]),
('fractional float is unbucketable', ['new-nav', 'a', {'key': 'u1', 'org': 2.5}, 'org'], [None, 0]),
('identity sample 6', ['new-nav', 'b', {'key': 'u1', 'org': -3.0, 'team': 2.5}, 'org'], ['-3', 33868]),
('identity sample 7', ['new-nav', 'a', {'key': '007', 'team': 'acme'}, 'team'], ['acme', 37026]),
('identity sample 32', ['new-nav', 'a', {'key': 'u42', 'org': 3.9}, 'org'], [None, 0])],
[('integral float matches integer identity', ['new-nav', 'a', {'key': 'u1', 'org': 5}, 'org'], ['5', 7520]),
('missing bucket attribute falls back to key', ['new-nav', 'a', {'key': 'u1'}, 'org'], ['u1', 4562]),
('zero attribute is a real identity', ['bulk-edit', 'b', {'key': 'u2', 'org': 0}, 'org'], ['0', 47112]),
('fractional float is unbucketable', ['new-nav', 'a', {'key': 'u1', 'org': 2.5}, 'org'], [None, 0]),
('leading-zero string kept verbatim', ['new-nav', 'a', {'key': 'u1', 'org': '007'}, 'org'], ['007', 42108]),
('identity sample 11', ['new-nav', 'a', {'key': 'u1', 'org': 12, 'team': 2.5}, None], ['u1', 4562]),
('identity sample 12', ['new-nav', 'b', {'key': '007'}, None], ['007', 68652]),
('identity sample 45', ['bulk-edit', 'b', {'key': 'u42', 'org': 2.5, 'team': None}, 'org'], [None, 0])],
[('missing bucket attribute falls back to key', ['new-nav', 'a', {'key': 'u1'}, 'org'], ['u1', 4562]),
('zero attribute is a real identity', ['bulk-edit', 'b', {'key': 'u2', 'org': 0}, 'org'], ['0', 47112]),
('fractional float is unbucketable', ['new-nav', 'a', {'key': 'u1', 'org': 2.5}, 'org'], [None, 0]),
('leading-zero string kept verbatim', ['new-nav', 'a', {'key': 'u1', 'org': '007'}, 'org'], ['007', 42108]),
('leading-zero key kept verbatim', ['bulk-edit', 'b', {'key': '05'}, None], ['05', 9565]),
('identity sample 16', ['new-nav', 'b', {'key': 'u1', 'org': '0012', 'team': ''}, None], ['u1', 96668]),
('identity sample 17', ['new-nav', 'a', {'key': 'u1', 'org': 12, 'team': True}, 'org'], ['12', 46025]),
('identity sample 31', ['bulk-edit', 'a', {'key': '05', 'org': 2.5}, 'org'], [None, 0])],
[('zero attribute is a real identity', ['bulk-edit', 'b', {'key': 'u2', 'org': 0}, 'org'], ['0', 47112]),
('fractional float is unbucketable', ['new-nav', 'a', {'key': 'u1', 'org': 2.5}, 'org'], [None, 0]),
('leading-zero string kept verbatim', ['new-nav', 'a', {'key': 'u1', 'org': '007'}, 'org'], ['007', 42108]),
('leading-zero key kept verbatim', ['bulk-edit', 'b', {'key': '05'}, None], ['05', 9565]),
('false attribute is unbucketable', ['bulk-edit', 'b', {'key': 'u1', 'org': False}, 'org'], [None, 0]),
('identity sample 21', ['new-nav', 'a', {'key': 'u42', 'org': 12, 'team': False}, 'team'], [None, 0]),
('identity sample 22', ['bulk-edit', 'a', {'key': 'u1', 'org': ''}, None], ['u1', 93162]),
('identity sample 35', ['bulk-edit', 'b', {'key': 'x0', 'org': 3.9, 'team': '0012'}, 'org'], [None, 0])]]
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 |
|---|---|---|---|
| boolean attribute is unbucketable | [None, 0] | [None, 0] | Passed |
| integral float bucketed as integer | ['5', 7520] | ['5', 7520] | Passed |
| integral float matches integer identity | ['5', 7520] | ['5', 7520] | Passed |
| missing bucket attribute falls back to key | ['u1', 4562] | ['u1', 4562] | Passed |
| zero attribute is a real identity | ['0', 47112] | ['0', 47112] | Passed |
| fractional float is unbucketable | ['2', 25699] | [None, 0] | Failed |
| identity sample 1 | ['5', 56729] | ['5', 56729] | Passed |
| identity sample 2 | ['05', 58693] | ['05', 58693] | Passed |
SHA-256 / 20964395d9554bdc462edd1691d6b16f13bccbf7cece063bd2b88fb1760aac5d
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import zlib
N = 1
observations = []
def solve(flag_key, salt, user, bucket_by):
if bucket_by and bucket_by in user:
value = user[bucket_by]
else:
value = user.get('key')
if isinstance(value, bool) or value is None:
return [None, 0]
if isinstance(value, float):
value = round(value)
if not isinstance(value, (int, str)):
return [None, 0]
ident = str(value)
return [ident, zlib.crc32((flag_key + '.' + salt + '.' + ident).encode()) % 100000]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('boolean attribute is unbucketable', ['new-nav', 'a', {'key': 'u1', 'org': True}, 'org'], [None, 0]),
('integral float bucketed as integer', ['new-nav', 'a', {'key': 'u1', 'org': 5.0}, 'org'], ['5', 7520]),
('integral float matches integer identity', ['new-nav', 'a', {'key': 'u1', 'org': 5}, 'org'], ['5', 7520]),
('missing bucket attribute falls back to key', ['new-nav', 'a', {'key': 'u1'}, 'org'], ['u1', 4562]),
('zero attribute is a real identity', ['bulk-edit', 'b', {'key': 'u2', 'org': 0}, 'org'], ['0', 47112]),
('fractional float is unbucketable', ['new-nav', 'a', {'key': 'u1', 'org': 2.5}, 'org'], [None, 0]),
('identity sample 1', ['new-nav', 'b', {'key': '05', 'org': '', 'team': 5.0}, 'team'], ['5', 56729]),
('identity sample 2', ['new-nav', 'b', {'key': 'u1', 'org': '05', 'team': [1]}, 'org'], ['05', 58693])],
[('integral float bucketed as integer', ['new-nav', 'a', {'key': 'u1', 'org': 5.0}, 'org'], ['5', 7520]),
('integral float matches integer identity', ['new-nav', 'a', {'key': 'u1', 'org': 5}, 'org'], ['5', 7520]),
('missing bucket attribute falls back to key', ['new-nav', 'a', {'key': 'u1'}, 'org'], ['u1', 4562]),
('zero attribute is a real identity', ['bulk-edit', 'b', {'key': 'u2', 'org': 0}, 'org'], ['0', 47112]),
('fractional float is unbucketable', ['new-nav', 'a', {'key': 'u1', 'org': 2.5}, 'org'], [None, 0]),
('identity sample 6', ['new-nav', 'b', {'key': 'u1', 'org': -3.0, 'team': 2.5}, 'org'], ['-3', 33868]),
('identity sample 7', ['new-nav', 'a', {'key': '007', 'team': 'acme'}, 'team'], ['acme', 37026]),
('identity sample 32', ['new-nav', 'a', {'key': 'u42', 'org': 3.9}, 'org'], [None, 0])],
[('integral float matches integer identity', ['new-nav', 'a', {'key': 'u1', 'org': 5}, 'org'], ['5', 7520]),
('missing bucket attribute falls back to key', ['new-nav', 'a', {'key': 'u1'}, 'org'], ['u1', 4562]),
('zero attribute is a real identity', ['bulk-edit', 'b', {'key': 'u2', 'org': 0}, 'org'], ['0', 47112]),
('fractional float is unbucketable', ['new-nav', 'a', {'key': 'u1', 'org': 2.5}, 'org'], [None, 0]),
('leading-zero string kept verbatim', ['new-nav', 'a', {'key': 'u1', 'org': '007'}, 'org'], ['007', 42108]),
('identity sample 11', ['new-nav', 'a', {'key': 'u1', 'org': 12, 'team': 2.5}, None], ['u1', 4562]),
('identity sample 12', ['new-nav', 'b', {'key': '007'}, None], ['007', 68652]),
('identity sample 45', ['bulk-edit', 'b', {'key': 'u42', 'org': 2.5, 'team': None}, 'org'], [None, 0])],
[('missing bucket attribute falls back to key', ['new-nav', 'a', {'key': 'u1'}, 'org'], ['u1', 4562]),
('zero attribute is a real identity', ['bulk-edit', 'b', {'key': 'u2', 'org': 0}, 'org'], ['0', 47112]),
('fractional float is unbucketable', ['new-nav', 'a', {'key': 'u1', 'org': 2.5}, 'org'], [None, 0]),
('leading-zero string kept verbatim', ['new-nav', 'a', {'key': 'u1', 'org': '007'}, 'org'], ['007', 42108]),
('leading-zero key kept verbatim', ['bulk-edit', 'b', {'key': '05'}, None], ['05', 9565]),
('identity sample 16', ['new-nav', 'b', {'key': 'u1', 'org': '0012', 'team': ''}, None], ['u1', 96668]),
('identity sample 17', ['new-nav', 'a', {'key': 'u1', 'org': 12, 'team': True}, 'org'], ['12', 46025]),
('identity sample 31', ['bulk-edit', 'a', {'key': '05', 'org': 2.5}, 'org'], [None, 0])],
[('zero attribute is a real identity', ['bulk-edit', 'b', {'key': 'u2', 'org': 0}, 'org'], ['0', 47112]),
('fractional float is unbucketable', ['new-nav', 'a', {'key': 'u1', 'org': 2.5}, 'org'], [None, 0]),
('leading-zero string kept verbatim', ['new-nav', 'a', {'key': 'u1', 'org': '007'}, 'org'], ['007', 42108]),
('leading-zero key kept verbatim', ['bulk-edit', 'b', {'key': '05'}, None], ['05', 9565]),
('false attribute is unbucketable', ['bulk-edit', 'b', {'key': 'u1', 'org': False}, 'org'], [None, 0]),
('identity sample 21', ['new-nav', 'a', {'key': 'u42', 'org': 12, 'team': False}, 'team'], [None, 0]),
('identity sample 22', ['bulk-edit', 'a', {'key': 'u1', 'org': ''}, None], ['u1', 93162]),
('identity sample 35', ['bulk-edit', 'b', {'key': 'x0', 'org': 3.9, 'team': '0012'}, 'org'], [None, 0])]]
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 |
|---|---|---|---|
| boolean attribute is unbucketable | [None, 0] | [None, 0] | Passed |
| integral float bucketed as integer | ['5', 7520] | ['5', 7520] | Passed |
| integral float matches integer identity | ['5', 7520] | ['5', 7520] | Passed |
| missing bucket attribute falls back to key | ['u1', 4562] | ['u1', 4562] | Passed |
| zero attribute is a real identity | ['0', 47112] | ['0', 47112] | Passed |
| fractional float is unbucketable | ['2', 25699] | [None, 0] | Failed |
| identity sample 1 | ['5', 56729] | ['5', 56729] | Passed |
| identity sample 2 | ['05', 58693] | ['05', 58693] | Passed |
SHA-256 / 32698352647e81c42cd974f23a77327a90ee219e751eab1bbb7bb6a769f2e727
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import zlib
N = 1
observations = []
def solve(flag_key, salt, user, bucket_by):
if bucket_by and bucket_by in user:
value = user[bucket_by]
else:
value = user.get('key')
if isinstance(value, bool) or value is None:
return [None, 0]
if isinstance(value, float):
if value != int(value):
return [None, 0]
value = int(value)
if not isinstance(value, (int, str)):
return [None, 0]
ident = str(value)
return [ident, zlib.crc32((flag_key + '.' + salt + '.' + ident).encode()) % 100000]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('boolean attribute is unbucketable', ['new-nav', 'a', {'key': 'u1', 'org': True}, 'org'], [None, 0]),
('integral float bucketed as integer', ['new-nav', 'a', {'key': 'u1', 'org': 5.0}, 'org'], ['5', 7520]),
('integral float matches integer identity', ['new-nav', 'a', {'key': 'u1', 'org': 5}, 'org'], ['5', 7520]),
('missing bucket attribute falls back to key', ['new-nav', 'a', {'key': 'u1'}, 'org'], ['u1', 4562]),
('zero attribute is a real identity', ['bulk-edit', 'b', {'key': 'u2', 'org': 0}, 'org'], ['0', 47112]),
('fractional float is unbucketable', ['new-nav', 'a', {'key': 'u1', 'org': 2.5}, 'org'], [None, 0]),
('identity sample 1', ['new-nav', 'b', {'key': '05', 'org': '', 'team': 5.0}, 'team'], ['5', 56729]),
('identity sample 2', ['new-nav', 'b', {'key': 'u1', 'org': '05', 'team': [1]}, 'org'], ['05', 58693])],
[('integral float bucketed as integer', ['new-nav', 'a', {'key': 'u1', 'org': 5.0}, 'org'], ['5', 7520]),
('integral float matches integer identity', ['new-nav', 'a', {'key': 'u1', 'org': 5}, 'org'], ['5', 7520]),
('missing bucket attribute falls back to key', ['new-nav', 'a', {'key': 'u1'}, 'org'], ['u1', 4562]),
('zero attribute is a real identity', ['bulk-edit', 'b', {'key': 'u2', 'org': 0}, 'org'], ['0', 47112]),
('fractional float is unbucketable', ['new-nav', 'a', {'key': 'u1', 'org': 2.5}, 'org'], [None, 0]),
('identity sample 6', ['new-nav', 'b', {'key': 'u1', 'org': -3.0, 'team': 2.5}, 'org'], ['-3', 33868]),
('identity sample 7', ['new-nav', 'a', {'key': '007', 'team': 'acme'}, 'team'], ['acme', 37026]),
('identity sample 32', ['new-nav', 'a', {'key': 'u42', 'org': 3.9}, 'org'], [None, 0])],
[('integral float matches integer identity', ['new-nav', 'a', {'key': 'u1', 'org': 5}, 'org'], ['5', 7520]),
('missing bucket attribute falls back to key', ['new-nav', 'a', {'key': 'u1'}, 'org'], ['u1', 4562]),
('zero attribute is a real identity', ['bulk-edit', 'b', {'key': 'u2', 'org': 0}, 'org'], ['0', 47112]),
('fractional float is unbucketable', ['new-nav', 'a', {'key': 'u1', 'org': 2.5}, 'org'], [None, 0]),
('leading-zero string kept verbatim', ['new-nav', 'a', {'key': 'u1', 'org': '007'}, 'org'], ['007', 42108]),
('identity sample 11', ['new-nav', 'a', {'key': 'u1', 'org': 12, 'team': 2.5}, None], ['u1', 4562]),
('identity sample 12', ['new-nav', 'b', {'key': '007'}, None], ['007', 68652]),
('identity sample 45', ['bulk-edit', 'b', {'key': 'u42', 'org': 2.5, 'team': None}, 'org'], [None, 0])],
[('missing bucket attribute falls back to key', ['new-nav', 'a', {'key': 'u1'}, 'org'], ['u1', 4562]),
('zero attribute is a real identity', ['bulk-edit', 'b', {'key': 'u2', 'org': 0}, 'org'], ['0', 47112]),
('fractional float is unbucketable', ['new-nav', 'a', {'key': 'u1', 'org': 2.5}, 'org'], [None, 0]),
('leading-zero string kept verbatim', ['new-nav', 'a', {'key': 'u1', 'org': '007'}, 'org'], ['007', 42108]),
('leading-zero key kept verbatim', ['bulk-edit', 'b', {'key': '05'}, None], ['05', 9565]),
('identity sample 16', ['new-nav', 'b', {'key': 'u1', 'org': '0012', 'team': ''}, None], ['u1', 96668]),
('identity sample 17', ['new-nav', 'a', {'key': 'u1', 'org': 12, 'team': True}, 'org'], ['12', 46025]),
('identity sample 31', ['bulk-edit', 'a', {'key': '05', 'org': 2.5}, 'org'], [None, 0])],
[('zero attribute is a real identity', ['bulk-edit', 'b', {'key': 'u2', 'org': 0}, 'org'], ['0', 47112]),
('fractional float is unbucketable', ['new-nav', 'a', {'key': 'u1', 'org': 2.5}, 'org'], [None, 0]),
('leading-zero string kept verbatim', ['new-nav', 'a', {'key': 'u1', 'org': '007'}, 'org'], ['007', 42108]),
('leading-zero key kept verbatim', ['bulk-edit', 'b', {'key': '05'}, None], ['05', 9565]),
('false attribute is unbucketable', ['bulk-edit', 'b', {'key': 'u1', 'org': False}, 'org'], [None, 0]),
('identity sample 21', ['new-nav', 'a', {'key': 'u42', 'org': 12, 'team': False}, 'team'], [None, 0]),
('identity sample 22', ['bulk-edit', 'a', {'key': 'u1', 'org': ''}, None], ['u1', 93162]),
('identity sample 35', ['bulk-edit', 'b', {'key': 'x0', 'org': 3.9, 'team': '0012'}, 'org'], [None, 0])]]
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 |
|---|---|---|---|
| boolean attribute is unbucketable | [None, 0] | [None, 0] | Passed |
| integral float bucketed as integer | ['5', 7520] | ['5', 7520] | Passed |
| integral float matches integer identity | ['5', 7520] | ['5', 7520] | Passed |
| missing bucket attribute falls back to key | ['u1', 4562] | ['u1', 4562] | Passed |
| zero attribute is a real identity | ['0', 47112] | ['0', 47112] | Passed |
| fractional float is unbucketable | [None, 0] | [None, 0] | Passed |
| identity sample 1 | ['5', 56729] | ['5', 56729] | Passed |
| identity sample 2 | ['05', 58693] | ['05', 58693] | Passed |
SHA-256 / 84d3369c51178087f52ef486061996ab5132f7ffe50e684227ad5d93fd391358
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:52.505953+00:00.
Case digest / 0065a2f3870999a9f61ce53660f22ad009e246dc56a9bcf00dce93f6a3dc448c