# Python Retirement Readiness (post-P1) Classification of every Python component still present. Evidence: prod-host `owner=` dispatch log (OBSERVED), AuxServiceMap/PythonContractMap scouts, container `entrypoint.sh`. **P2 rollback stays hot regardless** (do NOT remove rollback-to-python-p2.sh, :p2-rollback image b1b929953f, profile 39bb3e83). ## A. LIVE PRODUCTION REQUIRED (still owns behavior in the live flow) | Component | Role | Rust status | Retire when | |---|---|---|---| | oracle utas_server.py (:8199) NON-ECONOMY | **remaining**: user/club rename, non-active squad/, draft/*, mode-gated leaderboards + /sbs/* | **Most non-economy migrated 2026-08-17** (account/sync, auth, userMassInfo, user, clientdata, hub, club/stats/*, settings, accountinfo, phishing, match/reset, leaderboards/options, watchList, static acks, item-defs (item/resource,defid), marketdata (+/pricelimits), and the flag-off empty reads season/tournament/champion/clubUser/user/list → `{}` — all Rust). See PRODUCTION_AUTHORITY_MATRIX | remaining tail is mutation (user/club), no-Core-model (squad/), or unimplemented modes (draft/leaderboards/sbs) | | blaze_responder_v3b.py (:42130 Blaze) | FUT Blaze transport | Rust openfut-blaze-host COMPLETE, gate-proven (Gate 10) | container cutover (operator-gated deploy) | | blaze_responder_v3b.py (:42127 redirector TLS) | first-hop TLS redirect | Rust openfut-redirector-host COMPLETE (OpenSSL) | container cutover + cert consistency | | roster_server.py (:8081) | roster-update XML | Rust openfut-roster-host COMPLETE (unit-only) | container cutover | | pow_server.py (:8094/:8080) | Proof-of-Work / content | NO Rust crate; 58 templates, bodies un-reversed | needs Rust host + body RE (BLOCKED) | ## B. ORACLE ONLY (reference / differential, not production authority) - utas_server.py economy handlers: now oracle-only (economy is Rust; Python economy hits = 0). Used by `economy_differential.rs` as the parity oracle. KEEP. - fut_store.py / fut_accounts.py / fut_consumables.py: reference models + Ghidra-derived taxonomy source. KEEP. ## C. MIGRATION TOOL ONLY (offline) - scripts/*.py (seed_fifa17_cards.py, utas-observe/mutate/diff, check-*). KEEP (dev tooling). - fifa17-recon/tools/db_dump.py etc.: table extraction. KEEP. ## D. ROLLBACK ONLY (hot, DO NOT REMOVE) - rollback-to-python-p2.sh; image openfut-fut-backend:p2-rollback (b1b929953f) + :dev; profile 39bb3e83; compose/env backup; tuple OPENFUT_SERVERS="blaze roster utas pow". ## E. DEAD (advertised but not followed in current FIFA17 flow) - Nucleus /connect/token stub (:42131): 0 live hits across Gate 5-10 (client never POSTs). Keep the ADVERTISED URL so the client can't reach real EA, but no migration needed. No Rust listener required. - fifa-blaze (FIFA23 capture stub), openfut-bridge (FIFA23): retired lineage, not in FIFA17 flow. ## Retirement gating 1. **Mostly DONE (2026-08-17)**: account/sync, ut/auth (Rust SID mint), userMassInfo (full), clientdata, club/stats/{country,league,team}, watchList, static acks, the flag-off empty reads (season/tournament/champion/clubUser/user/list → `{}`), item-defs (item/resource,defid), and marketdata (+/pricelimits, container-type-exact) migrated + deployed. **Remaining on Python**: user/club rename (mutating; needs a Core write), non-active squad/ (no multi-squad Core model), and the unimplemented modes draft/* + leaderboards + /sbs/* (need the mode logic ported, not a proxy). 2. Deploy Rust blaze/roster/redirector via container cutover (operator-gated) — then those Python responders are class D/E only. 3. POW: build Rust host + reverse bodies (largest blocker) OR keep Python POW as class A indefinitely. 4. Only after a long stable window: consider retiring the P2 rollback (separate explicit decision — NOT now).