You make Nat46 part of the OS network stack.
You make nat64 part of the typical router.
> I ask because when I visit [0] in Firefox on a Linux system with both globally-routable IPv6 and locally-routable IPv4 addresses configured, I see a TCP conversation with the remote IPv4 address 192.168.2.2. When I remove the IPv4 address (and the IPv4 default route) from the local host, I get immediate failures... neither v4 nor v6 traffic is made.
Yes, that's the failure of ipv6 deployment.
Imagine you have two vlans, one ipv4 only, one ipv6 only. There's a router sitting across both vlans.
VLAN1 - ipv6 only
Router 2001::1
Device A 2001::1234
VLAN2 - ipv4 only
Router 192.168.1.1
Device B 192.168.1.2
Device A pings 192.168.1.2, the OS converts that transparently to ::ffff:192.168.1.2, it sends it to its default router 2001::1
That router does a 6>4 translation, converting the destination to 192.168.1.2 and the source to 192.168.1.1 (or however it's configured)
It maintains the protocol/port/address in its state as any ipv4 natting router would do, and the response is "unnatted" as an "established connection" (with connection also applying for icmp/udp as v4 nat does today)
An application on Device A has no need to be ipv6 aware. The A record in DNS which resolves to 192.168.1.2 is reachable from device A despite it not having a V4 address. The hard coded IP database in it works fine.
Now if Device B wants to reach Device A, it uses traditional port forwarding on the router, where 192.168.1.1:80 is forwarded to [2001::1234]:80, with source of ::ffff:192.168.1.2
With this in place, there is no need to update any applications, and certainly no need for dual stack.
The missing bits are the lack of common 64/46 natting -- I don't believe it's built into the normal linux network chain like v4 nat is, and the lack of transparent upgrading of v4 handling on an OS level.