FA-53371 / Accessibility interaction semantics / Open access
A platform unsupported role leaks through · case 01
A platform unsupported role leaks through.
ROOT CAUSE
The unsupported role decision in the role negotiation adapter violates its declared contract.
VERIFIED REPAIR
Apply the exact contract at the unsupported role decision: if chosen not in supported:
Unsuccessful approach: The local repair substitutes if chosen not in supported and not supported: but still mishandles the regression fixtures.
Case contract
Resolve an adapter role from ordered author tokens, native role, interactivity, required-role constraint and platform support. Supported abstract roles are group, link, image, button, article, generic and presentation. Skip unknown and abstract tokens (command, structure). Only first usable explicit token wins. Presentation is ignored on interactive objects; required native role (when required true) rejects incompatible overrides except native itself. Unsupported platform roles fall back to native if supported, otherwise generic. Generic yields no interface; link and button yield action, image yields image, article/group yield container. Return [role,interface,source] where source is explicit, native, or fallback.
Why this case matters
Offline accessibility bridge model with explicit policy; useful for testing semantic API adapters independently of browser implementations.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(data):
tokens,native,interactive,required,supported = data
known = {'group','link','image','button','article','generic','presentation'}
chosen = None
source = 'native'
for token in tokens.split():
if token not in known: continue
if token == 'presentation' and interactive: continue
if required and token != native: continue
chosen = token
source = 'explicit'
break
if chosen is None: chosen = native
if False:
chosen = native if native in supported else 'generic'
source = 'fallback'
interface = {'link':'action','button':'action','image':'image','article':'container','group':'container'}.get(chosen)
return [chosen,interface,source]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('ordered fallback', solve(['unknown command group link','image',False,False,['group','link','image']],), ['group','container','explicit'])
check('interactive presentation', solve(['presentation link','button',True,False,['presentation','link','button']],), ['link','action','explicit'])
check('required role', solve(['link image','image',False,True,['image','link']],), ['image','image','explicit'])
check('native fallback', solve(['article','image',False,False,['image']],), ['image','image','fallback'])
check('no supported native', solve(['group','image',False,False,[]],), ['generic',None,'fallback'])
check('empty uses native', solve([' '*N,'button',True,False,['button']],), ['button','action','native'])
check('unknown only', solve(['unknown'+str(N),['article','image','button','group','link'][N-1],False,False,['article','image','button','group','link']],), [['article','image','button','group','link'][N-1],['container','image','action','container','action'][N-1],'native'])
check('presentation retained', solve(['presentation','image',False,False,['presentation']],), ['presentation',None,'explicit'])
check('tab separated', solve(['unknown\timage','group',False,False,['image','group']],), ['image','image','explicit'])
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 |
|---|---|---|---|
| ordered fallback | ['group', 'container', 'explicit'] | ['group', 'container', 'explicit'] | Passed |
| interactive presentation | ['link', 'action', 'explicit'] | ['link', 'action', 'explicit'] | Passed |
| required role | ['image', 'image', 'explicit'] | ['image', 'image', 'explicit'] | Passed |
| native fallback | ['article', 'container', 'explicit'] | ['image', 'image', 'fallback'] | Failed |
| no supported native | ['group', 'container', 'explicit'] | ['generic', None, 'fallback'] | Failed |
| empty uses native | ['button', 'action', 'native'] | ['button', 'action', 'native'] | Passed |
| unknown only | ['article', 'container', 'native'] | ['article', 'container', 'native'] | Passed |
| presentation retained | ['presentation', None, 'explicit'] | ['presentation', None, 'explicit'] | Passed |
| tab separated | ['image', 'image', 'explicit'] | ['image', 'image', 'explicit'] | Passed |
SHA-256 / deeccf6d1748ef6173c9abb497308e771a3b55b9276390d359dd3b7b36b70620
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(data):
tokens,native,interactive,required,supported = data
known = {'group','link','image','button','article','generic','presentation'}
chosen = None
source = 'native'
for token in tokens.split():
if token not in known: continue
if token == 'presentation' and interactive: continue
if required and token != native: continue
chosen = token
source = 'explicit'
break
if chosen is None: chosen = native
if chosen not in supported and not supported:
chosen = native if native in supported else 'generic'
source = 'fallback'
interface = {'link':'action','button':'action','image':'image','article':'container','group':'container'}.get(chosen)
return [chosen,interface,source]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('ordered fallback', solve(['unknown command group link','image',False,False,['group','link','image']],), ['group','container','explicit'])
check('interactive presentation', solve(['presentation link','button',True,False,['presentation','link','button']],), ['link','action','explicit'])
check('required role', solve(['link image','image',False,True,['image','link']],), ['image','image','explicit'])
check('native fallback', solve(['article','image',False,False,['image']],), ['image','image','fallback'])
check('no supported native', solve(['group','image',False,False,[]],), ['generic',None,'fallback'])
check('empty uses native', solve([' '*N,'button',True,False,['button']],), ['button','action','native'])
check('unknown only', solve(['unknown'+str(N),['article','image','button','group','link'][N-1],False,False,['article','image','button','group','link']],), [['article','image','button','group','link'][N-1],['container','image','action','container','action'][N-1],'native'])
check('presentation retained', solve(['presentation','image',False,False,['presentation']],), ['presentation',None,'explicit'])
check('tab separated', solve(['unknown\timage','group',False,False,['image','group']],), ['image','image','explicit'])
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 |
|---|---|---|---|
| ordered fallback | ['group', 'container', 'explicit'] | ['group', 'container', 'explicit'] | Passed |
| interactive presentation | ['link', 'action', 'explicit'] | ['link', 'action', 'explicit'] | Passed |
| required role | ['image', 'image', 'explicit'] | ['image', 'image', 'explicit'] | Passed |
| native fallback | ['article', 'container', 'explicit'] | ['image', 'image', 'fallback'] | Failed |
| no supported native | ['generic', None, 'fallback'] | ['generic', None, 'fallback'] | Passed |
| empty uses native | ['button', 'action', 'native'] | ['button', 'action', 'native'] | Passed |
| unknown only | ['article', 'container', 'native'] | ['article', 'container', 'native'] | Passed |
| presentation retained | ['presentation', None, 'explicit'] | ['presentation', None, 'explicit'] | Passed |
| tab separated | ['image', 'image', 'explicit'] | ['image', 'image', 'explicit'] | Passed |
SHA-256 / 4af30835569503ad14ceb4fb4b028eb79e5fc2819e6d59ecb44bec538aa87510
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(data):
tokens,native,interactive,required,supported = data
known = {'group','link','image','button','article','generic','presentation'}
chosen = None
source = 'native'
for token in tokens.split():
if token not in known: continue
if token == 'presentation' and interactive: continue
if required and token != native: continue
chosen = token
source = 'explicit'
break
if chosen is None: chosen = native
if chosen not in supported:
chosen = native if native in supported else 'generic'
source = 'fallback'
interface = {'link':'action','button':'action','image':'image','article':'container','group':'container'}.get(chosen)
return [chosen,interface,source]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('ordered fallback', solve(['unknown command group link','image',False,False,['group','link','image']],), ['group','container','explicit'])
check('interactive presentation', solve(['presentation link','button',True,False,['presentation','link','button']],), ['link','action','explicit'])
check('required role', solve(['link image','image',False,True,['image','link']],), ['image','image','explicit'])
check('native fallback', solve(['article','image',False,False,['image']],), ['image','image','fallback'])
check('no supported native', solve(['group','image',False,False,[]],), ['generic',None,'fallback'])
check('empty uses native', solve([' '*N,'button',True,False,['button']],), ['button','action','native'])
check('unknown only', solve(['unknown'+str(N),['article','image','button','group','link'][N-1],False,False,['article','image','button','group','link']],), [['article','image','button','group','link'][N-1],['container','image','action','container','action'][N-1],'native'])
check('presentation retained', solve(['presentation','image',False,False,['presentation']],), ['presentation',None,'explicit'])
check('tab separated', solve(['unknown\timage','group',False,False,['image','group']],), ['image','image','explicit'])
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 |
|---|---|---|---|
| ordered fallback | ['group', 'container', 'explicit'] | ['group', 'container', 'explicit'] | Passed |
| interactive presentation | ['link', 'action', 'explicit'] | ['link', 'action', 'explicit'] | Passed |
| required role | ['image', 'image', 'explicit'] | ['image', 'image', 'explicit'] | Passed |
| native fallback | ['image', 'image', 'fallback'] | ['image', 'image', 'fallback'] | Passed |
| no supported native | ['generic', None, 'fallback'] | ['generic', None, 'fallback'] | Passed |
| empty uses native | ['button', 'action', 'native'] | ['button', 'action', 'native'] | Passed |
| unknown only | ['article', 'container', 'native'] | ['article', 'container', 'native'] | Passed |
| presentation retained | ['presentation', None, 'explicit'] | ['presentation', None, 'explicit'] | Passed |
| tab separated | ['image', 'image', 'explicit'] | ['image', 'image', 'explicit'] | Passed |
SHA-256 / 62dbfd865dd63edc6672be20e6f9f324928668fb6ad07de4b88d9517f3febb01
Verification & scope
Stipulated finite adapter contract, not a claim of platform accessibility or ARIA conformance. 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:45:38.393685+00:00.
Case digest / 59696e2154dc55047d430c0669797d2a6909036922e1fc2e76ed36fd1a0b10df