# FuelBoard App Store Submission Plan Updated: 2026-08-16 · Target: safe App Store submission. Companion to SECURITY.md (code security) — this file is the *review-gate* checklist: what must happen, who owns it, and the timeline. ## Status: SUBMITTABLE after the checklist below The two 2026-08-11 blockers are RESOLVED by P0 (live chain): - ~~LAN relay data source~~ → **app fetches from public HTTPS (raw.githubusercontent.com mirror) with a bundled real 8,022-station dump as the no-network fallback.** No private IP in the consumer path. Reviewers on Apple's network see real data. - ~~Always-location risk~~ → **Always is requested only when the user enables Alerts** (ProximityMonitor escalates WhenInUse → Always on alert opt-in). Onboarding requests WhenInUse only. ## Hard blockers (must happen before ANY submission) 1. **[USER] Apple Developer Program membership** — the app has never been signed (all builds are `CODE_SIGNING_ALLOWED=NO` + ad-hoc re-sign for SideStore). Requires a paid membership ($99/yr, up to 48 h to approve) and a developer account. 2. **[USER] Register App ID `com.apt.fuelboard`** in the developer portal, with the **App Group `group.com.apt.fuelboard`** capability AND the **In-App Purchase** capability enabled (the widget + app-group cache depend on the group; the tip jar needs IAP). 3. ~~[ME] `PrivacyInfo.xcprivacy`~~ — **DONE 2026-08-16** (app + widget manifests added; UserDefaults `1C8F.1`, Location + Diagnostics declared). 4. **[ME] Real Distribution signing** — Distribution certificate + App Store provisioning profile (or Xcode automatic signing once the account is in Xcode); then `xcodebuild archive` (no more `CODE_SIGNING_ALLOWED=NO`). 5. **[USER] Privacy policy URL** in App Store Connect — mandatory; the app collects location. A one-page GitHub Pages privacy policy is fine. ## Required tasks — owner [ME] (technical, do after account exists) - [x] **PrivacyInfo.xcprivacy** — app + widget manifests added (2026-08-16): UserDefaults reason `1C8F.1`; app also declares Location (linked, not tracking) + Diagnostics (not linked, not tracking — the dev beacon) - [ ] Distribution archive + TestFlight upload (needs Apple account) - [x] **Version bump** → `1.0.1` (build 2), app + widget plists - [x] **OGL attribution** — Settings → Data source footer now reads "Prices use the UK Fuel Finder dataset (Open Government Licence) and refresh up to twice a day." (2.3.1 hygiene) - [x] **Out-of-UK empty state** — "No X stations within N miles" + UK-only explainer + "Browse all UK stations" button (switches to Closest) - [ ] ~~Gate dev surface behind #if DEBUG~~ **DECLINED — kept in Release on purpose**: the user's home-testing installs the Release IPA and toggles `fuelboard.relayFallback` via Settings → Debug (revealed only by tapping About → Version ×5 — invisible to reviewers; no credentials involved). Gating it out of Release would break that workflow for zero review gain. - [ ] Final pass: `swift test` green (95 tests), archive smoke test on device - [ ] ~~Capture screenshots from simulator~~ **RAW CAPTURES DONE (2026-08-16)** — native 6.9″ 1320×2868 PNGs of all four tabs (Stations, Favourites, Alerts, Settings) at `/tmp/fuelboard-shots/asc/`; assembled into ASC frames by the user in the yuzu-hub App Store Screenshot Generator (https://yuzu-hub.github.io/appscreen/). Screenshot harness: launch args `-skipOnboarding` / `-tab stations|favourites|alerts|settings` (ContentView, same pattern as `-showKeySheet`). ## Required tasks — owner [USER] (App Store Connect, cannot be done by me) - [ ] Apple Developer Program membership + App ID (blockers #1–#2) - [ ] **Tip jar: create the three consumable IAPs** in App Store Connect → In-App Purchases (all type **Consumable**, exact product IDs, UK price tier; tip jars are an accepted App Review pattern): - `com.apt.fuelboard.tip099` — **£0.99** — "Splash & Dash" (Just enough to keep things moving.) - `com.apt.fuelboard.tip299` — **£2.99** — "Half a Tank" (A generous top-up for development.) - `com.apt.fuelboard.tip499` — **£4.99** — "Fill 'Er Up" (Keeping the app on the road.) App-side is ready (`41e4c91`): Settings → Support FuelBoard shows all three tiers with per-tier prices; sideloaded builds gracefully show "not available in this build yet" until the products exist. - [ ] App Store Connect app record: name, bundle ID `com.apt.fuelboard`, category (Utilities), pricing (Free), availability (UK first?) - [ ] Description, keywords, support URL, marketing URL, privacy policy URL - [ ] Privacy nutrition labels questionnaire (location: yes, linked to user for alerts/nearby; diagnostics: yes — the widget-diag beacon, not linked, not used for tracking; no ATT prompt needed) - [ ] Age rating questionnaire (4+; no objectionable content) - [ ] Export compliance: HTTPS-only + keychain → standard encryption exemption (5A992a), no documentation needed - [ ] Approve the TestFlight build and do a real-device pass before submit - [ ] Final "Submit for Review" click + stand by to answer review questions ## Review notes (copy-paste into App Store Connect) > FuelBoard shows the cheapest petrol, diesel, and premium fuel near the user > using the UK government Fuel Finder dataset (Open Government Licence). > Prices are downloaded from the internet up to twice a day; the app filters > 5/10/15-mile radii on-device and works offline from a bundled snapshot. > Location is used to (a) rank stations by distance and (b) power the > optional Alerts feature: when the user enables alerts, the app geofences > the cheapest station in their radius and sends a notification when they > approach it. Always-location is requested only when the user enables > alerts. The app also provides a home-screen widget showing the current > cheapest station nearby, and a price-history Trends chart for starred > stations. All data is UK-wide (Fuel Finder covers England, Scotland, Wales > and Northern Ireland); users outside the UK see an empty state explaining > this. ## Review risks (know before submitting) - **Always-location (5.1.1)** — the #1 question. The feature is visible (Alerts tab) and opt-in; the review notes above say so explicitly. - **Reviewer outside the UK** — empty radius; mitigated by the empty-state task above + review notes. - **"Cheapest" claims (2.3.1)** — mitigated by the OGL/footnote task. - **Live Activities** — reviewers may ask why; answer: price alerts at a glance. It is declared in the plist already. - **Brand logos (Shell, BP, Tesco…)** — Simple Icons (CC0) + Wikimedia, nominative use (cf. GasBuddy); low risk, keep sources documented. - **GitHub raw as data source** — public data, no credentials; bundled dump covers any regional GitHub unreachability. ## Timeline (best case) | Day | Owner | Milestone | |-----|-------|-----------| | 0–2 | USER | Developer Program enrollment + App ID + app group capability | | 2–3 | ME | Signing (automatic), PrivacyInfo.xcprivacy, attribution, empty state, version bump | | 3–4 | ME | Archive → TestFlight; screenshots captured | | 4–5 | USER | TestFlight install + real-device pass (onboarding, alerts, widget, offline) | | 5–6 | USER | App Store Connect metadata + labels + age rating + privacy URL | | 6–7 | USER/ME | Submit for review | | 7–14 | Apple | Review (typically 1–3 days, can be a week); answer questions same-day | Rollback note: nothing about submission changes the repo's rollback posture (`main` history is intact; release builds are tagged per submission).