"리빌드마다, macOS 가 앱을 보고 낯선 사람을 봤어. 기술적으론 맞았으니까."
증상
접근성을 허가해. 마이크를 허가해. 오타 하나 고치려고 앱을 리빌드해 — 그리고 macOS 가 둘 다 다시 물어. 또, 모든 빌드마다. 깨진 OS 나 깨진 앱처럼 느껴져. 둘 다 아냐: macOS 가 두 바이너리가 '같은 앱' 인지 정하는 방식의 완전히 논리적인 결과야.
원인: 지정 요구사항(Designated Requirement)
macOS 는 TCC 허가(접근성, 마이크 등)를 앱의 지정 요구사항 — '이게 그 앱이다' 라고 말하는 코드 서명 규칙 — 에 묶어. 평범한 swift build 는 애드혹 서명을 만들고, 그 지정 요구사항은 바이너리의 cdhash 에 고정돼. 소스 한 글자를 바꾸면 cdhash 가 바뀌고, DR 이 바뀌고, 방금 빌드한 앱이 유저가 허가한 앱과 안 맞아. macOS 가 잊는 게 아니라 — 이건 이름만 같은 다른 앱이라고 올바르게 결론 내리는 거야.
swift build -> 애드혹 서명 -> DR 이 cdhash 에 고정
|
v 한 줄 편집, 리빌드
cdhash 바뀜 -> DR 바뀜 -> TCC: "넌 누구야?" -> 영원히 재프롬프트
해법: 안정된 아이덴티티 하나로 서명 -> DR 안정 -> 허가 지속
해법, 그리고 해법 안의 함정
해법은 모든 앱이 공유하는 단일하고 안정된 자체 서명 아이덴티티 — 앱별 인증서가 아니라, 그건 문제를 곱하기만 해. 기계당 한 번 임포트하고, 빌드 스크립트가 그걸로 서명하게 하면, DR 이 바뀌길 멈춰. 그다음 알아둘 값어치가 있는 해법 안의 함정이 있어: security find-identity -v 는 Gatekeeper-유효 아이덴티티로 필터링하고, 자체 서명 인증서는 유효가 아니라(신뢰 안 됨으로 보고), 네 아이덴티티가 존재 안 하는 것처럼 보여. security find-identity -p codesigning — -v 없이 — 로 감지해. 플래그 하나가 '설계대로 작동' 과 한 시간의 혼란 사이에 서 있어. 마지막으로, 첫 제대로-서명된 빌드 후, 낡은 애드혹-고정 허가를 tccutil reset 으로 한 번 지우고 다시 허가해; 그때부터 지속돼.