Phase 287 — Eliminate the per-app DNS provisioning race
Freshly-installed apps no longer hand you a dead link before their DNS record is live. Keeps the {app}-{user}.livinity.io hyphen pattern; eliminates the NXDOMAIN negative-cache race via a verify-live gate + a "Hazırlanıyor…" provisioning UI that forms no DNS query until the record resolves from your own resolver.
What changed
- Tier-1 (Vercel): the app-subdomain provision route now polls public DoH (1.1.1.1 + dns.google, A+CNAME) after creating the CF tunnel-ingress + CNAME, and reports
ready/readyAt. Advisory — never 503 on timeout. - Tier-2 (box/livinityd): 3 additive optional
SubdomainConfigfields (subdomainReady/readyAt/readySource), threaded through install + surfaced onapps.list; weak box-resolver advisory re-poll as a floor. - UI:
useAppOpenReadyhook + client-side cache-busting favicon probe (gated strictly onsubdomainReady===true— never probes before the record exists). BOTH open paths gated independently: in-appuseLaunchAppand the store-iframehandleOpen. Honest "Open anyway" escape +ipconfig /flushdnshint (real worst-case = SOA MINIMUM 1800s ≈ 30 min).
Honest scope
Prevents the race for new installs on a clean client. An already-poisoned resolver clears only via TTL expiry (~30 min) or ipconfig /flushdns — the UI says so, no false claim of end-to-end elimination.
Gates
livinityd tsc=305 (baseline held) · ui build exit 0 · platform/web tsc exit 0 · 287-affected app tests 32/32. Purely additive — no migration.
Full Changelog: v44.45...v44.46