CustomerAddress.id is genuinely optional (Services/ApiModels.swift:46) —
some address book entries have no id. AddressesView.selectAddress sets
appState.address.selectedId = address.id directly with no fallback, so
picking one of those addresses leaves selectedId nil. The matching
cascade in both CartView and CheckoutView+Logic then skipped straight to
a label match, which silently collides whenever two addresses share an
empty or duplicate label (common for unnamed entries), and finally fell
back to addresses.first — always redisplaying whatever's first in the
list regardless of what was tapped, with no error surfaced anywhere.
Coordinates are set immediately and reliably at selection time and are
far less likely to collide than a label. Checkout already had a lat/lng
fallback but ordered after the weak label match; promoted it ahead of
label matching in both files, and added the same fallback to Cart, which
didn't have one at all.
Cart's delivery fee and Checkout's address validation both fetched the
customer profile without forcing a cache refresh (2h TTL), then let that
possibly-stale address book unconditionally overwrite the just-picked
appState.address coordinates before building the fee/validation payload.
Result: changing the address on Home didn't reliably move the cart's
delivery fee, and Checkout's 'Alterar' could silently revert to the old
address when the stale coordinates made the backend report it as not
served.
Force-refresh the profile fetch and only use it to fill genuine gaps in
appState.address, never to override a live user selection.