Initial commit: Visigine (Vite client + Express/SQLite backend)
Container-ready via docker/ compose (frontend nginx + backend Node). Compose adjusted for Coolify on the prod server: frontend uses expose:80 (no host binding — host 8080 is taken by the Coolify proxy; Traefik routes visigine.de), backend ALLOWED_ORIGINS=https://visigine.de. Secrets stay in server/.env (git-ignored); see server/.env.example. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
43
server/checks/ai-reachability.js
Normal file
43
server/checks/ai-reachability.js
Normal file
@@ -0,0 +1,43 @@
|
||||
// Group F — probe the target with AI bot user agents to detect WAF/CDN blocking.
|
||||
const BLOCKED_STATUSES = new Set([403, 429, 451, 503, 0])
|
||||
|
||||
const PROBES = [
|
||||
{
|
||||
id: 'ai-reach.claudebot',
|
||||
title: 'ClaudeBot wird blockiert (Cloudflare oder Firewall)',
|
||||
userAgent: 'ClaudeBot/1.0 (+https://www.anthropic.com)',
|
||||
},
|
||||
{
|
||||
id: 'ai-reach.gptbot',
|
||||
title: 'GPTBot wird blockiert (Cloudflare oder Firewall)',
|
||||
userAgent: 'GPTBot/1.0 (+https://openai.com/gptbot)',
|
||||
},
|
||||
]
|
||||
|
||||
export async function runAiReachabilityChecks({ targetUrl, mainStatus, fetchPage }) {
|
||||
// If the baseline fetch already failed, the probes would be misleading —
|
||||
// mark both as failed but skip the network calls.
|
||||
if (mainStatus !== 200) {
|
||||
return PROBES.map((p) => ({
|
||||
id: p.id,
|
||||
title: p.title,
|
||||
severity: 'high',
|
||||
passed: false,
|
||||
}))
|
||||
}
|
||||
|
||||
const probeResults = await Promise.all(
|
||||
PROBES.map((p) => fetchPage(targetUrl, { userAgent: p.userAgent }))
|
||||
)
|
||||
|
||||
return PROBES.map((p, i) => {
|
||||
const status = probeResults[i].status
|
||||
const blocked = BLOCKED_STATUSES.has(status)
|
||||
return {
|
||||
id: p.id,
|
||||
title: p.title,
|
||||
severity: 'high',
|
||||
passed: !blocked,
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user