ios-app-review-plugin 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. package/.claude/settings.local.json +42 -0
  2. package/.github/actions/ios-review/action.yml +106 -0
  3. package/.github/workflows/ci.yml +103 -0
  4. package/.github/workflows/publish.yml +57 -0
  5. package/CHANGELOG.md +66 -0
  6. package/CONTRIBUTING.md +175 -0
  7. package/LICENSE +21 -0
  8. package/README.md +205 -0
  9. package/bitrise/step.sh +128 -0
  10. package/bitrise/step.yml +101 -0
  11. package/dist/analyzer.d.ts.map +1 -0
  12. package/dist/analyzers/asc-iap.d.ts.map +1 -0
  13. package/dist/analyzers/asc-metadata.d.ts.map +1 -0
  14. package/dist/analyzers/asc-screenshots.d.ts.map +1 -0
  15. package/dist/analyzers/asc-version.d.ts.map +1 -0
  16. package/dist/analyzers/code-scanner.d.ts.map +1 -0
  17. package/dist/analyzers/deprecated-api.d.ts.map +1 -0
  18. package/dist/analyzers/entitlements.d.ts.map +1 -0
  19. package/dist/analyzers/index.d.ts.map +1 -0
  20. package/dist/analyzers/info-plist.d.ts.map +1 -0
  21. package/dist/analyzers/privacy.d.ts.map +1 -0
  22. package/dist/analyzers/private-api.d.ts.map +1 -0
  23. package/dist/analyzers/security.d.ts.map +1 -0
  24. package/dist/analyzers/ui-ux.d.ts.map +1 -0
  25. package/dist/asc/auth.d.ts.map +1 -0
  26. package/dist/asc/client.d.ts.map +1 -0
  27. package/dist/asc/endpoints/apps.d.ts.map +1 -0
  28. package/dist/asc/endpoints/iap.d.ts.map +1 -0
  29. package/dist/asc/endpoints/screenshots.d.ts.map +1 -0
  30. package/dist/asc/endpoints/versions.d.ts.map +1 -0
  31. package/dist/asc/errors.d.ts.map +1 -0
  32. package/dist/asc/index.d.ts.map +1 -0
  33. package/dist/asc/types.d.ts.map +1 -0
  34. package/dist/badge/generator.d.ts.map +1 -0
  35. package/dist/badge/index.d.ts.map +1 -0
  36. package/dist/badge/types.d.ts.map +1 -0
  37. package/dist/cache/file-cache.d.ts.map +1 -0
  38. package/dist/cache/index.d.ts.map +1 -0
  39. package/dist/cache/types.d.ts.map +1 -0
  40. package/dist/cli/commands/help.d.ts.map +1 -0
  41. package/dist/cli/commands/scan.d.ts.map +1 -0
  42. package/dist/cli/commands/version.d.ts.map +1 -0
  43. package/dist/cli/index.d.ts.map +1 -0
  44. package/dist/cli/types.d.ts.map +1 -0
  45. package/dist/git/diff.d.ts.map +1 -0
  46. package/dist/git/index.d.ts.map +1 -0
  47. package/dist/git/types.d.ts.map +1 -0
  48. package/dist/guidelines/database.d.ts.map +1 -0
  49. package/dist/guidelines/index.d.ts.map +1 -0
  50. package/dist/guidelines/matcher.d.ts.map +1 -0
  51. package/dist/guidelines/types.d.ts.map +1 -0
  52. package/dist/history/comparator.d.ts.map +1 -0
  53. package/dist/history/index.d.ts.map +1 -0
  54. package/dist/history/store.d.ts.map +1 -0
  55. package/dist/history/types.d.ts.map +1 -0
  56. package/dist/index.d.ts.map +1 -0
  57. package/dist/index.js +994 -0
  58. package/dist/parsers/index.d.ts.map +1 -0
  59. package/dist/parsers/plist.d.ts.map +1 -0
  60. package/dist/parsers/xcodeproj.d.ts.map +1 -0
  61. package/dist/progress/index.d.ts.map +1 -0
  62. package/dist/progress/reporter.d.ts.map +1 -0
  63. package/dist/progress/types.d.ts.map +1 -0
  64. package/dist/reports/html.d.ts.map +1 -0
  65. package/dist/reports/index.d.ts.map +1 -0
  66. package/dist/reports/json.d.ts.map +1 -0
  67. package/dist/reports/markdown.d.ts.map +1 -0
  68. package/dist/reports/types.d.ts.map +1 -0
  69. package/dist/rules/engine.d.ts.map +1 -0
  70. package/dist/rules/index.d.ts.map +1 -0
  71. package/dist/rules/loader.d.ts.map +1 -0
  72. package/dist/rules/types.d.ts.map +1 -0
  73. package/dist/types/index.d.ts.map +1 -0
  74. package/docs/ANALYZERS.md +237 -0
  75. package/docs/API.md +308 -0
  76. package/docs/BADGES.md +130 -0
  77. package/docs/CI_CD.md +283 -0
  78. package/docs/CLI.md +140 -0
  79. package/docs/REPORTS.md +212 -0
  80. package/docs/ROADMAP.md +267 -0
  81. package/docs/RULES.md +182 -0
  82. package/docs/SECURITY.md +89 -0
  83. package/docs/TROUBLESHOOTING.md +227 -0
  84. package/docs/tutorials/ASC_SETUP.md +188 -0
  85. package/docs/tutorials/CI_INTEGRATION.md +292 -0
  86. package/docs/tutorials/CUSTOM_RULES.md +291 -0
  87. package/docs/tutorials/GETTING_STARTED.md +226 -0
  88. package/docs/video-scripts/01-introduction.md +106 -0
  89. package/docs/video-scripts/02-cli-usage.md +120 -0
  90. package/docs/video-scripts/03-ci-integration.md +198 -0
  91. package/eslint.config.js +33 -0
  92. package/examples/.ios-review-rules.json +82 -0
  93. package/examples/bitrise-workflow.yml +129 -0
  94. package/examples/fastlane-lane.rb +71 -0
  95. package/examples/github-action.yml +147 -0
  96. package/fastlane/Fastfile.example +114 -0
  97. package/fastlane/README.md +99 -0
  98. package/jest.config.js +36 -0
  99. package/package.json +65 -0
  100. package/scripts/benchmark.ts +112 -0
  101. package/scripts/debug-parser.ts +37 -0
  102. package/scripts/debug-pbxproj.ts +36 -0
  103. package/scripts/debug-specific.ts +47 -0
  104. package/scripts/test-analyze.ts +67 -0
  105. package/scripts/xcode-cloud-review.sh +167 -0
  106. package/src/analyzer.ts +227 -0
  107. package/src/analyzers/asc-iap.ts +300 -0
  108. package/src/analyzers/asc-metadata.ts +326 -0
  109. package/src/analyzers/asc-screenshots.ts +310 -0
  110. package/src/analyzers/asc-version.ts +368 -0
  111. package/src/analyzers/code-scanner.ts +408 -0
  112. package/src/analyzers/deprecated-api.ts +390 -0
  113. package/src/analyzers/entitlements.ts +345 -0
  114. package/src/analyzers/index.ts +12 -0
  115. package/src/analyzers/info-plist.ts +409 -0
  116. package/src/analyzers/privacy.ts +376 -0
  117. package/src/analyzers/private-api.ts +377 -0
  118. package/src/analyzers/security.ts +327 -0
  119. package/src/analyzers/ui-ux.ts +509 -0
  120. package/src/asc/auth.ts +204 -0
  121. package/src/asc/client.ts +258 -0
  122. package/src/asc/endpoints/apps.ts +115 -0
  123. package/src/asc/endpoints/iap.ts +171 -0
  124. package/src/asc/endpoints/screenshots.ts +164 -0
  125. package/src/asc/endpoints/versions.ts +174 -0
  126. package/src/asc/errors.ts +109 -0
  127. package/src/asc/index.ts +108 -0
  128. package/src/asc/types.ts +369 -0
  129. package/src/badge/generator.ts +48 -0
  130. package/src/badge/index.ts +2 -0
  131. package/src/badge/types.ts +5 -0
  132. package/src/cache/file-cache.ts +75 -0
  133. package/src/cache/index.ts +2 -0
  134. package/src/cache/types.ts +10 -0
  135. package/src/cli/commands/help.ts +41 -0
  136. package/src/cli/commands/scan.ts +44 -0
  137. package/src/cli/commands/version.ts +12 -0
  138. package/src/cli/index.ts +92 -0
  139. package/src/cli/types.ts +17 -0
  140. package/src/git/diff.ts +21 -0
  141. package/src/git/index.ts +2 -0
  142. package/src/git/types.ts +5 -0
  143. package/src/guidelines/database.ts +344 -0
  144. package/src/guidelines/index.ts +4 -0
  145. package/src/guidelines/matcher.ts +84 -0
  146. package/src/guidelines/types.ts +28 -0
  147. package/src/history/comparator.ts +114 -0
  148. package/src/history/index.ts +3 -0
  149. package/src/history/store.ts +135 -0
  150. package/src/history/types.ts +40 -0
  151. package/src/index.ts +1113 -0
  152. package/src/parsers/index.ts +3 -0
  153. package/src/parsers/plist.ts +253 -0
  154. package/src/parsers/xcodeproj.ts +265 -0
  155. package/src/progress/index.ts +2 -0
  156. package/src/progress/reporter.ts +65 -0
  157. package/src/progress/types.ts +9 -0
  158. package/src/reports/html.ts +322 -0
  159. package/src/reports/index.ts +20 -0
  160. package/src/reports/json.ts +92 -0
  161. package/src/reports/markdown.ts +187 -0
  162. package/src/reports/types.ts +26 -0
  163. package/src/rules/engine.ts +121 -0
  164. package/src/rules/index.ts +3 -0
  165. package/src/rules/loader.ts +83 -0
  166. package/src/rules/types.ts +25 -0
  167. package/src/types/index.ts +247 -0
  168. package/tests/analyzer.test.ts +142 -0
  169. package/tests/analyzers/asc-iap.test.ts +228 -0
  170. package/tests/analyzers/asc-metadata.test.ts +210 -0
  171. package/tests/analyzers/asc-screenshots.test.ts +135 -0
  172. package/tests/analyzers/asc-version.test.ts +259 -0
  173. package/tests/analyzers/code-scanner.test.ts +745 -0
  174. package/tests/analyzers/deprecated-api.test.ts +286 -0
  175. package/tests/analyzers/entitlements.test.ts +411 -0
  176. package/tests/analyzers/info-plist.test.ts +148 -0
  177. package/tests/analyzers/privacy.test.ts +623 -0
  178. package/tests/analyzers/private-api.test.ts +255 -0
  179. package/tests/analyzers/security.test.ts +300 -0
  180. package/tests/analyzers/ui-ux.test.ts +357 -0
  181. package/tests/asc/auth.test.ts +189 -0
  182. package/tests/asc/client.test.ts +207 -0
  183. package/tests/asc/endpoints.test.ts +1359 -0
  184. package/tests/badge/generator.test.ts +73 -0
  185. package/tests/cache/file-cache.test.ts +124 -0
  186. package/tests/cli/cli-index.test.ts +510 -0
  187. package/tests/cli/commands.test.ts +67 -0
  188. package/tests/cli/scan.test.ts +152 -0
  189. package/tests/git/diff.test.ts +69 -0
  190. package/tests/guidelines/matcher.test.ts +209 -0
  191. package/tests/history/comparator.test.ts +272 -0
  192. package/tests/history/store.test.ts +200 -0
  193. package/tests/integration/cli.test.ts +95 -0
  194. package/tests/integration/e2e.test.ts +130 -0
  195. package/tests/parsers/plist.test.ts +240 -0
  196. package/tests/parsers/xcodeproj.test.ts +289 -0
  197. package/tests/progress/reporter.test.ts +117 -0
  198. package/tests/reports/html.test.ts +176 -0
  199. package/tests/reports/json.test.ts +235 -0
  200. package/tests/reports/markdown.test.ts +196 -0
  201. package/tests/rules/engine.test.ts +229 -0
  202. package/tests/rules/loader.test.ts +187 -0
  203. package/tests/setup.ts +15 -0
  204. package/tsconfig.json +27 -0
  205. package/tsconfig.test.json +9 -0
@@ -0,0 +1,89 @@
1
+ # Security Policy
2
+
3
+ ## Supported Versions
4
+
5
+ | Version | Supported |
6
+ |---------|-----------|
7
+ | 1.0.x | Yes |
8
+ | 0.4.x | Security fixes only |
9
+ | < 0.4 | No |
10
+
11
+ ## Reporting a Vulnerability
12
+
13
+ If you discover a security vulnerability in the iOS App Review Plugin, please report it responsibly.
14
+
15
+ **Do not open a public GitHub issue for security vulnerabilities.**
16
+
17
+ Instead, send a private report:
18
+
19
+ 1. Email: Send details to the repository maintainer via the email listed in the npm package or GitHub profile.
20
+ 2. GitHub Security Advisories: Use the [private vulnerability reporting feature](https://github.com/ahmetsina/ios-app-review-plugin/security/advisories/new) on the repository.
21
+
22
+ ### What to Include
23
+
24
+ - Description of the vulnerability
25
+ - Steps to reproduce
26
+ - Affected versions
27
+ - Potential impact
28
+ - Suggested fix (if any)
29
+
30
+ ### Response Timeline
31
+
32
+ - **Acknowledgment:** Within 48 hours
33
+ - **Assessment:** Within 5 business days
34
+ - **Fix timeline:** Depends on severity (critical: 7 days, high: 14 days, medium: 30 days)
35
+
36
+ ## Security Considerations
37
+
38
+ ### App Store Connect Credentials
39
+
40
+ The plugin uses ASC API credentials (Key ID, Issuer ID, private key) for App Store Connect validation. These credentials:
41
+
42
+ - Are read from environment variables (`ASC_KEY_ID`, `ASC_ISSUER_ID`, `ASC_PRIVATE_KEY_PATH`)
43
+ - Are never logged, stored, or transmitted outside the ASC API
44
+ - Are used only to generate short-lived JWTs for ASC API calls
45
+ - Should be stored in your CI platform's secrets management
46
+
47
+ **Never commit `.p8` private key files to version control.**
48
+
49
+ ### File System Access
50
+
51
+ The plugin reads files from the specified project path and its subdirectories. It:
52
+
53
+ - Reads source files (`.swift`, `.m`, `.mm`, `.h`, `.c`, `.cpp`), plists, storyboards, asset catalogs
54
+ - Does not modify any project files
55
+ - Does not execute any project code
56
+ - Does not download or install any dependencies from the project
57
+ - Writes only to explicitly specified output paths (report files, badge SVG, history store)
58
+
59
+ ### Scan History Storage
60
+
61
+ When `--save-history` is used, scan results are stored as JSON files in a `.ios-review-history` directory near the project. These files contain:
62
+
63
+ - Issue IDs and titles
64
+ - File paths and line numbers
65
+ - Scores and timestamps
66
+ - Git branch and commit info
67
+
68
+ Review the history directory contents and add it to `.gitignore` if the data is sensitive.
69
+
70
+ ### Network Access
71
+
72
+ The plugin makes network requests only when ASC validation is enabled (`--include-asc`). All requests go to Apple's App Store Connect API (`api.appstoreconnect.apple.com`) over HTTPS.
73
+
74
+ No telemetry, analytics, or other network calls are made.
75
+
76
+ ### Dependencies
77
+
78
+ The plugin uses a minimal dependency set:
79
+
80
+ - `@modelcontextprotocol/sdk` -- MCP protocol
81
+ - `fast-glob` -- File discovery
82
+ - `plist` -- Plist parsing
83
+ - `zod` -- Input validation
84
+
85
+ All dependencies should be audited regularly:
86
+
87
+ ```bash
88
+ npm audit
89
+ ```
@@ -0,0 +1,227 @@
1
+ # Troubleshooting
2
+
3
+ ## Installation Issues
4
+
5
+ ### "Cannot find module" errors after build
6
+
7
+ ```
8
+ Error: Cannot find module '/path/to/dist/index.js'
9
+ ```
10
+
11
+ Rebuild the project:
12
+
13
+ ```bash
14
+ npm run clean && npm run build
15
+ ```
16
+
17
+ ### Node.js version error
18
+
19
+ ```
20
+ SyntaxError: Unexpected token ...
21
+ ```
22
+
23
+ The plugin requires Node.js >= 18. Check your version:
24
+
25
+ ```bash
26
+ node --version
27
+ ```
28
+
29
+ ---
30
+
31
+ ## Project Parsing Errors
32
+
33
+ ### "No Xcode project found" or empty results
34
+
35
+ The plugin looks for `.xcodeproj` or `.xcworkspace` at the specified path. Make sure you point to the right location:
36
+
37
+ ```bash
38
+ # Point to the .xcodeproj file, not the directory containing it
39
+ ios-app-review scan ./MyApp/MyApp.xcodeproj
40
+
41
+ # Or the directory containing the .xcodeproj
42
+ ios-app-review scan ./MyApp/
43
+ ```
44
+
45
+ ### "Failed to parse project.pbxproj"
46
+
47
+ Complex `.pbxproj` files with unusual formatting may cause parse issues. Verify the file is valid:
48
+
49
+ ```bash
50
+ plutil -lint ./MyApp.xcodeproj/project.pbxproj
51
+ ```
52
+
53
+ If the project uses Xcode build settings variables like `$(SRCROOT)` in paths, the parser resolves these to the project's base directory.
54
+
55
+ ### No source files found
56
+
57
+ The scanner excludes these directories by default:
58
+ - `Pods/`
59
+ - `Carthage/`
60
+ - `build/`
61
+ - `DerivedData/`
62
+ - `Tests/`
63
+ - `UITests/`
64
+ - `*.generated.swift`
65
+
66
+ If your source files are in an unexpected location, ensure they are referenced in the Xcode project's target or accessible under the base path.
67
+
68
+ ---
69
+
70
+ ## Info.plist Issues
71
+
72
+ ### "Info.plist not found at configured path"
73
+
74
+ The path in the project's build settings (INFOPLIST_FILE) is relative to the project directory. The plugin resolves it automatically, but if the file was moved:
75
+
76
+ 1. Check the actual path: `find . -name "Info.plist"`
77
+ 2. Update the build setting in Xcode
78
+ 3. Or use `check_info_plist` directly with the absolute path
79
+
80
+ ### Plist parse errors
81
+
82
+ Binary plists are supported. If parsing fails, convert to XML format:
83
+
84
+ ```bash
85
+ plutil -convert xml1 ./MyApp/Info.plist
86
+ ```
87
+
88
+ ---
89
+
90
+ ## App Store Connect (ASC) Issues
91
+
92
+ ### "ASC_KEY_ID environment variable is required"
93
+
94
+ Set all three required environment variables:
95
+
96
+ ```bash
97
+ export ASC_KEY_ID="XXXXXXXXXX"
98
+ export ASC_ISSUER_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
99
+ export ASC_PRIVATE_KEY_PATH="/path/to/AuthKey_XXXXXXXXXX.p8"
100
+ ```
101
+
102
+ ### "Unable to read private key"
103
+
104
+ 1. Verify the file exists and is readable:
105
+ ```bash
106
+ ls -la "$ASC_PRIVATE_KEY_PATH"
107
+ ```
108
+ 2. Check the file format. It should start with `-----BEGIN PRIVATE KEY-----`.
109
+ 3. Ensure no extra whitespace or characters were added during transfer.
110
+
111
+ ### "401 Unauthorized" from ASC API
112
+
113
+ - **Key expired or revoked:** Regenerate the key in App Store Connect > Users and Access > Keys.
114
+ - **Wrong Issuer ID:** The Issuer ID is shown at the top of the Keys page, not on individual key rows.
115
+ - **Insufficient permissions:** The API key must have at least "App Manager" role.
116
+ - **Clock skew:** JWT tokens include timestamps. Ensure your system clock is accurate.
117
+
118
+ ### "404 Not Found" for bundle ID
119
+
120
+ The bundle ID must match an app that exists in your App Store Connect account. Check:
121
+
122
+ ```bash
123
+ # List apps (requires ASC CLI or API)
124
+ # The bundleId is case-sensitive
125
+ ```
126
+
127
+ ### Rate limiting
128
+
129
+ The ASC API client includes built-in rate limiting. If you see rate limit errors, the client will automatically retry after the specified delay. For parallel CI builds, consider staggering ASC validation steps.
130
+
131
+ ---
132
+
133
+ ## Custom Rules Issues
134
+
135
+ ### "No .ios-review-rules.json found"
136
+
137
+ The rule loader searches from the project directory upward. Place the file:
138
+ - In the project root (next to `.xcodeproj`)
139
+ - Or in any parent directory
140
+ - Or specify explicitly: `--config ./path/to/rules.json`
141
+
142
+ ### "Custom rules validation FAILED"
143
+
144
+ Common issues:
145
+ - **Invalid JSON:** Run `jq . .ios-review-rules.json` to validate syntax.
146
+ - **Missing required fields:** Every rule needs `id`, `title`, `description`, `severity`, and `pattern`.
147
+ - **version must be 1:** The schema version must be the literal number `1`.
148
+ - **Invalid severity:** Must be `"error"`, `"warning"`, or `"info"`.
149
+
150
+ ### Regex pattern not matching
151
+
152
+ - Backslashes must be double-escaped in JSON: `\\b` for `\b`, `\\s` for `\s`.
153
+ - Test patterns in JavaScript: `new RegExp("your-pattern", "g")`.
154
+ - Ensure the `flags` field is set (default: `"g"`). Without `g`, only the first match per file is reported.
155
+
156
+ ---
157
+
158
+ ## Large Project Performance
159
+
160
+ ### Scan takes too long
161
+
162
+ 1. **Use incremental scanning:**
163
+ ```bash
164
+ ios-app-review scan ./MyApp.xcodeproj --changed-since main
165
+ ```
166
+
167
+ 2. **Run specific analyzers:**
168
+ ```bash
169
+ ios-app-review scan ./MyApp.xcodeproj --analyzers code,security
170
+ ```
171
+
172
+ 3. **Exclude unnecessary targets:** The plugin analyzes all application targets by default. If you have multiple targets, use the `targetName` parameter (MCP) to focus on one.
173
+
174
+ ### Memory issues on very large projects
175
+
176
+ For projects with thousands of source files, Node.js may need more heap space:
177
+
178
+ ```bash
179
+ NODE_OPTIONS="--max-old-space-size=4096" ios-app-review scan ./MyApp.xcodeproj
180
+ ```
181
+
182
+ ---
183
+
184
+ ## History and Comparison Issues
185
+
186
+ ### "No previous scan found"
187
+
188
+ Run a scan with `--save-history` first to create the baseline:
189
+
190
+ ```bash
191
+ ios-app-review scan ./MyApp.xcodeproj --save-history
192
+ ```
193
+
194
+ History is stored in `.ios-review-history/` near the project directory.
195
+
196
+ ### History directory location
197
+
198
+ The history store writes to a `.ios-review-history` directory in the parent directory of the resolved project path. For example, if your project is at `/code/MyApp/MyApp.xcodeproj`, history is stored in `/code/MyApp/.ios-review-history/`.
199
+
200
+ ---
201
+
202
+ ## MCP Server Issues
203
+
204
+ ### Server does not start
205
+
206
+ When run without arguments, the binary starts as an MCP server on stdio. Ensure your MCP client configuration points to the correct path:
207
+
208
+ ```json
209
+ {
210
+ "ios-app-review": {
211
+ "command": "node",
212
+ "args": ["/absolute/path/to/ios-app-review-plugin/dist/index.js"]
213
+ }
214
+ }
215
+ ```
216
+
217
+ ### "Unknown tool" errors
218
+
219
+ Verify you are calling tools with their exact names. Tool names use underscores, not hyphens: `analyze_ios_app`, not `analyze-ios-app`.
220
+
221
+ ### Server crashes silently
222
+
223
+ Check stderr output. The server logs startup and fatal errors to stderr:
224
+
225
+ ```bash
226
+ node dist/index.js 2>server.log
227
+ ```
@@ -0,0 +1,188 @@
1
+ # App Store Connect Setup Tutorial
2
+
3
+ This tutorial walks through generating an API key, configuring environment variables, and using the ASC validation tools.
4
+
5
+ ## Overview
6
+
7
+ The ASC validators check your app's metadata, screenshots, version info, and in-app purchases directly against the App Store Connect API. This catches issues that are only visible in ASC, like missing screenshot sizes, incomplete localizations, or version conflicts.
8
+
9
+ **Requirements:**
10
+ - An Apple Developer Program membership
11
+ - Admin or App Manager access to App Store Connect
12
+ - An app already created in App Store Connect
13
+
14
+ ## Step 1: Generate an API Key
15
+
16
+ 1. Open [App Store Connect](https://appstoreconnect.apple.com/).
17
+ 2. Navigate to **Users and Access** > **Integrations** > **App Store Connect API**.
18
+ 3. Click **Generate API Key** (or the "+" button).
19
+ 4. Name it something descriptive: `ios-app-review-ci`.
20
+ 5. Select the **App Manager** role (minimum required).
21
+ 6. Click **Generate**.
22
+
23
+ You will see:
24
+ - **Key ID**: A 10-character alphanumeric string (e.g., `ABC1234DEF`)
25
+ - **Issuer ID**: A UUID shown at the top of the page (e.g., `12345678-abcd-efgh-ijkl-123456789012`)
26
+
27
+ 7. Click **Download API Key** to get the `.p8` file. You can only download this once.
28
+
29
+ Save the `.p8` file securely. A typical location:
30
+
31
+ ```
32
+ ~/.appstoreconnect/AuthKey_ABC1234DEF.p8
33
+ ```
34
+
35
+ ## Step 2: Configure Environment Variables
36
+
37
+ Set three environment variables:
38
+
39
+ ```bash
40
+ export ASC_KEY_ID="ABC1234DEF"
41
+ export ASC_ISSUER_ID="12345678-abcd-efgh-ijkl-123456789012"
42
+ export ASC_PRIVATE_KEY_PATH="$HOME/.appstoreconnect/AuthKey_ABC1234DEF.p8"
43
+ ```
44
+
45
+ For persistent configuration, add these to your shell profile (`~/.zshrc` or `~/.bashrc`).
46
+
47
+ ### For CI Systems
48
+
49
+ | Platform | How to store |
50
+ |----------|-------------|
51
+ | GitHub Actions | Settings > Secrets > Add `ASC_KEY_ID`, `ASC_ISSUER_ID`, `ASC_PRIVATE_KEY` (file contents) |
52
+ | Fastlane | `.env` file or Fastlane Match |
53
+ | Bitrise | Secrets tab in workflow editor |
54
+ | Xcode Cloud | Workflow > Environment Variables |
55
+
56
+ In CI, you typically store the `.p8` file contents as a secret and write it to a temp file:
57
+
58
+ ```bash
59
+ echo "$ASC_PRIVATE_KEY" > /tmp/AuthKey.p8
60
+ export ASC_PRIVATE_KEY_PATH=/tmp/AuthKey.p8
61
+ ```
62
+
63
+ ## Step 3: Verify the Connection
64
+
65
+ ### Using the CLI
66
+
67
+ ```bash
68
+ ios-app-review scan ./MyApp.xcodeproj --include-asc --analyzers asc-metadata
69
+ ```
70
+
71
+ If credentials are correct, you will see metadata validation results. If not, you will get an authentication error.
72
+
73
+ ### Using the MCP Tool
74
+
75
+ In Claude Code:
76
+
77
+ ```
78
+ Validate the App Store Connect metadata for bundle ID com.mycompany.myapp
79
+ ```
80
+
81
+ This calls the `validate_asc_metadata` tool.
82
+
83
+ ## Step 4: Run ASC Validators
84
+
85
+ ### Individual Validators
86
+
87
+ **Metadata check:**
88
+
89
+ ```bash
90
+ # Via MCP
91
+ validate_asc_metadata with bundleId "com.mycompany.myapp"
92
+ ```
93
+
94
+ Checks: app name length, subtitle, description, keywords, privacy policy URL, support URL, marketing URL.
95
+
96
+ **Screenshots check:**
97
+
98
+ ```bash
99
+ # Via MCP
100
+ validate_asc_screenshots with bundleId "com.mycompany.myapp"
101
+ ```
102
+
103
+ Checks: required device sizes present, screenshot counts per locale, no failed uploads.
104
+
105
+ **Version comparison:**
106
+
107
+ ```bash
108
+ # Via MCP
109
+ compare_versions with bundleId "com.mycompany.myapp", localVersion "2.1.0", localBuild "45"
110
+ ```
111
+
112
+ Checks: version/build number increments, submission status, release notes presence.
113
+
114
+ **IAP validation:**
115
+
116
+ ```bash
117
+ # Via MCP
118
+ validate_iap with bundleId "com.mycompany.myapp"
119
+ ```
120
+
121
+ Checks: localized names/descriptions, review screenshots, submission readiness.
122
+
123
+ ### Full ASC Validation
124
+
125
+ Run all four validators at once:
126
+
127
+ ```bash
128
+ # Via MCP
129
+ full_asc_validation with bundleId "com.mycompany.myapp"
130
+ ```
131
+
132
+ Or via CLI:
133
+
134
+ ```bash
135
+ ios-app-review scan ./MyApp.xcodeproj --include-asc
136
+ ```
137
+
138
+ ## Step 5: Understand ASC Results
139
+
140
+ ASC issues use these categories:
141
+
142
+ | Category | Validator |
143
+ |----------|-----------|
144
+ | `metadata` | asc-metadata |
145
+ | `screenshots` | asc-screenshots |
146
+ | `version` | asc-version |
147
+ | `iap` | asc-iap |
148
+
149
+ Common findings:
150
+
151
+ - **Missing privacy policy URL** -- Required for all apps. Add in App Store Connect > App Information.
152
+ - **App name too long** -- Must be 30 characters or fewer.
153
+ - **Missing screenshots for device** -- iPhone 6.7" and 6.5" are required. iPad 12.9" if supporting iPad.
154
+ - **Failed screenshot uploads** -- Re-upload screenshots that show "processing failed" status.
155
+ - **Version not incremented** -- The new version must be higher than the current App Store version.
156
+ - **IAP missing review screenshot** -- Each IAP needs a screenshot for Apple's review team.
157
+ - **IAP missing localization** -- Name and description must be provided in at least one language.
158
+
159
+ ## Troubleshooting
160
+
161
+ ### "401 Unauthorized"
162
+
163
+ - Verify the Key ID matches the downloaded key.
164
+ - Verify the Issuer ID (shown at the top of the Keys page, not per-key).
165
+ - Regenerate the key if it was revoked.
166
+ - Check system clock accuracy (JWT tokens are time-sensitive).
167
+
168
+ ### "404 Not Found" for bundle ID
169
+
170
+ - The bundle ID is case-sensitive.
171
+ - The app must exist in your ASC account.
172
+ - The API key must have access to the app (check team membership).
173
+
174
+ ### Rate Limiting
175
+
176
+ The ASC API has rate limits. The client handles retries automatically. If running in parallel CI jobs, stagger ASC checks or use a shared rate limiter.
177
+
178
+ ### Permission Errors
179
+
180
+ The API key needs at least **App Manager** role. **Developer** role is insufficient for reading all metadata.
181
+
182
+ ## Security Notes
183
+
184
+ - Never commit `.p8` files to version control.
185
+ - Add to `.gitignore`: `*.p8`, `AuthKey_*.p8`.
186
+ - Use CI secrets for all three credential values.
187
+ - The plugin generates short-lived JWT tokens (20-minute expiry) and does not persist credentials.
188
+ - Delete temp key files after CI runs: `rm /tmp/AuthKey.p8`.