Edit: Wow. I mistyped a bunch the first time around. Hopefully nobody read that. All corrected now. /edit
I went code spelunking… 🙂
Short version, the workaround would be this:
<?php
$front_page_id = get_option( 'page_on_front' );
$my_permalink = _get_page_link( $front_page_id );
?>
If you look into link-template.php in the WordPress core, you can kind of trace the path that happens. Calling the_permalink() leads to get_page_link(), which returns the permalink of the post/page ID you pass it. However, one of the checks that get_page_link() does is to see if the requested ID is currently set as ‘page_on_front’. If it is, a static value of “https://wordpress.stackexchange.com/” is returned as the permalink. If it’s not, the function _get_page_link() is called instead. Note the underscore on the front of the function.
In order to solve the issue, I cut past the_permalink() and get_page_link() and went straight to _get_page_link().
There may be some security issue or reason for this behavior to be default that I’m not aware of, but it works…