Verify factor identity again after recovery mutation
All checks were successful
Authentication acceptance / acceptance (push) Successful in 1m6s
Authentication acceptance / provider-contract (push) Successful in 12s

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a092fe-13b1-7f12-ac74-7d258af4d79c
This commit is contained in:
tegwick 2026-09-13 17:30:23 +02:00
parent 3b7df9047e
commit 4d893ed3c2
3 changed files with 10 additions and 2 deletions

View file

@ -35,7 +35,7 @@ def recover(store, request):
store.record(base,expected,False) # An audit outage prevents mutation.
store.disable(request['user'],request['serial'],expected)
current=store.snapshot(request['user'],request['serial'])
if current is None or current['active']:raise RecoveryError('readback_failed')
if current is None or current['active'] or fingerprint(dict(current,active=True))!=expected:raise RecoveryError('readback_failed')
store.record(base,expected,True)
return dict(base,status='recovered',changes_applied=True,replayed=False)

View file

@ -45,3 +45,11 @@ class RecoveryTests(unittest.TestCase):
def test_replaced_inactive_factor_cannot_replay_old_recovery(self):
r=self.approval();recover(self.store,r);self.store.state['id']=2
with self.assertRaises(RecoveryError):recover(self.store,r)
def test_replacement_after_disable_cannot_report_success(self):
original=self.store.disable
def replace_after_disable(*args):
original(*args);self.store.state['id']=2
self.store.disable=replace_after_disable
with self.assertRaisesRegex(RecoveryError,'readback_failed'):recover(self.store,self.approval())
self.assertFalse(self.store.rows['support-1']['complete'])