fix: serve admin bundle as hashed immutable assets

The lazy-loaded admin CSS/JS resolved to bare runtime names served
no-store, the same scheme that left the main bundle vulnerable to stale
CSS in iOS WebViews after a deploy. The original reason for keeping them
bare (hashed admin files could 404 when nginx fronts aiohttp) no longer
holds: the backend image now carries the same deterministically hashed
assets nginx serves, and the App.svelte loader already falls back to the
bare name if a hashed asset ever 404s.

Resolve the admin assets through the same hashed/version-stable path as
the main bundle so they are emitted as immutable, cache-busting URLs.

Also drop the inert <meta http-equiv="Cache-Control/Pragma/Expires">
tags from the shell: browsers ignore http-equiv caching directives for
the document and use the real HTTP headers, which are already set.
This commit is contained in:
3252a8
2026-06-08 22:47:44 +03:00
parent a2ce29da45
commit 194bf64ebb
3 changed files with 39 additions and 13 deletions
+25 -3
View File
@@ -1009,7 +1009,7 @@ class WebAppAssetTests(unittest.IsolatedAsyncioTestCase):
r"^subscription_webapp\.css\?v=[0-9a-f]{8}$",
)
def test_resolve_webapp_admin_asset_names_use_stable_runtime_builds(self):
def test_resolve_webapp_admin_asset_names_prefer_latest_hashed_builds(self):
with tempfile.TemporaryDirectory() as tmpdir:
asset_dir = Path(tmpdir)
(asset_dir / "subscription_webapp_admin.js").write_text(
@@ -1032,13 +1032,35 @@ class WebAppAssetTests(unittest.IsolatedAsyncioTestCase):
os.utime(new_css, (2, 2))
with patch.object(webapp_assets, "ASSET_DIR", asset_dir):
webapp_assets._ASSET_NAME_CACHE.clear()
self.assertEqual(
subscription_webapp._resolve_webapp_admin_js_asset_name(),
"subscription_webapp_admin.js",
"subscription_webapp_admin.min.22222222.js",
)
self.assertEqual(
subscription_webapp._resolve_webapp_admin_css_asset_name(),
"subscription_webapp_admin.css",
"subscription_webapp_admin.22222222.css",
)
def test_resolve_webapp_admin_asset_names_fall_back_to_runtime_builds(self):
with tempfile.TemporaryDirectory() as tmpdir:
asset_dir = Path(tmpdir)
(asset_dir / "subscription_webapp_admin.js").write_text(
"console.log('admin fallback');", encoding="utf-8"
)
(asset_dir / "subscription_webapp_admin.css").write_text(
".admin{color:red}", encoding="utf-8"
)
with patch.object(webapp_assets, "ASSET_DIR", asset_dir):
webapp_assets._ASSET_NAME_CACHE.clear()
self.assertRegex(
subscription_webapp._resolve_webapp_admin_js_asset_name(),
r"^subscription_webapp_admin\.js\?v=[0-9a-f]{8}$",
)
self.assertRegex(
subscription_webapp._resolve_webapp_admin_css_asset_name(),
r"^subscription_webapp_admin\.css\?v=[0-9a-f]{8}$",
)
async def test_js_asset_route_sets_immutable_cache_control_for_minified_asset(self):