From fbef773a24954cfdcd9c6b2e86bb496c651ae90f Mon Sep 17 00:00:00 2001 From: Jakub Zych Date: Sun, 27 Sep 2026 18:15:05 +0200 Subject: [PATCH] test(10-05): hygiene confines browser storage and self-tests each rule - --hygiene refuses localStorage, sessionStorage, indexedDB or document.cookie outside admin/src/state/useSidebar.ts (T-10-22) - --self-test plants each violation with a scratch test import, so the refusal must come from that rule and not from the untested-module check --- scripts/check-phase10.sh | 40 +++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) 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"