E allora i dati ti arrivavano in UTF8, ma tu usavi il latin nel content-type.
Il charset deve essere coerente OVUNQUE, basta un componente che "parli" diversamente per far saltare tutto.
Nelle tue varie prove non hai mai usato la combinazione giusta, di norma l'utf8_decode() non ci sarebbe bisogno di usarlo, a meno di situazioni molto particolari in cui non hai controllo sui charset dei vari componenti.