@mmerterden/multi-agent-pipeline 20.7.0 → 20.8.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.
Files changed (264) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/LICENSE +0 -10
  3. package/docs/facts.json +1 -1
  4. package/manifest.json +266 -267
  5. package/package.json +2 -2
  6. package/pipeline/scripts/_notices.mjs +1 -1
  7. package/pipeline/skills/.skill-manifest.json +68 -68
  8. package/pipeline/skills/shared/README.md +70 -70
  9. package/pipeline/skills/shared/external/alarmkit/SKILL.md +373 -381
  10. package/pipeline/skills/shared/external/alarmkit/evals/evals.json +23 -18
  11. package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +328 -378
  12. package/pipeline/skills/shared/external/app-clips/SKILL.md +260 -160
  13. package/pipeline/skills/shared/external/app-clips/evals/evals.json +27 -27
  14. package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +150 -83
  15. package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +135 -83
  16. package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +143 -85
  17. package/pipeline/skills/shared/external/app-intents/SKILL.md +302 -304
  18. package/pipeline/skills/shared/external/app-intents/evals/evals.json +21 -21
  19. package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +594 -894
  20. package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +339 -277
  21. package/pipeline/skills/shared/external/app-store-optimization/evals/evals.json +27 -23
  22. package/pipeline/skills/shared/external/app-store-optimization/references/keyword-research-methodology.md +105 -122
  23. package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +143 -166
  24. package/pipeline/skills/shared/external/app-store-review/SKILL.md +307 -326
  25. package/pipeline/skills/shared/external/app-store-review/evals/evals.json +21 -21
  26. package/pipeline/skills/shared/external/app-store-review/references/privacy-manifest.md +105 -67
  27. package/pipeline/skills/shared/external/app-store-review/references/review-checklists.md +114 -101
  28. package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +333 -360
  29. package/pipeline/skills/shared/external/apple-on-device-ai/evals/evals.json +24 -27
  30. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-conversion.md +215 -322
  31. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-optimization.md +161 -256
  32. package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models.md +277 -387
  33. package/pipeline/skills/shared/external/apple-on-device-ai/references/mlx-swift.md +196 -210
  34. package/pipeline/skills/shared/external/authentication/SKILL.md +265 -381
  35. package/pipeline/skills/shared/external/authentication/evals/evals.json +25 -25
  36. package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +133 -178
  37. package/pipeline/skills/shared/external/authentication/references/passkeys.md +111 -147
  38. package/pipeline/skills/shared/external/avkit/SKILL.md +267 -364
  39. package/pipeline/skills/shared/external/avkit/evals/evals.json +26 -26
  40. package/pipeline/skills/shared/external/avkit/references/avkit-patterns.md +375 -493
  41. package/pipeline/skills/shared/external/background-processing/SKILL.md +270 -382
  42. package/pipeline/skills/shared/external/background-processing/evals/evals.json +22 -22
  43. package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +169 -317
  44. package/pipeline/skills/shared/external/callkit-voip/SKILL.md +290 -371
  45. package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +24 -24
  46. package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +175 -343
  47. package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +292 -381
  48. package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +33 -30
  49. package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +227 -355
  50. package/pipeline/skills/shared/external/contacts-framework/SKILL.md +197 -346
  51. package/pipeline/skills/shared/external/contacts-framework/evals/evals.json +19 -21
  52. package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +169 -308
  53. package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +226 -376
  54. package/pipeline/skills/shared/external/core-bluetooth/evals/evals.json +25 -22
  55. package/pipeline/skills/shared/external/core-bluetooth/references/ble-patterns.md +257 -337
  56. package/pipeline/skills/shared/external/core-data/SKILL.md +292 -368
  57. package/pipeline/skills/shared/external/core-data/evals/evals.json +30 -27
  58. package/pipeline/skills/shared/external/core-motion/SKILL.md +235 -324
  59. package/pipeline/skills/shared/external/core-motion/evals/evals.json +31 -27
  60. package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +210 -310
  61. package/pipeline/skills/shared/external/core-nfc/SKILL.md +292 -366
  62. package/pipeline/skills/shared/external/core-nfc/evals/evals.json +22 -24
  63. package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +233 -329
  64. package/pipeline/skills/shared/external/coreml/SKILL.md +323 -367
  65. package/pipeline/skills/shared/external/coreml/evals/evals.json +24 -21
  66. package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +562 -565
  67. package/pipeline/skills/shared/external/cryptokit/SKILL.md +253 -394
  68. package/pipeline/skills/shared/external/cryptokit/evals/evals.json +20 -18
  69. package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +299 -488
  70. package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +270 -323
  71. package/pipeline/skills/shared/external/debugging-instruments/evals/evals.json +27 -30
  72. package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +167 -315
  73. package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +140 -193
  74. package/pipeline/skills/shared/external/device-integrity/SKILL.md +230 -353
  75. package/pipeline/skills/shared/external/device-integrity/evals/evals.json +25 -21
  76. package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +159 -197
  77. package/pipeline/skills/shared/external/energykit/SKILL.md +225 -392
  78. package/pipeline/skills/shared/external/energykit/evals/evals.json +29 -28
  79. package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +174 -470
  80. package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +261 -383
  81. package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +25 -22
  82. package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +165 -268
  83. package/pipeline/skills/shared/external/healthkit/SKILL.md +252 -303
  84. package/pipeline/skills/shared/external/healthkit/evals/evals.json +24 -23
  85. package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +369 -523
  86. package/pipeline/skills/shared/external/homekit-matter/SKILL.md +233 -348
  87. package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +27 -22
  88. package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +199 -305
  89. package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +368 -340
  90. package/pipeline/skills/shared/external/ios-accessibility/evals/evals.json +28 -27
  91. package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +314 -260
  92. package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +97 -67
  93. package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +165 -101
  94. package/pipeline/skills/shared/external/ios-localization/SKILL.md +258 -371
  95. package/pipeline/skills/shared/external/ios-localization/evals/evals.json +23 -23
  96. package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +283 -491
  97. package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +313 -440
  98. package/pipeline/skills/shared/external/ios-networking/SKILL.md +265 -341
  99. package/pipeline/skills/shared/external/ios-networking/evals/evals.json +24 -24
  100. package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +425 -652
  101. package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +143 -285
  102. package/pipeline/skills/shared/external/ios-networking/references/lightweight-clients.md +93 -53
  103. package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +231 -456
  104. package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +517 -784
  105. package/pipeline/skills/shared/external/ios-simulator/SKILL.md +265 -393
  106. package/pipeline/skills/shared/external/ios-simulator/evals/evals.json +21 -21
  107. package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +177 -270
  108. package/pipeline/skills/shared/external/live-activities/SKILL.md +318 -360
  109. package/pipeline/skills/shared/external/live-activities/evals/evals.json +21 -21
  110. package/pipeline/skills/shared/external/live-activities/references/activitykit-patterns.md +478 -710
  111. package/pipeline/skills/shared/external/mapkit-location/SKILL.md +295 -267
  112. package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +28 -24
  113. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-corelocation-patterns.md +378 -532
  114. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +397 -499
  115. package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +165 -348
  116. package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +26 -23
  117. package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +123 -130
  118. package/pipeline/skills/shared/external/musickit-audio/SKILL.md +189 -315
  119. package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +22 -21
  120. package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +181 -270
  121. package/pipeline/skills/shared/external/natural-language/SKILL.md +188 -340
  122. package/pipeline/skills/shared/external/natural-language/evals/evals.json +21 -21
  123. package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +171 -225
  124. package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +258 -392
  125. package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +30 -29
  126. package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +164 -231
  127. package/pipeline/skills/shared/external/pdfkit/SKILL.md +312 -344
  128. package/pipeline/skills/shared/external/pdfkit/evals/evals.json +19 -19
  129. package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +413 -624
  130. package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +242 -358
  131. package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +25 -21
  132. package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +161 -226
  133. package/pipeline/skills/shared/external/permissionkit/SKILL.md +282 -400
  134. package/pipeline/skills/shared/external/permissionkit/evals/evals.json +27 -30
  135. package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +237 -350
  136. package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +276 -325
  137. package/pipeline/skills/shared/external/photos-camera-media/references/av-playback.md +299 -545
  138. package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +344 -588
  139. package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +316 -660
  140. package/pipeline/skills/shared/external/photos-camera-media/references/photokit-patterns.md +270 -416
  141. package/pipeline/skills/shared/external/push-notifications/SKILL.md +312 -340
  142. package/pipeline/skills/shared/external/push-notifications/evals/evals.json +27 -26
  143. package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +328 -485
  144. package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +327 -560
  145. package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +218 -410
  146. package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +24 -27
  147. package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +221 -348
  148. package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +222 -393
  149. package/pipeline/skills/shared/external/shareplay-activities/evals/evals.json +23 -24
  150. package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +280 -420
  151. package/pipeline/skills/shared/external/speech-recognition/SKILL.md +217 -421
  152. package/pipeline/skills/shared/external/speech-recognition/evals/evals.json +23 -26
  153. package/pipeline/skills/shared/external/speech-recognition/references/speechanalyzer-patterns.md +133 -125
  154. package/pipeline/skills/shared/external/storekit/SKILL.md +228 -204
  155. package/pipeline/skills/shared/external/storekit/evals/evals.json +27 -24
  156. package/pipeline/skills/shared/external/storekit/references/app-review-guidelines.md +98 -109
  157. package/pipeline/skills/shared/external/storekit/references/core-patterns.md +298 -242
  158. package/pipeline/skills/shared/external/storekit/references/storekit-advanced.md +356 -649
  159. package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +274 -399
  160. package/pipeline/skills/shared/external/swift-api-design-guidelines/evals/evals.json +22 -24
  161. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/argument-labels-and-parameters.md +107 -108
  162. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/conventions-and-special-rules.md +93 -165
  163. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/naming-and-clarity.md +99 -137
  164. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/side-effects-and-mutating-pairs.md +77 -120
  165. package/pipeline/skills/shared/external/swift-architecture/SKILL.md +334 -350
  166. package/pipeline/skills/shared/external/swift-architecture/evals/evals.json +22 -22
  167. package/pipeline/skills/shared/external/swift-charts/SKILL.md +208 -394
  168. package/pipeline/skills/shared/external/swift-charts/evals/evals.json +27 -30
  169. package/pipeline/skills/shared/external/swift-charts/references/charts-patterns.md +351 -762
  170. package/pipeline/skills/shared/external/swift-codable/SKILL.md +339 -343
  171. package/pipeline/skills/shared/external/swift-codable/evals/evals.json +20 -20
  172. package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +303 -351
  173. package/pipeline/skills/shared/external/swift-concurrency/evals/evals.json +27 -24
  174. package/pipeline/skills/shared/external/swift-concurrency/references/approachable-concurrency.md +65 -80
  175. package/pipeline/skills/shared/external/swift-concurrency/references/async-algorithms.md +48 -84
  176. package/pipeline/skills/shared/external/swift-concurrency/references/bridging-interop.md +134 -79
  177. package/pipeline/skills/shared/external/swift-concurrency/references/concurrency-patterns.md +145 -167
  178. package/pipeline/skills/shared/external/swift-concurrency/references/diagnostics.md +62 -50
  179. package/pipeline/skills/shared/external/swift-concurrency/references/swiftui-concurrency.md +92 -121
  180. package/pipeline/skills/shared/external/swift-concurrency/references/synchronization-primitives.md +177 -241
  181. package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +258 -234
  182. package/pipeline/skills/shared/external/swift-language/SKILL.md +342 -382
  183. package/pipeline/skills/shared/external/swift-language/evals/evals.json +24 -27
  184. package/pipeline/skills/shared/external/swift-language/references/swift-attributes-interop.md +79 -56
  185. package/pipeline/skills/shared/external/swift-language/references/swift-patterns-extended.md +297 -340
  186. package/pipeline/skills/shared/external/swift-security/SKILL.md +180 -161
  187. package/pipeline/skills/shared/external/swift-security/evals/evals.json +25 -25
  188. package/pipeline/skills/shared/external/swift-security/references/biometric-authentication.md +314 -469
  189. package/pipeline/skills/shared/external/swift-security/references/certificate-trust.md +408 -476
  190. package/pipeline/skills/shared/external/swift-security/references/common-anti-patterns.md +260 -530
  191. package/pipeline/skills/shared/external/swift-security/references/compliance-owasp-mapping.md +270 -477
  192. package/pipeline/skills/shared/external/swift-security/references/credential-storage-patterns.md +573 -571
  193. package/pipeline/skills/shared/external/swift-security/references/cryptokit-public-key.md +370 -441
  194. package/pipeline/skills/shared/external/swift-security/references/cryptokit-symmetric.md +332 -433
  195. package/pipeline/skills/shared/external/swift-security/references/keychain-access-control.md +346 -468
  196. package/pipeline/skills/shared/external/swift-security/references/keychain-fundamentals.md +352 -472
  197. package/pipeline/skills/shared/external/swift-security/references/keychain-item-classes.md +431 -432
  198. package/pipeline/skills/shared/external/swift-security/references/keychain-sharing.md +328 -425
  199. package/pipeline/skills/shared/external/swift-security/references/migration-legacy-stores.md +341 -579
  200. package/pipeline/skills/shared/external/swift-security/references/secure-enclave.md +396 -457
  201. package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +354 -614
  202. package/pipeline/skills/shared/external/swift-testing/SKILL.md +188 -175
  203. package/pipeline/skills/shared/external/swift-testing/evals/evals.json +26 -24
  204. package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +80 -84
  205. package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +317 -433
  206. package/pipeline/skills/shared/external/swiftdata/SKILL.md +392 -256
  207. package/pipeline/skills/shared/external/swiftdata/evals/evals.json +24 -24
  208. package/pipeline/skills/shared/external/swiftdata/references/core-data-coexistence.md +206 -402
  209. package/pipeline/skills/shared/external/swiftdata/references/indexing.md +59 -52
  210. package/pipeline/skills/shared/external/swiftdata/references/predicate-pitfalls.md +57 -33
  211. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-advanced.md +354 -747
  212. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-queries.md +300 -508
  213. package/pipeline/skills/shared/external/swiftlint/SKILL.md +175 -226
  214. package/pipeline/skills/shared/external/swiftlint/references/adoption-and-configuration.md +141 -208
  215. package/pipeline/skills/shared/external/swiftlint/references/custom-rules-and-analyze.md +100 -109
  216. package/pipeline/skills/shared/external/swiftlint/references/plugins-run-scripts-and-integrations.md +159 -179
  217. package/pipeline/skills/shared/external/swiftlint/references/rule-reference.md +383 -18
  218. package/pipeline/skills/shared/external/swiftlint/references/rules-suppressions-and-baselines.md +143 -229
  219. package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +283 -366
  220. package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +396 -608
  221. package/pipeline/skills/shared/external/swiftui-animation/references/core-animation-bridge.md +336 -385
  222. package/pipeline/skills/shared/external/swiftui-gestures/SKILL.md +239 -349
  223. package/pipeline/skills/shared/external/swiftui-gestures/references/gesture-patterns.md +228 -310
  224. package/pipeline/skills/shared/external/swiftui-layout-components/SKILL.md +260 -249
  225. package/pipeline/skills/shared/external/swiftui-layout-components/references/form.md +92 -74
  226. package/pipeline/skills/shared/external/swiftui-layout-components/references/grids.md +112 -177
  227. package/pipeline/skills/shared/external/swiftui-layout-components/references/list.md +61 -64
  228. package/pipeline/skills/shared/external/swiftui-layout-components/references/scrollview.md +94 -134
  229. package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +193 -225
  230. package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +173 -327
  231. package/pipeline/skills/shared/external/swiftui-navigation/SKILL.md +193 -168
  232. package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +127 -150
  233. package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +132 -133
  234. package/pipeline/skills/shared/external/swiftui-navigation/references/sheets.md +152 -117
  235. package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +106 -140
  236. package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +316 -252
  237. package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +341 -332
  238. package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +547 -854
  239. package/pipeline/skills/shared/external/swiftui-patterns/references/design-polish.md +485 -537
  240. package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +417 -499
  241. package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +213 -376
  242. package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +86 -175
  243. package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +89 -195
  244. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +95 -182
  245. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-improving-swiftui-performance.md +71 -149
  246. package/pipeline/skills/shared/external/swiftui-performance/references/wwdc-session-sources.md +21 -27
  247. package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +303 -295
  248. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +204 -387
  249. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +469 -683
  250. package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +140 -186
  251. package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md +75 -86
  252. package/pipeline/skills/shared/external/swiftui-webkit/references/local-content-and-custom-schemes.md +63 -60
  253. package/pipeline/skills/shared/external/swiftui-webkit/references/migration-and-fallbacks.md +69 -137
  254. package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md +95 -67
  255. package/pipeline/skills/shared/external/tipkit/SKILL.md +220 -335
  256. package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +356 -494
  257. package/pipeline/skills/shared/external/vision-framework/SKILL.md +260 -375
  258. package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +393 -515
  259. package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +363 -539
  260. package/pipeline/skills/shared/external/weatherkit/SKILL.md +152 -310
  261. package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +288 -407
  262. package/pipeline/skills/shared/external/widgetkit/SKILL.md +216 -288
  263. package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +414 -719
  264. 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 primitives in Swift: SHA-2 and SHA-3, HMAC, AES-GCM and ChaChaPoly, P256, P384, P521, Curve25519 and ML-DSA signatures, ECDH with HKDF, HPKE, ML-KEM and X-Wing, Secure Enclave keys. 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)