API authentication:
- Add X-API-Secret shared-secret header validation on /chat and /stats
- /health remains public for monitoring
- Auth is a no-op when API_SECRET is empty (dev mode)
Rate limiting:
- Add per-user sliding-window rate limiter on /chat (10 req/60s default)
- Returns 429 with clear message when exceeded
- Self-cleaning memory (prunes expired entries on each check)
Exception sanitization:
- Discord bot no longer exposes raw exception text to users
- Error embeds show generic "Something went wrong" message
- Full exception details logged server-side with context
- query_chat_api RuntimeError no longer includes response body
Async correctness:
- Wrap synchronous RuleRepository.search() in run_in_executor()
to prevent blocking the event loop during SentenceTransformer inference
- Port contract stays synchronous; service owns the async boundary
Test coverage: 101 passed, 1 skipped (11 new tests for auth + rate limiting)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Discord bot: store full conversation UUID in footer instead of truncated
8-char prefix, fixing completely broken follow-up threading. Add footer
to follow-up embeds so conversation chains work beyond depth 1. Edit
loading message in-place instead of leaving ghost messages. Replace bare
except with specific exception types. Fix channel_id attribute access.
- GiteaClient: remove broken async context manager pattern that caused
every create_unanswered_issue call to raise RuntimeError. Use per-request
httpx.AsyncClient instead.
- Database: return singleton ConversationManager from app.state instead of
creating a new SQLAlchemy engine (and connection pool) on every request.
- Vector store: clamp cosine similarity to [0, 1] to prevent Pydantic
ValidationError crashes when ChromaDB returns distances > 1.0.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add vector store with sentence-transformers for semantic search
- FastAPI backend with /chat and /health endpoints
- Conversation state persistence via SQLite
- OpenRouter integration with structured JSON responses
- Discord bot with /ask slash command and reply-based follow-ups
- Automated Gitea issue creation for unanswered questions
- Docker support with docker-compose for easy deployment
- Example rule file and ingestion script
- Comprehensive documentation in README