diff --git a/docs/release-control/v6/internal/subsystems/api-contracts.md b/docs/release-control/v6/internal/subsystems/api-contracts.md
index da5ed8a7b..69595b942 100644
--- a/docs/release-control/v6/internal/subsystems/api-contracts.md
+++ b/docs/release-control/v6/internal/subsystems/api-contracts.md
@@ -381,6 +381,10 @@ action or state (`Manage access`, `Hosted billing attached`, `Email support`,
generic alert labels. Support copy is part of the same typed contract:
escalation surfaces must render short literal path/account/action wording
instead of longer procedural prose.
+That same typed portal page contract also owns favicon cache-busting: the
+rendered `` must point at the shared `/favicon.svg` asset
+through a versioned href so new portal icon revisions bypass browser cache on
+deploy instead of waiting for asset expiry.
That same typed overview contract must also preserve a sharp, high-density enterprise visual aesthetic (e.g. Cloudflare/GCP density standards) across all portal scenarios, removing gradients and heavy box-shadows to ensure a calm, rigorous visual language with standard 256px sidebars, Inter-grade typography, clean text-transform rules, and cleanly unboxed typography without excessive pills or stacked metrics.
plus a package-local `tsc --noEmit` gate, so future account-shell work should
extend the typed source boundary instead of reviving opaque global runtime
diff --git a/docs/release-control/v6/internal/subsystems/cloud-paid.md b/docs/release-control/v6/internal/subsystems/cloud-paid.md
index 2e7323c2a..04164d8b1 100644
--- a/docs/release-control/v6/internal/subsystems/cloud-paid.md
+++ b/docs/release-control/v6/internal/subsystems/cloud-paid.md
@@ -270,7 +270,10 @@ instance, but local portal design work must not depend on redeploying
That same preview/runtime boundary also owns shared browser chrome such as the
portal favicon: the local preview must serve the same `/favicon.svg` asset as
the real control-plane route so icon changes can be reviewed locally before
-deployment instead of appearing only after a live push.
+deployment instead of appearing only after a live push. The portal page itself
+must also reference that shared favicon through a versioned href so updated
+icon revisions bypass browser cache on deploy instead of waiting for asset
+expiry.
That same frontend delivery boundary must keep the account portal visual language sharp and high-density, avoiding gradients, heavy shadows, and decorative SaaS styling in favor of a clean, restrained, Cloudflare/GCP-grade baseline with flat inline workspace action rows and text-driven unboxed metadata instead of pills and absolutely inline row actions.
That same portal delivery boundary also owns the checked-in embedded bundle in
`internal/cloudcp/portal/dist/`. Visual or interaction changes are not
diff --git a/internal/cloudcp/portal/frontend/dev.mjs b/internal/cloudcp/portal/frontend/dev.mjs
index f82777614..c1033bb3e 100644
--- a/internal/cloudcp/portal/frontend/dev.mjs
+++ b/internal/cloudcp/portal/frontend/dev.mjs
@@ -1,6 +1,7 @@
import fs from 'node:fs';
import http from 'node:http';
import path from 'node:path';
+import { createHash } from 'node:crypto';
import { context } from 'esbuild';
import { createPortalBuildOptions, frontendRoot } from './build_config.mjs';
@@ -10,6 +11,7 @@ const previewHost = process.env.PULSE_PORTAL_PREVIEW_HOST || '127.0.0.1';
const previewPort = Number(process.env.PULSE_PORTAL_PREVIEW_PORT || '8765');
const previewScenarios = ['managed', 'readonly', 'selfhosted', 'empty'];
const previewFaviconSVG = fs.readFileSync(path.join(frontendRoot, '..', '..', 'favicon.svg'), 'utf8');
+const previewFaviconHref = '/favicon.svg?v=' + createHash('sha256').update(previewFaviconSVG).digest('hex').slice(0, 16);
function iso(value) {
return new Date(value).toISOString();
@@ -253,7 +255,7 @@ function buildPreviewHTML(assets, bootstrap, previewToast) {
'' +
'' +
'