# The /settings feature gate - live-test script > **CORRECTION, 2026-08-05 evening. Section 1 of this document is FALSE and the > test in section 3 should not be run as written.** > > Section 1 claims `IS_FRIENDLY_SEASON_ENABLED` and `IS_DRAFT_MODE_ENABLED` "have > never been set to true by anything, on any run". They are measured as **1**, on > two separate launches, while `/settings` was answering `{"configs": []}`: > > ``` > disp 0x1fd3a (friendlySeasonsEnabled) value = 1 > disp 0x1fd3d (enableDraftMode) value = 1 > disp 0x1fd45 (packOpeningAnimationEnabled) value = 1 > ``` > > Reproduce with `tools/gate_byte_probe.py` (needs the client at the FUT hub, since > CardsDLL loads only then): it resolves the pid by comm, > re-derives the CardsDLL slide from `/proc//maps`, proves it against the FNV > prologue at `0x180180d00` read from disk, walks the model singleton at > `DAT_1802e6398`, and decodes each displacement out of its accessor stub > (`0f b6 81 `) rather than assuming it. > > **Where the reasoning went wrong.** The finding that `FUN_18011dc50` is the only > writer and that the `FutDataManagerImpl` constructor never touches those bytes was > correct. The inference drawn from it was not. The applier runs whether or not the > configs array has content, and the settings struct it is handed defaults these > fields to 1, so the bytes were being written all along. "Nothing populates the > array" was treated as "nothing writes the byte". Those are different claims and > only the first one was established. > > Seasons therefore does not refuse because its gate byte is false. Its gate byte is > true. The mechanism is still unknown and needs a fresh diagnosis. Everything below > the correction is kept as the record of a wrong turn, not as a plan. Written 2026-08-05, after reversing `FutGetSettingsServerResponse` end to end. Nothing here has been in front of the game yet. The code default is `off`, which serves the exact historical `{"configs": []}`, so the tree is currently at the proven baseline and this test is opt-in. Full schema, atom ids, gate bytes and accessor addresses are in `ENDPOINT_MAP.md` under `FutGetSettingsServerResponse`. This file is only the experiment. --- ## 1. The claim being tested `GET /settings` is requested 11 times a session and has always been answered with an empty array. The array is not decoration: - Each element is `{"type": "", "value": }`. The client hashes the **string value** of `type` through the atom hasher and switches on it, 42 arms wide, so a flag is a row rather than a key. - `FUN_18011dc50` is the **only** writer of the `IS_*` UI gate bytes inside `FutDataManagerImpl`, and every line of it is `byte = (field == 1)`. - The `FutDataManagerImpl` constructor never touches those bytes. The whole 16620-char decompile was scanned for the block; it is absent. So `IS_FRIENDLY_SEASON_ENABLED` and `IS_DRAFT_MODE_ENABLED` have never been set to true by anything, on any run, in the whole history of this project. That is a mechanism for the standing bug in which **Seasons refuses while making zero requests to any of the four servers.** No response shape could ever explain that. A UI key evaluated from a byte nobody wrote does. **The store is the control that makes this readable.** `IS_STORE_ENABLED` is the same kind of byte read the same way, and the store screen works. It works because `storeEnabled` and its siblings already reach the client through the **Blaze** client-config store (`FUT_RS4_CONFIG`). That list contains no seasons flag, no draft flag, no tournament flag. Same mechanism, one populated, one blank. This is a hypothesis with a mechanism, not a demonstrated cause. --- ## 2. Pre-flight, from the terminal, costs nothing ```bash cd fifa17-recon/tools FUT_SETTINGS=gates python3 check_settings_flags.py # expect: 14 rows, PASS python3 check_settings_flags.py # expect: mode=off, PASS ``` The checker asserts every shipped flag name against **both** the atom table and the recovered switch arms. Both are needed: `enableSquadBuildingSetsFeature` is a genuine atom with no arm in this switch, so the atom table alone would wave through a flag that does nothing. A misnamed flag is silently inert and looks exactly like a failed fix, which is the failure mode this guards. --- ## 3. The run Budget: **one launch.** ```bash cd fifa17-recon/tools FUT_SETTINGS=gates ./openfut-fut.sh start ~/Desktop/launch-fifa17.sh ``` Then, in order, and write down what each one does: 1. **Store.** Open it. This is the control and it goes first, because if populating the array broke the store then the applier demonstrably ran and everything after this reads differently. 2. **Transfer list capacity.** Transfers → Transfer List. Read the capacity number. We send `maximumTradePileSize = 77`, a number FUT would never choose on its own. 3. **Seasons.** Single-player Seasons, the exact path that has been refusing. 4. **FUT Draft.** Both the offline and online entries. 5. **Tournaments**, for `tournamentQuitEnabled`. --- ## 4. Reading the result The control in step 2 is what makes a negative result informative, so read it before concluding anything about steps 3 to 5. | Store (1) | Capacity (2) | Seasons (3) | Reading | |---|---|---|---| | works | **77** | opens | Confirmed. The gate was the empty array. Make `gates` the default and move to the `/match` shape, which has been blocked behind this. | | works | **77** | still refuses | The array reached the consumer and the flag was applied, so the gate is **upstream of the UI key**. The settings line is then dead for Seasons and the next move is a live probe of the refusal path, not more response work. This is a real result, not a null one. | | works | not 77 | still refuses | The array never reached the consumer at all. Everything above is untested rather than refuted. Suspect the massinfo `settings` member (the deser's other caller) is what the client actually reads, and check which of the two paths fires in `/tmp/utas.log`. | | **breaks** | any | any | The applier ran and re-asserting the store flags did not hold them. Fall back to `FUT_SETTINGS=keep`, which sends only the already-working flags plus the control. If `keep` also breaks the store, populating the array is harmful in itself and the whole approach is wrong. | `keep` exists precisely so that "populating the array at all" and "the new gates" can be separated without guessing, and it costs one restart to use. --- ## 5. What would make this whole plan wrong **The gate might not be a UI key at all.** Seasons could be refusing on an entitlement, a persona attribute, or a Blaze session property evaluated inside the Denuvo-packed executable, in which case no `/settings` body reaches it. The step-2 control is what tells these apart: it distinguishes "the flag did not help" from "the array was never consumed", and no boolean flag can do that alone. **The store control could be weaker than it looks.** The argument assumes `IS_STORE_ENABLED` currently comes from the Blaze store rather than from a default. If it turns out the store screen does not read that key at all, then it is not a control for anything and the reasoning in §1 loses its anchor. **Draft has a second known suspect.** `GET ut/%s/squad/mode/draft/state` is still answered by the generic `/squad` handler with a full active-squad object, which is a textbook type-desync candidate. If Draft still fails while Seasons opens, that route is the next thing to look at, not the flag. **A negative result here is worth having.** The settings array has been the standing suspect for the greyed-out entry points for two rounds without anyone sending a single flag. Ruling it out costs one launch and removes it from the backlog permanently.