- Shipped
- 29 Agosti 2026, 00:33 UTC
- Author
- Kamo
- Commit
- 70813fa
Replacing an org's simple logo updated every surface that reads img/logo.svg and left the browser tab on the old mark. Generation was never the problem: provisionUpdate already regenerates the favicon set from img/logo.svg on every save, and every branding saver calls provision-theme. Delivery was. The favicons were the last theme write still on MinIOStorageService.upload's five-argument overload, which sets no Cache-Control at all, while img/logo.svg, config.json, globals.css and site.webmanifest beside them all carried THEME_ASSET_CACHE_CONTROL. With no explicit lifetime a browser invents one from the Last-Modified age and never asks whether the icon is still current. Visible from outside: curl -skI **************** returned no cache-control line at all, where img/logo.svg beside it returned "max-age=0, must-revalidate". Also moves favicon generation ahead of writeConfigFiles in provisionUpdate. That method stamps a new themeRevision into config.json, and every client appends it as ?v= to the favicon URLs it requests, so publishing the revision first opened a window in which a page load could read the new revision and cache the OLD bytes under the NEW address. Generating first closes it — by the time a revision names these objects they are the ones on disk. provisionFull already ran in this order. The best-effort catch stays: a favicon failure must not block the colour/config write, which is the critical part of a colour save. Objects written before this still carry no Cache-Control, and favicons are <link> hrefs straight to the theme host rather than proxied, so an org's favicon objects only gain the header on its next branding save.