🔒 LOCKED — Do not modify without snapshot first.
This is the canonical, working version of the 6-Layer+™ audit tool. It survived multiple failure modes during initial development. Any change here risks breaking the BG/EN audit pages, the PSI proxy integration, or the security boundary around the API key.
src/pages/
tools/audit/index.astro ← BG entry point (route: /tools/audit/)
tools/audit/_audit-body.html ← BG-localized scan form HTML
tools/audit/_audit-styles.css ← Audit's custom CSS, scoped to .audit-page
tools/audit/_audit-script.js ← Tool logic (PSI orchestration, scoring,
ROI calc, 6 layers). Shared between BG/EN.
en/tools/audit/index.astro ← EN entry point (route: /en/tools/audit/)
en/tools/audit/_audit-body.html ← EN-localized scan form HTML
public/tools/audit/
.htaccess ← Per-route CSP override:
`connect-src 'self' https: data:`
wildcard required for arbitrary scan targets
cors-proxy.php.template ← Template for /cors-proxy.php server file
psi-proxy.php.template ← Template for /psi-proxy.php server file
Server-only files (NEVER in git, NEVER in dist, NEVER in rsync --delete):
/psi-proxy.php — Multi-key Google PSI proxy (key rotation)
/cors-proxy.php — General-purpose CORS proxy for scanning targets
The audit’s standalone CSS uses global selectors (*, body, a, h1-h6).
These are prefixed with .audit-page so they don’t leak into BaseLayout’s
nav/footer. The <Fragment set:html={auditBody} /> is wrapped in
<div class="audit-page"> for this scope to apply.
If you re-extract from a standalone source, run the scoping pass:
css = css.replace(/:root\s*\{([^}]+)\}/, '.audit-page {$1}');
css = css.replace(/^body\s*\{/gm, '.audit-page {');
css = css.replace(/^body::before\s*\{/gm, '.audit-page::before {');
css = css.replace(/^\*\s*\{/gm, '.audit-page * {');
css = css.replace(/^a\s*\{/gm, '.audit-page a {');
css = css.replace(/^a:hover\s*\{/gm, '.audit-page a:hover {');
css = css.replace(/^code,kbd,pre,\.mono\s*\{/gm, '.audit-page :is(code,kbd,pre,.mono) {');
css = css.replace(/^(h[1-6])\s*\{/gm, '.audit-page $1 {');
BaseLayout provides them. Standalone snapshots include duplicates that must be stripped:
body = body
.replace(/<!-- NAV -->[\s\S]*?<\/nav>/m, '')
.replace(/<!-- FOOTER -->[\s\S]*?<\/footer>/m, '');
_audit-script.js MUST keep EMBEDDED_PSI_KEY = ''. The real key lives on
the server in /psi-proxy.php (gitignored, kept out of rsync). Audit calls
go through /psi-proxy.php?url=...&strategy=... not googleapis.com directly.
The .api-key-ui and .api-key-spacer elements in the body are
permanently hidden by the IIFE in _audit-script.js.
Chrome’s heuristic injects saved passwords into ANY input on a same-domain
page. The audit URL inputs use type="search", name="audit-target-url",
plus decoy hidden username + password fields BEFORE the real input to
absorb autofill.
public/tools/audit/.htaccess widens connect-src to 'self' https: data:
because the audit fetches arbitrary HTTPS targets. Site-wide CSP keeps
strict 'self'. NEVER widen the site-wide CSP to match.
Both files are excluded from rsync --delete in scripts/deploy.sh.
If you ever wipe the Hostinger /public_html, restore from
*.php.template files in public/tools/audit/. Both have:
SHA256(_audit-body.html, BG) = cf053a30...49af88
SHA256(_audit-body.html, EN) = 1690e11b...423f5c5
SHA256(_audit-styles.css) = a6b4d8e7...083ea6
SHA256(_audit-script.js) = 2679c55c...d86b8cb5
SHA256(index.astro, BG) = a29698960...8a0c27
SHA256(index.astro, EN) = 81a59805...431515
If npm run deploy warns about hash drift, investigate before pushing.
git checkout audit-stable-v1.0 -- src/pages/tools/audit src/pages/en/tools/audit
Or full revert:
git checkout audit-stable-v1.0