From d98d73b14aefb685c6e767e1255e6445aa08ac4c Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Fri, 24 Apr 2026 17:34:27 +0200 Subject: [PATCH] Apply final-review cleanup: robots sitemap, CI guards, header parity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove Sitemap line from robots.txt (no @astrojs/sitemap installed; was pointing to a 404 that would trip Google Search Console). - Align Permissions-Policy across all three enforcement layers (middleware, .htaccess, Cloudflare Transform Rule in OPERATOR-CHECKLIST) by dropping the stray fullscreen=(self) from the middleware. - Bump Lighthouse CI numberOfRuns from 1 to 3 to dampen CI-runner noise. - Add CI guard that fails the build if any marker survives into dist/ — prevents a legally incomplete imprint from shipping by accident. - Add SFTP_* secret null-guard before the rsync --delete step so a missing secret fails loudly instead of targeting the SSH user's home root. - Document the set:html compile-time-constant invariant in DualValueProps. Co-Authored-By: Claude Opus 4.7 (1M context) --- .gitea/workflows/deploy.yml | 13 +++++++++++++ lighthouserc.cjs | 2 +- public/robots.txt | 2 -- src/components/sections/DualValueProps.astro | 2 ++ src/middleware.ts | 2 +- 5 files changed, 17 insertions(+), 4 deletions(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index fe07ad0..1ea6580 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -31,6 +31,14 @@ jobs: - name: Build site run: npm run build + - name: Guard — no TBD markers may ship in built HTML + run: | + if grep -rl 'TBD:' dist 2>/dev/null | grep -E '\.(html|svg)$'; then + echo "Built output contains unfilled markers." + echo "Fill in imprint.astro and privacy.astro operator fields before merging to main." + exit 1 + fi + - name: Validate HTML run: npm run lint:html @@ -80,6 +88,11 @@ jobs: SFTP_HOST: ${{ secrets.SFTP_HOST }} SFTP_PATH: ${{ secrets.SFTP_PATH }} run: | + # Fail loudly if any secret is missing — otherwise rsync --delete + # could be directed at the SSH user's home root. + : "${SFTP_USER:?SFTP_USER secret must be set}" + : "${SFTP_HOST:?SFTP_HOST secret must be set}" + : "${SFTP_PATH:?SFTP_PATH secret must be set}" rsync -avz --delete \ -e "ssh -i ~/.ssh/id_ed25519 -o StrictHostKeyChecking=yes -o UserKnownHostsFile=~/.ssh/known_hosts" \ dist/ "$SFTP_USER@$SFTP_HOST:$SFTP_PATH/" diff --git a/lighthouserc.cjs b/lighthouserc.cjs index 23983bf..a9606c0 100644 --- a/lighthouserc.cjs +++ b/lighthouserc.cjs @@ -8,7 +8,7 @@ module.exports = { 'http://localhost/imprint/index.html', 'http://localhost/privacy/index.html', ], - numberOfRuns: 1, + numberOfRuns: 3, settings: { preset: 'desktop', }, diff --git a/public/robots.txt b/public/robots.txt index 137a33f..c2a49f4 100644 --- a/public/robots.txt +++ b/public/robots.txt @@ -1,4 +1,2 @@ User-agent: * Allow: / - -Sitemap: https://www.cameleer.io/sitemap-index.xml diff --git a/src/components/sections/DualValueProps.astro b/src/components/sections/DualValueProps.astro index c92ceeb..6c8a86b 100644 --- a/src/components/sections/DualValueProps.astro +++ b/src/components/sections/DualValueProps.astro @@ -4,6 +4,8 @@ interface Tile { capability: string; } +// tile.capability is a compile-time constant defined below — never feed +// user-supplied or CMS content into set:html further down (XSS risk). const tiles: Tile[] = [ { outcome: 'Cut debugging time in half.', diff --git a/src/middleware.ts b/src/middleware.ts index ab8f1c3..daad692 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -26,13 +26,13 @@ export function buildSecurityHeaders(): Record { "object-src 'none'", ].join('; '); + // Must match .htaccess and the Cloudflare Transform Rule in OPERATOR-CHECKLIST.md. const permissionsPolicy = [ 'geolocation=()', 'microphone=()', 'camera=()', 'payment=()', 'usb=()', - 'fullscreen=(self)', ].join(', '); return {