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,476 @@
|
|
|
1
|
+
# Keychain Item Classes
|
|
2
|
+
|
|
3
|
+
> Scope: Correct class selection and attribute usage for all five `kSecClass` types, with emphasis on uniqueness rules, AutoFill behavior, and migration safety.
|
|
4
|
+
|
|
5
|
+
The five `kSecClass` types — GenericPassword, InternetPassword, Key, Certificate, and Identity — each serve distinct roles with unique attribute requirements that AI code generators routinely get wrong. **Choosing the wrong class** causes silent AutoFill failures, query collisions, and subtle security degradation. This reference covers every class with its composite primary key, required and optional attributes, correct Swift patterns, and the specific mistakes to watch for.
|
|
6
|
+
|
|
7
|
+
The keychain is an encrypted SQLite database optimized for small secrets. Each item class defines a set of attributes forming a **composite primary key** — adding an item whose primary key matches an existing item returns `errSecDuplicateItem` (-25299). Understanding these primary keys is the single most important concept for correct keychain usage.
|
|
8
|
+
|
|
9
|
+
**Sources:** Apple Keychain Services documentation, TN3137 ("On Mac keychain APIs and implementations"), Quinn "The Eskimo!" DTS posts ("SecItem: Fundamentals," "SecItem: Pitfalls and Best Practices"), Apple Platform Security Guide, WWDC 2022–2024 passkey sessions, OWASP MASVS/MASTG.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Composite Primary Keys by Class
|
|
14
|
+
|
|
15
|
+
Every `kSecClass` defines a specific attribute set forming its uniqueness constraint. `kSecAttrAccessGroup` and `kSecAttrSynchronizable` participate in the primary key for all classes.
|
|
16
|
+
|
|
17
|
+
| Class | Primary Key Attributes | Typical Use |
|
|
18
|
+
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- |
|
|
19
|
+
| **GenericPassword** | `kSecAttrService` + `kSecAttrAccount` | App-specific secrets, API tokens, encryption keys |
|
|
20
|
+
| **InternetPassword** | `kSecAttrServer` + `kSecAttrProtocol` + `kSecAttrPort` + `kSecAttrPath` + `kSecAttrAccount` + `kSecAttrSecurityDomain` + `kSecAttrAuthenticationType` | Web credentials, server passwords, AutoFill |
|
|
21
|
+
| **Key** | `kSecAttrApplicationLabel` + `kSecAttrApplicationTag` + `kSecAttrKeyClass` + `kSecAttrKeyType` + `kSecAttrKeySizeInBits` + `kSecAttrEffectiveKeySize` | RSA/EC keys, symmetric keys |
|
|
22
|
+
| **Certificate** | `kSecAttrCertificateType` + `kSecAttrIssuer` + `kSecAttrSerialNumber` | X.509 certificates |
|
|
23
|
+
| **Identity** | Same as Certificate (virtual join, not a stored item) | TLS client auth, code signing |
|
|
24
|
+
|
|
25
|
+
Omitting a primary key attribute does not cause an error — the system uses a nil/empty default. But a second add with the same defaults produces `errSecDuplicateItem`, which is a frequent source of confusion.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## kSecClassGenericPassword — App-Specific Secrets
|
|
30
|
+
|
|
31
|
+
GenericPassword is the correct choice for API tokens, OAuth refresh tokens, encryption keys, and any secret that does not represent a web login credential. Its primary key is effectively **`kSecAttrService` + `kSecAttrAccount`**.
|
|
32
|
+
|
|
33
|
+
**Required for meaningful usage** (not enforced by the API, but omitting them causes collisions): `kSecAttrService` (CFString — typically bundle ID or service identifier) and `kSecAttrAccount` (CFString — the account or key name). The actual secret goes in `kSecValueData` as `Data`.
|
|
34
|
+
|
|
35
|
+
**Optional metadata attributes:** `kSecAttrLabel` (human-readable name), `kSecAttrDescription` (item kind), `kSecAttrComment` (user-editable note), `kSecAttrCreator` and `kSecAttrType` (FourCharCode as CFNumber), `kSecAttrGeneric` (arbitrary CFData for custom metadata), `kSecAttrIsInvisible`/`kSecAttrIsNegative` (boolean flags). System-managed read-only: `kSecAttrCreationDate`, `kSecAttrModificationDate`.
|
|
36
|
+
|
|
37
|
+
### The kSecAttrGeneric trap
|
|
38
|
+
|
|
39
|
+
`kSecAttrGeneric` is **NOT part of the primary key** despite its name suggesting otherwise. Two items with identical `kSecAttrService` + `kSecAttrAccount` but different `kSecAttrGeneric` values still collide — the second add fails with `errSecDuplicateItem`. Yet querying by `kSecAttrGeneric` that does not match returns `errSecItemNotFound` even though an item with that service+account exists. This inconsistency is a major source of bugs.
|
|
40
|
+
|
|
41
|
+
```swift
|
|
42
|
+
// ✅ GenericPassword for an app-specific API token
|
|
43
|
+
let addQuery: [String: Any] = [
|
|
44
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
45
|
+
kSecAttrService as String: "com.myapp.api",
|
|
46
|
+
kSecAttrAccount as String: "oauth-refresh-token",
|
|
47
|
+
kSecValueData as String: tokenString.data(using: .utf8)!,
|
|
48
|
+
kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,
|
|
49
|
+
kSecUseDataProtectionKeychain as String: true
|
|
50
|
+
]
|
|
51
|
+
let status = SecItemAdd(addQuery as CFDictionary, nil)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**When to choose GenericPassword vs InternetPassword:** If the credential belongs to a web domain and you want AutoFill, use InternetPassword. GenericPassword's `kSecAttrService` is an opaque string with no semantic meaning to the system — it cannot trigger Password AutoFill.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## kSecClassInternetPassword — AutoFill and Credential Sharing
|
|
59
|
+
|
|
60
|
+
InternetPassword exists specifically for credentials associated with network services. Its **7-attribute composite primary key** enables the system to match credentials to domains for Password AutoFill, Safari integration, and cross-device sync.
|
|
61
|
+
|
|
62
|
+
Primary key attributes: `kSecAttrServer` (hostname), `kSecAttrProtocol` (e.g., `kSecAttrProtocolHTTPS`), `kSecAttrPort` (CFNumber), `kSecAttrPath` (URL path), `kSecAttrAccount` (username), `kSecAttrSecurityDomain` (HTTP realm), `kSecAttrAuthenticationType` (e.g., `kSecAttrAuthenticationTypeHTMLForm`).
|
|
63
|
+
|
|
64
|
+
**Notable:** `kSecAttrGeneric` and `kSecAttrService` are **NOT available** for InternetPassword — the server/protocol/path attributes serve the equivalent purpose.
|
|
65
|
+
|
|
66
|
+
### How AutoFill Integration Works
|
|
67
|
+
|
|
68
|
+
Password AutoFill matches credentials to apps and websites by comparing `kSecAttrServer` against associated domains. Full integration requires three pieces:
|
|
69
|
+
|
|
70
|
+
1. **Store credentials as InternetPassword** with `kSecAttrServer` set to the website domain
|
|
71
|
+
2. **Configure Associated Domains** by adding `webcredentials:<domain>` to the app's entitlements
|
|
72
|
+
3. **Host an apple-app-site-association file** at `https://<domain>/.well-known/apple-app-site-association` containing `{"webcredentials": {"apps": ["TEAMID.com.example.app"]}}`
|
|
73
|
+
|
|
74
|
+
When all three are in place, the iOS QuickType bar automatically suggests matching credentials. Safari stores all web passwords as `kSecClassInternetPassword` — using GenericPassword for web credentials means the system can never suggest them for AutoFill.
|
|
75
|
+
|
|
76
|
+
```swift
|
|
77
|
+
// ✅ InternetPassword enabling AutoFill
|
|
78
|
+
let addQuery: [String: Any] = [
|
|
79
|
+
kSecClass as String: kSecClassInternetPassword,
|
|
80
|
+
kSecAttrServer as String: "example.com",
|
|
81
|
+
kSecAttrProtocol as String: kSecAttrProtocolHTTPS,
|
|
82
|
+
kSecAttrPort as String: 443,
|
|
83
|
+
kSecAttrPath as String: "/login",
|
|
84
|
+
kSecAttrAccount as String: "user@example.com",
|
|
85
|
+
kSecAttrAuthenticationType as String: kSecAttrAuthenticationTypeHTMLForm,
|
|
86
|
+
kSecValueData as String: "password123".data(using: .utf8)!,
|
|
87
|
+
kSecUseDataProtectionKeychain as String: true
|
|
88
|
+
]
|
|
89
|
+
let status = SecItemAdd(addQuery as CFDictionary, nil)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
```swift
|
|
93
|
+
// ❌ GenericPassword for web credentials — AutoFill will never find these
|
|
94
|
+
let badQuery: [String: Any] = [
|
|
95
|
+
kSecClass as String: kSecClassGenericPassword, // WRONG CLASS
|
|
96
|
+
kSecAttrService as String: "example.com", // Opaque to AutoFill
|
|
97
|
+
kSecAttrAccount as String: "user@example.com",
|
|
98
|
+
kSecValueData as String: "password123".data(using: .utf8)!
|
|
99
|
+
]
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Protocol and Authentication Constants
|
|
103
|
+
|
|
104
|
+
Protocol constants span **30+ values** including `kSecAttrProtocolHTTPS`, `kSecAttrProtocolHTTP`, `kSecAttrProtocolSSH`, `kSecAttrProtocolFTP`, `kSecAttrProtocolIMAPS`, `kSecAttrProtocolSMTP`, and many more. Authentication types include `kSecAttrAuthenticationTypeHTMLForm`, `kSecAttrAuthenticationTypeHTTPBasic`, `kSecAttrAuthenticationTypeHTTPDigest`, and `kSecAttrAuthenticationTypeDefault`.
|
|
105
|
+
|
|
106
|
+
### Credential Provider Extensions (iOS 12+)
|
|
107
|
+
|
|
108
|
+
For third-party password managers, `ASCredentialProviderViewController` enables credential provider extensions. Apps subclass this controller, populate `ASCredentialIdentityStore` with `ASPasswordCredentialIdentity` instances, and override `provideCredentialWithoutUserInteraction(for:)` for tap-to-fill behavior.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## kSecClassKey — Cryptographic Key Management
|
|
113
|
+
|
|
114
|
+
Key items require **`kSecAttrKeyType`** and **`kSecAttrKeySizeInBits`** for generation — omitting either from `SecKeyCreateRandomKey` returns `errSecParam` (-50). The `kSecAttrKeyClass` attribute (`kSecAttrKeyClassPublic`, `kSecAttrKeyClassPrivate`, `kSecAttrKeyClassSymmetric`) is set automatically during generation but must be specified when querying.
|
|
115
|
+
|
|
116
|
+
### ApplicationTag vs ApplicationLabel — The Critical Distinction
|
|
117
|
+
|
|
118
|
+
This confusion is the single most common keychain mistake for cryptographic keys, and AI generators get it wrong constantly:
|
|
119
|
+
|
|
120
|
+
- **`kSecAttrApplicationTag`** (CFData): **Developer-set** binary tag for finding and organizing keys. You choose its content — typically a reverse-DNS string encoded as Data. Part of the primary key. **Use this for lookup.**
|
|
121
|
+
- **`kSecAttrApplicationLabel`** (CFData): **System-generated** SHA-1 hash of the public key bytes (the `subjectPublicKey` element per RFC 5280 §4.1). Part of the primary key. **Used internally for identity formation** — it must match a certificate's `kSecAttrPublicKeyHash` to synthesize a `SecIdentity`. Never set this manually for asymmetric keys.
|
|
122
|
+
- **`kSecAttrLabel`** (CFString): Human-readable display name. NOT part of the primary key. Shows in Keychain Access on macOS.
|
|
123
|
+
|
|
124
|
+
### SecKeyCreateRandomKey — The Preferred API
|
|
125
|
+
|
|
126
|
+
`SecKeyCreateRandomKey` (iOS 10+, macOS 10.12+) generates keys atomically, returns a `SecKey` reference directly, auto-computes `kSecAttrApplicationLabel`, and supports Secure Enclave generation via `kSecAttrTokenID: kSecAttrTokenIDSecureEnclave`. Apple recommends storing **only the private key** and deriving the public key via `SecKeyCopyPublicKey()`.
|
|
127
|
+
|
|
128
|
+
```swift
|
|
129
|
+
// ✅ EC key creation with SecKeyCreateRandomKey
|
|
130
|
+
let tag = "com.myapp.keys.signing".data(using: .utf8)!
|
|
131
|
+
let attributes: [String: Any] = [
|
|
132
|
+
kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
|
|
133
|
+
kSecAttrKeySizeInBits as String: 256,
|
|
134
|
+
kSecPrivateKeyAttrs as String: [
|
|
135
|
+
kSecAttrIsPermanent as String: true,
|
|
136
|
+
kSecAttrApplicationTag as String: tag
|
|
137
|
+
]
|
|
138
|
+
]
|
|
139
|
+
var error: Unmanaged<CFError>?
|
|
140
|
+
guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else {
|
|
141
|
+
throw error!.takeRetainedValue() as Error
|
|
142
|
+
}
|
|
143
|
+
let publicKey = SecKeyCopyPublicKey(privateKey)!
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
```swift
|
|
147
|
+
// ✅ Secure Enclave key with biometric protection
|
|
148
|
+
var accessError: Unmanaged<CFError>?
|
|
149
|
+
guard let accessControl = SecAccessControlCreateWithFlags(
|
|
150
|
+
kCFAllocatorDefault,
|
|
151
|
+
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
|
|
152
|
+
[.privateKeyUsage, .userPresence],
|
|
153
|
+
&accessError
|
|
154
|
+
) else { throw accessError!.takeRetainedValue() as Error }
|
|
155
|
+
|
|
156
|
+
let tag = "com.myapp.keys.se-signing".data(using: .utf8)!
|
|
157
|
+
let attributes: [String: Any] = [
|
|
158
|
+
kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
|
|
159
|
+
kSecAttrKeySizeInBits as String: 256,
|
|
160
|
+
kSecAttrTokenID as String: kSecAttrTokenIDSecureEnclave,
|
|
161
|
+
kSecPrivateKeyAttrs as String: [
|
|
162
|
+
kSecAttrIsPermanent as String: true,
|
|
163
|
+
kSecAttrApplicationTag as String: tag,
|
|
164
|
+
kSecAttrAccessControl as String: accessControl
|
|
165
|
+
]
|
|
166
|
+
]
|
|
167
|
+
var genError: Unmanaged<CFError>?
|
|
168
|
+
guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &genError) else {
|
|
169
|
+
throw genError!.takeRetainedValue() as Error
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Direct `SecItemAdd` for keys is appropriate only when importing — Apple's "import, then add" pattern via `SecKeyCreateWithData`. Always create a `SecKey` object first; avoid adding raw key data directly.
|
|
174
|
+
|
|
175
|
+
### CryptoKit Key Storage Mapping
|
|
176
|
+
|
|
177
|
+
CryptoKit's NIST keys (P256, P384, P521) map to `SecKey` via `SecKeyCreateWithData` with `kSecAttrKeyTypeECSECPrimeRandom`, stored as `kSecClassKey`. **Non-NIST keys** (Curve25519, SymmetricKey) have no `SecKey` equivalent and must be stored as **`kSecClassGenericPassword`** items with raw key data in `kSecValueData`. Secure Enclave keys (`SecureEnclave.P256.Signing.PrivateKey`) export an encrypted blob that only the originating SE can restore — this blob is also stored as a generic password, not a key item.
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## kSecClassCertificate — DER-Encoded Certificate Storage
|
|
182
|
+
|
|
183
|
+
Certificates are **not encrypted** by the keychain (they are public data). The primary key is `kSecAttrCertificateType` + `kSecAttrIssuer` + `kSecAttrSerialNumber`.
|
|
184
|
+
|
|
185
|
+
Creation follows a two-step pattern: first create a `SecCertificate` from DER data, then add via `kSecValueRef`:
|
|
186
|
+
|
|
187
|
+
```swift
|
|
188
|
+
// ✅ Adding a certificate
|
|
189
|
+
guard let certificate = SecCertificateCreateWithData(nil, derData as CFData) else {
|
|
190
|
+
throw CertificateError.invalidDER // Only accepts DER, not PEM
|
|
191
|
+
}
|
|
192
|
+
let addQuery: [String: Any] = [
|
|
193
|
+
kSecClass as String: kSecClassCertificate,
|
|
194
|
+
kSecValueRef as String: certificate,
|
|
195
|
+
kSecUseDataProtectionKeychain as String: true
|
|
196
|
+
]
|
|
197
|
+
let status = SecItemAdd(addQuery as CFDictionary, nil)
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
When you pass a `SecCertificate` via `kSecValueRef`, the system **automatically extracts** `kSecAttrIssuer`, `kSecAttrSerialNumber`, `kSecAttrSubject`, `kSecAttrPublicKeyHash`, `kSecAttrCertificateType`, and `kSecAttrCertificateEncoding` from the certificate data. The critical attribute for identity formation is **`kSecAttrPublicKeyHash`** — the hash of the certificate's public key that must match a private key's `kSecAttrApplicationLabel`.
|
|
201
|
+
|
|
202
|
+
**Common pitfall (Apple DTS):** `kSecAttrApplicationTag` is **NOT a valid attribute for certificates** (only for keys). Using it with `kSecClassCertificate` causes `errSecParam` (-50) on the data protection keychain or mysterious silent failures on the file-based keychain.
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## kSecClassIdentity — The Virtual Join
|
|
207
|
+
|
|
208
|
+
**The keychain does not store digital identities as discrete items.** An identity is a logical join of a certificate and its matching private key, synthesized at query time when `kSecAttrPublicKeyHash` of a certificate matches `kSecAttrApplicationLabel` of a private key — both values being the SHA-1 hash of the public key.
|
|
209
|
+
|
|
210
|
+
### Why SecItemAdd with kSecClassIdentity Fails
|
|
211
|
+
|
|
212
|
+
Attempting `SecItemAdd` with `kSecClass: kSecClassIdentity` will fail with `errSecParam` (-50). The system has no "identity table." Identity items appear only when the matching relationship exists between separately stored certificate and key items.
|
|
213
|
+
|
|
214
|
+
Cascading implications:
|
|
215
|
+
|
|
216
|
+
- Adding a **certificate** can implicitly create an identity if a matching private key already exists
|
|
217
|
+
- Adding a **private key** can implicitly create an identity if a matching certificate exists
|
|
218
|
+
- Deleting a certificate or key can implicitly destroy an identity
|
|
219
|
+
- The identity "set" changes without any explicit identity operations
|
|
220
|
+
|
|
221
|
+
```swift
|
|
222
|
+
// ❌ Attempting to create an identity directly — fails with errSecParam (-50)
|
|
223
|
+
let attributes: [String: Any] = [
|
|
224
|
+
kSecClass as String: kSecClassIdentity,
|
|
225
|
+
kSecAttrLabel as String: "MyInvalidIdentity"
|
|
226
|
+
]
|
|
227
|
+
let status = SecItemAdd(attributes as CFDictionary, nil)
|
|
228
|
+
// status == errSecParam (-50)
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Three Correct Approaches to Creating an Identity
|
|
232
|
+
|
|
233
|
+
**Method 1: PKCS#12 import** (most common for server-issued certificates):
|
|
234
|
+
|
|
235
|
+
```swift
|
|
236
|
+
// ✅ Import identity from .p12 file
|
|
237
|
+
let options: [String: Any] = [kSecImportExportPassphrase as String: "p12password"]
|
|
238
|
+
var items: CFArray?
|
|
239
|
+
let status = SecPKCS12Import(p12Data as CFData, options as CFDictionary, &items)
|
|
240
|
+
guard status == errSecSuccess,
|
|
241
|
+
let results = items as? [[String: Any]],
|
|
242
|
+
let identity = results.first?[kSecImportItemIdentity as String] as? SecIdentity else {
|
|
243
|
+
throw IdentityError.importFailed
|
|
244
|
+
}
|
|
245
|
+
// Extract components
|
|
246
|
+
var certificate: SecCertificate?
|
|
247
|
+
SecIdentityCopyCertificate(identity, &certificate)
|
|
248
|
+
var privateKey: SecKey?
|
|
249
|
+
SecIdentityCopyPrivateKey(identity, &privateKey)
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
**Method 2: Add certificate and key separately** with matching public key hashes. Both items must be in the same keychain implementation — on macOS, both must use `kSecUseDataProtectionKeychain: true` or both must be in the file-based keychain.
|
|
253
|
+
|
|
254
|
+
**Method 3: macOS-only** — `SecIdentityCreateWithCertificate` searches keychains for a matching private key given a certificate reference.
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## Correctness Issues AI Generators Get Wrong
|
|
259
|
+
|
|
260
|
+
### 1. GenericPassword for Everything
|
|
261
|
+
|
|
262
|
+
AI code almost universally uses `kSecClassGenericPassword` with `kSecAttrService` for web credentials, completely missing AutoFill integration. The correct pattern uses `kSecClassInternetPassword` with `kSecAttrServer` and associated domains.
|
|
263
|
+
|
|
264
|
+
### 2. Direct Identity Creation
|
|
265
|
+
|
|
266
|
+
Generated code attempts `SecItemAdd` with `kSecClassIdentity` as if it were a storable item class. Identities must be created through PKCS#12 import or by adding matching certificate and key items separately.
|
|
267
|
+
|
|
268
|
+
### 3. Missing Key Type Attributes
|
|
269
|
+
|
|
270
|
+
Code omits `kSecAttrKeyType` from key queries, producing ambiguous matches across RSA and EC keys. Since key type is part of the composite primary key, this is a correctness bug, not a style issue.
|
|
271
|
+
|
|
272
|
+
### 4. ApplicationTag / ApplicationLabel Confusion
|
|
273
|
+
|
|
274
|
+
Generated code sets `kSecAttrApplicationLabel` as a human-readable string, not understanding it is an auto-generated public key hash used for identity matching. The developer-set tag for lookup is `kSecAttrApplicationTag`.
|
|
275
|
+
|
|
276
|
+
### 5. No Duplicate Handling
|
|
277
|
+
|
|
278
|
+
AI code calls `SecItemAdd` without handling `errSecDuplicateItem`. The correct pattern either attempts update-first-then-add, or catches the duplicate error and calls `SecItemUpdate`:
|
|
279
|
+
|
|
280
|
+
```swift
|
|
281
|
+
// ✅ Update-first pattern (preferred)
|
|
282
|
+
var status = SecItemUpdate(searchQuery as CFDictionary, updateAttrs as CFDictionary)
|
|
283
|
+
if status == errSecItemNotFound {
|
|
284
|
+
var addQuery = searchQuery
|
|
285
|
+
addQuery.merge(updateAttrs) { _, new in new }
|
|
286
|
+
status = SecItemAdd(addQuery as CFDictionary, nil)
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### 6. Missing kSecUseDataProtectionKeychain on macOS
|
|
291
|
+
|
|
292
|
+
Without this flag, macOS defaults to the legacy file-based keychain, causing `kSecAttrAccessible`, `kSecAttrAccessGroup`, and biometric access controls to be silently ignored or behave unexpectedly.
|
|
293
|
+
|
|
294
|
+
### 7. Storing Large Blobs in Keychain
|
|
295
|
+
|
|
296
|
+
The keychain is designed for small secrets. Storing large data degrades performance due to Secure Enclave decryption latency per item retrieval. Use envelope encryption for anything beyond a few KB.
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
## Modern API Patterns and Platform Differences
|
|
301
|
+
|
|
302
|
+
### kSecUseDataProtectionKeychain Unifies Cross-Platform Behavior
|
|
303
|
+
|
|
304
|
+
On **iOS/tvOS/watchOS**, the data protection keychain is the only implementation — this flag is ignored. On **macOS native apps**, `SecItem` defaults to the legacy file-based keychain. Setting `kSecUseDataProtectionKeychain: true` switches to the data protection keychain, giving iOS-identical behavior. On **Mac Catalyst** apps, data protection is the default.
|
|
305
|
+
|
|
306
|
+
Apple explicitly recommends setting this flag to `true` for all keychain operations. The file-based keychain is on the path to deprecation (`SecKeychainCreate` deprecated in macOS 12).
|
|
307
|
+
|
|
308
|
+
### TN3137 Key Takeaways
|
|
309
|
+
|
|
310
|
+
TN3137 documents macOS's **three keychain APIs** (legacy Keychain, SecKeychain, and the recommended SecItem) and **two implementations** (file-based and data protection). Critical routing rule: only `SecItem` can target either implementation; `SecKeychain` always targets file-based. The data protection keychain requires code signing and a provisioning profile on macOS.
|
|
311
|
+
|
|
312
|
+
Subtle behavioral difference: `SecItemDelete` defaults to `kSecMatchLimitAll` on the data protection keychain (deleting ALL matching items) but `kSecMatchLimitOne` on the file-based keychain — an inconsistency documented in Apple's bug tracker (r. 105800863).
|
|
313
|
+
|
|
314
|
+
### iCloud Keychain Sync Restrictions
|
|
315
|
+
|
|
316
|
+
`kSecAttrSynchronizable` must be explicitly set to `true` — items never sync by default. **All five classes** support sync on iOS 14+ / macOS 11+ / watchOS 7+; earlier versions only sync password classes.
|
|
317
|
+
|
|
318
|
+
Key restrictions:
|
|
319
|
+
|
|
320
|
+
- Items with "ThisDeviceOnly" accessibility **cannot** sync — combining `kSecAttrSynchronizable: true` with any `ThisDeviceOnly` accessibility returns `errSecParam` (-50)
|
|
321
|
+
- Persistent references are unsupported for synchronizable items
|
|
322
|
+
- tvOS accepts the attribute but never actually syncs
|
|
323
|
+
- Updates and deletes propagate to all copies across devices
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## Size Limits, Performance, and When to Use Files
|
|
328
|
+
|
|
329
|
+
Apple describes the keychain as storing **"small secrets"** without publishing a hard size limit. The underlying SQLite supports items up to approximately **16 MB** (`SQLITE_MAX_LENGTH`), but this is emphatically not the intended use.
|
|
330
|
+
|
|
331
|
+
### Performance Architecture
|
|
332
|
+
|
|
333
|
+
The keychain has a direct performance implication: **metadata is encrypted with a cached Application Processor key** (enabling fast attribute queries), while **secret values require a Secure Enclave round trip** per access. This means `kSecReturnAttributes`-only queries are substantially faster than `kSecReturnData` queries. Always request only what you need.
|
|
334
|
+
|
|
335
|
+
Query optimization rules:
|
|
336
|
+
|
|
337
|
+
1. **Use full composite keys** — broad queries force `securityd` to perform slow database scans
|
|
338
|
+
2. **Limit matches** — use `kSecMatchLimitOne` when expecting a single item to terminate search early
|
|
339
|
+
3. **Fetch metadata first** — if you only need to check existence, do not request `kSecReturnData`
|
|
340
|
+
|
|
341
|
+
### Envelope Encryption for Large Data
|
|
342
|
+
|
|
343
|
+
For data beyond a few kilobytes, use the **DEK/KEK pattern**: store a 32-byte AES-256 Data Encryption Key (DEK) in the keychain, encrypt the actual data with that key, and write the ciphertext to a file protected by `NSFileProtection`. OWASP MASTG recommends this pattern for MASVS L2 compliance.
|
|
344
|
+
|
|
345
|
+
Accessibility-to-file-protection mapping:
|
|
346
|
+
|
|
347
|
+
- `kSecAttrAccessibleWhenUnlocked` → `NSFileProtectionComplete`
|
|
348
|
+
- `kSecAttrAccessibleAfterFirstUnlock` → `NSFileProtectionCompleteUntilFirstUserAuthentication`
|
|
349
|
+
|
|
350
|
+
### Querying with kSecReturnAttributes for Metadata Inspection
|
|
351
|
+
|
|
352
|
+
```swift
|
|
353
|
+
// ✅ Inspect all metadata for a GenericPassword item
|
|
354
|
+
let query: [String: Any] = [
|
|
355
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
356
|
+
kSecAttrService as String: "com.myapp.api",
|
|
357
|
+
kSecReturnAttributes as String: true,
|
|
358
|
+
kSecReturnData as String: true,
|
|
359
|
+
kSecMatchLimit as String: kSecMatchLimitOne
|
|
360
|
+
]
|
|
361
|
+
var item: CFTypeRef?
|
|
362
|
+
let status = SecItemCopyMatching(query as CFDictionary, &item)
|
|
363
|
+
guard status == errSecSuccess, let attrs = item as? [String: Any] else { return }
|
|
364
|
+
|
|
365
|
+
// Available metadata in the returned dictionary:
|
|
366
|
+
let account = attrs[kSecAttrAccount as String] as? String
|
|
367
|
+
let service = attrs[kSecAttrService as String] as? String
|
|
368
|
+
let created = attrs[kSecAttrCreationDate as String] as? Date
|
|
369
|
+
let modified = attrs[kSecAttrModificationDate as String] as? Date
|
|
370
|
+
let accessible = attrs[kSecAttrAccessible as String] as? String
|
|
371
|
+
let syncable = attrs[kSecAttrSynchronizable as String] as? Bool
|
|
372
|
+
let secretData = attrs[kSecValueData as String] as? Data
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
When both `kSecReturnAttributes` and `kSecReturnData` are true with `kSecMatchLimitOne`, the result is a single dictionary containing all metadata plus the secret data under `kSecValueData`. With `kSecMatchLimitAll`, it is an array of such dictionaries.
|
|
376
|
+
|
|
377
|
+
---
|
|
378
|
+
|
|
379
|
+
## Testing Matrix for Class Correctness
|
|
380
|
+
|
|
381
|
+
| Test Scenario | Expected OSStatus | Rationale |
|
|
382
|
+
| -------------------------------------------------------- | ------------------------------ | ------------------------------------------------- |
|
|
383
|
+
| Add `kSecClassIdentity` via `SecItemAdd` | `errSecParam` (-50) | Identities must be imported, not created directly |
|
|
384
|
+
| Add `kSecClassKey` without `kSecAttrKeyType` | `errSecParam` (-50) | Crypto metadata is strictly required |
|
|
385
|
+
| Add item with identical composite primary key | `errSecDuplicateItem` (-25299) | Requires `SecItemUpdate` or delete-then-add |
|
|
386
|
+
| Sync `true` + `ThisDeviceOnly` accessibility | `errSecParam` (-50) | Contradictory constraints |
|
|
387
|
+
| Use `kSecAttrApplicationTag` with `kSecClassCertificate` | `errSecParam` (-50) | Tag is only valid for key items |
|
|
388
|
+
| Query `kSecClassKey` without `kSecAttrKeyClass` | May return wrong key class | Ambiguous match across public/private/symmetric |
|
|
389
|
+
|
|
390
|
+
---
|
|
391
|
+
|
|
392
|
+
## Migration: GenericPassword to InternetPassword
|
|
393
|
+
|
|
394
|
+
If your application currently stores web credentials as `kSecClassGenericPassword`, migrate to `kSecClassInternetPassword` to enable AutoFill:
|
|
395
|
+
|
|
396
|
+
```swift
|
|
397
|
+
// ✅ Migration pattern: GenericPassword → InternetPassword
|
|
398
|
+
func migrateWebCredentials() throws {
|
|
399
|
+
// 1. Query existing GenericPassword items for web credentials
|
|
400
|
+
let oldQuery: [String: Any] = [
|
|
401
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
402
|
+
kSecAttrService as String: "www.example.com",
|
|
403
|
+
kSecReturnAttributes as String: true,
|
|
404
|
+
kSecReturnData as String: true,
|
|
405
|
+
kSecMatchLimit as String: kSecMatchLimitAll
|
|
406
|
+
]
|
|
407
|
+
|
|
408
|
+
var items: CFTypeRef?
|
|
409
|
+
let fetchStatus = SecItemCopyMatching(oldQuery as CFDictionary, &items)
|
|
410
|
+
guard fetchStatus == errSecSuccess,
|
|
411
|
+
let results = items as? [[String: Any]] else { return }
|
|
412
|
+
|
|
413
|
+
for item in results {
|
|
414
|
+
guard let account = item[kSecAttrAccount as String] as? String,
|
|
415
|
+
let data = item[kSecValueData as String] as? Data else { continue }
|
|
416
|
+
|
|
417
|
+
// 2. Add as InternetPassword with proper attributes
|
|
418
|
+
let newQuery: [String: Any] = [
|
|
419
|
+
kSecClass as String: kSecClassInternetPassword,
|
|
420
|
+
kSecAttrServer as String: "www.example.com",
|
|
421
|
+
kSecAttrProtocol as String: kSecAttrProtocolHTTPS,
|
|
422
|
+
kSecAttrAccount as String: account,
|
|
423
|
+
kSecValueData as String: data,
|
|
424
|
+
kSecUseDataProtectionKeychain as String: true
|
|
425
|
+
]
|
|
426
|
+
let addStatus = SecItemAdd(newQuery as CFDictionary, nil)
|
|
427
|
+
guard addStatus == errSecSuccess || addStatus == errSecDuplicateItem else { continue }
|
|
428
|
+
|
|
429
|
+
// 3. Delete old GenericPassword item
|
|
430
|
+
let deleteQuery: [String: Any] = [
|
|
431
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
432
|
+
kSecAttrService as String: "www.example.com",
|
|
433
|
+
kSecAttrAccount as String: account
|
|
434
|
+
]
|
|
435
|
+
SecItemDelete(deleteQuery as CFDictionary)
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
---
|
|
441
|
+
|
|
442
|
+
## Cross-Reference Index
|
|
443
|
+
|
|
444
|
+
- **SecItem CRUD operations, query dictionaries, error handling** → `keychain-fundamentals.md`
|
|
445
|
+
- **Accessibility constants, SecAccessControl flags** → `keychain-access-control.md`
|
|
446
|
+
- **Biometric protection for keys and passwords** → `biometric-authentication.md`
|
|
447
|
+
- **Secure Enclave key generation and constraints** → `secure-enclave.md`
|
|
448
|
+
- **CryptoKit key types and keychain storage mapping** → `cryptokit-symmetric.md`, `cryptokit-public-key.md`
|
|
449
|
+
- **OAuth tokens, API keys, credential lifecycle** → `credential-storage-patterns.md`
|
|
450
|
+
- **Access groups, app extensions, sharing** → `keychain-sharing.md`
|
|
451
|
+
- **SecCertificate, SecTrust, trust evaluation** → `certificate-trust.md`
|
|
452
|
+
- **Legacy migration patterns** → `migration-legacy-stores.md`
|
|
453
|
+
- **AI-generated code anti-patterns** → `common-anti-patterns.md`
|
|
454
|
+
- **OWASP MASVS/MASTG compliance** → `compliance-owasp-mapping.md`
|
|
455
|
+
|
|
456
|
+
---
|
|
457
|
+
|
|
458
|
+
## Conclusion
|
|
459
|
+
|
|
460
|
+
The keychain's five classes form a precise taxonomy: GenericPassword for app-local secrets, InternetPassword for domain-associated credentials enabling AutoFill, Key for cryptographic material with its tag/label distinction, Certificate for public X.509 data, and Identity as a virtual construct emerging from matching certificate and key items. The most impactful decisions are choosing InternetPassword over GenericPassword for web credentials, always setting `kSecUseDataProtectionKeychain` for cross-platform consistency, understanding that identities cannot be directly created, and recognizing `kSecAttrApplicationTag` (developer-set, for lookup) versus `kSecAttrApplicationLabel` (system-generated, for identity matching) as fundamentally different attributes despite their similar names.
|
|
461
|
+
|
|
462
|
+
---
|
|
463
|
+
|
|
464
|
+
## Summary Checklist
|
|
465
|
+
|
|
466
|
+
1. **Correct class selection** — Use `kSecClassInternetPassword` (not GenericPassword) for any credential associated with a web domain to enable AutoFill
|
|
467
|
+
2. **Composite primary key completeness** — Include all primary key attributes for the chosen class to avoid `errSecDuplicateItem` collisions and query misses
|
|
468
|
+
3. **kSecAttrGeneric is NOT a primary key** — Do not rely on it for uniqueness in GenericPassword items; it causes asymmetric add/query behavior
|
|
469
|
+
4. **ApplicationTag vs ApplicationLabel** — Use `kSecAttrApplicationTag` (developer-set, CFData) for key lookup; never manually set `kSecAttrApplicationLabel` (system-generated hash for identity formation)
|
|
470
|
+
5. **Identity creation via import** — Never `SecItemAdd` with `kSecClassIdentity`; use `SecPKCS12Import` or add matching certificate + key pairs separately
|
|
471
|
+
6. **Key type and size required** — Always specify `kSecAttrKeyType` and `kSecAttrKeySizeInBits` when creating or querying `kSecClassKey` items
|
|
472
|
+
7. **kSecUseDataProtectionKeychain on macOS** — Set to `true` for all operations to get iOS-identical behavior and avoid silent legacy keychain fallback
|
|
473
|
+
8. **Sync and accessibility agreement** — Never combine `kSecAttrSynchronizable: true` with "ThisDeviceOnly" accessibility values
|
|
474
|
+
9. **Small secrets only** — Use envelope encryption (DEK in keychain, ciphertext in `NSFileProtection`-guarded file) for data beyond a few KB
|
|
475
|
+
10. **Certificate attributes** — Never use `kSecAttrApplicationTag` with `kSecClassCertificate`; let the system extract metadata via `kSecValueRef`
|
|
476
|
+
11. **Duplicate handling** — Always handle `errSecDuplicateItem` with an update-first-then-add or delete-then-add pattern
|