The most reliable way is to rely on your system firewall to prompt you to open up a port when an application binds to it (which can be accomplished with the default firewall software on a modern system.) Again, this is technically possible with IPv4 too, it's just impractical due to address space limitations.
> there is no protocol that allows me to allocate addresses per application on a central home router
Correct. But the whole point it to take the router out of the loop for this, and only use it as a coarse firewall. With IPv6 very device gets a separate /64, so it can simply allocate from its own pool of 10^19 addresses.
> And applications punching holes via APIs does exist in uPnP and NAT-PMP, but isn't that the same thing as what you dismissed above as a hack?
Not the same. With IPv6, you do not need to coordinate across multiple NAT devices (or even worse if you're double/triple NATted as in some countries.) You're also not limited by the maximum NAT table sizes (again amplified in the double/triple NATted situations.) Since each system has 10^19 addresses (preallocated out of a global pool of 10^38 addresses), these can now be treated as system resources and managed intelligently by the kernel.
I don't trust, and doubt I'll ever trust, the firewall on my Smart TV, even if it had one. That's because I don't trust that it'll ever receive timely security updates. So I must use [the firewall on] a central router.
I think applications communicating with firewalling is not a hack, but applications communicating with routing is a hack. E.g. I have two friends who share a house (and therefore an internet connection) and I can play a game with one or other of them (via uPnP) but not both at the same time. With IPv6 + uPnP (assuming that's supported), they'd still have the same firewalling they have now, but I'd be able to play a game with both of them. No?
For example, a single IP address per application would be fine, but there is no protocol that allows me to allocate addresses per application on a central home router such that I can then identify them to permit them individually.
And applications punching holes via APIs does exist in uPnP and NAT-PMP, but isn't that the same thing as what you dismissed above as a hack?