ProConnect ignores prompt=login, so preserving the IdP session locked
mobile users into the same identity forever. The logout endpoint now
accepts a mobile_scheme and ends the RP-initiated round-trip on a new
logout-callback view that deep-links back to the app, so the system
browser — which holds both the Django session handed over at login and
the IdP SSO cookie — terminates both sessions.
Then, Proconnect login page's Content Security Policy blocks
the direct redirect: Chrome enforces its form-action on the whole
redirect chain of the credential form submission, and "*" only matches
network schemes — so our network mobile scheme violates it and the user
stays stuck on the identity provider during logout workflow.
The callback now serves a page that ends the form chain on a
network mobile scheme, then hands off to the app from our own page,
outside the IdP policy: automatically via script (iOS
interception, unchanged) with a button as the always-working fallback.
Store review cycles make shipping web-layer fixes through the stores
too slow, so the apps update their JS bundle over the air. The chain is
fully self-hosted to keep sovereignty: bundles and channel manifests
live on an anonymous-read S3 bucket (create_bucket --public / the
create-ota-bucket script) and the Capgo plugin is driven entirely from
JS against that manifest (autoUpdate off — no Capgo server involved).
Bundles are RSA-signed at publish time and verified against the
per-instance public key baked in at cap sync, so a tampered zip on the
public bucket is rejected.
Versions use a git-derived <count>-<sha> id stamped into the builtin
bundle so a fresh install does not re-download its own commit, and
channels (dev/staging/prod) are fully independent because
NEXT_PUBLIC_* vars are inlined at build time.
Also ships docs/mobile.md.