You can’t use
wp_redirect or make HTTP redirects from inside a shortcode, redirects must happen before HTTP headers are sent out, before any HTML is sent to the browser, so shortcodes will always be too late.
So I looked around and I believe the problem is that some content is sent to the browser before the redirection happens, but I can’t find what it is.
The site header, the opening HTML tag, it’s not specifically post content, but any output of any kind. It doesn’t matter if your call to
add_shortcode happens before that, because it’s when the shortcode appears that matters, aka when the content is rendered.
Fundamentally, there is no way to fix this shortcode, and a shortcode can never be used to do this via PHP.
Instead, you should be performing this check on an action that happens before any HTML/output is made. Shortcodes are far too late.