Aura Audit Tool — STABLE v1.0

🔒 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.


Architecture (read before touching anything)

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

Critical invariants — DO NOT BREAK

1. CSS is scoped to .audit-page

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 {');

2. Body must NOT contain its own

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, '');

3. PSI API key NEVER goes client-side

_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.

4. URL inputs use credential-evasion attributes

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.

5. CSP override stays per-route

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.

6. /psi-proxy.php and /cors-proxy.php are server-only

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:


Stable state hashes (1b3f454c · 2026-05-01)

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.


Restore from this stable version

git checkout audit-stable-v1.0 -- src/pages/tools/audit src/pages/en/tools/audit

Or full revert:

git checkout audit-stable-v1.0