Honestly ISPs really missed an opportunity to essentially provide IPv6-only as a service and add an IPv4 compatibility layer to that (IPv6 already has a mechanism built in for this but grandma’s old laptop might not fully support it so you might need a local router provided by the ISP to give you native local IPv4 that allows you to access the internet) instead of CGNAT. But they chose to go with duct tape, spit, paper clips, and hope instead of investing in the correct solution. Shame on them and too bad for us.
And it's simply not true that there is no NAT in the wild with IPv6: every OPNsense installation with two uplinks and the need for anything better than an "arbitrary and uncontrollable" choice of the correct uplink for each outbound connection needs network prefix translation, as the residential dual-homing story for IPv6 is vaporware otherwise. NPT is used not for address space conservation, but to defer the decision about the correct source address to the router that has the knowledge of the correct policy.
And in this sense, IPv6 is worse than IPv4: there are too many people assuming no firewall and no NAT for IPv6, and designing their applications based on these almost-working (but de-facto now broken) premises. The correct premises are the same as for IPv4.
It might work better with UDP but I don't think those firewalls boxes tear down the mapping immediately on getting an RST - they wait until it times out.
NAT Behavioural Requirements for Unicast UDP, https://datatracker.ietf.org/doc/html/rfc4787
NAT Behavioural Requirements for TCP, https://datatracker.ietf.org/doc/html/rfc5382
TIL, thank you! I've been looking for this for quite a while after hearing it indirectly referenced recently, but only found host-side specifications for TCP simultaneous open.
Do you happen to know if common firewalls and NATs support it? If they do, I really wonder why TCP hole punching isn't more common.