FAILURE MAP
← Case archive

FA-53676 / Accessibility interaction semantics / Open access

Image recognition labels bypass consent · case 01

Image recognition labels bypass consent.

Verified by executionVariant 1 · 9 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The ocr consent decision in the image alternative adapter violates its declared contract.

THE FAILURE

The ocr consent decision in the image alternative adapter violates its declared contract.

Unsuccessful approach: The local repair substitutes if (consent or not alt) and loaded and not broken and ocr: but still mishandles the regression fixtures.

Case contract

Input [decorative,interactive,alt,title,caption,ocr,ocr_consent,filename,loaded,broken]. None alt means absent; empty alt is intentional. Interactive decorative images retain semantics. Source priority is explicit alt (even empty), nonempty caption, title, consented OCR when loaded and not broken; filename is never spoken. Decorative noninteractive images return None. Return [text,source,status] where status is broken, loading, ready with broken highest priority. Normalization strips only surrounding ASCII spaces; OCR is marked inferred.

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):
    decorative,interactive,alt,title,caption,ocr,consent,filename,loaded,broken = data
    if decorative and not interactive: return None
    status = 'broken' if broken else ('ready' if loaded else 'loading')
    if alt is not None: return [alt.strip(' '),'alt',status]
    if caption: return [caption.strip(' '),'caption',status]
    if title: return [title.strip(' '),'title',status]
    if loaded and not broken and ocr: return [ocr.strip(' '),'inferred',status]
    return ['',None,status]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('decorative inert', solve([True,False,None,'title','caption','ocr',True,'file',True,False],), None)
check('decorative interactive', solve([True,True,' Label '+str(N)+' ','title','caption','ocr',True,'file',True,False],), ['Label '+str(N),'alt','ready'])
check('intentional empty', solve([False,False,'','title','caption','ocr',True,'file',True,False],), ['','alt','ready'])
check('caption precedence', solve([False,False,None,'title',' caption ','ocr',True,'file',True,False],), ['caption','caption','ready'])
check('title only', solve([False,False,None,' title ','','ocr',True,'file',False,False],), ['title','title','loading'])
check('OCR inferred', solve([False,False,None,'','',' OCR '+str(N)+' ',True,'file',True,False],), ['OCR '+str(N),'inferred','ready'])
check('unconsented OCR', solve([False,False,None,'','','ocr',False,'file',True,False],), ['',None,'ready'])
check('loading OCR', solve([False,False,None,'','','ocr',True,'file',False,False],), ['',None,'loading'])
check('broken OCR', solve([False,False,None,'','','ocr',True,'file',True,True],), ['',None,'broken'])
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 fixtureActualExpectedOutcome
decorative inertNoneNonePassed
decorative interactive['Label 1', 'alt', 'ready']['Label 1', 'alt', 'ready']Passed
intentional empty['', 'alt', 'ready']['', 'alt', 'ready']Passed
caption precedence['caption', 'caption', 'ready']['caption', 'caption', 'ready']Passed
title only['title', 'title', 'loading']['title', 'title', 'loading']Passed
OCR inferred['OCR 1', 'inferred', 'ready']['OCR 1', 'inferred', 'ready']Passed
unconsented OCR['ocr', 'inferred', 'ready']['', None, 'ready']Failed
loading OCR['', None, 'loading']['', None, 'loading']Passed
broken OCR['', None, 'broken']['', None, 'broken']Passed

SHA-256 / a24a5e2a35e453d1d066fe905452b540d63987e9973f1242298c44b47761853c

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(data):
    decorative,interactive,alt,title,caption,ocr,consent,filename,loaded,broken = data
    if decorative and not interactive: return None
    status = 'broken' if broken else ('ready' if loaded else 'loading')
    if alt is not None: return [alt.strip(' '),'alt',status]
    if caption: return [caption.strip(' '),'caption',status]
    if title: return [title.strip(' '),'title',status]
    if (consent or not alt) and loaded and not broken and ocr: return [ocr.strip(' '),'inferred',status]
    return ['',None,status]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('decorative inert', solve([True,False,None,'title','caption','ocr',True,'file',True,False],), None)
check('decorative interactive', solve([True,True,' Label '+str(N)+' ','title','caption','ocr',True,'file',True,False],), ['Label '+str(N),'alt','ready'])
check('intentional empty', solve([False,False,'','title','caption','ocr',True,'file',True,False],), ['','alt','ready'])
check('caption precedence', solve([False,False,None,'title',' caption ','ocr',True,'file',True,False],), ['caption','caption','ready'])
check('title only', solve([False,False,None,' title ','','ocr',True,'file',False,False],), ['title','title','loading'])
check('OCR inferred', solve([False,False,None,'','',' OCR '+str(N)+' ',True,'file',True,False],), ['OCR '+str(N),'inferred','ready'])
check('unconsented OCR', solve([False,False,None,'','','ocr',False,'file',True,False],), ['',None,'ready'])
check('loading OCR', solve([False,False,None,'','','ocr',True,'file',False,False],), ['',None,'loading'])
check('broken OCR', solve([False,False,None,'','','ocr',True,'file',True,True],), ['',None,'broken'])
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 fixtureActualExpectedOutcome
decorative inertNoneNonePassed
decorative interactive['Label 1', 'alt', 'ready']['Label 1', 'alt', 'ready']Passed
intentional empty['', 'alt', 'ready']['', 'alt', 'ready']Passed
caption precedence['caption', 'caption', 'ready']['caption', 'caption', 'ready']Passed
title only['title', 'title', 'loading']['title', 'title', 'loading']Passed
OCR inferred['OCR 1', 'inferred', 'ready']['OCR 1', 'inferred', 'ready']Passed
unconsented OCR['ocr', 'inferred', 'ready']['', None, 'ready']Failed
loading OCR['', None, 'loading']['', None, 'loading']Passed
broken OCR['', None, 'broken']['', None, 'broken']Passed

SHA-256 / 8657204dbd0ff385af11dbda02864dc5112b31a2ea1b5a54e58e916409b7458d

HELD IN THE MEMBER ARCHIVE

The verified repair and its recorded checks are member-only.

This mechanism has 9 recorded checks per implementation. The open-access tier publishes the failure and the unsuccessful fix; the repaired source that passes every check, and the observations that prove it, are available to members.

Every case sharing this mechanism uses the same contract and the same repair, so this one record is held back for all of them.

Member access is invitation-based. Sign in with your invited account to inspect the repair.

Sign in to the archive ↗

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:41.410638+00:00.

Case digest / 36b3f228656e3c18f42a92d670f0e9e725ef607a72801c9fa939ad79d2186110