diff --git a/scripts/check-phase10.sh b/scripts/check-phase10.sh
index cb188af..87936e6 100755
--- a/scripts/check-phase10.sh
+++ b/scripts/check-phase10.sh
@@ -202,19 +202,41 @@ run_self_test() {
echo "refuse: self-test hygiene rejected the clean scratch copy" >&2
exit 1
}
- local plant
- for plant in vhtml fetch appname; do
- rm -rf "$scratch/admin/src/__plant"
+ # Each plant is imported by a scratch test, so only its own rule can fire;
+ # the refusal must name that rule.
+ local plant want out
+ for plant in vhtml fetch appname storage; do
+ rm -rf "$scratch/admin/src/__plant" "$scratch/admin/tests/__plant.test.ts"
mkdir -p "$scratch/admin/src/__plant"
case "$plant" in
- vhtml) printf '\n' >"$scratch/admin/src/__plant/Plant.vue" ;;
- fetch) printf 'export const load = () => fetch("/x")\n' >"$scratch/admin/src/__plant/plant.ts" ;;
- appname) printf '// Fonoteka\nexport {}\n' >"$scratch/admin/src/__plant/plant.ts" ;;
+ vhtml)
+ printf '\n' >"$scratch/admin/src/__plant/Plant.vue"
+ printf "import Plant from '../src/__plant/Plant.vue'\n" >"$scratch/admin/tests/__plant.test.ts"
+ want="raw-HTML directive"
+ ;;
+ fetch)
+ printf 'export const load = () => fetch("/x")\n' >"$scratch/admin/src/__plant/plant.ts"
+ want="direct fetch"
+ ;;
+ appname)
+ printf '// Fonoteka\nexport {}\n' >"$scratch/admin/src/__plant/plant.ts"
+ want="application names"
+ ;;
+ storage)
+ printf 'export const keep = (v: string) => localStorage.setItem("token", v)\n' >"$scratch/admin/src/__plant/plant.ts"
+ want="browser storage"
+ ;;
esac
- if (hygiene_checks "$scratch" "$APP") >/dev/null 2>&1; then
+ [[ -f "$scratch/admin/tests/__plant.test.ts" ]] ||
+ printf "import '../src/__plant/plant'\n" >"$scratch/admin/tests/__plant.test.ts"
+ if out="$( (hygiene_checks "$scratch" "$APP") 2>&1)"; then
echo "refuse: self-test hygiene accepted a planted $plant" >&2
exit 1
fi
+ if ! grep -q "$want" <<<"$out" || grep -q "imported by no test" <<<"$out"; then
+ echo "refuse: self-test hygiene rejected the $plant plant for the wrong reason: $out" >&2
+ exit 1
+ fi
done
echo "phase10 self-test passed"
}
@@ -307,6 +329,10 @@ hygiene_checks() {
[[ -z "$hits" ]] || fail "admin/src/api/types.ts declares a shape instead of aliasing the generated schema: $hits"
hits="$(cd "$tree" && grep -nE '^export type [A-Za-z]+ = ' admin/src/api/types.ts | grep -vE "= (Schemas\['cabana\.[A-Za-z_-]+'\]|NonNullable<[A-Za-z]+Path\['get'\]\['parameters'\]\['query'\]>|[A-Za-z]+Path\['get'\]\['parameters'\]\['path'\])\$" || true)"
[[ -z "$hits" ]] || fail "admin/src/api/types.ts alias not onto the generated schema: $hits"
+ # Browser storage holds only the sidebar flag (T-10-22), never a token.
+ hits="$(cd "$tree" && grep -rnE 'localStorage|sessionStorage|indexedDB|document\.cookie' admin/src 2>/dev/null |
+ grep -v '^admin/src/state/useSidebar.ts:' || true)"
+ [[ -z "$hits" ]] || fail "browser storage outside admin/src/state/useSidebar.ts: $hits"
# The embedded build loads nothing from another origin.
hits="$(cd "$tree" && grep -noE '(src|href)="(https?:)?//[^"]*"|url\((["'"'"']?)(https?:)?//' boardwalk/dist/index.html boardwalk/dist/assets/*.css 2>/dev/null || true)"
[[ -z "$hits" ]] || fail "boardwalk/dist references another origin: $hits"