From a87c94c6e5265640a2b11b403c5a93c5ceed0e83 Mon Sep 17 00:00:00 2001 From: Laurin-Notemann <47634664+Laurin-Notemann@users.noreply.github.com> Date: Mon, 12 Oct 2026 13:37:21 +0000 Subject: [PATCH] fix(otter): read Developer ID profiles that grant Associated Domains as a string Apple's Developer ID (Mac) profile grants com.apple.developer.associated-domains as the bare string "*". The profile schema only accepted a list, so the whole profile was rejected and no passkey entitlement was claimed: nightly .383 shipped without the WebAuthn keychain group. Accept both forms, and make the fixture match the profile Apple issued. Co-Authored-By: Claude Opus 5.5 --- scripts/otter/fixtures/macos-profile.plist | 7 ++++--- scripts/otter/macos-profile.ts | 21 +++++++++++++-------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/scripts/otter/fixtures/macos-profile.plist b/scripts/otter/fixtures/macos-profile.plist index ab4e2ce4510d..3fa8fe146790 100644 --- a/scripts/otter/fixtures/macos-profile.plist +++ b/scripts/otter/fixtures/macos-profile.plist @@ -1,4 +1,5 @@ + Entitlements @@ -10,11 +11,11 @@ keychain-access-groups YNJ5WLH965.* com.apple.developer.associated-domains - * - aps-environment + * + com.apple.developer.aps-environment production com.apple.security.application-groups - group.dev.otterware.code + group.dev.otterware.codeYNJ5WLH965.* diff --git a/scripts/otter/macos-profile.ts b/scripts/otter/macos-profile.ts index 9a2979f7ff53..ac719ddbd2cf 100644 --- a/scripts/otter/macos-profile.ts +++ b/scripts/otter/macos-profile.ts @@ -139,7 +139,10 @@ const ProvisioningProfilePlist = Schema.Struct({ Entitlements: Schema.Struct({ "com.apple.application-identifier": Schema.optional(Schema.String), "com.apple.developer.team-identifier": Schema.optional(Schema.String), - "com.apple.developer.associated-domains": Schema.optional(Schema.Array(Schema.String)), + // Developer ID profiles grant a wildcard as the bare string "*", not a list. + "com.apple.developer.associated-domains": Schema.optional( + Schema.Union([Schema.String, Schema.Array(Schema.String)]), + ), "keychain-access-groups": Schema.optional(Schema.Array(Schema.String)), [BROWSER_PASSKEYS_ENTITLEMENT]: Schema.optional(Schema.Boolean), }), @@ -200,13 +203,15 @@ export function renderMacPasskeyEntitlements( : ""; const associatedDomains = configuration.rpDomains .filter((domain) => - (grants?.["com.apple.developer.associated-domains"] ?? []).some( - (grant) => - grant === "*" || - grant === `webcredentials:${domain}` || - (grant.startsWith("webcredentials:*.") && - domain.endsWith(grant.slice("webcredentials:*".length))), - ), + [grants?.["com.apple.developer.associated-domains"] ?? []] + .flat() + .some( + (grant) => + grant === "*" || + grant === `webcredentials:${domain}` || + (grant.startsWith("webcredentials:*.") && + domain.endsWith(grant.slice("webcredentials:*".length))), + ), ) .map((domain) => ` webcredentials:${escapeXml(domain)}`) .join("\n");