Files
OpenFUT/docs/OVERNIGHT_HANDOFF_2026-08-17.md
T
funman300 42fd3c7e90 core: deploy correctness fixes (SBC exploit + economy TOCTOU) + docs
Bump openfut-core gitlink to 68d1065 (correctness fixes: SBC duplicate-card
exploit, non-atomic economy CAS guards, season/checkin panics, sbc_submissions
club_id migration 0019). Deployed to prod-core (DB migration ver 18 -> 19).

Add docs/CORE_CORRECTNESS_ISSUES.md (audit + Resolution) and
docs/OVERNIGHT_HANDOFF_2026-08-17.md.
2026-08-17 16:01:27 +00:00

11 KiB

Overnight session handoff — 2026-08-17

Autonomous session while you slept. Low-ceremony per your instruction. Everything below is verified as noted; nothing was committed or pushed (see Uncommitted work).

TL;DR

  1. Production promotion completed (you chose "promotion"): prod-host swapped to the post-P1 build, content-gap imported. Then I migrated the remaining Python UTAS routes that have a known contract to Rust: account/sync, ut/auth (SID mint), userMassInfo (full), clientdata, club/stats/{country,league,team}, and the trivial static acks. The client's observed FUT-hub/economy flow is now fully Rust; a tail of lower-traffic routes without a captured wire shape (item-defs, user-identity, watchList/marketdata, non-active squad/<n>, draft, and mode-gated season/tournament/champion/leaderboards/sbs) still proxy to the Python oracle.
  2. Launcher redesigned to a shareholder-grade egui UI (your headline ask). Builds clean; screenshots captured.
  3. New docs: MATCH_LIFECYCLE.md (you asked), CORE_CORRECTNESS_ISSUES.md (4 known Core bugs + 1 bonus exploit, ready to fix on your go/no-go).
  4. Nothing committed — all work is in the working tree for your review (git state is delicate: preserved-dirty Core submodule + a concurrent funman300 actor + detached launcher branch; I didn't want to entangle that unsupervised).

What's live in production now (10.10.0.120:8099)

Thing State
prod-host binary post-P1 fda40d12 + my migration rebuild (release, in target/release/openfut-utas-host)
prod-host pid 3207781 (hub-managed, restart=no; retained spec points at the rebuilt binary)
Catalog 9f6addaa (post-P1)
Core content (cards) 136d8d68 (post-P1, +18 content-gap defs) → Core loads 1710 defs
Core owned 1982 (1962 players + 17 consumables + 3 staff)
Coins 29,876,776 (baseline — reset from the P1 test value when the content-gap DB was swapped in; you said data isn't precious)
prod-core fixed build from canonical submodule (fbb54ea + 4 correctness fixes), DB migrated ver 18 → 19; binary now /home/alex/OpenFUT/target/release/openfut-core
UTAS routes (Rust) economy, club, squad (0/active/list/PUT), account/sync, ut/auth, userMassInfo, user, clientdata, hub, settings, accountinfo, leaderboards/options, match/reset, phishing, club/stats/{year,consumables,staff,country,league,team}, watchList, static acks (store/keepalive/captcha/tfa/livemessage/activeMessage)
Still Python (:8199) item-defs (item/resource, defid), club-identity (clubUser, user/list, user/club), squad/<n> (n≠0), draft, marketdata, mode-gated (season/tournament/champion/leaderboards/sbs → {} while off), and match CREATE/READY/PLAY. See docs/PRODUCTION_AUTHORITY_MATRIX.md.

Smoke-verified live in prod (in the prod netns): all migrated routes return owner=RUST, coins consistent, clientdata round-trips, club/stats context modes emit distinct nation/league/team buckets. Scripts: /home/alex/openfut-promotion/economy-2026-08-17-p2/{p2_precheck,smoke_migrated,smoke_clubstats}.py.

Changes made (all verified: builds clean, tests green)

1. Production promotion (deployed)

  • Host binary e5be8730 (P1) → fda40d12 (post-P1) + catalog 9f6addaa.
  • Content-gap DB swapped in (owned 1962 → 1982). Backups in /home/alex/openfut-promotion/economy-2026-08-17-p2/backup/ + ROLLBACK.txt.

2. Route migration to Rust (deployed, rebuilt binary)

  • POST /ut/auth — Rust mints the SID (OPENFUT-SID-{:016X}), opens the Rust session, adopts persona from body. No Python. (+ /ut/delete/auth.)
  • POST /openfut/account/sync — full Rust envelope; coins/unopenedPacks from Core.
  • GET /userMassInfofull Rust envelope (was a Python-proxy+overlay hybrid).
  • GET/PUT /clientdata/<key> — new host ClientDataStore (JSON-persisted).
  • GET /club/stats/{country,league,team} — made club_stats_body context-aware (nation/league/team buckets); classify now routes all club/stats/* to Rust.
  • GET /squad/0 — routed to the Rust active-squad projection (verified structurally identical to Python squad/0: same 15 keys, players=23).
  • GET /watchList (+ no-op add/remove) — empty list + authoritative Core credits.
  • Static acks (store, match/keepalive, captcha, tfa, livemessage, activeMessage) — Rust constants (StaticAck route), byte-identical to the oracle.
  • Captured the remaining routes' Python wire shapes as reference fixtures for later migration: docs/evidence/route-shapes-2026-08-17/ (user, defs, marketdata, clubUser, watchList, squad/0, season/tournament/champion/sbs, draft).
  • Files: openfut-utas-host/src/{lib.rs,clientdata_store.rs(new),config.rs}, openfut-adapter-fifa17/src/fut/{non_economy.rs,club_stats.rs}, openfut-utas-host/tests/economy_integration.rs.
  • Tests: openfut-utas-host + openfut-adapter-fifa17 full suites GREEN (188 adapter + 76 host lib + all integration incl the 116s economy integration).

3. Launcher redesign + polish + live account panel (built, NOT deployed — client tool)

  • Redesign: new openfut-launcher/src/theme.rs design system (palette, embedded fonts, egui Visuals/Style, card/pill helpers). Branded hero header (OF monogram), left nav rail, card-based dashboard with status pills, prominent accent Launch CTA, console-style Logs. All existing launch/health/preflight/service/config logic preserved.
  • Polish: OpenFUT window/taskbar icon (OF monogram IconData), Config tab rebuilt into themed cards, consistency sweep.
  • Live "Your Club" panel (new feature): a background AccountMonitor (mirrors HealthMonitor, 5s poll, non-blocking) fetches the account summary and the Dashboard shows a "Your Club" card — club name/abbr, Manager, COINS hero number, Level + XP bar, unopened packs, account funds — with clean loading/offline/error states.
  • Builds clean (0 warnings). Screenshots preserved (for your shareholder demo) in /home/alex/openfut-post-p1/launcher-screenshots-2026-08-17/launcher_account.png (the populated "Your Club" card: COINS 29,876,776, Level 12, packs 3) is the headline; plus dashboard/setup/logs/config + the offline state. All reviewed — product-quality.
  • Files: openfut-launcher/src/{theme.rs(new),account_monitor.rs(new),app.rs,main.rs, account_sync.rs,config.rs} + assets/ (fonts + icon). All additive; behavior preserved.

4. Core correctness fixes (deployed 2026-08-17)

All four CORE_CORRECTNESS_ISSUES.md classes fixed in the canonical openfut-core submodule and deployed to prod-core (see that doc's "Resolution" section):

  • Issue 3 (HIGH, exploit): SBC duplicate-card free-reward — submit_sbc now dedups ids + bounds the list (MAX_SBC_CARDS=30) → BadRequest. Regression test added.
  • Issue 2 (HIGH): non-atomic economy mutations — closed the concurrency-exploit races with single-statement compare-and-swap (spend_coins conditional debit, open_pack/buy_listing/sell_card/checkin claim-then-act). Multi-statement partial-failure edges (buy_pack, concurrent SBC, match/season chains) left as documented residual — need the transaction refactor, negligible for single-player.
  • Issue 4 (LOW): season.rs .expect() panics → graceful AppError; checkin index % 7.rem_euclid(7).
  • Issue 1 (LOW): sbc_submissions.club_id — migration 0019 (add + backfill) + submit_sbc binds it; milestone query now correct.
  • Verified: Core suite 179 green + clippy clean; migration dry-run on a prod-DB copy; post-deploy prod migration ver 19, owned 1982, coins 29,876,776, all Core + host endpoints 200. Rollback: backup/prod-core.preCoreFix.db (ver 18) + old binary path — see backup/ROLLBACK_CORE_FIX.txt.

New / updated docs

  • docs/MATCH_LIFECYCLE.md (NEW) — consolidated FUT match loop design (CREATE→READY→ PLAY→END), contracts, reward policy, ownership split, blockers. (You asked for this.)
  • docs/CORE_CORRECTNESS_ISSUES.md (NEW) — 4 known Core bugs + 1 bonus SBC duplicate-card exploit, each with file:line + concrete fix + severity. Needs your go/no-go (fixing bumps Core off the frozen P1 reference).
  • docs/PRODUCTION_AUTHORITY_MATRIX.md (UPDATED) — reflects the completed migration.
  • Vault 06 Agent Memory/Current Priorities.md (UPDATED).

Uncommitted work — needs your review

I committed nothing (git state is delicate: openfut-core is intentionally preserved-dirty; a concurrent funman300 actor; launcher on detached HEAD d1a71bd). Review + commit these when you're ready:

  • Superproject (mine): openfut-utas-host/src/{lib.rs,config.rs}, openfut-utas-host/src/clientdata_store.rs, openfut-utas-host/tests/{economy_integration.rs,host_test.rs}, openfut-adapter-fifa17/src/fut/{club_stats.rs,non_economy.rs}, docs/{PRODUCTION_AUTHORITY_MATRIX.md,MATCH_LIFECYCLE.md,CORE_CORRECTNESS_ISSUES.md,OVERNIGHT_HANDOFF_2026-08-17.md,PYTHON_RETIREMENT_PLAN.md}, and the reference fixtures docs/evidence/route-shapes-2026-08-17/.
  • Launcher submodule (mine): src/{app.rs,main.rs,theme.rs(new),account_monitor.rs(new),account_sync.rs,config.rs}, assets/ (fonts + icon).
  • Leave the pre-existing dirt alone (not mine): CLAUDE.md, README.md, .env.example, docker-compose.yml, AGENTS.md, setup.sh, openfut-bridge, fifa17-recon/docker/..., docs/{ARCHITECTURE,ROADMAP,docker,fifa17-emulation}.md, docs/research/, scripts/utas-filter-diff.py.
  • openfut-core (mine, this session): migrations/0019_sbc_submissions_club_id.sql (new), src/services/{sbc.rs,club.rs,pack.rs,market.rs,checkin.rs,season.rs}, tests/integration_test.rs. Built + deployed to prod-core; still detached HEAD at fbb54ea (edits uncommitted, per your branch strategy).

Open decisions for you

  1. Core correctness bugsDONE (2026-08-17): all four classes fixed + deployed to prod-core (see "Core correctness fixes" above and the Resolution section of docs/CORE_CORRECTNESS_ISSUES.md). prod-core is now off the frozen P1 point, running fbb54ea + fixes at migration ver 19. Residual (documented): the multi-statement transaction refactor for partial-failure atomicity — negligible for single-player; do it if/when concurrency matters.
  2. Match handshake legs (CREATE/READY/PLAY) — the only routes still on Python. Deferred: no match has ever been played in-game, READY items contract unknown, FUT_MODES off (see docs/MATCH_LIFECYCLE.md). Migrating them risks the economy /match/end routing for a never-exercised path — I judged it not worth it unmonitored.
  3. Aux service container cutover (blaze/redirector/roster → Rust) — operator-gated container change; unchanged.

Rollback (still hot)

  • Python P2 image openfut-fut-backend:p2-rollback (b1b929953f) + profile 39bb3e83 + rollback-to-python-p2.sh.
  • prod-host P1 binary + P1 catalog backed up in /home/alex/openfut-promotion/economy-2026-08-17-p2/backup/ (see ROLLBACK.txt).
  • prod state (pre-content-gap) backed up: backup/prod-core.preB.db, prod-identity.preB.json, plus P1 fifa17-production-{catalog,cards}.p1.json.