
La teva app de Mac obté accés al micròfon — i l'oblida a cada arrencada
GeekBye va demanar permís per al micròfon, li'l vas donar i funcionava. A la següent arrencada: desaparegut. I l'app no apareixia enlloc a Configuració del Sistema → Micròfon. El culpable era una funció de seguretat de macOS que executava l'app en silenci des d'una ruta que desapareix — aquí tens el diagnòstic i la solució d'un sol avís.
Aquí tens un error que et fa dubtar dels teus propis ulls. Instal·les GeekBye, et demana accés al micròfon, fas clic a Permet i la transcripció funciona. Genial. Surts, el tornes a obrir l'endemà al matí — i et torna a demanar accés al micròfon un altre cop. Vas a comprovar Configuració del Sistema → Privadesa i seguretat → Micròfon per arreglar-ho manualment, i GeekBye ni tan sols hi és a la llista. Ni denegat. Ni permès. Simplement absent, com si mai ho hagués demanat.
Cada peça individual semblava correcta. L'avís era real. El permís funcionava en aquell moment. L'app estava correctament signada i notaritzada amb les cadenes d'ús adequades. I tanmateix, la concessió s'evaporava a cada arrencada. GeekBye v2.0.6 ho va corregir — i la causa arrel és una de les coses més astutes que fa macOS per protegir-te.
La funció que amagava l'app d'ella mateixa
El culpable és el App Translocation de macOS, una funció de seguretat de Gatekeeper. Quan baixes una app i l'executes directament des del DMG o des de la carpeta ~/Downloads — a qualsevol lloc on encara estigui "en quarantena" — macOS no l'executa realment des d'on la veus. La copia de manera transparent a una ruta aleatòria, de només lectura, ben endins de /private/var/folders/.../AppTranslocation/… i executa aquesta còpia. És una bona defensa: impedeix que una baixada maliciosa manipuli fitxers del seu costat.
Però aquí ve el xoc. El sistema de permisos de macOS (TCC — allò que fa el seguiment de qui pot fer servir el teu micròfon, càmera i pantalla) identifica una app per la seva ruta i identitat de codi. Quan l'app està translocada, aquesta ruta és aleatòria i temporal. Així que, quan concedeixes accés al micròfon, macOS registra la concessió obedientment — contra una ruta que no existirà a la següent arrencada. Torna a obrir l'app, macOS la transloca a una ruta aleatòria diferent, veu una app de la qual no té cap registre i torna a demanar. I com que aquesta ruta fantasma mai és una ubicació estable, l'app mai es guanya una fila permanent a Configuració del Sistema → Micròfon.
L'app concedia permís a un fantasma.
Aquesta és també la raó per la qual només alguns usuaris ho patien. Si la teva còpia de GeekBye ja vivia a /Applications — perquè l'hi vas arrossegar, o perquè hi va arribar via actualització automàtica — no hi ha quarantena, no hi ha translocació, hi ha una ruta estable, i tot persisteix perfectament. L'error era invisible per a nosaltres i per a qualsevol que hagués passat la primera instal·lació, exactament el tipus d'error que sobreviu més temps.
La solució: dona a l'app una llar de veritat
Com que tot el problema és una ruta inestable, la solució és portar l'app a una d'estable. La v2.0.6 detecta quan GeekBye s'executa translocada (o simplement s'executa fora de /Applications) i ofereix amb un sol clic "Move to Applications" — fent servir la crida de reubicació de macOS que copia el paquet a /Applications i el torna a llançar des d'allà. A partir d'aquell moment l'app té una identitat fixa: la concessió del micròfon queda fixada, la gravació de pantalla queda fixada, i GeekBye finalment apareix a Configuració del Sistema on l'esperaries.
L'avís és educat. Ofereix Move to Applications, Not Now i Don't Ask Again — i recorda l'última tria, de manera que l'app mai empipa algú que té un motiu deliberat per executar-la des d'un altre lloc. La decisió de si tan sols cal mostrar l'avís està aïllada en funcions petites i pures (aquesta compilació està translocada? està fora de /Applications? l'usuari l'ha suprimit?) de manera que la lògica es prova amb tests unitaris sense necessitat de llançar una compilació notaritzada real en un volum en quarantena real.
La mateixa versió també va simplificar la mateixa experiència de permisos. GeekBye solia obrir una finestra de permisos personalitzada, feta a mida, dins de l'app — uns quants centenars de línies d'interfície intentant reproduir una cosa que el sistema operatiu ja fa bé. La v2.0.6 la va eliminar i es va recolzar en l'avís de permisos natiu de macOS, amb el suport d'un rètol tranquil i no bloquejant que apareix només quan realment falta un permís requerit. Menys codi, i un comportament que els usuaris ja reconeixen perquè totes les altres apps de Mac funcionen igual.
La part de la qual estic més orgullós: ho vam demostrar abans de creure-ho
Hauria estat fàcil endevinar la translocació i publicar una solució. En comptes d'això, la versió va publicar primer un diagnòstic d'arrencada: en arrencar, GeekBye ara informa de la seva pròpia ruta d'executable i de si està translocada, de si està dins de /Applications, i de l'estat actual dels permisos de micròfon i pantalla. Aquella telemetria va convertir una teoria plausible en una de confirmada — les dades de producció van mostrar que les sessions afectades s'executaven, de fet, des de rutes translocades fora de /Applications, exactament com havíem predit.
Aquest ordre importa. "L'avís apareix però el permís no queda fixat" té diverses explicacions possibles — un problema de signatura, una cadena d'ús que falta, un problema d'entitlement, una peculiaritat de la base de dades TCC. Vam descartar les causes a nivell d'API (la ruta de la sol·licitud era demostrablement correcta) i llavors vam deixar que les dades reals assenyalessin la capa d'identitat/ruta en comptes de publicar una solució esperançada i esperar que els tiquets de suport paressin.
Tres coses que ensenya aquest error
- Un permís que demana però no persisteix és un problema d'identitat, no d'API. Si el codi de la sol·licitud és correcte i la concessió tot i així desapareix, deixa de reescriure la sol·licitud. Pregunta't a quina ruta i identitat de codi el sistema operatiu vincula la concessió — i si aquesta identitat és estable entre arrencades.
- Publica el diagnòstic amb (o abans de) la solució. Uns pocs camps — des d'on m'executo, quin és el meu estat de permisos — van convertir una conjectura fonamentada en una causa arrel verificada i ens van dir exactament quins usuaris estaven afectats. Instrumenta el límit que sospites abans de pegar-lo.
- Els errors que s'amaguen dels desenvolupadors són els que s'executen en l'entorn "equivocat". El nostre vivia a
/Applicationsa totes les màquines de desenvolupament, així que l'error era estructuralment invisible per a nosaltres mentre afectava els usuaris de primera vegada. Quan un informe no es reprodueix, la primera pregunta és què hi ha de diferent en el lloc on s'executa, no s'equivoca l'usuari.
GeekBye v2.0.6 va publicar l'avís de reubicació i el diagnòstic junts. Per a l'arc de fiabilitat més ampli en què encaixa això, mira què costa realment una versió 2 (v2.0.0) i per què la gravació de pantalla captura el monitor equivocat (v2.0.10) — un altre error que només sortia en un entorn específic. Per a la versió de petits detalls del costat, programari tranquil: la solució del parpelleig i el xip de mode de resposta (v2.0.3 + v2.0.5).