DEV Community

Cover image for Every rejection becomes a check
Dominique Siacci for GoodBarber

Posted on AI-assisted

Every rejection becomes a check

Every app we ship gets reviewed by someone else's QA. Two someones, actually — Apple and Google — each with its own rulebook, and each rulebook comes in two parts: the rules as written, and the rules as applied. The written part you can read. The applied part you learn the way case law is learned: one decision at a time.

And here's the constraint that shapes everything downstream: you can't run their test suite locally. There is no command that tells you, before submission, what the review will say. Anyone who ships apps lives with this. What changes, when submitting is something you do continuously rather than occasionally, is what you're allowed to do with the answers. When the same review keeps answering you, week after week, letting the same rule surprise you twice isn't bad luck anymore. It's negligence.

So that became the discipline: every time the review teaches us something — a rejection pattern, a rule change, a shift in how an old rule gets applied — the lesson turns into an explicit check on our side, run before the store ever sees the app. We can't execute their suite. We can compile what it has already said.

The list of checks that discipline has produced is long. Here are two entries from it — two among many, picked because they're the rejection families that topped the questions at our recent Reddit AMA on store publishing: apps that look unfinished, and declarations that don't match the app.

The empty shelf

Stores reject apps that look unfinished — screens without content, sections that lead nowhere. Reasonably so: their reviewer opens the app cold, and an empty shelf reads as an abandoned store.

Our answer isn't a best-practices PDF. The guardrails live in the product itself: checklists that stand between a builder and a submission, refusing to let an app walk into review hollow. What used to be advice — "fill your sections before you submit" — became a feature that checks. Advice gets skipped; checks don't.

That's the pattern for everything automatable, and it's worth stating as a rule: when a piece of advice can be verified mechanically, it should stop being advice.

Say what you do, do what you say

The second family of checks is subtler. A review doesn't just look at what the app does — it cross-references what the app declares against what it actually does. Privacy declarations, permission requests, data-safety forms: every one of them is a claim, and a claim that doesn't match the binary is one of the most reliable ways to get rejected.

It's also the most avoidable rejection there is, because the mismatch is a diff — and diffs are what machines are for. In our case, the declarations are deduced from the app's configuration rather than filled in by hand. What remains for the pre-submission check is the moving part: a builder enables a feature one week and disables it the next, and the declarations must describe the app being submitted today, not the app as it looked when someone last thought about privacy. So coherence gets verified again, at the door.

The line between the machine and the eye

Not everything compiles into a check. A rule that says "no placeholder content" automates well. A rule whose application shifted last quarter, or that hinges on how a reviewer will read a particular screen — that one lives in judgment, not in code.

So the frontier is drawn plainly. Everything that can be verified mechanically is handed to the builder as a guardrail inside the product — they see it, they fix it, no expertise required. What can't be automated goes under an expert eye before submission: the store rules keep moving, and someone whose job is to read every change sees patterns no individual builder submitting once a year could. The review on the other side is run by humans; the last line on ours is too.

Failing first

None of this makes rejection impossible — a suite you can't run will always keep some surprises. What it does is more modest and more valuable: it guarantees that no app fails in front of Apple or Google for a reason we already knew about. The known rules are checked by machines. The learned patterns are checked by people. And every new lesson joins the list, which means the list only grows in one direction.

You can't run someone else's test suite. You can make sure yours fails first.

Top comments (0)