FAILURE MAP
← Case archive

FA-35181 / Notification interfaces / Open access

Sensitive notification preview redaction: confirmation-accepted from updated-reveal-pending · case 01

The confirmation-accepted event leaves a notification in revealed instead of revealed-updated.

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

ROOT CAUSE

Confirmation shows the pre-update sensitive preview.

VERIFIED REPAIR

Commit the updated-reveal-pending / confirmation-accepted transition to revealed-updated; preserve the other explicitly stipulated transitions.

Unsuccessful approach: Keeping redacted ignores approval of the current revision.

Case contract

Sensitive notification preview redaction is a bounded visual-notification workflow with mutable policy state {'secret': 'message', 'rendered': 'message', 'revision': 1, 'approved': 0, 'locked': False}. Its default transition relation is {('revealed', 'screen-locked'): 'redacting', ('redacting', 'redaction-applied'): 'redacted', ('redacted', 'reveal-click'): 'reveal-pending', ('reveal-pending', 'confirmation-accepted'): 'revealed', ('reveal-pending', 'confirmation-denied'): 'redacted', ('revealed', 'sensitive-update'): 'redacting-update', ('redacting-update', 'redaction-applied'): 'redacted-updated', ('redacted-updated', 'reveal-click'): 'updated-reveal-pending', ('updated-reveal-pending', 'confirmation-accepted'): 'revealed-updated', ('reveal-pending', 'screen-locked'): 'redacted'}; domain inputs can suppress or redirect transitions and update policy fields, as specified in solve. Different-generation events are inert. Batches apply in order. Optional observe returns the selected policy field alongside the phase.

Why this case matters

Visual notification lifecycle ordering can leave an inbox or toast showing the wrong actionable state even when transport succeeds.

1 / The failure

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

N = 1
observations = []
def solve(initial, events, generation, payload=None, observe=None):
    table = {('revealed', 'screen-locked'): 'redacting', ('redacting', 'redaction-applied'): 'redacted', ('redacted', 'reveal-click'): 'reveal-pending', ('reveal-pending', 'confirmation-accepted'): 'revealed', ('reveal-pending', 'confirmation-denied'): 'redacted', ('revealed', 'sensitive-update'): 'redacting-update', ('redacting-update', 'redaction-applied'): 'redacted-updated', ('redacted-updated', 'reveal-click'): 'updated-reveal-pending', ('updated-reveal-pending', 'confirmation-accepted'): 'revealed', ('reveal-pending', 'screen-locked'): 'redacted'}
    data = json.loads(json.dumps({'secret': 'message', 'rendered': 'message', 'revision': 1, 'approved': 0, 'locked': False})) if payload is None else {**json.loads(json.dumps({'secret': 'message', 'rendered': 'message', 'revision': 1, 'approved': 0, 'locked': False})), **json.loads(json.dumps(payload))}
    state = initial
    for delivery in events:
        event, event_generation = delivery[:2]
        arg = delivery[2] if len(delivery) > 2 else {}
        if event_generation == generation:
            previous = state
            if event == 'screen-locked': data['locked'] = True
            if event == 'sensitive-update':
                data['revision'] += 1
                data['secret'] = arg.get('text','updated')
            if event == 'confirmation-accepted':
                if data['locked'] or arg.get('revision',data['revision']) != data['revision']: event = 'confirmation-denied'
                else: data['approved'] = data['revision']
            state = table.get((state, event), state)
            if state in ('redacted','redacted-updated','redacting','redacting-update','hidden'): data['rendered'] = None
            if state in ('revealed','revealed-updated'): data['rendered'] = data['secret']
    return {'phase': state, 'value': data[observe]} if observe else state
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('revealed / screen-locked', solve('revealed', [('screen-locked', N)], N), 'redacting')
check('redacting / redaction-applied', solve('redacting', [('redaction-applied', N)], N), 'redacted')
check('redacted / reveal-click', solve('redacted', [('reveal-click', N)], N), 'reveal-pending')
check('reveal-pending / confirmation-accepted', solve('reveal-pending', [('confirmation-accepted', N)], N), 'revealed')
check('reveal-pending / confirmation-denied', solve('reveal-pending', [('confirmation-denied', N)], N), 'redacted')
check('revealed / sensitive-update', solve('revealed', [('sensitive-update', N)], N), 'redacting-update')
check('redacting-update / redaction-applied', solve('redacting-update', [('redaction-applied', N)], N), 'redacted-updated')
check('redacted-updated / reveal-click', solve('redacted-updated', [('reveal-click', N)], N), 'updated-reveal-pending')
check('updated-reveal-pending / confirmation-accepted', solve('updated-reveal-pending', [('confirmation-accepted', N)], N), 'revealed-updated')
check('reveal-pending / screen-locked', solve('reveal-pending', [('screen-locked', N)], N), 'redacted')
check('older notification incarnation', solve('revealed', [('screen-locked', N - 1)], N), 'revealed')
check('future notification incarnation', solve('revealed', [('screen-locked', N + 1)], N), 'revealed')
check('unknown event is inert', solve('revealed', [('unknown-event', N)], N), 'revealed')
check('empty delivery batch', solve('revealed', [], N), 'revealed')
check('N stale deliveries before current delivery', solve('revealed', [('screen-locked', N - 1)] * N + [('screen-locked', N)], N), 'redacting')
check('trace screen-locked then redaction-applied', solve('revealed', [('screen-locked', N), ('redaction-applied', N)], N), 'redacted')
check('trace redaction-applied then reveal-click', solve('redacting', [('redaction-applied', N), ('reveal-click', N)], N), 'reveal-pending')
check('trace reveal-click then confirmation-accepted', solve('redacted', [('reveal-click', N), ('confirmation-accepted', N)], N), 'revealed')
check('trace reveal-click then confirmation-denied', solve('redacted', [('reveal-click', N), ('confirmation-denied', N)], N), 'redacted')
check('trace reveal-click then screen-locked', solve('redacted', [('reveal-click', N), ('screen-locked', N)], N), 'redacted')
check('trace confirmation-accepted then screen-locked', solve('reveal-pending', [('confirmation-accepted', N), ('screen-locked', N)], N), 'redacting')
check('trace confirmation-accepted then sensitive-update', solve('reveal-pending', [('confirmation-accepted', N), ('sensitive-update', N)], N), 'redacting-update')
check('trace confirmation-denied then reveal-click', solve('reveal-pending', [('confirmation-denied', N), ('reveal-click', N)], N), 'reveal-pending')
check('trace sensitive-update then redaction-applied', solve('revealed', [('sensitive-update', N), ('redaction-applied', N)], N), 'redacted-updated')
check('trace redaction-applied then reveal-click', solve('redacting-update', [('redaction-applied', N), ('reveal-click', N)], N), 'updated-reveal-pending')
check('trace reveal-click then confirmation-accepted', solve('redacted-updated', [('reveal-click', N), ('confirmation-accepted', N)], N), 'revealed-updated')
check('trace screen-locked then reveal-click', solve('reveal-pending', [('screen-locked', N), ('reveal-click', N)], N), 'reveal-pending')
check('domain state regression 1: rendered', solve('revealed', [('screen-locked', N, {})], N, {}, 'rendered'), {'phase': 'redacting', 'value': None})
check('domain state regression 2: rendered', solve('reveal-pending', [('confirmation-accepted', N, {})], N, {'locked': True, 'rendered': None}, 'rendered'), {'phase': 'redacted', 'value': None})
check('domain state regression 3: approved', solve('reveal-pending', [('confirmation-accepted', N, {'revision': 0})], N, {'rendered': None}, 'approved'), {'phase': 'redacted', 'value': 0})
check('domain state regression 4: rendered', solve('reveal-pending', [('confirmation-accepted', N, {'revision': 1})], N, {'rendered': None}, 'rendered'), {'phase': 'revealed', 'value': 'message'})
check('domain state regression 5: rendered', solve('revealed', [('sensitive-update', N, {'text': 'new secret'})], N, {}, 'rendered'), {'phase': 'redacting-update', 'value': None})
check('domain state regression 6: rendered', solve('updated-reveal-pending', [('confirmation-accepted', N, {'revision': 2})], N, {'revision': 2, 'secret': 'new', 'rendered': None}, 'rendered'), {'phase': 'revealed-updated', 'value': 'new'})
check('domain state regression 7: rendered', solve('revealed', [('sensitive-update', N, {'text': 'replacement'}), ('redaction-applied', N, {}), ('reveal-click', N, {}), ('confirmation-accepted', N, {'revision': 2})], N, {}, 'rendered'), {'phase': 'revealed-updated', 'value': 'replacement'})
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
revealed / screen-lockedredactingredactingPassed
redacting / redaction-appliedredactedredactedPassed
redacted / reveal-clickreveal-pendingreveal-pendingPassed
reveal-pending / confirmation-acceptedrevealedrevealedPassed
reveal-pending / confirmation-deniedredactedredactedPassed
revealed / sensitive-updateredacting-updateredacting-updatePassed
redacting-update / redaction-appliedredacted-updatedredacted-updatedPassed
redacted-updated / reveal-clickupdated-reveal-pendingupdated-reveal-pendingPassed
updated-reveal-pending / confirmation-acceptedrevealedrevealed-updatedFailed
reveal-pending / screen-lockedredactedredactedPassed
older notification incarnationrevealedrevealedPassed
future notification incarnationrevealedrevealedPassed
unknown event is inertrevealedrevealedPassed
empty delivery batchrevealedrevealedPassed
N stale deliveries before current deliveryredactingredactingPassed
trace screen-locked then redaction-appliedredactedredactedPassed
trace redaction-applied then reveal-clickreveal-pendingreveal-pendingPassed
trace reveal-click then confirmation-acceptedrevealedrevealedPassed
trace reveal-click then confirmation-deniedredactedredactedPassed
trace reveal-click then screen-lockedredactedredactedPassed
trace confirmation-accepted then screen-lockedredactingredactingPassed
trace confirmation-accepted then sensitive-updateredacting-updateredacting-updatePassed
trace confirmation-denied then reveal-clickreveal-pendingreveal-pendingPassed
trace sensitive-update then redaction-appliedredacted-updatedredacted-updatedPassed
trace redaction-applied then reveal-clickupdated-reveal-pendingupdated-reveal-pendingPassed
trace reveal-click then confirmation-acceptedrevealedrevealed-updatedFailed
trace screen-locked then reveal-clickreveal-pendingreveal-pendingPassed
domain state regression 1: rendered{'phase': 'redacting', 'value': None}{'phase': 'redacting', 'value': None}Passed
domain state regression 2: rendered{'phase': 'redacted', 'value': None}{'phase': 'redacted', 'value': None}Passed
domain state regression 3: approved{'phase': 'redacted', 'value': 0}{'phase': 'redacted', 'value': 0}Passed
domain state regression 4: rendered{'phase': 'revealed', 'value': 'message'}{'phase': 'revealed', 'value': 'message'}Passed
domain state regression 5: rendered{'phase': 'redacting-update', 'value': None}{'phase': 'redacting-update', 'value': None}Passed
domain state regression 6: rendered{'phase': 'revealed', 'value': 'new'}{'phase': 'revealed-updated', 'value': 'new'}Failed
domain state regression 7: rendered{'phase': 'revealed', 'value': 'replacement'}{'phase': 'revealed-updated', 'value': 'replacement'}Failed

SHA-256 / 236cfa2b4ba3701f28604604817e0c52b25070d90647bc69f096a0e714a822d6

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(initial, events, generation, payload=None, observe=None):
    table = {('revealed', 'screen-locked'): 'redacting', ('redacting', 'redaction-applied'): 'redacted', ('redacted', 'reveal-click'): 'reveal-pending', ('reveal-pending', 'confirmation-accepted'): 'revealed', ('reveal-pending', 'confirmation-denied'): 'redacted', ('revealed', 'sensitive-update'): 'redacting-update', ('redacting-update', 'redaction-applied'): 'redacted-updated', ('redacted-updated', 'reveal-click'): 'updated-reveal-pending', ('updated-reveal-pending', 'confirmation-accepted'): 'redacted-updated', ('reveal-pending', 'screen-locked'): 'redacted'}
    data = json.loads(json.dumps({'secret': 'message', 'rendered': 'message', 'revision': 1, 'approved': 0, 'locked': False})) if payload is None else {**json.loads(json.dumps({'secret': 'message', 'rendered': 'message', 'revision': 1, 'approved': 0, 'locked': False})), **json.loads(json.dumps(payload))}
    state = initial
    for delivery in events:
        event, event_generation = delivery[:2]
        arg = delivery[2] if len(delivery) > 2 else {}
        if event_generation == generation:
            previous = state
            if event == 'screen-locked': data['locked'] = True
            if event == 'sensitive-update':
                data['revision'] += 1
                data['secret'] = arg.get('text','updated')
            if event == 'confirmation-accepted':
                if data['locked'] or arg.get('revision',data['revision']) != data['revision']: event = 'confirmation-denied'
                else: data['approved'] = data['revision']
            state = table.get((state, event), state)
            if state in ('redacted','redacted-updated','redacting','redacting-update','hidden'): data['rendered'] = None
            if state in ('revealed','revealed-updated'): data['rendered'] = data['secret']
    return {'phase': state, 'value': data[observe]} if observe else state
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('revealed / screen-locked', solve('revealed', [('screen-locked', N)], N), 'redacting')
check('redacting / redaction-applied', solve('redacting', [('redaction-applied', N)], N), 'redacted')
check('redacted / reveal-click', solve('redacted', [('reveal-click', N)], N), 'reveal-pending')
check('reveal-pending / confirmation-accepted', solve('reveal-pending', [('confirmation-accepted', N)], N), 'revealed')
check('reveal-pending / confirmation-denied', solve('reveal-pending', [('confirmation-denied', N)], N), 'redacted')
check('revealed / sensitive-update', solve('revealed', [('sensitive-update', N)], N), 'redacting-update')
check('redacting-update / redaction-applied', solve('redacting-update', [('redaction-applied', N)], N), 'redacted-updated')
check('redacted-updated / reveal-click', solve('redacted-updated', [('reveal-click', N)], N), 'updated-reveal-pending')
check('updated-reveal-pending / confirmation-accepted', solve('updated-reveal-pending', [('confirmation-accepted', N)], N), 'revealed-updated')
check('reveal-pending / screen-locked', solve('reveal-pending', [('screen-locked', N)], N), 'redacted')
check('older notification incarnation', solve('revealed', [('screen-locked', N - 1)], N), 'revealed')
check('future notification incarnation', solve('revealed', [('screen-locked', N + 1)], N), 'revealed')
check('unknown event is inert', solve('revealed', [('unknown-event', N)], N), 'revealed')
check('empty delivery batch', solve('revealed', [], N), 'revealed')
check('N stale deliveries before current delivery', solve('revealed', [('screen-locked', N - 1)] * N + [('screen-locked', N)], N), 'redacting')
check('trace screen-locked then redaction-applied', solve('revealed', [('screen-locked', N), ('redaction-applied', N)], N), 'redacted')
check('trace redaction-applied then reveal-click', solve('redacting', [('redaction-applied', N), ('reveal-click', N)], N), 'reveal-pending')
check('trace reveal-click then confirmation-accepted', solve('redacted', [('reveal-click', N), ('confirmation-accepted', N)], N), 'revealed')
check('trace reveal-click then confirmation-denied', solve('redacted', [('reveal-click', N), ('confirmation-denied', N)], N), 'redacted')
check('trace reveal-click then screen-locked', solve('redacted', [('reveal-click', N), ('screen-locked', N)], N), 'redacted')
check('trace confirmation-accepted then screen-locked', solve('reveal-pending', [('confirmation-accepted', N), ('screen-locked', N)], N), 'redacting')
check('trace confirmation-accepted then sensitive-update', solve('reveal-pending', [('confirmation-accepted', N), ('sensitive-update', N)], N), 'redacting-update')
check('trace confirmation-denied then reveal-click', solve('reveal-pending', [('confirmation-denied', N), ('reveal-click', N)], N), 'reveal-pending')
check('trace sensitive-update then redaction-applied', solve('revealed', [('sensitive-update', N), ('redaction-applied', N)], N), 'redacted-updated')
check('trace redaction-applied then reveal-click', solve('redacting-update', [('redaction-applied', N), ('reveal-click', N)], N), 'updated-reveal-pending')
check('trace reveal-click then confirmation-accepted', solve('redacted-updated', [('reveal-click', N), ('confirmation-accepted', N)], N), 'revealed-updated')
check('trace screen-locked then reveal-click', solve('reveal-pending', [('screen-locked', N), ('reveal-click', N)], N), 'reveal-pending')
check('domain state regression 1: rendered', solve('revealed', [('screen-locked', N, {})], N, {}, 'rendered'), {'phase': 'redacting', 'value': None})
check('domain state regression 2: rendered', solve('reveal-pending', [('confirmation-accepted', N, {})], N, {'locked': True, 'rendered': None}, 'rendered'), {'phase': 'redacted', 'value': None})
check('domain state regression 3: approved', solve('reveal-pending', [('confirmation-accepted', N, {'revision': 0})], N, {'rendered': None}, 'approved'), {'phase': 'redacted', 'value': 0})
check('domain state regression 4: rendered', solve('reveal-pending', [('confirmation-accepted', N, {'revision': 1})], N, {'rendered': None}, 'rendered'), {'phase': 'revealed', 'value': 'message'})
check('domain state regression 5: rendered', solve('revealed', [('sensitive-update', N, {'text': 'new secret'})], N, {}, 'rendered'), {'phase': 'redacting-update', 'value': None})
check('domain state regression 6: rendered', solve('updated-reveal-pending', [('confirmation-accepted', N, {'revision': 2})], N, {'revision': 2, 'secret': 'new', 'rendered': None}, 'rendered'), {'phase': 'revealed-updated', 'value': 'new'})
check('domain state regression 7: rendered', solve('revealed', [('sensitive-update', N, {'text': 'replacement'}), ('redaction-applied', N, {}), ('reveal-click', N, {}), ('confirmation-accepted', N, {'revision': 2})], N, {}, 'rendered'), {'phase': 'revealed-updated', 'value': 'replacement'})
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
revealed / screen-lockedredactingredactingPassed
redacting / redaction-appliedredactedredactedPassed
redacted / reveal-clickreveal-pendingreveal-pendingPassed
reveal-pending / confirmation-acceptedrevealedrevealedPassed
reveal-pending / confirmation-deniedredactedredactedPassed
revealed / sensitive-updateredacting-updateredacting-updatePassed
redacting-update / redaction-appliedredacted-updatedredacted-updatedPassed
redacted-updated / reveal-clickupdated-reveal-pendingupdated-reveal-pendingPassed
updated-reveal-pending / confirmation-acceptedredacted-updatedrevealed-updatedFailed
reveal-pending / screen-lockedredactedredactedPassed
older notification incarnationrevealedrevealedPassed
future notification incarnationrevealedrevealedPassed
unknown event is inertrevealedrevealedPassed
empty delivery batchrevealedrevealedPassed
N stale deliveries before current deliveryredactingredactingPassed
trace screen-locked then redaction-appliedredactedredactedPassed
trace redaction-applied then reveal-clickreveal-pendingreveal-pendingPassed
trace reveal-click then confirmation-acceptedrevealedrevealedPassed
trace reveal-click then confirmation-deniedredactedredactedPassed
trace reveal-click then screen-lockedredactedredactedPassed
trace confirmation-accepted then screen-lockedredactingredactingPassed
trace confirmation-accepted then sensitive-updateredacting-updateredacting-updatePassed
trace confirmation-denied then reveal-clickreveal-pendingreveal-pendingPassed
trace sensitive-update then redaction-appliedredacted-updatedredacted-updatedPassed
trace redaction-applied then reveal-clickupdated-reveal-pendingupdated-reveal-pendingPassed
trace reveal-click then confirmation-acceptedredacted-updatedrevealed-updatedFailed
trace screen-locked then reveal-clickreveal-pendingreveal-pendingPassed
domain state regression 1: rendered{'phase': 'redacting', 'value': None}{'phase': 'redacting', 'value': None}Passed
domain state regression 2: rendered{'phase': 'redacted', 'value': None}{'phase': 'redacted', 'value': None}Passed
domain state regression 3: approved{'phase': 'redacted', 'value': 0}{'phase': 'redacted', 'value': 0}Passed
domain state regression 4: rendered{'phase': 'revealed', 'value': 'message'}{'phase': 'revealed', 'value': 'message'}Passed
domain state regression 5: rendered{'phase': 'redacting-update', 'value': None}{'phase': 'redacting-update', 'value': None}Passed
domain state regression 6: rendered{'phase': 'redacted-updated', 'value': None}{'phase': 'revealed-updated', 'value': 'new'}Failed
domain state regression 7: rendered{'phase': 'redacted-updated', 'value': None}{'phase': 'revealed-updated', 'value': 'replacement'}Failed

SHA-256 / 44c86daf68e2076e0a491a8e0436786ec3dd67c384ca94eb6ee013611137f464

3 / The verified repair

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

N = 1
observations = []
def solve(initial, events, generation, payload=None, observe=None):
    table = {('revealed', 'screen-locked'): 'redacting', ('redacting', 'redaction-applied'): 'redacted', ('redacted', 'reveal-click'): 'reveal-pending', ('reveal-pending', 'confirmation-accepted'): 'revealed', ('reveal-pending', 'confirmation-denied'): 'redacted', ('revealed', 'sensitive-update'): 'redacting-update', ('redacting-update', 'redaction-applied'): 'redacted-updated', ('redacted-updated', 'reveal-click'): 'updated-reveal-pending', ('updated-reveal-pending', 'confirmation-accepted'): 'revealed-updated', ('reveal-pending', 'screen-locked'): 'redacted'}
    data = json.loads(json.dumps({'secret': 'message', 'rendered': 'message', 'revision': 1, 'approved': 0, 'locked': False})) if payload is None else {**json.loads(json.dumps({'secret': 'message', 'rendered': 'message', 'revision': 1, 'approved': 0, 'locked': False})), **json.loads(json.dumps(payload))}
    state = initial
    for delivery in events:
        event, event_generation = delivery[:2]
        arg = delivery[2] if len(delivery) > 2 else {}
        if event_generation == generation:
            previous = state
            if event == 'screen-locked': data['locked'] = True
            if event == 'sensitive-update':
                data['revision'] += 1
                data['secret'] = arg.get('text','updated')
            if event == 'confirmation-accepted':
                if data['locked'] or arg.get('revision',data['revision']) != data['revision']: event = 'confirmation-denied'
                else: data['approved'] = data['revision']
            state = table.get((state, event), state)
            if state in ('redacted','redacted-updated','redacting','redacting-update','hidden'): data['rendered'] = None
            if state in ('revealed','revealed-updated'): data['rendered'] = data['secret']
    return {'phase': state, 'value': data[observe]} if observe else state
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('revealed / screen-locked', solve('revealed', [('screen-locked', N)], N), 'redacting')
check('redacting / redaction-applied', solve('redacting', [('redaction-applied', N)], N), 'redacted')
check('redacted / reveal-click', solve('redacted', [('reveal-click', N)], N), 'reveal-pending')
check('reveal-pending / confirmation-accepted', solve('reveal-pending', [('confirmation-accepted', N)], N), 'revealed')
check('reveal-pending / confirmation-denied', solve('reveal-pending', [('confirmation-denied', N)], N), 'redacted')
check('revealed / sensitive-update', solve('revealed', [('sensitive-update', N)], N), 'redacting-update')
check('redacting-update / redaction-applied', solve('redacting-update', [('redaction-applied', N)], N), 'redacted-updated')
check('redacted-updated / reveal-click', solve('redacted-updated', [('reveal-click', N)], N), 'updated-reveal-pending')
check('updated-reveal-pending / confirmation-accepted', solve('updated-reveal-pending', [('confirmation-accepted', N)], N), 'revealed-updated')
check('reveal-pending / screen-locked', solve('reveal-pending', [('screen-locked', N)], N), 'redacted')
check('older notification incarnation', solve('revealed', [('screen-locked', N - 1)], N), 'revealed')
check('future notification incarnation', solve('revealed', [('screen-locked', N + 1)], N), 'revealed')
check('unknown event is inert', solve('revealed', [('unknown-event', N)], N), 'revealed')
check('empty delivery batch', solve('revealed', [], N), 'revealed')
check('N stale deliveries before current delivery', solve('revealed', [('screen-locked', N - 1)] * N + [('screen-locked', N)], N), 'redacting')
check('trace screen-locked then redaction-applied', solve('revealed', [('screen-locked', N), ('redaction-applied', N)], N), 'redacted')
check('trace redaction-applied then reveal-click', solve('redacting', [('redaction-applied', N), ('reveal-click', N)], N), 'reveal-pending')
check('trace reveal-click then confirmation-accepted', solve('redacted', [('reveal-click', N), ('confirmation-accepted', N)], N), 'revealed')
check('trace reveal-click then confirmation-denied', solve('redacted', [('reveal-click', N), ('confirmation-denied', N)], N), 'redacted')
check('trace reveal-click then screen-locked', solve('redacted', [('reveal-click', N), ('screen-locked', N)], N), 'redacted')
check('trace confirmation-accepted then screen-locked', solve('reveal-pending', [('confirmation-accepted', N), ('screen-locked', N)], N), 'redacting')
check('trace confirmation-accepted then sensitive-update', solve('reveal-pending', [('confirmation-accepted', N), ('sensitive-update', N)], N), 'redacting-update')
check('trace confirmation-denied then reveal-click', solve('reveal-pending', [('confirmation-denied', N), ('reveal-click', N)], N), 'reveal-pending')
check('trace sensitive-update then redaction-applied', solve('revealed', [('sensitive-update', N), ('redaction-applied', N)], N), 'redacted-updated')
check('trace redaction-applied then reveal-click', solve('redacting-update', [('redaction-applied', N), ('reveal-click', N)], N), 'updated-reveal-pending')
check('trace reveal-click then confirmation-accepted', solve('redacted-updated', [('reveal-click', N), ('confirmation-accepted', N)], N), 'revealed-updated')
check('trace screen-locked then reveal-click', solve('reveal-pending', [('screen-locked', N), ('reveal-click', N)], N), 'reveal-pending')
check('domain state regression 1: rendered', solve('revealed', [('screen-locked', N, {})], N, {}, 'rendered'), {'phase': 'redacting', 'value': None})
check('domain state regression 2: rendered', solve('reveal-pending', [('confirmation-accepted', N, {})], N, {'locked': True, 'rendered': None}, 'rendered'), {'phase': 'redacted', 'value': None})
check('domain state regression 3: approved', solve('reveal-pending', [('confirmation-accepted', N, {'revision': 0})], N, {'rendered': None}, 'approved'), {'phase': 'redacted', 'value': 0})
check('domain state regression 4: rendered', solve('reveal-pending', [('confirmation-accepted', N, {'revision': 1})], N, {'rendered': None}, 'rendered'), {'phase': 'revealed', 'value': 'message'})
check('domain state regression 5: rendered', solve('revealed', [('sensitive-update', N, {'text': 'new secret'})], N, {}, 'rendered'), {'phase': 'redacting-update', 'value': None})
check('domain state regression 6: rendered', solve('updated-reveal-pending', [('confirmation-accepted', N, {'revision': 2})], N, {'revision': 2, 'secret': 'new', 'rendered': None}, 'rendered'), {'phase': 'revealed-updated', 'value': 'new'})
check('domain state regression 7: rendered', solve('revealed', [('sensitive-update', N, {'text': 'replacement'}), ('redaction-applied', N, {}), ('reveal-click', N, {}), ('confirmation-accepted', N, {'revision': 2})], N, {}, 'rendered'), {'phase': 'revealed-updated', 'value': 'replacement'})
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
revealed / screen-lockedredactingredactingPassed
redacting / redaction-appliedredactedredactedPassed
redacted / reveal-clickreveal-pendingreveal-pendingPassed
reveal-pending / confirmation-acceptedrevealedrevealedPassed
reveal-pending / confirmation-deniedredactedredactedPassed
revealed / sensitive-updateredacting-updateredacting-updatePassed
redacting-update / redaction-appliedredacted-updatedredacted-updatedPassed
redacted-updated / reveal-clickupdated-reveal-pendingupdated-reveal-pendingPassed
updated-reveal-pending / confirmation-acceptedrevealed-updatedrevealed-updatedPassed
reveal-pending / screen-lockedredactedredactedPassed
older notification incarnationrevealedrevealedPassed
future notification incarnationrevealedrevealedPassed
unknown event is inertrevealedrevealedPassed
empty delivery batchrevealedrevealedPassed
N stale deliveries before current deliveryredactingredactingPassed
trace screen-locked then redaction-appliedredactedredactedPassed
trace redaction-applied then reveal-clickreveal-pendingreveal-pendingPassed
trace reveal-click then confirmation-acceptedrevealedrevealedPassed
trace reveal-click then confirmation-deniedredactedredactedPassed
trace reveal-click then screen-lockedredactedredactedPassed
trace confirmation-accepted then screen-lockedredactingredactingPassed
trace confirmation-accepted then sensitive-updateredacting-updateredacting-updatePassed
trace confirmation-denied then reveal-clickreveal-pendingreveal-pendingPassed
trace sensitive-update then redaction-appliedredacted-updatedredacted-updatedPassed
trace redaction-applied then reveal-clickupdated-reveal-pendingupdated-reveal-pendingPassed
trace reveal-click then confirmation-acceptedrevealed-updatedrevealed-updatedPassed
trace screen-locked then reveal-clickreveal-pendingreveal-pendingPassed
domain state regression 1: rendered{'phase': 'redacting', 'value': None}{'phase': 'redacting', 'value': None}Passed
domain state regression 2: rendered{'phase': 'redacted', 'value': None}{'phase': 'redacted', 'value': None}Passed
domain state regression 3: approved{'phase': 'redacted', 'value': 0}{'phase': 'redacted', 'value': 0}Passed
domain state regression 4: rendered{'phase': 'revealed', 'value': 'message'}{'phase': 'revealed', 'value': 'message'}Passed
domain state regression 5: rendered{'phase': 'redacting-update', 'value': None}{'phase': 'redacting-update', 'value': None}Passed
domain state regression 6: rendered{'phase': 'revealed-updated', 'value': 'new'}{'phase': 'revealed-updated', 'value': 'new'}Passed
domain state regression 7: rendered{'phase': 'revealed-updated', 'value': 'replacement'}{'phase': 'revealed-updated', 'value': 'replacement'}Passed

SHA-256 / ae4e9b83520af29f595fdf49b76d6f548581a6922645c7888aa4af3d353c74af

Verification & scope

Stipulated single-notification state and policy model only. Event delivery and acknowledgements are explicit test inputs. No DOM, accessibility announcements, live timers, networking, actual rendering, or production-platform conformance is simulated. 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:42:39.094517+00:00.

Case digest / ee8fabd80eb5fa00e798d02f495c97fc69f5852b72afdd7235963f65b4725f7d