From 3a33964c0a7b8b287953f096285e65b416adba72 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 11 Jun 2026 16:54:24 +0000 Subject: [PATCH 1/4] Add asset cache busting via ASSETS_VERSION and import map All JS/CSS/asset URLs now carry a ?v= query param derived from BreakEscape::ASSETS_VERSION (defaults to gem VERSION, overridable via BREAK_ESCAPE_ASSETS_VERSION env var). A dynamic import map is injected into page heads so the browser rewrites every internal ES6 module import to the versioned URL, closing the cache gap that query-param versioning on only the entry point would leave open. Bump VERSION (or set the env var) on deploy to bust nginx/Cloudflare infinite-cache for all clients. https://claude.ai/code/session_01FAHp4aNpzSAxXX81PFeSAq --- .../break_escape/application_helper.rb | 19 ++- .../break_escape/player_preferences_helper.rb | 5 +- app/views/break_escape/games/new.html.erb | 2 +- app/views/break_escape/games/show.html.erb | 117 +++++++++--------- .../break_escape/missions/index.html.erb | 2 +- .../player_preferences/_modal.html.erb | 4 +- .../player_preferences/show.html.erb | 7 +- .../break_escape/shared/_cybok_label.html.erb | 2 +- lib/break_escape/version.rb | 1 + 9 files changed, 88 insertions(+), 71 deletions(-) diff --git a/app/helpers/break_escape/application_helper.rb b/app/helpers/break_escape/application_helper.rb index 3a9dd4c9..81baa8a4 100644 --- a/app/helpers/break_escape/application_helper.rb +++ b/app/helpers/break_escape/application_helper.rb @@ -1,8 +1,25 @@ +require 'json' + module BreakEscape module ApplicationHelper - # Generate a random ID for DOM elements def generate_random_id SecureRandom.hex(8) end + + def be_asset_path(path) + "#{path}?v=#{BreakEscape::ASSETS_VERSION}" + end + + def break_escape_import_map + version = BreakEscape::ASSETS_VERSION + js_root = BreakEscape::Engine.root.join('public') + js_dir = js_root.join('break_escape', 'js') + imports = Dir.glob("#{js_dir}/**/*.js").sort.each_with_object({}) do |file, h| + path = "/#{Pathname.new(file).relative_path_from(js_root)}" + h[path] = "#{path}?v=#{version}" + end + content_tag(:script, JSON.generate({ imports: imports }).html_safe, + type: 'importmap', nonce: content_security_policy_nonce) + end end end diff --git a/app/helpers/break_escape/player_preferences_helper.rb b/app/helpers/break_escape/player_preferences_helper.rb index 97029b09..8efe0a8e 100644 --- a/app/helpers/break_escape/player_preferences_helper.rb +++ b/app/helpers/break_escape/player_preferences_helper.rb @@ -10,11 +10,8 @@ def sprite_valid_for_scenario?(sprite, scenario_data) end end - # Headshot filename for sprite (prefer _down_headshot for hacker_hood, else _headshot) - HEADSHOT_VERSION = 2 - def sprite_headshot_path(sprite) - "/break_escape/assets/characters/#{sprite}_headshot.png?v=#{HEADSHOT_VERSION}" + "/break_escape/assets/characters/#{sprite}_headshot.png?v=#{BreakEscape::ASSETS_VERSION}" end private diff --git a/app/views/break_escape/games/new.html.erb b/app/views/break_escape/games/new.html.erb index e27cbb8b..3a343ed7 100644 --- a/app/views/break_escape/games/new.html.erb +++ b/app/views/break_escape/games/new.html.erb @@ -1,5 +1,5 @@ <% content_for :head do %> - + <% end %> <%# Game Setup / VM Set Selection or Standalone Flags Page %>
diff --git a/app/views/break_escape/games/show.html.erb b/app/views/break_escape/games/show.html.erb index 7f335fe7..dd6dbf49 100644 --- a/app/views/break_escape/games/show.html.erb +++ b/app/views/break_escape/games/show.html.erb @@ -11,61 +11,62 @@ <%# All fonts are self-hosted in /break_escape/assets/fonts/ via fonts.css %> <%# Load game CSS files %> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <%= break_escape_import_map %>
@@ -249,14 +250,14 @@ <%# Load required libraries before the game module %> - + <%# Load game JavaScript (ES6 module) %> - + <%# Load Hacktivity ActionCable integration for VM console support %> <% if BreakEscape::Mission.hacktivity_mode? %> - + <% end %> <%# Session resume/restart dialog — not shown in hacktivity mode %> diff --git a/app/views/break_escape/missions/index.html.erb b/app/views/break_escape/missions/index.html.erb index 5eba695c..92b30b3e 100644 --- a/app/views/break_escape/missions/index.html.erb +++ b/app/views/break_escape/missions/index.html.erb @@ -4,7 +4,7 @@ BreakEscape - Select Mission <%= csrf_meta_tags %> <%= csp_meta_tag %> - + diff --git a/app/views/break_escape/player_preferences/_modal.html.erb b/app/views/break_escape/player_preferences/_modal.html.erb index bb33d1c2..6eadc8e1 100644 --- a/app/views/break_escape/player_preferences/_modal.html.erb +++ b/app/views/break_escape/player_preferences/_modal.html.erb @@ -93,8 +93,8 @@