Surveyed ~/dev (mewtwo) + jirachi. Battery mirrors actual workload:
mcp_server -> 9 MCP servers (joplin/obsidian/vault/project-rag/...)
tts_pipeline -> TTS/audio pipelines (Chatterbox, aygea-tts, vr-to-tts)
webhook_bridge -> Twitch/Discord bridges (multistream, notifier, overlay)
data_service -> data/API (Supabase MCP, PostgresHA, dashboard)
automation_glue -> batch/cron glue (fix-tokens, notesCleanup)
rust_service -> big Rust services (NineSentry, aystreamer): tokio
channels + Arc/Mutex + error enums + graceful shutdown
Each prompt is ~2-3KB (fits 128k context with output room), single-file,
runnable, graded on the same 5-pillar rubric. aygea_test_battery.md is the
index + scoring notes + the prompt_id schema the dashboard will need for
multi-prompt support.
Co-Authored-By: Claude <noreply@anthropic.com>
23 lines
1.9 KiB
Plaintext
23 lines
1.9 KiB
Plaintext
Write a complete, single-file HTTP webhook bridge in Python 3.11+ (stdlib `http.server` / `asyncio`) OR Node.js (stdlib `http`). It receives Twitch-style EventSub webhook events on `POST /webhook` and forwards them to a mock Discord webhook.
|
|
|
|
### Behavior
|
|
- Receive JSON webhook payloads of the form `{"event_id": "...", "type": "chat", "data": {...}}`.
|
|
- For each valid event, POST a small summary to the Discord webhook (mock it as `async def discord_send(payload)` that succeeds ~95% of the time and occasionally returns HTTP 429 with a `Retry-After` header).
|
|
- Reject anything that isn't a valid signed event.
|
|
|
|
### Requirements
|
|
1. **HMAC signature verification:** every request must carry a header `X-Signature: <hex sha256 hmac of the raw body>` computed with a shared secret. Mismatch → `401 Unauthorized`. Use `hmac.compare_digest` for constant-time comparison.
|
|
2. **Idempotency:** maintain an in-memory store keyed by `event_id`. If the same id is seen again within 5 minutes, skip forwarding and return `200` (replayed). Evict stale entries.
|
|
3. **Rate limiting:** a token-bucket limiter capping Discord forwards to **5 per second**. When exceeded, queue/delay rather than spamming.
|
|
4. **429 backoff:** when Discord returns 429, read `Retry-After` and back off that many seconds before retrying (once).
|
|
5. **No silent failures:** malformed JSON, missing headers, and downstream errors must produce clear responses/logs, never a bare 500 or a swallowed exception.
|
|
|
|
### Included tests
|
|
Include a runnable test section that:
|
|
- a) Sends a correctly-signed request → forwarded once, returns 200.
|
|
- b) Sends a tampered signature → 401, nothing forwarded.
|
|
- c) Replays the same event_id within 5 min → skipped (forward count does not increase).
|
|
- d) Bursts >5 events in one second → asserts the rate limiter delayed the excess (no more than 5 forwards/sec).
|
|
|
|
Provide clean, well-commented code that runs directly via `python file.py`.
|