@mmerterden/multi-agent-pipeline 20.7.0 → 20.8.1

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