diff --git a/.env.example b/.env.example
index 0940896..52dce04 100644
--- a/.env.example
+++ b/.env.example
@@ -85,10 +85,11 @@ ACME_EMAIL=
# .git (the prod image ships none) — leave empty; in dev the page reads .git directly.
CLUSEV_BUILD_SHA=
CLUSEV_BUILD_BRANCH=
-# Update source for the in-app version check. install.sh derives this from the clone origin
-# (git remote get-url origin). Leave empty to disable the check. Never put a private repo URL in a
-# tracked file — only here in the per-deployment .env.
-CLUSEV_REPOSITORY=
+# Update source for the in-app version check. install.sh sets this from the clone origin
+# (git remote get-url origin). Left UNSET (keep this commented), it falls back to the public repo
+# default in config/clusev.php — an empty value here would instead disable the check, so leave the
+# key absent rather than blank. Never put a private repo URL in a tracked file — only in the .env.
+# CLUSEV_REPOSITORY=https://github.com/clusev/clusev
# Display timezone for dashboard times (DB stays UTC). install.sh sets this from the host; UTC default.
APP_TIMEZONE=UTC
# External reverse-proxy TLS: set to the upstream proxy's address/CIDR so Caddy trusts its
diff --git a/.gitattributes b/.gitattributes
index d4ca542..1101091 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -15,4 +15,5 @@
/CLAUDE.md export-ignore
/rules.md export-ignore
/handoff.md export-ignore
+/kickoff-prompt.md export-ignore
/docs export-ignore
diff --git a/README.md b/README.md
index 9d4d826..a99d83d 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-

+
@@ -61,7 +61,7 @@ colour, dots and pills — never emoji.
## Architecture
-

+
Laravel is the **control plane**, not a re-implementation of your servers. The browser talks to it
diff --git a/scripts/promote.sh b/scripts/promote.sh
index 8c3800c..56c0f18 100755
--- a/scripts/promote.sh
+++ b/scripts/promote.sh
@@ -28,6 +28,23 @@ git -C "$src" archive --format=tar "$tag" | tar -x -C "$pub"
# Private CI never goes public.
rm -rf "${pub:?}/.github"
+# Leak guard — never publish a tree that still carries a private identifier or an internal doc. This
+# makes promote.sh safe even for a tag cut BEFORE the export-ignore / URL-neutralisation fixes: such
+# a tree is refused (the public repo is left untouched) instead of leaking the dev/staging repos.
+leak=0
+for f in CLAUDE.md rules.md handoff.md kickoff-prompt.md docs; do
+ [ -e "$pub/$f" ] && { echo "leak-guard: internal path present in the tree: $f" >&2; leak=1; }
+done
+if grep -rIl -e 'git\.bave\.dev' -e 'boban/clusev' -e 'clusev-staging' "$pub" >/dev/null 2>&1; then
+ echo "leak-guard: private repo identifier in the tree to be published:" >&2
+ grep -rIl -e 'git\.bave\.dev' -e 'boban/clusev' -e 'clusev-staging' "$pub" >&2
+ leak=1
+fi
+if [ "$leak" -ne 0 ]; then
+ echo "leak-guard: REFUSING to publish $tag — promote a tag cut after the leak-safety fixes (>= v0.9.58)." >&2
+ exit 1
+fi
+
git -C "$pub" add -A
# --allow-empty: stable promotion re-tags the same source commit as the last beta, so the
# extracted tree is byte-identical and there is nothing to stage — still produce a release commit.
diff --git a/scripts/promote.test.sh b/scripts/promote.test.sh
index b8da7fb..6eab364 100755
--- a/scripts/promote.test.sh
+++ b/scripts/promote.test.sh
@@ -42,4 +42,15 @@ git -C "$work/src" tag v1.0.1 v1.0.0
bash "$here/promote.sh" "$work/src" v1.0.1 "$work/pub" "Release v1.0.1"
git -C "$work/pub" rev-parse v1.0.1 >/dev/null 2>&1 || { echo "FAIL: identical-tree tag missing"; exit 1; }
git -C "$work/pub" log -1 --pretty=%s | grep -qx 'Release v1.0.1' || { echo "FAIL: identical-tree commit message"; exit 1; }
+
+# Leak guard: a tree carrying a private identifier in a PUBLISHED file must be REFUSED, with no tag
+# created (protects against promoting an old tag cut before the leak-safety fixes).
+git init -q "$work/leaky"
+printf 'home: https://git.bave.dev/boban/clusev\n' > "$work/leaky/README.md"
+git -C "$work/leaky" add -A && git -C "$work/leaky" commit -qm init && git -C "$work/leaky" tag v9.9.9
+git init -q "$work/pub2"
+if bash "$here/promote.sh" "$work/leaky" v9.9.9 "$work/pub2" "Release v9.9.9" 2>/dev/null; then
+ echo "FAIL: leak guard did not refuse a private-identifier tree"; exit 1
+fi
+git -C "$work/pub2" rev-parse v9.9.9 >/dev/null 2>&1 && { echo "FAIL: tag created despite leak"; exit 1; }
echo "PASS"