Issues / #129

hydraheadflatscreen: proactively request all TCC permissions on first run / after update

open bug Project: hydraheadflatscreen Reporter: 15 May 2026 12:57

Description

## Problem

TCC permissions (microphone) are currently only requested at the moment a voice-enabled experience is first streamed. This causes two bugs:

1. **Backup binary TCC prompt**: During self-update, the old binary is kept as `.backup`. If the backup binary is ever executed (e.g. rollback path, or prior test run), macOS treats it as a new identity and shows a separate TCC dialog. This dialog blocks the kiosk display and cannot be dismissed remotely (no Accessibility TCC). The requesting process can even be dead while the dialog persists.

2. **Mid-stream prompts**: If the mic permission has never been granted, the first mercator-talks stream triggers the TCC prompt mid-stream, overlaying the experience for the visitor.

## Expected behaviour

On first launch (or after an update that changes the binary identity), hydraheadflatscreen should proactively trigger all TCC permissions it needs by briefly exercising them before the kiosk grid appears:

- **Microphone**: open + immediately close an AudioQueue input at startup to trigger the TCC prompt while the kiosk is loading (not mid-stream).

Additionally, the self-update flow should NOT execute the `.backup` binary under any circumstance - rollback should be a file copy operation, not a process launch.

## Steps to reproduce (current session)

1. hydraheadflatscreen updated itself, creating `.hydranode/bin/hydraheadflatscreen.backup`
2. Backup binary was executed at some point (update rollback path or manual)
3. macOS prompted "hydraheadflatscreen.backup" would like to access the Microphone
4. Dialog persisted even after backup binary died and after `tccutil reset Microphone` and killing tccd
5. Dialog blocked the kiosk display - only physical click dismisses it

## Fix scope

- `internal/cli/run.go`: add startup TCC pre-flight that opens + closes an AudioQueue input
- Self-update path: ensure `.backup` binary is never exec'd, only used as file-level rollback