@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,490 +1,356 @@
1
1
  ---
2
2
  name: passkit-wallet
3
- description: "Integrate Apple Pay payments and Wallet passes using PassKit. Use when adding Apple Pay buttons, creating payment requests, handling payment authorization, adding passes to Wallet, configuring merchant capabilities, managing shipping/contact fields, or working with PKPaymentRequest, PKPaymentAuthorizationController, PKPaymentButton, AddPassToWalletButton, PKPass, PKAddPassesViewController, PKPassLibrary, Wallet pass distribution, or Apple Pay checkout flows for physical goods, real-world services, donations, and eligible recurring payments."
3
+ description: "Apple Pay and Wallet passes with PassKit: Apple Pay buttons, payment requests, authorization flow, merchant capabilities, shipping and contact fields, adding and distributing passes (PKPaymentRequest, PKPaymentButton, PKPaymentAuthorizationController, PKPass, AddPassToWalletButton, PKPassLibrary, PKAddPassesViewController). Use when building Apple Pay checkout for physical goods, real-world services, donations or eligible recurring payments, or adding and updating Wallet passes. Not for digital goods or subscriptions (storekit) or FinanceKit."
4
4
  metadata:
5
- source: "dpearson2699/swift-ios-skills (PolyForm Perimeter 1.0.0)"
5
+ source: multi-agent-pipeline
6
6
  ---
7
7
 
8
- # PassKit
8
+ # PassKit: Apple Pay and Wallet
9
9
 
10
- Accept Apple Pay payments for physical goods, real-world services, donations,
11
- and eligible recurring payments, and add passes to the user's Wallet. Covers
12
- payment buttons, payment requests, authorization, Wallet passes, and merchant
13
- configuration. Targets Swift 6.3 / iOS 26+.
10
+ PassKit covers two things: taking Apple Pay payments and putting passes
11
+ (tickets, cards, coupons) into Wallet. Apple Pay is meant for tangible
12
+ products, in-person or real-world services, donations and eligible recurring
13
+ charges.
14
+ Examples assume Swift 6.3 and iOS 26.
14
15
 
15
- For advanced Apple Pay flows, one `PKPaymentRequest` can set only one optional
16
- advanced request type: recurring, automatic reload, deferred, Apple Pay Later
17
- availability, or multi-token contexts. Use separate payment requests when a
18
- checkout needs more than one of those modes.
19
-
20
- ## Contents
21
-
22
- - [Setup](#setup)
23
- - [Displaying the Apple Pay Button](#displaying-the-apple-pay-button)
24
- - [Creating a Payment Request](#creating-a-payment-request)
25
- - [Presenting the Payment Sheet](#presenting-the-payment-sheet)
26
- - [Handling Payment Authorization](#handling-payment-authorization)
27
- - [Wallet Passes](#wallet-passes)
28
- - [Checking Pass Library](#checking-pass-library)
29
- - [Common Mistakes](#common-mistakes)
30
- - [Review Checklist](#review-checklist)
31
- - [References](#references)
16
+ One rule shapes advanced checkouts: a single `PKPaymentRequest` may carry at
17
+ most one optional advanced type. The candidates are a recurring request, an
18
+ automatic-reload request, a deferred request, the Apple Pay Later setting, and
19
+ multi-token contexts. When a flow
20
+ needs two of them, build two requests.
32
21
 
33
22
  ## Setup
34
23
 
35
- ### Project Configuration
36
-
37
- 1. Enable the **Apple Pay** capability in Xcode
38
- 2. Create a Merchant ID in the Apple Developer portal (format: `merchant.com.example.app`)
39
- 3. Generate and install a Payment Processing Certificate for your merchant ID
40
- 4. Add the merchant ID to your entitlements
24
+ 1. Add the **Apple Pay** capability to the target.
25
+ 2. Register a Merchant ID in the developer portal, in the form
26
+ `merchant.com.yourcompany.store`.
27
+ 3. Create the Payment Processing Certificate for that Merchant ID and hand it
28
+ to your processor or server.
29
+ 4. Make sure the Merchant ID is listed in the app's entitlements.
41
30
 
42
- ### Availability Check
31
+ ### Can this device pay?
43
32
 
44
- Always verify the device can make payments before showing Apple Pay UI. If you
45
- check for an active card with `canMakePayments(usingNetworks:capabilities:)`,
46
- Apple's HIG expects Apple Pay to be a primary, prominent payment option wherever
47
- you use that check.
33
+ Check before any Apple Pay UI appears, in two steps:
48
34
 
49
35
  ```swift
50
36
  import PassKit
51
37
 
52
- func canMakePayments() -> Bool {
53
- // Check device supports Apple Pay at all
54
- guard PKPaymentAuthorizationController.canMakePayments() else {
55
- return false
38
+ enum Checkout {
39
+ static let merchantID = "merchant.com.yourcompany.store"
40
+ static let country = "US"
41
+ static let currency = "USD"
42
+ static let networks: [PKPaymentNetwork] = [.visa, .masterCard, .amex, .discover]
43
+
44
+ static var deviceSupportsApplePay: Bool {
45
+ PKPaymentAuthorizationController.canMakePayments()
46
+ }
47
+
48
+ static var walletHasUsableCard: Bool {
49
+ PKPaymentAuthorizationController.canMakePayments(
50
+ usingNetworks: networks,
51
+ capabilities: .threeDSecure
52
+ )
56
53
  }
57
- // Check user has cards for the networks you support
58
- return PKPaymentAuthorizationController.canMakePayments(
59
- usingNetworks: [.visa, .masterCard, .amex, .discover],
60
- capabilities: .threeDSecure
61
- )
62
54
  }
63
55
  ```
64
56
 
65
- ## Displaying the Apple Pay Button
57
+ The first call asks whether the hardware and region support Apple Pay; the
58
+ second whether the user has a card on one of your networks. Keeping merchant
59
+ ID, country, currency and networks in one type also avoids scattering the
60
+ Merchant ID string through the codebase.
61
+
62
+ The Human Interface Guidelines attach a condition to the second call: an app
63
+ that asks whether the user holds an active card must then present Apple Pay
64
+ as a primary, prominent way to pay.
66
65
 
67
- ### SwiftUI
66
+ ## The Apple Pay button
68
67
 
69
- Use the built-in `PayWithApplePayButton` view in SwiftUI. Use Apple-provided
70
- button APIs for any control labeled Apple Pay; custom buttons must not include
71
- the Apple Pay logo or "Apple Pay" text.
68
+ Anything labelled Apple Pay must be Apple's own button. A custom control may
69
+ not show the Apple Pay mark or the words "Apple Pay".
72
70
 
73
71
  ```swift
74
- import SwiftUI
75
- import PassKit
72
+ struct BasketFooter: View {
73
+ let startPayment: () -> Void
76
74
 
77
- struct CheckoutView: View {
78
75
  var body: some View {
79
- PayWithApplePayButton(.buy) {
80
- startPayment()
81
- }
82
- .payWithApplePayButtonStyle(.black)
83
- .frame(height: 48)
84
- .padding()
76
+ PayWithApplePayButton(.checkout, action: startPayment)
77
+ .payWithApplePayButtonStyle(.black)
78
+ .frame(height: 50)
85
79
  }
86
80
  }
87
81
  ```
88
82
 
89
- ### UIKit
90
-
91
- Use `PKPaymentButton` for UIKit-based interfaces.
83
+ UIKit uses `PKPaymentButton`:
92
84
 
93
85
  ```swift
94
- let button = PKPaymentButton(
95
- paymentButtonType: .buy,
96
- paymentButtonStyle: .black
97
- )
98
- button.cornerRadius = 12
99
- button.addTarget(self, action: #selector(startPayment), for: .touchUpInside)
86
+ let payButton = PKPaymentButton(paymentButtonType: .checkout, paymentButtonStyle: .black)
87
+ payButton.cornerRadius = 10
88
+ payButton.addTarget(self, action: #selector(payTapped), for: .primaryActionTriggered)
100
89
  ```
101
90
 
102
- **Button types:** `.plain`, `.buy`, `.setUp`, `.inStore`, `.donate`,
103
- `.checkout`, `.continue`, `.book`, `.subscribe`, `.reload`, `.addMoney`,
104
- `.topUp`, `.order`, `.rent`, `.support`, `.contribute`, `.tip`
91
+ Pick the `PKPaymentButtonType` whose wording fits the action:
105
92
 
106
- ## Creating a Payment Request
93
+ | Purpose | Types |
94
+ |---------|-------|
95
+ | Generic or purchase | `.plain`, `.buy`, `.checkout`, `.continue`, `.order` |
96
+ | Setup and in-store | `.setUp`, `.inStore` |
97
+ | Giving | `.donate`, `.contribute`, `.support`, `.tip` |
98
+ | Bookings and plans | `.book`, `.rent`, `.subscribe` |
99
+ | Balances | `.reload`, `.addMoney`, `.topUp` |
107
100
 
108
- Build a `PKPaymentRequest` with your merchant details and the items being purchased.
109
- PassKit amount APIs take `NSDecimalNumber`, not `Double`.
101
+ ## Building the request
110
102
 
111
103
  ```swift
112
- func createPaymentRequest() -> PKPaymentRequest {
113
- let request = PKPaymentRequest()
114
- request.merchantIdentifier = "merchant.com.example.app"
115
- request.countryCode = "US"
116
- request.currencyCode = "USD"
117
- request.supportedNetworks = [.visa, .masterCard, .amex, .discover]
118
- request.merchantCapabilities = .threeDSecure
119
-
120
- request.paymentSummaryItems = [
121
- PKPaymentSummaryItem(
122
- label: "Widget",
123
- amount: NSDecimalNumber(string: "9.99")
124
- ),
125
- PKPaymentSummaryItem(
126
- label: "Shipping",
127
- amount: NSDecimalNumber(string: "4.99")
128
- ),
129
- PKPaymentSummaryItem(
130
- label: "My Store",
131
- amount: NSDecimalNumber(string: "14.98")
132
- ) // Total
133
- ]
134
-
135
- return request
104
+ func makeRequest(for basket: Basket) -> PKPaymentRequest {
105
+ let order = PKPaymentRequest()
106
+ order.merchantIdentifier = Checkout.merchantID
107
+ order.countryCode = Checkout.country
108
+ order.currencyCode = Checkout.currency
109
+ order.supportedNetworks = Checkout.networks
110
+ order.merchantCapabilities = .threeDSecure
111
+
112
+ let goods = PKPaymentSummaryItem(label: "Ceramic Mugs (2)", amount: NSDecimalNumber(string: "36.00"))
113
+ let tax = PKPaymentSummaryItem(label: "Sales Tax", amount: NSDecimalNumber(string: "2.97"))
114
+ let total = PKPaymentSummaryItem(label: "Clayworks Studio", amount: goods.amount.adding(tax.amount))
115
+ order.paymentSummaryItems = [goods, tax, total]
116
+ return order
136
117
  }
137
118
  ```
138
119
 
139
- The **last item** in `paymentSummaryItems` is treated as the total and its label
140
- appears in the Pay line on the payment sheet.
120
+ - Money is `NSDecimalNumber`, built from a string or integer parts. A `Double`
121
+ literal such as `36.1` is already imprecise before it reaches PassKit.
122
+ - The last summary item is the total. Its label, your business name, is what
123
+ appears on the Pay line. Leave it out and the sheet shows your last line
124
+ item there instead.
141
125
 
142
- ### Requesting Shipping and Contact Info
126
+ ### Shipping and contact details
143
127
 
144
- Request only the contact fields needed to price, fulfill, or legally process the
145
- order.
146
- Collect required product choices, optional notes, per-item shipping destinations,
147
- and pickup locations before the Apple Pay button when the payment sheet cannot
148
- collect them accurately.
128
+ Ask only for what you need to price, fulfil or legally process the order.
129
+ Anything the sheet cannot collect well (product options, notes, gifts shipped
130
+ to several addresses, a pickup store) belongs on your own screen before the
131
+ Apple Pay button.
149
132
 
150
133
  ```swift
151
- request.requiredShippingContactFields = [.postalAddress, .emailAddress, .name]
152
- request.requiredBillingContactFields = [.postalAddress]
153
-
154
- let standard = PKShippingMethod(
155
- label: "Standard",
156
- amount: NSDecimalNumber(string: "4.99")
157
- )
158
- standard.identifier = "standard"
159
- standard.detail = "5-7 business days"
160
-
161
- let express = PKShippingMethod(
162
- label: "Express",
163
- amount: NSDecimalNumber(string: "9.99")
164
- )
165
- express.identifier = "express"
166
- express.detail = "1-2 business days"
167
-
168
- request.shippingMethods = [standard, express]
169
-
170
- request.shippingType = .shipping // .delivery, .storePickup, .servicePickup
134
+ order.requiredShippingContactFields = [.postalAddress, .name, .phoneNumber]
135
+ order.requiredBillingContactFields = [.postalAddress]
136
+
137
+ func delivery(_ id: String, _ title: String, _ price: String, _ eta: String) -> PKShippingMethod {
138
+ let method = PKShippingMethod(label: title, amount: NSDecimalNumber(string: price))
139
+ method.identifier = id
140
+ method.detail = eta
141
+ return method
142
+ }
143
+
144
+ order.shippingMethods = [
145
+ delivery("ground", "Ground", "4.50", "Arrives in 3 to 5 days"),
146
+ delivery("overnight", "Overnight", "12.00", "Arrives tomorrow"),
147
+ ]
148
+ order.shippingType = .shipping
171
149
  ```
172
150
 
173
- ### Supported Networks
151
+ `shippingType` can be `.shipping`, `.delivery`, `.storePickup` or
152
+ `.servicePickup`.
174
153
 
175
- | Network | Constant |
176
- |---|---|
177
- | Visa | `.visa` |
178
- | Mastercard | `.masterCard` |
179
- | American Express | `.amex` |
180
- | Discover | `.discover` |
181
- | China UnionPay | `.chinaUnionPay` |
182
- | JCB | `.JCB` |
183
- | Maestro | `.maestro` |
184
- | Electron | `.electron` |
185
- | Interac | `.interac` |
154
+ ### Networks
186
155
 
187
- Query available networks at runtime with `PKPaymentRequest.availableNetworks()`.
156
+ `PKPaymentNetwork` constants include `.visa`, `.masterCard`, `.amex`,
157
+ `.discover`, `.chinaUnionPay`, `.JCB`, `.maestro`, `.electron` and `.interac`.
158
+ `PKPaymentRequest.availableNetworks()` reports what the device supports at
159
+ run time.
188
160
 
189
- ## Presenting the Payment Sheet
161
+ ## Presenting the sheet and authorizing
190
162
 
191
- Use `PKPaymentAuthorizationController` (works in both SwiftUI and UIKit, no view controller needed). The controller's delegate is weak, so retain the controller for the life of the sheet.
163
+ `PKPaymentAuthorizationController` works from SwiftUI and UIKit alike and
164
+ needs no view controller. Because the delegate property is weak, store the
165
+ controller in a property until the sheet has gone. The SDK marks every
166
+ delegate callback as main-actor, so the methods below are plain members of
167
+ the `@MainActor` coordinator. Marking them `nonisolated` would force the
168
+ non-`Sendable` `reply` handlers and shipping methods across actors, which
169
+ Swift 6 rejects.
192
170
 
193
171
  ```swift
194
- final class CheckoutCoordinator: NSObject {
195
- private var paymentController: PKPaymentAuthorizationController?
196
-
197
- @MainActor
198
- func startPayment() {
199
- let controller = PKPaymentAuthorizationController(
200
- paymentRequest: createPaymentRequest()
201
- )
202
- paymentController = controller
203
- controller.delegate = self
204
- controller.present { [weak self] presented in
205
- if !presented {
206
- self?.paymentController = nil
207
- }
172
+ @MainActor
173
+ final class PaymentCoordinator: NSObject, PKPaymentAuthorizationControllerDelegate {
174
+ private var controller: PKPaymentAuthorizationController?
175
+ private var basket = Basket()
176
+
177
+ func pay() {
178
+ let sheet = PKPaymentAuthorizationController(paymentRequest: makeRequest(for: basket))
179
+ sheet.delegate = self
180
+ controller = sheet
181
+ Task {
182
+ if await !sheet.present() { controller = nil }
208
183
  }
209
184
  }
210
- }
211
- ```
212
-
213
- ## Handling Payment Authorization
214
-
215
- Implement `PKPaymentAuthorizationControllerDelegate` to process the payment token.
216
185
 
217
- ```swift
218
- extension CheckoutCoordinator: PKPaymentAuthorizationControllerDelegate {
219
186
  func paymentAuthorizationController(
220
- _ controller: PKPaymentAuthorizationController,
187
+ _ sheet: PKPaymentAuthorizationController,
221
188
  didAuthorizePayment payment: PKPayment,
222
- handler completion: @escaping (PKPaymentAuthorizationResult) -> Void
189
+ handler reply: @escaping (PKPaymentAuthorizationResult) -> Void
223
190
  ) {
224
- // Send payment.token.paymentData to your payment processor
191
+ let token = payment.token.paymentData
225
192
  Task {
226
- do {
227
- try await paymentService.process(payment.token)
228
- completion(PKPaymentAuthorizationResult(status: .success, errors: nil))
229
- } catch {
230
- completion(PKPaymentAuthorizationResult(status: .failure, errors: [error]))
231
- }
193
+ let failure = await OrderAPI.charge(token)
194
+ let status: PKPaymentAuthorizationStatus = failure == nil ? .success : .failure
195
+ reply(PKPaymentAuthorizationResult(status: status, errors: failure.map { [$0] }))
232
196
  }
233
197
  }
234
198
 
235
- func paymentAuthorizationControllerDidFinish(
236
- _ controller: PKPaymentAuthorizationController
237
- ) {
238
- controller.dismiss { [weak self] in
239
- self?.paymentController = nil
199
+ func paymentAuthorizationControllerDidFinish(_ sheet: PKPaymentAuthorizationController) {
200
+ sheet.dismiss { [weak self] in
201
+ Task { @MainActor in self?.controller = nil }
240
202
  }
241
203
  }
242
- }
243
- ```
244
-
245
- ### Handling Shipping Changes
246
204
 
247
- ```swift
248
- func paymentAuthorizationController(
249
- _ controller: PKPaymentAuthorizationController,
250
- didSelectShippingMethod shippingMethod: PKShippingMethod,
251
- handler completion: @escaping (PKPaymentRequestShippingMethodUpdate) -> Void
252
- ) {
253
- let updatedItems = recalculateItems(with: shippingMethod)
254
- let update = PKPaymentRequestShippingMethodUpdate(paymentSummaryItems: updatedItems)
255
- completion(update)
205
+ func paymentAuthorizationController(
206
+ _ sheet: PKPaymentAuthorizationController,
207
+ didSelectShippingMethod method: PKShippingMethod,
208
+ handler reply: @escaping (PKPaymentRequestShippingMethodUpdate) -> Void
209
+ ) {
210
+ basket.shipping = method
211
+ let items = makeRequest(for: basket).paymentSummaryItems
212
+ reply(PKPaymentRequestShippingMethodUpdate(paymentSummaryItems: items))
213
+ }
256
214
  }
257
215
  ```
258
216
 
259
- ## Wallet Passes
260
-
261
- ### Adding a Pass to Wallet
217
+ - The payment token goes to your server or processor as opaque data. Never
218
+ decode it in the app.
219
+ - Report declines and network failures through the result's status and
220
+ errors so the sheet can show them.
221
+ - Dismiss only in `paymentAuthorizationControllerDidFinish(_:)`. Dismissing
222
+ from `didAuthorizePayment` leaves a blank sheet.
223
+ - Every shipping-method change recalculates the summary items, total included.
262
224
 
263
- Load signed `.pkpass` data, verify the device can add passes, then present
264
- `PKAddPassesViewController` when you want the user to review the pass before
265
- adding it. `PKPass(data:)` expects signed pass data and can throw invalid-data
266
- or invalid-signature errors. Name `invalid-data` and `invalid-signature`
267
- failures explicitly instead of hiding them behind a bare `try?` in review
268
- guidance.
225
+ Recurring, deferred, coupon and multi-merchant requests, plus a full SwiftUI
226
+ checkout screen, are in the [Wallet and advanced payments reference](references/wallet-passes.md).
269
227
 
270
- ```swift
271
- func addPassToWallet(data: Data) {
272
- guard PKAddPassesViewController.canAddPasses() else {
273
- return
274
- }
275
-
276
- do {
277
- let pass = try PKPass(data: data)
278
- guard let addController = PKAddPassesViewController(pass: pass) else {
279
- return
280
- }
281
- addController.delegate = self
282
- present(addController, animated: true)
283
- } catch {
284
- // Signed pass data is invalid or the signature cannot be validated.
285
- showRecoverablePassError(error)
286
- }
287
- }
288
- ```
228
+ ## Wallet passes
289
229
 
290
- ### SwiftUI Wallet Button
230
+ ### Adding a pass
291
231
 
292
- Use `AddPassToWalletButton` as the SwiftUI equivalent to `PKAddPassButton`.
232
+ Passes arrive as signed `.pkpass` data, usually from your server.
233
+ `PKPass(data:)` throws when the data is not a valid pass or when its signature
234
+ does not verify. Name those two failures in your error handling and show the
235
+ user something recoverable; a bare `try?` hides both.
293
236
 
294
237
  ```swift
295
- import PassKit
296
- import SwiftUI
297
-
298
- struct AddPassButton: View {
299
- let passData: Data
300
- @State private var addedToWallet = false
301
-
302
- var body: some View {
303
- if PKAddPassesViewController.canAddPasses(),
304
- let pass = try? PKPass(data: passData) {
305
- AddPassToWalletButton([pass]) { added in
306
- addedToWallet = added
307
- }
308
- .addPassToWalletButtonStyle(.blackOutline)
309
- .frame(width: 250, height: 50)
238
+ @MainActor
239
+ func offerPass(_ data: Data, from presenter: UIViewController) throws {
240
+ guard PKAddPassesViewController.canAddPasses() else { throw WalletError.addingUnavailable }
241
+ let pass: PKPass
242
+ do {
243
+ pass = try PKPass(data: data)
244
+ } catch let error as PKPassKitError {
245
+ switch error.code {
246
+ case .invalidSignature: throw WalletError.badSignature
247
+ case .invalidDataError: throw WalletError.invalidPass
248
+ default: throw WalletError.unknown(error)
310
249
  }
311
250
  }
251
+ guard let sheet = PKAddPassesViewController(pass: pass) else { throw WalletError.invalidPass }
252
+ sheet.delegate = presenter as? PKAddPassesViewControllerDelegate
253
+ presenter.present(sheet, animated: true)
312
254
  }
313
255
  ```
314
256
 
315
- ## Checking Pass Library
316
-
317
- Use `PKPassLibrary` to inspect and manage passes the user already has. Check
318
- `PKPassLibrary.isPassLibraryAvailable()` before pass-library operations, but use
319
- `PKAddPassesViewController.canAddPasses()` to decide whether the device can add
320
- passes. `passes()` only returns passes your app can access through its
321
- entitlements. When replacing an existing pass, check the Boolean result from
322
- `replacePass(with:)` and handle failure. For signed pass bundle construction,
323
- update web services, and `replacePass(with:)`, read
324
- [references/wallet-passes.md](references/wallet-passes.md).
325
-
326
- ```swift
327
- let library = PKPassLibrary()
328
-
329
- // Check if a specific pass is already in Wallet
330
- let hasPass = library.containsPass(pass)
331
-
332
- // Retrieve passes your app can access
333
- let passes = library.passes()
334
-
335
- // Check if pass library is available
336
- guard PKPassLibrary.isPassLibraryAvailable() else { return }
337
- ```
338
-
339
- ## Common Mistakes
340
-
341
- ### DON'T: Use StoreKit for physical goods
342
-
343
- Apple Pay (PassKit) is for **physical goods, real-world services, donations, and
344
- eligible recurring payments**. StoreKit is for virtual goods, app features, and
345
- digital-content subscriptions. Using the wrong framework leads to App Review
346
- rejection.
257
+ `PKAddPassesViewController` shows the pass so the user can confirm it first.
347
258
 
348
- ```swift
349
- // WRONG: Using StoreKit to sell a physical product
350
- let product = try await Product.products(for: ["com.example.tshirt"])
351
-
352
- // CORRECT: Use Apple Pay for physical goods
353
- let request = PKPaymentRequest()
354
- request.paymentSummaryItems = [
355
- PKPaymentSummaryItem(label: "T-Shirt", amount: NSDecimalNumber(string: "29.99")),
356
- PKPaymentSummaryItem(label: "My Store", amount: NSDecimalNumber(string: "29.99"))
357
- ]
358
- ```
259
+ ### SwiftUI button
359
260
 
360
- ### DON'T: Hardcode merchant ID in multiple places
261
+ `AddPassToWalletButton` is the SwiftUI version of `PKAddPassButton`. Show it
262
+ only when `canAddPasses()` is true and the pass parsed:
361
263
 
362
264
  ```swift
363
- // WRONG: Merchant ID scattered across the codebase
364
- let request1 = PKPaymentRequest()
365
- request1.merchantIdentifier = "merchant.com.example.app"
366
- // ...elsewhere:
367
- let request2 = PKPaymentRequest()
368
- request2.merchantIdentifier = "merchant.com.example.app" // easy to get out of sync
369
-
370
- // CORRECT: Centralize configuration
371
- enum PaymentConfig {
372
- static let merchantIdentifier = "merchant.com.example.app"
373
- static let countryCode = "US"
374
- static let currencyCode = "USD"
375
- static let supportedNetworks: [PKPaymentNetwork] = [.visa, .masterCard, .amex]
265
+ if PKAddPassesViewController.canAddPasses(), let ticket = parsedTicket {
266
+ AddPassToWalletButton([ticket]) { added in
267
+ ticketSaved = added
268
+ }
269
+ .addPassToWalletButtonStyle(.blackOutline)
270
+ .frame(width: 260, height: 50)
376
271
  }
377
272
  ```
378
273
 
379
- ### DON'T: Forget the total line item
380
-
381
- The last item in `paymentSummaryItems` is the total row. If you only list line
382
- items, the payment sheet uses the final line item as the Pay line instead of
383
- your business name.
384
-
385
- ```swift
386
- // WRONG: No total item
387
- request.paymentSummaryItems = [
388
- PKPaymentSummaryItem(label: "Widget", amount: NSDecimalNumber(string: "9.99"))
389
- ]
390
-
391
- // CORRECT: Last item is the total with your merchant name
392
- request.paymentSummaryItems = [
393
- PKPaymentSummaryItem(label: "Widget", amount: NSDecimalNumber(string: "9.99")),
394
- PKPaymentSummaryItem(
395
- label: "My Store",
396
- amount: NSDecimalNumber(string: "9.99")
397
- ) // Total
398
- ]
399
- ```
400
-
401
- ### DON'T: Use binary floating-point values for money
402
-
403
- ```swift
404
- // WRONG: PassKit amounts are NSDecimalNumber values
405
- PKPaymentSummaryItem(label: "Widget", amount: 9.99)
406
-
407
- // CORRECT: Construct decimal amounts explicitly
408
- PKPaymentSummaryItem(label: "Widget", amount: NSDecimalNumber(string: "9.99"))
409
- ```
410
-
411
- ### DON'T: Skip the canMakePayments check
412
-
413
- ```swift
414
- // WRONG: Show Apple Pay button without checking
415
- PayWithApplePayButton(.buy) { startPayment() }
416
-
417
- // CORRECT: Only show when available
418
- if PKPaymentAuthorizationController.canMakePayments(
419
- usingNetworks: PaymentConfig.supportedNetworks
420
- ) {
421
- PayWithApplePayButton(.buy) { startPayment() }
422
- } else {
423
- // Show alternative checkout or setup button
424
- Button("Set Up Apple Pay") { /* guide user */ }
425
- }
426
- ```
274
+ `parsedTicket` is a `PKPass?` produced by the throwing parse above, which has
275
+ already reported any invalid-data or signature error.
427
276
 
428
- ### DON'T: Dismiss the controller before completing authorization
277
+ ### The pass library
429
278
 
430
- Keep the authorization controller retained while presented, because its delegate
431
- property is weak. Dismiss only after the sheet finishes.
279
+ `PKPassLibrary` looks at, and manages, passes the user already has.
432
280
 
433
281
  ```swift
434
- // WRONG: Dismissing inside didAuthorizePayment
435
- func paymentAuthorizationController(
436
- _ controller: PKPaymentAuthorizationController,
437
- didAuthorizePayment payment: PKPayment,
438
- handler completion: @escaping (PKPaymentAuthorizationResult) -> Void
439
- ) {
440
- controller.dismiss() // Too early -- causes blank sheet
441
- completion(.init(status: .success, errors: nil))
442
- }
443
-
444
- // CORRECT: Dismiss only in paymentAuthorizationControllerDidFinish
445
- func paymentAuthorizationControllerDidFinish(
446
- _ controller: PKPaymentAuthorizationController
447
- ) {
448
- controller.dismiss { [weak self] in
449
- self?.paymentController = nil
282
+ guard PKPassLibrary.isPassLibraryAvailable() else { return }
283
+ let library = PKPassLibrary()
284
+ if library.containsPass(updated) {
285
+ if !library.replacePass(with: updated) {
286
+ showRetryableWalletError()
450
287
  }
451
288
  }
452
289
  ```
453
290
 
454
- ## Review Checklist
455
-
456
- - [ ] Apple Pay capability enabled and merchant ID configured in Developer portal
457
- - [ ] Payment Processing Certificate generated and installed
458
- - [ ] `canMakePayments(usingNetworks:)` checked before showing Apple Pay button
459
- - [ ] Apple Pay is prominent wherever active-card availability is checked
460
- - [ ] Product choices, optional details, and complex shipping choices collected before payment sheet
461
- - [ ] Last item in `paymentSummaryItems` is the total with merchant display name
462
- - [ ] Payment summary and token-context amounts use `NSDecimalNumber`
463
- - [ ] Payment token sent to server for processing (never decoded client-side)
464
- - [ ] `PKPaymentAuthorizationController` retained while presented and cleared after finish
465
- - [ ] `paymentAuthorizationControllerDidFinish` dismisses the controller
466
- - [ ] Shipping method changes recalculate totals via delegate callback
467
- - [ ] StoreKit used for virtual goods/digital content; Apple Pay used for physical goods, services, donations, and eligible recurring payments
468
- - [ ] Wallet passes loaded from signed `.pkpass` bundles
469
- - [ ] `PKPass(data:)` invalid-data and invalid-signature failures surfaced
470
- - [ ] `PKPassLibrary.isPassLibraryAvailable()` used for pass operations, not add-pass capability
471
- - [ ] `PKAddPassesViewController.canAddPasses()` checked before add-pass UI
472
- - [ ] `PKPassLibrary.replacePass(with:)` Boolean result checked when replacing a pass
473
- - [ ] Apple Pay button uses system-provided `PKPaymentButton` or `PayWithApplePayButton`
474
- - [ ] Add-to-Wallet UI uses system-provided `PKAddPassButton`, `AddPassToWalletButton`, or `PKAddPassesViewController`
475
- - [ ] Error states handled in authorization result (network failures, declined cards)
291
+ - `isPassLibraryAvailable()` gates library operations. Whether a pass can be
292
+ added is a different question, answered by `canAddPasses()`. Do not use one
293
+ for the other.
294
+ - `passes()` returns only passes your entitlements give you access to.
295
+ - `replacePass(with:)` returns a `Bool`; handle `false`.
296
+
297
+ Pass bundle contents, the update web service and replacement flow are in the
298
+ [reference](references/wallet-passes.md).
299
+
300
+ ## Common mistakes
301
+
302
+ - **StoreKit for physical goods, or PassKit for digital ones.** Tangible
303
+ products, services delivered outside the app, donations and qualifying
304
+ recurring charges use Apple Pay. In-app currency, unlocked features and
305
+ subscriptions to digital content use StoreKit. Mixing them up gets the app rejected.
306
+ - **Merchant ID copied everywhere.** Keep it, with country, currency and
307
+ networks, in one configuration type.
308
+ - **No total line.** The Pay line then shows the last item rather than your
309
+ business name.
310
+ - **`Double` amounts.** `amount: 9.99` is binary floating point; construct
311
+ `NSDecimalNumber` explicitly.
312
+ - **Skipping `canMakePayments`.** Show the button only when it can work, and
313
+ otherwise offer another checkout or a "Set Up Apple Pay" button.
314
+ - **Dismissing too early.** Keep the controller retained and dismiss only in
315
+ `paymentAuthorizationControllerDidFinish(_:)`.
316
+
317
+ ## Review checklist
318
+
319
+ - [ ] Apple Pay capability and Merchant ID configured
320
+ - [ ] Payment Processing Certificate created and installed
321
+ - [ ] `canMakePayments(usingNetworks:capabilities:)` checked before the button shows
322
+ - [ ] Apple Pay is prominent wherever the active-card check is used
323
+ - [ ] Product choices, extra details and complex shipping collected before the sheet
324
+ - [ ] Last summary item is the total, labelled with the merchant name
325
+ - [ ] Summary and token-context amounts are `NSDecimalNumber`
326
+ - [ ] Payment token goes to the server and is never decoded on device
327
+ - [ ] Controller retained while presented and released after finish
328
+ - [ ] `paymentAuthorizationControllerDidFinish` dismisses the sheet
329
+ - [ ] Shipping-method changes recalculate the totals
330
+ - [ ] StoreKit and Apple Pay responsibilities kept apart
331
+ - [ ] Every pass is a signed `.pkpass` bundle
332
+ - [ ] The user hears about a pass that fails to parse, whether the data or the signature is bad
333
+ - [ ] `isPassLibraryAvailable()` used for library work, not for add capability
334
+ - [ ] `canAddPasses()` checked before any add-pass UI
335
+ - [ ] `replacePass(with:)` result checked
336
+ - [ ] System buttons only: `PKPaymentButton` or `PayWithApplePayButton`
337
+ - [ ] Adding to Wallet uses `PKAddPassButton`, `AddPassToWalletButton` or `PKAddPassesViewController`
338
+ - [ ] Authorization results carry errors for declines and network failures
476
339
 
477
340
  ## References
478
341
 
479
- - Extended patterns (recurring/deferred payments, coupon codes, multi-merchant, pass bundles, pass updates): [references/wallet-passes.md](references/wallet-passes.md)
480
- - [PassKit framework](https://sosumi.ai/documentation/passkit)
481
- - [PKPaymentRequest](https://sosumi.ai/documentation/passkit/pkpaymentrequest)
482
- - [PKPaymentAuthorizationController](https://sosumi.ai/documentation/passkit/pkpaymentauthorizationcontroller)
483
- - [PKPaymentButton](https://sosumi.ai/documentation/passkit/pkpaymentbutton)
484
- - [PayWithApplePayButton](https://sosumi.ai/documentation/passkit/paywithapplepaybutton)
485
- - [AddPassToWalletButton](https://sosumi.ai/documentation/passkit/addpasstowalletbutton)
486
- - [PKPass](https://sosumi.ai/documentation/passkit/pkpass)
487
- - [PKAddPassesViewController](https://sosumi.ai/documentation/passkit/pkaddpassesviewcontroller)
488
- - [PKPassLibrary](https://sosumi.ai/documentation/passkit/pkpasslibrary)
489
- - [PKPaymentNetwork](https://sosumi.ai/documentation/passkit/pkpaymentnetwork)
490
- - [Apple Pay HIG](https://sosumi.ai/design/human-interface-guidelines/apple-pay)
342
+ - [Wallet and advanced payments](references/wallet-passes.md): recurring,
343
+ coupon, multi-merchant and deferred requests; pass bundles; pass updates;
344
+ SwiftUI checkout
345
+ - Apple documentation:
346
+ [PassKit](https://developer.apple.com/documentation/passkit),
347
+ [payment request](https://developer.apple.com/documentation/passkit/pkpaymentrequest),
348
+ [authorization controller](https://developer.apple.com/documentation/passkit/pkpaymentauthorizationcontroller),
349
+ [UIKit pay button](https://developer.apple.com/documentation/passkit/pkpaymentbutton),
350
+ [SwiftUI pay button](https://developer.apple.com/documentation/passkit/paywithapplepaybutton),
351
+ [SwiftUI add-pass button](https://developer.apple.com/documentation/passkit/addpasstowalletbutton),
352
+ [pass](https://developer.apple.com/documentation/passkit/pkpass),
353
+ [add-passes controller](https://developer.apple.com/documentation/passkit/pkaddpassesviewcontroller),
354
+ [pass library](https://developer.apple.com/documentation/passkit/pkpasslibrary),
355
+ [payment networks](https://developer.apple.com/documentation/passkit/pkpaymentnetwork)
356
+ - [HIG page for Apple Pay](https://developer.apple.com/design/human-interface-guidelines/apple-pay)