Fix the model and unit
The lab represents synthetic work in an in-memory FIFO queue. Each item is one work unit without an amount, counterparty, or financial message. Twenty initial items arrived at time minus five. Maintenance starts at zero and lasts ten minutes. Four items arrive at the start of each slot; after the pause, eight may be processed, completing at the slot’s end. This convention is part of the exercise and must accompany results. FIFO is not presented as a Swift requirement. The code uses deque to retain order and connects to no banking infrastructure.
Calculate required headroom
Forty new items accumulate during the pause, leaving sixty. Afterward, four arrive per minute while eight are processed. Net headroom is four, so draining takes fifteen minutes and total elapsed time is twenty-five. Dividing sixty by eight would ignore continuing arrivals. With capacity equal to four, backlog stops growing but does not shrink in this model. For sixty-one items, reserve sixteen complete slots. The function uses Fraction and upward rounding so the final item does not disappear through estimate truncation. These values are teaching assumptions without any measurement of Swift capacity.
Examine sensitivity and limits
Increasing arrivals to six changes two terms: eighty items accumulate during the pause, and only two per minute remain for recovery. Total time becomes fifty minutes. Increasing only the pause to twelve minutes while retaining four arrivals produces sixty-eight items and seventeen draining minutes, totaling twenty-nine. A small technical delay can therefore create a larger functional delay. The projection assumes constant rates and equivalent work. Bursts, retries, priorities, blocking, and downstream consumers require their own modelling and measurements. The PM should bring these assumptions to the meeting instead of presenting one number as a guarantee.
Observe age and preserve identities
At minute ten, the oldest item is fifteen minutes old. The first eight finish at eleven, the next eight at twelve, and the final four original items at thirteen, aged eighteen. Total backlog still exists at minute twenty and only clears at twenty-five. The report distinguishes these milestones and uses no age value when no items remain. It also confirms one hundred twenty completed identities: twenty initial items plus one hundred arrivals. Equal counts can conceal a duplicate and a missing item, so compare sets. Completing simulator work means neither settlement nor acceptance of a real message.
Demonstrate recovery to business
In a fictional APS incident, the process returns at minute ten, but the local agreement requires current data, known outcomes, and backlog within its limit. If the functional target is fifteen minutes, the twenty-five-minute scenario misses that commitment. Reporting should preserve the distinction and assign owners to unknowns. NIST reconstitution guidance distinguishes data and functionality validation; it serves here as a general reference without imposing a banking rule. Check the next stage too: eight items per minute in the first consumer are insufficient if final confirmation manages only five. The criterion should match the outcome actually promised.
Execute and transfer the reasoning
Reserve fifteen minutes to predict balances and ages, twenty to run and change a rate, fifteen to explain the difference, and ten to prepare an English note. The complete program records forty-one checks with Python version and code hash. It also includes the next lesson’s evidence criteria. Calculated rates do not replace representative authorized testing. Swift states that ITB performance and availability are not equivalent to production and excludes performance or stress testing there. Saving assumptions and limits alongside results lets another colleague repeat the analysis without turning invented numbers into an SLA.
"""DR original synthetic queue and change-evidence exercises, Python 3.13.
python3 run.py --output evidence.json
No Swift network, production benchmark, CSCF implementation or real approval.
Rates, timings, evidence labels and readiness gates are teaching assumptions.
"""
import argparse
from collections import deque
from fractions import Fraction
import hashlib
import json
import math
from pathlib import Path
import sys
checks=[]
def check(name,actual,expected):
assert actual==expected,(name,actual,expected)
checks.append(dict(name=name,actual=actual,expected=expected,passed=True))
def drain_minutes(backlog,arrivals,capacity):
if min(backlog,arrivals,capacity)<0:raise ValueError('negative input')
if backlog==0:return 0
if capacity<=arrivals:return None
return math.ceil(Fraction(backlog,capacity-arrivals))
def simulate(initial,initial_at,arrivals,capacities):
# Each slot is [t,t+1): arrivals at t, FIFO processing finishes at t+1.
# A processed work item is NOT a settled financial transaction.
if initial_at>0 or min(initial,arrivals,*capacities)<0:raise ValueError('invalid schedule')
queue=deque((f'old-{i}',initial_at) for i in range(initial))
trace=[];done=[]
for t,capacity in enumerate(capacities):
queue.extend((f'new-{t}-{i}',t) for i in range(arrivals))
processed=[]
for _ in range(min(capacity,len(queue))):
identity,entered=queue.popleft
processed.append(dict(id=identity,entered=entered,finished=t+1,age=t+1-entered))
done.extend(processed)
trace.append(dict(end=t+1,backlog=len(queue),processed=len(processed),oldestAge=t+1-queue[0][1] if queue else None))
return dict(trace=trace,done=done,pending=list(queue))
def reuse_candidate(assessor_agrees,significant_change,uncovered_control_change,prior_reuses):
# Models public FAQ prerequisites only; True is not a compliance decision.
return assessor_agrees and not significant_change and not uncovered_control_change and prior_reuses==0
def evidence_binding(candidate,report):
# Original conservative local gate, not a Swift-mandated record format.
return all(candidate[k]==report[k] for k in ('build','environment','footprint','controls')) and report['observed'] is True
def recovery_gate(service_up,reference_current,observations_complete,backlog,limit,owner_accepts):
return service_up and reference_current and observations_complete and backlog<=limit and owner_accepts
def main:
check('maintenance accumulation',20+4*10,60)
check('net drain rate',8-4,4)
check('drain duration',drain_minutes(60,4,8),15)
check('total recovery duration',10+drain_minutes(60,4,8),25)
check('rounded drain duration',drain_minutes(61,4,8),16)
check('equal capacity cannot drain',drain_minutes(60,4,4),None)
check('lower capacity cannot drain',drain_minutes(60,4,3),None)
check('empty backlog needs no drain',drain_minutes(0,4,8),0)
check('higher arrivals extend recovery',10+drain_minutes(20+6*10,6,8),50)
check('longer maintenance extends recovery',12+drain_minutes(20+4*12,4,8),29)
base=simulate(20,-5,4,[0]*10+[8]*15)
check('queue at maintenance end',base['trace'][9]['backlog'],60)
check('oldest age at maintenance end',base['trace'][9]['oldestAge'],15)
check('first resumed slot backlog',base['trace'][10]['backlog'],56)
check('queue still present at minute twenty',base['trace'][19]['backlog'],20)
check('queue clear at minute twenty five',base['trace'][24]['backlog'],0)
check('empty queue has no oldest age',base['trace'][24]['oldestAge'],None)
check('processed identities unique',len({x['id'] for x in base['done']}),120)
check('all expected work accounted',len(base['done'])+len(base['pending']),20+4*25)
check('first original item completes',base['done'][0]['finished'],11)
check('maximum item age',max(x['age'] for x in base['done']),18)
check('fifo original work first',all(x['id'].startswith('old-') for x in base['done'][:20]),True)
check('fast component does not meet functional target',10<=15 and 25>15,True)
check('local latest rollback start',40-12-8-5,15)
check('local rollback boundary allowed',15+12+8+5<=40,True)
check('one minute delay misses local boundary',16+12+8+5<=40,False)
check('reuse prerequisite set satisfied',reuse_candidate(True,False,False,0),True)
check('assessor agreement missing',reuse_candidate(False,False,False,0),False)
check('significant footprint change prevents reuse',reuse_candidate(True,True,False,0),False)
check('uncovered control change prevents reuse',reuse_candidate(True,False,True,0),False)
check('second consecutive reuse prevented',reuse_candidate(True,False,False,1),False)
candidate=dict(build='dr-7',environment='QUALIFICATION',footprint='fp-2',controls='scope-3')
report={**candidate,'observed':True}
check('matching evidence binding',evidence_binding(candidate,report),True)
for key in candidate:
check('changed '+key+' invalidates local binding',evidence_binding(candidate,{**report,key:'different'}),False)
check('planned evidence is insufficient',evidence_binding(candidate,{**report,'observed':False}),False)
check('complete local recovery gate',recovery_gate(True,True,True,0,0,True),True)
check('running process alone insufficient',recovery_gate(True,False,False,20,0,False),False)
check('unknown observations prevent closure',recovery_gate(True,True,False,0,0,True),False)
check('backlog limit prevents closure',recovery_gate(True,True,True,1,0,True),False)
check('acceptance authority still required',recovery_gate(True,True,True,0,0,False),False)
evidence=dict(scope='Original deterministic FIFO and local evidence models, not production capacity, Swift traffic, security compliance, institutional approval or financial settlement.',python=sys.version.split[0],runnerSha256=hashlib.sha256(Path(__file__).read_bytes).hexdigest,passed=len(checks),checks=checks)
parser=argparse.ArgumentParser;parser.add_argument('--output',required=True)
Path(parser.parse_args.output).write_text(json.dumps(evidence,indent=2)+'\n')
print(json.dumps({'passed':len(checks),'scope':evidence['scope']}))
if __name__=='__main__':main
Case: extending the pause from ten to twelve minutes increases total recovery from 25 to 29. The two additional minutes also create backlog to drain.
Common pitfalls
Dividing backlog by gross capacity; resetting age on recovery; counting replays as new completions; inferring production capacity from ITB.
Related topics: States, reconciliation, and recovery without duplication · Security scope and independent evidence · Continuity and operational handover
Recovery requires net capacity and observable functional criteria, with explicit identities, times, assumptions, and authority.
Reference: Python collections: deque · BigSavant Swift knowledge assessment2026.10; independent professional curriculum