Proving the server half

The compliance rules live on your server, not in the app — one command that signs in as a native client and checks the server still honours them on your install.

2 min readUpdated 26 August 2026mobile, compliance, verification, e2e, withdrawals

Removing something from the app is not the same as switching it off. The app is a client; the rules that matter to a store reviewer are enforced by your backend, and your backend is the part you are free to change.

So there is a driver that signs in the way the app signs in, over real HTTP, against your own server:

cd e2e
npm run test:mobile

It creates one throwaway account on the reserved .invalid mail domain, holds no money, is refused everywhere it tries to move any, and deletes itself on the way out. Pass --keep if you want to look at what it made.

What it checks

A native client can sign in, and gets credentials it can use. The app keeps no cookie jar — it reads the tokens out of the response body and sends them back as headers. That body copy is sent only to callers identifying as native, so a change to how logins are answered can leave the app signing in successfully and then logged out on its very next request.

Rate figures are withheld from native callers. APR, APY and ROI are stripped for the app, and the driver checks both directions: that something was actually removed, and that nothing appears for a native caller that a web caller does not get.

No exit is gated on the client. This is the one to care about. Withdraw and cancel must refuse for a reason about money or state — insufficient balance, no wallet, no open orders — and never because the request came from the app. An app that accepts deposits and refuses withdrawals is the worst thing this package could put in front of a reviewer, and it is close to the first thing they try.

No refusal points somewhere else to transact. A message that says to use the website is anti-steering, and it is a rejection under Apple 3.1.1 regardless of how reasonable the underlying restriction is.

Why a live driver and not a unit test

Because the unit tests were all green while the gate was dead.

Every native check in this product keys off a platform header. For a long while the app sent mobile and the server compared against the string app, so not one gate ever fired. The unit tests passed throughout — they called the checkers directly and never sent a header, so they were testing the rule rather than the wiring.

A request over the wire is the only thing that tells the two apart. Run this against your own deployment before you submit, and again after any change to authentication, withdrawals or geo policy.

A green run is evidence about the endpoints it exercises, not a certificate. It does not check your licences, your store listing, or anything the reviewer reads. Those are on the other pages in this section.