fix(apple): persist Keychain trust — sign macOS + data-protection keychain
ci / web (push) Failing after 34s
ci / docs-site (push) Failing after 40s
apple / swift (push) Successful in 1m17s
ci / rust (push) Successful in 1m8s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 5s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 6s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 5s
docker / deploy-docs (push) Successful in 19s
deb / build-publish (push) Failing after 2m19s

The client identity prompted for Keychain access on every launch/rebuild. Root
cause: the macOS app target was ad-hoc signed (CODE_SIGN_IDENTITY = "-"), and
the identity lived in the file keychain whose "Always Allow" ACL is bound to the
app's exact code signature (cdhash for ad-hoc). Every rebuild changed the binary
-> changed the cdhash -> the ACL no longer matched -> re-prompt.

- Sign the macOS target with Apple Development (team already set) instead of
  ad-hoc, so the designated requirement is identity-based and stable across
  rebuilds.
- Move the identity to the data-protection keychain (kSecUseDataProtectionKeychain)
  gated by a team-scoped keychain-access-group entitlement — access is granted by
  the app's entitlement, not a per-binary ACL, so it's prompt-free and survives
  rebuilds. Add Config/Punktfunk.entitlements and wire CODE_SIGN_ENTITLEMENTS into
  all six app configs (macOS/iOS/tvOS).
- Unsigned / ad-hoc builds (e.g. `swift run`) lack the entitlement
  (errSecMissingEntitlement) — fall back to the legacy file keychain so they still
  work (with the old prompt), no hard failure.

macOS re-mints the identity on first run (the old file-keychain copy isn't in the
data-protection keychain) -> one re-pair, which is acceptable. iOS keeps its
identity (the explicit access group equals the prior default).

Validated: swift build; swift test (39 passed, 0 failures); xcodebuild
-showBuildSettings confirms Apple Development + Config/Punktfunk.entitlements.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-12 23:25:36 +02:00
parent dfed90bff2
commit e2257a6158
3 changed files with 65 additions and 15 deletions
@@ -353,8 +353,8 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = punktfunk_Logo;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_IDENTITY = "-";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
CODE_SIGN_ENTITLEMENTS = Config/Punktfunk.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
@@ -387,8 +387,8 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = punktfunk_Logo;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_IDENTITY = "-";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
CODE_SIGN_ENTITLEMENTS = Config/Punktfunk.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
@@ -421,6 +421,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = punktfunk_Logo;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = Config/Punktfunk.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = F4H37KF6WC;
@@ -459,6 +460,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = punktfunk_Logo;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = Config/Punktfunk.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = F4H37KF6WC;
@@ -496,6 +498,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
CODE_SIGN_ENTITLEMENTS = Config/Punktfunk.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = F4H37KF6WC;
@@ -525,6 +528,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
CODE_SIGN_ENTITLEMENTS = Config/Punktfunk.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = F4H37KF6WC;