@devo-bmad-custom/agent-orchestration 1.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/bin/bmad.js +36 -0
- package/lib/cli.js +137 -0
- package/lib/filter.js +73 -0
- package/lib/installer.js +787 -0
- package/package.json +30 -0
- package/src/.agents/skills/audit-website/README.md +20 -0
- package/src/.agents/skills/audit-website/SKILL.md +470 -0
- package/src/.agents/skills/audit-website/agents/openai.yaml +6 -0
- package/src/.agents/skills/audit-website/assets/icon-small.svg +41 -0
- package/src/.agents/skills/audit-website/references/OUTPUT-FORMAT.md +250 -0
- package/src/.agents/skills/clean-code-standards/SKILL.md +105 -0
- package/src/.agents/skills/excalidraw-dark-standard/SKILL.md +282 -0
- package/src/.agents/skills/excalidraw-diagram-generator/SKILL.md +613 -0
- package/src/.agents/skills/excalidraw-diagram-generator/references/element-types.md +497 -0
- package/src/.agents/skills/excalidraw-diagram-generator/references/excalidraw-schema.md +350 -0
- package/src/.agents/skills/excalidraw-diagram-generator/scripts/README.md +193 -0
- package/src/.agents/skills/excalidraw-diagram-generator/scripts/add-arrow.py +312 -0
- package/src/.agents/skills/excalidraw-diagram-generator/scripts/add-icon-to-diagram.py +404 -0
- package/src/.agents/skills/excalidraw-diagram-generator/scripts/split-excalidraw-library.py +183 -0
- package/src/.agents/skills/excalidraw-diagram-generator/templates/business-flow-swimlane-template.excalidraw +334 -0
- package/src/.agents/skills/excalidraw-diagram-generator/templates/class-diagram-template.excalidraw +558 -0
- package/src/.agents/skills/excalidraw-diagram-generator/templates/data-flow-diagram-template.excalidraw +279 -0
- package/src/.agents/skills/excalidraw-diagram-generator/templates/er-diagram-template.excalidraw +662 -0
- package/src/.agents/skills/excalidraw-diagram-generator/templates/flowchart-template.excalidraw +179 -0
- package/src/.agents/skills/excalidraw-diagram-generator/templates/mindmap-template.excalidraw +244 -0
- package/src/.agents/skills/excalidraw-diagram-generator/templates/relationship-template.excalidraw +145 -0
- package/src/.agents/skills/excalidraw-diagram-generator/templates/sequence-diagram-template.excalidraw +509 -0
- package/src/.agents/skills/frontend-responsive-design-standards/SKILL.md +434 -0
- package/src/.agents/skills/java-fundamentals/SKILL.md +116 -0
- package/src/.agents/skills/java-performance/SKILL.md +119 -0
- package/src/.agents/skills/next-best-practices/SKILL.md +153 -0
- package/src/.agents/skills/next-best-practices/async-patterns.md +87 -0
- package/src/.agents/skills/next-best-practices/bundling.md +180 -0
- package/src/.agents/skills/next-best-practices/data-patterns.md +297 -0
- package/src/.agents/skills/next-best-practices/debug-tricks.md +105 -0
- package/src/.agents/skills/next-best-practices/directives.md +73 -0
- package/src/.agents/skills/next-best-practices/error-handling.md +227 -0
- package/src/.agents/skills/next-best-practices/file-conventions.md +140 -0
- package/src/.agents/skills/next-best-practices/font.md +245 -0
- package/src/.agents/skills/next-best-practices/functions.md +108 -0
- package/src/.agents/skills/next-best-practices/hydration-error.md +91 -0
- package/src/.agents/skills/next-best-practices/image.md +173 -0
- package/src/.agents/skills/next-best-practices/metadata.md +301 -0
- package/src/.agents/skills/next-best-practices/parallel-routes.md +287 -0
- package/src/.agents/skills/next-best-practices/route-handlers.md +146 -0
- package/src/.agents/skills/next-best-practices/rsc-boundaries.md +159 -0
- package/src/.agents/skills/next-best-practices/runtime-selection.md +39 -0
- package/src/.agents/skills/next-best-practices/scripts.md +141 -0
- package/src/.agents/skills/next-best-practices/self-hosting.md +371 -0
- package/src/.agents/skills/next-best-practices/suspense-boundaries.md +67 -0
- package/src/.agents/skills/nextjs-app-router-patterns/SKILL.md +537 -0
- package/src/.agents/skills/postgresql-optimization/SKILL.md +404 -0
- package/src/.agents/skills/python-backend/SKILL.md +153 -0
- package/src/.agents/skills/python-fundamentals/SKILL.md +234 -0
- package/src/.agents/skills/python-performance/SKILL.md +404 -0
- package/src/.agents/skills/react-expert/SKILL.md +335 -0
- package/src/.agents/skills/redis-best-practices/SKILL.md +438 -0
- package/src/.agents/skills/security-best-practices/SKILL.md +288 -0
- package/src/.agents/skills/security-review/LICENSE +22 -0
- package/src/.agents/skills/security-review/SKILL.md +312 -0
- package/src/.agents/skills/security-review/infrastructure/docker.md +432 -0
- package/src/.agents/skills/security-review/languages/javascript.md +388 -0
- package/src/.agents/skills/security-review/languages/python.md +363 -0
- package/src/.agents/skills/security-review/references/api-security.md +519 -0
- package/src/.agents/skills/security-review/references/authentication.md +353 -0
- package/src/.agents/skills/security-review/references/authorization.md +372 -0
- package/src/.agents/skills/security-review/references/business-logic.md +443 -0
- package/src/.agents/skills/security-review/references/cryptography.md +329 -0
- package/src/.agents/skills/security-review/references/csrf.md +398 -0
- package/src/.agents/skills/security-review/references/data-protection.md +378 -0
- package/src/.agents/skills/security-review/references/deserialization.md +410 -0
- package/src/.agents/skills/security-review/references/error-handling.md +436 -0
- package/src/.agents/skills/security-review/references/file-security.md +457 -0
- package/src/.agents/skills/security-review/references/injection.md +259 -0
- package/src/.agents/skills/security-review/references/logging.md +433 -0
- package/src/.agents/skills/security-review/references/misconfiguration.md +435 -0
- package/src/.agents/skills/security-review/references/modern-threats.md +475 -0
- package/src/.agents/skills/security-review/references/ssrf.md +415 -0
- package/src/.agents/skills/security-review/references/supply-chain.md +405 -0
- package/src/.agents/skills/security-review/references/xss.md +336 -0
- package/src/.agents/skills/subagent-driven-development/SKILL.md +275 -0
- package/src/.agents/skills/subagent-driven-development/code-quality-reviewer-prompt.md +26 -0
- package/src/.agents/skills/subagent-driven-development/implementer-prompt.md +113 -0
- package/src/.agents/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -0
- package/src/.agents/skills/systematic-debugging/CREATION-LOG.md +119 -0
- package/src/.agents/skills/systematic-debugging/SKILL.md +296 -0
- package/src/.agents/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
- package/src/.agents/skills/systematic-debugging/condition-based-waiting.md +115 -0
- package/src/.agents/skills/systematic-debugging/defense-in-depth.md +122 -0
- package/src/.agents/skills/systematic-debugging/find-polluter.sh +63 -0
- package/src/.agents/skills/systematic-debugging/root-cause-tracing.md +169 -0
- package/src/.agents/skills/systematic-debugging/test-academic.md +14 -0
- package/src/.agents/skills/systematic-debugging/test-pressure-1.md +58 -0
- package/src/.agents/skills/systematic-debugging/test-pressure-2.md +68 -0
- package/src/.agents/skills/systematic-debugging/test-pressure-3.md +69 -0
- package/src/.agents/skills/typescript-best-practices/SKILL.md +373 -0
- package/src/.agents/skills/ui-ux-pro-custom/SKILL.md +348 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/charts.csv +26 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/colors.csv +97 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/icons.csv +101 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/SKILL.md +106 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/accessibility.md +475 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/animation.md +466 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/composition-locals.md +231 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/deprecated-patterns.md +323 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/lists-scrolling.md +400 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/modifiers.md +331 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/navigation.md +416 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/performance.md +446 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/side-effects.md +516 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/source-code/foundation-source.md +13327 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/source-code/material3-source.md +19097 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/source-code/navigation-source.md +2947 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/source-code/runtime-source.md +11316 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/source-code/ui-source.md +7896 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/state-management.md +377 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/styles-experimental.md +470 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/theming-material3.md +349 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/view-composition.md +595 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/landing.csv +31 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/mobile-ui-layout.md +654 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/products.csv +97 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/react-performance.csv +45 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/astro.csv +54 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/flutter.csv +53 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/html-tailwind.csv +56 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/jetpack-compose.csv +53 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/nextjs.csv +53 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/nuxt-ui.csv +51 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/nuxtjs.csv +59 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/react-native.csv +56 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/react.csv +54 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/shadcn.csv +61 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/svelte.csv +54 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/swiftui.csv +51 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/vue.csv +50 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/styles.csv +68 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/alarmkit/SKILL.md +438 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/alarmkit/references/alarmkit-patterns.md +584 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/app-clips/SKILL.md +436 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/app-intents/SKILL.md +489 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/app-intents/references/appintents-advanced.md +1076 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/app-store-review/SKILL.md +340 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/app-store-review/references/privacy-manifest.md +90 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/app-store-review/references/review-checklists.md +106 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/apple-on-device-ai/SKILL.md +500 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/apple-on-device-ai/references/coreml-conversion.md +425 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/apple-on-device-ai/references/coreml-optimization.md +344 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/apple-on-device-ai/references/foundation-models.md +508 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/apple-on-device-ai/references/mlx-swift.md +285 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/authentication/SKILL.md +496 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/authentication/references/keychain-biometric.md +211 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/background-processing/SKILL.md +499 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/background-processing/references/background-task-patterns.md +390 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/callkit-voip/SKILL.md +461 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/callkit-voip/references/callkit-patterns.md +425 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/cloudkit-sync/SKILL.md +492 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/cloudkit-sync/references/cloudkit-patterns.md +461 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/codable-patterns/SKILL.md +467 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/contacts-framework/SKILL.md +425 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/contacts-framework/references/contacts-patterns.md +409 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/core-bluetooth/SKILL.md +491 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/core-bluetooth/references/ble-patterns.md +435 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/core-motion/SKILL.md +388 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/core-motion/references/motion-patterns.md +405 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/core-nfc/SKILL.md +495 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/core-nfc/references/nfc-patterns.md +420 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/coreml/SKILL.md +459 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/coreml/references/coreml-swift-integration.md +765 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/debugging-instruments/SKILL.md +422 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/debugging-instruments/references/instruments-guide.md +387 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/debugging-instruments/references/lldb-patterns.md +298 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/device-integrity/SKILL.md +477 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/energykit/SKILL.md +460 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/energykit/references/energykit-patterns.md +541 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/eventkit-calendar/SKILL.md +483 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/eventkit-calendar/references/eventkit-patterns.md +326 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/healthkit/SKILL.md +498 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/healthkit/references/healthkit-patterns.md +602 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/homekit-matter/SKILL.md +496 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/homekit-matter/references/matter-commissioning.md +455 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-accessibility/SKILL.md +301 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-accessibility/references/a11y-patterns.md +140 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-localization/SKILL.md +418 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-localization/references/formatstyle-locale.md +627 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-localization/references/string-catalogs.md +462 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-networking/SKILL.md +441 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-networking/references/background-websocket.md +862 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-networking/references/lightweight-clients.md +93 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-networking/references/network-framework.md +563 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-networking/references/urlsession-patterns.md +1116 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-security/SKILL.md +496 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-security/references/app-review-guidelines.md +174 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-security/references/cryptokit-advanced.md +297 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-security/references/file-storage-patterns.md +354 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-security/references/privacy-manifest.md +117 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/live-activities/SKILL.md +500 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/live-activities/references/live-activity-patterns.md +868 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/mapkit-location/SKILL.md +485 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/mapkit-location/references/corelocation-patterns.md +730 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/mapkit-location/references/mapkit-patterns.md +748 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/metrickit-diagnostics/SKILL.md +479 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/musickit-audio/SKILL.md +395 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/musickit-audio/references/musickit-patterns.md +363 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/natural-language/SKILL.md +412 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/natural-language/references/translation-patterns.md +311 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/passkit-wallet/SKILL.md +398 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/passkit-wallet/references/wallet-passes.md +254 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/pencilkit-drawing/SKILL.md +387 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/pencilkit-drawing/references/paperkit-integration.md +376 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/pencilkit-drawing/references/pencilkit-patterns.md +302 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/permissionkit/SKILL.md +446 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/permissionkit/references/permissionkit-patterns.md +435 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/photos-camera-media/SKILL.md +501 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/photos-camera-media/references/av-playback.md +701 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/photos-camera-media/references/camera-capture.md +774 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/photos-camera-media/references/image-loading-caching.md +869 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/photos-camera-media/references/photospicker-patterns.md +597 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/push-notifications/SKILL.md +501 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/push-notifications/references/notification-patterns.md +677 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/push-notifications/references/rich-notifications.md +745 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/realitykit-ar/SKILL.md +479 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/realitykit-ar/references/realitykit-patterns.md +480 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/shareplay-activities/SKILL.md +483 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/shareplay-activities/references/shareplay-patterns.md +544 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/speech-recognition/SKILL.md +485 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/storekit/SKILL.md +478 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/storekit/references/app-review-guidelines.md +58 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/storekit/references/storekit-advanced.md +755 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-charts/SKILL.md +487 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-charts/references/charts-patterns.md +895 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-concurrency/SKILL.md +408 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-concurrency/references/approachable-concurrency.md +80 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-concurrency/references/swift-6-2-concurrency.md +233 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-concurrency/references/swiftui-concurrency.md +187 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-concurrency/references/synchronization-primitives.md +341 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-language/SKILL.md +498 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-language/references/swift-patterns-extended.md +505 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-testing/SKILL.md +467 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-testing/references/testing-patterns.md +504 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftdata/SKILL.md +334 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftdata/references/core-data-coexistence.md +504 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftdata/references/swiftdata-advanced.md +975 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftdata/references/swiftdata-queries.md +675 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-animation/SKILL.md +481 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-animation/references/animation-advanced.md +804 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-animation/references/core-animation-bridge.md +553 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-gestures/SKILL.md +450 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-gestures/references/gesture-patterns.md +425 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-layout-components/SKILL.md +336 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-layout-components/references/form.md +97 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-layout-components/references/grids.md +69 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-layout-components/references/list.md +99 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-layout-components/references/scrollview.md +147 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-liquid-glass/SKILL.md +325 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-liquid-glass/references/liquid-glass.md +387 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-navigation/SKILL.md +262 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-navigation/references/deeplinks.md +207 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-navigation/references/navigationstack.md +177 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-navigation/references/sheets.md +169 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-navigation/references/tabview.md +178 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-patterns/SKILL.md +381 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-patterns/references/architecture-patterns.md +486 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-patterns/references/deprecated-migration.md +1097 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-patterns/references/design-polish.md +780 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-patterns/references/platform-and-sharing.md +696 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-performance/SKILL.md +491 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +46 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +29 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-performance/references/understanding-hangs-in-your-app.md +33 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-performance/references/understanding-improving-swiftui-performance.md +52 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-uikit-interop/SKILL.md +428 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-uikit-interop/references/hosting-migration.md +534 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-uikit-interop/references/representable-recipes.md +1133 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/tipkit/SKILL.md +494 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/tipkit/references/tipkit-patterns.md +782 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/vision-framework/SKILL.md +475 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/vision-framework/references/vision-requests.md +736 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/vision-framework/references/visionkit-scanner.md +738 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/weatherkit/SKILL.md +410 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/weatherkit/references/weatherkit-patterns.md +567 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/widgetkit/SKILL.md +497 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/widgetkit/references/widgetkit-advanced.md +871 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/typography.csv +58 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/ui-reasoning.csv +101 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/ux-guidelines.csv +100 -0
- package/src/.agents/skills/ui-ux-pro-custom/data/web-interface.csv +31 -0
- package/src/.agents/skills/ui-ux-pro-custom/scripts/core.py +253 -0
- package/src/.agents/skills/ui-ux-pro-custom/scripts/design_system.py +1067 -0
- package/src/.agents/skills/ui-ux-pro-custom/scripts/search.py +114 -0
- package/src/.agents/skills/ux-audit/SKILL.md +151 -0
- package/src/.agents/skills/websocket-engineer/SKILL.md +168 -0
- package/src/.agents/skills/websocket-engineer/references/alternatives.md +391 -0
- package/src/.agents/skills/websocket-engineer/references/patterns.md +400 -0
- package/src/.agents/skills/websocket-engineer/references/protocol.md +195 -0
- package/src/.agents/skills/websocket-engineer/references/scaling.md +333 -0
- package/src/.agents/skills/websocket-engineer/references/security.md +474 -0
- package/src/.agents/skills/writing-skills/SKILL.md +655 -0
- package/src/.agents/skills/writing-skills/anthropic-best-practices.md +1150 -0
- package/src/.agents/skills/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
- package/src/.agents/skills/writing-skills/graphviz-conventions.dot +172 -0
- package/src/.agents/skills/writing-skills/persuasion-principles.md +187 -0
- package/src/.agents/skills/writing-skills/render-graphs.js +168 -0
- package/src/.agents/skills/writing-skills/testing-skills-with-subagents.md +384 -0
- package/src/.claude/commands/bmad-track-compact.md +19 -0
- package/src/.claude/commands/bmad-track-extended.md +19 -0
- package/src/.claude/commands/bmad-track-large.md +19 -0
- package/src/.claude/commands/bmad-track-medium.md +19 -0
- package/src/.claude/commands/bmad-track-nano.md +19 -0
- package/src/.claude/commands/bmad-track-rv.md +18 -0
- package/src/.claude/commands/bmad-track-small.md +19 -0
- package/src/_memory/config.yaml +11 -0
- package/src/_memory/master-orchestrator-sidecar/docs-index.md +3 -0
- package/src/_memory/master-orchestrator-sidecar/instructions.md +2566 -0
- package/src/_memory/master-orchestrator-sidecar/memories.md +8 -0
- package/src/_memory/master-orchestrator-sidecar/session-state.md +15 -0
- package/src/_memory/master-orchestrator-sidecar/triage-history.md +3 -0
- package/src/_memory/master-orchestrator-sidecar/workflows-overview.html +1230 -0
- package/src/_memory/skills/excalidraw/SKILL.md +78 -0
- package/src/_memory/skills/excalidraw/diagram-patterns.md +53 -0
- package/src/_memory/skills/nimbalyst-tracking/SKILL.md +103 -0
- package/src/_memory/skills/writing-skills/SKILL.md +655 -0
- package/src/bmb/agents/agent-builder.md +59 -0
- package/src/bmb/agents/module-builder.md +60 -0
- package/src/bmb/agents/workflow-builder.md +61 -0
- package/src/bmb/config.yaml +12 -0
- package/src/bmb/module-help.csv +13 -0
- package/src/bmb/workflows/agent/data/agent-architecture.md +258 -0
- package/src/bmb/workflows/agent/data/agent-compilation.md +185 -0
- package/src/bmb/workflows/agent/data/agent-menu-patterns.md +189 -0
- package/src/bmb/workflows/agent/data/agent-metadata.md +133 -0
- package/src/bmb/workflows/agent/data/agent-validation.md +111 -0
- package/src/bmb/workflows/agent/data/brainstorm-context.md +96 -0
- package/src/bmb/workflows/agent/data/communication-presets.csv +61 -0
- package/src/bmb/workflows/agent/data/critical-actions.md +75 -0
- package/src/bmb/workflows/agent/data/persona-properties.md +252 -0
- package/src/bmb/workflows/agent/data/principles-crafting.md +142 -0
- package/src/bmb/workflows/agent/data/reference/module-examples/architect.md +68 -0
- package/src/bmb/workflows/agent/data/reference/with-sidecar/journal-keeper/journal-keeper-sidecar/entries/yy-mm-dd-entry-template.md +17 -0
- package/src/bmb/workflows/agent/data/understanding-agent-types.md +126 -0
- package/src/bmb/workflows/agent/steps-c/step-01-brainstorm.md +129 -0
- package/src/bmb/workflows/agent/steps-c/step-02-discovery.md +170 -0
- package/src/bmb/workflows/agent/steps-c/step-03-sidecar-metadata.md +309 -0
- package/src/bmb/workflows/agent/steps-c/step-04-persona.md +213 -0
- package/src/bmb/workflows/agent/steps-c/step-05-commands-menu.md +179 -0
- package/src/bmb/workflows/agent/steps-c/step-06-activation.md +278 -0
- package/src/bmb/workflows/agent/steps-c/step-07-build-agent.md +316 -0
- package/src/bmb/workflows/agent/steps-c/step-08-celebrate.md +247 -0
- package/src/bmb/workflows/agent/steps-e/e-01-load-existing.md +221 -0
- package/src/bmb/workflows/agent/steps-e/e-02-discover-edits.md +195 -0
- package/src/bmb/workflows/agent/steps-e/e-03-placeholder.md +1 -0
- package/src/bmb/workflows/agent/steps-e/e-04-sidecar-metadata.md +126 -0
- package/src/bmb/workflows/agent/steps-e/e-05-persona.md +135 -0
- package/src/bmb/workflows/agent/steps-e/e-06-commands-menu.md +123 -0
- package/src/bmb/workflows/agent/steps-e/e-07-activation.md +124 -0
- package/src/bmb/workflows/agent/steps-e/e-08-edit-agent.md +197 -0
- package/src/bmb/workflows/agent/steps-e/e-09-celebrate.md +155 -0
- package/src/bmb/workflows/agent/steps-v/v-01-load-review.md +137 -0
- package/src/bmb/workflows/agent/steps-v/v-02a-validate-metadata.md +116 -0
- package/src/bmb/workflows/agent/steps-v/v-02b-validate-persona.md +124 -0
- package/src/bmb/workflows/agent/steps-v/v-02c-validate-menu.md +127 -0
- package/src/bmb/workflows/agent/steps-v/v-02d-validate-structure.md +134 -0
- package/src/bmb/workflows/agent/steps-v/v-02e-validate-sidecar.md +134 -0
- package/src/bmb/workflows/agent/steps-v/v-03-summary.md +104 -0
- package/src/bmb/workflows/agent/templates/agent-plan.template.md +5 -0
- package/src/bmb/workflows/agent/templates/agent-template.md +89 -0
- package/src/bmb/workflows/agent/workflow-create-agent.md +72 -0
- package/src/bmb/workflows/agent/workflow-edit-agent.md +75 -0
- package/src/bmb/workflows/agent/workflow-validate-agent.md +73 -0
- package/src/bmb/workflows/module/data/agent-architecture.md +179 -0
- package/src/bmb/workflows/module/data/agent-spec-template.md +79 -0
- package/src/bmb/workflows/module/data/module-standards.md +263 -0
- package/src/bmb/workflows/module/data/module-yaml-conventions.md +392 -0
- package/src/bmb/workflows/module/module-help-generate.md +254 -0
- package/src/bmb/workflows/module/steps-b/step-01-welcome.md +148 -0
- package/src/bmb/workflows/module/steps-b/step-02-spark.md +141 -0
- package/src/bmb/workflows/module/steps-b/step-03-module-type.md +149 -0
- package/src/bmb/workflows/module/steps-b/step-04-vision.md +83 -0
- package/src/bmb/workflows/module/steps-b/step-05-identity.md +97 -0
- package/src/bmb/workflows/module/steps-b/step-06-users.md +86 -0
- package/src/bmb/workflows/module/steps-b/step-07-value.md +76 -0
- package/src/bmb/workflows/module/steps-b/step-08-agents.md +97 -0
- package/src/bmb/workflows/module/steps-b/step-09-workflows.md +83 -0
- package/src/bmb/workflows/module/steps-b/step-10-tools.md +91 -0
- package/src/bmb/workflows/module/steps-b/step-11-scenarios.md +84 -0
- package/src/bmb/workflows/module/steps-b/step-12-creative.md +95 -0
- package/src/bmb/workflows/module/steps-b/step-13-review.md +105 -0
- package/src/bmb/workflows/module/steps-b/step-14-finalize.md +117 -0
- package/src/bmb/workflows/module/steps-c/step-01-load-brief.md +179 -0
- package/src/bmb/workflows/module/steps-c/step-01b-continue.md +82 -0
- package/src/bmb/workflows/module/steps-c/step-02-structure.md +105 -0
- package/src/bmb/workflows/module/steps-c/step-03-config.md +119 -0
- package/src/bmb/workflows/module/steps-c/step-04-agents.md +168 -0
- package/src/bmb/workflows/module/steps-c/step-05-workflows.md +184 -0
- package/src/bmb/workflows/module/steps-c/step-06-docs.md +401 -0
- package/src/bmb/workflows/module/steps-c/step-07-complete.md +152 -0
- package/src/bmb/workflows/module/steps-e/step-01-load-target.md +81 -0
- package/src/bmb/workflows/module/steps-e/step-02-select-edit.md +77 -0
- package/src/bmb/workflows/module/steps-e/step-03-apply-edit.md +77 -0
- package/src/bmb/workflows/module/steps-e/step-04-review.md +80 -0
- package/src/bmb/workflows/module/steps-e/step-05-confirm.md +75 -0
- package/src/bmb/workflows/module/steps-v/step-01-load-target.md +96 -0
- package/src/bmb/workflows/module/steps-v/step-02-file-structure.md +93 -0
- package/src/bmb/workflows/module/steps-v/step-03-module-yaml.md +99 -0
- package/src/bmb/workflows/module/steps-v/step-04-agent-specs.md +152 -0
- package/src/bmb/workflows/module/steps-v/step-05-workflow-specs.md +152 -0
- package/src/bmb/workflows/module/steps-v/step-06-documentation.md +143 -0
- package/src/bmb/workflows/module/steps-v/step-07-installation.md +102 -0
- package/src/bmb/workflows/module/steps-v/step-08-report.md +197 -0
- package/src/bmb/workflows/module/templates/brief-template.md +154 -0
- package/src/bmb/workflows/module/templates/workflow-spec-template.md +96 -0
- package/src/bmb/workflows/module/workflow-create-module-brief.md +71 -0
- package/src/bmb/workflows/module/workflow-create-module.md +86 -0
- package/src/bmb/workflows/module/workflow-edit-module.md +66 -0
- package/src/bmb/workflows/module/workflow-validate-module.md +66 -0
- package/src/bmb/workflows/workflow/data/architecture.md +150 -0
- package/src/bmb/workflows/workflow/data/common-workflow-tools.csv +19 -0
- package/src/bmb/workflows/workflow/data/csv-data-file-standards.md +53 -0
- package/src/bmb/workflows/workflow/data/frontmatter-standards.md +184 -0
- package/src/bmb/workflows/workflow/data/input-discovery-standards.md +191 -0
- package/src/bmb/workflows/workflow/data/intent-vs-prescriptive-spectrum.md +44 -0
- package/src/bmb/workflows/workflow/data/menu-handling-standards.md +133 -0
- package/src/bmb/workflows/workflow/data/output-format-standards.md +135 -0
- package/src/bmb/workflows/workflow/data/step-file-rules.md +235 -0
- package/src/bmb/workflows/workflow/data/step-type-patterns.md +257 -0
- package/src/bmb/workflows/workflow/data/subprocess-optimization-patterns.md +188 -0
- package/src/bmb/workflows/workflow/data/trimodal-workflow-structure.md +164 -0
- package/src/bmb/workflows/workflow/data/workflow-chaining-standards.md +222 -0
- package/src/bmb/workflows/workflow/data/workflow-examples.md +232 -0
- package/src/bmb/workflows/workflow/data/workflow-type-criteria.md +134 -0
- package/src/bmb/workflows/workflow/steps-c/step-00-conversion.md +263 -0
- package/src/bmb/workflows/workflow/steps-c/step-01-discovery.md +194 -0
- package/src/bmb/workflows/workflow/steps-c/step-01b-continuation.md +3 -0
- package/src/bmb/workflows/workflow/steps-c/step-02-classification.md +270 -0
- package/src/bmb/workflows/workflow/steps-c/step-03-requirements.md +283 -0
- package/src/bmb/workflows/workflow/steps-c/step-04-tools.md +282 -0
- package/src/bmb/workflows/workflow/steps-c/step-05-plan-review.md +243 -0
- package/src/bmb/workflows/workflow/steps-c/step-06-design.md +330 -0
- package/src/bmb/workflows/workflow/steps-c/step-07-foundation.md +239 -0
- package/src/bmb/workflows/workflow/steps-c/step-08-build-step-01.md +379 -0
- package/src/bmb/workflows/workflow/steps-c/step-09-build-next-step.md +350 -0
- package/src/bmb/workflows/workflow/steps-c/step-10-confirmation.md +322 -0
- package/src/bmb/workflows/workflow/steps-c/step-11-completion.md +191 -0
- package/src/bmb/workflows/workflow/steps-e/step-e-01-assess-workflow.md +237 -0
- package/src/bmb/workflows/workflow/steps-e/step-e-02-discover-edits.md +251 -0
- package/src/bmb/workflows/workflow/steps-e/step-e-03-fix-validation.md +254 -0
- package/src/bmb/workflows/workflow/steps-e/step-e-04-direct-edit.md +277 -0
- package/src/bmb/workflows/workflow/steps-e/step-e-05-apply-edit.md +154 -0
- package/src/bmb/workflows/workflow/steps-e/step-e-06-validate-after.md +190 -0
- package/src/bmb/workflows/workflow/steps-e/step-e-07-complete.md +206 -0
- package/src/bmb/workflows/workflow/steps-v/step-01-validate-max-mode.md +109 -0
- package/src/bmb/workflows/workflow/steps-v/step-01-validate.md +221 -0
- package/src/bmb/workflows/workflow/steps-v/step-01b-structure.md +152 -0
- package/src/bmb/workflows/workflow/steps-v/step-02-frontmatter-validation.md +199 -0
- package/src/bmb/workflows/workflow/steps-v/step-02b-path-violations.md +265 -0
- package/src/bmb/workflows/workflow/steps-v/step-03-menu-validation.md +164 -0
- package/src/bmb/workflows/workflow/steps-v/step-04-step-type-validation.md +211 -0
- package/src/bmb/workflows/workflow/steps-v/step-05-output-format-validation.md +200 -0
- package/src/bmb/workflows/workflow/steps-v/step-06-validation-design-check.md +195 -0
- package/src/bmb/workflows/workflow/steps-v/step-07-instruction-style-check.md +209 -0
- package/src/bmb/workflows/workflow/steps-v/step-08-collaborative-experience-check.md +199 -0
- package/src/bmb/workflows/workflow/steps-v/step-08b-subprocess-optimization.md +179 -0
- package/src/bmb/workflows/workflow/steps-v/step-09-cohesive-review.md +186 -0
- package/src/bmb/workflows/workflow/steps-v/step-10-report-complete.md +154 -0
- package/src/bmb/workflows/workflow/steps-v/step-11-plan-validation.md +237 -0
- package/src/bmb/workflows/workflow/templates/minimal-output-template.md +11 -0
- package/src/bmb/workflows/workflow/templates/step-01-init-continuable-template.md +241 -0
- package/src/bmb/workflows/workflow/templates/step-1b-template.md +224 -0
- package/src/bmb/workflows/workflow/templates/step-template.md +294 -0
- package/src/bmb/workflows/workflow/templates/workflow-template.md +102 -0
- package/src/bmb/workflows/workflow/workflow-create-workflow.md +79 -0
- package/src/bmb/workflows/workflow/workflow-edit-workflow.md +65 -0
- package/src/bmb/workflows/workflow/workflow-rework-workflow.md +65 -0
- package/src/bmb/workflows/workflow/workflow-validate-max-parallel-workflow.md +66 -0
- package/src/bmb/workflows/workflow/workflow-validate-workflow.md +65 -0
- package/src/bmm/agents/analyst.md +104 -0
- package/src/bmm/agents/architect.md +85 -0
- package/src/bmm/agents/dev.md +100 -0
- package/src/bmm/agents/pm.md +98 -0
- package/src/bmm/agents/qa.md +90 -0
- package/src/bmm/agents/quick-flow-solo-dev.md +92 -0
- package/src/bmm/agents/review-agent.md +129 -0
- package/src/bmm/agents/sm.md +90 -0
- package/src/bmm/agents/tech-writer/tech-writer.md +94 -0
- package/src/bmm/agents/ux-designer.md +124 -0
- package/src/bmm/data/project-context-template.md +26 -0
- package/src/bmm/module-help.csv +31 -0
- package/src/bmm/teams/default-party.csv +20 -0
- package/src/bmm/teams/team-fullstack.yaml +12 -0
- package/src/bmm/workflows/1-analysis/create-product-brief/product-brief.template.md +10 -0
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-01-init.md +115 -0
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-01b-continue.md +107 -0
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-02-vision.md +141 -0
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-03-users.md +144 -0
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-04-metrics.md +147 -0
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-05-scope.md +161 -0
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-06-complete.md +99 -0
- package/src/bmm/workflows/1-analysis/create-product-brief/workflow.md +57 -0
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-01-init.md +87 -0
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-02-domain-analysis.md +156 -0
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-03-competitive-landscape.md +165 -0
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-04-regulatory-focus.md +140 -0
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-05-technical-trends.md +152 -0
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-06-research-synthesis.md +345 -0
- package/src/bmm/workflows/1-analysis/research/market-steps/step-01-init.md +92 -0
- package/src/bmm/workflows/1-analysis/research/market-steps/step-02-customer-behavior.md +164 -0
- package/src/bmm/workflows/1-analysis/research/market-steps/step-03-customer-pain-points.md +174 -0
- package/src/bmm/workflows/1-analysis/research/market-steps/step-04-customer-decisions.md +184 -0
- package/src/bmm/workflows/1-analysis/research/market-steps/step-05-competitive-analysis.md +105 -0
- package/src/bmm/workflows/1-analysis/research/market-steps/step-06-research-completion.md +360 -0
- package/src/bmm/workflows/1-analysis/research/research.template.md +29 -0
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-01-init.md +87 -0
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-02-technical-overview.md +165 -0
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-03-integration-patterns.md +174 -0
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-04-architectural-patterns.md +141 -0
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-05-implementation-research.md +159 -0
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-06-research-synthesis.md +387 -0
- package/src/bmm/workflows/1-analysis/research/workflow-domain-research.md +54 -0
- package/src/bmm/workflows/1-analysis/research/workflow-market-research.md +54 -0
- package/src/bmm/workflows/1-analysis/research/workflow-technical-research.md +54 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/data/domain-complexity.csv +15 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/data/prd-purpose.md +197 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/data/project-types.csv +11 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-01-init.md +139 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-01b-continue.md +100 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02-discovery.md +160 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02b-vision.md +88 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02c-executive-summary.md +99 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-03-success.md +169 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-04-journeys.md +156 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-05-domain.md +136 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-06-innovation.md +176 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-07-project-type.md +184 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-08-scoping.md +174 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-09-functional.md +175 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-10-nonfunctional.md +189 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-11-polish.md +162 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-12-complete.md +79 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-01-discovery.md +183 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-01b-legacy-conversion.md +149 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-02-review.md +187 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-03-edit.md +192 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-04-complete.md +108 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-01-discovery.md +166 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-02-format-detection.md +131 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-02b-parity-check.md +150 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-03-density-validation.md +118 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-04-brief-coverage-validation.md +155 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-05-measurability-validation.md +170 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-06-traceability-validation.md +158 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-07-implementation-leakage-validation.md +147 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-08-domain-compliance-validation.md +182 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-09-project-type-validation.md +202 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-10-smart-validation.md +148 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-11-holistic-quality-validation.md +201 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-12-completeness-validation.md +179 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-13-report-complete.md +164 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/templates/prd-template.md +10 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/workflow-create-prd.md +65 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/workflow-edit-prd.md +65 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/workflow-validate-prd.md +63 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-01-init.md +63 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-01b-continue.md +63 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-02-discovery.md +106 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-03-core-experience.md +111 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-04-emotional-response.md +115 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-05-inspiration.md +127 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-06-design-system.md +167 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-07-defining-experience.md +143 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-08-visual-foundation.md +118 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-09-design-directions.md +154 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-10-user-journeys.md +136 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-11-component-strategy.md +165 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-12-ux-patterns.md +135 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-13-responsive-accessibility.md +192 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-14-complete.md +101 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/ux-design-template.md +13 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/workflow.md +45 -0
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-01-document-discovery.md +185 -0
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-02-prd-analysis.md +129 -0
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-03-epic-coverage-validation.md +130 -0
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-04-ux-alignment.md +93 -0
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-05-epic-quality-review.md +196 -0
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-06-final-assessment.md +129 -0
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/templates/readiness-report-template.md +4 -0
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/workflow.md +54 -0
- package/src/bmm/workflows/3-solutioning/create-architecture/architecture-decision-template.md +12 -0
- package/src/bmm/workflows/3-solutioning/create-architecture/data/domain-complexity.csv +13 -0
- package/src/bmm/workflows/3-solutioning/create-architecture/data/project-types.csv +7 -0
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-01-init.md +89 -0
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-01b-continue.md +82 -0
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-02-context.md +106 -0
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-03-starter.md +138 -0
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-04-decisions.md +129 -0
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-05-patterns.md +166 -0
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-06-structure.md +186 -0
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-07-validation.md +163 -0
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-08-complete.md +38 -0
- package/src/bmm/workflows/3-solutioning/create-architecture/workflow.md +49 -0
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-01-validate-prerequisites.md +129 -0
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-02-design-epics.md +124 -0
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-03-create-stories.md +122 -0
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-04-final-validation.md +84 -0
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/templates/epics-template.md +57 -0
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/workflow.md +58 -0
- package/src/bmm/workflows/4-implementation/code-review/checklist.md +23 -0
- package/src/bmm/workflows/4-implementation/code-review/instructions.xml +227 -0
- package/src/bmm/workflows/4-implementation/code-review/workflow.yaml +43 -0
- package/src/bmm/workflows/4-implementation/correct-course/checklist.md +288 -0
- package/src/bmm/workflows/4-implementation/correct-course/instructions.md +207 -0
- package/src/bmm/workflows/4-implementation/correct-course/workflow.yaml +53 -0
- package/src/bmm/workflows/4-implementation/create-story/checklist.md +159 -0
- package/src/bmm/workflows/4-implementation/create-story/instructions.xml +574 -0
- package/src/bmm/workflows/4-implementation/create-story/template.md +79 -0
- package/src/bmm/workflows/4-implementation/create-story/workflow.yaml +52 -0
- package/src/bmm/workflows/4-implementation/dev-story/checklist.md +80 -0
- package/src/bmm/workflows/4-implementation/dev-story/instructions.xml +493 -0
- package/src/bmm/workflows/4-implementation/dev-story/workflow.yaml +20 -0
- package/src/bmm/workflows/4-implementation/retrospective/instructions.md +1444 -0
- package/src/bmm/workflows/4-implementation/retrospective/workflow.yaml +52 -0
- package/src/bmm/workflows/4-implementation/sprint-planning/checklist.md +33 -0
- package/src/bmm/workflows/4-implementation/sprint-planning/instructions.md +232 -0
- package/src/bmm/workflows/4-implementation/sprint-planning/sprint-status-template.yaml +55 -0
- package/src/bmm/workflows/4-implementation/sprint-planning/workflow.yaml +52 -0
- package/src/bmm/workflows/4-implementation/sprint-status/instructions.md +230 -0
- package/src/bmm/workflows/4-implementation/sprint-status/workflow.yaml +25 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-01-mode-detection.md +158 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-02-context-gathering.md +122 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-03-execute.md +93 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-04-self-check.md +93 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-05-adversarial-review.md +87 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-06-resolve-findings.md +146 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md +50 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-01-understand.md +204 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-02-investigate.md +152 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-03-generate.md +123 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-04-review.md +201 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/tech-spec-template.md +74 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md +79 -0
- package/src/bmm/workflows/document-project/checklist.md +245 -0
- package/src/bmm/workflows/document-project/documentation-requirements.csv +12 -0
- package/src/bmm/workflows/document-project/instructions.md +130 -0
- package/src/bmm/workflows/document-project/templates/deep-dive-template.md +345 -0
- package/src/bmm/workflows/document-project/templates/index-template.md +169 -0
- package/src/bmm/workflows/document-project/templates/project-overview-template.md +103 -0
- package/src/bmm/workflows/document-project/templates/project-scan-report-schema.json +160 -0
- package/src/bmm/workflows/document-project/templates/source-tree-template.md +135 -0
- package/src/bmm/workflows/document-project/workflow.yaml +22 -0
- package/src/bmm/workflows/document-project/workflows/deep-dive-instructions.md +298 -0
- package/src/bmm/workflows/document-project/workflows/deep-dive.yaml +31 -0
- package/src/bmm/workflows/document-project/workflows/full-scan-instructions.md +1106 -0
- package/src/bmm/workflows/document-project/workflows/full-scan.yaml +31 -0
- package/src/bmm/workflows/generate-project-context/project-context-template.md +21 -0
- package/src/bmm/workflows/generate-project-context/steps/step-01-discover.md +184 -0
- package/src/bmm/workflows/generate-project-context/steps/step-02-generate.md +322 -0
- package/src/bmm/workflows/generate-project-context/steps/step-03-complete.md +235 -0
- package/src/bmm/workflows/generate-project-context/workflow.md +49 -0
- package/src/bmm/workflows/qa/automate/workflow.yaml +233 -0
- package/src/bmm/workflows/qa-generate-e2e-tests/checklist.md +33 -0
- package/src/bmm/workflows/qa-generate-e2e-tests/instructions.md +110 -0
- package/src/bmm/workflows/qa-generate-e2e-tests/workflow.yaml +42 -0
- package/src/core/agents/bmad-master.md +56 -0
- package/src/core/agents/master-orchestrator.md +54 -0
- package/src/core/config.yaml +9 -0
- package/src/core/module-help.csv +10 -0
- package/src/core/scripts/generate-loop-report.py +72 -0
- package/src/core/skills/prepare-to-merge/SKILL.md +77 -0
- package/src/core/tasks/editorial-review-prose.xml +102 -0
- package/src/core/tasks/editorial-review-structure.xml +208 -0
- package/src/core/tasks/help.md +86 -0
- package/src/core/tasks/index-docs.xml +65 -0
- package/src/core/tasks/review-adversarial-general.xml +66 -0
- package/src/core/tasks/review-adversarial-loop.xml +46 -0
- package/src/core/tasks/review-edge-case-hunter.xml +63 -0
- package/src/core/tasks/review-party-loop.xml +46 -0
- package/src/core/tasks/shard-doc.xml +108 -0
- package/src/core/tasks/workflow.xml +236 -0
- package/src/core/templates/review-loop-report.html +88 -0
- package/src/core/templates/review-loop-report.md +5 -0
- package/src/core/workflows/advanced-elicitation/methods.csv +51 -0
- package/src/core/workflows/advanced-elicitation/workflow.xml +118 -0
- package/src/core/workflows/brainstorming/brain-methods.csv +62 -0
- package/src/core/workflows/brainstorming/steps/step-01-session-setup.md +212 -0
- package/src/core/workflows/brainstorming/steps/step-01b-continue.md +122 -0
- package/src/core/workflows/brainstorming/steps/step-02a-user-selected.md +225 -0
- package/src/core/workflows/brainstorming/steps/step-02b-ai-recommended.md +237 -0
- package/src/core/workflows/brainstorming/steps/step-02c-random-selection.md +209 -0
- package/src/core/workflows/brainstorming/steps/step-02d-progressive-flow.md +264 -0
- package/src/core/workflows/brainstorming/steps/step-02e-deep-dive.md +68 -0
- package/src/core/workflows/brainstorming/steps/step-03-technique-execution.md +403 -0
- package/src/core/workflows/brainstorming/steps/step-04-idea-organization.md +303 -0
- package/src/core/workflows/brainstorming/template.md +15 -0
- package/src/core/workflows/brainstorming/workflow.md +60 -0
- package/src/core/workflows/extract-trackers/workflow.md +45 -0
- package/src/core/workflows/party-mode/steps/step-01-agent-loading.md +142 -0
- package/src/core/workflows/party-mode/steps/step-02-discussion-orchestration.md +187 -0
- package/src/core/workflows/party-mode/steps/step-03-graceful-exit.md +168 -0
- package/src/core/workflows/party-mode/workflow.md +194 -0
- package/src/docs/dev/tmux/actions_popup.py +291 -0
- package/src/docs/dev/tmux/actions_popup.sh +110 -0
- package/src/docs/dev/tmux/claude_usage.sh +15 -0
- package/src/docs/dev/tmux/colors.conf +34 -0
- package/src/docs/dev/tmux/cpu_usage.sh +7 -0
- package/src/docs/dev/tmux/dispatch.sh +10 -0
- package/src/docs/dev/tmux/float_init.sh +13 -0
- package/src/docs/dev/tmux/float_term.sh +23 -0
- package/src/docs/dev/tmux/open_clip.sh +14 -0
- package/src/docs/dev/tmux/paste_clipboard.sh +13 -0
- package/src/docs/dev/tmux/paste_image_wrapper.sh +83 -0
- package/src/docs/dev/tmux/ram_usage.sh +3 -0
- package/src/docs/dev/tmux/title_sync.sh +54 -0
- package/src/docs/dev/tmux/tmux-setup.md +806 -0
- package/src/docs/dev/tmux/tmux.conf +127 -0
- package/src/docs/dev/tmux/xclip +18 -0
|
@@ -0,0 +1,496 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: authentication
|
|
3
|
+
description: "Implement iOS authentication patterns including Sign in with Apple (ASAuthorizationAppleIDProvider, ASAuthorizationController, ASAuthorizationAppleIDCredential), credential state checking, identity token validation, ASWebAuthenticationSession for OAuth and third-party auth flows, ASAuthorizationPasswordProvider for AutoFill credential suggestions, and biometric authentication with LAContext. Use when implementing Sign in with Apple, handling Apple ID credentials, building OAuth login flows, integrating Password AutoFill, checking credential revocation state, or validating identity tokens server-side."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Authentication
|
|
7
|
+
|
|
8
|
+
Implement authentication flows on iOS using the AuthenticationServices
|
|
9
|
+
framework, including Sign in with Apple, OAuth/third-party web auth,
|
|
10
|
+
Password AutoFill, and biometric authentication.
|
|
11
|
+
|
|
12
|
+
## Contents
|
|
13
|
+
|
|
14
|
+
- [Sign in with Apple](#sign-in-with-apple)
|
|
15
|
+
- [Credential Handling](#credential-handling)
|
|
16
|
+
- [Credential State Checking](#credential-state-checking)
|
|
17
|
+
- [Token Validation](#token-validation)
|
|
18
|
+
- [Existing Account Setup Flows](#existing-account-setup-flows)
|
|
19
|
+
- [ASWebAuthenticationSession (OAuth)](#aswebauthenticationsession-oauth)
|
|
20
|
+
- [Password AutoFill Credentials](#password-autofill-credentials)
|
|
21
|
+
- [Biometric Authentication](#biometric-authentication)
|
|
22
|
+
- [SwiftUI SignInWithAppleButton](#swiftui-signinwithapplebutton)
|
|
23
|
+
- [Common Mistakes](#common-mistakes)
|
|
24
|
+
- [Review Checklist](#review-checklist)
|
|
25
|
+
- [References](#references)
|
|
26
|
+
|
|
27
|
+
## Sign in with Apple
|
|
28
|
+
|
|
29
|
+
Add the "Sign in with Apple" capability in Xcode before using these APIs.
|
|
30
|
+
|
|
31
|
+
### UIKit: ASAuthorizationController Setup
|
|
32
|
+
|
|
33
|
+
```swift
|
|
34
|
+
import AuthenticationServices
|
|
35
|
+
|
|
36
|
+
final class LoginViewController: UIViewController {
|
|
37
|
+
func startSignInWithApple() {
|
|
38
|
+
let provider = ASAuthorizationAppleIDProvider()
|
|
39
|
+
let request = provider.createRequest()
|
|
40
|
+
request.requestedScopes = [.fullName, .email]
|
|
41
|
+
|
|
42
|
+
let controller = ASAuthorizationController(authorizationRequests: [request])
|
|
43
|
+
controller.delegate = self
|
|
44
|
+
controller.presentationContextProvider = self
|
|
45
|
+
controller.performRequests()
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
extension LoginViewController: ASAuthorizationControllerPresentationContextProviding {
|
|
50
|
+
func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
|
|
51
|
+
view.window!
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Delegate: Handling Success and Failure
|
|
57
|
+
|
|
58
|
+
```swift
|
|
59
|
+
extension LoginViewController: ASAuthorizationControllerDelegate {
|
|
60
|
+
func authorizationController(
|
|
61
|
+
controller: ASAuthorizationController,
|
|
62
|
+
didCompleteWithAuthorization authorization: ASAuthorization
|
|
63
|
+
) {
|
|
64
|
+
guard let credential = authorization.credential
|
|
65
|
+
as? ASAuthorizationAppleIDCredential else { return }
|
|
66
|
+
|
|
67
|
+
let userID = credential.user // Stable, unique, per-team identifier
|
|
68
|
+
let email = credential.email // nil after first authorization
|
|
69
|
+
let fullName = credential.fullName // nil after first authorization
|
|
70
|
+
let identityToken = credential.identityToken // JWT for server validation
|
|
71
|
+
let authCode = credential.authorizationCode // Short-lived code for server exchange
|
|
72
|
+
|
|
73
|
+
// Save userID to Keychain for credential state checks
|
|
74
|
+
// See references/keychain-biometric.md for Keychain patterns
|
|
75
|
+
saveUserID(userID)
|
|
76
|
+
|
|
77
|
+
// Send identityToken and authCode to your server
|
|
78
|
+
authenticateWithServer(identityToken: identityToken, authCode: authCode)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
func authorizationController(
|
|
82
|
+
controller: ASAuthorizationController,
|
|
83
|
+
didCompleteWithError error: any Error
|
|
84
|
+
) {
|
|
85
|
+
let authError = error as? ASAuthorizationError
|
|
86
|
+
switch authError?.code {
|
|
87
|
+
case .canceled:
|
|
88
|
+
break // User dismissed
|
|
89
|
+
case .failed:
|
|
90
|
+
showError("Authorization failed")
|
|
91
|
+
case .invalidResponse:
|
|
92
|
+
showError("Invalid response")
|
|
93
|
+
case .notHandled:
|
|
94
|
+
showError("Not handled")
|
|
95
|
+
case .notInteractive:
|
|
96
|
+
break // Non-interactive request failed -- expected for silent checks
|
|
97
|
+
default:
|
|
98
|
+
showError("Unknown error")
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Credential Handling
|
|
105
|
+
|
|
106
|
+
`ASAuthorizationAppleIDCredential` properties and their behavior:
|
|
107
|
+
|
|
108
|
+
| Property | Type | First Auth | Subsequent Auth |
|
|
109
|
+
|---|---|---|---|
|
|
110
|
+
| `user` | `String` | Always | Always |
|
|
111
|
+
| `email` | `String?` | Provided if requested | `nil` |
|
|
112
|
+
| `fullName` | `PersonNameComponents?` | Provided if requested | `nil` |
|
|
113
|
+
| `identityToken` | `Data?` | JWT (Base64) | JWT (Base64) |
|
|
114
|
+
| `authorizationCode` | `Data?` | Short-lived code | Short-lived code |
|
|
115
|
+
| `realUserStatus` | `ASUserDetectionStatus` | `.likelyReal` / `.unknown` | `.unknown` |
|
|
116
|
+
|
|
117
|
+
**Critical:** `email` and `fullName` are provided ONLY on the first
|
|
118
|
+
authorization. Cache them immediately during the initial sign-up flow. If the
|
|
119
|
+
user later deletes and re-adds the app, these values will not be returned.
|
|
120
|
+
|
|
121
|
+
```swift
|
|
122
|
+
func handleCredential(_ credential: ASAuthorizationAppleIDCredential) {
|
|
123
|
+
// Always persist the user identifier
|
|
124
|
+
let userID = credential.user
|
|
125
|
+
|
|
126
|
+
// Cache name and email IMMEDIATELY -- only available on first auth
|
|
127
|
+
if let fullName = credential.fullName {
|
|
128
|
+
let name = PersonNameComponentsFormatter().string(from: fullName)
|
|
129
|
+
UserProfile.saveName(name) // Persist to your backend
|
|
130
|
+
}
|
|
131
|
+
if let email = credential.email {
|
|
132
|
+
UserProfile.saveEmail(email) // Persist to your backend
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Credential State Checking
|
|
138
|
+
|
|
139
|
+
Check credential state on every app launch. The user may revoke access at
|
|
140
|
+
any time via Settings > Apple Account > Sign-In & Security.
|
|
141
|
+
|
|
142
|
+
```swift
|
|
143
|
+
func checkCredentialState() async {
|
|
144
|
+
let provider = ASAuthorizationAppleIDProvider()
|
|
145
|
+
guard let userID = loadSavedUserID() else {
|
|
146
|
+
showLoginScreen()
|
|
147
|
+
return
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
do {
|
|
151
|
+
let state = try await provider.credentialState(forUserID: userID)
|
|
152
|
+
switch state {
|
|
153
|
+
case .authorized:
|
|
154
|
+
proceedToMainApp()
|
|
155
|
+
case .revoked:
|
|
156
|
+
// User revoked -- sign out and clear local data
|
|
157
|
+
signOut()
|
|
158
|
+
showLoginScreen()
|
|
159
|
+
case .notFound:
|
|
160
|
+
showLoginScreen()
|
|
161
|
+
case .transferred:
|
|
162
|
+
// App transferred to new team -- migrate user identifier
|
|
163
|
+
migrateUser()
|
|
164
|
+
@unknown default:
|
|
165
|
+
showLoginScreen()
|
|
166
|
+
}
|
|
167
|
+
} catch {
|
|
168
|
+
// Network error -- allow offline access or retry
|
|
169
|
+
proceedToMainApp()
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Credential Revocation Notification
|
|
175
|
+
|
|
176
|
+
```swift
|
|
177
|
+
NotificationCenter.default.addObserver(
|
|
178
|
+
forName: ASAuthorizationAppleIDProvider.credentialRevokedNotification,
|
|
179
|
+
object: nil,
|
|
180
|
+
queue: .main
|
|
181
|
+
) { _ in
|
|
182
|
+
// Sign out immediately
|
|
183
|
+
AuthManager.shared.signOut()
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Token Validation
|
|
188
|
+
|
|
189
|
+
The `identityToken` is a JWT. Send it to your server for validation --
|
|
190
|
+
never trust it client-side alone.
|
|
191
|
+
|
|
192
|
+
```swift
|
|
193
|
+
func sendTokenToServer(credential: ASAuthorizationAppleIDCredential) async throws {
|
|
194
|
+
guard let tokenData = credential.identityToken,
|
|
195
|
+
let token = String(data: tokenData, encoding: .utf8),
|
|
196
|
+
let authCodeData = credential.authorizationCode,
|
|
197
|
+
let authCode = String(data: authCodeData, encoding: .utf8) else {
|
|
198
|
+
throw AuthError.missingToken
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
var request = URLRequest(url: URL(string: "https://api.example.com/auth/apple")!)
|
|
202
|
+
request.httpMethod = "POST"
|
|
203
|
+
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
|
204
|
+
request.httpBody = try JSONEncoder().encode(
|
|
205
|
+
["identityToken": token, "authorizationCode": authCode]
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
let (data, response) = try await URLSession.shared.data(for: request)
|
|
209
|
+
guard (response as? HTTPURLResponse)?.statusCode == 200 else {
|
|
210
|
+
throw AuthError.serverValidationFailed
|
|
211
|
+
}
|
|
212
|
+
let session = try JSONDecoder().decode(SessionResponse.self, from: data)
|
|
213
|
+
// Store session token in Keychain -- see references/keychain-biometric.md
|
|
214
|
+
try KeychainHelper.save(session.accessToken, forKey: "accessToken")
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Server-side, validate the JWT against Apple's public keys at
|
|
219
|
+
`https://appleid.apple.com/auth/keys` (JWKS). Verify: `iss` is
|
|
220
|
+
`https://appleid.apple.com`, `aud` matches your bundle ID, `exp` not passed.
|
|
221
|
+
|
|
222
|
+
## Existing Account Setup Flows
|
|
223
|
+
|
|
224
|
+
On launch, silently check for existing Sign in with Apple and password
|
|
225
|
+
credentials before showing a login screen:
|
|
226
|
+
|
|
227
|
+
```swift
|
|
228
|
+
func performExistingAccountSetupFlows() {
|
|
229
|
+
let appleIDRequest = ASAuthorizationAppleIDProvider().createRequest()
|
|
230
|
+
let passwordRequest = ASAuthorizationPasswordProvider().createRequest()
|
|
231
|
+
|
|
232
|
+
let controller = ASAuthorizationController(
|
|
233
|
+
authorizationRequests: [appleIDRequest, passwordRequest]
|
|
234
|
+
)
|
|
235
|
+
controller.delegate = self
|
|
236
|
+
controller.presentationContextProvider = self
|
|
237
|
+
controller.performRequests(
|
|
238
|
+
options: .preferImmediatelyAvailableCredentials
|
|
239
|
+
)
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Call this in `viewDidAppear` or on app launch. If no existing credentials
|
|
244
|
+
are found, the delegate receives a `.notInteractive` error -- handle it
|
|
245
|
+
silently and show your normal login UI.
|
|
246
|
+
|
|
247
|
+
## ASWebAuthenticationSession (OAuth)
|
|
248
|
+
|
|
249
|
+
Use `ASWebAuthenticationSession` for OAuth and third-party authentication
|
|
250
|
+
(Google, GitHub, etc.). Never use `WKWebView` for auth flows.
|
|
251
|
+
|
|
252
|
+
```swift
|
|
253
|
+
import AuthenticationServices
|
|
254
|
+
|
|
255
|
+
final class OAuthController: NSObject, ASWebAuthenticationPresentationContextProviding {
|
|
256
|
+
func startOAuthFlow() {
|
|
257
|
+
let authURL = URL(string:
|
|
258
|
+
"https://provider.com/oauth/authorize?client_id=YOUR_ID&redirect_uri=myapp://callback&response_type=code"
|
|
259
|
+
)!
|
|
260
|
+
let session = ASWebAuthenticationSession(
|
|
261
|
+
url: authURL, callback: .customScheme("myapp")
|
|
262
|
+
) { callbackURL, error in
|
|
263
|
+
guard let callbackURL, error == nil,
|
|
264
|
+
let code = URLComponents(url: callbackURL, resolvingAgainstBaseURL: false)?
|
|
265
|
+
.queryItems?.first(where: { $0.name == "code" })?.value else { return }
|
|
266
|
+
Task { await self.exchangeCodeForTokens(code) }
|
|
267
|
+
}
|
|
268
|
+
session.presentationContextProvider = self
|
|
269
|
+
session.prefersEphemeralWebBrowserSession = true // No shared cookies
|
|
270
|
+
session.start()
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
|
|
274
|
+
ASPresentationAnchor()
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### SwiftUI WebAuthenticationSession
|
|
280
|
+
|
|
281
|
+
```swift
|
|
282
|
+
struct OAuthLoginView: View {
|
|
283
|
+
@Environment(\.webAuthenticationSession) private var webAuthSession
|
|
284
|
+
|
|
285
|
+
var body: some View {
|
|
286
|
+
Button("Sign in with Provider") {
|
|
287
|
+
Task {
|
|
288
|
+
let url = URL(string: "https://provider.com/oauth/authorize?client_id=YOUR_ID")!
|
|
289
|
+
let callbackURL = try await webAuthSession.authenticate(
|
|
290
|
+
using: url, callback: .customScheme("myapp")
|
|
291
|
+
)
|
|
292
|
+
// Extract authorization code from callbackURL
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
Callback types: `.customScheme("myapp")` for URL scheme redirects;
|
|
300
|
+
`.https(host:path:)` for universal link redirects (preferred).
|
|
301
|
+
|
|
302
|
+
## Password AutoFill Credentials
|
|
303
|
+
|
|
304
|
+
Use `ASAuthorizationPasswordProvider` to offer saved keychain credentials
|
|
305
|
+
alongside Sign in with Apple:
|
|
306
|
+
|
|
307
|
+
```swift
|
|
308
|
+
func performSignIn() {
|
|
309
|
+
let appleIDRequest = ASAuthorizationAppleIDProvider().createRequest()
|
|
310
|
+
appleIDRequest.requestedScopes = [.fullName, .email]
|
|
311
|
+
|
|
312
|
+
let passwordRequest = ASAuthorizationPasswordProvider().createRequest()
|
|
313
|
+
|
|
314
|
+
let controller = ASAuthorizationController(
|
|
315
|
+
authorizationRequests: [appleIDRequest, passwordRequest]
|
|
316
|
+
)
|
|
317
|
+
controller.delegate = self
|
|
318
|
+
controller.presentationContextProvider = self
|
|
319
|
+
controller.performRequests()
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// In delegate:
|
|
323
|
+
func authorizationController(
|
|
324
|
+
controller: ASAuthorizationController,
|
|
325
|
+
didCompleteWithAuthorization authorization: ASAuthorization
|
|
326
|
+
) {
|
|
327
|
+
switch authorization.credential {
|
|
328
|
+
case let appleIDCredential as ASAuthorizationAppleIDCredential:
|
|
329
|
+
handleAppleIDLogin(appleIDCredential)
|
|
330
|
+
case let passwordCredential as ASPasswordCredential:
|
|
331
|
+
// User selected a saved password from keychain
|
|
332
|
+
signInWithPassword(
|
|
333
|
+
username: passwordCredential.user,
|
|
334
|
+
password: passwordCredential.password
|
|
335
|
+
)
|
|
336
|
+
default:
|
|
337
|
+
break
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
Set `textContentType` on text fields for AutoFill to work:
|
|
343
|
+
|
|
344
|
+
```swift
|
|
345
|
+
usernameField.textContentType = .username
|
|
346
|
+
passwordField.textContentType = .password
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
## Biometric Authentication
|
|
350
|
+
|
|
351
|
+
Use `LAContext` from LocalAuthentication for Face ID / Touch ID as a
|
|
352
|
+
sign-in or re-authentication mechanism. For protecting Keychain items
|
|
353
|
+
with biometric access control (`SecAccessControl`, `.biometryCurrentSet`),
|
|
354
|
+
see the `ios-security` skill.
|
|
355
|
+
|
|
356
|
+
```swift
|
|
357
|
+
import LocalAuthentication
|
|
358
|
+
|
|
359
|
+
func authenticateWithBiometrics() async throws -> Bool {
|
|
360
|
+
let context = LAContext()
|
|
361
|
+
var error: NSError?
|
|
362
|
+
|
|
363
|
+
guard context.canEvaluatePolicy(
|
|
364
|
+
.deviceOwnerAuthenticationWithBiometrics, error: &error
|
|
365
|
+
) else {
|
|
366
|
+
throw AuthError.biometricsUnavailable
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
return try await context.evaluatePolicy(
|
|
370
|
+
.deviceOwnerAuthenticationWithBiometrics,
|
|
371
|
+
localizedReason: "Sign in to your account"
|
|
372
|
+
)
|
|
373
|
+
}
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
**Required:** Add `NSFaceIDUsageDescription` to Info.plist. Missing this
|
|
377
|
+
key crashes on Face ID devices.
|
|
378
|
+
|
|
379
|
+
## SwiftUI SignInWithAppleButton
|
|
380
|
+
|
|
381
|
+
```swift
|
|
382
|
+
import AuthenticationServices
|
|
383
|
+
|
|
384
|
+
struct AppleSignInView: View {
|
|
385
|
+
@Environment(\.colorScheme) var colorScheme
|
|
386
|
+
|
|
387
|
+
var body: some View {
|
|
388
|
+
SignInWithAppleButton(.signIn) { request in
|
|
389
|
+
request.requestedScopes = [.fullName, .email]
|
|
390
|
+
} onCompletion: { result in
|
|
391
|
+
switch result {
|
|
392
|
+
case .success(let authorization):
|
|
393
|
+
guard let credential = authorization.credential
|
|
394
|
+
as? ASAuthorizationAppleIDCredential else { return }
|
|
395
|
+
handleCredential(credential)
|
|
396
|
+
case .failure(let error):
|
|
397
|
+
handleError(error)
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
.signInWithAppleButtonStyle(
|
|
401
|
+
colorScheme == .dark ? .white : .black
|
|
402
|
+
)
|
|
403
|
+
.frame(height: 50)
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
## Common Mistakes
|
|
409
|
+
|
|
410
|
+
### 1. Not checking credential state on app launch
|
|
411
|
+
|
|
412
|
+
```swift
|
|
413
|
+
// DON'T: Assume the user is still authorized
|
|
414
|
+
func appDidLaunch() {
|
|
415
|
+
if UserDefaults.standard.bool(forKey: "isLoggedIn") {
|
|
416
|
+
showMainApp() // User may have revoked access!
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// DO: Check credential state every launch
|
|
421
|
+
func appDidLaunch() async {
|
|
422
|
+
await checkCredentialState() // See "Credential State Checking" above
|
|
423
|
+
}
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
### 2. Not performing existing account setup flows
|
|
427
|
+
|
|
428
|
+
```swift
|
|
429
|
+
// DON'T: Always show a full login screen on launch
|
|
430
|
+
// DO: Call performExistingAccountSetupFlows() first;
|
|
431
|
+
// show login UI only if .notInteractive error received
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
### 3. Assuming email/name are always provided
|
|
435
|
+
|
|
436
|
+
```swift
|
|
437
|
+
// DON'T: Force-unwrap email or fullName
|
|
438
|
+
let email = credential.email! // Crashes on subsequent logins
|
|
439
|
+
|
|
440
|
+
// DO: Handle nil gracefully -- only available on first authorization
|
|
441
|
+
if let email = credential.email {
|
|
442
|
+
saveEmail(email) // Persist immediately
|
|
443
|
+
}
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
### 4. Not implementing ASAuthorizationControllerPresentationContextProviding
|
|
447
|
+
|
|
448
|
+
```swift
|
|
449
|
+
// DON'T: Skip the presentation context provider
|
|
450
|
+
controller.delegate = self
|
|
451
|
+
controller.performRequests() // May not display UI correctly
|
|
452
|
+
|
|
453
|
+
// DO: Always set the presentation context provider
|
|
454
|
+
controller.delegate = self
|
|
455
|
+
controller.presentationContextProvider = self // Required for proper UI
|
|
456
|
+
controller.performRequests()
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
### 5. Storing identityToken in UserDefaults
|
|
460
|
+
|
|
461
|
+
```swift
|
|
462
|
+
// DON'T: Store tokens in UserDefaults
|
|
463
|
+
UserDefaults.standard.set(tokenString, forKey: "identityToken")
|
|
464
|
+
|
|
465
|
+
// DO: Store in Keychain
|
|
466
|
+
// See references/keychain-biometric.md for Keychain patterns
|
|
467
|
+
try KeychainHelper.save(tokenData, forKey: "identityToken")
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
## Review Checklist
|
|
471
|
+
|
|
472
|
+
- [ ] "Sign in with Apple" capability added in Xcode project
|
|
473
|
+
- [ ] `ASAuthorizationControllerPresentationContextProviding` implemented
|
|
474
|
+
- [ ] Credential state checked on every app launch (`credentialState(forUserID:)`)
|
|
475
|
+
- [ ] `credentialRevokedNotification` observer registered; sign-out handled
|
|
476
|
+
- [ ] `email` and `fullName` cached on first authorization (not assumed available later)
|
|
477
|
+
- [ ] `identityToken` sent to server for validation, not trusted client-side only
|
|
478
|
+
- [ ] Tokens stored in Keychain, not UserDefaults or files
|
|
479
|
+
- [ ] `performExistingAccountSetupFlows` called before showing login UI
|
|
480
|
+
- [ ] Error cases handled: `.canceled`, `.failed`, `.notInteractive`
|
|
481
|
+
- [ ] `NSFaceIDUsageDescription` in Info.plist for biometric auth
|
|
482
|
+
- [ ] `ASWebAuthenticationSession` used for OAuth (not `WKWebView`)
|
|
483
|
+
- [ ] `prefersEphemeralWebBrowserSession` set for OAuth when appropriate
|
|
484
|
+
- [ ] `textContentType` set on username/password fields for AutoFill
|
|
485
|
+
|
|
486
|
+
## References
|
|
487
|
+
|
|
488
|
+
- Keychain & biometric patterns: `references/keychain-biometric.md`
|
|
489
|
+
- [AuthenticationServices](https://sosumi.ai/documentation/authenticationservices)
|
|
490
|
+
- [ASAuthorizationAppleIDProvider](https://sosumi.ai/documentation/authenticationservices/asauthorizationappleidprovider)
|
|
491
|
+
- [ASAuthorizationAppleIDCredential](https://sosumi.ai/documentation/authenticationservices/asauthorizationappleidcredential)
|
|
492
|
+
- [ASAuthorizationController](https://sosumi.ai/documentation/authenticationservices/asauthorizationcontroller)
|
|
493
|
+
- [ASWebAuthenticationSession](https://sosumi.ai/documentation/authenticationservices/aswebauthenticationsession)
|
|
494
|
+
- [ASAuthorizationPasswordProvider](https://sosumi.ai/documentation/authenticationservices/asauthorizationpasswordprovider)
|
|
495
|
+
- [SignInWithAppleButton](https://sosumi.ai/documentation/authenticationservices/signinwithapplebutton)
|
|
496
|
+
- [Implementing User Authentication with Sign in with Apple](https://sosumi.ai/documentation/authenticationservices/implementing-user-authentication-with-sign-in-with-apple)
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# Keychain Token Storage & Biometric Authentication
|
|
2
|
+
|
|
3
|
+
Self-contained reference for storing authentication tokens in Keychain and
|
|
4
|
+
protecting them with biometric authentication (Face ID / Touch ID). Covers
|
|
5
|
+
the patterns most commonly needed alongside Sign in with Apple and OAuth flows.
|
|
6
|
+
|
|
7
|
+
## Contents
|
|
8
|
+
|
|
9
|
+
- [Storing Tokens in Keychain](#storing-tokens-in-keychain)
|
|
10
|
+
- [Reading Tokens from Keychain](#reading-tokens-from-keychain)
|
|
11
|
+
- [Deleting Tokens from Keychain](#deleting-tokens-from-keychain)
|
|
12
|
+
- [kSecAttrAccessible Values](#ksecattracccessible-values)
|
|
13
|
+
- [Biometric Authentication with LAContext](#biometric-authentication-with-lacontext)
|
|
14
|
+
- [Biometric-Protected Keychain Items](#biometric-protected-keychain-items)
|
|
15
|
+
- [SecAccessControl Flags](#secaccesscontrol-flags)
|
|
16
|
+
- [Keychain Error Handling](#keychain-error-handling)
|
|
17
|
+
|
|
18
|
+
## Storing Tokens in Keychain
|
|
19
|
+
|
|
20
|
+
The Keychain is the ONLY correct place to store tokens, passwords, API keys, or
|
|
21
|
+
secrets. Never store these in UserDefaults, files, or Core Data.
|
|
22
|
+
|
|
23
|
+
```swift
|
|
24
|
+
func saveToKeychain(account: String, data: Data, service: String) throws {
|
|
25
|
+
let query: [String: Any] = [
|
|
26
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
27
|
+
kSecAttrAccount as String: account,
|
|
28
|
+
kSecAttrService as String: service,
|
|
29
|
+
kSecValueData as String: data,
|
|
30
|
+
kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
let status = SecItemAdd(query as CFDictionary, nil)
|
|
34
|
+
|
|
35
|
+
if status == errSecDuplicateItem {
|
|
36
|
+
let updateQuery: [String: Any] = [
|
|
37
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
38
|
+
kSecAttrAccount as String: account,
|
|
39
|
+
kSecAttrService as String: service
|
|
40
|
+
]
|
|
41
|
+
let updates: [String: Any] = [kSecValueData as String: data]
|
|
42
|
+
let updateStatus = SecItemUpdate(updateQuery as CFDictionary, updates as CFDictionary)
|
|
43
|
+
guard updateStatus == errSecSuccess else {
|
|
44
|
+
throw KeychainError.updateFailed(updateStatus)
|
|
45
|
+
}
|
|
46
|
+
} else if status != errSecSuccess {
|
|
47
|
+
throw KeychainError.saveFailed(status)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Reading Tokens from Keychain
|
|
53
|
+
|
|
54
|
+
```swift
|
|
55
|
+
func readFromKeychain(account: String, service: String) throws -> Data {
|
|
56
|
+
let query: [String: Any] = [
|
|
57
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
58
|
+
kSecAttrAccount as String: account,
|
|
59
|
+
kSecAttrService as String: service,
|
|
60
|
+
kSecReturnData as String: true,
|
|
61
|
+
kSecMatchLimit as String: kSecMatchLimitOne
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
var result: AnyObject?
|
|
65
|
+
let status = SecItemCopyMatching(query as CFDictionary, &result)
|
|
66
|
+
|
|
67
|
+
guard status == errSecSuccess, let data = result as? Data else {
|
|
68
|
+
throw KeychainError.readFailed(status)
|
|
69
|
+
}
|
|
70
|
+
return data
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Deleting Tokens from Keychain
|
|
75
|
+
|
|
76
|
+
```swift
|
|
77
|
+
func deleteFromKeychain(account: String, service: String) throws {
|
|
78
|
+
let query: [String: Any] = [
|
|
79
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
80
|
+
kSecAttrAccount as String: account,
|
|
81
|
+
kSecAttrService as String: service
|
|
82
|
+
]
|
|
83
|
+
|
|
84
|
+
let status = SecItemDelete(query as CFDictionary)
|
|
85
|
+
guard status == errSecSuccess || status == errSecItemNotFound else {
|
|
86
|
+
throw KeychainError.deleteFailed(status)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## kSecAttrAccessible Values
|
|
92
|
+
|
|
93
|
+
| Value | When Available | Device-Only | Use For |
|
|
94
|
+
|---|---|---|---|
|
|
95
|
+
| `kSecAttrAccessibleWhenUnlocked` | Device unlocked | No | General credentials |
|
|
96
|
+
| `kSecAttrAccessibleWhenUnlockedThisDeviceOnly` | Device unlocked | Yes | Sensitive credentials |
|
|
97
|
+
| `kSecAttrAccessibleAfterFirstUnlock` | After first unlock | No | Background-accessible tokens |
|
|
98
|
+
| `kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly` | After first unlock | Yes | Background tokens, no backup |
|
|
99
|
+
| `kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly` | Passcode set + unlocked | Yes | Highest security |
|
|
100
|
+
|
|
101
|
+
Rules:
|
|
102
|
+
- Use `ThisDeviceOnly` variants for sensitive data. Prevents backup/restore to other devices.
|
|
103
|
+
- Use `AfterFirstUnlock` for tokens needed by background operations.
|
|
104
|
+
- Use `WhenPasscodeSetThisDeviceOnly` for most sensitive data. Item is deleted if passcode is removed.
|
|
105
|
+
- NEVER use `kSecAttrAccessibleAlways` (deprecated and insecure).
|
|
106
|
+
|
|
107
|
+
## Biometric Authentication with LAContext
|
|
108
|
+
|
|
109
|
+
Use `LAContext` from LocalAuthentication for Face ID / Touch ID prompts before
|
|
110
|
+
accessing sensitive data or performing protected actions.
|
|
111
|
+
|
|
112
|
+
```swift
|
|
113
|
+
import LocalAuthentication
|
|
114
|
+
|
|
115
|
+
func authenticateWithBiometrics() async throws -> Bool {
|
|
116
|
+
let context = LAContext()
|
|
117
|
+
var error: NSError?
|
|
118
|
+
|
|
119
|
+
guard context.canEvaluatePolicy(
|
|
120
|
+
.deviceOwnerAuthenticationWithBiometrics, error: &error
|
|
121
|
+
) else {
|
|
122
|
+
// Biometrics not available -- fall back to passcode
|
|
123
|
+
if context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) {
|
|
124
|
+
return try await context.evaluatePolicy(
|
|
125
|
+
.deviceOwnerAuthentication,
|
|
126
|
+
localizedReason: "Authenticate to access your account"
|
|
127
|
+
)
|
|
128
|
+
}
|
|
129
|
+
throw AuthError.biometricsUnavailable
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return try await context.evaluatePolicy(
|
|
133
|
+
.deviceOwnerAuthenticationWithBiometrics,
|
|
134
|
+
localizedReason: "Authenticate to access your account"
|
|
135
|
+
)
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Info.plist Requirement
|
|
140
|
+
|
|
141
|
+
You MUST include `NSFaceIDUsageDescription` in Info.plist:
|
|
142
|
+
|
|
143
|
+
```xml
|
|
144
|
+
<key>NSFaceIDUsageDescription</key>
|
|
145
|
+
<string>Authenticate to access your secure data</string>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Missing this key causes a crash on Face ID devices.
|
|
149
|
+
|
|
150
|
+
### LAContext Configuration
|
|
151
|
+
|
|
152
|
+
```swift
|
|
153
|
+
let context = LAContext()
|
|
154
|
+
context.localizedFallbackTitle = "Use Passcode"
|
|
155
|
+
context.touchIDAuthenticationAllowableReuseDuration = 30
|
|
156
|
+
let currentState = context.evaluatedPolicyDomainState // Compare to detect enrollment changes
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Biometric-Protected Keychain Items
|
|
160
|
+
|
|
161
|
+
Protect keychain items so they require biometric authentication to read:
|
|
162
|
+
|
|
163
|
+
```swift
|
|
164
|
+
let access = SecAccessControlCreateWithFlags(
|
|
165
|
+
nil,
|
|
166
|
+
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
|
|
167
|
+
.biometryCurrentSet,
|
|
168
|
+
nil
|
|
169
|
+
)!
|
|
170
|
+
|
|
171
|
+
let query: [String: Any] = [
|
|
172
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
173
|
+
kSecAttrAccount as String: "auth-token",
|
|
174
|
+
kSecValueData as String: tokenData,
|
|
175
|
+
kSecAttrAccessControl as String: access,
|
|
176
|
+
kSecUseAuthenticationContext as String: LAContext()
|
|
177
|
+
]
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## SecAccessControl Flags
|
|
181
|
+
|
|
182
|
+
| Flag | Behavior |
|
|
183
|
+
|------|----------|
|
|
184
|
+
| `.biometryCurrentSet` | Requires biometry, invalidated if enrollment changes. Most secure. |
|
|
185
|
+
| `.biometryAny` | Requires biometry, survives enrollment changes. |
|
|
186
|
+
| `.userPresence` | Biometry or passcode. Most flexible. |
|
|
187
|
+
|
|
188
|
+
Use `.biometryCurrentSet` for high-security items (tokens, keys). Use
|
|
189
|
+
`.userPresence` when you want to allow passcode fallback without a separate
|
|
190
|
+
`LAContext` evaluation.
|
|
191
|
+
|
|
192
|
+
## Keychain Error Handling
|
|
193
|
+
|
|
194
|
+
```swift
|
|
195
|
+
enum KeychainError: Error {
|
|
196
|
+
case saveFailed(OSStatus)
|
|
197
|
+
case updateFailed(OSStatus)
|
|
198
|
+
case readFailed(OSStatus)
|
|
199
|
+
case deleteFailed(OSStatus)
|
|
200
|
+
|
|
201
|
+
var localizedDescription: String {
|
|
202
|
+
switch self {
|
|
203
|
+
case .saveFailed(let status),
|
|
204
|
+
.updateFailed(let status),
|
|
205
|
+
.readFailed(let status),
|
|
206
|
+
.deleteFailed(let status):
|
|
207
|
+
return SecCopyErrorMessageString(status, nil) as String? ?? "Unknown error"
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
```
|