
Je Mac-app krijgt microfoontoegang — en vergeet die bij elke start weer
GeekBye vroeg om microfoontoegang, je gaf die, en het werkte. Volgende start: weg. En de app verscheen nooit in Systeeminstellingen → Microfoon. De boosdoener was een macOS-beveiligingsfunctie die de app stiekem draaide vanaf een pad dat verdwijnt — hier is de diagnose en de oplossing met één prompt.
Hier is een bug die je aan je eigen ogen doet twijfelen. Je installeert GeekBye, hij vraagt om microfoontoegang, je klikt op Sta toe, en transcriptie werkt. Mooi. Je sluit af, opent hem de volgende ochtend weer — en hij vraagt opnieuw om microfoontoegang. Je gaat naar Systeeminstellingen → Privacy en beveiliging → Microfoon om het handmatig op te lossen, en GeekBye staat er niet eens in. Niet geweigerd. Niet toegestaan. Gewoon afwezig, alsof hij het nooit heeft gevraagd.
Elk afzonderlijk onderdeel zag er correct uit. De prompt was echt. De toestemming werkte op dat moment. De app was correct ondertekend en genotariseerd met de juiste gebruiksteksten. En toch verdampte de toestemming bij elke start. GeekBye v2.0.6 loste het op — en de grondoorzaak is een van de sluwste dingen die macOS doet om je te beschermen.
De functie die de app voor zichzelf verborg
De boosdoener is macOS App Translocation, een Gatekeeper-beveiligingsfunctie. Wanneer je een app downloadt en hem rechtstreeks vanaf de DMG of vanuit je ~/Downloads-map draait — overal waar hij nog "in quarantaine" staat — draait macOS hem niet echt vanaf de plek waar je hem ziet. Het kopieert hem transparant naar een willekeurig, alleen-lezen pad diep onder /private/var/folders/.../AppTranslocation/… en draait die kopie. Het is een goede verdediging: het voorkomt dat een kwaadaardige download knoeit met bestanden ernaast.
Maar hier zit de botsing. Het rechtensysteem van macOS (TCC — het ding dat bijhoudt wie je microfoon, camera en scherm mag gebruiken) identificeert een app op basis van zijn pad en code-identiteit. Wanneer de app getransloceerd is, is dat pad willekeurig en tijdelijk. Dus wanneer je microfoontoegang verleent, registreert macOS de toestemming plichtsgetrouw — tegen een pad dat er de volgende start niet meer zal zijn. Heropen de app, macOS transloceert hem naar een ander willekeurig pad, ziet een app waar het geen gegevens van heeft, en vraagt opnieuw. En omdat dat spookachtige pad nooit een stabiele locatie is, verdient de app nooit een permanente regel in Systeeminstellingen → Microfoon.
De app verleende toestemming aan een geest.
Dit is ook waarom slechts sommige mensen ertegenaan liepen. Als jouw exemplaar van GeekBye al in /Applications stond — omdat je hem daarheen sleepte, of omdat hij er via auto-update terechtkwam — is er geen quarantaine, geen translocatie, een stabiel pad, en blijft alles perfect behouden. De bug was onzichtbaar voor ons en voor iedereen voorbij hun eerste installatie, precies het soort bug dat het langst overleeft.
De fix: geef de app een echt thuis
Aangezien het hele probleem een onstabiel pad is, is de fix om de app op een stabiel pad te krijgen. v2.0.6 detecteert wanneer GeekBye getransloceerd draait (of gewoon buiten /Applications draait) en biedt met één klik "Move to Applications" aan — met de macOS-verplaatsingsaanroep die de bundel naar /Applications kopieert en hem daarvandaan opnieuw start. Vanaf dat moment heeft de app een vaste identiteit: de microfoontoestemming blijft plakken, schermopname blijft plakken, en GeekBye verschijnt eindelijk in Systeeminstellingen waar je hem zou verwachten.
De prompt is er beleefd over. Hij biedt Move to Applications, Not Now en Don't Ask Again — en hij onthoudt de laatste keuze, zodat de app nooit zeurt tegen iemand die een bewuste reden heeft om hem elders te draaien. De beslissing of de prompt überhaupt getoond moet worden, is geïsoleerd in kleine, pure functies (is deze build getransloceerd? staat hij buiten /Applications? heeft de gebruiker hem onderdrukt?) zodat de logica unit-getest wordt zonder een echte genotariseerde build op een echt quarantainevolume te hoeven starten.
Dezelfde release vereenvoudigde ook de rechtenervaring zelf. GeekBye liet vroeger een op maat gemaakt, eigen in-app-rechtenvenster verschijnen — een paar honderd regels UI die iets probeerden na te maken wat het OS al goed doet. v2.0.6 verwijderde het en leunde op de native macOS-rechtenprompt, ondersteund door een rustige, niet-blokkerende banner die alleen verschijnt wanneer een vereiste toestemming daadwerkelijk ontbreekt. Minder code, en gedrag dat gebruikers al herkennen omdat elke andere Mac-app op dezelfde manier werkt.
Het deel waar ik het meest trots op ben: we bewezen het voordat we het geloofden
Het zou makkelijk zijn geweest om translocatie te gokken en een fix uit te brengen. In plaats daarvan bracht de release eerst een opstartdiagnostiek uit: bij het starten rapporteert GeekBye nu zijn eigen uitvoerbare pad en of hij getransloceerd is, of hij binnen /Applications staat, en de huidige microfoon- en schermrechtenstatus. Die telemetrie maakte van een plausibele theorie een bevestigde — productiedata toonde dat de getroffen sessies inderdaad draaiden vanaf getransloceerde paden buiten /Applications, precies zoals voorspeld.
Die volgorde doet ertoe. "Prompt verschijnt maar toestemming blijft niet plakken" heeft meerdere mogelijke verklaringen — een ondertekeningsprobleem, een ontbrekende gebruikstekst, een entitlement-kwestie, een eigenaardigheid in de TCC-database. We sloten de oorzaken op API-niveau uit (het aanvraagpad was aantoonbaar correct), en lieten toen echte data wijzen naar de identiteits-/padlaag in plaats van een hoopvolle fix uit te brengen en te hopen dat de supporttickets stopten.
Drie dingen die deze bug leert
- Een toestemming die vraagt maar niet behouden blijft, is een identiteits_probleem, geen _API-probleem. Als de aanvraagcode correct is en de toestemming toch verdwijnt, stop dan met het herschrijven van de aanvraag. Vraag je af aan welk pad en welke code-identiteit het OS de toestemming koppelt — en of die identiteit stabiel is over starts heen.
- Breng de diagnostiek uit met (of vóór) de fix. Een paar velden — waar draai ik vandaan, wat is mijn rechtenstatus — maakten van een gefundeerde gok een geverifieerde grondoorzaak en vertelden ons precies welke gebruikers getroffen waren. Instrumenteer de grens die je verdenkt voordat je hem patcht.
- De bugs die zich verbergen voor ontwikkelaars zijn degene die in de "verkeerde" omgeving draaien. De onze leefde in
/Applicationsop elke ontwikkelmachine, dus de bug was structureel onzichtbaar voor ons terwijl hij eerstegebruikers trof. Wanneer een melding niet reproduceerbaar is, is de eerste vraag wat is er anders aan waar het draait, niet vergist de gebruiker zich.
GeekBye v2.0.6 bracht de verplaatsingsprompt en de diagnostiek samen uit. Voor de bredere betrouwbaarheidsboog waar dit in past, zie wat een versie 2 echt kost (v2.0.0) en waarom schermopname het verkeerde scherm vastlegt (v2.0.10) — een andere bug die alleen in een specifieke omgeving opdook. Voor de release met kleine details ernaast, kalme software: de flikkerfix en de antwoordmodus-chip (v2.0.3 + v2.0.5).