fix(fifa17): a dangling manager ref must not refuse the squad save

Every real squad save was failing with 400 unresolved_wire_ids. Reproduced on
staging with the repo's own seeder, which sends the captured retail body:

  route=squad-replace status=400 outcome=unresolved_wire_ids detail=[[100000427]]

FIFA 17 always sends a manager ref, and on a real profile it does not resolve to
an owned instance. scripts/sold-staging-seed-squad.py already recorded why:
production's own squad points at instance 100000427, which is absent from
production's /club/staff (1975 items spanning 100000001..100004826), and the
client accepts that squad back unchanged -- so the client never validates the
manager against the club, and the pre-0023 server accepted it.

Making the manager ownership-backed (d37a9d5 / 25f4ad1) turned that ref into a
hard refusal, which took out the primary FUT write path: no squad save means no
squad, which means the client will not enter the FUT hub at all.

A manager ref is not a squad slot. An unresolvable PLAYER slot must still refuse
the save -- committing it would silently drop an owned card from the club. An
unresolvable MANAGER ref just means there is no ownership-backed manager, which
is exactly the state before migration 0023: the save commits, the assignment is
cleared as a full replacement should, and the id is reported on
ProposedSquad::unresolved_manager_wire_id so the host can log what it could not
map instead of letting it vanish. A ref that DOES resolve is still assigned and
still authorized against the club.

Verified end to end on staging: the seeder now answers {"id": 0} with 11
occupied slots, the host logs
`manager_ref_unresolved=100000427 (saved with no manager assignment)`, and the
projected squad carries `manager: []`.
This commit is contained in:
funman300
2026-08-21 04:28:43 +00:00
parent 054a912357
commit d6aa704b01
5 changed files with 79 additions and 21 deletions
+14 -5
View File
@@ -316,15 +316,24 @@ mod tests {
assert_eq!(ext.kicktakers[0].index, 0);
}
/// A manager ref that does not resolve must NOT refuse the save: FIFA always
/// sends one, and on a real profile it is dangling (production points at
/// 100000427, absent from its own /club/staff). The save commits with no
/// ownership-backed manager and reports the id it could not map.
#[test]
fn build_refuses_an_unowned_manager() {
// Manager wire id present but NOT resolvable → refused, never assigned a
// manager the club does not own.
fn an_unresolvable_manager_ref_clears_the_assignment_without_refusing() {
let put = parse_squad_put(PUT_F442.as_bytes()).unwrap();
let mut ids = full_resolver().0;
ids.remove(&100000427);
let err = build_squad_write(&put, &MapResolver(ids)).unwrap_err();
assert_eq!(err, SquadBuildError::UnresolvedWireIds(vec![100000427]));
let build = build_squad_write(&put, &MapResolver(ids)).expect("save must still commit");
assert_eq!(build.canonical.manager_owned_card_id, None);
assert_eq!(
build.canonical.unresolved_manager_wire_id,
Some(100000427),
"the ref we could not map is reported, not swallowed"
);
// The starting XI is untouched -- only the manager assignment is dropped.
assert_eq!(build.canonical.slots.len(), 11);
}
#[test]