buildanything 1.7.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +9 -3
- package/CHANGELOG.md +112 -0
- package/README.md +2 -2
- package/agents/a11y-architect.md +166 -0
- package/agents/business-model.md +80 -29
- package/agents/code-architect.md +75 -0
- package/agents/code-reviewer.md +255 -0
- package/agents/code-simplifier.md +64 -0
- package/agents/design-brand-guardian.md +293 -53
- package/agents/design-critic.md +139 -0
- package/agents/design-inclusive-visuals-specialist.md +6 -19
- package/agents/design-ui-designer.md +335 -56
- package/agents/design-ux-architect.md +403 -55
- package/agents/design-ux-researcher.md +264 -49
- package/agents/engineering-ai-engineer.md +26 -36
- package/agents/engineering-backend-architect.md +185 -36
- package/agents/engineering-data-engineer.md +225 -43
- package/agents/engineering-devops-automator.md +227 -74
- package/agents/engineering-frontend-developer.md +210 -34
- package/agents/engineering-mobile-app-builder.md +6 -1
- package/agents/engineering-rapid-prototyper.md +30 -9
- package/agents/engineering-security-engineer.md +263 -61
- package/agents/engineering-senior-developer.md +128 -19
- package/agents/engineering-sre.md +84 -0
- package/agents/engineering-technical-writer.md +285 -41
- package/agents/feature-intel.md +110 -0
- package/agents/ios-app-review-guardian.md +66 -0
- package/agents/ios-foundation-models-specialist.md +64 -0
- package/agents/ios-storekit-specialist.md +59 -0
- package/agents/ios-swift-architect.md +129 -0
- package/agents/ios-swift-search.md +137 -0
- package/agents/ios-swift-ui-design.md +136 -0
- package/agents/marketing-app-store-optimizer.md +246 -64
- package/agents/planner.md +216 -0
- package/agents/pr-test-analyzer.md +63 -0
- package/agents/product-feedback-synthesizer.md +8 -2
- package/agents/refactor-cleaner.md +102 -0
- package/agents/security-reviewer.md +128 -0
- package/agents/silent-failure-hunter.md +54 -0
- package/agents/swift-build-resolver.md +119 -0
- package/agents/swift-reviewer.md +112 -0
- package/agents/tech-feasibility.md +21 -1
- package/agents/testing-api-tester.md +236 -59
- package/agents/testing-evidence-collector.md +26 -1
- package/agents/testing-performance-benchmarker.md +21 -1
- package/agents/testing-reality-checker.md +6 -1
- package/agents/visual-research.md +116 -0
- package/bin/adapters/cycle-counter-tool.ts +155 -0
- package/bin/adapters/scribe-tool.ts +71 -0
- package/bin/adapters/state-save-tool.ts +130 -0
- package/bin/adapters/write-lease-tool.ts +127 -0
- package/bin/buildanything-runtime.js +15 -0
- package/bin/buildanything-runtime.ts +328 -0
- package/bin/setup.js +83 -8
- package/commands/add-feature.md +2 -0
- package/commands/build.md +752 -332
- package/commands/fix.md +65 -0
- package/commands/self-check.md +121 -0
- package/commands/setup.md +114 -0
- package/commands/ux-review.md +63 -0
- package/commands/verify.md +69 -0
- package/docs/migration/agents.yaml +729 -0
- package/docs/migration/phase-graph.yaml +1088 -0
- package/docs/migration/sdk-host-compat.md +18 -0
- package/hooks/compile-writer-owner-cache.ts +171 -0
- package/hooks/hooks.json +36 -0
- package/hooks/pre-tool-use +19 -0
- package/hooks/pre-tool-use.ts +776 -0
- package/hooks/record-mode-transitions.ts +178 -0
- package/hooks/session-start +89 -2
- package/hooks/subagent-start +17 -0
- package/hooks/subagent-start.ts +471 -0
- package/hooks/subagent-stop +17 -0
- package/hooks/subagent-stop.ts +153 -0
- package/package.json +28 -5
- package/protocols/architecture-schema.md +171 -0
- package/protocols/build-fix.md +52 -0
- package/protocols/cleanup.md +54 -0
- package/protocols/decision-log.md +131 -0
- package/protocols/eval-harness.md +61 -0
- package/protocols/fake-data-detector.md +64 -0
- package/protocols/ios-context.md +234 -0
- package/protocols/ios-frameworks-map.md +323 -0
- package/protocols/ios-phase-branches.md +337 -0
- package/protocols/ios-preflight.md +27 -0
- package/protocols/launch-readiness.md +258 -0
- package/protocols/metric-loop.md +153 -0
- package/protocols/smoke-test.md +118 -0
- package/protocols/state-schema.json +388 -0
- package/protocols/state-schema.md +172 -0
- package/protocols/verify.md +127 -0
- package/protocols/visual-dna.md +185 -0
- package/protocols/web-phase-branches.md +351 -0
- package/skills/ios/_VENDORED.md +62 -0
- package/skills/ios/activitykit/LICENSE +131 -0
- package/skills/ios/activitykit/SKILL.md +505 -0
- package/skills/ios/activitykit/references/activitykit-patterns.md +868 -0
- package/skills/ios/app-intents/LICENSE +131 -0
- package/skills/ios/app-intents/SKILL.md +494 -0
- package/skills/ios/app-intents/references/appintents-advanced.md +1076 -0
- package/skills/ios/app-store-connect-metadata/SKILL.md +148 -0
- package/skills/ios/apple-on-device-ai/LICENSE +131 -0
- package/skills/ios/apple-on-device-ai/SKILL.md +505 -0
- package/skills/ios/apple-on-device-ai/references/coreml-conversion.md +425 -0
- package/skills/ios/apple-on-device-ai/references/coreml-optimization.md +344 -0
- package/skills/ios/apple-on-device-ai/references/foundation-models.md +508 -0
- package/skills/ios/apple-on-device-ai/references/mlx-swift.md +285 -0
- package/skills/ios/asc-privacy-manifest/SKILL.md +350 -0
- package/skills/ios/hig-components-content/SKILL.md +86 -0
- package/skills/ios/hig-components-content/references/activity-views.md +79 -0
- package/skills/ios/hig-components-content/references/charts.md +180 -0
- package/skills/ios/hig-components-content/references/collections.md +48 -0
- package/skills/ios/hig-components-content/references/color-wells.md +42 -0
- package/skills/ios/hig-components-content/references/image-views.md +82 -0
- package/skills/ios/hig-components-content/references/image-wells.md +34 -0
- package/skills/ios/hig-components-content/references/lockups.md +78 -0
- package/skills/ios/hig-components-content/references/web-views.md +36 -0
- package/skills/ios/hig-components-controls/SKILL.md +88 -0
- package/skills/ios/hig-components-controls/references/combo-boxes.md +40 -0
- package/skills/ios/hig-components-controls/references/controls.md +112 -0
- package/skills/ios/hig-components-controls/references/gauges.md +74 -0
- package/skills/ios/hig-components-controls/references/labels.md +92 -0
- package/skills/ios/hig-components-controls/references/pickers.md +128 -0
- package/skills/ios/hig-components-controls/references/rating-indicators.md +38 -0
- package/skills/ios/hig-components-controls/references/segmented-controls.md +94 -0
- package/skills/ios/hig-components-controls/references/sliders.md +92 -0
- package/skills/ios/hig-components-controls/references/steppers.md +40 -0
- package/skills/ios/hig-components-controls/references/text-fields.md +88 -0
- package/skills/ios/hig-components-controls/references/text-views.md +56 -0
- package/skills/ios/hig-components-controls/references/toggles.md +127 -0
- package/skills/ios/hig-components-controls/references/token-fields.md +48 -0
- package/skills/ios/hig-components-controls/references/virtual-keyboards.md +156 -0
- package/skills/ios/hig-components-dialogs/SKILL.md +76 -0
- package/skills/ios/hig-components-dialogs/references/action-sheets.md +74 -0
- package/skills/ios/hig-components-dialogs/references/alerts.md +158 -0
- package/skills/ios/hig-components-dialogs/references/digit-entry-views.md +32 -0
- package/skills/ios/hig-components-dialogs/references/popovers.md +81 -0
- package/skills/ios/hig-components-dialogs/references/sheets.md +157 -0
- package/skills/ios/hig-components-layout/SKILL.md +99 -0
- package/skills/ios/hig-components-layout/references/boxes.md +48 -0
- package/skills/ios/hig-components-layout/references/column-views.md +44 -0
- package/skills/ios/hig-components-layout/references/lists-and-tables.md +99 -0
- package/skills/ios/hig-components-layout/references/ornaments.md +56 -0
- package/skills/ios/hig-components-layout/references/outline-views.md +64 -0
- package/skills/ios/hig-components-layout/references/panels.md +75 -0
- package/skills/ios/hig-components-layout/references/scroll-views.md +123 -0
- package/skills/ios/hig-components-layout/references/sidebars.md +109 -0
- package/skills/ios/hig-components-layout/references/split-views.md +110 -0
- package/skills/ios/hig-components-layout/references/tab-bars.md +173 -0
- package/skills/ios/hig-components-layout/references/tab-views.md +68 -0
- package/skills/ios/hig-components-layout/references/windows.md +188 -0
- package/skills/ios/hig-components-menus/SKILL.md +81 -0
- package/skills/ios/hig-components-menus/references/action-button.md +61 -0
- package/skills/ios/hig-components-menus/references/buttons.md +261 -0
- package/skills/ios/hig-components-menus/references/context-menus.md +105 -0
- package/skills/ios/hig-components-menus/references/disclosure-controls.md +84 -0
- package/skills/ios/hig-components-menus/references/dock-menus.md +40 -0
- package/skills/ios/hig-components-menus/references/edit-menus.md +88 -0
- package/skills/ios/hig-components-menus/references/menus.md +171 -0
- package/skills/ios/hig-components-menus/references/pop-up-buttons.md +70 -0
- package/skills/ios/hig-components-menus/references/pull-down-buttons.md +77 -0
- package/skills/ios/hig-components-menus/references/the-menu-bar.md +303 -0
- package/skills/ios/hig-components-menus/references/toolbars.md +256 -0
- package/skills/ios/hig-components-search/SKILL.md +68 -0
- package/skills/ios/hig-components-search/references/page-controls.md +120 -0
- package/skills/ios/hig-components-search/references/path-controls.md +40 -0
- package/skills/ios/hig-components-search/references/search-fields.md +189 -0
- package/skills/ios/hig-components-status/SKILL.md +80 -0
- package/skills/ios/hig-components-status/references/activity-rings.md +105 -0
- package/skills/ios/hig-components-status/references/progress-indicators.md +116 -0
- package/skills/ios/hig-components-status/references/status-bars.md +38 -0
- package/skills/ios/hig-components-system/SKILL.md +88 -0
- package/skills/ios/hig-components-system/references/app-clips.md +387 -0
- package/skills/ios/hig-components-system/references/app-shortcuts.md +114 -0
- package/skills/ios/hig-components-system/references/complications.md +425 -0
- package/skills/ios/hig-components-system/references/home-screen-quick-actions.md +42 -0
- package/skills/ios/hig-components-system/references/live-activities.md +442 -0
- package/skills/ios/hig-components-system/references/notifications.md +153 -0
- package/skills/ios/hig-components-system/references/top-shelf.md +135 -0
- package/skills/ios/hig-components-system/references/watch-faces.md +40 -0
- package/skills/ios/hig-components-system/references/widgets.md +517 -0
- package/skills/ios/hig-foundations/SKILL.md +98 -0
- package/skills/ios/hig-foundations/references/accessibility.md +291 -0
- package/skills/ios/hig-foundations/references/app-icons.md +210 -0
- package/skills/ios/hig-foundations/references/branding.md +44 -0
- package/skills/ios/hig-foundations/references/color.md +274 -0
- package/skills/ios/hig-foundations/references/dark-mode.md +116 -0
- package/skills/ios/hig-foundations/references/icons.md +263 -0
- package/skills/ios/hig-foundations/references/images.md +176 -0
- package/skills/ios/hig-foundations/references/immersive-experiences.md +174 -0
- package/skills/ios/hig-foundations/references/inclusion.md +189 -0
- package/skills/ios/hig-foundations/references/layout.md +425 -0
- package/skills/ios/hig-foundations/references/materials.md +238 -0
- package/skills/ios/hig-foundations/references/motion.md +103 -0
- package/skills/ios/hig-foundations/references/privacy.md +231 -0
- package/skills/ios/hig-foundations/references/right-to-left.md +206 -0
- package/skills/ios/hig-foundations/references/sf-symbols.md +310 -0
- package/skills/ios/hig-foundations/references/spatial-layout.md +142 -0
- package/skills/ios/hig-foundations/references/typography.md +1146 -0
- package/skills/ios/hig-foundations/references/writing.md +91 -0
- package/skills/ios/hig-inputs/SKILL.md +94 -0
- package/skills/ios/hig-inputs/references/apple-pencil-and-scribble.md +148 -0
- package/skills/ios/hig-inputs/references/camera-control.md +107 -0
- package/skills/ios/hig-inputs/references/digital-crown.md +83 -0
- package/skills/ios/hig-inputs/references/eyes.md +120 -0
- package/skills/ios/hig-inputs/references/focus-and-selection.md +120 -0
- package/skills/ios/hig-inputs/references/game-controls.md +156 -0
- package/skills/ios/hig-inputs/references/gestures.md +208 -0
- package/skills/ios/hig-inputs/references/gyro-and-accelerometer.md +40 -0
- package/skills/ios/hig-inputs/references/keyboards.md +234 -0
- package/skills/ios/hig-inputs/references/nearby-interactions.md +70 -0
- package/skills/ios/hig-inputs/references/pointing-devices.md +237 -0
- package/skills/ios/hig-inputs/references/remotes.md +67 -0
- package/skills/ios/hig-inputs/references/spatial-interactions.md +70 -0
- package/skills/ios/hig-patterns/SKILL.md +104 -0
- package/skills/ios/hig-patterns/references/charting-data.md +81 -0
- package/skills/ios/hig-patterns/references/collaboration-and-sharing.md +86 -0
- package/skills/ios/hig-patterns/references/drag-and-drop.md +134 -0
- package/skills/ios/hig-patterns/references/entering-data.md +69 -0
- package/skills/ios/hig-patterns/references/feedback.md +67 -0
- package/skills/ios/hig-patterns/references/file-management.md +135 -0
- package/skills/ios/hig-patterns/references/going-full-screen.md +79 -0
- package/skills/ios/hig-patterns/references/launching.md +81 -0
- package/skills/ios/hig-patterns/references/live-viewing-apps.md +79 -0
- package/skills/ios/hig-patterns/references/loading.md +59 -0
- package/skills/ios/hig-patterns/references/managing-accounts.md +107 -0
- package/skills/ios/hig-patterns/references/managing-notifications.md +99 -0
- package/skills/ios/hig-patterns/references/modality.md +82 -0
- package/skills/ios/hig-patterns/references/multitasking.md +131 -0
- package/skills/ios/hig-patterns/references/offering-help.md +117 -0
- package/skills/ios/hig-patterns/references/onboarding.md +69 -0
- package/skills/ios/hig-patterns/references/playing-audio.md +124 -0
- package/skills/ios/hig-patterns/references/playing-haptics.md +280 -0
- package/skills/ios/hig-patterns/references/playing-video.md +180 -0
- package/skills/ios/hig-patterns/references/printing.md +50 -0
- package/skills/ios/hig-patterns/references/ratings-and-reviews.md +48 -0
- package/skills/ios/hig-patterns/references/searching.md +70 -0
- package/skills/ios/hig-patterns/references/settings.md +84 -0
- package/skills/ios/hig-patterns/references/undo-and-redo.md +58 -0
- package/skills/ios/hig-patterns/references/workouts.md +76 -0
- package/skills/ios/hig-platforms/SKILL.md +84 -0
- package/skills/ios/hig-platforms/references/designing-for-games.md +159 -0
- package/skills/ios/hig-platforms/references/designing-for-ios.md +66 -0
- package/skills/ios/hig-platforms/references/designing-for-ipados.md +64 -0
- package/skills/ios/hig-platforms/references/designing-for-macos.md +70 -0
- package/skills/ios/hig-platforms/references/designing-for-tvos.md +68 -0
- package/skills/ios/hig-platforms/references/designing-for-visionos.md +85 -0
- package/skills/ios/hig-platforms/references/designing-for-watchos.md +74 -0
- package/skills/ios/hig-project-context/SKILL.md +133 -0
- package/skills/ios/hig-technologies/SKILL.md +107 -0
- package/skills/ios/hig-technologies/references/airplay.md +125 -0
- package/skills/ios/hig-technologies/references/always-on.md +62 -0
- package/skills/ios/hig-technologies/references/apple-pay.md +441 -0
- package/skills/ios/hig-technologies/references/augmented-reality.md +247 -0
- package/skills/ios/hig-technologies/references/carekit.md +224 -0
- package/skills/ios/hig-technologies/references/carplay.md +119 -0
- package/skills/ios/hig-technologies/references/game-center.md +343 -0
- package/skills/ios/hig-technologies/references/generative-ai.md +110 -0
- package/skills/ios/hig-technologies/references/healthkit.md +120 -0
- package/skills/ios/hig-technologies/references/homekit.md +343 -0
- package/skills/ios/hig-technologies/references/icloud.md +52 -0
- package/skills/ios/hig-technologies/references/id-verifier.md +73 -0
- package/skills/ios/hig-technologies/references/imessage-apps-and-stickers.md +105 -0
- package/skills/ios/hig-technologies/references/in-app-purchase.md +263 -0
- package/skills/ios/hig-technologies/references/live-photos.md +54 -0
- package/skills/ios/hig-technologies/references/mac-catalyst.md +216 -0
- package/skills/ios/hig-technologies/references/machine-learning.md +394 -0
- package/skills/ios/hig-technologies/references/maps.md +221 -0
- package/skills/ios/hig-technologies/references/nfc.md +51 -0
- package/skills/ios/hig-technologies/references/photo-editing.md +40 -0
- package/skills/ios/hig-technologies/references/researchkit.md +134 -0
- package/skills/ios/hig-technologies/references/shareplay.md +142 -0
- package/skills/ios/hig-technologies/references/shazamkit.md +47 -0
- package/skills/ios/hig-technologies/references/sign-in-with-apple.md +288 -0
- package/skills/ios/hig-technologies/references/siri.md +523 -0
- package/skills/ios/hig-technologies/references/tap-to-pay-on-iphone.md +208 -0
- package/skills/ios/hig-technologies/references/voiceover.md +90 -0
- package/skills/ios/hig-technologies/references/wallet.md +420 -0
- package/skills/ios/ios-26-platform/SKILL.md +53 -0
- package/skills/ios/ios-26-platform/references/automatic-adoption.md +161 -0
- package/skills/ios/ios-26-platform/references/backward-compat.md +238 -0
- package/skills/ios/ios-26-platform/references/liquid-glass.md +255 -0
- package/skills/ios/ios-26-platform/references/swiftui-apis.md +277 -0
- package/skills/ios/ios-26-platform/references/toolbar-navigation.md +250 -0
- package/skills/ios/ios-bootstrap/SKILL.md +107 -0
- package/skills/ios/ios-bootstrap/references/apple-docs-mcp-config.md +28 -0
- package/skills/ios/ios-bootstrap/references/new-project-dialog.md +41 -0
- package/skills/ios/ios-bootstrap/references/xcode-mcp-config.md +29 -0
- package/skills/ios/ios-debugger-agent/LICENSE +21 -0
- package/skills/ios/ios-debugger-agent/SKILL.md +58 -0
- package/skills/ios/ios-debugger-agent/agents/openai.yaml +4 -0
- package/skills/ios/ios-entitlements-generator/SKILL.md +47 -0
- package/skills/ios/ios-info-plist-hardening/SKILL.md +130 -0
- package/skills/ios/ios-maestro-flow-author/SKILL.md +68 -0
- package/skills/ios/ios-maestro-flow-author/references/input-and-scroll.yaml +17 -0
- package/skills/ios/ios-maestro-flow-author/references/modal-and-dismiss.yaml +14 -0
- package/skills/ios/ios-maestro-flow-author/references/onboarding-flow.yaml +16 -0
- package/skills/ios/ios-maestro-flow-author/references/tab-navigation.yaml +13 -0
- package/skills/ios/ios-maestro-flow-author/references/tap-and-assert.yaml +9 -0
- package/skills/ios/swift-accessibility/LICENSE +21 -0
- package/skills/ios/swift-accessibility/SKILL.md +371 -0
- package/skills/ios/swift-accessibility/examples/before-after-appkit.md +446 -0
- package/skills/ios/swift-accessibility/examples/before-after-swiftui.md +441 -0
- package/skills/ios/swift-accessibility/examples/before-after-uikit.md +464 -0
- package/skills/ios/swift-accessibility/references/assistive-access.md +441 -0
- package/skills/ios/swift-accessibility/references/display-settings.md +491 -0
- package/skills/ios/swift-accessibility/references/dynamic-type.md +420 -0
- package/skills/ios/swift-accessibility/references/media-accessibility.md +421 -0
- package/skills/ios/swift-accessibility/references/motor-input.md +393 -0
- package/skills/ios/swift-accessibility/references/nutrition-labels.md +362 -0
- package/skills/ios/swift-accessibility/references/platform-specifics.md +515 -0
- package/skills/ios/swift-accessibility/references/semantic-structure.md +585 -0
- package/skills/ios/swift-accessibility/references/testing-auditing.md +507 -0
- package/skills/ios/swift-accessibility/references/voice-control.md +317 -0
- package/skills/ios/swift-accessibility/references/voiceover-swiftui.md +584 -0
- package/skills/ios/swift-accessibility/references/voiceover-uikit.md +519 -0
- package/skills/ios/swift-accessibility/references/wcag-mapping.md +167 -0
- package/skills/ios/swift-accessibility/resources/audit-template.swift +128 -0
- package/skills/ios/swift-accessibility/resources/qa-checklist.md +258 -0
- package/skills/ios/swift-actor-persistence/SKILL.md +143 -0
- package/skills/ios/swift-concurrency/LICENSE +21 -0
- package/skills/ios/swift-concurrency/SKILL.md +171 -0
- package/skills/ios/swift-concurrency/references/_index.md +50 -0
- package/skills/ios/swift-concurrency/references/actors.md +660 -0
- package/skills/ios/swift-concurrency/references/async-algorithms.md +847 -0
- package/skills/ios/swift-concurrency/references/async-await-basics.md +266 -0
- package/skills/ios/swift-concurrency/references/async-sequences.md +710 -0
- package/skills/ios/swift-concurrency/references/core-data.md +560 -0
- package/skills/ios/swift-concurrency/references/glossary.md +135 -0
- package/skills/ios/swift-concurrency/references/linting.md +155 -0
- package/skills/ios/swift-concurrency/references/memory-management.md +569 -0
- package/skills/ios/swift-concurrency/references/migration.md +1104 -0
- package/skills/ios/swift-concurrency/references/performance.md +593 -0
- package/skills/ios/swift-concurrency/references/sendable.md +598 -0
- package/skills/ios/swift-concurrency/references/tasks.md +636 -0
- package/skills/ios/swift-concurrency/references/testing.md +592 -0
- package/skills/ios/swift-concurrency/references/threading.md +495 -0
- package/skills/ios/swift-concurrency-6-2/SKILL.md +216 -0
- package/skills/ios/swift-protocol-di-testing/SKILL.md +190 -0
- package/skills/ios/swift-security-expert/LICENSE +21 -0
- package/skills/ios/swift-security-expert/SKILL.md +470 -0
- package/skills/ios/swift-security-expert/references/biometric-authentication.md +565 -0
- package/skills/ios/swift-security-expert/references/certificate-trust.md +592 -0
- package/skills/ios/swift-security-expert/references/common-anti-patterns.md +690 -0
- package/skills/ios/swift-security-expert/references/compliance-owasp-mapping.md +537 -0
- package/skills/ios/swift-security-expert/references/credential-storage-patterns.md +721 -0
- package/skills/ios/swift-security-expert/references/cryptokit-public-key.md +505 -0
- package/skills/ios/swift-security-expert/references/cryptokit-symmetric.md +497 -0
- package/skills/ios/swift-security-expert/references/keychain-access-control.md +508 -0
- package/skills/ios/swift-security-expert/references/keychain-fundamentals.md +596 -0
- package/skills/ios/swift-security-expert/references/keychain-item-classes.md +476 -0
- package/skills/ios/swift-security-expert/references/keychain-sharing.md +458 -0
- package/skills/ios/swift-security-expert/references/migration-legacy-stores.md +727 -0
- package/skills/ios/swift-security-expert/references/secure-enclave.md +539 -0
- package/skills/ios/swift-security-expert/references/testing-security-code.md +781 -0
- package/skills/ios/swift-testing-expert/LICENSE +21 -0
- package/skills/ios/swift-testing-expert/SKILL.md +79 -0
- package/skills/ios/swift-testing-expert/references/_index.md +12 -0
- package/skills/ios/swift-testing-expert/references/async-testing-and-waiting.md +127 -0
- package/skills/ios/swift-testing-expert/references/expectations.md +145 -0
- package/skills/ios/swift-testing-expert/references/fundamentals.md +141 -0
- package/skills/ios/swift-testing-expert/references/migration-from-xctest.md +127 -0
- package/skills/ios/swift-testing-expert/references/parallelization-and-isolation.md +95 -0
- package/skills/ios/swift-testing-expert/references/parameterized-testing.md +284 -0
- package/skills/ios/swift-testing-expert/references/performance-and-best-practices.md +187 -0
- package/skills/ios/swift-testing-expert/references/traits-and-tags.md +114 -0
- package/skills/ios/swift-testing-expert/references/xcode-workflows.md +70 -0
- package/skills/ios/swiftdata-pro/LICENSE +21 -0
- package/skills/ios/swiftdata-pro/SKILL.md +102 -0
- package/skills/ios/swiftdata-pro/agents/openai.yaml +10 -0
- package/skills/ios/swiftdata-pro/assets/swiftdata-pro-icon.png +0 -0
- package/skills/ios/swiftdata-pro/assets/swiftdata-pro-icon.svg +29 -0
- package/skills/ios/swiftdata-pro/references/class-inheritance.md +104 -0
- package/skills/ios/swiftdata-pro/references/cloudkit.md +10 -0
- package/skills/ios/swiftdata-pro/references/core-rules.md +20 -0
- package/skills/ios/swiftdata-pro/references/indexing.md +27 -0
- package/skills/ios/swiftdata-pro/references/predicates.md +73 -0
- package/skills/ios/swiftui-design-principles/AGENTS.md +21 -0
- package/skills/ios/swiftui-design-principles/LICENSE +21 -0
- package/skills/ios/swiftui-design-principles/README.md +41 -0
- package/skills/ios/swiftui-design-principles/SKILL.md +605 -0
- package/skills/ios/swiftui-design-principles/metadata.json +10 -0
- package/skills/ios/swiftui-design-tokens/SKILL.md +475 -0
- package/skills/ios/swiftui-liquid-glass/LICENSE +21 -0
- package/skills/ios/swiftui-liquid-glass/SKILL.md +95 -0
- package/skills/ios/swiftui-liquid-glass/agents/openai.yaml +4 -0
- package/skills/ios/swiftui-liquid-glass/references/liquid-glass.md +280 -0
- package/skills/ios/swiftui-performance-audit/LICENSE +21 -0
- package/skills/ios/swiftui-performance-audit/SKILL.md +111 -0
- package/skills/ios/swiftui-performance-audit/agents/openai.yaml +4 -0
- package/skills/ios/swiftui-performance-audit/references/code-smells.md +150 -0
- package/skills/ios/swiftui-performance-audit/references/demystify-swiftui-performance-wwdc23.md +46 -0
- package/skills/ios/swiftui-performance-audit/references/optimizing-swiftui-performance-instruments.md +29 -0
- package/skills/ios/swiftui-performance-audit/references/profiling-intake.md +44 -0
- package/skills/ios/swiftui-performance-audit/references/report-template.md +47 -0
- package/skills/ios/swiftui-performance-audit/references/understanding-hangs-in-your-app.md +33 -0
- package/skills/ios/swiftui-performance-audit/references/understanding-improving-swiftui-performance.md +52 -0
- package/skills/ios/swiftui-pro/LICENSE +21 -0
- package/skills/ios/swiftui-pro/SKILL.md +108 -0
- package/skills/ios/swiftui-pro/agents/openai.yaml +10 -0
- package/skills/ios/swiftui-pro/assets/swiftui-pro-icon.png +0 -0
- package/skills/ios/swiftui-pro/assets/swiftui-pro-icon.svg +29 -0
- package/skills/ios/swiftui-pro/references/accessibility.md +13 -0
- package/skills/ios/swiftui-pro/references/api.md +39 -0
- package/skills/ios/swiftui-pro/references/data.md +43 -0
- package/skills/ios/swiftui-pro/references/design.md +31 -0
- package/skills/ios/swiftui-pro/references/hygiene.md +9 -0
- package/skills/ios/swiftui-pro/references/navigation.md +14 -0
- package/skills/ios/swiftui-pro/references/performance.md +46 -0
- package/skills/ios/swiftui-pro/references/swift.md +56 -0
- package/skills/ios/swiftui-pro/references/views.md +35 -0
- package/skills/ios/swiftui-ui-patterns/LICENSE +21 -0
- package/skills/ios/swiftui-ui-patterns/SKILL.md +100 -0
- package/skills/ios/swiftui-ui-patterns/agents/openai.yaml +4 -0
- package/skills/ios/swiftui-ui-patterns/references/app-wiring.md +201 -0
- package/skills/ios/swiftui-ui-patterns/references/async-state.md +96 -0
- package/skills/ios/swiftui-ui-patterns/references/components-index.md +50 -0
- package/skills/ios/swiftui-ui-patterns/references/controls.md +57 -0
- package/skills/ios/swiftui-ui-patterns/references/deeplinks.md +66 -0
- package/skills/ios/swiftui-ui-patterns/references/focus.md +90 -0
- package/skills/ios/swiftui-ui-patterns/references/form.md +97 -0
- package/skills/ios/swiftui-ui-patterns/references/grids.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/haptics.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/input-toolbar.md +51 -0
- package/skills/ios/swiftui-ui-patterns/references/lightweight-clients.md +93 -0
- package/skills/ios/swiftui-ui-patterns/references/list.md +86 -0
- package/skills/ios/swiftui-ui-patterns/references/loading-placeholders.md +38 -0
- package/skills/ios/swiftui-ui-patterns/references/macos-settings.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/matched-transitions.md +59 -0
- package/skills/ios/swiftui-ui-patterns/references/media.md +73 -0
- package/skills/ios/swiftui-ui-patterns/references/menu-bar.md +101 -0
- package/skills/ios/swiftui-ui-patterns/references/navigationstack.md +159 -0
- package/skills/ios/swiftui-ui-patterns/references/overlay.md +45 -0
- package/skills/ios/swiftui-ui-patterns/references/performance.md +62 -0
- package/skills/ios/swiftui-ui-patterns/references/previews.md +48 -0
- package/skills/ios/swiftui-ui-patterns/references/scroll-reveal.md +133 -0
- package/skills/ios/swiftui-ui-patterns/references/scrollview.md +87 -0
- package/skills/ios/swiftui-ui-patterns/references/searchable.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/sheets.md +155 -0
- package/skills/ios/swiftui-ui-patterns/references/split-views.md +72 -0
- package/skills/ios/swiftui-ui-patterns/references/tabview.md +114 -0
- package/skills/ios/swiftui-ui-patterns/references/theming.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/title-menus.md +93 -0
- package/skills/ios/swiftui-ui-patterns/references/top-bar.md +49 -0
- package/skills/ios/swiftui-view-refactor/LICENSE +21 -0
- package/skills/ios/swiftui-view-refactor/SKILL.md +207 -0
- package/skills/ios/swiftui-view-refactor/agents/openai.yaml +4 -0
- package/skills/ios/swiftui-view-refactor/references/mv-patterns.md +161 -0
- package/skills/ios/widgetkit/LICENSE +131 -0
- package/skills/ios/widgetkit/SKILL.md +502 -0
- package/skills/ios/widgetkit/references/widgetkit-advanced.md +871 -0
- package/skills/ios/writing-for-interfaces/SKILL.md +75 -0
- package/skills/web/accessibility/SKILL.md +146 -0
- package/skills/web/aceternity-ui/SKILL.md +719 -0
- package/skills/web/aceternity-ui/metadata.json +10 -0
- package/skills/web/api-design/SKILL.md +523 -0
- package/skills/web/chart-accessibility/SKILL.md +332 -0
- package/skills/web/composition-patterns/AGENTS.md +946 -0
- package/skills/web/composition-patterns/README.md +60 -0
- package/skills/web/composition-patterns/SKILL.md +89 -0
- package/skills/web/composition-patterns/metadata.json +11 -0
- package/skills/web/composition-patterns/rules/_sections.md +29 -0
- package/skills/web/composition-patterns/rules/_template.md +24 -0
- package/skills/web/composition-patterns/rules/architecture-avoid-boolean-props.md +100 -0
- package/skills/web/composition-patterns/rules/architecture-compound-components.md +112 -0
- package/skills/web/composition-patterns/rules/patterns-children-over-render-props.md +87 -0
- package/skills/web/composition-patterns/rules/patterns-explicit-variants.md +100 -0
- package/skills/web/composition-patterns/rules/react19-no-forwardref.md +42 -0
- package/skills/web/composition-patterns/rules/state-context-interface.md +191 -0
- package/skills/web/composition-patterns/rules/state-decouple-implementation.md +113 -0
- package/skills/web/composition-patterns/rules/state-lift-state.md +125 -0
- package/skills/web/cost-aware-llm-pipeline/SKILL.md +183 -0
- package/skills/web/database-migrations/SKILL.md +429 -0
- package/skills/web/deployment-patterns/SKILL.md +427 -0
- package/skills/web/docker-patterns/SKILL.md +364 -0
- package/skills/web/e2e-testing/SKILL.md +326 -0
- package/skills/web/lighthouse-ci/SKILL.md +361 -0
- package/skills/web/mcp-server-patterns/SKILL.md +69 -0
- package/skills/web/next-best-practices/SKILL.md +153 -0
- package/skills/web/next-best-practices/async-patterns.md +87 -0
- package/skills/web/next-best-practices/bundling.md +180 -0
- package/skills/web/next-best-practices/data-patterns.md +297 -0
- package/skills/web/next-best-practices/debug-tricks.md +105 -0
- package/skills/web/next-best-practices/directives.md +73 -0
- package/skills/web/next-best-practices/error-handling.md +227 -0
- package/skills/web/next-best-practices/file-conventions.md +140 -0
- package/skills/web/next-best-practices/font.md +245 -0
- package/skills/web/next-best-practices/functions.md +108 -0
- package/skills/web/next-best-practices/hydration-error.md +91 -0
- package/skills/web/next-best-practices/image.md +173 -0
- package/skills/web/next-best-practices/metadata.md +301 -0
- package/skills/web/next-best-practices/parallel-routes.md +287 -0
- package/skills/web/next-best-practices/route-handlers.md +146 -0
- package/skills/web/next-best-practices/rsc-boundaries.md +159 -0
- package/skills/web/next-best-practices/runtime-selection.md +39 -0
- package/skills/web/next-best-practices/scripts.md +141 -0
- package/skills/web/next-best-practices/self-hosting.md +371 -0
- package/skills/web/next-best-practices/suspense-boundaries.md +67 -0
- package/skills/web/next-cache-components/SKILL.md +411 -0
- package/skills/web/postgres-best-practices/SKILL.md +14 -0
- package/skills/web/postgres-best-practices/references/schema-design.md +9 -0
- package/skills/web/react-best-practices/AGENTS.md +3810 -0
- package/skills/web/react-best-practices/README.md +123 -0
- package/skills/web/react-best-practices/SKILL.md +149 -0
- package/skills/web/react-best-practices/metadata.json +15 -0
- package/skills/web/react-best-practices/rules/_sections.md +46 -0
- package/skills/web/react-best-practices/rules/_template.md +28 -0
- package/skills/web/react-best-practices/rules/advanced-effect-event-deps.md +56 -0
- package/skills/web/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/skills/web/react-best-practices/rules/advanced-init-once.md +42 -0
- package/skills/web/react-best-practices/rules/advanced-use-latest.md +39 -0
- package/skills/web/react-best-practices/rules/async-api-routes.md +38 -0
- package/skills/web/react-best-practices/rules/async-cheap-condition-before-await.md +37 -0
- package/skills/web/react-best-practices/rules/async-defer-await.md +82 -0
- package/skills/web/react-best-practices/rules/async-dependencies.md +51 -0
- package/skills/web/react-best-practices/rules/async-parallel.md +28 -0
- package/skills/web/react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/skills/web/react-best-practices/rules/bundle-analyzable-paths.md +63 -0
- package/skills/web/react-best-practices/rules/bundle-barrel-imports.md +60 -0
- package/skills/web/react-best-practices/rules/bundle-conditional.md +31 -0
- package/skills/web/react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/skills/web/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/skills/web/react-best-practices/rules/bundle-preload.md +50 -0
- package/skills/web/react-best-practices/rules/client-event-listeners.md +74 -0
- package/skills/web/react-best-practices/rules/client-localstorage-schema.md +71 -0
- package/skills/web/react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/skills/web/react-best-practices/rules/client-swr-dedup.md +56 -0
- package/skills/web/react-best-practices/rules/js-batch-dom-css.md +107 -0
- package/skills/web/react-best-practices/rules/js-cache-function-results.md +80 -0
- package/skills/web/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/skills/web/react-best-practices/rules/js-cache-storage.md +70 -0
- package/skills/web/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/skills/web/react-best-practices/rules/js-early-exit.md +50 -0
- package/skills/web/react-best-practices/rules/js-flatmap-filter.md +60 -0
- package/skills/web/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/skills/web/react-best-practices/rules/js-index-maps.md +37 -0
- package/skills/web/react-best-practices/rules/js-length-check-first.md +49 -0
- package/skills/web/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/skills/web/react-best-practices/rules/js-request-idle-callback.md +105 -0
- package/skills/web/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/skills/web/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/skills/web/react-best-practices/rules/rendering-activity.md +26 -0
- package/skills/web/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/skills/web/react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/skills/web/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/skills/web/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/skills/web/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/skills/web/react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
- package/skills/web/react-best-practices/rules/rendering-resource-hints.md +85 -0
- package/skills/web/react-best-practices/rules/rendering-script-defer-async.md +68 -0
- package/skills/web/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/skills/web/react-best-practices/rules/rendering-usetransition-loading.md +75 -0
- package/skills/web/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/skills/web/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/skills/web/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
- package/skills/web/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/skills/web/react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/skills/web/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/skills/web/react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
- package/skills/web/react-best-practices/rules/rerender-memo.md +44 -0
- package/skills/web/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
- package/skills/web/react-best-practices/rules/rerender-no-inline-components.md +82 -0
- package/skills/web/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
- package/skills/web/react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
- package/skills/web/react-best-practices/rules/rerender-transitions.md +40 -0
- package/skills/web/react-best-practices/rules/rerender-use-deferred-value.md +59 -0
- package/skills/web/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
- package/skills/web/react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/skills/web/react-best-practices/rules/server-auth-actions.md +96 -0
- package/skills/web/react-best-practices/rules/server-cache-lru.md +41 -0
- package/skills/web/react-best-practices/rules/server-cache-react.md +76 -0
- package/skills/web/react-best-practices/rules/server-dedup-props.md +65 -0
- package/skills/web/react-best-practices/rules/server-hoist-static-io.md +149 -0
- package/skills/web/react-best-practices/rules/server-no-shared-module-state.md +50 -0
- package/skills/web/react-best-practices/rules/server-parallel-fetching.md +83 -0
- package/skills/web/react-best-practices/rules/server-parallel-nested-fetching.md +34 -0
- package/skills/web/react-best-practices/rules/server-serialization.md +38 -0
- package/skills/web/seo/SKILL.md +154 -0
- package/skills/web/web-design-guidelines/SKILL.md +39 -0
- package/skills/web/zap-scan-config/SKILL.md +444 -0
- package/skills/web/zap-scan-config/assets/.gitkeep +9 -0
- package/skills/web/zap-scan-config/assets/github_action.yml +207 -0
- package/skills/web/zap-scan-config/assets/gitlab_ci.yml +226 -0
- package/skills/web/zap-scan-config/assets/zap_automation.yaml +196 -0
- package/skills/web/zap-scan-config/assets/zap_context.xml +192 -0
- package/skills/web/zap-scan-config/references/EXAMPLE.md +40 -0
- package/skills/web/zap-scan-config/references/api_testing_guide.md +475 -0
- package/skills/web/zap-scan-config/references/authentication_guide.md +431 -0
- package/skills/web/zap-scan-config/references/false_positive_handling.md +427 -0
- package/skills/web/zap-scan-config/references/owasp_mapping.md +255 -0
- package/src/lrr/aggregator.ts +80 -0
- package/src/orchestrator/hooks/context-header.ts +95 -0
- package/src/orchestrator/hooks/token-accounting-emitter.ts +77 -0
- package/src/orchestrator/hooks/token-accounting.ts +101 -0
- package/src/orchestrator/mcp/cycle-counter.ts +129 -0
- package/src/orchestrator/mcp/scribe.ts +283 -0
- package/src/orchestrator/mcp/state-save.ts +149 -0
- package/src/orchestrator/mcp/write-lease.ts +167 -0
- package/src/orchestrator/phase4-shared-context.ts +41 -0
- package/src/orchestrator/schemas/backward-edge.ts +46 -0
- package/agents/agentic-identity-trust.md +0 -121
- package/agents/data-consolidation-agent.md +0 -39
- package/agents/design-image-prompt-engineer.md +0 -105
- package/agents/design-visual-storyteller.md +0 -147
- package/agents/design-whimsy-injector.md +0 -89
- package/agents/engineering-autonomous-optimization-architect.md +0 -105
- package/agents/market-intel.md +0 -35
- package/agents/marketing-instagram-curator.md +0 -111
- package/agents/marketing-reddit-community-builder.md +0 -121
- package/agents/marketing-social-media-strategist.md +0 -74
- package/agents/marketing-tiktok-strategist.md +0 -123
- package/agents/marketing-twitter-engager.md +0 -124
- package/agents/marketing-wechat-official-account.md +0 -143
- package/agents/marketing-xiaohongshu-specialist.md +0 -136
- package/agents/marketing-zhihu-strategist.md +0 -160
- package/agents/product-behavioral-nudge-engine.md +0 -78
- package/agents/project-management-experiment-tracker.md +0 -102
- package/agents/report-distribution-agent.md +0 -43
- package/agents/risk-analysis.md +0 -45
- package/agents/sales-data-extraction-agent.md +0 -46
- package/agents/specialized-cultural-intelligence-strategist.md +0 -65
- package/agents/specialized-developer-advocate.md +0 -146
- package/agents/support-analytics-reporter.md +0 -133
- package/agents/support-executive-summary-generator.md +0 -64
- package/agents/support-finance-tracker.md +0 -145
- package/agents/support-legal-compliance-checker.md +0 -129
- package/agents/support-support-responder.md +0 -91
- package/agents/testing-accessibility-auditor.md +0 -110
- package/agents/testing-test-results-analyzer.md +0 -97
- package/agents/testing-tool-evaluator.md +0 -76
- package/agents/testing-workflow-optimizer.md +0 -99
- package/agents/user-research.md +0 -40
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
# Keychain Sharing: Access Groups, Extensions, and Cross-Device Sync
|
|
2
|
+
|
|
3
|
+
> Scope: Access-group design and entitlement correctness for sharing keychain items across app targets, extensions, and devices.
|
|
4
|
+
|
|
5
|
+
Keychain access groups are the sole mechanism for sharing credentials between apps and extensions on Apple platforms. Correct configuration requires exact Team ID prefixes, per-target entitlements, and explicit `kSecAttrAccessGroup` usage in code — three requirements that most AI-generated code gets wrong. This reference covers access group mechanics, the two entitlement systems, correct and incorrect Swift patterns, macOS-specific requirements, iCloud sync, platform edge cases, and debugging strategies. All guidance reflects current behavior through iOS 18, macOS Sequoia 15, and the 2025–2026 developer landscape.
|
|
6
|
+
|
|
7
|
+
**Authoritative sources:** Apple "Sharing Access to Keychain Items Among a Collection of Apps" documentation, TN3137 "On Mac Keychain APIs and Implementations," Apple Platform Security Guide (iCloud Keychain syncing), Quinn "The Eskimo!" DTS forum posts "SecItem: Fundamentals" and "SecItem: Pitfalls and Best Practices" (updated May 2025), Configuring Keychain Sharing documentation.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## How Access Groups Work
|
|
12
|
+
|
|
13
|
+
Every app belongs to one or more **access groups** — string identifiers that tag which processes can read and write specific keychain items. An app can belong to many groups, but each keychain item belongs to **exactly one**. The `securityd` daemon enforces access by checking the calling process's entitlements against the item's group at runtime.
|
|
14
|
+
|
|
15
|
+
The system constructs a virtual array of access groups for each app by concatenating three sources **in this exact order**:
|
|
16
|
+
|
|
17
|
+
1. **Keychain access groups** from the `keychain-access-groups` entitlement
|
|
18
|
+
2. **Application identifier** — automatically generated as `TeamID.BundleID` (e.g., `SKMME9E2Y8.com.example.MyApp`)
|
|
19
|
+
3. **App groups** from the `com.apple.security.application-groups` entitlement (iOS 8+)
|
|
20
|
+
|
|
21
|
+
**The first item in this concatenated list becomes the default access group.** When `SecItemAdd` is called without specifying `kSecAttrAccessGroup`, the item lands in that default group. When `SecItemCopyMatching` is called without specifying a group, the search spans **all** groups the app belongs to. This ordering means a keychain access group can be the default (it appears first), but an app group can never be the default because the application identifier always precedes it.
|
|
22
|
+
|
|
23
|
+
Example for an app with one keychain group and one app group:
|
|
24
|
+
|
|
25
|
+
```text
|
|
26
|
+
[SKMME9E2Y8.com.example.SharedItems, ← keychain access group (default)
|
|
27
|
+
SKMME9E2Y8.com.example.MyApp, ← application identifier (automatic)
|
|
28
|
+
group.com.example.AppSuite] ← app group
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Sharing is restricted to a single development team.** Apps from different developer teams cannot share keychain items through access groups. The Team ID prefix on every group identifier, enforced through code-signed provisioning profiles, prevents cross-team access. The only way different developers' apps can share credentials is through iCloud Keychain + Associated Domains (password autofill based on web domain ownership), which is an entirely different mechanism.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Two Entitlements, Two Formats, Different Purposes
|
|
36
|
+
|
|
37
|
+
The most common developer mistake is **confusing Keychain Sharing with App Groups**. These are separate capabilities with different entitlement keys, different identifier formats, and different scopes.
|
|
38
|
+
|
|
39
|
+
### Keychain Sharing (`keychain-access-groups`)
|
|
40
|
+
|
|
41
|
+
This entitlement exists solely for sharing keychain items between apps. Identifiers are prefixed with the Team ID:
|
|
42
|
+
|
|
43
|
+
```xml
|
|
44
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
45
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
|
|
46
|
+
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
47
|
+
<plist version="1.0">
|
|
48
|
+
<dict>
|
|
49
|
+
<key>keychain-access-groups</key>
|
|
50
|
+
<array>
|
|
51
|
+
<string>$(AppIdentifierPrefix)com.example.SharedItems</string>
|
|
52
|
+
</array>
|
|
53
|
+
</dict>
|
|
54
|
+
</plist>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The `$(AppIdentifierPrefix)` build variable resolves at signing time to the Team ID followed by a dot (e.g., `SKMME9E2Y8.`). In code, the fully resolved string is required — `"SKMME9E2Y8.com.example.SharedItems"` — not just `"com.example.SharedItems"`.
|
|
58
|
+
|
|
59
|
+
### App Groups (`com.apple.security.application-groups`)
|
|
60
|
+
|
|
61
|
+
App Groups share more than keychain items: shared file containers, `UserDefaults(suiteName:)`, and IPC. The identifier uses a `group.` prefix with **no Team ID**:
|
|
62
|
+
|
|
63
|
+
```xml
|
|
64
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
65
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
|
|
66
|
+
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
67
|
+
<plist version="1.0">
|
|
68
|
+
<dict>
|
|
69
|
+
<key>com.apple.security.application-groups</key>
|
|
70
|
+
<array>
|
|
71
|
+
<string>group.com.example.AppSuite</string>
|
|
72
|
+
</array>
|
|
73
|
+
</dict>
|
|
74
|
+
</plist>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Since iOS 8, app group names double as keychain access groups — `"group.com.example.AppSuite"` can be used as the `kSecAttrAccessGroup` value. However, App Groups appear last in the access group array and **can never be the default group for new items**. A critical macOS caveat: **app groups cannot be used as keychain access groups on macOS** — this is an iOS/iPadOS-only feature.
|
|
78
|
+
|
|
79
|
+
### Comparison Table
|
|
80
|
+
|
|
81
|
+
| Aspect | Keychain Sharing | App Groups |
|
|
82
|
+
| -------------------------- | ------------------------------------------ | ------------------------------------------------------------ |
|
|
83
|
+
| **Entitlement key** | `keychain-access-groups` | `com.apple.security.application-groups` |
|
|
84
|
+
| **Format** | `$(AppIdentifierPrefix)com.example.shared` | `group.com.example.shared` |
|
|
85
|
+
| **Team ID prefix** | Yes (automatic via build variable) | No (`group.` prefix instead) |
|
|
86
|
+
| **Shares** | Keychain items only | Containers, UserDefaults, IPC, and keychain items (iOS only) |
|
|
87
|
+
| **Can be default group** | Yes (if first in array) | No |
|
|
88
|
+
| **macOS keychain sharing** | Yes (with data protection keychain) | No |
|
|
89
|
+
|
|
90
|
+
Both entitlements can be used simultaneously. If only keychain sharing is needed, use Keychain Sharing. If App Groups are already in use for shared UserDefaults or file containers, they can piggyback for keychain sharing on iOS — but always specify `kSecAttrAccessGroup` explicitly.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Code Patterns: Correct and Incorrect
|
|
95
|
+
|
|
96
|
+
### Storing an item with an explicit access group
|
|
97
|
+
|
|
98
|
+
```swift
|
|
99
|
+
import Security
|
|
100
|
+
|
|
101
|
+
let teamID = "SKMME9E2Y8"
|
|
102
|
+
let accessGroup = "\(teamID).com.example.SharedItems"
|
|
103
|
+
|
|
104
|
+
let password = "s3cretT0ken".data(using: .utf8)!
|
|
105
|
+
let addQuery: [String: Any] = [
|
|
106
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
107
|
+
kSecAttrService as String: "com.example.authService",
|
|
108
|
+
kSecAttrAccount as String: "user@example.com",
|
|
109
|
+
kSecAttrAccessGroup as String: accessGroup,
|
|
110
|
+
kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,
|
|
111
|
+
kSecValueData as String: password
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
let status = SecItemAdd(addQuery as CFDictionary, nil)
|
|
115
|
+
guard status == errSecSuccess else {
|
|
116
|
+
print("Keychain add failed: \(status)") // -34018 = missing entitlement
|
|
117
|
+
return
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
The Team ID must be the **literal 10-character string** from the Apple Developer account, not a build variable — `$(AppIdentifierPrefix)` only works in entitlements plists, not in Swift code.
|
|
122
|
+
|
|
123
|
+
### Access group without Team ID prefix (most common AI mistake)
|
|
124
|
+
|
|
125
|
+
```swift
|
|
126
|
+
// ❌ WRONG — Missing Team ID prefix
|
|
127
|
+
let accessGroup = "com.example.SharedItems"
|
|
128
|
+
|
|
129
|
+
let addQuery: [String: Any] = [
|
|
130
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
131
|
+
kSecAttrService as String: "com.example.authService",
|
|
132
|
+
kSecAttrAccount as String: "user@example.com",
|
|
133
|
+
kSecAttrAccessGroup as String: accessGroup, // Will fail!
|
|
134
|
+
kSecValueData as String: password
|
|
135
|
+
]
|
|
136
|
+
// Returns errSecMissingEntitlement (-34018) on iOS 13+
|
|
137
|
+
// Returns errSecItemNotFound (-25300) on older versions
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Xcode's Keychain Sharing UI shows `com.example.SharedItems` without the prefix, which misleads developers and AI generators alike. **In code, the full `TEAMID.com.example.SharedItems` string is always required.**
|
|
141
|
+
|
|
142
|
+
### App extension reading a shared keychain item
|
|
143
|
+
|
|
144
|
+
The extension target must have its own Keychain Sharing capability with the same group:
|
|
145
|
+
|
|
146
|
+
```swift
|
|
147
|
+
// In a widget extension, share extension, or other app extension
|
|
148
|
+
let teamID = "SKMME9E2Y8"
|
|
149
|
+
let accessGroup = "\(teamID).com.example.SharedItems"
|
|
150
|
+
|
|
151
|
+
let readQuery: [String: Any] = [
|
|
152
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
153
|
+
kSecAttrService as String: "com.example.authService",
|
|
154
|
+
kSecAttrAccount as String: "user@example.com",
|
|
155
|
+
kSecAttrAccessGroup as String: accessGroup,
|
|
156
|
+
kSecReturnData as String: true
|
|
157
|
+
]
|
|
158
|
+
|
|
159
|
+
var result: AnyObject?
|
|
160
|
+
let status = SecItemCopyMatching(readQuery as CFDictionary, &result)
|
|
161
|
+
if status == errSecSuccess, let data = result as? Data {
|
|
162
|
+
let token = String(data: data, encoding: .utf8)
|
|
163
|
+
// Use the shared token
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Extension that fails because it lacks the entitlement
|
|
168
|
+
|
|
169
|
+
```swift
|
|
170
|
+
// ❌ This code is syntactically correct, but the extension target is
|
|
171
|
+
// missing the Keychain Sharing capability in Xcode → Signing & Capabilities.
|
|
172
|
+
// The main app has it, but extensions are SEPARATE executable targets.
|
|
173
|
+
// Result: errSecMissingEntitlement (-34018)
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**Each executable target — main app, widget extension, share extension, notification extension — needs its own Keychain Sharing entitlement.** Frameworks do not have entitlements; only the targets linking them do. In Xcode: select the extension target → Signing & Capabilities → + Capability → Keychain Sharing → add the same group name.
|
|
177
|
+
|
|
178
|
+
### iCloud Keychain sync with `kSecAttrSynchronizable`
|
|
179
|
+
|
|
180
|
+
```swift
|
|
181
|
+
let syncQuery: [String: Any] = [
|
|
182
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
183
|
+
kSecAttrService as String: "com.example.authService",
|
|
184
|
+
kSecAttrAccount as String: "user@example.com",
|
|
185
|
+
kSecAttrAccessGroup as String: "\(teamID).com.example.SharedItems",
|
|
186
|
+
kSecAttrSynchronizable as String: kCFBooleanTrue!,
|
|
187
|
+
kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlock,
|
|
188
|
+
kSecValueData as String: password
|
|
189
|
+
]
|
|
190
|
+
let status = SecItemAdd(syncQuery as CFDictionary, nil)
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
**Critical constraints:**
|
|
194
|
+
|
|
195
|
+
- Synchronizable items **cannot** use `kSecAttrAccessible` values ending in `ThisDeviceOnly` — the item would never sync. Attempting this silently fails to sync across devices.
|
|
196
|
+
- When querying for synchronizable items, include `kSecAttrSynchronizable: true` or `kSecAttrSynchronizableAny` — otherwise the search excludes them.
|
|
197
|
+
- The user must have iCloud Keychain enabled and be signed into the same Apple ID on all target devices.
|
|
198
|
+
- Synchronization is orthogonal to on-device sharing: an item can be both in a shared access group and synchronizable across devices.
|
|
199
|
+
|
|
200
|
+
```swift
|
|
201
|
+
// ✅ Query that finds both sync and non-sync items
|
|
202
|
+
let findQuery: [String: Any] = [
|
|
203
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
204
|
+
kSecAttrService as String: "com.example.authService",
|
|
205
|
+
kSecAttrSynchronizable as String: kSecAttrSynchronizableAny,
|
|
206
|
+
kSecReturnData as String: true
|
|
207
|
+
]
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Assuming items sync by default
|
|
211
|
+
|
|
212
|
+
```swift
|
|
213
|
+
// ❌ WRONG — This item will NOT sync to iCloud Keychain.
|
|
214
|
+
// kSecAttrSynchronizable defaults to false when omitted.
|
|
215
|
+
let addQuery: [String: Any] = [
|
|
216
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
217
|
+
kSecAttrService as String: "com.example.authService",
|
|
218
|
+
kSecAttrAccount as String: "user@example.com",
|
|
219
|
+
kSecValueData as String: password
|
|
220
|
+
// No kSecAttrSynchronizable → stays on this device only
|
|
221
|
+
]
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
iCloud Keychain sync is **strictly opt-in per item**. Omitting `kSecAttrSynchronizable` or setting it to `false` means the item exists only on the current device. Synchronized items benefit from end-to-end encryption — Apple cannot decrypt the data.
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## Cross-Target Entitlements Setup
|
|
229
|
+
|
|
230
|
+
Extensions are separate sandboxed executable targets that do **not** inherit capabilities from their containing app.
|
|
231
|
+
|
|
232
|
+
### Xcode Configuration Steps
|
|
233
|
+
|
|
234
|
+
1. Select the main application target → Signing & Capabilities → + Capability → Keychain Sharing.
|
|
235
|
+
2. Add the desired group identifier (e.g., `com.example.shared`). Xcode auto-prefixes with Team ID in the entitlements file.
|
|
236
|
+
3. **Repeat for every extension target** — select the extension target, add Keychain Sharing, add the **exact same** group identifier.
|
|
237
|
+
4. For App Groups: add the App Groups capability to each target and use the same `group.` identifier.
|
|
238
|
+
|
|
239
|
+
### Required Entitlements Matrix
|
|
240
|
+
|
|
241
|
+
| Target | `keychain-access-groups` | `application-groups` | Notes |
|
|
242
|
+
| --------------------- | --------------------------- | ---------------------------- | ------------------------------------ |
|
|
243
|
+
| **Main app** | `TEAMID.com.example.shared` | `group.com.example.appsuite` | First entry defines default group |
|
|
244
|
+
| **Share extension** | `TEAMID.com.example.shared` | `group.com.example.appsuite` | Must match exactly |
|
|
245
|
+
| **Widget extension** | `TEAMID.com.example.shared` | `group.com.example.appsuite` | Independent signing and provisioning |
|
|
246
|
+
| **Notification ext.** | `TEAMID.com.example.shared` | `group.com.example.appsuite` | Same rules apply |
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## The macOS Keychain Split
|
|
251
|
+
|
|
252
|
+
macOS maintains **two completely separate keychain implementations**, and confusing them is a source of endless bugs. Per Apple's TN3137:
|
|
253
|
+
|
|
254
|
+
**File-based keychain** — the legacy system dating back to Mac OS X. Uses Access Control Lists (`SecAccess`), stores items in `.keychain-db` files, and is the default target for `SecItem` API calls on macOS. Does not support iCloud Keychain, biometrics, Secure Enclave keys, or access groups.
|
|
255
|
+
|
|
256
|
+
**Data protection keychain** — originated on iOS and arrived on macOS via iCloud Keychain in 10.9. Uses keychain access groups + `SecAccessControl`, supports iCloud sync, Touch ID/Face ID, and Secure Enclave. Available only in user-login contexts — **`launchd` daemons cannot use it**.
|
|
257
|
+
|
|
258
|
+
### Cross-platform macOS support with `kSecUseDataProtectionKeychain`
|
|
259
|
+
|
|
260
|
+
```swift
|
|
261
|
+
var query: [String: Any] = [
|
|
262
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
263
|
+
kSecAttrService as String: "com.example.authService",
|
|
264
|
+
kSecAttrAccount as String: "user@example.com",
|
|
265
|
+
kSecAttrAccessGroup as String: "\(teamID).com.example.SharedItems",
|
|
266
|
+
kSecUseDataProtectionKeychain as String: true,
|
|
267
|
+
kSecValueData as String: password
|
|
268
|
+
]
|
|
269
|
+
let status = SecItemAdd(query as CFDictionary, nil)
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
On macOS, `kSecAttrAccessGroup` **is silently ignored** unless the data protection keychain is targeted. Setting `kSecUseDataProtectionKeychain` to `true` opts into iOS-style keychain behavior. On iOS, tvOS, and watchOS this key is ignored (those platforms always use data protection).
|
|
273
|
+
|
|
274
|
+
Two ways to target the data protection keychain on macOS: set `kSecUseDataProtectionKeychain` to `true`, or set `kSecAttrSynchronizable` to `true` (which also enables iCloud sync). Mac Catalyst and iOS Apps on Mac use data protection exclusively — the flag is ignored there.
|
|
275
|
+
|
|
276
|
+
| Platform/Runtime | Default keychain | Access groups supported | Required flag |
|
|
277
|
+
| ------------------ | ----------------- | ----------------------- | ------------------------------------- |
|
|
278
|
+
| **iOS/iPadOS** | Data Protection | Yes | None |
|
|
279
|
+
| **Mac Catalyst** | Data Protection | Yes | None |
|
|
280
|
+
| **macOS (AppKit)** | Legacy file-based | No (by default) | `kSecUseDataProtectionKeychain: true` |
|
|
281
|
+
|
|
282
|
+
Apple's TN3137 states the file-based keychain is **"on the road to deprecation."** `SecKeychainCreate` was deprecated in the macOS 12 SDK. New code should target data protection exclusively, with the sole exception of `launchd` daemons that lack a user context.
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## Migrating Items Between Access Groups
|
|
287
|
+
|
|
288
|
+
`kSecAttrAccessGroup` is **immutable** for an existing keychain item — it cannot be changed via `SecItemUpdate`. Migration requires a read-add-delete sequence:
|
|
289
|
+
|
|
290
|
+
1. **Read**: Retrieve the complete item from its original access group via `SecItemCopyMatching`.
|
|
291
|
+
2. **Add**: Call `SecItemAdd` with the new `kSecAttrAccessGroup`.
|
|
292
|
+
3. **Delete**: Only after `SecItemAdd` returns `errSecSuccess`, delete the original item via `SecItemDelete`.
|
|
293
|
+
|
|
294
|
+
If the add operation fails, the original item remains untouched, preventing data loss. This pattern is safe because it never deletes until the new copy is confirmed.
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## Lifecycle Edge Cases
|
|
299
|
+
|
|
300
|
+
### Keychain items persist after app uninstall
|
|
301
|
+
|
|
302
|
+
This behavior is undocumented but has been consistent since iOS's early days. Apple attempted to delete keychain items on app removal in iOS 10.3 beta but rolled it back before release due to compatibility issues. Quinn "The Eskimo!" has warned this behavior **could change without notice**. If shared keychain items exist between App A and App B, deleting App A leaves all shared items intact for App B. Even deleting all apps in a shared group does not remove orphaned items — only a factory reset clears them reliably.
|
|
303
|
+
|
|
304
|
+
A common workaround for detecting fresh installs (since `UserDefaults` _are_ wiped on uninstall):
|
|
305
|
+
|
|
306
|
+
```swift
|
|
307
|
+
func clearKeychainOnFreshInstall() {
|
|
308
|
+
let hasLaunchedBefore = UserDefaults.standard.bool(forKey: "hasLaunchedBefore")
|
|
309
|
+
if !hasLaunchedBefore {
|
|
310
|
+
// Scope deletion to specific service/group to avoid nuking shared items
|
|
311
|
+
let query: [String: Any] = [
|
|
312
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
313
|
+
kSecAttrService as String: "com.example.authService"
|
|
314
|
+
]
|
|
315
|
+
SecItemDelete(query as CFDictionary)
|
|
316
|
+
UserDefaults.standard.set(true, forKey: "hasLaunchedBefore")
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
> For the complete versioned migration approach and fresh-install detection pattern, see `migration-legacy-stores.md` § First-Launch Keychain Cleanup.
|
|
322
|
+
> Key point: The pattern above handles the basic sharing-context case; the canonical file covers multi-version migration coordination, safe deletion ordering, and CI implications.
|
|
323
|
+
|
|
324
|
+
### App transfers between teams break keychain access
|
|
325
|
+
|
|
326
|
+
Items are tied to the original Team ID. If an app is transferred to another developer account, keychain items stored under the old Team ID become inaccessible. Recommended workaround: transfer the app back, release an update that exports/migrates keychain data to an external store, then transfer again.
|
|
327
|
+
|
|
328
|
+
### Cross-developer sharing is impossible via access groups
|
|
329
|
+
|
|
330
|
+
The Team ID prefix enforcement, through code-signed provisioning profiles, prevents apps from different teams from accessing each other's keychain items. Cross-developer credential sharing requires iCloud Keychain + Associated Domains (password autofill based on web domain ownership).
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
## Platform-Specific Patterns
|
|
335
|
+
|
|
336
|
+
### watchOS
|
|
337
|
+
|
|
338
|
+
watchOS 2+ runs a **separate keychain** not connected to the paired iPhone's keychain through access groups. Sharing credentials between iPhone and Watch requires either iCloud Keychain sync (`kSecAttrSynchronizable: true`, available since watchOS 6.2) or WatchConnectivity data transfer. For watchOS apps, add Keychain Sharing to the **WatchKit Extension target**, not the WatchKit App target.
|
|
339
|
+
|
|
340
|
+
### Widget Extensions (WidgetKit)
|
|
341
|
+
|
|
342
|
+
Widget extensions follow the same rules as all app extensions — add Keychain Sharing or App Groups capabilities to the widget extension target independently. Widgets commonly need auth tokens for network requests. Store these in the shared keychain group rather than `UserDefaults(suiteName:)`, which lacks keychain-level encryption. App Group shared containers use only standard filesystem encryption (`NSFileProtectionCompleteUntilFirstUserAuthentication`), making the keychain the more secure choice for sensitive credentials.
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## Build and Distribution Considerations
|
|
347
|
+
|
|
348
|
+
The entitlement format and Team ID prefix rules are consistent across all build configurations: development, Ad Hoc, TestFlight, and App Store distribution. The Team ID is inherent to the developer account and does not change between configurations.
|
|
349
|
+
|
|
350
|
+
However, the specific **provisioning profile** for each distribution type dictates which entitlements are allowed and embeds the correct `AppIdentifierPrefix`. Verify that the provisioning profile for each build type correctly authorizes the required access groups.
|
|
351
|
+
|
|
352
|
+
**Legacy account caveat:** Most modern accounts use the Team ID as the App ID prefix, but legacy accounts (pre-June 2011) may have per-app prefixes that differ from the Team ID. Adding capabilities like Associated Domains to one target but not another has been reported to change the prefix, causing `-34018` errors. Ensure all targets sharing a keychain group have identical capabilities.
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## Debugging When Keychain Sharing Breaks
|
|
357
|
+
|
|
358
|
+
### Essential Error Codes
|
|
359
|
+
|
|
360
|
+
| Code | Constant | Meaning |
|
|
361
|
+
| ---------- | ----------------------------- | ---------------------------------------------------------------- |
|
|
362
|
+
| **0** | `errSecSuccess` | Operation succeeded |
|
|
363
|
+
| **-25299** | `errSecDuplicateItem` | Item exists; use `SecItemUpdate` instead |
|
|
364
|
+
| **-25300** | `errSecItemNotFound` | No match found; also returned pre-iOS 13 for unauthorized groups |
|
|
365
|
+
| **-34018** | `errSecMissingEntitlement` | App lacks entitlement for the specified access group |
|
|
366
|
+
| **-25308** | `errSecInteractionNotAllowed` | Device locked and item requires `WhenUnlocked` access |
|
|
367
|
+
| **-50** | `errSecParam` | Invalid parameter (missing `kSecClass`, wrong value types) |
|
|
368
|
+
|
|
369
|
+
Starting with **iOS 13**, querying an unauthorized access group returns the explicit `errSecMissingEntitlement` (-34018) instead of the ambiguous `errSecItemNotFound`. This makes debugging significantly easier on modern OS versions.
|
|
370
|
+
|
|
371
|
+
### Debugging Checklist
|
|
372
|
+
|
|
373
|
+
**1. Verify entitlements on the built binary** — not the `.entitlements` source file:
|
|
374
|
+
|
|
375
|
+
```bash
|
|
376
|
+
codesign -d --entitlements :- /path/to/YourApp.app
|
|
377
|
+
codesign -d --entitlements :- /path/to/YourExtension.appex
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
Compare the `keychain-access-groups` arrays — they must contain a common group.
|
|
381
|
+
|
|
382
|
+
**2. Inspect the provisioning profile:**
|
|
383
|
+
|
|
384
|
+
```bash
|
|
385
|
+
security cms -D -i YourApp.app/embedded.mobileprovision
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
Verify that `keychain-access-groups`, `com.apple.security.application-groups`, and `com.apple.developer.team-identifier` are present and correct.
|
|
389
|
+
|
|
390
|
+
**3. Test on a physical device.** The iOS Simulator does not use real provisioning profiles and may not surface entitlement issues. Keychain Sharing behavior in the Simulator can differ from device behavior.
|
|
391
|
+
|
|
392
|
+
**4. Monitor system logs.** Open Console.app, select the connected device, filter for "keychain", and reproduce the issue. The system logs explicit messages when an entitlement check fails, identifying the missing group.
|
|
393
|
+
|
|
394
|
+
**5. Check for App ID prefix mismatches** across all sharing targets — especially if any target has different capabilities enabled.
|
|
395
|
+
|
|
396
|
+
### Test Matrix
|
|
397
|
+
|
|
398
|
+
| Scenario | Main App | Share Ext | Widget Ext | Expected |
|
|
399
|
+
| ------------------------------------------ | :------: | :-------: | :--------: | ----------------------------------------- |
|
|
400
|
+
| Write/read in `TeamID.com.example.shared` | Pass | Pass | Pass | All targets see same item |
|
|
401
|
+
| Write/read in `group.com.example.appsuite` | Pass | Pass | Pass | Only when `kSecAttrAccessGroup` specified |
|
|
402
|
+
| iCloud sync (non-`ThisDeviceOnly`) | Pass | N/A | N/A | Item appears on second device |
|
|
403
|
+
| Missing entitlement in extension | N/A | Fail | N/A | `-34018` or `-25300` |
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
407
|
+
## Security Threat Model Notes
|
|
408
|
+
|
|
409
|
+
- **End-to-end encryption:** Synchronized iCloud Keychain items are encrypted end-to-end; Apple cannot decrypt them.
|
|
410
|
+
- **Malicious device risk:** A device joined to the user's iCloud account could potentially access or poison synchronized keychain items. Always scope secrets minimally and validate data retrieved from shared or synchronized keychains.
|
|
411
|
+
- **Over-sharing risk:** Items placed in a shared access group are readable by all apps in that group. Use the narrowest possible access group — do not share an access group across apps that do not need the same credentials.
|
|
412
|
+
- **Orphaned items:** After all apps in a shared group are uninstalled, keychain items remain on-device until factory reset. Consider this when storing highly sensitive data.
|
|
413
|
+
|
|
414
|
+
---
|
|
415
|
+
|
|
416
|
+
## What Changed in 2024–2026
|
|
417
|
+
|
|
418
|
+
The core `SecItem` API has **not changed**. No new keychain-sharing-specific APIs were introduced in iOS 17, 18, or macOS 14/15. Apple still has not shipped a Swift-native keychain wrapper; the C-based Security framework remains the only official interface.
|
|
419
|
+
|
|
420
|
+
The **Passwords app** introduced in iOS 18 and macOS Sequoia (WWDC 2024) provides a dedicated user-facing interface for managing passwords, passkeys, and verification codes. This is a UI layer over iCloud Keychain — it does not affect the `SecItem` API or access group mechanics.
|
|
421
|
+
|
|
422
|
+
**Passkey enhancements** continued through WWDC 2024–2025, including automatic passkey upgrades and credential import/export APIs (`ASCredentialExportManager`). These operate at the credential-manager level and do not introduce new keychain-sharing mechanisms.
|
|
423
|
+
|
|
424
|
+
`kSecAttrAccessibleAlways` and `kSecAttrAccessibleAlwaysThisDeviceOnly` remain deprecated since iOS 12. Use `kSecAttrAccessibleAfterFirstUnlock` or the more restrictive `kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly`.
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
## Cross-References
|
|
429
|
+
|
|
430
|
+
- `keychain-fundamentals.md` — SecItem CRUD patterns, `kSecUseDataProtectionKeychain` on macOS, query dictionary construction
|
|
431
|
+
- `keychain-access-control.md` — Accessibility constants for shared items, `ThisDeviceOnly` vs syncable implications
|
|
432
|
+
- `keychain-item-classes.md` — Composite primary keys and how `kSecAttrAccessGroup` interacts with each `kSecClass`
|
|
433
|
+
- `common-anti-patterns.md` — Anti-pattern #5 (missing `kSecAttrAccessible`), which compounds in shared contexts
|
|
434
|
+
- `credential-storage-patterns.md` — OAuth token sharing between app and extensions
|
|
435
|
+
|
|
436
|
+
---
|
|
437
|
+
|
|
438
|
+
## Conclusion
|
|
439
|
+
|
|
440
|
+
Keychain sharing on Apple platforms is a precise, entitlement-driven system where small configuration errors — a missing Team ID prefix, a capability not added to an extension target, a forgotten `kSecUseDataProtectionKeychain` on macOS — produce cryptic errors with no runtime warnings. The access group array's three-source concatenation order determines defaults and search scope in ways that catch developers off guard.
|
|
441
|
+
|
|
442
|
+
Three rules prevent most issues: always include the full Team ID prefix in code (`TEAMID.com.example.shared`, never just `com.example.shared`); add Keychain Sharing to every executable target that needs access, not just the main app; and set `kSecUseDataProtectionKeychain` to `true` on macOS for iOS-consistent behavior. For iCloud sync, remember that `kSecAttrSynchronizable` defaults to `false` and that queries must explicitly opt in to find synchronizable items.
|
|
443
|
+
|
|
444
|
+
---
|
|
445
|
+
|
|
446
|
+
## Summary Checklist
|
|
447
|
+
|
|
448
|
+
1. **Team ID prefix in code** — Access group strings in Swift must use the fully resolved `TEAMID.com.example.shared` format; `$(AppIdentifierPrefix)` only works in entitlements plists.
|
|
449
|
+
2. **Per-target entitlements** — Every executable target (main app, each extension) must independently have the Keychain Sharing capability added in Xcode with the same group identifier.
|
|
450
|
+
3. **Keychain Sharing vs App Groups** — These are separate entitlements with different formats (`keychain-access-groups` with Team ID prefix vs `com.apple.security.application-groups` with `group.` prefix). App Groups cannot serve as keychain access groups on macOS.
|
|
451
|
+
4. **Default access group awareness** — The first entry in the concatenated access group array (keychain groups → app identifier → app groups) becomes the default. App Groups can never be the default.
|
|
452
|
+
5. **Explicit `kSecAttrAccessGroup`** — Always specify the access group in both `SecItemAdd` and `SecItemCopyMatching` calls. Omitting it on add uses the default group (which may be unexpected); omitting it on query searches all groups (which may be slow or overly broad).
|
|
453
|
+
6. **iCloud sync is opt-in** — `kSecAttrSynchronizable` defaults to `false`. Sync requires non-`ThisDeviceOnly` accessibility, and queries must include `kSecAttrSynchronizable: true` or `kSecAttrSynchronizableAny` to find synced items.
|
|
454
|
+
7. **macOS data protection keychain** — Set `kSecUseDataProtectionKeychain: true` on all macOS `SecItem` calls. Without it, `kSecAttrAccessGroup` is silently ignored and the legacy file-based keychain is used.
|
|
455
|
+
8. **Items persist after uninstall** — Keychain items survive app deletion. Use a `UserDefaults` flag to detect fresh installs and clean up stale items. Scope deletion carefully to avoid nuking shared items.
|
|
456
|
+
9. **`kSecAttrAccessGroup` is immutable** — Moving an item between groups requires a read-add-delete sequence, not an update.
|
|
457
|
+
10. **Verify built binary entitlements** — Use `codesign -d --entitlements :-` on the built `.app`/`.appex` to confirm entitlements, not the source `.entitlements` file. Test on physical devices; the Simulator may not surface entitlement issues.
|
|
458
|
+
11. **watchOS is isolated** — The Apple Watch has a separate keychain not connected via access groups. Use iCloud Keychain sync or WatchConnectivity for cross-device credential sharing.
|