@mmerterden/multi-agent-pipeline 20.7.0 → 20.8.1

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.
Files changed (284) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/LICENSE +0 -10
  3. package/docs/facts.json +1 -1
  4. package/manifest.json +285 -285
  5. package/package.json +3 -3
  6. package/pipeline/lib/redact.mjs +3 -2
  7. package/pipeline/scripts/_notices.mjs +1 -1
  8. package/pipeline/scripts/gen-skills-index.mjs +13 -1
  9. package/pipeline/scripts/pre-commit-check.sh +4 -0
  10. package/pipeline/skills/.skill-manifest.json +69 -69
  11. package/pipeline/skills/shared/README.md +70 -70
  12. package/pipeline/skills/shared/external/alarmkit/SKILL.md +373 -381
  13. package/pipeline/skills/shared/external/alarmkit/evals/evals.json +23 -18
  14. package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +328 -378
  15. package/pipeline/skills/shared/external/app-clips/SKILL.md +260 -160
  16. package/pipeline/skills/shared/external/app-clips/evals/evals.json +27 -27
  17. package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +150 -83
  18. package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +135 -83
  19. package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +143 -85
  20. package/pipeline/skills/shared/external/app-intents/SKILL.md +302 -304
  21. package/pipeline/skills/shared/external/app-intents/evals/evals.json +21 -21
  22. package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +594 -894
  23. package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +345 -277
  24. package/pipeline/skills/shared/external/app-store-optimization/evals/evals.json +27 -23
  25. package/pipeline/skills/shared/external/app-store-optimization/references/keyword-research-methodology.md +107 -121
  26. package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +145 -165
  27. package/pipeline/skills/shared/external/app-store-review/SKILL.md +306 -326
  28. package/pipeline/skills/shared/external/app-store-review/evals/evals.json +21 -21
  29. package/pipeline/skills/shared/external/app-store-review/references/privacy-manifest.md +105 -67
  30. package/pipeline/skills/shared/external/app-store-review/references/review-checklists.md +114 -101
  31. package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +335 -360
  32. package/pipeline/skills/shared/external/apple-on-device-ai/evals/evals.json +24 -27
  33. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-conversion.md +215 -322
  34. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-optimization.md +161 -256
  35. package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models.md +277 -387
  36. package/pipeline/skills/shared/external/apple-on-device-ai/references/mlx-swift.md +196 -210
  37. package/pipeline/skills/shared/external/authentication/SKILL.md +277 -381
  38. package/pipeline/skills/shared/external/authentication/evals/evals.json +25 -25
  39. package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +135 -178
  40. package/pipeline/skills/shared/external/authentication/references/passkeys.md +111 -147
  41. package/pipeline/skills/shared/external/avkit/SKILL.md +267 -364
  42. package/pipeline/skills/shared/external/avkit/evals/evals.json +26 -26
  43. package/pipeline/skills/shared/external/avkit/references/avkit-patterns.md +375 -493
  44. package/pipeline/skills/shared/external/background-processing/SKILL.md +274 -384
  45. package/pipeline/skills/shared/external/background-processing/evals/evals.json +22 -22
  46. package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +173 -321
  47. package/pipeline/skills/shared/external/callkit-voip/SKILL.md +290 -371
  48. package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +24 -24
  49. package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +175 -343
  50. package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +292 -381
  51. package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +33 -30
  52. package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +227 -355
  53. package/pipeline/skills/shared/external/contacts-framework/SKILL.md +197 -346
  54. package/pipeline/skills/shared/external/contacts-framework/evals/evals.json +19 -21
  55. package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +169 -308
  56. package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +228 -376
  57. package/pipeline/skills/shared/external/core-bluetooth/evals/evals.json +25 -22
  58. package/pipeline/skills/shared/external/core-bluetooth/references/ble-patterns.md +257 -337
  59. package/pipeline/skills/shared/external/core-data/SKILL.md +302 -368
  60. package/pipeline/skills/shared/external/core-data/evals/evals.json +30 -27
  61. package/pipeline/skills/shared/external/core-motion/SKILL.md +235 -324
  62. package/pipeline/skills/shared/external/core-motion/evals/evals.json +31 -27
  63. package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +210 -310
  64. package/pipeline/skills/shared/external/core-nfc/SKILL.md +292 -366
  65. package/pipeline/skills/shared/external/core-nfc/evals/evals.json +22 -24
  66. package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +233 -329
  67. package/pipeline/skills/shared/external/coreml/SKILL.md +323 -367
  68. package/pipeline/skills/shared/external/coreml/evals/evals.json +24 -21
  69. package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +562 -565
  70. package/pipeline/skills/shared/external/cryptokit/SKILL.md +253 -394
  71. package/pipeline/skills/shared/external/cryptokit/evals/evals.json +20 -18
  72. package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +299 -488
  73. package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +270 -323
  74. package/pipeline/skills/shared/external/debugging-instruments/evals/evals.json +27 -30
  75. package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +167 -315
  76. package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +140 -193
  77. package/pipeline/skills/shared/external/device-integrity/SKILL.md +236 -353
  78. package/pipeline/skills/shared/external/device-integrity/evals/evals.json +25 -21
  79. package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +159 -197
  80. package/pipeline/skills/shared/external/energykit/SKILL.md +225 -392
  81. package/pipeline/skills/shared/external/energykit/evals/evals.json +29 -28
  82. package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +174 -470
  83. package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +261 -383
  84. package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +25 -22
  85. package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +165 -268
  86. package/pipeline/skills/shared/external/healthkit/SKILL.md +252 -303
  87. package/pipeline/skills/shared/external/healthkit/evals/evals.json +24 -23
  88. package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +369 -523
  89. package/pipeline/skills/shared/external/homekit-matter/SKILL.md +233 -348
  90. package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +27 -22
  91. package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +199 -305
  92. package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +368 -340
  93. package/pipeline/skills/shared/external/ios-accessibility/evals/evals.json +28 -27
  94. package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +314 -260
  95. package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +97 -67
  96. package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +165 -101
  97. package/pipeline/skills/shared/external/ios-localization/SKILL.md +258 -371
  98. package/pipeline/skills/shared/external/ios-localization/evals/evals.json +23 -23
  99. package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +283 -491
  100. package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +313 -440
  101. package/pipeline/skills/shared/external/ios-networking/SKILL.md +265 -341
  102. package/pipeline/skills/shared/external/ios-networking/evals/evals.json +24 -24
  103. package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +425 -652
  104. package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +143 -285
  105. package/pipeline/skills/shared/external/ios-networking/references/lightweight-clients.md +93 -53
  106. package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +231 -456
  107. package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +517 -784
  108. package/pipeline/skills/shared/external/ios-simulator/SKILL.md +265 -393
  109. package/pipeline/skills/shared/external/ios-simulator/evals/evals.json +21 -21
  110. package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +177 -270
  111. package/pipeline/skills/shared/external/live-activities/SKILL.md +318 -360
  112. package/pipeline/skills/shared/external/live-activities/evals/evals.json +21 -21
  113. package/pipeline/skills/shared/external/live-activities/references/activitykit-patterns.md +478 -710
  114. package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +3 -3
  115. package/pipeline/skills/shared/external/localization-reuse-map/example-mapping.json +1 -1
  116. package/pipeline/skills/shared/external/localization-reuse-map/reference/format-and-output.md +8 -7
  117. package/pipeline/skills/shared/external/localization-reuse-map/reference/publish-and-snapshot.md +2 -2
  118. package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +5 -2
  119. package/pipeline/skills/shared/external/localization-reuse-map/scripts/_shared.py +100 -0
  120. package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-artifact.py +45 -26
  121. package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-spreadsheet.py +14 -16
  122. package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-annotations.py +12 -5
  123. package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-legacy-labels.py +2 -1
  124. package/pipeline/skills/shared/external/localization-reuse-map/scripts/publish-confluence.py +6 -5
  125. package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-overlay.py +44 -18
  126. package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-legacy-values.py +5 -2
  127. package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-new-values.py +10 -11
  128. package/pipeline/skills/shared/external/localization-reuse-map/scripts/scan-screen-keys.py +4 -33
  129. package/pipeline/skills/shared/external/localization-reuse-map/scripts/verify-map.py +12 -59
  130. package/pipeline/skills/shared/external/mapkit-location/SKILL.md +297 -267
  131. package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +28 -24
  132. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-corelocation-patterns.md +378 -532
  133. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +397 -499
  134. package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +165 -348
  135. package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +26 -23
  136. package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +123 -130
  137. package/pipeline/skills/shared/external/musickit-audio/SKILL.md +189 -315
  138. package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +22 -21
  139. package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +181 -270
  140. package/pipeline/skills/shared/external/natural-language/SKILL.md +188 -340
  141. package/pipeline/skills/shared/external/natural-language/evals/evals.json +21 -21
  142. package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +171 -225
  143. package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +258 -392
  144. package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +30 -29
  145. package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +164 -231
  146. package/pipeline/skills/shared/external/pdfkit/SKILL.md +312 -344
  147. package/pipeline/skills/shared/external/pdfkit/evals/evals.json +19 -19
  148. package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +413 -624
  149. package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +242 -358
  150. package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +25 -21
  151. package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +161 -226
  152. package/pipeline/skills/shared/external/permissionkit/SKILL.md +282 -400
  153. package/pipeline/skills/shared/external/permissionkit/evals/evals.json +27 -30
  154. package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +237 -350
  155. package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +276 -325
  156. package/pipeline/skills/shared/external/photos-camera-media/references/av-playback.md +299 -545
  157. package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +344 -588
  158. package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +316 -660
  159. package/pipeline/skills/shared/external/photos-camera-media/references/photokit-patterns.md +270 -416
  160. package/pipeline/skills/shared/external/push-notifications/SKILL.md +312 -340
  161. package/pipeline/skills/shared/external/push-notifications/evals/evals.json +27 -26
  162. package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +328 -485
  163. package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +327 -560
  164. package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +218 -410
  165. package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +24 -27
  166. package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +221 -348
  167. package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +222 -393
  168. package/pipeline/skills/shared/external/shareplay-activities/evals/evals.json +23 -24
  169. package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +280 -420
  170. package/pipeline/skills/shared/external/skill-creator/template.md +7 -1
  171. package/pipeline/skills/shared/external/speech-recognition/SKILL.md +217 -421
  172. package/pipeline/skills/shared/external/speech-recognition/evals/evals.json +23 -26
  173. package/pipeline/skills/shared/external/speech-recognition/references/speechanalyzer-patterns.md +133 -125
  174. package/pipeline/skills/shared/external/storekit/SKILL.md +228 -204
  175. package/pipeline/skills/shared/external/storekit/evals/evals.json +27 -24
  176. package/pipeline/skills/shared/external/storekit/references/app-review-guidelines.md +98 -109
  177. package/pipeline/skills/shared/external/storekit/references/core-patterns.md +302 -241
  178. package/pipeline/skills/shared/external/storekit/references/storekit-advanced.md +356 -649
  179. package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +274 -399
  180. package/pipeline/skills/shared/external/swift-api-design-guidelines/evals/evals.json +22 -24
  181. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/argument-labels-and-parameters.md +107 -108
  182. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/conventions-and-special-rules.md +93 -165
  183. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/naming-and-clarity.md +99 -137
  184. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/side-effects-and-mutating-pairs.md +77 -120
  185. package/pipeline/skills/shared/external/swift-architecture/SKILL.md +334 -350
  186. package/pipeline/skills/shared/external/swift-architecture/evals/evals.json +22 -22
  187. package/pipeline/skills/shared/external/swift-charts/SKILL.md +208 -394
  188. package/pipeline/skills/shared/external/swift-charts/evals/evals.json +27 -30
  189. package/pipeline/skills/shared/external/swift-charts/references/charts-patterns.md +351 -762
  190. package/pipeline/skills/shared/external/swift-codable/SKILL.md +339 -343
  191. package/pipeline/skills/shared/external/swift-codable/evals/evals.json +20 -20
  192. package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +304 -351
  193. package/pipeline/skills/shared/external/swift-concurrency/evals/evals.json +27 -24
  194. package/pipeline/skills/shared/external/swift-concurrency/references/approachable-concurrency.md +65 -80
  195. package/pipeline/skills/shared/external/swift-concurrency/references/async-algorithms.md +48 -84
  196. package/pipeline/skills/shared/external/swift-concurrency/references/bridging-interop.md +134 -79
  197. package/pipeline/skills/shared/external/swift-concurrency/references/concurrency-patterns.md +145 -167
  198. package/pipeline/skills/shared/external/swift-concurrency/references/diagnostics.md +62 -50
  199. package/pipeline/skills/shared/external/swift-concurrency/references/swiftui-concurrency.md +92 -121
  200. package/pipeline/skills/shared/external/swift-concurrency/references/synchronization-primitives.md +177 -241
  201. package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +258 -234
  202. package/pipeline/skills/shared/external/swift-language/SKILL.md +342 -382
  203. package/pipeline/skills/shared/external/swift-language/evals/evals.json +24 -27
  204. package/pipeline/skills/shared/external/swift-language/references/swift-attributes-interop.md +79 -56
  205. package/pipeline/skills/shared/external/swift-language/references/swift-patterns-extended.md +297 -340
  206. package/pipeline/skills/shared/external/swift-security/SKILL.md +183 -162
  207. package/pipeline/skills/shared/external/swift-security/evals/evals.json +25 -25
  208. package/pipeline/skills/shared/external/swift-security/references/biometric-authentication.md +314 -469
  209. package/pipeline/skills/shared/external/swift-security/references/certificate-trust.md +411 -476
  210. package/pipeline/skills/shared/external/swift-security/references/common-anti-patterns.md +260 -530
  211. package/pipeline/skills/shared/external/swift-security/references/compliance-owasp-mapping.md +270 -477
  212. package/pipeline/skills/shared/external/swift-security/references/credential-storage-patterns.md +573 -571
  213. package/pipeline/skills/shared/external/swift-security/references/cryptokit-public-key.md +370 -441
  214. package/pipeline/skills/shared/external/swift-security/references/cryptokit-symmetric.md +332 -433
  215. package/pipeline/skills/shared/external/swift-security/references/keychain-access-control.md +346 -468
  216. package/pipeline/skills/shared/external/swift-security/references/keychain-fundamentals.md +375 -491
  217. package/pipeline/skills/shared/external/swift-security/references/keychain-item-classes.md +431 -432
  218. package/pipeline/skills/shared/external/swift-security/references/keychain-sharing.md +328 -425
  219. package/pipeline/skills/shared/external/swift-security/references/migration-legacy-stores.md +341 -579
  220. package/pipeline/skills/shared/external/swift-security/references/secure-enclave.md +397 -457
  221. package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +354 -614
  222. package/pipeline/skills/shared/external/swift-testing/SKILL.md +191 -175
  223. package/pipeline/skills/shared/external/swift-testing/evals/evals.json +26 -24
  224. package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +81 -84
  225. package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +317 -433
  226. package/pipeline/skills/shared/external/swiftdata/SKILL.md +394 -256
  227. package/pipeline/skills/shared/external/swiftdata/evals/evals.json +24 -24
  228. package/pipeline/skills/shared/external/swiftdata/references/core-data-coexistence.md +206 -402
  229. package/pipeline/skills/shared/external/swiftdata/references/indexing.md +59 -52
  230. package/pipeline/skills/shared/external/swiftdata/references/predicate-pitfalls.md +57 -33
  231. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-advanced.md +354 -747
  232. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-queries.md +300 -508
  233. package/pipeline/skills/shared/external/swiftlint/SKILL.md +175 -226
  234. package/pipeline/skills/shared/external/swiftlint/references/adoption-and-configuration.md +141 -208
  235. package/pipeline/skills/shared/external/swiftlint/references/custom-rules-and-analyze.md +100 -109
  236. package/pipeline/skills/shared/external/swiftlint/references/plugins-run-scripts-and-integrations.md +159 -179
  237. package/pipeline/skills/shared/external/swiftlint/references/rule-reference.md +383 -18
  238. package/pipeline/skills/shared/external/swiftlint/references/rules-suppressions-and-baselines.md +143 -229
  239. package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +283 -366
  240. package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +396 -608
  241. package/pipeline/skills/shared/external/swiftui-animation/references/core-animation-bridge.md +336 -385
  242. package/pipeline/skills/shared/external/swiftui-gestures/SKILL.md +239 -349
  243. package/pipeline/skills/shared/external/swiftui-gestures/references/gesture-patterns.md +228 -310
  244. package/pipeline/skills/shared/external/swiftui-layout-components/SKILL.md +260 -249
  245. package/pipeline/skills/shared/external/swiftui-layout-components/references/form.md +92 -74
  246. package/pipeline/skills/shared/external/swiftui-layout-components/references/grids.md +112 -177
  247. package/pipeline/skills/shared/external/swiftui-layout-components/references/list.md +61 -64
  248. package/pipeline/skills/shared/external/swiftui-layout-components/references/scrollview.md +94 -134
  249. package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +193 -225
  250. package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +173 -327
  251. package/pipeline/skills/shared/external/swiftui-navigation/SKILL.md +201 -168
  252. package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +127 -150
  253. package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +134 -133
  254. package/pipeline/skills/shared/external/swiftui-navigation/references/sheets.md +152 -117
  255. package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +111 -138
  256. package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +316 -252
  257. package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +341 -332
  258. package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +547 -854
  259. package/pipeline/skills/shared/external/swiftui-patterns/references/design-polish.md +485 -537
  260. package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +417 -499
  261. package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +213 -376
  262. package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +86 -175
  263. package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +89 -195
  264. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +95 -182
  265. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-improving-swiftui-performance.md +71 -149
  266. package/pipeline/skills/shared/external/swiftui-performance/references/wwdc-session-sources.md +21 -27
  267. package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +303 -295
  268. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +204 -387
  269. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +469 -683
  270. package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +140 -186
  271. package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md +75 -86
  272. package/pipeline/skills/shared/external/swiftui-webkit/references/local-content-and-custom-schemes.md +63 -60
  273. package/pipeline/skills/shared/external/swiftui-webkit/references/migration-and-fallbacks.md +69 -137
  274. package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md +95 -67
  275. package/pipeline/skills/shared/external/tipkit/SKILL.md +220 -335
  276. package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +356 -494
  277. package/pipeline/skills/shared/external/vision-framework/SKILL.md +260 -375
  278. package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +393 -515
  279. package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +363 -539
  280. package/pipeline/skills/shared/external/weatherkit/SKILL.md +160 -315
  281. package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +288 -407
  282. package/pipeline/skills/shared/external/widgetkit/SKILL.md +224 -288
  283. package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +416 -719
  284. package/pipeline/skills/shared/external/NOTICE-swift-ios-skills.md +0 -39
@@ -1,495 +1,354 @@
1
1
  ---
2
2
  name: cryptokit
3
- description: "Use Apple CryptoKit for Swift cryptographic primitives. Use when hashing with SHA-2 or SHA-3, generating HMACs, encrypting with AES-GCM or ChaChaPoly, signing with P256/P384/P521/Curve25519 or ML-DSA keys, performing ECDH, HPKE, ML-KEM, or X-Wing key exchange, using Secure Enclave CryptoKit keys, or migrating CommonCrypto code to CryptoKit."
3
+ description: "CryptoKit in Swift: SHA-2, SHA-3, HMAC, AES-GCM, ChaChaPoly, P256, P384, P521, Curve25519 and ML-DSA signatures, ECDH with HKDF, HPKE, ML-KEM, X-Wing, SecureEnclave.P256 signing and ECDH. Use when hashing, encrypting, signing or exchanging keys, or migrating from CommonCrypto. Not for Keychain policy (swift-security)."
4
4
  metadata:
5
- source: "dpearson2699/swift-ios-skills (PolyForm Perimeter 1.0.0)"
5
+ source: multi-agent-pipeline
6
6
  ---
7
7
 
8
8
  # CryptoKit
9
9
 
10
- Apple CryptoKit provides a Swift-native API for cryptographic operations:
11
- hashing, message authentication, symmetric encryption, public-key signing,
12
- key agreement, HPKE, quantum-secure key encapsulation/signing, and Secure
13
- Enclave-backed keys. Most core primitives are available on iOS 13+; check
14
- availability for HPKE (iOS 17+) and SHA-3 / post-quantum APIs (iOS 26+).
15
- Prefer CryptoKit over CommonCrypto or raw Security framework APIs for new
16
- cryptographic primitive code targeting Swift 6.3+.
17
-
18
- ## Contents
19
-
20
- - [Hashing](#hashing)
21
- - [HMAC](#hmac)
22
- - [Symmetric Encryption](#symmetric-encryption)
23
- - [Public-Key Signing](#public-key-signing)
24
- - [Key Agreement](#key-agreement)
25
- - [HPKE](#hpke)
26
- - [Post-Quantum CryptoKit](#post-quantum-cryptokit)
27
- - [Secure Enclave](#secure-enclave)
28
- - [Common Mistakes](#common-mistakes)
29
- - [Review Checklist](#review-checklist)
30
- - [References](#references)
10
+ CryptoKit is Apple's Swift API for hashing, message authentication, symmetric
11
+ encryption, signatures, key agreement, HPKE, quantum-secure key encapsulation
12
+ and signatures, and keys kept in the Secure Enclave. For new code (Swift 6.3+)
13
+ reach for it before CommonCrypto or raw Security framework calls.
31
14
 
32
- ## Hashing
15
+ | Feature set | Minimum iOS |
16
+ |---|---|
17
+ | Hashing, HMAC, AES-GCM, ChaChaPoly, P-curves, Curve25519, Secure Enclave P256 | 13 |
18
+ | HPKE | 17 |
19
+ | SHA-3, ML-KEM, ML-DSA, X-Wing | 26 |
33
20
 
34
- CryptoKit provides SHA256, SHA384, and SHA512 hash functions on iOS 13+.
35
- SHA3_256, SHA3_384, and SHA3_512 are available on iOS 26+. All conform
36
- to the `HashFunction` protocol.
21
+ ## Hashing
37
22
 
38
- ### One-shot hashing
23
+ `SHA256`, `SHA384` and `SHA512` exist from iOS 13; `SHA3_256`, `SHA3_384` and
24
+ `SHA3_512` from iOS 26. All of them conform to `HashFunction`, so the API is the
25
+ same for each.
39
26
 
40
27
  ```swift
41
28
  import CryptoKit
29
+ import Foundation
42
30
 
43
- let data = Data("Hello, world!".utf8)
44
- let digest = SHA256.hash(data: data)
45
- let hex = digest.compactMap { String(format: "%02x", $0) }.joined()
46
- ```
47
-
48
- SHA384 and SHA512 work identically -- substitute the type name.
49
-
50
- ### SHA-3 availability
51
-
52
- Use SHA-3 only behind an availability check unless the deployment target is
53
- iOS 26+:
54
-
55
- ```swift
56
- if #available(iOS 26.0, *) {
57
- let digest = SHA3_256.hash(data: data)
31
+ func fingerprint(_ blob: Data) -> String {
32
+ SHA256.hash(data: blob).map { String(format: "%02x", $0) }.joined()
58
33
  }
59
- ```
60
-
61
- ### Incremental hashing
62
-
63
- For large data or streaming input, hash incrementally:
64
-
65
- ```swift
66
- var hasher = SHA256()
67
- hasher.update(data: chunk1)
68
- hasher.update(data: chunk2)
69
- let digest = hasher.finalize()
70
- ```
71
-
72
- ### Digest comparison
73
34
 
74
- Compare CryptoKit digest values directly. Do not convert digests to
75
- strings or arrays for security-sensitive equality checks.
35
+ func strongerFingerprint(_ blob: Data) -> Data {
36
+ if #available(iOS 26.0, *) {
37
+ return Data(SHA3_384.hash(data: blob))
38
+ }
39
+ return Data(SHA384.hash(data: blob))
40
+ }
76
41
 
77
- ```swift
78
- let expected = SHA256.hash(data: reference)
79
- let actual = SHA256.hash(data: received)
80
- if expected == actual {
81
- // Data integrity verified
42
+ func streamingDigest(_ chunks: [Data]) -> SHA512.Digest {
43
+ var running = SHA512()
44
+ for chunk in chunks {
45
+ running.update(data: chunk)
46
+ }
47
+ return running.finalize()
82
48
  }
83
49
  ```
84
50
 
85
- ## HMAC
51
+ - Put SHA-3 behind `if #available(iOS 26.0, *)` unless the deployment target is
52
+ already 26.
53
+ - Use the incremental `update(data:)` / `finalize()` form for large or
54
+ streamed input.
55
+ - Compare digests with `==` on the digest values. Do not turn them into strings
56
+ or arrays for a security-relevant equality check.
86
57
 
87
- HMAC provides message authentication using a symmetric key and a hash function.
58
+ ## HMAC
88
59
 
89
- ### Computing an authentication code
60
+ An HMAC proves that data came from someone holding a shared symmetric key.
90
61
 
91
62
  ```swift
92
- let key = SymmetricKey(size: .bits256)
93
- let data = Data("message".utf8)
94
-
95
- let mac = HMAC<SHA256>.authenticationCode(for: data, using: key)
96
- ```
63
+ import CryptoKit
64
+ import Foundation
97
65
 
98
- ### Verifying an authentication code
66
+ let webhookKey = SymmetricKey(size: .bits256)
99
67
 
100
- ```swift
101
- let isValid = HMAC<SHA256>.isValidAuthenticationCode(
102
- mac, authenticating: data, using: key
103
- )
104
- ```
105
-
106
- This uses constant-time comparison internally.
68
+ func tag(_ body: Data) -> HMAC<SHA256>.MAC {
69
+ HMAC<SHA256>.authenticationCode(for: body, using: webhookKey)
70
+ }
107
71
 
108
- ### Incremental HMAC
72
+ func isGenuine(_ body: Data, mac: HMAC<SHA256>.MAC) -> Bool {
73
+ HMAC<SHA256>.isValidAuthenticationCode(mac, authenticating: body, using: webhookKey)
74
+ }
109
75
 
110
- ```swift
111
- var hmac = HMAC<SHA256>(key: key)
112
- hmac.update(data: chunk1)
113
- hmac.update(data: chunk2)
114
- let mac = hmac.finalize()
76
+ func tagInPieces(_ parts: [Data]) -> HMAC<SHA256>.MAC {
77
+ var signer = HMAC<SHA256>(key: webhookKey)
78
+ parts.forEach { signer.update(data: $0) }
79
+ return signer.finalize()
80
+ }
115
81
  ```
116
82
 
117
- ## Symmetric Encryption
83
+ `isValidAuthenticationCode(_:authenticating:using:)` compares in constant time.
118
84
 
119
- CryptoKit provides two authenticated encryption ciphers: AES-GCM and
120
- ChaChaPoly. Both produce a sealed box containing the nonce, ciphertext,
121
- and authentication tag.
85
+ ## Symmetric encryption
122
86
 
123
- ### AES-GCM
87
+ Both ciphers are AEAD: the sealed box bundles a nonce, the ciphertext and an
88
+ authentication tag.
124
89
 
125
- The default choice for symmetric encryption. Hardware-accelerated on Apple
126
- silicon.
90
+ - **AES-GCM** is the default. Apple silicon accelerates it in hardware.
91
+ - **ChaChaPoly** fits devices without AES acceleration or protocols that
92
+ mandate ChaCha20-Poly1305, such as TLS cipher suites or WireGuard.
127
93
 
128
94
  ```swift
129
- let key = SymmetricKey(size: .bits256)
130
- let plaintext = Data("Secret message".utf8)
131
-
132
- // Encrypt
133
- let sealedBox = try AES.GCM.seal(plaintext, using: key)
134
- let ciphertext = sealedBox.combined! // nonce + ciphertext + tag
135
-
136
- // Decrypt
137
- let box = try AES.GCM.SealedBox(combined: ciphertext)
138
- let decrypted = try AES.GCM.open(box, using: key)
139
- ```
140
-
141
- ### ChaChaPoly
142
-
143
- Use ChaChaPoly when AES hardware acceleration is unavailable or when
144
- interoperating with protocols that require ChaCha20-Poly1305 (e.g., TLS,
145
- WireGuard).
146
-
147
- ```swift
148
- let sealedBox = try ChaChaPoly.seal(plaintext, using: key)
149
- let combined = sealedBox.combined // Always non-optional for ChaChaPoly
150
-
151
- let box = try ChaChaPoly.SealedBox(combined: combined)
152
- let decrypted = try ChaChaPoly.open(box, using: key)
153
- ```
154
-
155
- ### Authenticated data
95
+ import CryptoKit
96
+ import Foundation
156
97
 
157
- Both ciphers support additional authenticated data (AAD). The AAD is
158
- authenticated but not encrypted -- useful for metadata that must remain
159
- in the clear but be tamper-proof.
98
+ func lockNote(_ note: Data, key: SymmetricKey) throws -> Data {
99
+ let box = try AES.GCM.seal(note, using: key)
100
+ guard let packed = box.combined else { throw CryptoKitError.incorrectParameterSize }
101
+ return packed
102
+ }
160
103
 
161
- ```swift
162
- let header = Data("v1".utf8)
163
- let sealedBox = try AES.GCM.seal(
164
- plaintext, using: key, authenticating: header
165
- )
166
- let decrypted = try AES.GCM.open(
167
- sealedBox, using: key, authenticating: header
168
- )
169
- ```
104
+ func unlockNote(_ packed: Data, key: SymmetricKey) throws -> Data {
105
+ try AES.GCM.open(AES.GCM.SealedBox(combined: packed), using: key)
106
+ }
170
107
 
171
- Use `.bits256` as the default `SymmetricKey` size for AES-256-GCM or
172
- ChaChaPoly. To create a key from existing data:
108
+ func lockWithChaCha(_ note: Data, key: SymmetricKey) throws -> Data {
109
+ try ChaChaPoly.seal(note, using: key).combined
110
+ }
173
111
 
174
- ```swift
175
- let key = SymmetricKey(data: existingKeyData)
112
+ func unlockWithChaCha(_ packed: Data, key: SymmetricKey) throws -> Data {
113
+ try ChaChaPoly.open(ChaChaPoly.SealedBox(combined: packed), using: key)
114
+ }
176
115
  ```
177
116
 
178
- ## Public-Key Signing
117
+ `combined` is optional on `AES.GCM.SealedBox` (it is `nil` when a non-standard
118
+ nonce size was used) and non-optional on `ChaChaPoly.SealedBox`.
179
119
 
180
- CryptoKit supports ECDSA signing with NIST curves and Ed25519 via
181
- Curve25519.
120
+ ### Additional authenticated data
182
121
 
183
- ### NIST curves: P256, P384, P521
122
+ Metadata that must travel in the clear but must not be altered goes in the AAD.
123
+ It is authenticated, not encrypted.
184
124
 
185
125
  ```swift
186
- let signingKey = P256.Signing.PrivateKey()
187
- let publicKey = signingKey.publicKey
126
+ import CryptoKit
127
+ import Foundation
188
128
 
189
- // Sign
190
- let signature = try signingKey.signature(for: data)
129
+ func sealRecord(_ payload: Data, recordID: String, key: SymmetricKey) throws -> AES.GCM.SealedBox {
130
+ try AES.GCM.seal(payload, using: key, authenticating: Data(recordID.utf8))
131
+ }
191
132
 
192
- // Verify
193
- let isValid = publicKey.isValidSignature(signature, for: data)
133
+ func openRecord(_ box: AES.GCM.SealedBox, recordID: String, key: SymmetricKey) throws -> Data {
134
+ try AES.GCM.open(box, using: key, authenticating: Data(recordID.utf8))
135
+ }
194
136
  ```
195
137
 
196
- P384 and P521 use the same API -- substitute the curve name.
138
+ ### Keys
139
+
140
+ `SymmetricKey(size: .bits256)` gives AES-256-GCM or ChaChaPoly strength and is
141
+ the right default. Wrap existing key bytes with `SymmetricKey(data:)`.
197
142
 
198
- NIST keys support DER, PEM, X9.63, and raw representations. See
199
- [references/cryptokit-patterns.md](references/cryptokit-patterns.md) for
200
- serialization examples.
143
+ ## Signatures
201
144
 
202
- ### Curve25519 / Ed25519
145
+ ECDSA uses the NIST curves; Ed25519 comes from `Curve25519`.
203
146
 
204
147
  ```swift
205
- let signingKey = Curve25519.Signing.PrivateKey()
206
- let publicKey = signingKey.publicKey
148
+ import CryptoKit
149
+ import Foundation
207
150
 
208
- // Sign
209
- let signature = try signingKey.signature(for: data)
151
+ func signRelease(_ manifest: Data) throws -> (P256.Signing.PublicKey, P256.Signing.ECDSASignature) {
152
+ let signer = P256.Signing.PrivateKey()
153
+ return (signer.publicKey, try signer.signature(for: manifest))
154
+ }
155
+
156
+ func verifyRelease(_ manifest: Data, key: P256.Signing.PublicKey, sig: P256.Signing.ECDSASignature) -> Bool {
157
+ key.isValidSignature(sig, for: manifest)
158
+ }
210
159
 
211
- // Verify
212
- let isValid = publicKey.isValidSignature(signature, for: data)
160
+ func edSign(_ message: Data) throws -> (Curve25519.Signing.PublicKey, Data) {
161
+ let signer = Curve25519.Signing.PrivateKey()
162
+ return (signer.publicKey, try signer.signature(for: message))
163
+ }
213
164
  ```
214
165
 
215
- Curve25519 keys use `rawRepresentation` only (no DER/PEM/X9.63).
166
+ P384 and P521 have the same shape as P256. NIST keys serialize as DER, PEM,
167
+ X9.63 or raw. Curve25519 keys offer only `rawRepresentation`.
216
168
 
217
169
  ### Choosing a curve
218
170
 
219
- | Curve | Signature Scheme | Key Size | Typical Use |
171
+ | Curve | Algorithm | Size | Notes |
220
172
  |---|---|---|---|
221
- | P256 | ECDSA | 256-bit | General purpose; Secure Enclave support |
222
- | P384 | ECDSA | 384-bit | Higher security requirements |
223
- | P521 | ECDSA | 521-bit | Maximum NIST security level |
224
- | Curve25519 | Ed25519 | 256-bit | Fast; simple API; no Secure Enclave |
173
+ | P256 | ECDSA | 256-bit | general default; Secure Enclave capable |
174
+ | P384 | ECDSA | 384-bit | higher margin |
175
+ | P521 | ECDSA | 521-bit | top NIST level |
176
+ | Curve25519 | Ed25519 | 256-bit | fast and simple; no Secure Enclave |
225
177
 
226
- Use P256 by default. Use Curve25519 when interoperating with Ed25519-based
227
- protocols.
178
+ Start with P256. Use Curve25519 when a protocol specifies Ed25519.
228
179
 
229
- ## Key Agreement
180
+ ## Key agreement
230
181
 
231
- Key agreement lets two parties derive a shared symmetric key from their
232
- public/private key pairs using ECDH.
233
-
234
- ### ECDH with P256
182
+ ECDH turns two key pairs into one shared secret. Each side combines its own
183
+ private key with the other side's public key, and both arrive at the same value.
235
184
 
236
185
  ```swift
237
- // Alice
238
- let aliceKey = P256.KeyAgreement.PrivateKey()
239
-
240
- // Bob
241
- let bobKey = P256.KeyAgreement.PrivateKey()
242
-
243
- // Alice computes shared secret
244
- let sharedSecret = try aliceKey.sharedSecretFromKeyAgreement(
245
- with: bobKey.publicKey
246
- )
247
-
248
- // Derive a symmetric key using HKDF
249
- let symmetricKey = sharedSecret.hkdfDerivedSymmetricKey(
250
- using: SHA256.self,
251
- salt: Data("salt".utf8),
252
- sharedInfo: Data("my-app-v1".utf8),
253
- outputByteCount: 32
254
- )
255
- ```
256
-
257
- Bob computes the same `sharedSecret` using his private key and Alice's
258
- public key. Both derive the same `symmetricKey`.
259
-
260
- ### ECDH with Curve25519
186
+ import CryptoKit
187
+ import Foundation
188
+
189
+ func sessionKey(mine: P256.KeyAgreement.PrivateKey, theirs: P256.KeyAgreement.PublicKey) throws -> SymmetricKey {
190
+ let secret = try mine.sharedSecretFromKeyAgreement(with: theirs)
191
+ return secret.hkdfDerivedSymmetricKey(
192
+ using: SHA256.self,
193
+ salt: Data("chat-v2-salt".utf8),
194
+ sharedInfo: Data("chat-v2 message key".utf8),
195
+ outputByteCount: 32
196
+ )
197
+ }
261
198
 
262
- ```swift
263
- let aliceKey = Curve25519.KeyAgreement.PrivateKey()
264
- let bobKey = Curve25519.KeyAgreement.PrivateKey()
265
-
266
- let sharedSecret = try aliceKey.sharedSecretFromKeyAgreement(
267
- with: bobKey.publicKey
268
- )
269
-
270
- let symmetricKey = sharedSecret.hkdfDerivedSymmetricKey(
271
- using: SHA256.self,
272
- salt: Data(),
273
- sharedInfo: Data("context".utf8),
274
- outputByteCount: 32
275
- )
199
+ func x25519Key(mine: Curve25519.KeyAgreement.PrivateKey, theirs: Curve25519.KeyAgreement.PublicKey) throws -> SymmetricKey {
200
+ try mine.sharedSecretFromKeyAgreement(with: theirs).hkdfDerivedSymmetricKey(
201
+ using: SHA256.self,
202
+ salt: Data(),
203
+ sharedInfo: Data("sync-pairing v1".utf8),
204
+ outputByteCount: 32
205
+ )
206
+ }
276
207
  ```
277
208
 
278
- ### Key derivation functions
209
+ ### Derivation
279
210
 
280
- `SharedSecret` is not directly usable as a `SymmetricKey`. Always derive
281
- a key using one of:
211
+ A `SharedSecret` is not a `SymmetricKey` and must always go through a KDF.
282
212
 
283
- | Method | Standard | Use |
213
+ | Method | Standard | When |
284
214
  |---|---|---|
285
- | `hkdfDerivedSymmetricKey` | HKDF (RFC 5869) | Recommended default |
286
- | `x963DerivedSymmetricKey` | ANSI X9.63 | Interop with X9.63 systems |
215
+ | `hkdfDerivedSymmetricKey` | HKDF, RFC 5869 | default choice |
216
+ | `x963DerivedSymmetricKey` | ANSI X9.63 | interoperating with X9.63 systems |
287
217
 
288
- Always provide a non-empty `sharedInfo` string to bind the derived key
289
- to a specific protocol context.
218
+ Always pass a non-empty `sharedInfo` that names the protocol and purpose, so
219
+ the derived key cannot be reused somewhere else.
290
220
 
291
221
  ## HPKE
292
222
 
293
- HPKE is available on iOS 17+ for public-key encryption workflows. Prefer it over
294
- hand-rolled ECDH + HKDF + AEAD protocols when encrypting to a recipient public key.
223
+ HPKE (iOS 17+) is the ready-made way to encrypt to someone's public key.
224
+ Prefer it over wiring ECDH, HKDF and an AEAD together by hand.
295
225
 
296
226
  ```swift
297
- let info = Data("my-protocol-v1".utf8)
298
- let recipientKey = Curve25519.KeyAgreement.PrivateKey()
299
- var sender = try HPKE.Sender(
300
- recipientKey: recipientKey.publicKey,
301
- ciphersuite: .Curve25519_SHA256_ChachaPoly,
302
- info: info
303
- )
304
- let encapsulatedKey = sender.encapsulatedKey
305
- let ciphertext = try sender.seal(
306
- plaintext,
307
- authenticating: Data("metadata".utf8)
308
- )
309
-
310
- var recipient = try HPKE.Recipient(
311
- privateKey: recipientKey,
312
- ciphersuite: .Curve25519_SHA256_ChachaPoly,
313
- info: info,
314
- encapsulatedKey: encapsulatedKey
315
- )
316
- ```
317
-
318
- `HPKE.Sender` and `HPKE.Recipient` are stateful; keep them as `var`, send
319
- `encapsulatedKey` alongside the ciphertext, and open messages in the same
320
- order they were sealed. See [references/cryptokit-patterns.md](references/cryptokit-patterns.md)
321
- for ciphersuite selection and post-quantum HPKE.
322
-
323
- ## Post-Quantum CryptoKit
324
-
325
- iOS 26+ adds quantum-secure APIs:
326
-
327
- - Key encapsulation: `MLKEM768`, `MLKEM1024`
328
- - Hybrid HPKE: `XWingMLKEM768X25519` with `.XWingMLKEM768X25519_SHA256_AES_GCM_256`
329
- - Digital signatures: `MLDSA65`, `MLDSA87`
330
- - Secure Enclave variants: `SecureEnclave.MLKEM768`, `SecureEnclave.MLKEM1024`,
331
- `SecureEnclave.MLDSA65`, `SecureEnclave.MLDSA87`
332
-
333
- Use hybrid mechanisms for migration when both classical and quantum-secure
334
- resistance matter. Account for much larger public keys, ciphertexts, and
335
- signatures than P256 or Curve25519.
336
-
337
- ## Secure Enclave
338
-
339
- The Secure Enclave provides hardware-backed key storage. Private keys
340
- never leave the hardware. For classical elliptic-curve CryptoKit, Secure
341
- Enclave supports P256 signing and key agreement. On iOS 26+ supported
342
- hardware, CryptoKit also exposes Secure Enclave ML-KEM key encapsulation
343
- and ML-DSA signing types.
344
-
345
- ### Availability check
227
+ import CryptoKit
228
+ import Foundation
346
229
 
347
- ```swift
348
- guard SecureEnclave.isAvailable else {
349
- // Fall back to software keys
350
- return
230
+ func encryptForDevice(_ messages: [Data], to device: Curve25519.KeyAgreement.PublicKey) throws -> (Data, [Data]) {
231
+ let context = Data("device-backup v3".utf8)
232
+ var sender = try HPKE.Sender(recipientKey: device, ciphersuite: .Curve25519_SHA256_ChachaPoly, info: context)
233
+ let sealed = try messages.map { try sender.seal($0, authenticating: Data("header".utf8)) }
234
+ return (sender.encapsulatedKey, sealed)
351
235
  }
352
- ```
353
-
354
- ### Creating a Secure Enclave signing key
355
-
356
- ```swift
357
- let privateKey = try SecureEnclave.P256.Signing.PrivateKey()
358
- let publicKey = privateKey.publicKey // Standard P256.Signing.PublicKey
359
-
360
- let signature = try privateKey.signature(for: data)
361
- let isValid = publicKey.isValidSignature(signature, for: data)
362
- ```
363
-
364
- ### Access control
365
-
366
- Use `SecAccessControl` with `.privateKeyUsage` when the key requires biometric
367
- or passcode-gated use. Keep detailed Keychain policy decisions in the
368
- `swift-security` domain.
369
-
370
- ### Persisting Secure Enclave keys
371
-
372
- The `dataRepresentation` is an encrypted blob that only the same device's
373
- Secure Enclave can restore. Store it in the Keychain.
374
-
375
- ```swift
376
- // Export
377
- let blob = privateKey.dataRepresentation
378
236
 
379
- // Restore
380
- let restored = try SecureEnclave.P256.Signing.PrivateKey(
381
- dataRepresentation: blob
382
- )
383
- ```
384
-
385
- ### Secure Enclave key agreement
386
-
387
- ```swift
388
- let seKey = try SecureEnclave.P256.KeyAgreement.PrivateKey()
389
- let peerPublicKey: P256.KeyAgreement.PublicKey = // from peer
390
-
391
- let sharedSecret = try seKey.sharedSecretFromKeyAgreement(
392
- with: peerPublicKey
393
- )
394
- ```
395
-
396
- ## Common Mistakes
397
-
398
- ### 1. Using the shared secret directly as a key
399
-
400
- ```swift
401
- // DON'T
402
- let badKey = sharedSecret.withUnsafeBytes { bytes in
403
- SymmetricKey(data: Data(bytes))
237
+ func decryptOnDevice(_ sealed: [Data], encapsulated: Data, key: Curve25519.KeyAgreement.PrivateKey) throws -> [Data] {
238
+ let context = Data("device-backup v3".utf8)
239
+ var receiver = try HPKE.Recipient(privateKey: key, ciphersuite: .Curve25519_SHA256_ChachaPoly,
240
+ info: context, encapsulatedKey: encapsulated)
241
+ return try sealed.map { try receiver.open($0, authenticating: Data("header".utf8)) }
404
242
  }
405
-
406
- // DO -- derive with HKDF
407
- let goodKey = sharedSecret.hkdfDerivedSymmetricKey(
408
- using: SHA256.self,
409
- salt: salt,
410
- sharedInfo: info,
411
- outputByteCount: 32
412
- )
413
243
  ```
414
244
 
415
- ### 2. Reusing nonces
245
+ - `HPKE.Sender` and `HPKE.Recipient` keep a sequence counter, so they must be
246
+ `var`.
247
+ - Ship `encapsulatedKey` together with the ciphertext.
248
+ - The recipient must open messages in the same order the sender sealed them.
416
249
 
417
- ```swift
418
- // DON'T -- hardcoded nonce
419
- let nonce = try AES.GCM.Nonce(data: Data(repeating: 0, count: 12))
420
- let box = try AES.GCM.seal(data, using: key, nonce: nonce)
250
+ ## Post-quantum CryptoKit (iOS 26+)
421
251
 
422
- // DO -- let CryptoKit generate a random nonce (default behavior)
423
- let box = try AES.GCM.seal(data, using: key)
424
- ```
252
+ | Purpose | Types |
253
+ |---|---|
254
+ | Key encapsulation | `MLKEM768`, `MLKEM1024` |
255
+ | Hybrid HPKE | `XWingMLKEM768X25519` with `.XWingMLKEM768X25519_SHA256_AES_GCM_256` |
256
+ | Signatures | `MLDSA65`, `MLDSA87` |
257
+ | Secure Enclave | `SecureEnclave.MLKEM768`, `SecureEnclave.MLKEM1024`, `SecureEnclave.MLDSA65`, `SecureEnclave.MLDSA87` |
425
258
 
426
- ### 3. Ignoring authentication tag verification
259
+ - During a migration where both classical and quantum resistance matter, use
260
+ the hybrid X-Wing suite.
261
+ - Keys, ciphertexts and signatures are far larger than their P256 or
262
+ Curve25519 counterparts. Budget for that in storage and on the wire.
427
263
 
428
- ```swift
429
- // DON'T -- manually strip tag and decrypt
430
- // DO -- always use AES.GCM.open() or ChaChaPoly.open()
431
- // which verifies the tag automatically
432
- ```
433
-
434
- ### 4. Using Insecure hashes for security
435
-
436
- ```swift
437
- // DON'T -- MD5/SHA1 for integrity or security
438
- import CryptoKit
439
- let bad = Insecure.MD5.hash(data: data)
440
-
441
- // DO -- use SHA256 or stronger
442
- let good = SHA256.hash(data: data)
443
- ```
264
+ ## Secure Enclave
444
265
 
445
- `Insecure.MD5` and `Insecure.SHA1` exist only for legacy compatibility
446
- (checksum verification, protocol interop). Never use them for new
447
- security-sensitive operations.
266
+ The Secure Enclave generates and holds private keys in hardware; they never
267
+ leave it.
448
268
 
449
- ### 5. Storing symmetric keys in UserDefaults
269
+ - Classical support covers P256 signing and P256 key agreement only.
270
+ - On iOS 26 with supported hardware, ML-KEM and ML-DSA keys can live there too.
271
+ - Always check `SecureEnclave.isAvailable` and fall back to software keys.
450
272
 
451
273
  ```swift
452
- // DON'T
453
- UserDefaults.standard.set(rawKeyData, forKey: "encryptionKey")
274
+ import CryptoKit
275
+ import Foundation
276
+ import Security
454
277
 
455
- // DO -- store in Keychain
456
- // See references/cryptokit-patterns.md for Keychain storage patterns
457
- ```
278
+ enum DeviceKeyError: Error {
279
+ case noSecureEnclave
280
+ case accessControlRejected
281
+ }
458
282
 
459
- ### 6. Not checking Secure Enclave availability
283
+ func deviceSigningKey() throws -> Data {
284
+ guard SecureEnclave.isAvailable else { throw DeviceKeyError.noSecureEnclave }
285
+ guard let rule = SecAccessControlCreateWithFlags(nil, kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
286
+ [.privateKeyUsage, .biometryCurrentSet], nil) else {
287
+ throw DeviceKeyError.accessControlRejected
288
+ }
289
+ let key = try SecureEnclave.P256.Signing.PrivateKey(accessControl: rule)
290
+ _ = key.publicKey
291
+ return key.dataRepresentation
292
+ }
460
293
 
461
- ```swift
462
- // DON'T -- crash on simulator or unsupported hardware
463
- let key = try SecureEnclave.P256.Signing.PrivateKey()
294
+ func restoreDeviceKey(_ blob: Data) throws -> SecureEnclave.P256.Signing.PrivateKey {
295
+ try SecureEnclave.P256.Signing.PrivateKey(dataRepresentation: blob)
296
+ }
464
297
 
465
- // DO
466
- guard SecureEnclave.isAvailable else { /* fallback */ }
467
- let key = try SecureEnclave.P256.Signing.PrivateKey()
298
+ func enclaveAgreement(with peer: P256.KeyAgreement.PublicKey) throws -> SharedSecret {
299
+ let mine = try SecureEnclave.P256.KeyAgreement.PrivateKey()
300
+ return try mine.sharedSecretFromKeyAgreement(with: peer)
301
+ }
468
302
  ```
469
303
 
470
- ## Review Checklist
471
-
472
- - [ ] Using CryptoKit, not CommonCrypto or raw Security framework
473
- - [ ] SHA256+ for hashing; no MD5/SHA1 for security purposes
474
- - [ ] HMAC verification uses `isValidAuthenticationCode` (constant-time)
475
- - [ ] AES-GCM or ChaChaPoly for symmetric encryption; 256-bit keys
476
- - [ ] Nonces are random (default) -- not hardcoded or reused
477
- - [ ] Authenticated data (AAD) used where metadata needs integrity
478
- - [ ] SharedSecret derived via HKDF, not used directly
479
- - [ ] sharedInfo parameter is non-empty and context-specific
480
- - [ ] HPKE used instead of custom ECDH+HKDF+AEAD for recipient public-key encryption on iOS 17+
481
- - [ ] SHA-3 and post-quantum APIs guarded with iOS 26+ availability
482
- - [ ] Secure Enclave availability checked before use
483
- - [ ] Secure Enclave key `dataRepresentation` stored in Keychain
484
- - [ ] Private keys not logged, printed, or serialized unnecessarily
485
- - [ ] Symmetric keys stored in Keychain, not UserDefaults or files
486
- - [ ] Encryption export compliance considered (`ITSAppUsesNonExemptEncryption`)
304
+ - The public key of a Secure Enclave signing key is an ordinary
305
+ `P256.Signing.PublicKey`; signing and verifying look the same as in software.
306
+ - Gate use behind biometrics or the passcode with a `SecAccessControl` that
307
+ includes `.privateKeyUsage`. Deeper Keychain policy choices belong to
308
+ `swift-security`.
309
+ - `dataRepresentation` is an encrypted blob that only the same device's Secure
310
+ Enclave can turn back into a key. Store it in the Keychain and restore it
311
+ with `init(dataRepresentation:)`.
312
+
313
+ ## Common mistakes
314
+
315
+ - **Using the raw shared secret as a key.** Always derive with HKDF.
316
+ - **Fixed or repeated nonces.** Passing something like
317
+ `AES.GCM.Nonce(data: Data(count: 12))` to `seal(_:using:nonce:)` for every
318
+ message breaks GCM. Let CryptoKit pick a random nonce by leaving the argument
319
+ out.
320
+ - **Decrypting without the tag check.** Never peel the tag off and decrypt by
321
+ hand. `AES.GCM.open` and `ChaChaPoly.open` verify it for you.
322
+ - **Insecure hashes for security.** `Insecure.MD5` and `Insecure.SHA1` exist
323
+ for legacy checksums and protocol interop only.
324
+ - **Key bytes in `UserDefaults`.** Keys go in the Keychain; see
325
+ [the Keychain patterns](references/cryptokit-patterns.md#keychain-storage).
326
+ - **Secure Enclave without an availability check.** Key creation fails in
327
+ Simulator and on unsupported hardware.
328
+
329
+ ## Review checklist
330
+
331
+ - [ ] CryptoKit is used instead of CommonCrypto or raw Security calls
332
+ - [ ] Hashing uses SHA-256 or stronger; no MD5 or SHA-1 for security
333
+ - [ ] HMACs are verified with `isValidAuthenticationCode`
334
+ - [ ] Encryption is AES-GCM or ChaChaPoly with 256-bit keys
335
+ - [ ] Nonces are random, never hardcoded or reused
336
+ - [ ] AAD protects metadata that needs integrity
337
+ - [ ] Every `SharedSecret` goes through HKDF
338
+ - [ ] `sharedInfo` is non-empty and specific to the context
339
+ - [ ] HPKE replaces hand-built ECDH + HKDF + AEAD for recipient encryption on iOS 17+
340
+ - [ ] SHA-3 and post-quantum code is behind an iOS 26 availability check
341
+ - [ ] `SecureEnclave.isAvailable` is checked
342
+ - [ ] Secure Enclave `dataRepresentation` is stored in the Keychain
343
+ - [ ] Private keys are never logged, printed or serialized without need
344
+ - [ ] Symmetric keys live in the Keychain, not `UserDefaults` or loose files
345
+ - [ ] Export compliance (`ITSAppUsesNonExemptEncryption`) has been considered
487
346
 
488
347
  ## References
489
348
 
490
- - Extended patterns (key serialization, Insecure module, Keychain integration, AES key wrapping, HPKE): [references/cryptokit-patterns.md](references/cryptokit-patterns.md)
491
- - Apple documentation: [CryptoKit](https://sosumi.ai/documentation/cryptokit)
492
- - Apple documentation: [HPKE](https://sosumi.ai/documentation/cryptokit/hpke)
493
- - Apple documentation: [Quantum-secure workflows](https://sosumi.ai/documentation/cryptokit/enhancing-your-app-s-privacy-and-security-with-quantum-secure-workflows)
494
- - Apple sample: [Performing Common Cryptographic Operations](https://sosumi.ai/documentation/cryptokit/performing-common-cryptographic-operations)
495
- - Apple sample: [Storing CryptoKit Keys in the Keychain](https://sosumi.ai/documentation/cryptokit/storing-cryptokit-keys-in-the-keychain)
349
+ - [CryptoKit patterns](references/cryptokit-patterns.md) - key serialization, Keychain storage, AES key wrap, HKDF, HPKE ciphersuites, post-quantum usage, the Insecure namespace, sealed box layout, digest signing, export compliance, performance, CommonCrypto migration
350
+ - [CryptoKit](https://developer.apple.com/documentation/cryptokit)
351
+ - [HPKE](https://developer.apple.com/documentation/cryptokit/hpke)
352
+ - [Enhancing your app's privacy and security with quantum-secure workflows](https://developer.apple.com/documentation/cryptokit/enhancing-your-app-s-privacy-and-security-with-quantum-secure-workflows)
353
+ - [Performing common cryptographic operations](https://developer.apple.com/documentation/cryptokit/performing-common-cryptographic-operations)
354
+ - [Storing CryptoKit keys in the keychain](https://developer.apple.com/documentation/cryptokit/storing-cryptokit-keys-in-the-keychain)