You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fix Screen Recording permission cache never downgrading after revocation (#29)
The persisted screenCaptureTCCGranted flag seeded the in-process granted
state at launch and could never be cleared, so revoking Screen Recording
in System Settings while Heard wasn't running left the app showing
Granted forever.
Replace the boolean with ScreenCaptureGrantCache, a pure state machine:
a grant cached from a previous session is trusted only for a ~30 s
reconfirmation window after launch (10 poll probes), then cleared if
probes keep failing. A grant confirmed live within a session remains
sticky for the process lifetime, and the authoritative SCShareableContent
check after the Grant… flow now clears a stale cache immediately on a
definitive false.
https://claude.ai/code/session_01UMbvMVowzQq3LgFpaQA8aE
Co-authored-by: Claude <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: handoff.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -54,6 +54,7 @@ All items from the post-v0.2.2 robustness review are now resolved (see `ROADMAP.
54
54
-**Recording self-test + one-shot recovery**: at T+2s, the monitor checks whether non-zero samples have arrived. If silent, it tears down and rebuilds the tap/aggregate/IOProc once with fresh helper-process enumeration. If the rebuild's self-test still fails, the recording is flagged `appAudioTapFailed` and the menu bar shows "Recording (mic only)".
55
55
-**`stopWatching` ends the active meeting**: toggling watching off mid-meeting fires `onMeetingEnded` synchronously so the recording stops and the transcript pipeline runs. `AppModel.stopWatching` preserves the resulting `.processing` phase instead of overwriting it with `.dormant`.
56
56
-**TCC permissions required**: Microphone (`NSMicrophoneUsageDescription`), System Audio Capture (`NSAudioCaptureUsageDescription`), Screen Recording (`NSScreenCaptureUsageDescription`), Accessibility (`NSAccessibilityUsageDescription`) — all four must be granted. Use `./scripts/bundle.sh --reset` to clear all four TCC grants and reinstall cleanly.
57
+
-**Screen Recording grant caching**: the grant persists in UserDefaults (`screenCaptureTCCGranted`) so it survives macOS 15's stale `CGPreflightScreenCaptureAccess()` on fresh launches. The cache is reconfirmed after launch via `ScreenCaptureGrantCache` (pure, tested state machine in `Services.swift`): a grant cached from a previous session is trusted for a ~30 s grace window (10 probes × 3 s poll) and cleared if probes keep failing — covering revocation while the app wasn't running. A grant confirmed live within a session is never downgraded (revocations only take effect after restart); an authoritative `SCShareableContent` false (post-"Grant…" check) clears the cache immediately.
0 commit comments