Upload README.md
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
# CRM System v1.0
|
||||
|
||||
> Self-hosted CRM for small sales teams (5–25 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.
|
||||
Reference in New Issue
Block a user