Backend:
- Structured JSON logging (python-json-logger) with request ID correlation
- RequestIDMiddleware (server-generated UUID, no client trust)
- Global exception handlers: AppException, RequestValidationError, generic 500
— all return consistent {"error": {code, message, request_id}} format
- Async rate limiting with lock + stale key eviction on auth endpoints
- Health endpoint checks DB connectivity, returns version + status
- Custom exception classes (NotFoundException, ForbiddenException, etc.)
- OpenAPI docs with tag descriptions, conditional URL (disabled in production)
- LOG_LEVEL, DOCS_ENABLED, RATE_LIMIT_* settings added
Docker:
- Backend: multi-stage build (builder + runtime), non-root user, HEALTHCHECK
- Frontend: removed dead user, HEALTHCHECK directive
- docker-compose: restart policies, healthchecks, Redis service, named volumes
for uploads/PDFs, rate limit env vars forwarded
- Alembic migrations run only in Dockerfile CMD (removed from lifespan)
Nginx:
- server_tokens off
- CSP, Referrer-Policy, Permissions-Policy headers
- HSTS ready (commented, enable with TLS)
Config & Docs:
- .env.production.example with production-ready settings
- CLAUDE.md project conventions (structure, workflow, naming, how-to)
- .env.example updated with new variables
Review fixes applied:
- Rate limiter: async lock prevents race condition, stale key eviction
- Request ID: always server-generated (no log injection)
- Removed duplicate alembic migration from lifespan
- Removed dead app user from frontend Dockerfile
- Health check logs DB errors
- Rate limit env vars forwarded in docker-compose
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
84 lines
3.3 KiB
Markdown
84 lines
3.3 KiB
Markdown
# AI Assistant - Project Conventions
|
|
|
|
## Tech Stack
|
|
|
|
- **Backend**: Python 3.12, FastAPI, SQLAlchemy 2.0 (async), Alembic, Pydantic v2
|
|
- **Frontend**: React 18, TypeScript, Vite, Tailwind CSS, shadcn/ui, Zustand, TanStack Query
|
|
- **Database**: PostgreSQL 16
|
|
- **AI**: Claude API (Anthropic SDK) with streaming + tool use
|
|
- **Deployment**: Docker Compose (nginx, backend, frontend, postgres, redis)
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
backend/
|
|
app/
|
|
api/v1/ # FastAPI routers (thin controllers)
|
|
core/ # Security, middleware, logging, exceptions
|
|
models/ # SQLAlchemy ORM models (inherit from Base in database.py)
|
|
schemas/ # Pydantic request/response models
|
|
services/ # Business logic layer
|
|
utils/ # Utilities (file storage, text extraction)
|
|
workers/ # Background tasks (document processing, notifications)
|
|
templates/ # Jinja2 templates (PDF generation)
|
|
alembic/ # Database migrations
|
|
scripts/ # Standalone scripts (seed_admin.py)
|
|
tests/ # Pytest test files
|
|
|
|
frontend/
|
|
src/
|
|
api/ # Axios API client modules
|
|
components/ # React components (layout/, chat/, auth/, shared/, etc.)
|
|
hooks/ # Custom React hooks
|
|
stores/ # Zustand state stores
|
|
pages/ # Page components (mapped to routes)
|
|
lib/ # Utilities (cn(), query-client)
|
|
```
|
|
|
|
## Adding a New Feature (Endpoint to UI)
|
|
|
|
1. **Model**: Create in `backend/app/models/`, inherit `Base` from `database.py`
|
|
2. **Migration**: `alembic revision -m "description"` or write manually in `alembic/versions/`
|
|
3. **Schema**: Create Pydantic models in `backend/app/schemas/`
|
|
4. **Service**: Business logic in `backend/app/services/`
|
|
5. **Router**: FastAPI endpoint in `backend/app/api/v1/`, register in `router.py`
|
|
6. **Frontend API**: Typed functions in `frontend/src/api/`
|
|
7. **Page/Component**: React component in `frontend/src/pages/` or `components/`
|
|
8. **Route**: Add to `frontend/src/routes.tsx`
|
|
9. **i18n**: Add keys to both `public/locales/en/` and `ru/translation.json`
|
|
10. **Tests**: Add to `backend/tests/`
|
|
|
|
## Conventions
|
|
|
|
- **Auth**: JWT access (15min) + refresh (24h/30d) tokens. Use `get_current_user` dependency.
|
|
- **Admin**: Use `require_admin` dependency. All admin endpoints under `/api/v1/admin/`.
|
|
- **Ownership**: Always filter by `user_id` — never expose other users' data.
|
|
- **Schemas**: Use `model_config = {"from_attributes": True}` for ORM compatibility.
|
|
- **JSONB columns**: Name the Python attribute `metadata_` with `mapped_column("metadata", JSONB)`.
|
|
- **Error responses**: Use `HTTPException` or `AppException` subclasses.
|
|
- **i18n**: All user-facing strings via `useTranslation()`. Both `en` and `ru` required.
|
|
- **State**: Zustand for client state, TanStack Query for server state.
|
|
- **Sidebar nav**: Add to `navItems` array in `sidebar.tsx`.
|
|
|
|
## Running
|
|
|
|
```bash
|
|
# Development
|
|
cp .env.example .env
|
|
docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build
|
|
|
|
# Production
|
|
cp .env.production.example .env
|
|
docker compose up -d --build
|
|
|
|
# Seed admin user
|
|
docker compose exec backend python scripts/seed_admin.py
|
|
|
|
# Run backend tests (requires test DB)
|
|
docker compose exec backend pytest
|
|
```
|
|
|
|
## Environment Variables
|
|
|
|
See `.env.example` for development and `.env.production.example` for production.
|