mirror of
https://github.com/nexu-io/open-design.git
synced 2026-09-20 06:15:06 +08:00
f5707c8cae
* fix(cms): host campaign touchpoints on the home view only Every placement this app authorizes is a home placement (`opend.home.*`), but the hosts did not follow. The modal pair mounted on every route except onboarding, and the account badge rode the entry rail across all of its tabs plus the project workbench corner — so a CMS campaign could open over an open project, which is where a user reported meeting it. The hosts now answer to the home view: App mounts the Test and Production modals only there, EntryShell gates the badge and the hover entry on `view === 'home'`, and the workbench cluster carries no CMS touchpoint at all. The built-in DeepSeek pill is product chrome rather than a CMS host and keeps its reach across entry tabs and project detail; the source contract that guarded that reach is split to say so. * fix(cms): stop a wake from re-presenting a displayed campaign Screen sleep hides the page, which withdraws the lease and takes the modal down. Waking refreshes — and the refresh carried the withdrawn lease as its revalidation subject, which the impression gate read as "the active activity" and exempted from the device impression. The server offers the same activity, so the campaign re-opened on every wake, for as long as it was published. The exemption now belongs to the presentation still on screen and nothing else. A page that goes hidden releases that presentation, so the offer arriving on wake is a new one and the impression closes it. A suppressed offer has to clear rather than retain: retaining republishes the very lease the visibility fence just withdrew, which was how the first cut of this fix kept the modal on screen. Retain stays for the case it was written for — an offer arriving beside a live presentation, which keeps its mount. * fix(cms): keep a displayed campaign through a recoverable poll failure The lifecycle draws a line no other layer may redraw: only the server's own withdrawal ends a live lease, and a transport failure rides out on the lease already granted, retried inside the same cycle. The modal's `onError` ignored that line and released its open presentation for any error at all. That was harmless while the impression gate still exempted the active lease. Keying the exemption on the presentation alone — which is what stopped a wake from re-presenting a displayed campaign — made the two disagree: a poll that failed on a dropped connection left the modal mounted with no presentation to show for it, so the retry that recovered the very same activity read the device impression, found nothing on screen, and cleared the host. The campaign vanished mid-flight on ordinary network noise and could not return for the rest of the run. The presentation now follows the lease it belongs to, withdrawn only by a withdrawal. The wake fence still releases it on hidden, because that presentation is genuinely over. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(cms): retain presentation with active lease * test(cms): await mounted presentation before refresh --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: ivy-ting <234137810+ivy-ting@users.noreply.github.com>