#3: Stored XSS in stats dashboard - escape p[path] with html.escape() #4: Caddy timeout race - increase read/write_timeout 30s -> 60s #5: Missing CSP header - add Content-Security-Policy to Caddyfile
4.4 KiB
4.4 KiB
AGENTS — AO3 Mirror v5
This file is for AI agents (Hermes, Claude Code, Codex) working on the AO3 reverse proxy mirror.
Project Overview
AO3 Mirror v5 is a high-performance reverse proxy for archiveofourown.org, redesigned from the ground up with sticky sessions, Service Worker client-side caching, and a full 5000-proxy P2C pool — matching the go3 architecture with modern Python tooling.
- Domain: agento3.miscs.dev (behind Cloudflare CDN)
- Target: archiveofourown.org
- Stack: Python 3.11, FastAPI, uvicorn + uvloop + httptools, curl_cffi, Caddy
- Proxy Pool: 5000 WebShare proxies, P2C selection, state machine (healthy/unstable/blocked/probing)
- Client: Service Worker for static cache + offline fallback
- Architecture Reference: https://tomorin.cv/AO3-CN/go3 (go3 v2 branch)
Architecture v5
User Browser
│ ao3_sessid_proxy cookie = sticky proxy
│
├─ Service Worker (sw.js)
│ ├─ Cache API — static assets cached in browser
│ ├─ Navigation intercept — offline mirror picker
│ └─ Request passthrough — for non-static, non-nav
│
└─ HTTPS → Caddy → 2× uvicorn workers (8081-8082)
│
├─ Proxy Pool (5000, P2C selection)
│ ├─ State machine: healthy/unstable/blocked/probing
│ ├─ Concurrency limit: asyncio.Semaphore(400)
│ └─ Passive probing: 10s interval, 10 concurrency
│
├─ Sticky Session (ao3_sessid_proxy)
│ └─ User pinned to one proxy for session duration
│
├─ Service Worker Deploy (/sw.js, /sw-YYYYMMDD.js)
│ └─ HTML injection: auto-register SW on page load
│
├─ CF Challenge → User Browser
│ └─ All proxies blocked → rewrite challenge → browser solves
│
├─ Static Cache (server-side LRU + disk MD5)
│
└─ Local routes: /stats, /health, /metrics
Build Commands
# Start all workers + reload Caddy
cd /home/ubuntu/ao3-mirror && bash start.sh
# Stop everything
cd /home/ubuntu/ao3-mirror && bash stop.sh
# Restart daemon only
sudo systemctl restart ao3-daemon
# Restart Caddy only
sudo systemctl reload caddy
# Syntax check all Python files
python3 -m py_compile proxy_pool.py ao3_fetcher.py app.py cache.py stats.py url_rewriter.py
# Deploy Service Worker update
# 1. Edit static/sw.js
# 2. Update SERVICE_WORKER_DATE in app.py
# 3. Restart workers
Core Files (v5)
| File | Purpose |
|---|---|
app.py |
FastAPI backend v5 — proxy handler, sticky sessions, SW deploy, stats |
proxy_pool.py |
P2C proxy pool v5 — 5000 proxies, state machine, semaphore limiter |
ao3_fetcher.py |
Single-request fetcher v5 — no internal retry, CF detection |
cache.py |
Per-worker LRU cache (5000 entries, path-differentiated TTL) |
stats.py |
In-memory stats with batch SQLite flush every 60s |
url_rewriter.py |
URL/header rewriting (ao3 → mirror domain) |
static/sw.js |
Service Worker — client-side cache, offline fallback |
Caddyfile |
Caddy config — SW routes, round-robin, 60s timeouts |
scripts/daemon.py |
Passive worker supervision (systemd) |
start.sh |
Startup — kills old workers, starts new, reloads Caddy |
Security Baseline
- No secrets in code — proxy credentials in
/home/ubuntu/proxy.txt - Workers bound to 127.0.0.1 only
- Cloudflare CDN terminates TLS at edge
- CORS headers restrict cross-origin access
- stats/health/metrics are read-only
Engine Guidance
- Complex multi-file changes, architecture evolution → Hermes (here)
- Quick targeted fixes, single-file changes → Hermes
- Deploy, monitor, notify, schedule → Hermes
- Proxy pool refresh → Hermes cron (30min)
- Not sure? Start with Hermes — everything runs via Hermes
Monitoring
- Health: https://agento3.miscs.dev/health
- Stats: https://agento3.miscs.dev/stats
- Metrics: https://agento3.miscs.dev/metrics
- SW: https://agento3.miscs.dev/sw.js → /sw-YYYYMMDD.js
CTO Goal (Persistent Focus)
Manage akiba/agento3 as CTO. Triage issues hourly, implement top priority, get founder approval before merging. Never ship without YES.
Commit Conventions
- One commit per meaningful change
- Python files only (no binaries, .pyc, logs, .env)
- SOUL.md updated for architectural changes
- ao3-mirror skill updated when workflows change