@mmerterden/multi-agent-pipeline 20.6.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.
- package/CHANGELOG.md +27 -0
- package/LICENSE +0 -10
- package/docs/facts.json +1 -1
- package/manifest.json +328 -329
- package/package.json +2 -2
- package/pipeline/multi-agent-refs/features/design-conformance.md +62 -64
- package/pipeline/scripts/_notices.mjs +12 -1
- package/pipeline/scripts/gen-skills-index.mjs +1 -1
- package/pipeline/skills/.skill-manifest.json +106 -106
- package/pipeline/skills/shared/README.md +71 -71
- package/pipeline/skills/shared/external/agent-introspection-debugging/SKILL.md +1 -0
- package/pipeline/skills/shared/external/alarmkit/SKILL.md +373 -381
- package/pipeline/skills/shared/external/alarmkit/evals/evals.json +23 -18
- package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +328 -378
- package/pipeline/skills/shared/external/android-architecture/SKILL.md +2 -0
- package/pipeline/skills/shared/external/android-performance/SKILL.md +2 -0
- package/pipeline/skills/shared/external/android-security/SKILL.md +2 -0
- package/pipeline/skills/shared/external/app-clips/SKILL.md +260 -160
- package/pipeline/skills/shared/external/app-clips/evals/evals.json +27 -27
- package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +150 -83
- package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +135 -83
- package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +143 -85
- package/pipeline/skills/shared/external/app-intents/SKILL.md +302 -304
- package/pipeline/skills/shared/external/app-intents/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +594 -894
- package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +339 -277
- package/pipeline/skills/shared/external/app-store-optimization/evals/evals.json +27 -23
- package/pipeline/skills/shared/external/app-store-optimization/references/keyword-research-methodology.md +105 -122
- package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +143 -166
- package/pipeline/skills/shared/external/app-store-review/SKILL.md +307 -326
- package/pipeline/skills/shared/external/app-store-review/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/app-store-review/references/privacy-manifest.md +105 -67
- package/pipeline/skills/shared/external/app-store-review/references/review-checklists.md +114 -101
- package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +333 -360
- package/pipeline/skills/shared/external/apple-on-device-ai/evals/evals.json +24 -27
- package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-conversion.md +215 -322
- package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-optimization.md +161 -256
- package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models.md +277 -387
- package/pipeline/skills/shared/external/apple-on-device-ai/references/mlx-swift.md +196 -210
- package/pipeline/skills/shared/external/authentication/SKILL.md +265 -381
- package/pipeline/skills/shared/external/authentication/evals/evals.json +25 -25
- package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +133 -178
- package/pipeline/skills/shared/external/authentication/references/passkeys.md +111 -147
- package/pipeline/skills/shared/external/avkit/SKILL.md +267 -364
- package/pipeline/skills/shared/external/avkit/evals/evals.json +26 -26
- package/pipeline/skills/shared/external/avkit/references/avkit-patterns.md +375 -493
- package/pipeline/skills/shared/external/background-processing/SKILL.md +270 -382
- package/pipeline/skills/shared/external/background-processing/evals/evals.json +22 -22
- package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +169 -317
- package/pipeline/skills/shared/external/backlog/BACKLOG.md +1 -1
- package/pipeline/skills/shared/external/backlog/SKILL.md +56 -33
- package/pipeline/skills/shared/external/callkit-voip/SKILL.md +290 -371
- package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +175 -343
- package/pipeline/skills/shared/external/ci-cd-pipelines/SKILL.md +1 -0
- package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +292 -381
- package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +33 -30
- package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +227 -355
- package/pipeline/skills/shared/external/compose-components/SKILL.md +2 -0
- package/pipeline/skills/shared/external/compose-navigation/SKILL.md +3 -2
- package/pipeline/skills/shared/external/compose-testing/SKILL.md +2 -0
- package/pipeline/skills/shared/external/contacts-framework/SKILL.md +197 -346
- package/pipeline/skills/shared/external/contacts-framework/evals/evals.json +19 -21
- package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +169 -308
- package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +226 -376
- package/pipeline/skills/shared/external/core-bluetooth/evals/evals.json +25 -22
- package/pipeline/skills/shared/external/core-bluetooth/references/ble-patterns.md +257 -337
- package/pipeline/skills/shared/external/core-data/SKILL.md +292 -368
- package/pipeline/skills/shared/external/core-data/evals/evals.json +30 -27
- package/pipeline/skills/shared/external/core-motion/SKILL.md +235 -324
- package/pipeline/skills/shared/external/core-motion/evals/evals.json +31 -27
- package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +210 -310
- package/pipeline/skills/shared/external/core-nfc/SKILL.md +292 -366
- package/pipeline/skills/shared/external/core-nfc/evals/evals.json +22 -24
- package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +233 -329
- package/pipeline/skills/shared/external/coreml/SKILL.md +323 -367
- package/pipeline/skills/shared/external/coreml/evals/evals.json +24 -21
- package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +562 -565
- package/pipeline/skills/shared/external/council/SKILL.md +1 -0
- package/pipeline/skills/shared/external/cryptokit/SKILL.md +253 -394
- package/pipeline/skills/shared/external/cryptokit/evals/evals.json +20 -18
- package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +299 -488
- package/pipeline/skills/shared/external/css-modern/SKILL.md +1 -0
- package/pipeline/skills/shared/external/database-patterns/SKILL.md +1 -0
- package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +270 -323
- package/pipeline/skills/shared/external/debugging-instruments/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +167 -315
- package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +140 -193
- package/pipeline/skills/shared/external/device-integrity/SKILL.md +230 -353
- package/pipeline/skills/shared/external/device-integrity/evals/evals.json +25 -21
- package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +159 -197
- package/pipeline/skills/shared/external/energykit/SKILL.md +225 -392
- package/pipeline/skills/shared/external/energykit/evals/evals.json +29 -28
- package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +174 -470
- package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +261 -383
- package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +25 -22
- package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +165 -268
- package/pipeline/skills/shared/external/evidence-github/SKILL.md +2 -0
- package/pipeline/skills/shared/external/evidence-registry/SKILL.md +2 -0
- package/pipeline/skills/shared/external/gradle-kotlin-dsl/SKILL.md +2 -0
- package/pipeline/skills/shared/external/healthkit/SKILL.md +252 -303
- package/pipeline/skills/shared/external/healthkit/evals/evals.json +24 -23
- package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +369 -523
- package/pipeline/skills/shared/external/homekit-matter/SKILL.md +233 -348
- package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +27 -22
- package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +199 -305
- package/pipeline/skills/shared/external/html-semantic/SKILL.md +1 -0
- package/pipeline/skills/shared/external/humanizer/SKILL.md +1 -0
- package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +368 -340
- package/pipeline/skills/shared/external/ios-accessibility/evals/evals.json +28 -27
- package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +314 -260
- package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +97 -67
- package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +165 -101
- package/pipeline/skills/shared/external/ios-coding-standard/SKILL.md +1 -0
- package/pipeline/skills/shared/external/ios-localization/SKILL.md +258 -371
- package/pipeline/skills/shared/external/ios-localization/evals/evals.json +23 -23
- package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +283 -491
- package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +313 -440
- package/pipeline/skills/shared/external/ios-module-structure/SKILL.md +1 -0
- package/pipeline/skills/shared/external/ios-networking/SKILL.md +265 -341
- package/pipeline/skills/shared/external/ios-networking/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +425 -652
- package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +143 -285
- package/pipeline/skills/shared/external/ios-networking/references/lightweight-clients.md +93 -53
- package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +231 -456
- package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +517 -784
- package/pipeline/skills/shared/external/ios-security/SKILL.md +2 -0
- package/pipeline/skills/shared/external/ios-simulator/SKILL.md +265 -393
- package/pipeline/skills/shared/external/ios-simulator/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +177 -270
- package/pipeline/skills/shared/external/live-activities/SKILL.md +318 -360
- package/pipeline/skills/shared/external/live-activities/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/live-activities/references/activitykit-patterns.md +478 -710
- package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +91 -283
- package/pipeline/skills/shared/external/localization-reuse-map/reference/format-and-output.md +119 -151
- package/pipeline/skills/shared/external/localization-reuse-map/reference/publish-and-snapshot.md +60 -90
- package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +119 -156
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-artifact.py +726 -787
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-spreadsheet.py +253 -288
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-annotations.py +243 -304
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-legacy-labels.py +88 -104
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/publish-confluence.py +181 -235
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-key-shots.py +198 -263
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-overlay.py +461 -466
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-legacy-values.py +145 -151
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-new-values.py +123 -141
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/scan-screen-keys.py +146 -157
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/snapshot-resources.sh +22 -19
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/verify-map.py +156 -140
- package/pipeline/skills/shared/external/mapkit-location/SKILL.md +295 -267
- package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +28 -24
- package/pipeline/skills/shared/external/mapkit-location/references/mapkit-corelocation-patterns.md +378 -532
- package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +397 -499
- package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +165 -348
- package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +26 -23
- package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +123 -130
- package/pipeline/skills/shared/external/musickit-audio/SKILL.md +189 -315
- package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +22 -21
- package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +181 -270
- package/pipeline/skills/shared/external/natural-language/SKILL.md +188 -340
- package/pipeline/skills/shared/external/natural-language/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +171 -225
- package/pipeline/skills/shared/external/nextjs-app-router/SKILL.md +1 -0
- package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +258 -392
- package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +30 -29
- package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +164 -231
- package/pipeline/skills/shared/external/pdfkit/SKILL.md +312 -344
- package/pipeline/skills/shared/external/pdfkit/evals/evals.json +19 -19
- package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +413 -624
- package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +242 -358
- package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +25 -21
- package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +161 -226
- package/pipeline/skills/shared/external/permissionkit/SKILL.md +282 -400
- package/pipeline/skills/shared/external/permissionkit/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +237 -350
- package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +276 -325
- package/pipeline/skills/shared/external/photos-camera-media/references/av-playback.md +299 -545
- package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +344 -588
- package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +316 -660
- package/pipeline/skills/shared/external/photos-camera-media/references/photokit-patterns.md +270 -416
- package/pipeline/skills/shared/external/play-store-review/SKILL.md +2 -0
- package/pipeline/skills/shared/external/push-notifications/SKILL.md +312 -340
- package/pipeline/skills/shared/external/push-notifications/evals/evals.json +27 -26
- package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +328 -485
- package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +327 -560
- package/pipeline/skills/shared/external/python-patterns/SKILL.md +1 -0
- package/pipeline/skills/shared/external/react-best-practices/SKILL.md +1 -0
- package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +218 -410
- package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +24 -27
- package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +221 -348
- package/pipeline/skills/shared/external/rest-api-design/SKILL.md +1 -0
- package/pipeline/skills/shared/external/retrofit-networking/SKILL.md +2 -0
- package/pipeline/skills/shared/external/room-database/SKILL.md +2 -0
- package/pipeline/skills/shared/external/search-first/SKILL.md +1 -0
- package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +222 -393
- package/pipeline/skills/shared/external/shareplay-activities/evals/evals.json +23 -24
- package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +280 -420
- package/pipeline/skills/shared/external/signal-community/SKILL.md +2 -0
- package/pipeline/skills/shared/external/skill-creator/SKILL.md +80 -41
- package/pipeline/skills/shared/external/skill-creator/audit.md +63 -59
- package/pipeline/skills/shared/external/skill-creator/checklist.md +28 -20
- package/pipeline/skills/shared/external/skill-creator/examples.md +40 -40
- package/pipeline/skills/shared/external/skill-creator/label-check.md +48 -36
- package/pipeline/skills/shared/external/skill-creator/scripts/audit-panel.js +91 -100
- package/pipeline/skills/shared/external/skill-creator/template.md +51 -39
- package/pipeline/skills/shared/external/speech-recognition/SKILL.md +217 -421
- package/pipeline/skills/shared/external/speech-recognition/evals/evals.json +23 -26
- package/pipeline/skills/shared/external/speech-recognition/references/speechanalyzer-patterns.md +133 -125
- package/pipeline/skills/shared/external/storekit/SKILL.md +228 -204
- package/pipeline/skills/shared/external/storekit/evals/evals.json +27 -24
- package/pipeline/skills/shared/external/storekit/references/app-review-guidelines.md +98 -109
- package/pipeline/skills/shared/external/storekit/references/core-patterns.md +298 -242
- package/pipeline/skills/shared/external/storekit/references/storekit-advanced.md +356 -649
- package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +274 -399
- package/pipeline/skills/shared/external/swift-api-design-guidelines/evals/evals.json +22 -24
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/argument-labels-and-parameters.md +107 -108
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/conventions-and-special-rules.md +93 -165
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/naming-and-clarity.md +99 -137
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/side-effects-and-mutating-pairs.md +77 -120
- package/pipeline/skills/shared/external/swift-architecture/SKILL.md +334 -350
- package/pipeline/skills/shared/external/swift-architecture/evals/evals.json +22 -22
- package/pipeline/skills/shared/external/swift-charts/SKILL.md +208 -394
- package/pipeline/skills/shared/external/swift-charts/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/swift-charts/references/charts-patterns.md +351 -762
- package/pipeline/skills/shared/external/swift-codable/SKILL.md +339 -343
- package/pipeline/skills/shared/external/swift-codable/evals/evals.json +20 -20
- package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +303 -351
- package/pipeline/skills/shared/external/swift-concurrency/evals/evals.json +27 -24
- package/pipeline/skills/shared/external/swift-concurrency/references/approachable-concurrency.md +65 -80
- package/pipeline/skills/shared/external/swift-concurrency/references/async-algorithms.md +48 -84
- package/pipeline/skills/shared/external/swift-concurrency/references/bridging-interop.md +134 -79
- package/pipeline/skills/shared/external/swift-concurrency/references/concurrency-patterns.md +145 -167
- package/pipeline/skills/shared/external/swift-concurrency/references/diagnostics.md +62 -50
- package/pipeline/skills/shared/external/swift-concurrency/references/swiftui-concurrency.md +92 -121
- package/pipeline/skills/shared/external/swift-concurrency/references/synchronization-primitives.md +177 -241
- package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +258 -234
- package/pipeline/skills/shared/external/swift-language/SKILL.md +342 -382
- package/pipeline/skills/shared/external/swift-language/evals/evals.json +24 -27
- package/pipeline/skills/shared/external/swift-language/references/swift-attributes-interop.md +79 -56
- package/pipeline/skills/shared/external/swift-language/references/swift-patterns-extended.md +297 -340
- package/pipeline/skills/shared/external/swift-security/SKILL.md +180 -161
- package/pipeline/skills/shared/external/swift-security/evals/evals.json +25 -25
- package/pipeline/skills/shared/external/swift-security/references/biometric-authentication.md +314 -469
- package/pipeline/skills/shared/external/swift-security/references/certificate-trust.md +408 -476
- package/pipeline/skills/shared/external/swift-security/references/common-anti-patterns.md +260 -530
- package/pipeline/skills/shared/external/swift-security/references/compliance-owasp-mapping.md +270 -477
- package/pipeline/skills/shared/external/swift-security/references/credential-storage-patterns.md +573 -571
- package/pipeline/skills/shared/external/swift-security/references/cryptokit-public-key.md +370 -441
- package/pipeline/skills/shared/external/swift-security/references/cryptokit-symmetric.md +332 -433
- package/pipeline/skills/shared/external/swift-security/references/keychain-access-control.md +346 -468
- package/pipeline/skills/shared/external/swift-security/references/keychain-fundamentals.md +352 -472
- package/pipeline/skills/shared/external/swift-security/references/keychain-item-classes.md +431 -432
- package/pipeline/skills/shared/external/swift-security/references/keychain-sharing.md +328 -425
- package/pipeline/skills/shared/external/swift-security/references/migration-legacy-stores.md +341 -579
- package/pipeline/skills/shared/external/swift-security/references/secure-enclave.md +396 -457
- package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +354 -614
- package/pipeline/skills/shared/external/swift-testing/SKILL.md +188 -175
- package/pipeline/skills/shared/external/swift-testing/evals/evals.json +26 -24
- package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +80 -84
- package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +317 -433
- package/pipeline/skills/shared/external/swiftdata/SKILL.md +392 -256
- package/pipeline/skills/shared/external/swiftdata/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/swiftdata/references/core-data-coexistence.md +206 -402
- package/pipeline/skills/shared/external/swiftdata/references/indexing.md +59 -52
- package/pipeline/skills/shared/external/swiftdata/references/predicate-pitfalls.md +57 -33
- package/pipeline/skills/shared/external/swiftdata/references/swiftdata-advanced.md +354 -747
- package/pipeline/skills/shared/external/swiftdata/references/swiftdata-queries.md +300 -508
- package/pipeline/skills/shared/external/swiftlint/SKILL.md +175 -226
- package/pipeline/skills/shared/external/swiftlint/references/adoption-and-configuration.md +141 -208
- package/pipeline/skills/shared/external/swiftlint/references/custom-rules-and-analyze.md +100 -109
- package/pipeline/skills/shared/external/swiftlint/references/plugins-run-scripts-and-integrations.md +159 -179
- package/pipeline/skills/shared/external/swiftlint/references/rule-reference.md +383 -18
- package/pipeline/skills/shared/external/swiftlint/references/rules-suppressions-and-baselines.md +143 -229
- package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +283 -366
- package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +396 -608
- package/pipeline/skills/shared/external/swiftui-animation/references/core-animation-bridge.md +336 -385
- package/pipeline/skills/shared/external/swiftui-gestures/SKILL.md +239 -349
- package/pipeline/skills/shared/external/swiftui-gestures/references/gesture-patterns.md +228 -310
- package/pipeline/skills/shared/external/swiftui-layout-components/SKILL.md +260 -249
- package/pipeline/skills/shared/external/swiftui-layout-components/references/form.md +92 -74
- package/pipeline/skills/shared/external/swiftui-layout-components/references/grids.md +112 -177
- package/pipeline/skills/shared/external/swiftui-layout-components/references/list.md +61 -64
- package/pipeline/skills/shared/external/swiftui-layout-components/references/scrollview.md +94 -134
- package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +193 -225
- package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +173 -327
- package/pipeline/skills/shared/external/swiftui-navigation/SKILL.md +193 -168
- package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +127 -150
- package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +132 -133
- package/pipeline/skills/shared/external/swiftui-navigation/references/sheets.md +152 -117
- package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +106 -140
- package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +316 -252
- package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +341 -332
- package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +547 -854
- package/pipeline/skills/shared/external/swiftui-patterns/references/design-polish.md +485 -537
- package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +417 -499
- package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +213 -376
- package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +86 -175
- package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +89 -195
- package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +95 -182
- package/pipeline/skills/shared/external/swiftui-performance/references/understanding-improving-swiftui-performance.md +71 -149
- package/pipeline/skills/shared/external/swiftui-performance/references/wwdc-session-sources.md +21 -27
- package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +303 -295
- package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +204 -387
- package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +469 -683
- package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +140 -186
- package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md +75 -86
- package/pipeline/skills/shared/external/swiftui-webkit/references/local-content-and-custom-schemes.md +63 -60
- package/pipeline/skills/shared/external/swiftui-webkit/references/migration-and-fallbacks.md +69 -137
- package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md +95 -67
- package/pipeline/skills/shared/external/tailwind-css/SKILL.md +1 -0
- package/pipeline/skills/shared/external/testing-backend/SKILL.md +1 -0
- package/pipeline/skills/shared/external/tipkit/SKILL.md +220 -335
- package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +356 -494
- package/pipeline/skills/shared/external/typescript-patterns/SKILL.md +1 -0
- package/pipeline/skills/shared/external/vision-framework/SKILL.md +260 -375
- package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +393 -515
- package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +363 -539
- package/pipeline/skills/shared/external/vue-composition/SKILL.md +1 -0
- package/pipeline/skills/shared/external/weatherkit/SKILL.md +152 -310
- package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +288 -407
- package/pipeline/skills/shared/external/web-accessibility/SKILL.md +1 -0
- package/pipeline/skills/shared/external/web-performance/SKILL.md +1 -0
- package/pipeline/skills/shared/external/web-testing/SKILL.md +1 -0
- package/pipeline/skills/shared/external/widgetkit/SKILL.md +216 -288
- package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +414 -719
- package/pipeline/skills/shared/external/NOTICE-swift-ios-skills.md +0 -39
|
@@ -3,45 +3,45 @@
|
|
|
3
3
|
"evals": [
|
|
4
4
|
{
|
|
5
5
|
"id": 0,
|
|
6
|
-
"name": "passkey-
|
|
7
|
-
"prompt": "
|
|
8
|
-
"expected_output": "
|
|
6
|
+
"name": "passkey-enrollment-and-login",
|
|
7
|
+
"prompt": "Our recipe app wants passwordless accounts on iOS 26. Show how to add passkey enrollment and passkey login, including suggestions in the username field, and mention hardware keys for staff accounts.",
|
|
8
|
+
"expected_output": "Configures Associated Domains with a webcredentials entry and association file, uses ASAuthorizationPlatformPublicKeyCredentialProvider with separate registration and assertion requests built from server challenges, sends results to the server for verification before creating a session, sets textContentType .username and calls performAutoFillAssistedRequests, and uses the security-key provider only as a separate path for physical keys.",
|
|
9
9
|
"files": [],
|
|
10
10
|
"expectations": [
|
|
11
|
-
"
|
|
12
|
-
"Uses
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
11
|
+
"Requires a webcredentials entry under Associated Domains",
|
|
12
|
+
"Uses the platform provider with distinct registration and assertion requests",
|
|
13
|
+
"Takes challenges from the server and verifies results server-side before issuing a session",
|
|
14
|
+
"Uses performAutoFillAssistedRequests with a .username field for inline suggestions",
|
|
15
|
+
"Treats the security-key provider as a separate branch for physical keys only"
|
|
16
16
|
]
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
19
|
"id": 1,
|
|
20
|
-
"name": "
|
|
21
|
-
"prompt": "Review
|
|
22
|
-
"expected_output": "
|
|
20
|
+
"name": "apple-and-github-login-review",
|
|
21
|
+
"prompt": "Review our login code: Sign in with Apple reads credential.email! on every sign-in, we never check whether the Apple ID is still linked, the identity token is decoded in the app to get the user, GitHub login runs inside a WKWebView, the session token is in UserDefaults, and Face ID success unlocks the stored token.",
|
|
22
|
+
"expected_output": "Flags the missing capability or presentation provider if absent, caches email and name only on first authorization without force unwraps, adds getCredentialState at launch plus credentialRevokedNotification, moves identity token and authorization code validation to the server, switches GitHub to ASWebAuthenticationSession with a real presentation anchor, stores tokens in the Keychain, and treats LAContext as local re-authentication rather than a secret release.",
|
|
23
23
|
"files": [],
|
|
24
24
|
"expectations": [
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
25
|
+
"Notes that email and fullName arrive only on the first authorization and must be cached then",
|
|
26
|
+
"Adds getCredentialState at launch and observes credentialRevokedNotification",
|
|
27
|
+
"Validates the identity token and authorization code on the server",
|
|
28
|
+
"Replaces WKWebView with ASWebAuthenticationSession and a real presentation anchor",
|
|
29
|
+
"Moves tokens to the Keychain",
|
|
30
|
+
"States that LAContext success alone must not release stored secrets"
|
|
31
31
|
]
|
|
32
32
|
},
|
|
33
33
|
{
|
|
34
34
|
"id": 2,
|
|
35
|
-
"name": "
|
|
36
|
-
"prompt": "
|
|
37
|
-
"expected_output": "
|
|
35
|
+
"name": "auth-scope-routing",
|
|
36
|
+
"prompt": "While adding Sign in with Apple, can you also design our Keychain migration, pick SecAccessControl flags, add certificate pinning, and map us against OWASP MASVS? Also write our WebAuthn relying-party server.",
|
|
37
|
+
"expected_output": "Keeps the sign-in flow in scope, routes Keychain migration, access-control policy, CryptoKit, Secure Enclave, pinning and MASVS to the swift-security skill, restates the minimum rule that tokens go in the Keychain and evaluatePolicy does not release secrets, and does not claim to own the backend WebAuthn relying-party implementation beyond server challenges and verification.",
|
|
38
38
|
"files": [],
|
|
39
39
|
"expectations": [
|
|
40
|
-
"
|
|
41
|
-
"Routes
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"Does not
|
|
40
|
+
"Implements or discusses the Sign in with Apple flow itself",
|
|
41
|
+
"Routes Keychain architecture, access-control flags, pinning and MASVS to swift-security",
|
|
42
|
+
"Keeps the rule that tokens belong in the Keychain",
|
|
43
|
+
"Says evaluatePolicy alone does not release protected secrets",
|
|
44
|
+
"Does not present itself as the owner of a backend WebAuthn relying-party implementation"
|
|
45
45
|
]
|
|
46
46
|
}
|
|
47
47
|
]
|
|
@@ -1,238 +1,193 @@
|
|
|
1
|
-
# Keychain
|
|
1
|
+
# Keychain and Biometrics
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
The minimum storage and biometric patterns that sign-in code needs. This is a
|
|
4
|
+
quick reference, not a security architecture: Keychain migration,
|
|
5
|
+
access-control policy design, CryptoKit, Secure Enclave, pinning, sharing
|
|
6
|
+
items across apps, hardening and MASVS/MASTG mapping belong to `swift-security`.
|
|
7
|
+
Back to the [skill overview](../SKILL.md).
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
architecture guide. Route Keychain migration, access-control policy design,
|
|
10
|
-
CryptoKit encryption, Secure Enclave keys, certificate pinning, keychain
|
|
11
|
-
sharing, storage-hardening strategy, and OWASP MASVS/MASTG mapping to
|
|
12
|
-
`swift-security`.
|
|
9
|
+
## Where secrets go
|
|
13
10
|
|
|
14
|
-
|
|
11
|
+
Session tokens, refresh tokens, passwords and API keys belong in the Keychain.
|
|
12
|
+
`UserDefaults`, loose files and Core Data are all wrong for them.
|
|
15
13
|
|
|
16
|
-
|
|
17
|
-
- [Reading Tokens from Keychain](#reading-tokens-from-keychain)
|
|
18
|
-
- [Deleting Tokens from Keychain](#deleting-tokens-from-keychain)
|
|
19
|
-
- [Biometric Authentication with LAContext](#biometric-authentication-with-lacontext)
|
|
20
|
-
- [Biometric-Protected Keychain Items](#biometric-protected-keychain-items)
|
|
21
|
-
- [Keychain Error Handling](#keychain-error-handling)
|
|
22
|
-
- [References](#references)
|
|
14
|
+
## A small token vault
|
|
23
15
|
|
|
24
|
-
|
|
16
|
+
```swift
|
|
17
|
+
import Foundation
|
|
18
|
+
import Security
|
|
25
19
|
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
struct TokenVault {
|
|
21
|
+
let service: String
|
|
28
22
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
kSecAttrService as String: service,
|
|
35
|
-
kSecValueData as String: data,
|
|
36
|
-
kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
|
|
37
|
-
]
|
|
23
|
+
private func query(_ account: String) -> [String: Any] {
|
|
24
|
+
[kSecClass as String: kSecClassGenericPassword,
|
|
25
|
+
kSecAttrService as String: service,
|
|
26
|
+
kSecAttrAccount as String: account]
|
|
27
|
+
}
|
|
38
28
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
throw
|
|
29
|
+
func store(_ secret: Data, account: String) throws {
|
|
30
|
+
var insert = query(account)
|
|
31
|
+
insert[kSecValueData as String] = secret
|
|
32
|
+
insert[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
|
|
33
|
+
|
|
34
|
+
switch SecItemAdd(insert as CFDictionary, nil) {
|
|
35
|
+
case errSecSuccess:
|
|
36
|
+
return
|
|
37
|
+
case errSecDuplicateItem:
|
|
38
|
+
let changes = [kSecValueData as String: secret] as CFDictionary
|
|
39
|
+
let status = SecItemUpdate(query(account) as CFDictionary, changes)
|
|
40
|
+
if status != errSecSuccess { throw VaultError.updateFailed(status) }
|
|
41
|
+
case let status:
|
|
42
|
+
throw VaultError.saveFailed(status)
|
|
51
43
|
}
|
|
52
|
-
} else if status != errSecSuccess {
|
|
53
|
-
throw KeychainError.saveFailed(status)
|
|
54
44
|
}
|
|
55
|
-
}
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
## Reading Tokens from Keychain
|
|
59
45
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
var result: AnyObject?
|
|
71
|
-
let status = SecItemCopyMatching(query as CFDictionary, &result)
|
|
72
|
-
|
|
73
|
-
guard status == errSecSuccess, let data = result as? Data else {
|
|
74
|
-
throw KeychainError.readFailed(status)
|
|
46
|
+
func fetch(account: String) throws -> Data {
|
|
47
|
+
var lookup = query(account)
|
|
48
|
+
lookup[kSecReturnData as String] = kCFBooleanTrue
|
|
49
|
+
lookup[kSecMatchLimit as String] = kSecMatchLimitOne
|
|
50
|
+
var item: AnyObject?
|
|
51
|
+
let status = SecItemCopyMatching(lookup as CFDictionary, &item)
|
|
52
|
+
guard status == errSecSuccess else { throw VaultError.readFailed(status) }
|
|
53
|
+
guard let secret = item as? Data else { throw VaultError.readFailed(errSecDecode) }
|
|
54
|
+
return secret
|
|
75
55
|
}
|
|
76
|
-
return data
|
|
77
|
-
}
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
## Deleting Tokens from Keychain
|
|
81
56
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
]
|
|
89
|
-
|
|
90
|
-
let status = SecItemDelete(query as CFDictionary)
|
|
91
|
-
guard status == errSecSuccess || status == errSecItemNotFound else {
|
|
92
|
-
throw KeychainError.deleteFailed(status)
|
|
57
|
+
func remove(account: String) throws {
|
|
58
|
+
let status = SecItemDelete(query(account) as CFDictionary)
|
|
59
|
+
// A missing item already counts as removed.
|
|
60
|
+
if status != errSecSuccess && status != errSecItemNotFound {
|
|
61
|
+
throw VaultError.deleteFailed(status)
|
|
62
|
+
}
|
|
93
63
|
}
|
|
94
64
|
}
|
|
95
65
|
```
|
|
96
66
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
67
|
+
Every operation goes through the same `query(_:)`, so add, update, read and
|
|
68
|
+
delete always match the same item.
|
|
69
|
+
|
|
70
|
+
### Accessibility
|
|
101
71
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
72
|
+
Pick a `ThisDeviceOnly` class for sensitive credentials unless backup restore
|
|
73
|
+
or sharing is an explicit requirement; anything broader is a `swift-security`
|
|
74
|
+
decision. Do not use `kSecAttrAccessibleAlways`. Apple lists it as not
|
|
75
|
+
recommended because the item stays readable whatever the lock state.
|
|
105
76
|
|
|
77
|
+
## Biometrics with `LAContext`
|
|
106
78
|
|
|
107
|
-
|
|
79
|
+
An `LAContext` prompt is a local gate for the interface. It does not prove that
|
|
80
|
+
a secret may be released. For high-value secrets, attach access control to the
|
|
81
|
+
Keychain item and let `SecItemCopyMatching` run the authentication.
|
|
108
82
|
|
|
109
|
-
|
|
110
|
-
showing sensitive screens or performing protected actions. This is a local
|
|
111
|
-
interaction gate, not proof that a stored secret is safe to release. For tokens,
|
|
112
|
-
private keys, or high-value credentials, bind access to the Keychain item with
|
|
113
|
-
`SecAccessControl` and let `SecItemCopyMatching` perform the authentication.
|
|
83
|
+
Falling back to the device passcode when biometrics are not available:
|
|
114
84
|
|
|
115
85
|
```swift
|
|
116
86
|
import LocalAuthentication
|
|
117
87
|
|
|
118
|
-
func
|
|
88
|
+
func unlockSettings(reason: String) async throws -> Bool {
|
|
119
89
|
let context = LAContext()
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
return try await context.evaluatePolicy(
|
|
128
|
-
.deviceOwnerAuthentication,
|
|
129
|
-
localizedReason: "Authenticate to access your account"
|
|
130
|
-
)
|
|
90
|
+
let policy: LAPolicy
|
|
91
|
+
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) {
|
|
92
|
+
policy = .deviceOwnerAuthenticationWithBiometrics
|
|
93
|
+
} else {
|
|
94
|
+
var passcodeProblem: NSError?
|
|
95
|
+
guard context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &passcodeProblem) else {
|
|
96
|
+
throw passcodeProblem ?? LAError(.passcodeNotSet)
|
|
131
97
|
}
|
|
132
|
-
|
|
98
|
+
policy = .deviceOwnerAuthentication // biometrics or passcode
|
|
133
99
|
}
|
|
134
|
-
|
|
135
|
-
return try await context.evaluatePolicy(
|
|
136
|
-
.deviceOwnerAuthenticationWithBiometrics,
|
|
137
|
-
localizedReason: "Authenticate to access your account"
|
|
138
|
-
)
|
|
100
|
+
return try await context.evaluatePolicy(policy, localizedReason: reason)
|
|
139
101
|
}
|
|
140
102
|
```
|
|
141
103
|
|
|
142
|
-
### Info.plist
|
|
143
|
-
|
|
144
|
-
You MUST include `NSFaceIDUsageDescription` in Info.plist:
|
|
104
|
+
### Info.plist
|
|
145
105
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
<string>Authenticate to access your secure data</string>
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
Missing this key causes a crash on Face ID devices.
|
|
106
|
+
Add `NSFaceIDUsageDescription` with a sentence explaining why the app uses
|
|
107
|
+
Face ID. Face ID devices crash the app if it is missing.
|
|
152
108
|
|
|
153
|
-
###
|
|
109
|
+
### Tuning the context
|
|
154
110
|
|
|
155
111
|
```swift
|
|
156
112
|
let context = LAContext()
|
|
157
|
-
context.localizedFallbackTitle = "
|
|
158
|
-
context.touchIDAuthenticationAllowableReuseDuration =
|
|
159
|
-
let
|
|
113
|
+
context.localizedFallbackTitle = "Enter Passcode"
|
|
114
|
+
context.touchIDAuthenticationAllowableReuseDuration = 60 // seconds
|
|
115
|
+
let enrollmentHash = context.domainState.biometry.stateHash // store it; a different value later means enrollment changed
|
|
160
116
|
```
|
|
161
117
|
|
|
162
|
-
|
|
118
|
+
`evaluatedPolicyDomainState` served the same purpose but is deprecated since
|
|
119
|
+
iOS 18 in favor of `domainState.biometry.stateHash`.
|
|
163
120
|
|
|
164
|
-
|
|
121
|
+
## Items that require biometrics to read
|
|
165
122
|
|
|
166
123
|
```swift
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
124
|
+
func sealBehindBiometrics(_ payload: Data, in item: (service: String, account: String)) throws {
|
|
125
|
+
guard let control = SecAccessControlCreateWithFlags(
|
|
126
|
+
nil,
|
|
127
|
+
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
|
|
128
|
+
.biometryCurrentSet,
|
|
129
|
+
nil
|
|
130
|
+
) else { throw VaultError.saveFailed(errSecParam) }
|
|
131
|
+
|
|
132
|
+
let attributes: [String: Any] = [
|
|
133
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
134
|
+
kSecAttrService as String: item.service,
|
|
135
|
+
kSecAttrAccount as String: item.account,
|
|
136
|
+
kSecValueData as String: payload,
|
|
137
|
+
kSecAttrAccessControl as String: control,
|
|
138
|
+
]
|
|
139
|
+
let added = SecItemAdd(attributes as CFDictionary, nil)
|
|
140
|
+
if added != errSecSuccess { throw VaultError.saveFailed(added) }
|
|
141
|
+
}
|
|
184
142
|
|
|
185
|
-
|
|
186
|
-
let context = LAContext()
|
|
187
|
-
context.localizedReason = "
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
guard status == errSecSuccess, let tokenData = result as? Data else {
|
|
200
|
-
throw KeychainError.readFailed(status)
|
|
143
|
+
func openBiometricItem(_ item: (service: String, account: String)) throws -> Data { // prompts via Keychain
|
|
144
|
+
let context = LAContext()
|
|
145
|
+
context.localizedReason = "Unlock your saved card"
|
|
146
|
+
let lookup: [String: Any] = [
|
|
147
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
148
|
+
kSecAttrService as String: item.service,
|
|
149
|
+
kSecAttrAccount as String: item.account,
|
|
150
|
+
kSecReturnData as String: true,
|
|
151
|
+
kSecUseAuthenticationContext as String: context,
|
|
152
|
+
]
|
|
153
|
+
var item: AnyObject?
|
|
154
|
+
let status = SecItemCopyMatching(lookup as CFDictionary, &item)
|
|
155
|
+
guard status == errSecSuccess, let data = item as? Data else { throw VaultError.readFailed(status) }
|
|
156
|
+
return data
|
|
201
157
|
}
|
|
202
158
|
```
|
|
203
159
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
160
|
+
Here the Keychain decides whether the data is released. `.biometryCurrentSet`
|
|
161
|
+
makes the item unreadable once enrolled fingers or faces change; choosing
|
|
162
|
+
between that and other flags is a `swift-security` question.
|
|
208
163
|
|
|
209
|
-
##
|
|
164
|
+
## Errors
|
|
210
165
|
|
|
211
166
|
```swift
|
|
212
|
-
enum
|
|
167
|
+
enum VaultError: Error, CustomStringConvertible {
|
|
213
168
|
case saveFailed(OSStatus)
|
|
214
169
|
case updateFailed(OSStatus)
|
|
215
170
|
case readFailed(OSStatus)
|
|
216
171
|
case deleteFailed(OSStatus)
|
|
217
172
|
|
|
218
|
-
var
|
|
173
|
+
var description: String {
|
|
174
|
+
let status: OSStatus
|
|
219
175
|
switch self {
|
|
220
|
-
case .saveFailed(let
|
|
221
|
-
|
|
222
|
-
.readFailed(let status),
|
|
223
|
-
.deleteFailed(let status):
|
|
224
|
-
return SecCopyErrorMessageString(status, nil) as String? ?? "Unknown error"
|
|
176
|
+
case .saveFailed(let s), .updateFailed(let s), .readFailed(let s), .deleteFailed(let s):
|
|
177
|
+
status = s
|
|
225
178
|
}
|
|
179
|
+
let message = SecCopyErrorMessageString(status, nil).map { $0 as String }
|
|
180
|
+
return message ?? "OSStatus \(status)"
|
|
226
181
|
}
|
|
227
182
|
}
|
|
228
183
|
```
|
|
229
184
|
|
|
230
|
-
##
|
|
185
|
+
## Apple documentation
|
|
231
186
|
|
|
232
|
-
- [
|
|
233
|
-
- [
|
|
234
|
-
|
|
235
|
-
- [
|
|
236
|
-
-
|
|
237
|
-
-
|
|
238
|
-
-
|
|
187
|
+
- [LAContext](https://developer.apple.com/documentation/localauthentication/lacontext)
|
|
188
|
+
- [biometryCurrentSet](https://developer.apple.com/documentation/security/secaccesscontrolcreateflags/biometrycurrentset)
|
|
189
|
+
and [userPresence](https://developer.apple.com/documentation/security/secaccesscontrolcreateflags/userpresence) access-control flags
|
|
190
|
+
- [kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly](https://developer.apple.com/documentation/security/ksecattraccessiblewhenpasscodesetthisdeviceonly)
|
|
191
|
+
- Security framework article on limiting when keychain items are accessible
|
|
192
|
+
- LocalAuthentication article on reading keychain items behind Face ID or Touch ID
|
|
193
|
+
- The `NSFaceIDUsageDescription` Info.plist key reference
|