← back to dashboard

places — Fix-Ready Issue

_Regenerated 2026-08-04. Sources: state/asc.json and state/asc-review.json (both generated 2026-08-03T19:15:04Z), state/asc-live.json (reports "places": false — not live), state/fleet.json, and app source at /Users/zzxwill/Programming/go/src/zzxwill/apple-apps/apps/places/. Doctor diagnosis: Not auto-healing (fixable=false, autoHeal=true). Verify verdict: {"app":"places","isRealFix":false,"confidence":"high","reasoning":"No fix attempted","risks":""}. All file/line citations below were re-verified against working-tree source on 2026-08-04._

Status

UNHEALTHY — version 1.0 is REJECTED / UNRESOLVED_ISSUES (Guideline 2.1 information request) with an expired build attached, and it was not auto-healed because the doctor classified it fixable=false: both blockers require human actions in the App Store Connect console (select a build, reply in Resolution Center, record a device video), not a code patch the healer could apply — so no fix was ever attempted.


Root Cause & Evidence

Two blocking error checks on the current submission. Source: state/asc-review.jsonapps.placesreviewState: "UNRESOLVED_ISSUES", summary: {errors: 2, warnings: 0, infos: 1, blocking: 2}, nextAction: "Select a non-expired build for this version in App Store Connect".

1. The build attached to version 1.0 has expired

Failing log line, verbatim from apps.places.checks[0]:

{ "severity": "error", "message": "build is expired", "remediation": "Select a non-expired build for this version in App Store Connect", "field": null }

The timeline records exactly one build event — Build 1 (VALID, 2026-04-03T07:57:26-07:00) — followed by Submitted v1.0 on 2026-04-03 (complete) and again on 2026-06-10 (rejected). Separately, asc.jsonapps.places reports latest_build_number: "2" (VALID, uploaded 2026-06-14T03:40:06-07:00, build_count: 2) — i.e. a newer build exists, uploaded four days after the rejection.

> Inference, not a recorded fact: the review timeline never mentions Build 2, and the check still fires, which is consistent with version 1.0 still carrying the expired Build 1 while Build 2 sits unselected. Confirm the currently-attached build in App Store Connect before acting — this is the single most important thing to re-verify.

2. The latest review submission has unresolved App Review issues

Failing log line, verbatim from apps.places.checks[1]:

{ "severity": "error", "message": "Latest review submission has unresolved issues in App Review", "remediation": "Resolve the outstanding App Review issues in App Store Connect, then resubmit if needed.", "field": null }

Underlying reviewer message (apps.places.message.latest, from APPLE, 2026-06-10T22:59:10.327Z):

> Guideline 2.1 - Information Needed - New App Submission
> We need additional information to continue the review of this new app... Reply in App Store Connect with all of the following information:
> 1. A screen recording captured on a physical device, running the latest operating system, demonstrating the app's functionality. The recording must begin with launching the app and show the typical user flow through its core features — explicitly including Any prompts requesting access to sensitive data or device capabilities (for example, location, contacts, camera, or App Tracking Transparency)
> 2. A list of the device models and operating systems the app was tested on before submitting for review
> 3. A description of the app's purpose and target audience, including the problem it solves and the value it provides
> 4. Instructions for setting up and accessing the app's main features, including any required login credentials or sample files
> 5. A list of the external services, tools, or platforms the app uses to deliver its core functionality
> 6. Describe any regional differences in the app's features or content, or confirm that the app functions consistently across all regions
> 7. If the app operates in a highly regulated industry or includes protected third-party material, provide any relevant documentation or credentials...

The same message warns under "How to Prevent Common Issues":

> Guideline 5.1.1 - Purpose strings: Each purpose string must clearly and completely describe why the app needs access to the requested data or capability, and in most cases provide an example of how the data will be used.

Secondary risk: purpose strings are thin (Guideline 5.1.1)

The app declares two sensitive-data prompts, both of which must appear in the item-1 recording. Verified in /Users/zzxwill/Programming/go/src/zzxwill/apple-apps/apps/places/project.yml, lines 29-30:

INFOPLIST_KEY_NSPhotoLibraryUsageDescription: "This app needs access to your photo library to index locations and enable offline search."
INFOPLIST_KEY_NSLocationWhenInUseUsageDescription: "This app needs your location to show nearby photo locations on the map."

Both state *why* but neither gives an *example of how the data will be used* — exactly what the reviewer's 5.1.1 note calls out. This is the only likely code/config change in the entire fix.

Correction to the pre-drafted reply — CLGeocoder is not on-device

/Users/zzxwill/Programming/go/src/zzxwill/apple-apps/apple-apps-fleet/state/issues/_reply-places.md line 28 currently asserts:

> None. The app makes no network calls. Reverse-geocoding of coordinates to place names uses Apple's on-device CLGeocoder.

and line 22 asserts no network calls, all data stays on device. This is wrong and must be corrected before sending. CLGeocoder is an Apple *network* service — it transmits coordinates to Apple's geocoding servers. Re-verified 2026-08-04 in /Users/zzxwill/Programming/go/src/zzxwill/apple-apps/apps/places/SearchLocationsInApplePhotos/AppState.swift: CLGeocoder() at lines 218 and 507; reverseGeocodeLocation at lines 227, 273, and 519. Telling App Review the app makes no network calls while it geocodes user photo coordinates over the network is the kind of inaccuracy that escalates a 2.1 info request into a trust problem.

The same inaccurate claim is repeated in the app's own /Users/zzxwill/Programming/go/src/zzxwill/apple-apps/apps/places/CLAUDE.md ("all data stays on-device", "No network permissions — searches and data must remain local"). Correct it there too, so the next agent reading that file does not re-introduce the claim into a reviewer reply.

Everything else in item 5 verifies against source:

Supporting facts


Claude-Ready Fix Prompt

> The App Store app places (ASC id 6761598902, bundle com.zhouzhengxi.search-locations-in-apple-photos, version 1.0) is REJECTED under Guideline 2.1 with an expired build attached. App source is at /Users/zzxwill/Programming/go/src/zzxwill/apple-apps/apps/places/. Do the following, in order.
>
> 0. Re-pull ASC state first. The snapshots behind this issue are dated 2026-08-03. Confirm version 1.0 is still REJECTED, confirm which build is actually attached, and check whether Build 2 has itself expired before acting.
>
> 1. Tighten both purpose strings (Guideline 5.1.1) — the only code/config change required.
> Edit /Users/zzxwill/Programming/go/src/zzxwill/apple-apps/apps/places/project.yml lines 29-30. Rewrite both to name the concrete use, with an example:
> - INFOPLIST_KEY_NSPhotoLibraryUsageDescription — explain that the app reads the location metadata attached to photos in order to plot them on a map and make them searchable by place name (e.g. "show all photos taken in Tokyo").
> - INFOPLIST_KEY_NSLocationWhenInUseUsageDescription — explain that the current location is used only to center the map and rank nearby photo locations.
>
> Do not claim in either string that data never leaves the device — see step 3, item 5. Do not hand-edit /Users/zzxwill/Programming/go/src/zzxwill/apple-apps/apps/places/SearchLocationsInApplePhotos.xcodeproj/project.pbxproj; it is generated from project.yml by XcodeGen.
>
> 2. Cut and upload a fresh build. Bump CURRENT_PROJECT_VERSION in project.yml (line 10) from 2 to 3, then from /Users/zzxwill/Programming/go/src/zzxwill/apple-apps/apps/places/ run make gen && make export && make upload. The Makefile wires scheme SearchLocationsInApplePhotos (line 2), ExportOptions.plist, and ASC API key K4J825WNC7 (line 10) at ~/private_keys/AuthKey_K4J825WNC7.p8 (line 12), issuer ef4f5cc6-4152-436c-861d-fe7082529f1a (line 11). Note make export depends on archive, which depends on gen. Then attach the new build to version 1.0 in App Store Connect, replacing the expired one.
>
> *(If step 1 is deliberately skipped, the minimum viable action is to attach the existing VALID Build 2 — uploaded 2026-06-14T03:40:06-07:00 — to version 1.0. But since step 1 changes Info.plist strings, a new build supersedes it.)*
>
> 3. Answer all 7 reviewer items. A draft exists at /Users/zzxwill/Programming/go/src/zzxwill/apple-apps/apple-apps-fleet/state/issues/_reply-places.md — read it first and reuse it, but fix these before sending:
> - Item 5 (external services) — MUST FIX. The draft (line 28) says the app "makes no network calls" and calls CLGeocoder "on-device". Both are wrong: CLGeocoder (SearchLocationsInApplePhotos/AppState.swift lines 218, 507; reverseGeocodeLocation at 227, 273, 519) sends coordinates to Apple's geocoding service over the network. Rewrite item 5 to state: no third-party services; reverse-geocoding uses Apple's CLGeocoder (an Apple-operated network service); local storage is SQLite via GRDB. Also soften the "no network calls / all data stays on device" phrasing in item 3 (line 22) — the photos stay on device, but coordinates are geocoded via Apple. While you are at it, correct the same claim in /Users/zzxwill/Programming/go/src/zzxwill/apple-apps/apps/places/CLAUDE.md.
> - Item 2 (devices/OS tested): the draft (lines 17-19) lists a physical device plus two simulators. Do not ship these unverified — confirm with the user which physical device and OS were actually used, since Apple explicitly asks for pre-submission testing devices.
> - Item 4: keep the note (line 25) that the reviewer must grant Photos access and test on a device holding geotagged photos, otherwise the app shows empty results — the most likely reason a reviewer saw a blank app.
>
> Post the corrected reply in the Resolution Center thread (currently empty of any developer response), and copy items 3-7 into App Review Information → Notes on version 1.0 so future submissions are not asked again.
>
> 4. Record the screen recording (item 1) — requires the user; cannot be automated. On a physical device running the latest iOS, starting from app launch, showing both the Photos-permission prompt and the Location-permission prompt, then the core search and map flow. The checklist at _reply-places.md lines 36-43 has the exact 6 steps. Attach the file to the Resolution Center reply.
>
> 5. Resubmit version 1.0 once a non-expired build is attached and the Notes plus Resolution Center reply (with recording) are posted.
>
> Do not add places to state/fleet.jsonapps as part of this fix. It is not currently enrolled in the auto-build loop; enrolling it is a separate decision — confirm with the user first.


Last Known-Good Build

Per /Users/zzxwill/Programming/go/src/zzxwill/apple-apps/apple-apps-fleet/state/asc.jsonapps.places:

Build 2 is the last known-good build: VALID, uploaded after the rejection, and (by inference — see Root Cause §1) not the one attached to version 1.0. Verify Build 2 has not since expired before relying on it.