Files
crm-system/README.md
T
2026-06-03 23:51:59 +00:00

144 lines
4.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CRM System v1.0
> Self-hosted CRM for small sales teams (525 sales reps).
> Stack: FastAPI + SQLAlchemy (async) + Alembic + Pydantic v2 + SQLite/PostgreSQL + Alpine.js + Tailwind + Docker + Coolify
## Quick Start (Development)
### 1. Clone and Setup
```bash
git clone <repo-url> crm-system
cd crm-system
# Create virtual environment
python3 -m venv .venv
source .venv/bin/activate
# Install dependencies
pip install -r requirements.txt -r requirements-dev.txt
```
### 2. Configure Environment
```bash
# Copy template
cp .env.example .env
# Generate a secure AUTH_SECRET (min 32 chars)
python3 -c "import secrets; print('AUTH_SECRET=' + secrets.token_urlsafe(48))" >> .env
# Edit .env and set AUTH_SECRET (remove the placeholder line first)
```
### 3. Initialize Database
```bash
# Apply migrations
alembic upgrade head
# (Optional) Create migration after model changes
# alembic revision --autogenerate -m "description"
```
### 4. Run Server
```bash
# Development with auto-reload
uvicorn app.main:app --reload --port 8000
# Production-like
uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 2
```
Open:
- API: http://localhost:8000
- Swagger UI: http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc
- Health: http://localhost:8000/health
### 5. Bootstrap First User
```bash
curl -X POST http://localhost:8000/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "admin@example.com",
"password": "secure-password-123",
"name": "First Admin"
}'
```
This creates the first user + a default org. After that, registration is disabled (use admin invite flow in v1.1).
## Project Structure
```
crm-system/
├── app/ # Application package
│ ├── main.py # FastAPI entry point
│ ├── core/ # Core modules (config, db, security, deps)
│ ├── models/ # SQLAlchemy models
│ ├── schemas/ # Pydantic schemas (request/response)
│ ├── services/ # Business logic layer
│ ├── api/v1/ # API routers (versioned)
│ └── webui/ # Static frontend (Phase 4c)
├── alembic/ # Database migrations
│ ├── env.py # Async migration environment
│ └── versions/ # Migration scripts
├── tests/ # Test suite (pytest + pytest-asyncio)
├── requirements.txt # Production dependencies
├── requirements-dev.txt # Test/lint dependencies
├── pyproject.toml # Tool configuration
├── alembic.ini # Alembic configuration
├── .env.example # Environment template
└── README.md
```
## Testing
```bash
# Run all tests
pytest -v --tb=short
# Run with coverage
pytest --cov=app --cov-report=term-missing
# Run specific test file
pytest tests/test_auth.py -v
# Stop on first failure (for debugging)
pytest -x
```
## Environment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
| `AUTH_SECRET` | ✅ | | JWT signing secret (≥32 chars). Hard-fail if missing. |
| `DATABASE_URL` | ❌ | `sqlite+aiosqlite:///./dev.db` | Async DB URL (aiosqlite or asyncpg) |
| `JWT_ALGORITHM` | ❌ | `HS256` | JWT algorithm |
| `JWT_EXPIRY_HOURS` | ❌ | `24` | Token lifetime |
| `BCRYPT_ROUNDS` | ❌ | `12` | Password hashing cost |
| `CORS_ORIGINS` | ❌ | `http://localhost:5500,http://localhost:8000` | Allowed origins (comma-separated, NO wildcards) |
| `ENVIRONMENT` | ❌ | `development` | `development` or `production` |
| `LOG_LEVEL` | ❌ | `INFO` | Python log level |
## Architecture Decisions (ADR)
- **JWT Library**: `python-jose[cryptography]==3.3.0` (pattern reuse from wochenplaner)
- **Database**: SQLite (aiosqlite) for dev, PostgreSQL (asyncpg) for prod
- **Auth**: Stateless JWT in localStorage, bcrypt password hashing (12 rounds)
- **Security**: CORS whitelist (no wildcard), CSP middleware, no default admin user
- **Async**: All routers/services/DB operations are async (SQLAlchemy 2.0 + aiosqlite)
See `/a0/.a0/02-architecture.md` Section 13 for full lockdown decisions.
## Deployment
See `/a0/.a0/03-task-graph.json` Phase 4d for Docker + Coolify setup (out of scope for Phase 4a).
## License
Internal project proprietary.