7things left that need code written
The app is built. It is on TestFlight today, subscriptions have been
purchased for real money on a real iPhone, and push notifications finished on 24 August.
Sign-in, account deletion and the age gate are all done and were done a while ago.
What is left is still mostly not engineering. Twenty-five items in
total, of which seven involve touching code. The rest is about a day of paperwork and a
few days of deliberately trying to break our own app before a reviewer does.
The code list went from three to seven, and that is a good sign rather than a
bad one. Every one of the four additions was found by looking: a bug sweep
across 1 to 3 September and a security review on 3 September, both run deliberately
rather than triggered by a complaint. A reviewer would have found at least two of them.
Nothing on this page is blocked; the paperwork that has been the critical path since
24 August is still the critical path, and it still has not started.
September 26 does not wait for any of this. The tournament plan settled
on 25 August puts ten invited players on the app through TestFlight, which needs no
store release at all. That decoupling is deliberate: it means the list below can be
done properly rather than quickly, and a rejection costs a queue place rather than the
event.
The one thing nobody controls is Apple's review clock. A first-ever
submission runs several days and sometimes longer. That is the argument for being
thorough now: a rejection does not cost the fix, it costs another trip through the
queue.
What is left, in the order it has to happen
Marked Code where an engineer writes something, and Both where the item
has to be done separately for Apple and for Google. Everything else is done once.
1. Fix
7 items
The things that would actually get us bounced. All small. Four of them were found after the last edition, by looking rather than by being told.
- The privacy policy link is broken, not just off-brand. This was thought to be a branding mismatch: the listing will say DirtyStack Poker while the policy sits on tblmaster.com. The security review on 3 September found something worse. That address redirects over an unencrypted connection to the home page of a different domain entirely, so a reviewer following the privacy link does not reach a privacy policy at all. Apple checks this link. It is the single most likely rejection on this page.Code
- An Android confirmation email opens a browser instead of the app. The small file that lets our website vouch for the app is missing, so the link never hands off. A new Android player confirming their email lands on a web page rather than back in the app they just installed.Code
- Gate the room logos behind a per-room permission. The app displays logos belonging to rooms that have not agreed to it. Fine while ten invited testers are looking; not fine on a public store listing.Code
- Two notification categories can never fire as written. The digest notifications default to off, so unless a player goes looking for the switch, nobody will ever receive one. The listing promises notifications; two of the six quietly cannot deliver.Code
- The nine o'clock alert routes nowhere. Tapping it opens a screen that does not answer it. A reviewer tapping a notification and landing nowhere is a straightforward rejection.Code
- Real screenshots for the two subscriptions. Each subscription needs its own review image in App Store Connect, and ours are still placeholders. Placeholders stop the subscriptions being approved alongside the app, which means an approved app with a paywall that sells nothing.Code
- Decide what happens to the test accounts. A test phone number, a fixed one-time code and a QA login are live in production on purpose, because a reviewer needs a way in. They are useful during review and wrong once the app is genuinely public, so the decision is when they come out, not whether.Code
2. Prepare
6 items
The paperwork. Roughly a day, and none of it depends on any remaining engineering.
- The privacy questionnaires. Apple calls it App Privacy, Google calls it Data Safety, and they ask much the same thing in different shapes. Slowest to get right, so it goes first. Ours is unusually simple because the app carries no advertising SDK, which means no tracking prompt and a much shorter form. Worth protecting: adding a normal ad network later reopens both.Both
- Listing text. Name, subtitle, description, keywords, support and marketing links.Both
- Say plainly that there is no real money. No wagering, no cash-out, no real-money prizes. Putting it in the description answers the obvious reviewer question before it is asked, rather than after a rejection.Both
- Screenshots of the app itself, captured from a real build rather than a simulator, so the app looks as populated as it actually is.Both
- Age rating. Apple rates poker imagery 17+, Google 18+, even with no real money involved. The app already enforces an 18+ gate, so this is declaring what we already do.Both
- Reviewer notes and a working demo account. Apple requires one because the app has a login. This is also where we explain what the app is, so a reviewer is not guessing.Both
3. Prove
7 items
Trying to break it ourselves, on the exact build we intend to submit. This is the part that protects the schedule.
- A clean install on a real phone, walked end to end as a brand-new player who has never opened it. Not the development build, and not an account that already has history.
- Every way of signing in. Apple, Facebook, phone and email. Facebook matters most right now because it moved to the company account on 25 August, so it is the newest and least exercised path. A reviewer tapping a dead sign-in button is a straightforward rejection.
- Buy a subscription, then restore it, on the build being submitted rather than the one we tested in July.
- Accept the notification prompt and receive a real notification. Push finished on 24 August, so this is the newest thing in the app and the least proven in a reviewer's hands.
- Sweep for anything invented. Placeholder adverts, demo rooms, seeded results. A reviewer cannot tell a fixture from a lie, and neither can a real player.
- Confirm the error tracker is quiet on the candidate build. Apple rejects on crashes found during review, and we would rather find them.
- The same pass again on Android, through internal testing. Different phones, different sign-in quirks, different purchase plumbing.Both
4. Submit
3 items
Mechanical, and already rehearsed once. There is a written ritual for it.
- Cut the production builds. Version bump, release notes, build from the main line.Both
- Upload and confirm the upload actually worked. Both stores report a state that looks like progress while having failed, and a failed upload still consumes the build number, so this gets checked rather than assumed.Both
- Submit for review.Both
5. Wait, then finish
2 items
Out of our hands, and worth planning around rather than watching.
- Google's first release has its own delay. A brand-new app takes time to propagate before even our own testers can install it. We have hit this already; it is not a bug and it does not respond to effort.
- Verify an Android purchase end to end, which cannot happen until that first release clears. It is the one piece of the payment path never proven on Android.
One decision worth making deliberately
The old plan was to submit an incomplete app on purpose. That is no longer necessary.
Back in early August, push notifications were months of work and the review queue was
the longest pole, so the plan was to submit without them, hold the approved build
unreleased, finish push during the wait, and ship it as an immediate follow-up. That
was a good plan for the situation.
Push finished on 24 August, so the situation changed. We can submit a
complete app instead of a deliberately partial one. That removes a real constraint:
Apple will not accept a second version while one sits approved-but-unreleased, which
is exactly the corner the old plan put us in.
Worth confirming out loud rather than inheriting, because the old plan is still
written down in the repo and would otherwise be followed by default.