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.
This commit is contained in:
2026-09-29 16:55:08 +10:00
parent 48e439ed6e
commit be8c959de2
3 changed files with 207 additions and 10 deletions
+22
View File
@@ -191,6 +191,28 @@ fi
echo
echo "=============================================================="
echo "REGRESSION: project path is ABSOLUTE (relative => empty dialogs)"
echo "=============================================================="
# A relative project path makes every getWorkspacePath() call fail its access check with 403,
# which modal.js silently swallows - so CodeGit/Macro/Market/Settings render EMPTY with no error.
# docs/known-issues.md S6. This is the bug that presented as "just a black box".
PP=$(php83 -r '
$raw=@file_get_contents("/var/www/atheos/data/projects.db.json.php");
if(!$raw) exit;
preg_match("/<\?php\/\*\|(.*)\|\*\/\?>/s",$raw,$m);
$d=json_decode($m[1],true);
if(is_array($d)) echo reset($d);' 2>/dev/null)
case "$PP" in
/*) ok "projects store holds an absolute path ($PP)" ;;
"") bad "could not read the projects store" ;;
*) bad "projects store holds a RELATIVE path ('$PP') - dialogs will render empty; re-run scripts/fix-project-path.sh" ;;
esac
if grep -q 'isAbsPath($projectPath)' /var/www/atheos/common.php 2>/dev/null; then
ok "loadState resolves a relative projectPath (heals poisoned sessions)"
else
bad "loadState does NOT resolve relative project paths - re-run scripts/fix-project-path.sh"
fi
echo "=============================================================="
echo "IDENTITY: git identity is SET by the operator (FR-11 superseded by explicit request)"
echo "=============================================================="
# FR-11 originally required the agent to leave the identity EMPTY so it could not impersonate