fix: empty dialogs - relative project path caused a silently-swallowed 403 (+ cache-busting) #7

Merged
hermes merged 2 commits from fix/cache-busting into master 2026-09-29 16:55:36 +10:00
2 Commits
Author SHA1 Message Date
hermes be8c959de2 fix: dialogs rendered EMPTY - relative project path caused a silent 403
THE ACTUAL CAUSE of "codegit is just a black box". Sections 4 and 5 were real bugs but
neither was it; this is.

CHAIN
  1. install/process.php stores a RELATIVE folder name -> projects.db {"Blog":"blog"}
  2. common.php::loadState() does $projectPath = reset($projectList) -> "blog", and
     SESSION("projectPath","blog") PERSISTS it, so the bad value sticks across logins
  3. filetree puts it straight into the DOM: <a id="project-root" data-path="blog">
  4. codegit sends repo="blog"; getWorkspacePath("blog") fails checkPath() ->
       traits/path.php:67  Common::send(403, "Client does not have access.")
  5. modal.js SILENTLY discards it:
       settled: function(reply,status){ if (status !== 200) return; ... }
     No toast, no console error, #content left empty.

That last step is why it presents as an empty black dialog rather than an error - the request
fails and nothing reports it. Which is exactly why it survived the CSS fixes.

PINNED DOWN BY CAPTURING THE REAL REQUEST, not by reading CSS:
  POST /dialog.php {"target":"codegit","action":"codegit","repo":"blog"} -> 403
  #content innerHTML length: 0
  getWorkspacePath("blog") -> 403
  projects store           -> {"Blog":"blog"}

FIX (scripts/fix-project-path.sh) - both parts required:
  A. resolve the path in loadState and re-store it, which also HEALS sessions already
     holding the relative value (and re-persists so it stays healed)
  B. make the projects store absolute, so array_search() can still map path -> name for
     the tree label. Fixing only (A) would silently break the label: the path would resolve
     but array_search would return false and the tree would show an empty project name.

VERIFIED from a deliberately poisoned session ("blog"): it self-heals to the absolute path,
dialog returns 200, #content fills with 1758 chars. An EXISTING browser session heals on its
next page load - no hard refresh or re-login needed.

Tests: 47 passed, 0 failed, 1 accepted-risk
  + projects store must hold an absolute path
  + loadState must resolve a relative projectPath

Also marks section 4 as superseded so a future reader doesn't stop at the CSS explanation.
2026-09-29 16:55:08 +10:00
hermes 48e439ed6e fix: cache-bust asset URLs - the real reason the panel fix appeared not to work
Reported again as "code git still no go just a black box is it because I'm on firefox?"

It is NOT Firefox. Tested properly: installed Firefox 155 and drove the live server with
Playwright, authenticated. Result:

  assets Firefox requested:  theme/main.min.css?v=1790663824   <- versioned
  applied panel rule:        height: auto; max-height: 58vh    <- the fix IS applied
  dialog 193px | panel 138px | toolbar INSIDE | JS errors: none

CodeGit renders correctly in Firefox. Firefox was simply still running the OLD CSS.

WHY THE EARLIER FIX DIDN'T TAKE
  Atheos emits asset URLs with no version:
    <link rel="stylesheet" href="theme/main.min.css">
    <script src="public/modules.min.js"></script>
  Same path before and after a change, and originally no cache headers at all. So the browser
  keeps its cached copy and never even asks the server. Changing the CSS server-side cannot
  help when the browser isn't fetching it - which is why the previous Cache-Control fix was
  necessary but NOT sufficient against a cache that was already poisoned.

FIX - versioned URLs
  SourceManager::getTag() and the theme link in index.php now append the file mtime:
    theme/main.min.css?v=1790663824
  A changed file gets a NEW URL, so it is fetched immediately; an unchanged file keeps its URL
  and stays cached. This works even against an already-stale cache, which headers alone cannot
  do. The page itself is served no-store, so the next normal reload picks up new URLs
  automatically - no hard refresh needed by the user.

Both parts are now in scripts/fix-panel-layout.sh (idempotent, verified):
  1. Cache-Control: no-cache for *.css/*.js (revalidation; keeps 304s fast)
  2. mtime-versioned asset URLs (the part that actually defeats a poisoned cache)

Tests: 45 passed, 0 failed, 1 accepted-risk
  + asset URLs must carry ?v=  (guards against this regressing and silently hiding future fixes)
2026-09-29 16:47:28 +10:00