@mmerterden/multi-agent-pipeline 8.6.1 → 10.0.6

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 (928) hide show
  1. package/CHANGELOG.md +544 -2484
  2. package/README.md +117 -138
  3. package/docs/features.md +1 -1
  4. package/index.js +8 -10
  5. package/install/_adapters.mjs +5 -1
  6. package/install/_common.mjs +63 -0
  7. package/install/claude.mjs +14 -14
  8. package/install/copilot.mjs +14 -8
  9. package/install/index.mjs +85 -19
  10. package/install/templates/claude-hooks.json +18 -0
  11. package/install/templates/copilot-instructions.md +3 -3
  12. package/package.json +21 -6
  13. package/pipeline/adapters/_base.mjs +366 -14
  14. package/pipeline/adapters/antigravity.mjs +140 -0
  15. package/pipeline/adapters/codex.mjs +159 -0
  16. package/pipeline/adapters/copilot-chat-orchestration.mjs +148 -0
  17. package/pipeline/adapters/copilot-chat.mjs +34 -68
  18. package/pipeline/adapters/cursor-orchestration.mjs +152 -0
  19. package/pipeline/adapters/cursor.mjs +49 -90
  20. package/pipeline/agents/android-architect.md +5 -5
  21. package/pipeline/agents/backend-architect.md +4 -4
  22. package/pipeline/agents/code-reviewer.md +10 -10
  23. package/pipeline/agents/dev-critic.md +17 -17
  24. package/pipeline/agents/explorer.md +3 -3
  25. package/pipeline/agents/ios-architect.md +4 -4
  26. package/pipeline/agents/security-auditor.md +12 -12
  27. package/pipeline/agents/task-clarifier.md +18 -18
  28. package/pipeline/claude-md-template.md +3 -3
  29. package/pipeline/commands/archive-guard.md +3 -3
  30. package/pipeline/commands/figma-to-swiftui.md +10 -10
  31. package/pipeline/commands/multi-agent/_account-picker.md +13 -9
  32. package/pipeline/commands/multi-agent/_dev-context.md +15 -15
  33. package/pipeline/commands/multi-agent/_input-parser.md +4 -4
  34. package/pipeline/commands/multi-agent/_repo-picker.md +9 -9
  35. package/pipeline/commands/multi-agent/analysis-resolve.md +129 -0
  36. package/pipeline/commands/multi-agent/analysis.md +667 -0
  37. package/pipeline/commands/multi-agent/autopilot.md +22 -22
  38. package/pipeline/commands/multi-agent/build-optimize.md +77 -0
  39. package/pipeline/commands/multi-agent/channels.md +96 -96
  40. package/pipeline/commands/multi-agent/delete.md +19 -17
  41. package/pipeline/commands/multi-agent/dev-autopilot.md +23 -23
  42. package/pipeline/commands/multi-agent/dev-local-autopilot.md +23 -23
  43. package/pipeline/commands/multi-agent/dev-local.md +25 -22
  44. package/pipeline/commands/multi-agent/dev.md +49 -49
  45. package/pipeline/commands/multi-agent/diff-explain.md +4 -4
  46. package/pipeline/commands/multi-agent/garbage-collect.md +58 -0
  47. package/pipeline/commands/multi-agent/help.md +75 -66
  48. package/pipeline/commands/multi-agent/issue.md +3 -3
  49. package/pipeline/commands/multi-agent/jira.md +12 -12
  50. package/pipeline/commands/multi-agent/kill.md +6 -6
  51. package/pipeline/commands/multi-agent/language.md +12 -12
  52. package/pipeline/commands/multi-agent/local-autopilot.md +34 -34
  53. package/pipeline/commands/multi-agent/local.md +24 -25
  54. package/pipeline/commands/multi-agent/log.md +6 -6
  55. package/pipeline/commands/multi-agent/manual-test.md +3 -3
  56. package/pipeline/commands/multi-agent/prune-logs.md +60 -0
  57. package/pipeline/commands/multi-agent/purge.md +10 -7
  58. package/pipeline/commands/multi-agent/refactor.md +9 -9
  59. package/pipeline/commands/multi-agent/refs/analysis-template.md +1062 -0
  60. package/pipeline/commands/multi-agent/refs/android-guide.md +15 -13
  61. package/pipeline/commands/multi-agent/refs/audit-guide.md +20 -20
  62. package/pipeline/commands/multi-agent/refs/backend-guide.md +9 -9
  63. package/pipeline/commands/multi-agent/refs/channels/confluence.md +17 -17
  64. package/pipeline/commands/multi-agent/refs/channels/issue-comment.md +30 -30
  65. package/pipeline/commands/multi-agent/refs/channels/jira.md +15 -15
  66. package/pipeline/commands/multi-agent/refs/channels/pr-review-actions.md +19 -17
  67. package/pipeline/commands/multi-agent/refs/channels/pr.md +22 -22
  68. package/pipeline/commands/multi-agent/refs/channels/wiki.md +19 -19
  69. package/pipeline/commands/multi-agent/refs/component-dispatch.md +11 -11
  70. package/pipeline/commands/multi-agent/refs/conventions-defaults.md +179 -0
  71. package/pipeline/commands/multi-agent/refs/cross-cli-contract.md +35 -33
  72. package/pipeline/commands/multi-agent/refs/features/dev-critic.md +5 -5
  73. package/pipeline/commands/multi-agent/refs/features/external-context-injection.md +6 -6
  74. package/pipeline/commands/multi-agent/refs/features/model-fallback.md +73 -0
  75. package/pipeline/commands/multi-agent/refs/features/plan-todos.md +1 -1
  76. package/pipeline/commands/multi-agent/refs/features/prior-fix-detection.md +4 -4
  77. package/pipeline/commands/multi-agent/refs/features/repo-map.md +6 -6
  78. package/pipeline/commands/multi-agent/refs/features/shadow-git.md +2 -2
  79. package/pipeline/commands/multi-agent/refs/frontend-guide.md +16 -16
  80. package/pipeline/commands/multi-agent/refs/issue-jira-triad.md +18 -18
  81. package/pipeline/commands/multi-agent/refs/keychain.md +18 -8
  82. package/pipeline/commands/multi-agent/refs/knowledge.md +9 -9
  83. package/pipeline/commands/multi-agent/refs/multi-repo-integration-build.md +19 -19
  84. package/pipeline/commands/multi-agent/refs/phases/log-format.md +29 -9
  85. package/pipeline/commands/multi-agent/refs/phases/modes.md +33 -33
  86. package/pipeline/commands/multi-agent/refs/phases/operations.md +11 -11
  87. package/pipeline/commands/multi-agent/refs/phases/phase-0-init.md +93 -57
  88. package/pipeline/commands/multi-agent/refs/phases/phase-1-analysis.md +59 -28
  89. package/pipeline/commands/multi-agent/refs/phases/phase-2-planning.md +115 -63
  90. package/pipeline/commands/multi-agent/refs/phases/phase-3-dev.md +99 -36
  91. package/pipeline/commands/multi-agent/refs/phases/phase-4-review.md +160 -63
  92. package/pipeline/commands/multi-agent/refs/phases/phase-5-test.md +33 -18
  93. package/pipeline/commands/multi-agent/refs/phases/phase-6-commit.md +45 -43
  94. package/pipeline/commands/multi-agent/refs/phases/phase-7-report.md +54 -28
  95. package/pipeline/commands/multi-agent/refs/phases.md +17 -17
  96. package/pipeline/commands/multi-agent/refs/picker-contract.md +65 -0
  97. package/pipeline/commands/multi-agent/refs/progress-contract.md +37 -21
  98. package/pipeline/commands/multi-agent/refs/rules.md +83 -25
  99. package/pipeline/commands/multi-agent/refs/swiftui-guide.md +32 -30
  100. package/pipeline/commands/multi-agent/refs/tracker-contract.md +54 -30
  101. package/pipeline/commands/multi-agent/refs/wiki-capture.md +36 -33
  102. package/pipeline/commands/multi-agent/resume.md +9 -9
  103. package/pipeline/commands/multi-agent/review.md +24 -24
  104. package/pipeline/commands/multi-agent/scan.md +10 -10
  105. package/pipeline/commands/multi-agent/search.md +8 -8
  106. package/pipeline/commands/multi-agent/setup.md +111 -84
  107. package/pipeline/commands/multi-agent/stack.md +5 -5
  108. package/pipeline/commands/multi-agent/status.md +5 -5
  109. package/pipeline/commands/multi-agent/sync.md +123 -111
  110. package/pipeline/commands/multi-agent/test.md +6 -6
  111. package/pipeline/commands/multi-agent/update.md +1 -1
  112. package/pipeline/commands/multi-agent.md +66 -60
  113. package/pipeline/commands/sim-test.md +14 -14
  114. package/pipeline/eval/golden-tasks/01-ios-bugfix-darkmode/expected/phase-1-analysis.json +1 -1
  115. package/pipeline/eval/golden-tasks/01-ios-bugfix-darkmode/expected/phase-4-review.json +2 -2
  116. package/pipeline/eval/golden-tasks/01-ios-bugfix-darkmode/expected/phase-4-triage.json +2 -2
  117. package/pipeline/eval/golden-tasks/01-ios-bugfix-darkmode/metadata.json +1 -1
  118. package/pipeline/eval/golden-tasks/02-android-feature-compose/expected/phase-1-analysis.json +2 -2
  119. package/pipeline/eval/golden-tasks/02-android-feature-compose/expected/phase-4-review.json +3 -3
  120. package/pipeline/eval/golden-tasks/02-android-feature-compose/expected/phase-4-triage.json +4 -4
  121. package/pipeline/eval/golden-tasks/02-android-feature-compose/metadata.json +1 -1
  122. package/pipeline/eval/golden-tasks/02-android-feature-compose/task.json +1 -1
  123. package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/expected/phase-1-analysis.json +29 -0
  124. package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/expected/phase-2-plan.json +42 -0
  125. package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/expected/phase-4-review.json +20 -0
  126. package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/expected/phase-4-triage.json +15 -0
  127. package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/metadata.json +14 -0
  128. package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/task.json +12 -0
  129. package/pipeline/eval/golden-tasks/04-frontend-next-hydration/expected/phase-1-analysis.json +29 -0
  130. package/pipeline/eval/golden-tasks/04-frontend-next-hydration/expected/phase-2-plan.json +40 -0
  131. package/pipeline/eval/golden-tasks/04-frontend-next-hydration/expected/phase-4-review.json +20 -0
  132. package/pipeline/eval/golden-tasks/04-frontend-next-hydration/expected/phase-4-triage.json +15 -0
  133. package/pipeline/eval/golden-tasks/04-frontend-next-hydration/metadata.json +14 -0
  134. package/pipeline/eval/golden-tasks/04-frontend-next-hydration/task.json +12 -0
  135. package/pipeline/eval/golden-tasks/05-ios-security-keychain/expected/phase-1-analysis.json +29 -0
  136. package/pipeline/eval/golden-tasks/05-ios-security-keychain/expected/phase-2-plan.json +42 -0
  137. package/pipeline/eval/golden-tasks/05-ios-security-keychain/expected/phase-4-review.json +28 -0
  138. package/pipeline/eval/golden-tasks/05-ios-security-keychain/expected/phase-4-triage.json +27 -0
  139. package/pipeline/eval/golden-tasks/05-ios-security-keychain/metadata.json +14 -0
  140. package/pipeline/eval/golden-tasks/05-ios-security-keychain/task.json +12 -0
  141. package/pipeline/eval/golden-tasks/06-android-refactor-usecase/expected/phase-1-analysis.json +29 -0
  142. package/pipeline/eval/golden-tasks/06-android-refactor-usecase/expected/phase-2-plan.json +41 -0
  143. package/pipeline/eval/golden-tasks/06-android-refactor-usecase/expected/phase-4-review.json +12 -0
  144. package/pipeline/eval/golden-tasks/06-android-refactor-usecase/expected/phase-4-triage.json +6 -0
  145. package/pipeline/eval/golden-tasks/06-android-refactor-usecase/metadata.json +14 -0
  146. package/pipeline/eval/golden-tasks/06-android-refactor-usecase/task.json +12 -0
  147. package/pipeline/eval/golden-tasks/07-backend-node-idempotency/expected/phase-1-analysis.json +29 -0
  148. package/pipeline/eval/golden-tasks/07-backend-node-idempotency/expected/phase-2-plan.json +42 -0
  149. package/pipeline/eval/golden-tasks/07-backend-node-idempotency/expected/phase-4-review.json +28 -0
  150. package/pipeline/eval/golden-tasks/07-backend-node-idempotency/expected/phase-4-triage.json +27 -0
  151. package/pipeline/eval/golden-tasks/07-backend-node-idempotency/metadata.json +14 -0
  152. package/pipeline/eval/golden-tasks/07-backend-node-idempotency/task.json +12 -0
  153. package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/expected/phase-1-analysis.json +25 -0
  154. package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/expected/phase-2-plan.json +31 -0
  155. package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/expected/phase-4-review.json +12 -0
  156. package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/expected/phase-4-triage.json +18 -0
  157. package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/metadata.json +14 -0
  158. package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/task.json +12 -0
  159. package/pipeline/eval/golden-tasks/README.md +14 -14
  160. package/pipeline/eval/intent-cases.json +40 -0
  161. package/pipeline/eval/run-metrics-fixture.json +46 -0
  162. package/pipeline/eval/triage/01-empty-findings/notes.md +1 -1
  163. package/pipeline/eval/triage/02-real-blocker/notes.md +2 -2
  164. package/pipeline/eval/triage/03-out-of-scope-defer/notes.md +1 -1
  165. package/pipeline/eval/triage/04-false-positive-reject/notes.md +1 -1
  166. package/pipeline/eval/triage/05-mixed-classification/notes.md +2 -2
  167. package/pipeline/eval/triage/06-severity-mismatch/notes.md +2 -2
  168. package/pipeline/eval/triage/07-duplicate-reviewers/notes.md +1 -1
  169. package/pipeline/eval/triage/08-style-misclassified/notes.md +1 -1
  170. package/pipeline/eval/triage/09-cascading-finding/notes.md +2 -2
  171. package/pipeline/eval/triage/10-deferred-crossref/notes.md +2 -2
  172. package/pipeline/eval/triage/11-vercel-token-leak-blocker/expected.json +3 -3
  173. package/pipeline/eval/triage/11-vercel-token-leak-blocker/input.json +2 -2
  174. package/pipeline/eval/triage/11-vercel-token-leak-blocker/notes.md +5 -5
  175. package/pipeline/eval/triage/README.md +4 -4
  176. package/pipeline/lib/account-resolver.sh +3 -3
  177. package/pipeline/lib/ask-choice.sh +98 -0
  178. package/pipeline/lib/channels-multi-repo.sh +3 -3
  179. package/pipeline/lib/classify-intent.sh +110 -0
  180. package/pipeline/lib/context-link-extractor.sh +3 -3
  181. package/pipeline/lib/credential-store-resolver.sh +3 -3
  182. package/pipeline/lib/credential-store.sh +9 -5
  183. package/pipeline/lib/extract-conventions.sh +1034 -0
  184. package/pipeline/lib/fetch-confluence.sh +3 -3
  185. package/pipeline/lib/fetch-crashlytics.sh +5 -5
  186. package/pipeline/lib/fetch-fortify.sh +5 -21
  187. package/pipeline/lib/fetch-swagger.sh +5 -5
  188. package/pipeline/lib/figma-screenshot.sh +536 -0
  189. package/pipeline/lib/issue-fetcher.sh +46 -20
  190. package/pipeline/lib/md2confluence-v3.py +1076 -0
  191. package/pipeline/lib/multi-repo-pipeline.sh +13 -22
  192. package/pipeline/lib/plan-todos.sh +7 -7
  193. package/pipeline/lib/post-pr-review.sh +53 -21
  194. package/pipeline/lib/repo-cache.sh +5 -5
  195. package/pipeline/lib/review-watch.sh +17 -13
  196. package/pipeline/lib/shadow-git.sh +7 -7
  197. package/pipeline/lib/submodule-detector.sh +3 -3
  198. package/pipeline/lib/vercel-deploy.sh +28 -15
  199. package/pipeline/preferences-template.json +21 -4
  200. package/pipeline/rules/app-store-guidelines.md +2 -2
  201. package/pipeline/rules/code-style.md +6 -6
  202. package/pipeline/rules/figma-pipeline.md +100 -2
  203. package/pipeline/rules/kotlin-android.md +8 -8
  204. package/pipeline/rules/security.md +4 -4
  205. package/pipeline/rules/tdd.md +1 -1
  206. package/pipeline/rules/testing.md +5 -5
  207. package/pipeline/schemas/agent-state.schema.json +55 -20
  208. package/pipeline/schemas/analysis-output.schema.json +7 -2
  209. package/pipeline/schemas/analysis-spec.schema.json +484 -0
  210. package/pipeline/schemas/clarify-output.schema.json +5 -5
  211. package/pipeline/schemas/conventions-output.schema.json +70 -0
  212. package/pipeline/schemas/dev-critic-output.schema.json +2 -2
  213. package/pipeline/schemas/diff-risk.schema.json +3 -3
  214. package/pipeline/schemas/figma-project-config.schema.json +3 -3
  215. package/pipeline/schemas/learnings-ledger.schema.json +39 -0
  216. package/pipeline/schemas/migrations/README.md +2 -2
  217. package/pipeline/schemas/migrations/figma-config-1.0.0-to-2.0.0.mjs +5 -5
  218. package/pipeline/schemas/migrations/prefs-2.0.0-to-2.1.0.mjs +3 -3
  219. package/pipeline/schemas/migrations/prefs-2.1.0-to-2.2.0.mjs +4 -4
  220. package/pipeline/schemas/migrations/prefs-2.2.0-to-2.3.0.mjs +5 -5
  221. package/pipeline/schemas/migrations/state-2.0.0-to-2.1.0.mjs +3 -3
  222. package/pipeline/schemas/plan-todos.schema.json +4 -4
  223. package/pipeline/schemas/planning-output.schema.json +3 -3
  224. package/pipeline/schemas/prefs.schema.json +97 -13
  225. package/pipeline/schemas/reviewer-output.schema.json +7 -3
  226. package/pipeline/schemas/test-gap.schema.json +1 -1
  227. package/pipeline/schemas/token-budget.json +8 -8
  228. package/pipeline/schemas/triage-corpus.schema.json +1 -1
  229. package/pipeline/schemas/triage-output.schema.json +44 -6
  230. package/pipeline/scripts/README.md +64 -64
  231. package/pipeline/scripts/aggregate-metrics.mjs +55 -16
  232. package/pipeline/scripts/audit-log-rotate.sh +3 -3
  233. package/pipeline/scripts/audit-log.sh +20 -7
  234. package/pipeline/scripts/benchmark-phase-0.sh +6 -6
  235. package/pipeline/scripts/build-skills-index.mjs +15 -15
  236. package/pipeline/scripts/check-md-links.mjs +59 -0
  237. package/pipeline/scripts/classify-plan-safety.mjs +24 -18
  238. package/pipeline/scripts/cost-budget-check.mjs +160 -0
  239. package/pipeline/scripts/cost-table.json +23 -13
  240. package/pipeline/scripts/diff-explain.mjs +12 -12
  241. package/pipeline/scripts/diff-risk-score.mjs +18 -17
  242. package/pipeline/scripts/eval-golden-tasks-live.mjs +13 -10
  243. package/pipeline/scripts/eval-golden-tasks.mjs +3 -14
  244. package/pipeline/scripts/eval-intent.mjs +103 -0
  245. package/pipeline/scripts/eval-triage.mjs +3 -3
  246. package/pipeline/scripts/evidence-gate.mjs +155 -0
  247. package/pipeline/scripts/fixtures/install-layout.tsv +9 -9
  248. package/pipeline/scripts/gc-tmp.sh +102 -0
  249. package/pipeline/scripts/gen-mode-dispatch.mjs +27 -21
  250. package/pipeline/scripts/gen-skills-index.mjs +6 -6
  251. package/pipeline/scripts/github-ssh-setup.sh +1 -1
  252. package/pipeline/scripts/keychain-save.sh +1 -1
  253. package/pipeline/scripts/keychain.py +6 -6
  254. package/pipeline/scripts/learnings-ledger.mjs +284 -0
  255. package/pipeline/scripts/lint-skills.mjs +80 -0
  256. package/pipeline/scripts/log-metric.sh +18 -9
  257. package/pipeline/scripts/match-skills.mjs +13 -8
  258. package/pipeline/scripts/memory-load.sh +3 -3
  259. package/pipeline/scripts/memory-save.sh +5 -5
  260. package/pipeline/scripts/migrate-prefs.mjs +17 -17
  261. package/pipeline/scripts/migrate-state.mjs +12 -12
  262. package/pipeline/scripts/output-quality-check.sh +7 -7
  263. package/pipeline/scripts/phase-banner.sh +5 -5
  264. package/pipeline/scripts/phase-tracker.sh +90 -53
  265. package/pipeline/scripts/pre-commit-check.sh +45 -5
  266. package/pipeline/scripts/pre-push-check.sh +7 -7
  267. package/pipeline/scripts/prune-logs.sh +118 -0
  268. package/pipeline/scripts/render-agent-log-cost.sh +55 -18
  269. package/pipeline/scripts/render-cost-summary.sh +9 -9
  270. package/pipeline/scripts/render-work-summary.sh +4 -4
  271. package/pipeline/scripts/repo-map.mjs +9 -9
  272. package/pipeline/scripts/run-aggregator.mjs +7 -6
  273. package/pipeline/scripts/run-metrics.mjs +129 -0
  274. package/pipeline/scripts/run-smokes.mjs +76 -0
  275. package/pipeline/scripts/scan-skills.sh +11 -11
  276. package/pipeline/scripts/search-logs.sh +8 -8
  277. package/pipeline/scripts/sign-skills.sh +2 -2
  278. package/pipeline/scripts/smoke-adapters.sh +79 -10
  279. package/pipeline/scripts/smoke-add-detail.sh +5 -5
  280. package/pipeline/scripts/smoke-agent-log-cost.sh +85 -6
  281. package/pipeline/scripts/smoke-agent-model-routing.sh +3 -3
  282. package/pipeline/scripts/smoke-ask-choice.sh +42 -0
  283. package/pipeline/scripts/smoke-bitbucket-contract.sh +19 -3
  284. package/pipeline/scripts/smoke-changelog-version.sh +47 -0
  285. package/pipeline/scripts/smoke-channels-flow.sh +1 -1
  286. package/pipeline/scripts/smoke-ci-workflows.sh +5 -5
  287. package/pipeline/scripts/smoke-clarify.sh +3 -3
  288. package/pipeline/scripts/smoke-commands-skills-parity.sh +4 -4
  289. package/pipeline/scripts/smoke-community-gates.sh +75 -0
  290. package/pipeline/scripts/smoke-compliance-skills.sh +5 -5
  291. package/pipeline/scripts/smoke-cost-budget.sh +70 -0
  292. package/pipeline/scripts/smoke-cost-summary.sh +4 -4
  293. package/pipeline/scripts/smoke-cross-cli-behavior.sh +50 -9
  294. package/pipeline/scripts/smoke-cross-phase-cohesion.sh +5 -5
  295. package/pipeline/scripts/smoke-delete-flow.sh +5 -5
  296. package/pipeline/scripts/smoke-dev-critic.sh +2 -2
  297. package/pipeline/scripts/smoke-diff-explain.sh +22 -3
  298. package/pipeline/scripts/smoke-diff-risk.sh +1 -1
  299. package/pipeline/scripts/smoke-dynamic-skill-loading.sh +1 -1
  300. package/pipeline/scripts/smoke-eval-live.sh +4 -4
  301. package/pipeline/scripts/smoke-evidence-gate.sh +93 -0
  302. package/pipeline/scripts/smoke-existing-discovery-gate.sh +1 -1
  303. package/pipeline/scripts/smoke-extract-conventions.sh +163 -0
  304. package/pipeline/scripts/smoke-figma-android-parity.sh +1 -1
  305. package/pipeline/scripts/smoke-figma-credential-store.sh +3 -3
  306. package/pipeline/scripts/smoke-figma-cross-cli-inventory.sh +12 -12
  307. package/pipeline/scripts/smoke-figma-dispatch.sh +5 -5
  308. package/pipeline/scripts/smoke-figma-sync.sh +1 -1
  309. package/pipeline/scripts/smoke-gate-hooks.sh +56 -0
  310. package/pipeline/scripts/smoke-gc-tmp.sh +84 -0
  311. package/pipeline/scripts/smoke-identity-isolation.sh +7 -7
  312. package/pipeline/scripts/smoke-install-layout.sh +10 -10
  313. package/pipeline/scripts/smoke-intent-guard.sh +86 -0
  314. package/pipeline/scripts/smoke-issue-comment-template.sh +3 -3
  315. package/pipeline/scripts/smoke-issue-jira-triad.sh +1 -1
  316. package/pipeline/scripts/smoke-keychain.sh +6 -6
  317. package/pipeline/scripts/smoke-language-axis.sh +2 -2
  318. package/pipeline/scripts/smoke-learnings-ledger.sh +86 -0
  319. package/pipeline/scripts/smoke-lib-scripts.sh +2 -2
  320. package/pipeline/scripts/smoke-mcp-gate.sh +68 -0
  321. package/pipeline/scripts/smoke-md-links.sh +8 -0
  322. package/pipeline/scripts/smoke-md2confluence.sh +126 -0
  323. package/pipeline/scripts/smoke-metrics-cache-ratio.sh +72 -0
  324. package/pipeline/scripts/smoke-migrate-state.sh +10 -10
  325. package/pipeline/scripts/smoke-mode-dispatch-drift.sh +7 -4
  326. package/pipeline/scripts/smoke-model-fallback.sh +80 -0
  327. package/pipeline/scripts/smoke-multi-repo-integration.sh +3 -3
  328. package/pipeline/scripts/smoke-multi-repo-worktree.sh +1 -1
  329. package/pipeline/scripts/smoke-no-mcp-in-dev-phases.sh +115 -0
  330. package/pipeline/scripts/smoke-no-token-prompt.sh +31 -15
  331. package/pipeline/scripts/smoke-pat-audit.sh +26 -5
  332. package/pipeline/scripts/smoke-per-repo-memory.sh +1 -1
  333. package/pipeline/scripts/smoke-phase-0-multi-repo.sh +1 -1
  334. package/pipeline/scripts/smoke-phase-6-multi.sh +2 -2
  335. package/pipeline/scripts/smoke-phase-banner.sh +1 -1
  336. package/pipeline/scripts/smoke-phase-tracker.sh +1 -1
  337. package/pipeline/scripts/smoke-phase0-bridge-contract.sh +4 -4
  338. package/pipeline/scripts/smoke-phase4-triage.sh +94 -7
  339. package/pipeline/scripts/smoke-plan-approval-gate.sh +3 -3
  340. package/pipeline/scripts/smoke-plan-safety.sh +1 -1
  341. package/pipeline/scripts/smoke-plan-todos.sh +7 -4
  342. package/pipeline/scripts/smoke-pr-review-actions.sh +2 -2
  343. package/pipeline/scripts/smoke-pre-commit.sh +34 -2
  344. package/pipeline/scripts/smoke-pref-migration.sh +1 -1
  345. package/pipeline/scripts/smoke-prefs-language.sh +5 -5
  346. package/pipeline/scripts/smoke-progress-contract.sh +3 -3
  347. package/pipeline/scripts/smoke-prune-logs.sh +87 -0
  348. package/pipeline/scripts/smoke-push-retry.sh +1 -1
  349. package/pipeline/scripts/smoke-readme-counts.sh +1 -1
  350. package/pipeline/scripts/smoke-repo-map.sh +9 -9
  351. package/pipeline/scripts/smoke-review-watch.sh +12 -0
  352. package/pipeline/scripts/smoke-run-aggregator.sh +7 -7
  353. package/pipeline/scripts/smoke-run-metrics.sh +50 -0
  354. package/pipeline/scripts/smoke-schema-validation.sh +18 -11
  355. package/pipeline/scripts/smoke-search.sh +5 -5
  356. package/pipeline/scripts/smoke-shared-runtime.sh +108 -0
  357. package/pipeline/scripts/smoke-skill-authoring.sh +13 -13
  358. package/pipeline/scripts/smoke-skill-language.sh +4 -4
  359. package/pipeline/scripts/smoke-skill-manifest.sh +2 -2
  360. package/pipeline/scripts/smoke-skill-scan.sh +2 -2
  361. package/pipeline/scripts/smoke-stack-swap.sh +2 -2
  362. package/pipeline/scripts/smoke-subagent-validators.sh +8 -5
  363. package/pipeline/scripts/smoke-sync-adapters.sh +1 -1
  364. package/pipeline/scripts/smoke-sync-delegation.sh +7 -7
  365. package/pipeline/scripts/smoke-sync-parity.sh +1 -1
  366. package/pipeline/scripts/smoke-tasklist-ordering.sh +7 -7
  367. package/pipeline/scripts/smoke-telemetry.sh +1 -1
  368. package/pipeline/scripts/smoke-test-gap.sh +5 -5
  369. package/pipeline/scripts/smoke-token-budget.sh +1 -1
  370. package/pipeline/scripts/smoke-tracker-contract.sh +6 -6
  371. package/pipeline/scripts/smoke-tracker-tokens-invocation.sh +9 -1
  372. package/pipeline/scripts/smoke-triage-memory.sh +2 -2
  373. package/pipeline/scripts/smoke-url-enrichment.sh +2 -2
  374. package/pipeline/scripts/smoke-validator-contradiction.sh +1 -1
  375. package/pipeline/scripts/smoke-validator-gates.sh +164 -0
  376. package/pipeline/scripts/smoke-vercel-deploy-redact.sh +11 -11
  377. package/pipeline/scripts/smoke-wiki-integration.sh +2 -2
  378. package/pipeline/scripts/smoke-work-summary.sh +3 -3
  379. package/pipeline/scripts/smoke-worktree-path-convention.sh +4 -4
  380. package/pipeline/scripts/smoke-write-state.sh +2 -2
  381. package/pipeline/scripts/stack-swap.sh +3 -3
  382. package/pipeline/scripts/sync-adapters.mjs +37 -10
  383. package/pipeline/scripts/sync-parity-check.sh +6 -6
  384. package/pipeline/scripts/test-gap-scan.mjs +11 -13
  385. package/pipeline/scripts/token-budget-report.mjs +4 -4
  386. package/pipeline/scripts/triage-memory.mjs +6 -6
  387. package/pipeline/scripts/uninstall.mjs +42 -4
  388. package/pipeline/scripts/update-issue-progress.sh +2 -2
  389. package/pipeline/scripts/validate-analysis.mjs +19 -21
  390. package/pipeline/scripts/validate-diff-risk.mjs +4 -4
  391. package/pipeline/scripts/validate-planning.mjs +3 -3
  392. package/pipeline/scripts/validate-reviewer.mjs +4 -4
  393. package/pipeline/scripts/validate-schemas.mjs +4 -4
  394. package/pipeline/scripts/validate-test-gap.mjs +4 -4
  395. package/pipeline/scripts/validate-triage.mjs +68 -9
  396. package/pipeline/scripts/verify-skills.sh +7 -7
  397. package/pipeline/scripts/write-state.mjs +49 -11
  398. package/pipeline/skills/.skill-manifest.json +245 -149
  399. package/pipeline/skills/.skills-index.json +236 -47
  400. package/pipeline/skills/figma-android/README.md +5 -5
  401. package/pipeline/skills/figma-android/figma-component-code-connect/SKILL.md +3 -3
  402. package/pipeline/skills/figma-android/figma-component-implement/SKILL.md +8 -8
  403. package/pipeline/skills/figma-android/figma-component-test/SKILL.md +4 -4
  404. package/pipeline/skills/figma-android/figma-component-wiki/SKILL.md +5 -5
  405. package/pipeline/skills/figma-android/figma-to-component/SKILL.md +14 -14
  406. package/pipeline/skills/figma-common/README.md +29 -29
  407. package/pipeline/skills/figma-common/figma-cli-iterate/SKILL.md +20 -15
  408. package/pipeline/skills/figma-common/figma-cli-iterate-mend/SKILL.md +35 -30
  409. package/pipeline/skills/figma-common/figma-cli-lean-iterate/SKILL.md +35 -30
  410. package/pipeline/skills/figma-common/figma-cli-skip/SKILL.md +20 -20
  411. package/pipeline/skills/figma-common/figma-commit/COMMON_REBASE.md +32 -32
  412. package/pipeline/skills/figma-common/figma-commit/REVIEW.md +9 -9
  413. package/pipeline/skills/figma-common/figma-commit/SKILL.md +25 -20
  414. package/pipeline/skills/figma-common/figma-component-confluence-sync/SKILL.md +11 -6
  415. package/pipeline/skills/figma-common/figma-component-start/SKILL.md +30 -25
  416. package/pipeline/skills/figma-common/figma-component-status-update/SKILL.md +9 -4
  417. package/pipeline/skills/figma-common/figma-fix/SKILL.md +27 -22
  418. package/pipeline/skills/figma-common/figma-form-integration/SKILL.md +38 -38
  419. package/pipeline/skills/figma-common/figma-issue/SKILL.md +39 -34
  420. package/pipeline/skills/figma-common/figma-iterate/SKILL.md +20 -15
  421. package/pipeline/skills/figma-common/figma-iteration-commit/SKILL.md +44 -39
  422. package/pipeline/skills/figma-common/figma-mend/SKILL.md +6 -6
  423. package/pipeline/skills/figma-common/figma-price-integration/SKILL.md +30 -30
  424. package/pipeline/skills/figma-common/figma-remote-mcp-auth/SKILL.md +1 -1
  425. package/pipeline/skills/figma-common/figma-review/SKILL.md +31 -26
  426. package/pipeline/skills/figma-common/figma-setup/SKILL.md +11 -11
  427. package/pipeline/skills/figma-common/figma-setup/scripts/fetch-mcp-token.py +5 -5
  428. package/pipeline/skills/figma-common/figma-skip/SKILL.md +6 -6
  429. package/pipeline/skills/figma-common/figma-ui-patterns/SKILL.md +12 -12
  430. package/pipeline/skills/figma-common/figma-utility/SKILL.md +4 -4
  431. package/pipeline/skills/figma-common/figma-utility/scripts/figma-utility.py +1 -1
  432. package/pipeline/skills/figma-common/figma-validate/SKILL.md +48 -48
  433. package/pipeline/skills/figma-common/performance-iteration-commit-all/SKILL.md +42 -37
  434. package/pipeline/skills/figma-common/performance-review-next/SKILL.md +23 -18
  435. package/pipeline/skills/figma-common/performance-start/SKILL.md +52 -47
  436. package/pipeline/skills/figma-common/performance-swiftui/SKILL.md +68 -68
  437. package/pipeline/skills/figma-common/performance-tour/SKILL.md +42 -37
  438. package/pipeline/skills/figma-ios/REVIEW_CHECKLIST.md +16 -16
  439. package/pipeline/skills/figma-ios/figma-component-code-connect/SKILL.md +15 -15
  440. package/pipeline/skills/figma-ios/figma-component-implement/SKILL.md +9 -9
  441. package/pipeline/skills/figma-ios/figma-component-test/SKILL.md +15 -15
  442. package/pipeline/skills/figma-ios/figma-component-wiki/SKILL.md +18 -18
  443. package/pipeline/skills/figma-ios/figma-to-component/SKILL.md +38 -38
  444. package/pipeline/skills/figma-ios/figma-to-component/halt-return-protocol.md +2 -2
  445. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-0-init.md +12 -12
  446. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-1-gathering.md +5 -5
  447. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-1.5-existing-discovery.md +19 -19
  448. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-2-orchestrator.md +25 -25
  449. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-2a-testing-identifiers.md +7 -7
  450. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-2b-localization.md +6 -6
  451. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-2c-accessibility.md +38 -38
  452. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-2d-analytics.md +3 -3
  453. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3-orchestrator.md +29 -29
  454. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3a-location.md +6 -6
  455. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3b-tokens.md +3 -3
  456. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3c-nested.md +12 -12
  457. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3d-patterns.md +57 -57
  458. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3e-assets.md +5 -5
  459. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3f-utilities.md +6 -6
  460. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3g-property-coverage.md +10 -10
  461. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3h-variant-config.md +16 -16
  462. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4-orchestrator.md +23 -23
  463. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4a-configuration.md +26 -26
  464. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4b-view.md +43 -43
  465. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4c-documentation.md +17 -17
  466. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4d-preview.md +19 -19
  467. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4e-modifiers.md +15 -15
  468. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-5-orchestrator.md +39 -39
  469. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-5a-viewinspector.md +7 -7
  470. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-5b-snapshot.md +29 -29
  471. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-5c-unit.md +9 -9
  472. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-6-code-connect.md +31 -31
  473. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-7-wiki.md +5 -5
  474. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-7a-confluence-generate.md +18 -18
  475. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-7a-wiki-generate.md +16 -16
  476. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-8-cleanup.md +2 -2
  477. package/pipeline/skills/figma-ios/figma-to-component/reference/accessibility.md +1 -1
  478. package/pipeline/skills/figma-ios/figma-to-component/reference/code-connect.md +49 -49
  479. package/pipeline/skills/figma-ios/figma-to-component/reference/figma-to-swiftui-effects.md +8 -8
  480. package/pipeline/skills/figma-ios/figma-to-component/reference/halt-return-protocol.md +2 -2
  481. package/pipeline/skills/figma-ios/figma-to-component/reference/macros.md +9 -9
  482. package/pipeline/skills/figma-ios/figma-to-component/reference/missing-tokens.md +4 -4
  483. package/pipeline/skills/figma-ios/figma-to-component/reference/orchestrator-discipline.md +10 -10
  484. package/pipeline/skills/figma-ios/figma-to-component/reference/remote-mcp-script.md +5 -5
  485. package/pipeline/skills/figma-ios/figma-to-component/reference/rest-api-script.md +11 -11
  486. package/pipeline/skills/figma-ios/figma-to-component/reference/scripts-inventory.md +14 -14
  487. package/pipeline/skills/figma-ios/figma-to-component/reference/snapshot-testing.md +2 -2
  488. package/pipeline/skills/figma-ios/figma-to-component/reference/subcomponent-graph.md +4 -4
  489. package/pipeline/skills/figma-ios/figma-to-component/reference/testing-identifiers-naming.md +6 -6
  490. package/pipeline/skills/figma-ios/figma-to-component/reference/tools.md +9 -9
  491. package/pipeline/skills/figma-ios/figma-to-component/reference/viewinspector.md +1 -1
  492. package/pipeline/skills/figma-ios/figma-to-component/reference/wiki-to-confluence-mapping.md +1 -1
  493. package/pipeline/skills/figma-ios/figma-to-component/scripts/apply-author-login-map.py +5 -5
  494. package/pipeline/skills/figma-ios/figma-to-component/scripts/backfill-status.py +18 -18
  495. package/pipeline/skills/figma-ios/figma-to-component/scripts/build-author-registry.py +4 -4
  496. package/pipeline/skills/figma-ios/figma-to-component/scripts/bulk-sync-issues.py +4 -4
  497. package/pipeline/skills/figma-ios/figma-to-component/scripts/code-connect-data-gather.py +1 -1
  498. package/pipeline/skills/figma-ios/figma-to-component/scripts/code-connect-publish.sh +3 -3
  499. package/pipeline/skills/figma-ios/figma-to-component/scripts/confluence-component-status-upload.py +18 -18
  500. package/pipeline/skills/figma-ios/figma-to-component/scripts/confluence-component-status.py +4 -4
  501. package/pipeline/skills/figma-ios/figma-to-component/scripts/confluence-data-gather.py +5 -5
  502. package/pipeline/skills/figma-ios/figma-to-component/scripts/confluence-page-ids.example.json +9 -0
  503. package/pipeline/skills/figma-ios/figma-to-component/scripts/confluence-publish.py +3 -3
  504. package/pipeline/skills/figma-ios/figma-to-component/scripts/figma-subcomponent-graph.py +1 -1
  505. package/pipeline/skills/figma-ios/figma-to-component/scripts/figma-update.py +5 -5
  506. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/issue_sync_propagate.py +1 -1
  507. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/registry_writer.py +4 -4
  508. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_figma_update.py +1 -1
  509. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_registry_writer.py +3 -3
  510. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_skill_figma_issue.py +1 -1
  511. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_update_issue_gh.py +1 -1
  512. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase1-gather.py +12 -12
  513. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase2-finalize.py +3 -3
  514. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase3-scripts.py +26 -26
  515. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase4-finalize.py +4 -4
  516. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase5-finalize.py +4 -4
  517. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase6-finalize.py +5 -5
  518. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase7-finalize.py +4 -4
  519. package/pipeline/skills/figma-ios/figma-to-component/scripts/register-icons-codeconnect.py +4 -4
  520. package/pipeline/skills/figma-ios/figma-to-component/scripts/remote-mcp-fetch.py +5 -5
  521. package/pipeline/skills/figma-ios/figma-to-component/scripts/resolve-author-logins.py +2 -2
  522. package/pipeline/skills/figma-ios/figma-to-component/scripts/run-uicomponents-tests.sh +1 -1
  523. package/pipeline/skills/figma-ios/figma-to-component/scripts/sidebar-generator.py +5 -5
  524. package/pipeline/skills/figma-ios/figma-to-component/scripts/update-issue-from-registry.py +41 -41
  525. package/pipeline/skills/figma-ios/figma-to-component/scripts/validate-phase4.sh +8 -8
  526. package/pipeline/skills/figma-ios/figma-to-component/scripts/validate-phase6.sh +7 -7
  527. package/pipeline/skills/shared/README.md +62 -41
  528. package/pipeline/skills/shared/core/apple-archive-compliance/SKILL.md +39 -39
  529. package/pipeline/skills/shared/core/google-play-compliance/SKILL.md +44 -44
  530. package/pipeline/skills/shared/core/multi-agent/SKILL.md +182 -176
  531. package/pipeline/skills/shared/core/multi-agent-analysis/SKILL.md +55 -0
  532. package/pipeline/skills/shared/core/multi-agent-analysis-resolve/SKILL.md +48 -0
  533. package/pipeline/skills/shared/core/multi-agent-autopilot/SKILL.md +16 -16
  534. package/pipeline/skills/shared/core/multi-agent-build-optimize/SKILL.md +48 -0
  535. package/pipeline/skills/shared/core/multi-agent-channels/SKILL.md +40 -40
  536. package/pipeline/skills/shared/core/multi-agent-delete/SKILL.md +33 -30
  537. package/pipeline/skills/shared/core/multi-agent-dev/SKILL.md +26 -26
  538. package/pipeline/skills/shared/core/multi-agent-dev-autopilot/SKILL.md +22 -22
  539. package/pipeline/skills/shared/core/multi-agent-dev-local/SKILL.md +6 -6
  540. package/pipeline/skills/shared/core/multi-agent-dev-local-autopilot/SKILL.md +12 -12
  541. package/pipeline/skills/shared/core/multi-agent-diff-explain/SKILL.md +20 -20
  542. package/pipeline/skills/shared/core/multi-agent-garbage-collect/SKILL.md +61 -0
  543. package/pipeline/skills/shared/core/multi-agent-help/SKILL.md +22 -22
  544. package/pipeline/skills/shared/core/multi-agent-issue/SKILL.md +15 -15
  545. package/pipeline/skills/shared/core/multi-agent-jira/SKILL.md +12 -12
  546. package/pipeline/skills/shared/core/multi-agent-kill/SKILL.md +14 -14
  547. package/pipeline/skills/shared/core/multi-agent-language/SKILL.md +12 -12
  548. package/pipeline/skills/shared/core/multi-agent-local/SKILL.md +10 -10
  549. package/pipeline/skills/shared/core/multi-agent-local-autopilot/SKILL.md +18 -18
  550. package/pipeline/skills/shared/core/multi-agent-log/SKILL.md +9 -9
  551. package/pipeline/skills/shared/core/multi-agent-manual-test/SKILL.md +20 -20
  552. package/pipeline/skills/shared/core/multi-agent-prune-logs/SKILL.md +63 -0
  553. package/pipeline/skills/shared/core/multi-agent-purge/SKILL.md +16 -13
  554. package/pipeline/skills/shared/core/multi-agent-refactor/SKILL.md +110 -110
  555. package/pipeline/skills/shared/core/multi-agent-resume/SKILL.md +13 -13
  556. package/pipeline/skills/shared/core/multi-agent-review/SKILL.md +22 -22
  557. package/pipeline/skills/shared/core/multi-agent-scan/SKILL.md +18 -18
  558. package/pipeline/skills/shared/core/multi-agent-search/SKILL.md +13 -13
  559. package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +33 -30
  560. package/pipeline/skills/shared/core/multi-agent-stack/SKILL.md +14 -14
  561. package/pipeline/skills/shared/core/multi-agent-status/SKILL.md +9 -9
  562. package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +79 -79
  563. package/pipeline/skills/shared/core/multi-agent-test/SKILL.md +5 -5
  564. package/pipeline/skills/shared/core/multi-agent-update/SKILL.md +10 -10
  565. package/pipeline/skills/shared/external/NOTICE-swift-ios-skills.md +41 -0
  566. package/pipeline/skills/shared/external/NOTICE-xcode-build-skills.md +53 -0
  567. package/pipeline/skills/shared/external/agentflow/SKILL.md +9 -9
  568. package/pipeline/skills/shared/external/alarmkit/SKILL.md +113 -52
  569. package/pipeline/skills/shared/external/alarmkit/evals/evals.json +41 -0
  570. package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +23 -16
  571. package/pipeline/skills/shared/external/app-clips/SKILL.md +85 -354
  572. package/pipeline/skills/shared/external/app-clips/evals/evals.json +50 -0
  573. package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +135 -0
  574. package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +125 -0
  575. package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +113 -0
  576. package/pipeline/skills/shared/external/app-intents/SKILL.md +152 -59
  577. package/pipeline/skills/shared/external/app-intents/evals/evals.json +47 -0
  578. package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +161 -118
  579. package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +289 -392
  580. package/pipeline/skills/shared/external/app-store-optimization/evals/evals.json +46 -0
  581. package/pipeline/skills/shared/external/app-store-optimization/references/keyword-research-methodology.md +174 -0
  582. package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +191 -0
  583. package/pipeline/skills/shared/external/app-store-review/SKILL.md +57 -107
  584. package/pipeline/skills/shared/external/app-store-review/evals/evals.json +44 -0
  585. package/pipeline/skills/shared/external/app-store-review/references/privacy-manifest.md +35 -12
  586. package/pipeline/skills/shared/external/app-store-review/references/review-checklists.md +28 -26
  587. package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +53 -62
  588. package/pipeline/skills/shared/external/apple-on-device-ai/evals/evals.json +47 -0
  589. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-conversion.md +7 -1
  590. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-optimization.md +4 -1
  591. package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models.md +32 -12
  592. package/pipeline/skills/shared/external/apple-on-device-ai/references/mlx-swift.md +34 -30
  593. package/pipeline/skills/shared/external/authentication/SKILL.md +134 -138
  594. package/pipeline/skills/shared/external/authentication/evals/evals.json +48 -0
  595. package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +56 -29
  596. package/pipeline/skills/shared/external/authentication/references/passkeys.md +183 -0
  597. package/pipeline/skills/shared/external/avkit/SKILL.md +497 -0
  598. package/pipeline/skills/shared/external/avkit/evals/evals.json +55 -0
  599. package/pipeline/skills/shared/external/avkit/references/avkit-patterns.md +668 -0
  600. package/pipeline/skills/shared/external/background-processing/SKILL.md +29 -29
  601. package/pipeline/skills/shared/external/background-processing/evals/evals.json +44 -0
  602. package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +44 -19
  603. package/pipeline/skills/shared/external/callkit-voip/SKILL.md +136 -99
  604. package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +47 -0
  605. package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +27 -8
  606. package/pipeline/skills/shared/external/ci-cd-pipelines/SKILL.md +7 -6
  607. package/pipeline/skills/shared/external/clean-code/SKILL.md +2 -2
  608. package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +63 -56
  609. package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +47 -0
  610. package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +7 -4
  611. package/pipeline/skills/shared/external/contacts-framework/SKILL.md +31 -11
  612. package/pipeline/skills/shared/external/contacts-framework/evals/evals.json +41 -0
  613. package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +51 -51
  614. package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +70 -65
  615. package/pipeline/skills/shared/external/core-bluetooth/evals/evals.json +44 -0
  616. package/pipeline/skills/shared/external/core-bluetooth/references/ble-patterns.md +25 -1
  617. package/pipeline/skills/shared/external/core-data/SKILL.md +496 -0
  618. package/pipeline/skills/shared/external/core-data/evals/evals.json +44 -0
  619. package/pipeline/skills/shared/external/core-motion/SKILL.md +47 -14
  620. package/pipeline/skills/shared/external/core-motion/evals/evals.json +49 -0
  621. package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +47 -16
  622. package/pipeline/skills/shared/external/core-nfc/SKILL.md +43 -54
  623. package/pipeline/skills/shared/external/core-nfc/evals/evals.json +49 -0
  624. package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +32 -2
  625. package/pipeline/skills/shared/external/coreml/SKILL.md +89 -48
  626. package/pipeline/skills/shared/external/coreml/evals/evals.json +44 -0
  627. package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +82 -37
  628. package/pipeline/skills/shared/external/cryptokit/SKILL.md +493 -0
  629. package/pipeline/skills/shared/external/cryptokit/evals/evals.json +44 -0
  630. package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +602 -0
  631. package/pipeline/skills/shared/external/css-modern/SKILL.md +3 -2
  632. package/pipeline/skills/shared/external/database-patterns/SKILL.md +6 -5
  633. package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +77 -47
  634. package/pipeline/skills/shared/external/debugging-instruments/evals/evals.json +47 -0
  635. package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +42 -34
  636. package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +2 -2
  637. package/pipeline/skills/shared/external/device-integrity/SKILL.md +136 -176
  638. package/pipeline/skills/shared/external/device-integrity/evals/evals.json +45 -0
  639. package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +240 -0
  640. package/pipeline/skills/shared/external/energykit/SKILL.md +73 -34
  641. package/pipeline/skills/shared/external/energykit/evals/evals.json +45 -0
  642. package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +80 -38
  643. package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +67 -53
  644. package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +44 -0
  645. package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +53 -3
  646. package/pipeline/skills/shared/external/healthkit/SKILL.md +57 -124
  647. package/pipeline/skills/shared/external/healthkit/evals/evals.json +46 -0
  648. package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +82 -1
  649. package/pipeline/skills/shared/external/homekit-matter/SKILL.md +43 -41
  650. package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +45 -0
  651. package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +13 -8
  652. package/pipeline/skills/shared/external/html-semantic/SKILL.md +5 -4
  653. package/pipeline/skills/shared/external/humanizer/SKILL.md +4 -4
  654. package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +174 -18
  655. package/pipeline/skills/shared/external/ios-accessibility/evals/evals.json +49 -0
  656. package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +262 -4
  657. package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +117 -0
  658. package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +141 -0
  659. package/pipeline/skills/shared/external/ios-localization/SKILL.md +67 -14
  660. package/pipeline/skills/shared/external/ios-localization/evals/evals.json +49 -0
  661. package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +20 -3
  662. package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +131 -22
  663. package/pipeline/skills/shared/external/ios-networking/SKILL.md +69 -22
  664. package/pipeline/skills/shared/external/ios-networking/evals/evals.json +50 -0
  665. package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +28 -16
  666. package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +354 -0
  667. package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +69 -44
  668. package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +35 -69
  669. package/pipeline/skills/shared/external/ios-security/references/file-storage-patterns.md +8 -8
  670. package/pipeline/skills/shared/external/ios-simulator/SKILL.md +485 -0
  671. package/pipeline/skills/shared/external/ios-simulator/evals/evals.json +44 -0
  672. package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +316 -0
  673. package/pipeline/skills/shared/external/live-activities/SKILL.md +120 -131
  674. package/pipeline/skills/shared/external/live-activities/evals/evals.json +44 -0
  675. package/pipeline/skills/shared/external/live-activities/references/{live-activity-patterns.md → activitykit-patterns.md} +148 -63
  676. package/pipeline/skills/shared/external/mapkit-location/SKILL.md +40 -21
  677. package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +47 -0
  678. package/pipeline/skills/shared/external/mapkit-location/references/{corelocation-patterns.md → mapkit-corelocation-patterns.md} +88 -41
  679. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +27 -24
  680. package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +129 -172
  681. package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +46 -0
  682. package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +180 -0
  683. package/pipeline/skills/shared/external/musickit-audio/SKILL.md +45 -18
  684. package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +44 -0
  685. package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +26 -6
  686. package/pipeline/skills/shared/external/natural-language/SKILL.md +48 -18
  687. package/pipeline/skills/shared/external/natural-language/evals/evals.json +47 -0
  688. package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +20 -7
  689. package/pipeline/skills/shared/external/nextjs-app-router/SKILL.md +4 -3
  690. package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +156 -66
  691. package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +51 -0
  692. package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +69 -19
  693. package/pipeline/skills/shared/external/pdfkit/SKILL.md +499 -0
  694. package/pipeline/skills/shared/external/pdfkit/evals/evals.json +42 -0
  695. package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +844 -0
  696. package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +122 -28
  697. package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +44 -0
  698. package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +49 -18
  699. package/pipeline/skills/shared/external/permissionkit/SKILL.md +100 -51
  700. package/pipeline/skills/shared/external/permissionkit/evals/evals.json +47 -0
  701. package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +48 -8
  702. package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +13 -15
  703. package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +4 -4
  704. package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +2 -2
  705. package/pipeline/skills/shared/external/photos-camera-media/references/{photospicker-patterns.md → photokit-patterns.md} +3 -3
  706. package/pipeline/skills/shared/external/push-notifications/SKILL.md +45 -48
  707. package/pipeline/skills/shared/external/push-notifications/evals/evals.json +46 -0
  708. package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +22 -33
  709. package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +56 -37
  710. package/pipeline/skills/shared/external/python-patterns/SKILL.md +4 -3
  711. package/pipeline/skills/shared/external/react-best-practices/SKILL.md +1 -0
  712. package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +74 -53
  713. package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +47 -0
  714. package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +10 -10
  715. package/pipeline/skills/shared/external/rest-api-design/SKILL.md +21 -20
  716. package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +81 -64
  717. package/pipeline/skills/shared/external/shareplay-activities/evals/evals.json +47 -0
  718. package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +48 -9
  719. package/pipeline/skills/shared/external/speech-recognition/SKILL.md +118 -104
  720. package/pipeline/skills/shared/external/speech-recognition/evals/evals.json +49 -0
  721. package/pipeline/skills/shared/external/speech-recognition/references/speechanalyzer-patterns.md +171 -0
  722. package/pipeline/skills/shared/external/spm-build-analysis/SKILL.md +93 -0
  723. package/pipeline/skills/shared/external/spm-build-analysis/references/build-optimization-sources.md +155 -0
  724. package/pipeline/skills/shared/external/spm-build-analysis/references/recommendation-format.md +85 -0
  725. package/pipeline/skills/shared/external/spm-build-analysis/references/spm-analysis-checks.md +105 -0
  726. package/pipeline/skills/shared/external/spm-build-analysis/scripts/check_spm_pins.py +118 -0
  727. package/pipeline/skills/shared/external/storekit/SKILL.md +110 -44
  728. package/pipeline/skills/shared/external/storekit/evals/evals.json +44 -0
  729. package/pipeline/skills/shared/external/storekit/references/app-review-guidelines.md +94 -43
  730. package/pipeline/skills/shared/external/storekit/references/storekit-advanced.md +82 -33
  731. package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +449 -0
  732. package/pipeline/skills/shared/external/swift-api-design-guidelines/evals/evals.json +50 -0
  733. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/argument-labels-and-parameters.md +164 -0
  734. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/conventions-and-special-rules.md +219 -0
  735. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/naming-and-clarity.md +184 -0
  736. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/side-effects-and-mutating-pairs.md +158 -0
  737. package/pipeline/skills/shared/external/swift-architecture/SKILL.md +499 -0
  738. package/pipeline/skills/shared/external/swift-architecture/evals/evals.json +45 -0
  739. package/pipeline/skills/shared/external/swift-charts/SKILL.md +52 -40
  740. package/pipeline/skills/shared/external/swift-charts/evals/evals.json +47 -0
  741. package/pipeline/skills/shared/external/swift-charts/references/charts-patterns.md +92 -11
  742. package/pipeline/skills/shared/external/swift-codable/SKILL.md +43 -16
  743. package/pipeline/skills/shared/external/swift-codable/evals/evals.json +43 -0
  744. package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +50 -30
  745. package/pipeline/skills/shared/external/swift-concurrency/evals/evals.json +44 -0
  746. package/pipeline/skills/shared/external/swift-concurrency/references/approachable-concurrency.md +11 -4
  747. package/pipeline/skills/shared/external/swift-concurrency/references/async-algorithms.md +113 -0
  748. package/pipeline/skills/shared/external/swift-concurrency/references/bridging-interop.md +150 -0
  749. package/pipeline/skills/shared/external/swift-concurrency/references/{swift-6-2-concurrency.md → concurrency-patterns.md} +22 -11
  750. package/pipeline/skills/shared/external/swift-concurrency/references/diagnostics.md +52 -0
  751. package/pipeline/skills/shared/external/swift-concurrency/references/swiftui-concurrency.md +2 -2
  752. package/pipeline/skills/shared/external/swift-concurrency/references/synchronization-primitives.md +21 -15
  753. package/pipeline/skills/shared/external/swift-concurrency-expert/SKILL.md +3 -3
  754. package/pipeline/skills/shared/external/swift-concurrency-pro/SKILL.md +2 -2
  755. package/pipeline/skills/shared/external/swift-concurrency-pro/references/actors.md +3 -3
  756. package/pipeline/skills/shared/external/swift-concurrency-pro/references/async-streams.md +1 -1
  757. package/pipeline/skills/shared/external/swift-concurrency-pro/references/bridging.md +3 -3
  758. package/pipeline/skills/shared/external/swift-concurrency-pro/references/bug-patterns.md +3 -3
  759. package/pipeline/skills/shared/external/swift-concurrency-pro/references/cancellation.md +8 -8
  760. package/pipeline/skills/shared/external/swift-concurrency-pro/references/diagnostics.md +1 -1
  761. package/pipeline/skills/shared/external/swift-concurrency-pro/references/hotspots.md +2 -2
  762. package/pipeline/skills/shared/external/swift-concurrency-pro/references/interop.md +4 -4
  763. package/pipeline/skills/shared/external/swift-concurrency-pro/references/new-features.md +1 -1
  764. package/pipeline/skills/shared/external/swift-concurrency-pro/references/structured.md +2 -2
  765. package/pipeline/skills/shared/external/swift-concurrency-pro/references/testing.md +2 -2
  766. package/pipeline/skills/shared/external/swift-concurrency-pro/references/unstructured.md +3 -3
  767. package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +339 -0
  768. package/pipeline/skills/shared/external/swift-language/SKILL.md +33 -34
  769. package/pipeline/skills/shared/external/swift-language/evals/evals.json +47 -0
  770. package/pipeline/skills/shared/external/swift-language/references/swift-attributes-interop.md +97 -0
  771. package/pipeline/skills/shared/external/swift-language/references/swift-patterns-extended.md +19 -6
  772. package/pipeline/skills/shared/external/swift-security/SKILL.md +195 -0
  773. package/pipeline/skills/shared/external/swift-security/evals/evals.json +48 -0
  774. package/pipeline/skills/shared/external/swift-security/references/biometric-authentication.md +595 -0
  775. package/pipeline/skills/shared/external/swift-security/references/certificate-trust.md +611 -0
  776. package/pipeline/skills/shared/external/swift-security/references/common-anti-patterns.md +708 -0
  777. package/pipeline/skills/shared/external/swift-security/references/compliance-owasp-mapping.md +573 -0
  778. package/pipeline/skills/shared/external/swift-security/references/credential-storage-patterns.md +752 -0
  779. package/pipeline/skills/shared/external/swift-security/references/cryptokit-public-key.md +538 -0
  780. package/pipeline/skills/shared/external/swift-security/references/cryptokit-symmetric.md +530 -0
  781. package/pipeline/skills/shared/external/swift-security/references/keychain-access-control.md +543 -0
  782. package/pipeline/skills/shared/external/swift-security/references/keychain-fundamentals.md +620 -0
  783. package/pipeline/skills/shared/external/swift-security/references/keychain-item-classes.md +515 -0
  784. package/pipeline/skills/shared/external/swift-security/references/keychain-sharing.md +496 -0
  785. package/pipeline/skills/shared/external/swift-security/references/migration-legacy-stores.md +747 -0
  786. package/pipeline/skills/shared/external/swift-security/references/secure-enclave.md +566 -0
  787. package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +813 -0
  788. package/pipeline/skills/shared/external/swift-testing/SKILL.md +97 -297
  789. package/pipeline/skills/shared/external/swift-testing/evals/evals.json +44 -0
  790. package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +123 -0
  791. package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +162 -34
  792. package/pipeline/skills/shared/external/swift-testing-pro/SKILL.md +2 -2
  793. package/pipeline/skills/shared/external/swift-testing-pro/references/async-tests.md +3 -3
  794. package/pipeline/skills/shared/external/swift-testing-pro/references/core-rules.md +2 -2
  795. package/pipeline/skills/shared/external/swift-testing-pro/references/migrating-from-xctest.md +5 -5
  796. package/pipeline/skills/shared/external/swift-testing-pro/references/new-features.md +3 -3
  797. package/pipeline/skills/shared/external/swift-testing-pro/references/writing-better-tests.md +5 -5
  798. package/pipeline/skills/shared/external/swiftdata/SKILL.md +44 -23
  799. package/pipeline/skills/shared/external/swiftdata/evals/evals.json +47 -0
  800. package/pipeline/skills/shared/external/swiftdata/references/core-data-coexistence.md +3 -3
  801. package/pipeline/skills/shared/external/swiftdata/references/indexing.md +75 -0
  802. package/pipeline/skills/shared/external/swiftdata/references/predicate-pitfalls.md +54 -0
  803. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-advanced.md +14 -10
  804. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-queries.md +5 -5
  805. package/pipeline/skills/shared/external/swiftdata-pro/SKILL.md +2 -2
  806. package/pipeline/skills/shared/external/swiftdata-pro/references/class-inheritance.md +2 -2
  807. package/pipeline/skills/shared/external/swiftdata-pro/references/cloudkit.md +1 -1
  808. package/pipeline/skills/shared/external/swiftdata-pro/references/core-rules.md +6 -6
  809. package/pipeline/skills/shared/external/swiftlint/SKILL.md +337 -0
  810. package/pipeline/skills/shared/external/swiftlint/references/adoption-and-configuration.md +297 -0
  811. package/pipeline/skills/shared/external/swiftlint/references/custom-rules-and-analyze.md +170 -0
  812. package/pipeline/skills/shared/external/swiftlint/references/plugins-run-scripts-and-integrations.md +307 -0
  813. package/pipeline/skills/shared/external/swiftlint/references/rule-reference.md +35 -0
  814. package/pipeline/skills/shared/external/swiftlint/references/rules-suppressions-and-baselines.md +306 -0
  815. package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +56 -65
  816. package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +48 -44
  817. package/pipeline/skills/shared/external/swiftui-animation/references/core-animation-bridge.md +6 -6
  818. package/pipeline/skills/shared/external/swiftui-expert-skill/references/charts-accessibility.md +13 -13
  819. package/pipeline/skills/shared/external/swiftui-expert-skill/references/charts.md +3 -3
  820. package/pipeline/skills/shared/external/swiftui-expert-skill/references/image-optimization.md +1 -1
  821. package/pipeline/skills/shared/external/swiftui-expert-skill/references/latest-apis.md +4 -4
  822. package/pipeline/skills/shared/external/swiftui-expert-skill/references/layout-best-practices.md +2 -2
  823. package/pipeline/skills/shared/external/swiftui-expert-skill/references/list-patterns.md +1 -1
  824. package/pipeline/skills/shared/external/swiftui-expert-skill/references/macos-scenes.md +16 -16
  825. package/pipeline/skills/shared/external/swiftui-expert-skill/references/macos-views.md +11 -11
  826. package/pipeline/skills/shared/external/swiftui-expert-skill/references/macos-window-styling.md +7 -7
  827. package/pipeline/skills/shared/external/swiftui-expert-skill/references/state-management.md +5 -5
  828. package/pipeline/skills/shared/external/swiftui-expert-skill/references/view-structure.md +6 -6
  829. package/pipeline/skills/shared/external/swiftui-gestures/SKILL.md +38 -16
  830. package/pipeline/skills/shared/external/swiftui-gestures/references/gesture-patterns.md +13 -3
  831. package/pipeline/skills/shared/external/swiftui-layout-components/SKILL.md +32 -28
  832. package/pipeline/skills/shared/external/swiftui-layout-components/references/form.md +1 -1
  833. package/pipeline/skills/shared/external/swiftui-layout-components/references/grids.md +202 -41
  834. package/pipeline/skills/shared/external/swiftui-layout-components/references/list.md +16 -25
  835. package/pipeline/skills/shared/external/swiftui-layout-components/references/scrollview.md +71 -26
  836. package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +284 -65
  837. package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +387 -0
  838. package/pipeline/skills/shared/external/swiftui-navigation/SKILL.md +10 -10
  839. package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +15 -3
  840. package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +2 -2
  841. package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +1 -1
  842. package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +51 -25
  843. package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +78 -6
  844. package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +161 -16
  845. package/pipeline/skills/shared/external/swiftui-patterns/references/design-polish.md +85 -27
  846. package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +37 -33
  847. package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +39 -51
  848. package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +204 -30
  849. package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +226 -21
  850. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +220 -20
  851. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-improving-swiftui-performance.md +159 -34
  852. package/pipeline/skills/shared/external/swiftui-performance/references/wwdc-session-sources.md +27 -0
  853. package/pipeline/skills/shared/external/swiftui-pro/SKILL.md +2 -2
  854. package/pipeline/skills/shared/external/swiftui-pro/references/accessibility.md +4 -4
  855. package/pipeline/skills/shared/external/swiftui-pro/references/api.md +1 -1
  856. package/pipeline/skills/shared/external/swiftui-pro/references/data.md +2 -2
  857. package/pipeline/skills/shared/external/swiftui-pro/references/design.md +4 -4
  858. package/pipeline/skills/shared/external/swiftui-pro/references/hygiene.md +2 -2
  859. package/pipeline/skills/shared/external/swiftui-pro/references/navigation.md +1 -1
  860. package/pipeline/skills/shared/external/swiftui-pro/references/performance.md +1 -1
  861. package/pipeline/skills/shared/external/swiftui-pro/references/swift.md +2 -2
  862. package/pipeline/skills/shared/external/swiftui-pro/references/views.md +2 -2
  863. package/pipeline/skills/shared/external/swiftui-ui-patterns/SKILL.md +1 -1
  864. package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +12 -12
  865. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +3 -3
  866. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +1 -1
  867. package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +11 -11
  868. package/pipeline/skills/shared/external/swiftui-webkit/references/migration-and-fallbacks.md +124 -10
  869. package/pipeline/skills/shared/external/tailwind-css/SKILL.md +3 -2
  870. package/pipeline/skills/shared/external/testing-backend/SKILL.md +2 -1
  871. package/pipeline/skills/shared/external/tipkit/SKILL.md +3 -3
  872. package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +9 -9
  873. package/pipeline/skills/shared/external/typescript-patterns/SKILL.md +17 -16
  874. package/pipeline/skills/shared/external/vision-framework/SKILL.md +11 -11
  875. package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +1 -1
  876. package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +5 -5
  877. package/pipeline/skills/shared/external/vue-composition/SKILL.md +7 -6
  878. package/pipeline/skills/shared/external/weatherkit/SKILL.md +3 -3
  879. package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +9 -9
  880. package/pipeline/skills/shared/external/web-accessibility/SKILL.md +1 -0
  881. package/pipeline/skills/shared/external/web-performance/SKILL.md +8 -7
  882. package/pipeline/skills/shared/external/web-testing/SKILL.md +7 -6
  883. package/pipeline/skills/shared/external/widgetkit/SKILL.md +23 -17
  884. package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +99 -0
  885. package/pipeline/skills/shared/external/xcode-build-benchmark/SKILL.md +89 -0
  886. package/pipeline/skills/shared/external/xcode-build-benchmark/references/benchmark-artifacts.md +94 -0
  887. package/pipeline/skills/shared/external/xcode-build-benchmark/references/benchmarking-workflow.md +67 -0
  888. package/pipeline/skills/shared/external/xcode-build-benchmark/schemas/build-benchmark.schema.json +230 -0
  889. package/pipeline/skills/shared/external/xcode-build-benchmark/scripts/benchmark_builds.py +308 -0
  890. package/pipeline/skills/shared/external/xcode-build-fixer/SKILL.md +219 -0
  891. package/pipeline/skills/shared/external/xcode-build-fixer/references/build-settings-best-practices.md +216 -0
  892. package/pipeline/skills/shared/external/xcode-build-fixer/references/fix-patterns.md +290 -0
  893. package/pipeline/skills/shared/external/xcode-build-fixer/references/recommendation-format.md +85 -0
  894. package/pipeline/skills/shared/external/xcode-build-fixer/scripts/benchmark_builds.py +308 -0
  895. package/pipeline/skills/shared/external/xcode-build-orchestrator/SKILL.md +157 -0
  896. package/pipeline/skills/shared/external/xcode-build-orchestrator/references/benchmark-artifacts.md +94 -0
  897. package/pipeline/skills/shared/external/xcode-build-orchestrator/references/build-settings-best-practices.md +216 -0
  898. package/pipeline/skills/shared/external/xcode-build-orchestrator/references/orchestration-report-template.md +143 -0
  899. package/pipeline/skills/shared/external/xcode-build-orchestrator/references/recommendation-format.md +85 -0
  900. package/pipeline/skills/shared/external/xcode-build-orchestrator/scripts/benchmark_builds.py +308 -0
  901. package/pipeline/skills/shared/external/xcode-build-orchestrator/scripts/diagnose_compilation.py +273 -0
  902. package/pipeline/skills/shared/external/xcode-build-orchestrator/scripts/generate_optimization_report.py +533 -0
  903. package/pipeline/skills/shared/external/xcode-compilation-analyzer/SKILL.md +90 -0
  904. package/pipeline/skills/shared/external/xcode-compilation-analyzer/references/build-optimization-sources.md +155 -0
  905. package/pipeline/skills/shared/external/xcode-compilation-analyzer/references/code-compilation-checks.md +106 -0
  906. package/pipeline/skills/shared/external/xcode-compilation-analyzer/references/recommendation-format.md +85 -0
  907. package/pipeline/skills/shared/external/xcode-compilation-analyzer/scripts/diagnose_compilation.py +273 -0
  908. package/pipeline/skills/shared/external/xcode-project-analyzer/SKILL.md +77 -0
  909. package/pipeline/skills/shared/external/xcode-project-analyzer/references/build-optimization-sources.md +155 -0
  910. package/pipeline/skills/shared/external/xcode-project-analyzer/references/build-settings-best-practices.md +216 -0
  911. package/pipeline/skills/shared/external/xcode-project-analyzer/references/project-audit-checks.md +101 -0
  912. package/pipeline/skills/shared/external/xcode-project-analyzer/references/recommendation-format.md +85 -0
  913. package/pipeline/skills/skills-index.md +213 -192
  914. package/docs/GENERICITY-REVIEW.md +0 -277
  915. package/docs/STABILITY-FIX-PLAN.md +0 -168
  916. package/pipeline/scripts/.last-figma-sync-plan.json +0 -23
  917. package/pipeline/scripts/README-figma-smokes.md +0 -34
  918. package/pipeline/scripts/figma-placeholder-map.json +0 -191
  919. package/pipeline/scripts/import-figma-skills.sh +0 -253
  920. package/pipeline/scripts/smoke-figma-config-schema.sh +0 -144
  921. package/pipeline/scripts/smoke-figma-skill-import.sh +0 -174
  922. package/pipeline/scripts/smoke-install-leak-gate.sh +0 -125
  923. package/pipeline/scripts/smoke-personal-data.sh +0 -82
  924. package/pipeline/scripts/sync-figma-source.sh +0 -228
  925. package/pipeline/skills/figma-ios/figma-to-component/scripts/confluence-page-ids.json +0 -94
  926. package/pipeline/skills/shared/external/app-store-review/references/code-signing.md +0 -259
  927. package/pipeline/skills/shared/external/app-store-review/references/rejection-patterns.md +0 -152
  928. package/pipeline/skills/shared/external/pencilkit-drawing/references/paperkit-integration.md +0 -376
@@ -0,0 +1,752 @@
1
+ # Credential Storage Patterns
2
+
3
+ > Scope: Secure lifecycle patterns for client-side credentials on Apple platforms, including storage, refresh, rotation, migration, and logout cleanup.
4
+
5
+ The iOS Keychain is the only Apple-sanctioned storage mechanism for OAuth tokens, API keys, passwords, and other credentials. Cybernews found in 2025 that 71% of iOS apps leak at least one hardcoded secret - primarily through `UserDefaults`, `Info.plist`, or `.xcconfig` files that produce plaintext artifacts trivially extractable from device backups or IPA bundles. This reference covers the complete credential lifecycle: secure storage via Keychain Services, OAuth2/OIDC authentication flows, atomic token refresh with rotation, runtime secret fetching, key rotation strategies, and comprehensive logout cleanup.
6
+
7
+ Authoritative sources: Apple Developer Documentation (Keychain Services, Authentication Services), Apple Platform Security Guide (December 2024), WWDC 2019 Session 516 "What's New in Authentication", WWDC 2021 Session 10105 "Secure login with iCloud Keychain verification codes", WWDC 2024 Session 10125 "Streamline sign-in with passkey upgrades and credential managers", OWASP Mobile Top 10 2024, MASVS v2.1.0 (January 2024), MASTG v2, CISA/FBI "Product Security Bad Practices" advisory v2.0 (January 2025), and the Cybernews iOS app security research (March 2025).
8
+
9
+ ---
10
+
11
+ ## Contents
12
+
13
+ - [The Six Anti-Patterns AI Code Generators Reproduce](#the-six-anti-patterns-ai-code-generators-reproduce)
14
+ - [Anti-Pattern 1 - Tokens in UserDefaults](#anti-pattern-1-tokens-in-userdefaults)
15
+ - [Anti-Pattern 2 - Hardcoded API Keys in Source Code](#anti-pattern-2-hardcoded-api-keys-in-source-code)
16
+ - [Anti-Pattern 3 - Production Secrets in .xcconfig](#anti-pattern-3-production-secrets-in-xcconfig)
17
+ - [Anti-Pattern 4 - Missing kSecAttrAccessible Specification](#anti-pattern-4-missing-ksecattraccessible-specification)
18
+ - [Anti-Pattern 5 - Non-Atomic Token Refresh](#anti-pattern-5-non-atomic-token-refresh)
19
+ - [Anti-Pattern 6 - Incomplete Credential Clearing on Logout](#anti-pattern-6-incomplete-credential-clearing-on-logout)
20
+ - [Correct Baseline for Credential Storage](#correct-baseline-for-credential-storage)
21
+ - [Data Protection Class Selection for Credentials](#data-protection-class-selection-for-credentials)
22
+ - [Actor-Based KeychainManager - Thread-Safe Credential Storage](#actor-based-keychainmanager-thread-safe-credential-storage)
23
+ - [OAuth2 Token Storage and Retrieval Cycle](#oauth2-token-storage-and-retrieval-cycle)
24
+ - [Token Model](#token-model)
25
+ - [ASWebAuthenticationSession + PKCE Flow](#aswebauthenticationsession-pkce-flow)
26
+ - [Atomic Token Refresh with Rotation Support](#atomic-token-refresh-with-rotation-support)
27
+ - [Refresh Coordinator with Promise Coalescing](#refresh-coordinator-with-promise-coalescing)
28
+ - [Runtime API Key Fetching with Keychain Cache and TTL](#runtime-api-key-fetching-with-keychain-cache-and-ttl)
29
+ - [Comprehensive Credential Clearing on Logout](#comprehensive-credential-clearing-on-logout)
30
+ - [Key Rotation and Versioned Migration](#key-rotation-and-versioned-migration)
31
+ - [Rotation Strategies by Secret Type](#rotation-strategies-by-secret-type)
32
+ - [Versioned Keychain Items for Migration](#versioned-keychain-items-for-migration)
33
+ - [Detecting Compromised Credentials](#detecting-compromised-credentials)
34
+ - [Device Binding and Backup Implications](#device-binding-and-backup-implications)
35
+ - [Biometric Protection for High-Value Credentials](#biometric-protection-for-high-value-credentials)
36
+ - [iOS 17+ and 18+ Modernizations](#ios-17-and-18-modernizations)
37
+ - [Static Analysis and CI/CD Guardrails](#static-analysis-and-cicd-guardrails)
38
+ - [OWASP MASTG Compliance Mapping](#owasp-mastg-compliance-mapping)
39
+ - [Conclusion](#conclusion)
40
+ - [Summary Checklist](#summary-checklist)
41
+
42
+ ## The Six Anti-Patterns AI Code Generators Reproduce
43
+
44
+ AI coding assistants routinely generate insecure credential handling. Each anti-pattern below is documented with evidence, an incorrect code sample, and the correct alternative.
45
+
46
+ ### Anti-Pattern 1 - Tokens in UserDefaults
47
+
48
+ `UserDefaults` writes an unencrypted XML plist at `/var/mobile/Containers/Data/Application/{APP_ID}/Library/Preferences/{BUNDLE_ID}.plist`. This file is included in iTunes/Finder device backups, readable with iMazing or iExplorer on non-jailbroken devices, and trivially extractable on jailbroken devices via `objection`'s `ios nsuserdefaults get` command. Apple's documentation is explicit: the defaults system stores information on disk in an unencrypted format and must not be used for personal or sensitive information.
49
+
50
+ ```swift
51
+ // ❌ INCORRECT - AI-generated token storage in UserDefaults
52
+ // Tokens are written as plaintext XML plist, readable from device backups
53
+ func saveTokens(accessToken: String, refreshToken: String) {
54
+ UserDefaults.standard.set(accessToken, forKey: "access_token")
55
+ UserDefaults.standard.set(refreshToken, forKey: "refresh_token")
56
+ }
57
+ ```
58
+
59
+ **OWASP mapping:** Violates M9 (Insecure Data Storage), MASVS-STORAGE-1, MASWE-0002, and fails MASTG-TEST-0300/0301.
60
+
61
+ > For the canonical ❌/✅ code samples, objection detection commands, and full remediation checklist for this pattern, see `common-anti-patterns.md` section Anti-Pattern #1 - Storing Secrets in UserDefaults.
62
+
63
+ ### Anti-Pattern 2 - Hardcoded API Keys in Source Code
64
+
65
+ CISA and the FBI classify hardcoded credentials as a formal "bad security practice" (CWE-798, ranked in 2024 CWE Top 25). The Cybernews research team found 815,000+ hardcoded secrets across 156,080 iOS apps simply by unzipping IPA files and scanning plaintext - no decompilation required.
66
+
67
+ ```swift
68
+ // ❌ INCORRECT - Hardcoded API key discoverable via `strings` on the Mach-O binary
69
+ struct APIConfig {
70
+ static let stripeSecretKey = "sk_live_51ABC123DEF456..."
71
+ static let firebaseAPIKey = "AIzaSyB1234567890abcdefg"
72
+ }
73
+ // Attacker runs: strings MyApp.app/MyApp | grep "sk_live"
74
+ ```
75
+
76
+ **OWASP mapping:** Violates M1 (Improper Credential Usage), MASWE-0005, and CISA/FBI advisory item #8.
77
+
78
+ ### Anti-Pattern 3 - Production Secrets in .xcconfig
79
+
80
+ The `.xcconfig` pattern solves only the git-commit problem. When you reference `$(MY_API_KEY)` in Info.plist, Xcode resolves the variable at build time and embeds the literal plaintext value in the compiled Info.plist inside the `.app` bundle. Extraction takes seconds: rename `.ipa` to `.zip`, unzip, open Info.plist.
81
+
82
+ ```swift
83
+ // ❌ INCORRECT - .xcconfig value compiled into Info.plist as plaintext
84
+ // In Secrets.xcconfig: MAPS_API_KEY = gm_pk_a1b2c3d4e5f6g7h8i9
85
+ // In Info.plist: <key>MapsAPIKey</key><string>$(MAPS_API_KEY)</string>
86
+
87
+ let apiKey = Bundle.main.infoDictionary?["MapsAPIKey"] as? String
88
+ // Attacker: unzip App.ipa && plutil -p Payload/App.app/Info.plist | grep Maps
89
+ ```
90
+
91
+ ### Anti-Pattern 4 - Missing kSecAttrAccessible Specification
92
+
93
+ When you add a Keychain item without specifying `kSecAttrAccessible`, the system applies the default: `kSecAttrAccessibleWhenUnlocked` (iOS 4.0+). While reasonable, this default allows Keychain items to migrate to new devices via encrypted backups and treats devices without a passcode as "always unlocked." Explicitly setting `kSecAttrAccessibleWhenUnlockedThisDeviceOnly` prevents backup migration and confines the credential to the original hardware.
94
+
95
+ ### Anti-Pattern 5 - Non-Atomic Token Refresh
96
+
97
+ When an access token expires, the app must delete the old token and store the new one. If the app crashes between these operations, the Keychain enters an inconsistent state. Concurrent refresh attempts compound the problem: two threads can both detect expiry, both call the refresh endpoint, and one writes a stale or already-rotated refresh token. With Refresh Token Rotation (RTR), this race can invalidate the entire token family.
98
+
99
+ ### Anti-Pattern 6 - Incomplete Credential Clearing on Logout
100
+
101
+ The most common partial-cleanup bug is deleting the access token while leaving the refresh token in the Keychain. A refresh token is often longer-lived and more powerful - it can silently generate new access tokens.
102
+
103
+ ```swift
104
+ // ❌ INCORRECT - Partial cleanup leaves refresh token behind
105
+ func logout() {
106
+ let query: [String: Any] = [
107
+ kSecClass as String: kSecClassGenericPassword,
108
+ kSecAttrService as String: "com.myapp.auth",
109
+ kSecAttrAccount as String: "access_token"
110
+ ]
111
+ SecItemDelete(query as CFDictionary)
112
+ // BUG: refresh_token, user_profile, cached API keys all remain
113
+ }
114
+ ```
115
+
116
+ ### Correct Baseline for Credential Storage
117
+
118
+ ✅ Store credentials in Keychain, not `UserDefaults`/plist/source literals.
119
+ ✅ Set `kSecAttrAccessible` explicitly for each item based on access pattern.
120
+ ✅ Use add-or-update semantics and handle all `OSStatus` outcomes.
121
+ ✅ Delete all credential artifacts (access token, refresh token, derived caches) on logout.
122
+
123
+ ---
124
+
125
+ ## Data Protection Class Selection for Credentials
126
+
127
+ Choosing the correct `kSecAttrAccessible` value is the highest-ROI decision for credential confidentiality. The Keychain encrypts items using dual AES-256-GCM keys: a metadata key (cached for fast searches) and a per-row secret key that always requires a Secure Enclave round trip (Apple Platform Security Guide, December 2024; full architecture: `keychain-fundamentals.md` section Two-Tier Encryption and Query Cost).
128
+
129
+ | Accessibility Class | Device-Bound | Background Access | Primary Use Case | Risk Note |
130
+ | -------------------------------------------------- | ------------ | ----------------------- | ----------------------------- | ------------------------------------------------------------------- |
131
+ | `kSecAttrAccessibleWhenUnlockedThisDeviceOnly` | Yes | No | OAuth tokens, API keys | **Recommended default** - strongest for credentials |
132
+ | `kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly` | Yes | No | Highest-assurance secrets | Item permanently destroyed if user removes passcode |
133
+ | `kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly` | Yes | Yes (post-first unlock) | Background token refresh | Larger exposure window; use only when background access is required |
134
+ | `kSecAttrAccessibleAfterFirstUnlock` | No | Yes | Background + backup migration | Transfers via encrypted backup; avoid for sensitive tokens |
135
+
136
+ **Rule of thumb:** Default to `kSecAttrAccessibleWhenUnlockedThisDeviceOnly` for all OAuth tokens and API keys. Use `AfterFirstUnlockThisDeviceOnly` only when background refresh is required (e.g., silent push notification handling). Never use `kSecAttrSynchronizable` for app tokens - iCloud Keychain sync is designed for website passwords, not application secrets.
137
+
138
+ > For complete accessibility constant selection criteria, data protection tier explanations, and `SecAccessControl` interaction rules, see `keychain-access-control.md` section The "When" Layer: Seven Accessibility Constants.
139
+
140
+ ---
141
+
142
+ ## Actor-Based KeychainManager - Thread-Safe Credential Storage
143
+
144
+ The `SecItemAdd`, `SecItemCopyMatching`, `SecItemUpdate`, and `SecItemDelete` functions (all iOS 2.0+) are synchronous C functions performing IPC to the `securityd` daemon. They are thread-safe for independent items, but concurrent modifications to the same item produce race conditions - notably `errSecDuplicateItem` (-25299) when two threads both try to add a missing item simultaneously. A Swift actor (iOS 13+, idiomatic from iOS 17+ with mature concurrency) provides a serial executor that eliminates these races.
145
+
146
+ ```swift
147
+ // ✅ CORRECT - Actor-based KeychainManager with proper kSecAttrAccessible
148
+ // Requires: iOS 13+ (actors), recommended iOS 17+ for mature concurrency
149
+ import Foundation
150
+ import Security
151
+
152
+ public actor KeychainManager {
153
+
154
+ public enum KeychainError: Error {
155
+ case unexpectedStatus(OSStatus), itemNotFound, encodingFailed, decodingFailed
156
+ }
157
+
158
+ let service: String
159
+ private let accessGroup: String?
160
+ private let accessibility: CFString
161
+
162
+ public init(service: String, accessGroup: String? = nil,
163
+ accessibility: CFString = kSecAttrAccessibleWhenUnlockedThisDeviceOnly) {
164
+ self.service = service; self.accessGroup = accessGroup; self.accessibility = accessibility
165
+ }
166
+
167
+ func baseQuery(account: String) -> [CFString: Any] {
168
+ var q: [CFString: Any] = [
169
+ kSecClass: kSecClassGenericPassword, kSecAttrService: service,
170
+ kSecAttrAccount: account, kSecAttrAccessible: accessibility
171
+ ]
172
+ if let accessGroup { q[kSecAttrAccessGroup] = accessGroup }
173
+ #if os(macOS)
174
+ q[kSecUseDataProtectionKeychain] = true // iOS-style data protection on macOS
175
+ #endif
176
+ return q
177
+ }
178
+
179
+ /// Add-or-update semantics: try update first, fall back to add.
180
+ public func save(account: String, data: Data) throws {
181
+ var searchQ = baseQuery(account: account)
182
+ searchQ.removeValue(forKey: kSecAttrAccessible)
183
+ let attrs: [CFString: Any] = [kSecValueData: data, kSecAttrAccessible: accessibility]
184
+ var status = SecItemUpdate(searchQ as CFDictionary, attrs as CFDictionary)
185
+ if status == errSecItemNotFound {
186
+ var addQ = baseQuery(account: account); addQ[kSecValueData] = data
187
+ status = SecItemAdd(addQ as CFDictionary, nil)
188
+ }
189
+ guard status == errSecSuccess else { throw KeychainError.unexpectedStatus(status) }
190
+ }
191
+
192
+ public func load(account: String) throws -> Data {
193
+ var q = baseQuery(account: account)
194
+ q.removeValue(forKey: kSecAttrAccessible)
195
+ q[kSecReturnData] = kCFBooleanTrue; q[kSecMatchLimit] = kSecMatchLimitOne
196
+ var result: AnyObject?
197
+ let status = SecItemCopyMatching(q as CFDictionary, &result)
198
+ switch status {
199
+ case errSecSuccess: guard let d = result as? Data else { throw KeychainError.decodingFailed }; return d
200
+ case errSecItemNotFound: throw KeychainError.itemNotFound
201
+ default: throw KeychainError.unexpectedStatus(status)
202
+ }
203
+ }
204
+
205
+ public func delete(account: String) throws {
206
+ var q = baseQuery(account: account); q.removeValue(forKey: kSecAttrAccessible)
207
+ let s = SecItemDelete(q as CFDictionary)
208
+ guard s == errSecSuccess || s == errSecItemNotFound else { throw KeychainError.unexpectedStatus(s) }
209
+ }
210
+
211
+ /// Delete ALL items for this service - used during logout.
212
+ public func deleteAll() throws {
213
+ var q: [CFString: Any] = [kSecClass: kSecClassGenericPassword, kSecAttrService: service as CFString]
214
+ if let accessGroup { q[kSecAttrAccessGroup] = accessGroup as CFString }
215
+ #if os(macOS)
216
+ q[kSecUseDataProtectionKeychain] = true
217
+ #endif
218
+ let s = SecItemDelete(q as CFDictionary)
219
+ guard s == errSecSuccess || s == errSecItemNotFound else { throw KeychainError.unexpectedStatus(s) }
220
+ }
221
+ }
222
+ ```
223
+
224
+ **Why an actor?** The actor's serial executor guarantees that `save`, `load`, `delete`, and `deleteAll` never interleave. Two concurrent callers hitting `save` for the same account queue instead of racing. The synchronous `SecItem*` C calls execute safely within the actor - callers `await` access, suspending rather than blocking the cooperative thread pool.
225
+
226
+ **Global actor alternative** - when Keychain serialization must span multiple modules:
227
+
228
+ ```swift
229
+ // ✅ Pattern: Global actor for cross-module Keychain serialization
230
+ // Requires: iOS 13.0+ (global actors via Swift 5.5+)
231
+ @globalActor
232
+ actor KeychainActor {
233
+ static let shared = KeychainActor()
234
+ }
235
+
236
+ @KeychainActor
237
+ func saveCredential(_ data: Data, account: String) throws {
238
+ let query: [CFString: Any] = [
239
+ kSecClass: kSecClassGenericPassword,
240
+ kSecAttrService: "com.myapp.auth" as CFString,
241
+ kSecAttrAccount: account as CFString,
242
+ kSecAttrAccessible: kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
243
+ kSecValueData: data
244
+ ]
245
+ let status = SecItemAdd(query as CFDictionary, nil)
246
+ guard status == errSecSuccess else {
247
+ throw NSError(domain: NSOSStatusErrorDomain, code: Int(status))
248
+ }
249
+ }
250
+ ```
251
+
252
+ ---
253
+
254
+ ## OAuth2 Token Storage and Retrieval Cycle
255
+
256
+ `ASWebAuthenticationSession` (iOS 12.0+) is the mandatory standard for secure web-based login flows. Using legacy web views like `WKWebView` or `SFSafariViewController` for OAuth is a significant anti-pattern - they allow the host app to inspect web content or steal credentials. WWDC 2019 "What's New in Authentication" formally recommended migrating from the deprecated `SFAuthenticationSession` to `ASWebAuthenticationSession`.
257
+
258
+ ### Token Model
259
+
260
+ ```swift
261
+ // ✅ CORRECT - Codable token model with expiry tracking
262
+ struct OAuthTokens: Codable {
263
+ let accessToken: String
264
+ let refreshToken: String
265
+ let expiresAt: Date
266
+ let tokenType: String
267
+
268
+ var isExpired: Bool {
269
+ Date() >= expiresAt
270
+ }
271
+
272
+ /// Proactive refresh before expiry.
273
+ /// Both providers agree: refresh at 75-90% of lifetime or with a fixed
274
+ /// buffer (e.g., 60 seconds) to account for network latency and clock skew.
275
+ var shouldRefresh: Bool {
276
+ let buffer: TimeInterval = 60
277
+ return Date() >= expiresAt.addingTimeInterval(-buffer)
278
+ }
279
+ }
280
+ ```
281
+
282
+ ### ASWebAuthenticationSession + PKCE Flow
283
+
284
+ ```swift
285
+ // ✅ CORRECT - ASWebAuthenticationSession + PKCE + Keychain storage
286
+ // Requires: iOS 13.0+ (for prefersEphemeralWebBrowserSession)
287
+ import AuthenticationServices
288
+ import CryptoKit
289
+
290
+ final class OAuthManager: NSObject, ASWebAuthenticationPresentationContextProviding {
291
+
292
+ private let keychain = KeychainManager(
293
+ service: "com.myapp.auth",
294
+ accessibility: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
295
+ )
296
+ private let clientID = "mobile-app-client" // public client, no secret needed
297
+ private let redirectScheme = "com.myapp.auth"
298
+
299
+ func startAuthentication() async throws -> OAuthTokens {
300
+ let codeVerifier = generateCodeVerifier() // RFC 7636 PKCE
301
+ let codeChallenge = generateCodeChallenge(from: codeVerifier)
302
+
303
+ var components = URLComponents(string: "https://auth.example.com/authorize")!
304
+ components.queryItems = [
305
+ URLQueryItem(name: "response_type", value: "code"),
306
+ URLQueryItem(name: "client_id", value: clientID),
307
+ URLQueryItem(name: "redirect_uri", value: "\(redirectScheme)://callback"),
308
+ URLQueryItem(name: "scope", value: "openid profile offline_access"),
309
+ URLQueryItem(name: "code_challenge", value: codeChallenge),
310
+ URLQueryItem(name: "code_challenge_method", value: "S256"),
311
+ URLQueryItem(name: "state", value: UUID().uuidString)
312
+ ]
313
+
314
+ let callbackURL: URL = try await withCheckedThrowingContinuation { continuation in
315
+ let session = ASWebAuthenticationSession(
316
+ url: components.url!, callbackURLScheme: redirectScheme
317
+ ) { url, error in
318
+ if let error { continuation.resume(throwing: error) }
319
+ else if let url { continuation.resume(returning: url) }
320
+ }
321
+ session.prefersEphemeralWebBrowserSession = true // iOS 13+: no cookie sharing
322
+ session.presentationContextProvider = self
323
+ session.start()
324
+ }
325
+
326
+ guard let code = URLComponents(url: callbackURL, resolvingAgainstBaseURL: false)?
327
+ .queryItems?.first(where: { $0.name == "code" })?.value else {
328
+ throw OAuthError.missingAuthorizationCode
329
+ }
330
+
331
+ let tokens = try await exchangeCodeForTokens(code: code, codeVerifier: codeVerifier)
332
+ try await keychain.save(account: "oauth_tokens", data: JSONEncoder().encode(tokens))
333
+ return tokens
334
+ }
335
+
336
+ // MARK: - PKCE helpers (RFC 7636)
337
+
338
+ private func generateCodeVerifier() -> String {
339
+ var buffer = [UInt8](repeating: 0, count: 32)
340
+ _ = SecRandomCopyBytes(kSecRandomDefault, buffer.count, &buffer)
341
+ return Data(buffer).base64EncodedString()
342
+ .replacingOccurrences(of: "+", with: "-")
343
+ .replacingOccurrences(of: "/", with: "_")
344
+ .replacingOccurrences(of: "=", with: "")
345
+ }
346
+
347
+ private func generateCodeChallenge(from verifier: String) -> String {
348
+ // CryptoKit SHA256 (iOS 13.0+) - replaces legacy CC_SHA256
349
+ let hash = SHA256.hash(data: Data(verifier.utf8))
350
+ return Data(hash).base64EncodedString()
351
+ .replacingOccurrences(of: "+", with: "-")
352
+ .replacingOccurrences(of: "/", with: "_")
353
+ .replacingOccurrences(of: "=", with: "")
354
+ }
355
+
356
+ private func exchangeCodeForTokens(code: String, codeVerifier: String) async throws -> OAuthTokens {
357
+ // Standard OAuth2 token exchange - implement with your authorization server
358
+ fatalError("Implement token exchange")
359
+ }
360
+
361
+ func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor { ASPresentationAnchor() }
362
+ enum OAuthError: Error { case missingAuthorizationCode }
363
+ }
364
+ ```
365
+
366
+ **iOS 17.4+ improvement:** `ASWebAuthenticationSession.Callback` enables HTTPS universal link callbacks instead of custom URL schemes. Universal links provide a cryptographic guarantee of domain ownership, making them significantly less susceptible to interception (RFC 8252, OAuth 2.0 for Native Apps).
367
+
368
+ **Privacy vs SSO trade-off:** Setting `prefersEphemeralWebBrowserSession = true` maximizes privacy and session isolation but breaks Single Sign-On. Toggle based on whether your app prioritizes strict isolation or seamless SSO.
369
+
370
+ ---
371
+
372
+ ## Atomic Token Refresh with Rotation Support
373
+
374
+ When a server implements Refresh Token Rotation (RTR) - as Okta, Auth0, and others do - each refresh response includes a new refresh token and the old one is immediately invalidated. If the app stores the new access token but crashes before persisting the new refresh token, the user is locked out. The solution: update both tokens atomically within the actor's serial execution context.
375
+
376
+ Servers typically provide a short grace period (e.g., 30 seconds per Okta's configuration) during which the previous refresh token remains valid to handle network retries. If a previously invalidated token is reused outside the grace period, the server invalidates the entire token family - a strong signal of credential compromise.
377
+
378
+ ```swift
379
+ // ✅ CORRECT - Atomic token refresh with rotation support
380
+ // Requires: iOS 13.0+ (actor serialization guarantees no interleaving)
381
+ extension KeychainManager {
382
+ func atomicTokenUpdate(oldAccount: String = "oauth_tokens", newTokens: OAuthTokens) throws {
383
+ let newData = try JSONEncoder().encode(newTokens) // Encode BEFORE mutation
384
+
385
+ var delQ: [CFString: Any] = [kSecClass: kSecClassGenericPassword,
386
+ kSecAttrService: self.service as CFString,
387
+ kSecAttrAccount: oldAccount as CFString]
388
+ #if os(macOS)
389
+ delQ[kSecUseDataProtectionKeychain] = true
390
+ #endif
391
+ let delStatus = SecItemDelete(delQ as CFDictionary)
392
+ guard delStatus == errSecSuccess || delStatus == errSecItemNotFound else {
393
+ throw KeychainError.unexpectedStatus(delStatus)
394
+ }
395
+
396
+ var addQ = baseQuery(account: oldAccount); addQ[kSecValueData] = newData
397
+ let addStatus = SecItemAdd(addQ as CFDictionary, nil)
398
+ guard addStatus == errSecSuccess else { throw KeychainError.unexpectedStatus(addStatus) }
399
+ }
400
+ }
401
+ ```
402
+
403
+ ### Refresh Coordinator with Promise Coalescing
404
+
405
+ If multiple concurrent callers detect an expired token, only one refresh request should fire and all callers share the result:
406
+
407
+ ```swift
408
+ // ✅ CORRECT - Single-flight refresh coordinator
409
+ // Requires: iOS 13.0+
410
+ actor TokenRefreshCoordinator {
411
+
412
+ private let keychain: KeychainManager
413
+ private let tokenEndpoint: URL
414
+ private var refreshTask: Task<OAuthTokens, Error>?
415
+
416
+ init(keychain: KeychainManager, tokenEndpoint: URL) {
417
+ self.keychain = keychain; self.tokenEndpoint = tokenEndpoint
418
+ }
419
+
420
+ /// Returns a valid access token, refreshing if necessary.
421
+ func validAccessToken() async throws -> String {
422
+ guard let data = try? await keychain.load(account: "oauth_tokens"),
423
+ let tokens = try? JSONDecoder().decode(OAuthTokens.self, from: data) else {
424
+ throw TokenError.notAuthenticated
425
+ }
426
+ guard tokens.shouldRefresh else { return tokens.accessToken }
427
+
428
+ // Coalesce: reuse in-flight refresh if one exists
429
+ if let existing = refreshTask { return try await existing.value.accessToken }
430
+
431
+ let task = Task<OAuthTokens, Error> {
432
+ defer { refreshTask = nil }
433
+ return try await performRefresh(currentRefreshToken: tokens.refreshToken)
434
+ }
435
+ refreshTask = task
436
+ return try await task.value.accessToken
437
+ }
438
+
439
+ private func performRefresh(currentRefreshToken: String) async throws -> OAuthTokens {
440
+ var request = URLRequest(url: tokenEndpoint)
441
+ request.httpMethod = "POST"
442
+ request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
443
+ request.httpBody = "grant_type=refresh_token&refresh_token=\(currentRefreshToken)".data(using: .utf8)
444
+
445
+ let (data, response) = try await URLSession.shared.data(for: request)
446
+ guard let http = response as? HTTPURLResponse else { throw TokenError.networkError }
447
+
448
+ switch http.statusCode {
449
+ case 200:
450
+ // Decode server response (access_token, refresh_token?, expires_in, token_type)
451
+ let json = try JSONSerialization.jsonObject(with: data) as! [String: Any]
452
+ let newTokens = OAuthTokens(
453
+ accessToken: json["access_token"] as! String,
454
+ refreshToken: (json["refresh_token"] as? String) ?? currentRefreshToken,
455
+ expiresAt: Date().addingTimeInterval(json["expires_in"] as! TimeInterval),
456
+ tokenType: json["token_type"] as! String
457
+ )
458
+ try await keychain.atomicTokenUpdate(newTokens: newTokens)
459
+ return newTokens
460
+ case 400, 401:
461
+ try? await keychain.deleteAll() // Refresh token revoked - force re-auth
462
+ throw TokenError.refreshTokenExpired
463
+ default:
464
+ throw TokenError.serverError(http.statusCode)
465
+ }
466
+ }
467
+
468
+ enum TokenError: Error {
469
+ case notAuthenticated, refreshTokenExpired, networkError, serverError(Int)
470
+ }
471
+ }
472
+ ```
473
+
474
+ ---
475
+
476
+ ## Runtime API Key Fetching with Keychain Cache and TTL
477
+
478
+ The most secure pattern for API keys is a backend proxy - the key never reaches the device. When that is not feasible, fetch the key from a secure backend at runtime and cache it in the Keychain with a time-to-live. The Keychain has no native TTL mechanism, so store expiry metadata alongside the secret.
479
+
480
+ Use App Attest (`DCAppAttestService`, iOS 14.0+) to prove app integrity before the backend issues secrets. The app generates a hardware-backed key pair in the Secure Enclave and requests an attestation object from Apple. The backend validates this object, ensuring the app is untampered and running on a genuine device, before delivering short-lived API keys.
481
+
482
+ ```swift
483
+ // ✅ CORRECT - Runtime secret fetching with TTL-based Keychain cache
484
+ // Requires: iOS 13.0+
485
+ actor RuntimeSecretManager {
486
+
487
+ private struct CachedSecret: Codable {
488
+ let value: String; let fetchedAt: Date; let ttlSeconds: TimeInterval
489
+ var isExpired: Bool { Date().timeIntervalSince(fetchedAt) >= ttlSeconds }
490
+ }
491
+
492
+ private let keychain: KeychainManager
493
+ private let secretsEndpoint: URL
494
+ private let defaultTTL: TimeInterval
495
+ private var memoryCache: [String: CachedSecret] = [:]
496
+
497
+ init(keychain: KeychainManager, secretsEndpoint: URL, defaultTTL: TimeInterval = 3600) {
498
+ self.keychain = keychain; self.secretsEndpoint = secretsEndpoint; self.defaultTTL = defaultTTL
499
+ }
500
+
501
+ /// Three-tier lookup: memory → Keychain → network
502
+ func secret(forKey key: String) async throws -> String {
503
+ if let c = memoryCache[key], !c.isExpired { return c.value }
504
+
505
+ if let data = try? await keychain.load(account: "secret_\(key)"),
506
+ let c = try? JSONDecoder().decode(CachedSecret.self, from: data), !c.isExpired {
507
+ memoryCache[key] = c; return c.value
508
+ }
509
+
510
+ let freshValue = try await fetchFromBackend(key: key)
511
+ let cached = CachedSecret(value: freshValue, fetchedAt: Date(), ttlSeconds: defaultTTL)
512
+ try await keychain.save(account: "secret_\(key)", data: JSONEncoder().encode(cached))
513
+ memoryCache[key] = cached
514
+ return freshValue
515
+ }
516
+
517
+ private func fetchFromBackend(key: String) async throws -> String {
518
+ var request = URLRequest(url: secretsEndpoint.appendingPathComponent(key))
519
+ // Authenticate with App Attest (iOS 14.0+) before backend issues secret
520
+ let (data, response) = try await URLSession.shared.data(for: request)
521
+ guard let http = response as? HTTPURLResponse, http.statusCode == 200,
522
+ let json = try? JSONDecoder().decode([String: String].self, from: data),
523
+ let value = json["value"] else { throw SecretFetchError.serverError }
524
+ return value
525
+ }
526
+
527
+ enum SecretFetchError: Error { case serverError }
528
+ }
529
+ ```
530
+
531
+ ---
532
+
533
+ ## Comprehensive Credential Clearing on Logout
534
+
535
+ A secure logout must clear every credential artifact: access token, refresh token, cached secrets, user profile data, and in-memory caches. It must also revoke tokens server-side when possible. Group all auth-related Keychain items under a single `kSecAttrService` value so `SecItemDelete` can wipe them in one call - no forgotten refresh tokens, no orphaned API keys.
536
+
537
+ ```swift
538
+ // ✅ CORRECT - Complete credential clearing on logout
539
+ // OWASP MASVS-STORAGE-1, MASVS-STORAGE-2 compliant | iOS 13.0+
540
+ actor SessionManager {
541
+
542
+ private let keychain = KeychainManager(service: "com.myapp.auth",
543
+ accessibility: kSecAttrAccessibleWhenUnlockedThisDeviceOnly)
544
+
545
+ func logout() async {
546
+ // 1. Server-side revocation (best-effort)
547
+ if let data = try? await keychain.load(account: "oauth_tokens"),
548
+ let tokens = try? JSONDecoder().decode(OAuthTokens.self, from: data) {
549
+ try? await revoke(token: tokens.refreshToken)
550
+ try? await revoke(token: tokens.accessToken)
551
+ }
552
+ // 2. Nuclear Keychain cleanup - ALL items for this service
553
+ try? await keychain.deleteAll()
554
+ // 3. Clear cookies for auth domain
555
+ HTTPCookieStorage.shared.cookies(for: URL(string: "https://auth.example.com")!)?
556
+ .forEach { HTTPCookieStorage.shared.deleteCookie($0) }
557
+ // 4. Clear URL cache
558
+ URLCache.shared.removeAllCachedResponses()
559
+ }
560
+
561
+ private func revoke(token: String) async throws {
562
+ var req = URLRequest(url: URL(string: "https://auth.example.com/oauth/revoke")!)
563
+ req.httpMethod = "POST"
564
+ req.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
565
+ req.httpBody = "token=\(token)".data(using: .utf8)
566
+ _ = try await URLSession.shared.data(for: req)
567
+ }
568
+ }
569
+ ```
570
+
571
+ **Server-driven revocation signals:** Backends can signal revocation via HTTP 401/403 with custom reason codes (e.g., `token_revoked`) or via silent push notifications (APNs) to trigger background logout and Keychain clearing.
572
+
573
+ ---
574
+
575
+ ## Key Rotation and Versioned Migration
576
+
577
+ ### Rotation Strategies by Secret Type
578
+
579
+ **OAuth refresh tokens** - rely on server-driven RTR. Okta's model issues a new refresh token on every use with a configurable grace period (0-60 seconds). If a previously invalidated token is reused outside the grace period, the server invalidates the entire token family.
580
+
581
+ **Long-lived API keys** - rotation is a planned event: generate a new least-privilege key, deploy it, verify operation, then revoke the old one. Maintain emergency playbooks for compromise scenarios.
582
+
583
+ ### Versioned Keychain Items for Migration
584
+
585
+ Version Keychain items using the `kSecAttrAccount` key to enable backward-compatible migration during rotation:
586
+
587
+ ```swift
588
+ // ✅ CORRECT - Versioned Keychain migration during rotation
589
+ // Requires: iOS 13.0+
590
+ actor TokenMigrationManager {
591
+
592
+ private let keychain: KeychainManager
593
+ private static let currentVersion = 2
594
+
595
+ init(keychain: KeychainManager) { self.keychain = keychain }
596
+
597
+ /// Call on app launch to migrate old token formats.
598
+ func migrateIfNeeded() async throws {
599
+ if let _ = try? await keychain.load(account: "oauth_tokens_v2") {
600
+ return // Already current
601
+ }
602
+ if let oldData = try? await keychain.load(account: "oauth_tokens") {
603
+ let migrated = try migrateV1ToV2(oldData)
604
+ try await keychain.save(account: "oauth_tokens_v2", data: migrated)
605
+ try await keychain.delete(account: "oauth_tokens") // Clean up old
606
+ }
607
+ }
608
+
609
+ private func migrateV1ToV2(_ data: Data) throws -> Data {
610
+ // Implement format conversion between versions
611
+ return data
612
+ }
613
+ }
614
+ ```
615
+
616
+ ### Detecting Compromised Credentials
617
+
618
+ Four strategies: (1) **Token reuse detection** - server invalidates the entire token family when an already-rotated refresh token is presented. (2) **Anomaly monitoring** - geographic or temporal anomalies in token usage patterns. (3) **Proactive refresh** - refresh tokens at 75-90% of their lifetime rather than waiting for expiry. (4) **Breach database checks** - services like AWS Cognito check credentials against known breach databases during authentication.
619
+
620
+ ---
621
+
622
+ ## Device Binding and Backup Implications
623
+
624
+ Using `ThisDeviceOnly` variants prevents credential cloning but introduces friction during device upgrades. Because `ThisDeviceOnly` secrets are non-migratory, they will not transfer when a user restores an iCloud backup to a new device. The application must detect missing credentials on first launch and gracefully route the user through re-authentication.
625
+
626
+ ```swift
627
+ // ✅ Pattern: Detect missing credentials after device restore
628
+ func handleAppLaunch() async {
629
+ do {
630
+ let _ = try await keychain.load(account: "oauth_tokens_v2")
631
+ // Tokens present - proceed normally
632
+ } catch KeychainManager.KeychainError.itemNotFound {
633
+ // Likely a fresh install or device restore
634
+ // Route to authentication flow
635
+ await presentLoginScreen()
636
+ } catch {
637
+ // Unexpected error - log and route to auth
638
+ logger.error("Keychain load failed: \(error)")
639
+ await presentLoginScreen()
640
+ }
641
+ }
642
+ ```
643
+
644
+ **Why not `kSecAttrSynchronizable` for app tokens?** Setting it to `true` syncs the item across all trusted Apple devices via iCloud Keychain. While appropriate for website passwords managed by the Passwords app, this significantly increases the attack surface for OAuth tokens and API keys. Omit this attribute to keep secrets local.
645
+
646
+ ---
647
+
648
+ ## Biometric Protection for High-Value Credentials
649
+
650
+ For user-initiated, high-value operations (e.g., payment authorization, viewing sensitive data), add `SecAccessControl` with biometric gating. Avoid biometric protection for refresh tokens that require headless background renewal.
651
+
652
+ ```swift
653
+ // ✅ CORRECT - Maximum OWASP MASTG L2 compliance configuration
654
+ // Requires: iOS 11.3+ (for .or compound constraint)
655
+ func createHighSecurityKeychainItem(account: String, secret: Data) throws {
656
+ var error: Unmanaged<CFError>?
657
+ guard let accessControl = SecAccessControlCreateWithFlags(
658
+ kCFAllocatorDefault,
659
+ kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
660
+ [.biometryCurrentSet, .or, .devicePasscode],
661
+ &error
662
+ ) else {
663
+ throw error!.takeRetainedValue() as Error
664
+ }
665
+
666
+ let query: [CFString: Any] = [
667
+ kSecClass: kSecClassGenericPassword,
668
+ kSecAttrService: "com.myapp.auth" as CFString,
669
+ kSecAttrAccount: account as CFString,
670
+ kSecValueData: secret,
671
+ kSecAttrAccessControl: accessControl,
672
+ kSecUseDataProtectionKeychain: true
673
+ ]
674
+
675
+ let status = SecItemAdd(query as CFDictionary, nil)
676
+ guard status == errSecSuccess else {
677
+ throw NSError(domain: NSOSStatusErrorDomain, code: Int(status))
678
+ }
679
+ }
680
+ ```
681
+
682
+ **Cross-reference:** See `biometric-authentication.md` for detailed `LAContext` integration patterns and the LAContext-only bypass vulnerability. See `keychain-access-control.md` for the full accessibility class decision tree.
683
+
684
+ ---
685
+
686
+ ## iOS 17+ and 18+ Modernizations
687
+
688
+ **iOS 17** introduced `ASWebAuthenticationSession.Callback` (iOS 17.4+), enabling HTTPS universal link callbacks instead of custom URL schemes - more secure redirect handling that verifies domain ownership. Shared password groups let teams share credentials via end-to-end encrypted iCloud Keychain. Third-party credential provider extensions can now supply passkeys alongside passwords.
689
+
690
+ **iOS 18** brought the standalone Passwords app (replacing Keychain Access for end users), automatic passkey upgrades via `.conditional` registration style, and expanded credential provider extensions to support verification codes. No new `SecItem*` APIs were introduced, but the ecosystem shift toward passkeys means the Keychain's role is evolving from storing passwords to storing cryptographic keys for WebAuthn-based authentication.
691
+
692
+ **WWDC 2024** Session 10125 "Streamline sign-in with passkey upgrades and credential managers" detailed the automatic passkey upgrade flow. WWDC 2021 Session 10105 introduced on-device TOTP verification code generation synced via iCloud Keychain, reducing dependence on SMS-based 2FA.
693
+
694
+ **Swift 6 strict concurrency direction:** The community `swift-keychain-kit` library introduces `SecretData` as a non-copyable type (`~Copyable`) that uses `mlock` to prevent swapping to disk and zeroes memory on deallocation. While not yet an Apple framework, this pattern points toward where Keychain APIs are heading: consumed secrets that cannot accidentally be copied into insecure memory.
695
+
696
+ ---
697
+
698
+ ## Static Analysis and CI/CD Guardrails
699
+
700
+ Catch credential anti-patterns before they reach production:
701
+
702
+ | Tool | Purpose | Integration Point |
703
+ | ---------------------------- | ------------------------------------------------------ | ------------------------ |
704
+ | **truffleHog / gitleaks** | Scan for hardcoded secrets in source code | PR/commit hooks |
705
+ | **strings / class-dump** | Verify no secrets in compiled binary | Post-build CI step |
706
+ | **SwiftLint** (custom rules) | Flag `UserDefaults` usage for token-like keys | Local + CI |
707
+ | **Frida / Objection** | Verify `kSecAttrAccessible` values at runtime | QA / penetration testing |
708
+ | **MobSF** | Automated network traffic and storage leakage analysis | Dynamic regression gate |
709
+
710
+ **Rule:** Fail the build if static analysis detects secrets in the codebase or compiled binary.
711
+
712
+ ---
713
+
714
+ ## OWASP MASTG Compliance Mapping
715
+
716
+ The OWASP Mobile Top 10 (2024) places M1 (Improper Credential Usage) as the number-one mobile security risk. The MASVS v2.1.0 restructured requirements with MASWE (Mobile App Security Weakness Enumeration) bridging controls to specific tests.
717
+
718
+ | Pattern | OWASP Controls | MASWE Weaknesses | MASTG Tests |
719
+ | ------------------------------------------ | ----------------------- | ---------------------------------- | ------------------------------------- |
720
+ | Keychain with `WhenUnlockedThisDeviceOnly` | M1, M9, MASVS-STORAGE-1 | MASWE-0002, MASWE-0004, MASWE-0036 | MASTG-TEST-0299, 0300, 0301, 0302 |
721
+ | Actor-based thread-safe access | M9, MASVS-STORAGE-1 | MASWE-0002 | MASTG-TEST-0300 |
722
+ | ASWebAuthenticationSession (ephemeral) | M1, MASVS-AUTH-1 | MASWE-0032 | MASTG-TEST-0064 |
723
+ | Atomic token refresh | M1, MASVS-AUTH-1 | MASWE-0038 | - |
724
+ | Runtime secret fetching | M1, MASVS-STORAGE-1 | MASWE-0005 | - |
725
+ | Comprehensive logout cleanup | M9, MASVS-STORAGE-2 | MASWE-0004 | MASTG-TEST-0298 |
726
+ | Biometric + `ThisDeviceOnly` | M9, MASVS-STORAGE-2 | MASWE-0046 | MASTG-TEST-0298, MASTG-DEMO-0043-0047 |
727
+
728
+ The legacy test identifiers MSTG-STORAGE-1 and MSTG-STORAGE-2 map to the deprecated MASTG-TEST-0052 and MASTG-TEST-0053, now replaced by the granular suite MASTG-TEST-0296 through MASTG-TEST-0314.
729
+
730
+ ---
731
+
732
+ ## Conclusion
733
+
734
+ The Keychain is not optional - it is the only mechanism Apple provides that encrypts credentials via the Secure Enclave and enforces data protection classes tied to device lock state. Three architectural decisions eliminate the majority of credential vulnerabilities: (1) use a Swift actor as the single Keychain access point to eliminate race conditions in token refresh; (2) fetch secrets at runtime from a backend proxy using App Attest for app attestation rather than embedding them in the binary; (3) group all auth-related Keychain items under a single `kSecAttrService` so logout can clear everything in one call.
735
+
736
+ The future trajectory - passkeys, non-copyable secret types, HTTPS callbacks - reinforces rather than replaces these fundamentals.
737
+
738
+ ---
739
+
740
+ ## Summary Checklist
741
+
742
+ 1. **Keychain-only storage** - all tokens, API keys, and credentials stored exclusively in the Keychain with `kSecAttrAccessibleWhenUnlockedThisDeviceOnly`; never in `UserDefaults`, `Info.plist`, `.xcconfig`, or hardcoded in source
743
+ 2. **Actor-serialized access** - all Keychain operations routed through a Swift `actor` (or `@globalActor`) to prevent race conditions and `errSecDuplicateItem` errors from concurrent access
744
+ 3. **ASWebAuthenticationSession + PKCE** - OAuth2 flows use `ASWebAuthenticationSession` with `prefersEphemeralWebBrowserSession = true` and PKCE (RFC 7636); never `WKWebView` or `SFSafariViewController`
745
+ 4. **Atomic token refresh** - refresh token rotation handled atomically within the actor: encode new tokens before any mutation, delete old, store new; promise coalescing prevents duplicate refresh requests
746
+ 5. **Runtime secret fetching** - API keys fetched from an attested backend (App Attest / DeviceCheck, iOS 14.0+) and cached in Keychain with application-layer TTL; three-tier lookup: memory → Keychain → network
747
+ 6. **Comprehensive logout** - `deleteAll()` by `kSecAttrService` clears all credential items in one call; also revokes tokens server-side, clears cookies, and clears `URLCache`
748
+ 7. **No `kSecAttrSynchronizable` for app tokens** - iCloud Keychain sync is for website passwords, not application secrets; `ThisDeviceOnly` variants prevent backup exfiltration
749
+ 8. **Device restore detection** - app detects missing `ThisDeviceOnly` credentials after device restore and gracefully routes to re-authentication
750
+ 9. **Versioned migration** - Keychain items versioned via `kSecAttrAccount` naming (e.g., `oauth_tokens_v2`) to support format changes and rollback during rotation
751
+ 10. **CI/CD secret scanning** - static analysis (truffleHog, gitleaks, `strings`) integrated into build pipeline to catch hardcoded secrets before deployment; fail the build on detection
752
+ 11. **OWASP MASTG compliance** - patterns satisfy M1, M9, MASVS-STORAGE-1, MASVS-AUTH-1 controls; validate with MASTG-TEST-0298 through 0302 and dynamic analysis (Frida/Objection) confirming protection classes at runtime