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.
- package/.claude/settings.local.json +42 -0
- package/.github/actions/ios-review/action.yml +106 -0
- package/.github/workflows/ci.yml +103 -0
- package/.github/workflows/publish.yml +57 -0
- package/CHANGELOG.md +66 -0
- package/CONTRIBUTING.md +175 -0
- package/LICENSE +21 -0
- package/README.md +205 -0
- package/bitrise/step.sh +128 -0
- package/bitrise/step.yml +101 -0
- package/dist/analyzer.d.ts.map +1 -0
- package/dist/analyzers/asc-iap.d.ts.map +1 -0
- package/dist/analyzers/asc-metadata.d.ts.map +1 -0
- package/dist/analyzers/asc-screenshots.d.ts.map +1 -0
- package/dist/analyzers/asc-version.d.ts.map +1 -0
- package/dist/analyzers/code-scanner.d.ts.map +1 -0
- package/dist/analyzers/deprecated-api.d.ts.map +1 -0
- package/dist/analyzers/entitlements.d.ts.map +1 -0
- package/dist/analyzers/index.d.ts.map +1 -0
- package/dist/analyzers/info-plist.d.ts.map +1 -0
- package/dist/analyzers/privacy.d.ts.map +1 -0
- package/dist/analyzers/private-api.d.ts.map +1 -0
- package/dist/analyzers/security.d.ts.map +1 -0
- package/dist/analyzers/ui-ux.d.ts.map +1 -0
- package/dist/asc/auth.d.ts.map +1 -0
- package/dist/asc/client.d.ts.map +1 -0
- package/dist/asc/endpoints/apps.d.ts.map +1 -0
- package/dist/asc/endpoints/iap.d.ts.map +1 -0
- package/dist/asc/endpoints/screenshots.d.ts.map +1 -0
- package/dist/asc/endpoints/versions.d.ts.map +1 -0
- package/dist/asc/errors.d.ts.map +1 -0
- package/dist/asc/index.d.ts.map +1 -0
- package/dist/asc/types.d.ts.map +1 -0
- package/dist/badge/generator.d.ts.map +1 -0
- package/dist/badge/index.d.ts.map +1 -0
- package/dist/badge/types.d.ts.map +1 -0
- package/dist/cache/file-cache.d.ts.map +1 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/types.d.ts.map +1 -0
- package/dist/cli/commands/help.d.ts.map +1 -0
- package/dist/cli/commands/scan.d.ts.map +1 -0
- package/dist/cli/commands/version.d.ts.map +1 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/types.d.ts.map +1 -0
- package/dist/git/diff.d.ts.map +1 -0
- package/dist/git/index.d.ts.map +1 -0
- package/dist/git/types.d.ts.map +1 -0
- package/dist/guidelines/database.d.ts.map +1 -0
- package/dist/guidelines/index.d.ts.map +1 -0
- package/dist/guidelines/matcher.d.ts.map +1 -0
- package/dist/guidelines/types.d.ts.map +1 -0
- package/dist/history/comparator.d.ts.map +1 -0
- package/dist/history/index.d.ts.map +1 -0
- package/dist/history/store.d.ts.map +1 -0
- package/dist/history/types.d.ts.map +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +994 -0
- package/dist/parsers/index.d.ts.map +1 -0
- package/dist/parsers/plist.d.ts.map +1 -0
- package/dist/parsers/xcodeproj.d.ts.map +1 -0
- package/dist/progress/index.d.ts.map +1 -0
- package/dist/progress/reporter.d.ts.map +1 -0
- package/dist/progress/types.d.ts.map +1 -0
- package/dist/reports/html.d.ts.map +1 -0
- package/dist/reports/index.d.ts.map +1 -0
- package/dist/reports/json.d.ts.map +1 -0
- package/dist/reports/markdown.d.ts.map +1 -0
- package/dist/reports/types.d.ts.map +1 -0
- package/dist/rules/engine.d.ts.map +1 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/loader.d.ts.map +1 -0
- package/dist/rules/types.d.ts.map +1 -0
- package/dist/types/index.d.ts.map +1 -0
- package/docs/ANALYZERS.md +237 -0
- package/docs/API.md +308 -0
- package/docs/BADGES.md +130 -0
- package/docs/CI_CD.md +283 -0
- package/docs/CLI.md +140 -0
- package/docs/REPORTS.md +212 -0
- package/docs/ROADMAP.md +267 -0
- package/docs/RULES.md +182 -0
- package/docs/SECURITY.md +89 -0
- package/docs/TROUBLESHOOTING.md +227 -0
- package/docs/tutorials/ASC_SETUP.md +188 -0
- package/docs/tutorials/CI_INTEGRATION.md +292 -0
- package/docs/tutorials/CUSTOM_RULES.md +291 -0
- package/docs/tutorials/GETTING_STARTED.md +226 -0
- package/docs/video-scripts/01-introduction.md +106 -0
- package/docs/video-scripts/02-cli-usage.md +120 -0
- package/docs/video-scripts/03-ci-integration.md +198 -0
- package/eslint.config.js +33 -0
- package/examples/.ios-review-rules.json +82 -0
- package/examples/bitrise-workflow.yml +129 -0
- package/examples/fastlane-lane.rb +71 -0
- package/examples/github-action.yml +147 -0
- package/fastlane/Fastfile.example +114 -0
- package/fastlane/README.md +99 -0
- package/jest.config.js +36 -0
- package/package.json +65 -0
- package/scripts/benchmark.ts +112 -0
- package/scripts/debug-parser.ts +37 -0
- package/scripts/debug-pbxproj.ts +36 -0
- package/scripts/debug-specific.ts +47 -0
- package/scripts/test-analyze.ts +67 -0
- package/scripts/xcode-cloud-review.sh +167 -0
- package/src/analyzer.ts +227 -0
- package/src/analyzers/asc-iap.ts +300 -0
- package/src/analyzers/asc-metadata.ts +326 -0
- package/src/analyzers/asc-screenshots.ts +310 -0
- package/src/analyzers/asc-version.ts +368 -0
- package/src/analyzers/code-scanner.ts +408 -0
- package/src/analyzers/deprecated-api.ts +390 -0
- package/src/analyzers/entitlements.ts +345 -0
- package/src/analyzers/index.ts +12 -0
- package/src/analyzers/info-plist.ts +409 -0
- package/src/analyzers/privacy.ts +376 -0
- package/src/analyzers/private-api.ts +377 -0
- package/src/analyzers/security.ts +327 -0
- package/src/analyzers/ui-ux.ts +509 -0
- package/src/asc/auth.ts +204 -0
- package/src/asc/client.ts +258 -0
- package/src/asc/endpoints/apps.ts +115 -0
- package/src/asc/endpoints/iap.ts +171 -0
- package/src/asc/endpoints/screenshots.ts +164 -0
- package/src/asc/endpoints/versions.ts +174 -0
- package/src/asc/errors.ts +109 -0
- package/src/asc/index.ts +108 -0
- package/src/asc/types.ts +369 -0
- package/src/badge/generator.ts +48 -0
- package/src/badge/index.ts +2 -0
- package/src/badge/types.ts +5 -0
- package/src/cache/file-cache.ts +75 -0
- package/src/cache/index.ts +2 -0
- package/src/cache/types.ts +10 -0
- package/src/cli/commands/help.ts +41 -0
- package/src/cli/commands/scan.ts +44 -0
- package/src/cli/commands/version.ts +12 -0
- package/src/cli/index.ts +92 -0
- package/src/cli/types.ts +17 -0
- package/src/git/diff.ts +21 -0
- package/src/git/index.ts +2 -0
- package/src/git/types.ts +5 -0
- package/src/guidelines/database.ts +344 -0
- package/src/guidelines/index.ts +4 -0
- package/src/guidelines/matcher.ts +84 -0
- package/src/guidelines/types.ts +28 -0
- package/src/history/comparator.ts +114 -0
- package/src/history/index.ts +3 -0
- package/src/history/store.ts +135 -0
- package/src/history/types.ts +40 -0
- package/src/index.ts +1113 -0
- package/src/parsers/index.ts +3 -0
- package/src/parsers/plist.ts +253 -0
- package/src/parsers/xcodeproj.ts +265 -0
- package/src/progress/index.ts +2 -0
- package/src/progress/reporter.ts +65 -0
- package/src/progress/types.ts +9 -0
- package/src/reports/html.ts +322 -0
- package/src/reports/index.ts +20 -0
- package/src/reports/json.ts +92 -0
- package/src/reports/markdown.ts +187 -0
- package/src/reports/types.ts +26 -0
- package/src/rules/engine.ts +121 -0
- package/src/rules/index.ts +3 -0
- package/src/rules/loader.ts +83 -0
- package/src/rules/types.ts +25 -0
- package/src/types/index.ts +247 -0
- package/tests/analyzer.test.ts +142 -0
- package/tests/analyzers/asc-iap.test.ts +228 -0
- package/tests/analyzers/asc-metadata.test.ts +210 -0
- package/tests/analyzers/asc-screenshots.test.ts +135 -0
- package/tests/analyzers/asc-version.test.ts +259 -0
- package/tests/analyzers/code-scanner.test.ts +745 -0
- package/tests/analyzers/deprecated-api.test.ts +286 -0
- package/tests/analyzers/entitlements.test.ts +411 -0
- package/tests/analyzers/info-plist.test.ts +148 -0
- package/tests/analyzers/privacy.test.ts +623 -0
- package/tests/analyzers/private-api.test.ts +255 -0
- package/tests/analyzers/security.test.ts +300 -0
- package/tests/analyzers/ui-ux.test.ts +357 -0
- package/tests/asc/auth.test.ts +189 -0
- package/tests/asc/client.test.ts +207 -0
- package/tests/asc/endpoints.test.ts +1359 -0
- package/tests/badge/generator.test.ts +73 -0
- package/tests/cache/file-cache.test.ts +124 -0
- package/tests/cli/cli-index.test.ts +510 -0
- package/tests/cli/commands.test.ts +67 -0
- package/tests/cli/scan.test.ts +152 -0
- package/tests/git/diff.test.ts +69 -0
- package/tests/guidelines/matcher.test.ts +209 -0
- package/tests/history/comparator.test.ts +272 -0
- package/tests/history/store.test.ts +200 -0
- package/tests/integration/cli.test.ts +95 -0
- package/tests/integration/e2e.test.ts +130 -0
- package/tests/parsers/plist.test.ts +240 -0
- package/tests/parsers/xcodeproj.test.ts +289 -0
- package/tests/progress/reporter.test.ts +117 -0
- package/tests/reports/html.test.ts +176 -0
- package/tests/reports/json.test.ts +235 -0
- package/tests/reports/markdown.test.ts +196 -0
- package/tests/rules/engine.test.ts +229 -0
- package/tests/rules/loader.test.ts +187 -0
- package/tests/setup.ts +15 -0
- package/tsconfig.json +27 -0
- package/tsconfig.test.json +9 -0
package/docs/REPORTS.md
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# Report Formats
|
|
2
|
+
|
|
3
|
+
The plugin generates reports in three formats: Markdown, HTML, and JSON. All share the same underlying data -- an `EnrichedAnalysisReport` that includes a readiness score, enriched issues with guideline cross-references, and optional historical comparison.
|
|
4
|
+
|
|
5
|
+
## Markdown Format
|
|
6
|
+
|
|
7
|
+
Selected with `--format markdown` (the default).
|
|
8
|
+
|
|
9
|
+
### Structure
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
# App Store Review Readiness Report
|
|
13
|
+
|
|
14
|
+
**Project:** `/path/to/MyApp.xcodeproj`
|
|
15
|
+
**Date:** 1/15/2025, 3:42:00 PM
|
|
16
|
+
**Status:** ISSUES FOUND
|
|
17
|
+
|
|
18
|
+
## Review Readiness Score
|
|
19
|
+
|
|
20
|
+
**Score: 72/100** [=======---]
|
|
21
|
+
|
|
22
|
+
## Summary
|
|
23
|
+
|
|
24
|
+
| Metric | Count |
|
|
25
|
+
| ------ | ----- |
|
|
26
|
+
| Total Issues | 8 |
|
|
27
|
+
| Errors | 2 |
|
|
28
|
+
| Warnings | 4 |
|
|
29
|
+
| Info | 2 |
|
|
30
|
+
| Duration | 342ms |
|
|
31
|
+
|
|
32
|
+
## Historical Comparison <-- only if includeHistory=true
|
|
33
|
+
|
|
34
|
+
| Metric | Value |
|
|
35
|
+
| ------ | ----- |
|
|
36
|
+
| Previous Score | 65/100 |
|
|
37
|
+
| Current Score | 72/100 |
|
|
38
|
+
| Delta | +7 |
|
|
39
|
+
| Trend | Improving |
|
|
40
|
+
| New Issues | 1 |
|
|
41
|
+
| Resolved Issues | 3 |
|
|
42
|
+
| Ongoing Issues | 5 |
|
|
43
|
+
|
|
44
|
+
## Priority Remediation <-- only if errors exist
|
|
45
|
+
|
|
46
|
+
1. **Hardcoded API key** -- This appears to be a hardcoded API key or secret.
|
|
47
|
+
- Guideline: [Security Best Practice](https://...)
|
|
48
|
+
|
|
49
|
+
## Issues by Category
|
|
50
|
+
|
|
51
|
+
### Info.plist
|
|
52
|
+
|
|
53
|
+
#### [ERROR] Missing required key: CFBundleExecutable
|
|
54
|
+
...
|
|
55
|
+
|
|
56
|
+
### Code Quality
|
|
57
|
+
|
|
58
|
+
#### [WARN] Hardcoded IPv4 address
|
|
59
|
+
...
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Score Bar
|
|
63
|
+
|
|
64
|
+
The score bar is a 10-character ASCII gauge:
|
|
65
|
+
|
|
66
|
+
- Score 85 -> `[=========- ]`
|
|
67
|
+
- Score 50 -> `[=====-----]`
|
|
68
|
+
- Score 10 -> `[=---------]`
|
|
69
|
+
|
|
70
|
+
### Issue Rendering
|
|
71
|
+
|
|
72
|
+
Each issue includes:
|
|
73
|
+
- Severity badge: `[ERROR]`, `[WARN]`, or `[INFO]`
|
|
74
|
+
- Title and description
|
|
75
|
+
- File location (path:line) when available
|
|
76
|
+
- Guideline link when matched
|
|
77
|
+
- Suggestion when available
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## HTML Format
|
|
82
|
+
|
|
83
|
+
Selected with `--format html`.
|
|
84
|
+
|
|
85
|
+
### Features
|
|
86
|
+
|
|
87
|
+
- Self-contained single HTML file (no external CSS/JS)
|
|
88
|
+
- Dark mode support via `prefers-color-scheme` media query
|
|
89
|
+
- Circular score gauge with color coding (green >= 80, orange >= 50, red < 50)
|
|
90
|
+
- Collapsible issue categories using `<details>` elements
|
|
91
|
+
- Severity badges with color-coded pill labels
|
|
92
|
+
- Monospace font for file locations
|
|
93
|
+
- Trend arrows (SVG) for historical comparison
|
|
94
|
+
- Mobile responsive via viewport meta tag
|
|
95
|
+
|
|
96
|
+
### Color Scheme
|
|
97
|
+
|
|
98
|
+
| Element | Light Mode | Dark Mode |
|
|
99
|
+
|---------|------------|-----------|
|
|
100
|
+
| Background | `#ffffff` | `#1a1a2e` |
|
|
101
|
+
| Text | `#1a1a1a` | `#e0e0e0` |
|
|
102
|
+
| Card background | `#f8f9fa` | `#16213e` |
|
|
103
|
+
| Border | `#dee2e6` | `#2a2a4a` |
|
|
104
|
+
|
|
105
|
+
### Severity Badge Colors
|
|
106
|
+
|
|
107
|
+
| Severity | Color |
|
|
108
|
+
|----------|-------|
|
|
109
|
+
| error | `#dc3545` (red) |
|
|
110
|
+
| warning | `#fd7e14` (orange) |
|
|
111
|
+
| info | `#0d6efd` (blue) |
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## JSON Format
|
|
116
|
+
|
|
117
|
+
Selected with `--format json`.
|
|
118
|
+
|
|
119
|
+
### Schema
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"schemaVersion": "1.0",
|
|
124
|
+
"exitCode": 0,
|
|
125
|
+
"score": 85,
|
|
126
|
+
"timestamp": "2025-01-15T15:42:00.000Z",
|
|
127
|
+
"projectPath": "/path/to/MyApp.xcodeproj",
|
|
128
|
+
"summary": {
|
|
129
|
+
"totalIssues": 3,
|
|
130
|
+
"errors": 0,
|
|
131
|
+
"warnings": 2,
|
|
132
|
+
"info": 1,
|
|
133
|
+
"passed": true,
|
|
134
|
+
"duration": 342
|
|
135
|
+
},
|
|
136
|
+
"issues": [
|
|
137
|
+
{
|
|
138
|
+
"id": "hardcoded-ipv4",
|
|
139
|
+
"title": "Hardcoded IPv4 address",
|
|
140
|
+
"description": "Hardcoded IPv4 addresses may cause issues on IPv6-only networks.\n\nFound: `\"192.168.1.1\"`",
|
|
141
|
+
"severity": "warning",
|
|
142
|
+
"category": "code",
|
|
143
|
+
"filePath": "/path/to/NetworkManager.swift",
|
|
144
|
+
"lineNumber": 42,
|
|
145
|
+
"guideline": "Guideline 2.5.1 - IPv6 Compatibility",
|
|
146
|
+
"suggestion": "Use hostnames instead of hardcoded IP addresses for IPv6 compatibility.",
|
|
147
|
+
"guidelineUrl": "https://developer.apple.com/app-store/review/guidelines/#software-requirements",
|
|
148
|
+
"guidelineExcerpt": "Apps must use public APIs and run on the currently shipping OS...",
|
|
149
|
+
"severityScore": 9
|
|
150
|
+
}
|
|
151
|
+
],
|
|
152
|
+
"comparison": {
|
|
153
|
+
"previousScanId": "abc123",
|
|
154
|
+
"previousTimestamp": "2025-01-10T11:20:00.000Z",
|
|
155
|
+
"previousScore": 72,
|
|
156
|
+
"currentScore": 85,
|
|
157
|
+
"scoreDelta": 13,
|
|
158
|
+
"trend": "improving",
|
|
159
|
+
"newIssuesCount": 0,
|
|
160
|
+
"resolvedIssuesCount": 3,
|
|
161
|
+
"ongoingIssuesCount": 2
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Field Reference
|
|
167
|
+
|
|
168
|
+
**Top level:**
|
|
169
|
+
|
|
170
|
+
| Field | Type | Description |
|
|
171
|
+
|-------|------|-------------|
|
|
172
|
+
| `schemaVersion` | string | Always `"1.0"` |
|
|
173
|
+
| `exitCode` | 0 or 1 | 0 if passed, 1 if errors exist |
|
|
174
|
+
| `score` | number | 0-100 review readiness score |
|
|
175
|
+
| `timestamp` | string | ISO 8601 timestamp |
|
|
176
|
+
| `projectPath` | string | Analyzed project path |
|
|
177
|
+
| `summary` | object | Aggregate counts |
|
|
178
|
+
| `issues` | array | All enriched issues |
|
|
179
|
+
| `comparison` | object or undefined | Present only when history is included |
|
|
180
|
+
|
|
181
|
+
**Issue object:**
|
|
182
|
+
|
|
183
|
+
| Field | Type | Present |
|
|
184
|
+
|-------|------|---------|
|
|
185
|
+
| `id` | string | always |
|
|
186
|
+
| `title` | string | always |
|
|
187
|
+
| `description` | string | always |
|
|
188
|
+
| `severity` | `"error"` / `"warning"` / `"info"` | always |
|
|
189
|
+
| `category` | string | always |
|
|
190
|
+
| `filePath` | string | when applicable |
|
|
191
|
+
| `lineNumber` | number | when applicable |
|
|
192
|
+
| `guideline` | string | when matched |
|
|
193
|
+
| `suggestion` | string | when available |
|
|
194
|
+
| `guidelineUrl` | string | when matched by GuidelineMatcher |
|
|
195
|
+
| `guidelineExcerpt` | string | when matched |
|
|
196
|
+
| `severityScore` | number | when matched (0-10) |
|
|
197
|
+
|
|
198
|
+
### Parsing in CI
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
# Check pass/fail
|
|
202
|
+
PASSED=$(cat report.json | jq '.summary.passed')
|
|
203
|
+
|
|
204
|
+
# Count errors
|
|
205
|
+
ERRORS=$(cat report.json | jq '.summary.errors')
|
|
206
|
+
|
|
207
|
+
# Get score
|
|
208
|
+
SCORE=$(cat report.json | jq '.score')
|
|
209
|
+
|
|
210
|
+
# List error-severity issue titles
|
|
211
|
+
cat report.json | jq -r '.issues[] | select(.severity == "error") | .title'
|
|
212
|
+
```
|
package/docs/ROADMAP.md
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
# Project Roadmap
|
|
2
|
+
|
|
3
|
+
This document outlines the development phases, milestones, and detailed tasks for the iOS App Store Review Plugin.
|
|
4
|
+
|
|
5
|
+
## Phase 1: Foundation & Codebase Analysis (MVP) :white_check_mark:
|
|
6
|
+
|
|
7
|
+
**Goal**: Create a working MCP server that can analyze iOS project files locally without requiring App Store Connect access.
|
|
8
|
+
|
|
9
|
+
**Milestone**: `v0.1.0 - MVP Release`
|
|
10
|
+
|
|
11
|
+
### 1.1 Project Setup
|
|
12
|
+
- [x] Initialize TypeScript project with strict configuration
|
|
13
|
+
- [x] Set up ESLint and Prettier
|
|
14
|
+
- [x] Configure Jest for testing
|
|
15
|
+
- [x] Set up build pipeline
|
|
16
|
+
- [x] Create MCP server skeleton
|
|
17
|
+
- [x] Add GitHub Actions for CI/CD
|
|
18
|
+
|
|
19
|
+
### 1.2 Xcode Project Parser
|
|
20
|
+
- [x] Parse `.xcodeproj` directory structure
|
|
21
|
+
- [x] Extract build settings
|
|
22
|
+
- [x] Identify targets and schemes
|
|
23
|
+
- [x] Parse `Info.plist` files
|
|
24
|
+
- [x] Parse entitlements files
|
|
25
|
+
- [x] Handle workspace (`.xcworkspace`) files
|
|
26
|
+
|
|
27
|
+
### 1.3 Info.plist Analyzer
|
|
28
|
+
- [x] Check required keys (bundle identifier, version, etc.)
|
|
29
|
+
- [x] Validate privacy usage descriptions:
|
|
30
|
+
- NSCameraUsageDescription
|
|
31
|
+
- NSPhotoLibraryUsageDescription
|
|
32
|
+
- NSLocationWhenInUseUsageDescription
|
|
33
|
+
- NSMicrophoneUsageDescription
|
|
34
|
+
- NSContactsUsageDescription
|
|
35
|
+
- (20+ more privacy keys)
|
|
36
|
+
- [x] Check App Transport Security configuration
|
|
37
|
+
- [x] Validate URL schemes
|
|
38
|
+
- [x] Check required device capabilities
|
|
39
|
+
- [x] Verify launch storyboard/XIB configuration
|
|
40
|
+
|
|
41
|
+
### 1.4 Privacy Manifest Analyzer (iOS 17+)
|
|
42
|
+
- [x] Check for `PrivacyInfo.xcprivacy` presence
|
|
43
|
+
- [x] Validate required reason APIs:
|
|
44
|
+
- File timestamp APIs
|
|
45
|
+
- System boot time APIs
|
|
46
|
+
- Disk space APIs
|
|
47
|
+
- Active keyboard APIs
|
|
48
|
+
- User defaults APIs
|
|
49
|
+
- [x] Check tracking domains declaration
|
|
50
|
+
- [x] Validate data collection declarations
|
|
51
|
+
- [x] Cross-reference with actual API usage in code
|
|
52
|
+
|
|
53
|
+
### 1.5 Entitlements Analyzer
|
|
54
|
+
- [x] Parse entitlements file
|
|
55
|
+
- [x] Validate against declared capabilities
|
|
56
|
+
- [x] Check for debugging entitlements in release
|
|
57
|
+
- [x] Validate App Groups configuration
|
|
58
|
+
- [x] Check Push Notification entitlements
|
|
59
|
+
- [x] Validate Keychain sharing groups
|
|
60
|
+
|
|
61
|
+
### 1.6 Basic Code Scanner
|
|
62
|
+
- [x] Detect hardcoded IP addresses (IPv6 compliance)
|
|
63
|
+
- [x] Find TODO/FIXME comments
|
|
64
|
+
- [x] Detect hardcoded API keys/secrets
|
|
65
|
+
- [x] Find test/debug code patterns
|
|
66
|
+
- [x] Check for `#if DEBUG` usage
|
|
67
|
+
- [x] Detect print/NSLog statements in release
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Phase 2: App Store Connect Integration :white_check_mark:
|
|
72
|
+
|
|
73
|
+
**Goal**: Add ability to fetch and validate app metadata from App Store Connect.
|
|
74
|
+
|
|
75
|
+
**Milestone**: `v0.2.0 - ASC Integration`
|
|
76
|
+
|
|
77
|
+
### 2.1 API Client Setup
|
|
78
|
+
- [x] Implement JWT authentication
|
|
79
|
+
- [x] Create API client with rate limiting
|
|
80
|
+
- [x] Handle token refresh
|
|
81
|
+
- [x] Add error handling and retries
|
|
82
|
+
- [x] Create typed API responses
|
|
83
|
+
|
|
84
|
+
### 2.2 App Metadata Validation
|
|
85
|
+
- [x] Fetch app information
|
|
86
|
+
- [x] Validate app name length (30 chars)
|
|
87
|
+
- [x] Check subtitle (30 chars)
|
|
88
|
+
- [x] Validate description length and content
|
|
89
|
+
- [x] Check keywords (100 chars total)
|
|
90
|
+
- [x] Validate promotional text
|
|
91
|
+
- [x] Check support URL validity
|
|
92
|
+
- [x] Validate privacy policy URL
|
|
93
|
+
- [x] Verify marketing URL
|
|
94
|
+
|
|
95
|
+
### 2.3 Screenshot & Preview Validation
|
|
96
|
+
- [x] Fetch screenshot metadata
|
|
97
|
+
- [x] Check required device sizes
|
|
98
|
+
- [x] Validate screenshot count (1-10 per size)
|
|
99
|
+
- [x] Check app preview videos
|
|
100
|
+
- [x] Verify localized screenshots
|
|
101
|
+
|
|
102
|
+
### 2.4 Version & Build Checks
|
|
103
|
+
- [x] Compare local vs. submitted version
|
|
104
|
+
- [x] Check build number incrementing
|
|
105
|
+
- [x] Validate version string format
|
|
106
|
+
- [x] Check for pending submissions
|
|
107
|
+
|
|
108
|
+
### 2.5 In-App Purchase Validation
|
|
109
|
+
- [x] List configured IAPs
|
|
110
|
+
- [x] Validate IAP metadata
|
|
111
|
+
- [x] Check pricing configuration
|
|
112
|
+
- [x] Verify review screenshots for IAPs
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Phase 3: Advanced Analysis :white_check_mark:
|
|
117
|
+
|
|
118
|
+
**Goal**: Add sophisticated analysis capabilities and better integration.
|
|
119
|
+
|
|
120
|
+
**Milestone**: `v0.3.0 - Advanced Analysis`
|
|
121
|
+
|
|
122
|
+
### 3.1 Deprecated API Detection
|
|
123
|
+
- [x] Build deprecated API database
|
|
124
|
+
- [x] Scan Swift files for deprecated calls
|
|
125
|
+
- [x] Scan Objective-C files
|
|
126
|
+
- [x] Check minimum deployment target compatibility
|
|
127
|
+
- [x] Identify APIs removed in target iOS version
|
|
128
|
+
- [x] Generate migration suggestions
|
|
129
|
+
|
|
130
|
+
### 3.2 Private API Detection
|
|
131
|
+
- [x] Create private API signature database
|
|
132
|
+
- [x] Scan for known private selectors
|
|
133
|
+
- [x] Check for undocumented frameworks
|
|
134
|
+
- [x] Detect runtime API usage
|
|
135
|
+
- [x] Scan for private URL schemes
|
|
136
|
+
|
|
137
|
+
### 3.3 Security Analysis
|
|
138
|
+
- [x] Check for insecure HTTP connections
|
|
139
|
+
- [x] Detect weak cryptography usage
|
|
140
|
+
- [x] Find insecure data storage patterns
|
|
141
|
+
- [x] Check for jailbreak detection bypasses
|
|
142
|
+
- [x] Validate SSL pinning implementation
|
|
143
|
+
- [x] Check keychain access configuration
|
|
144
|
+
|
|
145
|
+
### 3.4 UI/UX Compliance
|
|
146
|
+
- [x] Check for required launch screen
|
|
147
|
+
- [x] Validate icon sizes and presence
|
|
148
|
+
- [x] Check accessibility support
|
|
149
|
+
- [x] Detect placeholder/lorem ipsum text
|
|
150
|
+
- [x] Verify iPad support if universal
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Phase 4: Intelligence & Reporting :white_check_mark:
|
|
155
|
+
|
|
156
|
+
**Goal**: Add smart analysis and comprehensive reporting.
|
|
157
|
+
|
|
158
|
+
**Milestone**: `v0.4.0 - Smart Analysis`
|
|
159
|
+
|
|
160
|
+
### 4.1 Guidelines Cross-Reference
|
|
161
|
+
- [x] Map issues to specific guidelines
|
|
162
|
+
- [x] Provide guideline excerpts
|
|
163
|
+
- [x] Link to Apple documentation
|
|
164
|
+
- [x] Track guideline version changes
|
|
165
|
+
- [x] Add severity scoring
|
|
166
|
+
|
|
167
|
+
### 4.2 Report Generation
|
|
168
|
+
- [x] Generate markdown reports
|
|
169
|
+
- [x] Create HTML reports
|
|
170
|
+
- [x] Add JSON export for CI/CD
|
|
171
|
+
- [x] Include remediation suggestions
|
|
172
|
+
- [x] Add code location references
|
|
173
|
+
- [x] Generate summary statistics
|
|
174
|
+
|
|
175
|
+
### 4.3 Historical Comparison
|
|
176
|
+
- [x] Store previous scan results
|
|
177
|
+
- [x] Compare between scans
|
|
178
|
+
- [x] Track issue resolution
|
|
179
|
+
- [x] Generate trend reports
|
|
180
|
+
|
|
181
|
+
### 4.4 Custom Rules
|
|
182
|
+
- [x] Allow user-defined rules
|
|
183
|
+
- [x] Support regex-based rules
|
|
184
|
+
- [x] Add rule severity configuration
|
|
185
|
+
- [x] Create rule disable comments
|
|
186
|
+
- [x] Support per-project configuration
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Phase 5: CI/CD & Polish :white_check_mark:
|
|
191
|
+
|
|
192
|
+
**Goal**: Production-ready release with CI/CD integration.
|
|
193
|
+
|
|
194
|
+
**Milestone**: `v1.0.0 - Production Release`
|
|
195
|
+
|
|
196
|
+
### 5.1 CI/CD Integration
|
|
197
|
+
- [x] Create GitHub Action
|
|
198
|
+
- [x] Add Fastlane plugin
|
|
199
|
+
- [x] Create Xcode Cloud integration guide
|
|
200
|
+
- [x] Add Bitrise step
|
|
201
|
+
- [x] Support exit codes for CI
|
|
202
|
+
- [x] Create badge generation
|
|
203
|
+
|
|
204
|
+
### 5.2 Performance Optimization
|
|
205
|
+
- [x] Add caching layer
|
|
206
|
+
- [x] Implement incremental scanning
|
|
207
|
+
- [x] Optimize large project handling
|
|
208
|
+
- [x] Add progress reporting
|
|
209
|
+
- [x] Implement parallel analysis
|
|
210
|
+
|
|
211
|
+
### 5.3 Documentation
|
|
212
|
+
- [x] Complete API documentation
|
|
213
|
+
- [x] Add video tutorials
|
|
214
|
+
- [x] Create troubleshooting guide
|
|
215
|
+
- [x] Document all rules
|
|
216
|
+
- [x] Add example configurations
|
|
217
|
+
|
|
218
|
+
### 5.4 Testing & Quality
|
|
219
|
+
- [x] Achieve 80%+ code coverage
|
|
220
|
+
- [x] Add integration tests
|
|
221
|
+
- [x] Test with real-world projects
|
|
222
|
+
- [x] Security audit
|
|
223
|
+
- [x] Performance benchmarks
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Future Considerations
|
|
228
|
+
|
|
229
|
+
### Potential Phase 6+ Features
|
|
230
|
+
- [ ] Watch app analysis
|
|
231
|
+
- [ ] tvOS app support
|
|
232
|
+
- [ ] macOS (Catalyst) support
|
|
233
|
+
- [ ] App Clips validation
|
|
234
|
+
- [ ] SwiftUI-specific checks
|
|
235
|
+
- [ ] Storyboard/XIB analysis
|
|
236
|
+
- [ ] Localization validation
|
|
237
|
+
- [ ] Accessibility audit
|
|
238
|
+
- [ ] Memory/performance predictions
|
|
239
|
+
- [ ] AI-powered rejection prediction
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## Success Metrics
|
|
244
|
+
|
|
245
|
+
| Metric | Target |
|
|
246
|
+
|--------|--------|
|
|
247
|
+
| Detection accuracy | >95% for common issues |
|
|
248
|
+
| False positive rate | <5% |
|
|
249
|
+
| Scan time (avg project) | <30 seconds |
|
|
250
|
+
| Guideline coverage | 80% of rejection reasons |
|
|
251
|
+
| User satisfaction | 4.5+ rating |
|
|
252
|
+
|
|
253
|
+
## Timeline Estimates
|
|
254
|
+
|
|
255
|
+
| Phase | Duration |
|
|
256
|
+
|-------|----------|
|
|
257
|
+
| Phase 1 | 4-6 weeks |
|
|
258
|
+
| Phase 2 | 3-4 weeks |
|
|
259
|
+
| Phase 3 | 4-5 weeks |
|
|
260
|
+
| Phase 4 | 3-4 weeks |
|
|
261
|
+
| Phase 5 | 2-3 weeks |
|
|
262
|
+
|
|
263
|
+
**Total estimated development time**: 16-22 weeks
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
*This roadmap is subject to change based on community feedback and Apple's guideline updates.*
|
package/docs/RULES.md
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# Custom Rules
|
|
2
|
+
|
|
3
|
+
Create a `.ios-review-rules.json` file in your project root (or any parent directory) to define team-specific or project-specific rules.
|
|
4
|
+
|
|
5
|
+
## Config Format
|
|
6
|
+
|
|
7
|
+
```json
|
|
8
|
+
{
|
|
9
|
+
"version": 1,
|
|
10
|
+
"rules": [
|
|
11
|
+
{
|
|
12
|
+
"id": "my-rule-id",
|
|
13
|
+
"title": "Short title",
|
|
14
|
+
"description": "Longer description shown in reports",
|
|
15
|
+
"severity": "error",
|
|
16
|
+
"pattern": "regex-pattern-string",
|
|
17
|
+
"flags": "gi",
|
|
18
|
+
"fileTypes": [".swift"],
|
|
19
|
+
"guideline": "Guideline 2.5.4",
|
|
20
|
+
"suggestion": "How to fix this",
|
|
21
|
+
"category": "custom"
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
"disabledRules": ["built-in-rule-id"],
|
|
25
|
+
"severityOverrides": {
|
|
26
|
+
"hardcoded-ipv4": "error"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Top-level Fields
|
|
32
|
+
|
|
33
|
+
| Field | Type | Required | Description |
|
|
34
|
+
|-------|------|----------|-------------|
|
|
35
|
+
| `version` | `1` (literal) | yes | Schema version. Must be `1`. |
|
|
36
|
+
| `rules` | array | yes | Custom rule definitions. |
|
|
37
|
+
| `disabledRules` | string[] | no | IDs of rules to skip (built-in or custom). |
|
|
38
|
+
| `severityOverrides` | object | no | Override severity for any rule by ID. Keys are rule IDs, values are `"error"`, `"warning"`, or `"info"`. |
|
|
39
|
+
|
|
40
|
+
### Rule Fields
|
|
41
|
+
|
|
42
|
+
| Field | Type | Required | Description |
|
|
43
|
+
|-------|------|----------|-------------|
|
|
44
|
+
| `id` | string | yes | Unique identifier (e.g., `team-no-force-cast`). |
|
|
45
|
+
| `title` | string | yes | Short title for reports. |
|
|
46
|
+
| `description` | string | yes | Detailed description shown in issue output. |
|
|
47
|
+
| `severity` | string | yes | One of `error`, `warning`, `info`. |
|
|
48
|
+
| `pattern` | string | yes | JavaScript regex pattern (without delimiters). |
|
|
49
|
+
| `flags` | string | no | Regex flags. Default: `"g"`. Use `"gi"` for case-insensitive. |
|
|
50
|
+
| `fileTypes` | string[] | no | File extensions to scan (e.g., `[".swift", ".m"]`). Default: all source files. |
|
|
51
|
+
| `guideline` | string | no | Related App Store guideline reference. |
|
|
52
|
+
| `suggestion` | string | no | Remediation guidance. |
|
|
53
|
+
| `category` | string | no | Issue category. Default: `"custom"`. |
|
|
54
|
+
|
|
55
|
+
## Pattern Syntax
|
|
56
|
+
|
|
57
|
+
Patterns use JavaScript `RegExp` syntax. Common examples:
|
|
58
|
+
|
|
59
|
+
| Pattern | Matches |
|
|
60
|
+
|---------|---------|
|
|
61
|
+
| `\\bUIWebView\\b` | Word-boundary match for `UIWebView` |
|
|
62
|
+
| `print\\s*\\(` | `print(` calls |
|
|
63
|
+
| `["'\`]http://[^"'\`]+["'\`]` | HTTP URLs in string literals |
|
|
64
|
+
| `\\bTODO\\b` | TODO markers |
|
|
65
|
+
| `force_cast` | Literal string `force_cast` |
|
|
66
|
+
|
|
67
|
+
Backslashes must be double-escaped in JSON (`\\b` for `\b`).
|
|
68
|
+
|
|
69
|
+
When the `g` flag is present, the engine finds all matches in each file. Without `g`, it reports only the first match per file.
|
|
70
|
+
|
|
71
|
+
## Inline Suppression
|
|
72
|
+
|
|
73
|
+
Suppress a specific rule on the next line with a comment:
|
|
74
|
+
|
|
75
|
+
```swift
|
|
76
|
+
// ios-review-disable-next-line my-rule-id
|
|
77
|
+
let x = unsafeOperation() // this line won't trigger my-rule-id
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Multiple rule IDs can be comma-separated:
|
|
81
|
+
|
|
82
|
+
```swift
|
|
83
|
+
// ios-review-disable-next-line my-rule-id, another-rule
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Disabling Built-in Rules
|
|
87
|
+
|
|
88
|
+
Use `disabledRules` to turn off any built-in rule by its ID:
|
|
89
|
+
|
|
90
|
+
```json
|
|
91
|
+
{
|
|
92
|
+
"version": 1,
|
|
93
|
+
"rules": [],
|
|
94
|
+
"disabledRules": [
|
|
95
|
+
"print-statement",
|
|
96
|
+
"todo-comment",
|
|
97
|
+
"force-unwrap"
|
|
98
|
+
]
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Severity Overrides
|
|
103
|
+
|
|
104
|
+
Promote or demote any rule (built-in or custom):
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
{
|
|
108
|
+
"version": 1,
|
|
109
|
+
"rules": [],
|
|
110
|
+
"severityOverrides": {
|
|
111
|
+
"hardcoded-ipv4": "error",
|
|
112
|
+
"placeholder-text": "info"
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Complete Example
|
|
118
|
+
|
|
119
|
+
```json
|
|
120
|
+
{
|
|
121
|
+
"version": 1,
|
|
122
|
+
"rules": [
|
|
123
|
+
{
|
|
124
|
+
"id": "team-no-swiftui-preview",
|
|
125
|
+
"title": "SwiftUI preview in production code",
|
|
126
|
+
"description": "SwiftUI #Preview macros should only appear in dedicated preview files.",
|
|
127
|
+
"severity": "warning",
|
|
128
|
+
"pattern": "#Preview\\s*\\{",
|
|
129
|
+
"flags": "g",
|
|
130
|
+
"fileTypes": [".swift"],
|
|
131
|
+
"suggestion": "Move #Preview blocks to separate preview files or wrap in #if DEBUG."
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
"id": "team-no-print-release",
|
|
135
|
+
"title": "Print statement in non-debug code",
|
|
136
|
+
"description": "Use os_log or Logger instead of print() for production logging.",
|
|
137
|
+
"severity": "error",
|
|
138
|
+
"pattern": "\\bprint\\s*\\(",
|
|
139
|
+
"flags": "g",
|
|
140
|
+
"fileTypes": [".swift"],
|
|
141
|
+
"suggestion": "Replace print() with Logger from the os module."
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"id": "team-copyright-header",
|
|
145
|
+
"title": "Missing copyright header",
|
|
146
|
+
"description": "All source files must include the team copyright header.",
|
|
147
|
+
"severity": "info",
|
|
148
|
+
"pattern": "^(?!.*Copyright.*ACME Corp)",
|
|
149
|
+
"flags": "",
|
|
150
|
+
"fileTypes": [".swift"],
|
|
151
|
+
"suggestion": "Add '// Copyright ACME Corp' to the top of the file."
|
|
152
|
+
}
|
|
153
|
+
],
|
|
154
|
+
"disabledRules": ["force-unwrap"],
|
|
155
|
+
"severityOverrides": {
|
|
156
|
+
"insecure-http": "error"
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Validating Rules
|
|
162
|
+
|
|
163
|
+
Use the `validate_custom_rules` MCP tool or verify manually:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
# The tool will parse, compile, and report any errors
|
|
167
|
+
# in the rules file without running a full scan.
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
From Claude Code, ask:
|
|
171
|
+
|
|
172
|
+
```
|
|
173
|
+
Validate my custom rules at ./MyApp.xcodeproj
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
The tool will report the config path, version, rule count, compiled regex patterns, and whether validation passed.
|
|
177
|
+
|
|
178
|
+
## Scanned File Types
|
|
179
|
+
|
|
180
|
+
The custom rules engine scans files with these extensions by default: `.swift`, `.m`, `.mm`, `.h`, `.c`, `.cpp`. Narrow this per-rule with the `fileTypes` field.
|
|
181
|
+
|
|
182
|
+
Directories excluded: `node_modules`, `Pods`, `build`, `.build`.
|