File size: 2,624 Bytes
995a1fb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
"""The cache-busting token in index.html must be bumped when CSS/JS changes.

Root cause of a real 2026-09-14 report ("this still looks the same",
"78 is still not up"). The Space serves /static/*.css with
`cache-control: public, max-age=31536000` — a full YEAR — and the HTML
references the assets with `?v=<token>` query strings for cache busting.
The `20260912-paddle` token stayed static through four subsequent PRs
(#76, #77, #78, #79). Every browser that had loaded the app any time
after the Paddle release was serving the CSS/JS from cache regardless of
what shipped — no way to see the fixes without a manual hard refresh
that most users won't ever perform.

Two things pinned here:

  1) EVERY versioned reference in index.html uses the SAME token — a
     mixed set is the classic partial-refresh bug (new CSS against old
     JS, or vice-versa, which reads on screen as broken selectors).
  2) The token must not still be `20260912-paddle`, so this PR's bump
     doesn't get quietly undone. Future PRs that change any static
     asset get an obvious failing test to nudge them into bumping.
"""
import pathlib
import re


def _read(rel):
    return pathlib.Path(rel).read_text(encoding="utf-8")


def _tokens_in_index():
    html = _read("dee/static/index.html")
    return sorted(set(re.findall(r"\.(?:css|js)\?v=([A-Za-z0-9_.-]+)", html)))


def test_index_html_uses_one_cache_busting_token_everywhere():
    """A mixed set is the classic 'new CSS against old JS' partial-refresh
    bug. One token — everything invalidates together, or nothing does."""
    tokens = _tokens_in_index()
    assert tokens, "no ?v= cache-busting tokens in index.html — that would " \
                   "make every CSS/JS change invisible until manual reload"
    assert len(tokens) == 1, (
        "index.html carries multiple ?v= tokens: " + ", ".join(tokens) +
        ". They MUST match; a mix ships new CSS against old JS or vice-versa"
    )


def test_the_cache_token_isnt_the_2026_09_12_stale_one():
    """A specific regression guard for THIS PR. The Paddle-release token
    stayed static through #76-#79, so users never picked up any of those
    fixes without manually clearing cache. Any future PR that changes a
    static asset and forgets to bump the token gets a red test."""
    tokens = _tokens_in_index()
    assert tokens
    assert tokens[0] != "20260912-paddle", (
        "the cache token is the stale 2026-09-12 Paddle-release value. "
        "Bump it — otherwise browsers keep serving month-old CSS and JS "
        "against the current server (cache-control: max-age=31536000)."
    )