diff --git a/AGENTS.md b/AGENTS.md index 363b73f..51aa001 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -30,9 +30,11 @@ This repository owns deployment concerns only. Backend and frontend directories - Everything runs through Docker, Docker Compose, Bash scripts, and environment files/templates. - The CSV-to-PostgreSQL workflow is a one-time administrative bootstrap/recovery command, never a scheduled ingestion service. ZarinPal owns future production payment writes. - An idempotent authenticated start request enqueues overview, payment-performance, fees, and peer-comparison jobs for bounded parallel calculation by a separate on-demand Go worker. Redis caches/coordinates each section for 30 days, and a separate authenticated SSE request streams partial completion. This worker is event-driven, never scheduled. +- The worker uses Asynq pinned to `v0.26.0`. Asynq is pre-`v1.0.0`; never use a floating dependency or upgrade it without compatibility review and passing queue/retry/recovery tests. - Each section attempt has a 60-second timeout and at most two automatic retries for transient failures using exponential backoff with jitter. Deterministic failures are not retried. +- Default worker limits are 16 concurrent jobs globally and 4 per merchant. Analytics starts are limited to 10/minute with burst 3; failed-section manual retries to 3/10 minutes with burst 1; SSE to 2 concurrent streams/user and 4/merchant. Limits are enforced in independent authenticated-user and merchant buckets, configured through validated environment values, and return `429` plus `Retry-After` before work is queued. - Redis and the analytics worker are private Compose services with health checks and resource limits; neither is exposed through Nginx. Redis is disposable cache/coordination state and is excluded from backup/restore. -- Nginx disables response buffering/compression for the SSE route, preserves authenticated same-origin cookies and event ids, and uses reviewed stream timeouts/heartbeat behavior without weakening normal API proxy settings. +- Nginx disables response buffering/compression for the SSE route, preserves authenticated same-origin cookies and event ids, allows 15-second heartbeats, and supports one-hour authorized replay/snapshot recovery without weakening normal API proxy settings. - Nginx is the only public entry point. PostgreSQL and internal services are not internet-exposed. - Health checks distinguish liveness from readiness. - Backups are encrypted where supported, validated, retention-aware, and paired with rehearsed restores. diff --git a/CAPABILITY-MAP.md b/CAPABILITY-MAP.md index f2be247..d89e9fc 100644 --- a/CAPABILITY-MAP.md +++ b/CAPABILITY-MAP.md @@ -53,6 +53,8 @@ Build sequence: data foundation → identity and analytics → API → dashboard 11. An idempotent start request enqueues overview, payment-performance, fees, and peer-comparison sections for bounded parallel calculation by a separate Go worker; Redis caches each typed section for 30 days under merchant/cohort and metric-definition revisions. 12. A separate authenticated SSE request exposes each section as it becomes ready. Redis and the on-demand worker remain private, and Redis is never a source of truth or backup target. 13. Each section attempt is limited to 60 seconds and at most two transient retries with exponential backoff/jitter; deterministic errors fail immediately. +14. The worker pins pre-1.0 Asynq `v0.26.0`, runs at 16 jobs globally and 4/merchant by default, and changes require reviewed dependency/load evidence. +15. Start, manual-retry, and SSE limits use independent authenticated-user/merchant buckets and return `429` with `Retry-After` before work is queued. SSE heartbeats run every 15 seconds and authorized run-event replay lasts one hour. ## Required capability specs