FA-24766 / Client state / Open access
A selector cache leaks one consumer selector result into another consumer · case 01
A selector cache leaks one consumer selector result into another consumer.
ROOT CAUSE
The faulty implementation violates Selector memoization is scoped by consumer, committed version and selector identity. Cached null and false results are hits. A miss installs only the exact composite key.
VERIFIED REPAIR
Selector memoization is scoped by consumer, committed version and selector identity. Cached null and false results are hits. A miss installs only the exact composite key.
Unsuccessful approach: The partial repair still violates at least one explicit regression oracle.
Case contract
Selector memoization is scoped by consumer, committed version and selector identity. Cached null and false results are hits. A miss installs only the exact composite key.
Why this case matters
A bounded offline client-state transition with explicit lifecycle inputs.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(cache, consumer, version, selector, result):
key=(consumer,version,selector)
old=next((v for (c,n,s),v in cache.items() if n==version),result)
return old,list({**cache,key:old}.items())
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('different selector', solve({('a',1,'left'):2},'a',1,'right',3), (3, list({('a', 1, 'left'): 2, ('a', 1, 'right'): 3}.items())))
check('different consumer', solve({('a',1,'left'):2},'b',1,'left',N), (N, list({('a', 1, 'left'): 2, ('b', 1, 'left'): N}.items())))
check('same cache key', solve({('a',1,'left'):0},'a',1,'left',9), (0, list({('a', 1, 'left'): 0}.items())))
check('new version', solve({('a',1,'left'):2},'a',2,'left',3), (3, list({('a', 1, 'left'): 2, ('a', 2, 'left'): 3}.items())))
check('empty cache', solve({},'a',N,'left',False), (False, list({('a', N, 'left'): False}.items())))
check('null cached', solve({('a',1,'left'):None},'a',1,'left',3), (None, list({('a', 1, 'left'): None}.items())))
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 |
|---|---|---|---|
| different selector | [2, [[['a', 1, 'left'], 2], [['a', 1, 'right'], 2]]] | [3, [[['a', 1, 'left'], 2], [['a', 1, 'right'], 3]]] | Failed |
| different consumer | [2, [[['a', 1, 'left'], 2], [['b', 1, 'left'], 2]]] | [1, [[['a', 1, 'left'], 2], [['b', 1, 'left'], 1]]] | Failed |
| same cache key | [0, [[['a', 1, 'left'], 0]]] | [0, [[['a', 1, 'left'], 0]]] | Passed |
| new version | [3, [[['a', 1, 'left'], 2], [['a', 2, 'left'], 3]]] | [3, [[['a', 1, 'left'], 2], [['a', 2, 'left'], 3]]] | Passed |
| empty cache | [False, [[['a', 1, 'left'], False]]] | [False, [[['a', 1, 'left'], False]]] | Passed |
| null cached | [None, [[['a', 1, 'left'], None]]] | [None, [[['a', 1, 'left'], None]]] | Passed |
SHA-256 / a4f07b1e2a0933175011360fcab8f876513aa5ae7bf06b1ed6914ce2de1565cb
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(cache, consumer, version, selector, result):
key=(consumer,version,selector)
old=next((v for (c,n,s),v in cache.items() if c==consumer and n==version),result)
return old,list({**cache,key:old}.items())
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('different selector', solve({('a',1,'left'):2},'a',1,'right',3), (3, list({('a', 1, 'left'): 2, ('a', 1, 'right'): 3}.items())))
check('different consumer', solve({('a',1,'left'):2},'b',1,'left',N), (N, list({('a', 1, 'left'): 2, ('b', 1, 'left'): N}.items())))
check('same cache key', solve({('a',1,'left'):0},'a',1,'left',9), (0, list({('a', 1, 'left'): 0}.items())))
check('new version', solve({('a',1,'left'):2},'a',2,'left',3), (3, list({('a', 1, 'left'): 2, ('a', 2, 'left'): 3}.items())))
check('empty cache', solve({},'a',N,'left',False), (False, list({('a', N, 'left'): False}.items())))
check('null cached', solve({('a',1,'left'):None},'a',1,'left',3), (None, list({('a', 1, 'left'): None}.items())))
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 |
|---|---|---|---|
| different selector | [2, [[['a', 1, 'left'], 2], [['a', 1, 'right'], 2]]] | [3, [[['a', 1, 'left'], 2], [['a', 1, 'right'], 3]]] | Failed |
| different consumer | [1, [[['a', 1, 'left'], 2], [['b', 1, 'left'], 1]]] | [1, [[['a', 1, 'left'], 2], [['b', 1, 'left'], 1]]] | Passed |
| same cache key | [0, [[['a', 1, 'left'], 0]]] | [0, [[['a', 1, 'left'], 0]]] | Passed |
| new version | [3, [[['a', 1, 'left'], 2], [['a', 2, 'left'], 3]]] | [3, [[['a', 1, 'left'], 2], [['a', 2, 'left'], 3]]] | Passed |
| empty cache | [False, [[['a', 1, 'left'], False]]] | [False, [[['a', 1, 'left'], False]]] | Passed |
| null cached | [None, [[['a', 1, 'left'], None]]] | [None, [[['a', 1, 'left'], None]]] | Passed |
SHA-256 / 62551fc6b4ed22f3dd74f3003090e516f9f6618ab4ce3bddbe141bacb330aabb
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(cache, consumer, version, selector, result):
key=(consumer,version,selector)
return cache.get(key,result),list({**cache,key:cache.get(key,result)}.items())
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('different selector', solve({('a',1,'left'):2},'a',1,'right',3), (3, list({('a', 1, 'left'): 2, ('a', 1, 'right'): 3}.items())))
check('different consumer', solve({('a',1,'left'):2},'b',1,'left',N), (N, list({('a', 1, 'left'): 2, ('b', 1, 'left'): N}.items())))
check('same cache key', solve({('a',1,'left'):0},'a',1,'left',9), (0, list({('a', 1, 'left'): 0}.items())))
check('new version', solve({('a',1,'left'):2},'a',2,'left',3), (3, list({('a', 1, 'left'): 2, ('a', 2, 'left'): 3}.items())))
check('empty cache', solve({},'a',N,'left',False), (False, list({('a', N, 'left'): False}.items())))
check('null cached', solve({('a',1,'left'):None},'a',1,'left',3), (None, list({('a', 1, 'left'): None}.items())))
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 |
|---|---|---|---|
| different selector | [3, [[['a', 1, 'left'], 2], [['a', 1, 'right'], 3]]] | [3, [[['a', 1, 'left'], 2], [['a', 1, 'right'], 3]]] | Passed |
| different consumer | [1, [[['a', 1, 'left'], 2], [['b', 1, 'left'], 1]]] | [1, [[['a', 1, 'left'], 2], [['b', 1, 'left'], 1]]] | Passed |
| same cache key | [0, [[['a', 1, 'left'], 0]]] | [0, [[['a', 1, 'left'], 0]]] | Passed |
| new version | [3, [[['a', 1, 'left'], 2], [['a', 2, 'left'], 3]]] | [3, [[['a', 1, 'left'], 2], [['a', 2, 'left'], 3]]] | Passed |
| empty cache | [False, [[['a', 1, 'left'], False]]] | [False, [[['a', 1, 'left'], False]]] | Passed |
| null cached | [None, [[['a', 1, 'left'], None]]] | [None, [[['a', 1, 'left'], None]]] | Passed |
SHA-256 / 03ecb6ad26447dafd187f348d49dd6d9ffab767fef21735f133770adea0c7eab
Verification & scope
This models the stated application policy only; no browser or framework conformance is claimed. 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:41:00.575493+00:00.
Case digest / bb670617be4bd6c554de3731b54fc19d4235b27550ab7ad08574e5947fa2ed68