Backend service for LLM-powered incident analysis in the Baskerville WordPress security plugin.
Deployed at https://api.baskerville.ai.
WordPress sites running the Baskerville plugin detect traffic and decision spikes locally, then POST aggregated statistics here. The service calls an LLM (OpenAI or Anthropic), generates an incident report, and returns recommended defensive actions (block country, block ASN, raise challenge threshold, etc.).
The plugin never sends raw IPs or visitor PII — only aggregate histograms and counts.
WordPress plugin (every 5 min)
├── Saves 5-min snapshot: traffic/block/challenge counts,
│ country/fingerprint/UA/ASN histograms, immature_ratio
├── Detects spike (3x vs 30-min baseline)
└── POST /v1/analyze → { job_id }
Plugin polls GET /v1/report/{job_id} every 2 min
└── status: ready → { actions[], reasoning, report_markdown }
LLM runs asynchronously — the plugin gets a job_id immediately and polls for the result.
Submit a spike payload for LLM analysis.
{
"license_key": "...",
"domain": "example.com",
"spike_type": "traffic | decisions | both",
"spike_factor": 163.4,
"current_snapshot": {
"traffic_count": 1958,
"block_count": 847,
"immature_ratio": 0.97,
"countries": { "SG": 1840, "US": 12 },
"fingerprints": { "webdriver": 89 },
"asns": { "ALIBABA-US (AS45102)": 1820 }
},
"baseline_snapshot": { ... },
"timeline": [ ... ],
"ip_overlap": { "overlap_count": 340, "overlap_pct": 49.1 }
}Returns immediately:
{ "job_id": "550e8400-e29b-41d4-a716-446655440000" }Poll for result.
{
"status": "pending | ready | error",
"actions": [
{ "type": "block_asn", "target": "ALIBABA-US (AS45102)", "ttl_hours": 2 },
{ "type": "block_country", "target": "SG", "ttl_hours": 2 }
],
"reasoning": "97% of attack traffic originates from Alibaba Singapore...",
"report_markdown": "## Incident Report\n..."
}Job TTL: 2 hours.
{ "status": "ok" }app/
main.py # FastAPI app, /health
llm.py # LLM abstraction (OpenAI / Anthropic)
jobs.py # In-memory job store with TTL
routers/
analyze.py # POST /v1/analyze
report.py # GET /v1/report/{job_id}
Dockerfile
deployment.yaml # Kubernetes: Deployment + Service + Ingress
requirements.txt
| Env var | Default | Description |
|---|---|---|
LLM_PROVIDER |
openai |
LLM backend: openai or anthropic |
OPENAI_API_KEY |
— | Required when LLM_PROVIDER=openai |
ANTHROPIC_API_KEY |
— | Required when LLM_PROVIDER=anthropic |
Kubernetes cluster (same as Baskervillehall), ingress-nginx at 162.19.110.101.
# Build and push
docker buildx build --platform linux/amd64 -t equalitie/baskerville-cloud:latest .
docker push equalitie/baskerville-cloud:latest
# Deploy
kubectl apply -f deployment.yaml
kubectl rollout restart deployment baskerville-cloud
kubectl rollout status deployment baskerville-cloudTLS is managed by cert-manager (letsencrypt-prod).