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?
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, ISPs hand out entire /64 per customer (at a minimum, almost all will give you larger subnets if you ask). This allows you to have a separate IP address per application, which can be allocated from an unfirewalled pool.
There's also the fact that almost all major OSs now come with sane firewall defaults, also allowing applications to punch holes via APIs. (You could also have done this with IPv4 if it had a larger address space.)
If you spend some time thinking about how to solve these problems with IPv6, you will find that there are lots of ways to do it that are simpler and far more secure.