Stamp official Docker builds with a low-cardinality provenance marker and report build_provenance/image_modified in anonymous telemetry. Local and fork builds default to custom, while official GitHub/GitLab release paths mark images as official.
The backend renders the Mini App shell and rewrites the stylesheet and
script tags to content-hashed names (subscription_webapp.<hash>.css).
Those hashed files are gitignored build artifacts, so a clean checkout
has none of them and the backend image was built without any webapp
assets. The resolver therefore stat()-ed a missing file and fell back to
the bare /subscription_webapp.css URL.
That bare URL never changes between deploys and is served no-store. Most
clients re-fetch it, but iOS WebViews (WKWebView) ignore no-store for
subresources and keep serving a stale cached copy, so after every deploy
the CSS no longer matched the markup and the Mini App looked broken on
iOS only. The earlier no-store / ?v= / Clear-Site-Data attempts could not
help because none of them gave iOS a new URL to fetch.
Copy the freshly built assets from the frontend-builder stage into the
backend image (frontend-builder is reordered ahead of the backend stage
so the copy resolves). The build is deterministic, so the hash matches
the one the nginx image serves; the shell now emits immutable, hashed
URLs that change on every asset change and force iOS to fetch fresh CSS.