121 lines
4.0 KiB
Markdown
121 lines
4.0 KiB
Markdown
# Maskan CRM Backend
|
|||
|
|
|
||
|
|
Independent FastAPI API for Maskan CRM. This repository owns CRM contacts,
|
||
|
|
organizations, leads, pipelines, activities, products, quotes, users,
|
||
|
|
permissions, audit records, and first-party integration credentials.
|
||
|
|
|
||
|
|
## Runtime
|
||
|
|
|
||
|
|
- Python 3.11 to 3.13
|
||
|
|
- FastAPI and SQLAlchemy
|
||
|
|
- Alembic migrations
|
||
|
|
- PostgreSQL 16 for every non-test environment
|
||
|
|
- Node.js 20+ only as a consistent command runner for DevOps
|
||
|
|
|
||
|
|
The API never shares a database or database credentials with MaskanX.
|
||
|
|
|
||
|
|
## Local Setup
|
||
|
|
|
||
|
|
```powershell
|
||
|
|
Copy-Item .env.local.example .env.local
|
||
|
|
npm install
|
||
|
|
python -m venv .venv
|
||
|
|
.\.venv\Scripts\python.exe -m pip install -e ".[dev]"
|
||
|
|
npm run docker:up
|
||
|
|
npm run local:seed
|
||
|
|
```
|
||
|
|
|
||
|
|
`docker:up` starts the API and PostgreSQL. To run the API directly with reload,
|
||
|
|
start only PostgreSQL and use:
|
||
|
|
|
||
|
|
```powershell
|
||
|
|
npm run local:migrate
|
||
|
|
npm run local:seed
|
||
|
|
npm run local
|
||
|
|
```
|
||
|
|
|
||
|
|
### Which PostgreSQL are you pointing at?
|
||
|
|
|
||
|
|
`.env.local.example` ships with `DB_PORT=5433`, the port Docker Compose
|
||
|
|
publishes for this repository's own `maskan-crm-postgres` container. That is
|
||
|
|
correct when you run `npm run docker:up`.
|
||
|
|
|
||
|
|
If you instead use a PostgreSQL you already run locally (usually port `5432`),
|
||
|
|
set `DB_PORT=5432` and `DB_PASSWORD` to that server's password, and create the
|
||
|
|
database first:
|
||
|
|
|
||
|
|
```sql
|
||
|
|
CREATE DATABASE maskan_crm;
|
||
|
|
```
|
||
|
|
|
||
|
|
Pointing at a port where nothing is listening fails with
|
||
|
|
`psycopg.errors.ConnectionTimeout: connection timeout expired` during
|
||
|
|
`local:migrate` or `local:seed`, and the API returns 500s on `/auth/login`
|
||
|
|
(which the browser then reports as a CORS error, because the error response
|
||
|
|
carries no CORS headers).
|
||
|
|
|
||
|
|
Open:
|
||
|
|
|
||
|
|
- API: `http://127.0.0.1:8091`
|
||
|
|
- API docs: `http://127.0.0.1:8091/api/docs`
|
||
|
|
- Readiness: `http://127.0.0.1:8091/health/ready`
|
||
|
|
|
||
|
|
## Lifecycle Commands
|
||
|
|
|
||
|
|
The requested environment command names are available using this backend's
|
||
|
|
native Python tooling. Alembic replaces Sequelize because this is a FastAPI
|
||
|
|
service.
|
||
|
|
|
||
|
|
| Command | Purpose |
|
||
|
|
| --- | --- |
|
||
|
|
| `npm start` | Start using `.env` or injected environment variables |
|
||
|
|
| `npm run build` | Build the Python wheel into `dist/` |
|
||
|
|
| `npm run local` | Start with `.env.local` and reload |
|
||
|
|
| `npm run local:migrate` | Apply local Alembic migrations |
|
||
|
|
| `npm run local:migrate:undo` | Undo the newest local migration |
|
||
|
|
| `npm run local:migrate:undo:all` | Roll back all local migrations |
|
||
|
|
| `npm run local:seed` | Seed the bootstrap workspace and optional demo data |
|
||
|
|
| `npm run local:seed:undo` | Remove the local bootstrap workspace |
|
||
|
|
| `npm run local:reset` | Recreate and seed the local schema |
|
||
|
|
| `npm run dev*` | Equivalent commands using `.env.development` |
|
||
|
|
| `npm test` | Run unit/API tests using `.env.testing` |
|
||
|
|
| `npm run test:migrate` | Apply migrations using `.env.testing` |
|
||
|
|
| `npm run test:seed` | Seed using `.env.testing` |
|
||
|
|
| `npm run test:reset` | Recreate the test schema |
|
||
|
|
| `npm run prod` | Start with production validation enabled |
|
||
|
|
| `npm run prod:migrate` | Apply production migrations |
|
||
|
|
| `npm run prod:seed` | Seed production without demo records |
|
||
|
|
|
||
|
|
## Production
|
||
|
|
|
||
|
|
Supply secrets through the deployment platform, not committed files:
|
||
|
|
|
||
|
|
```text
|
||
|
|
MASKAN_CRM_ENV=production
|
||
|
|
MASKAN_CRM_MODE=standalone
|
||
|
|
MASKAN_CRM_CORS_ORIGINS=https://crm.example.com
|
||
|
|
MASKAN_CRM_JWT_SECRET=<at-least-32-random-characters>
|
||
|
|
DB_HOST=<managed-postgres-host>
|
||
|
|
DB_PORT=5432
|
||
|
|
DB_NAME=maskan_crm
|
||
|
|
DB_USER=<dedicated-user>
|
||
|
|
DB_PASSWORD=<secret>
|
||
|
|
DB_SSLMODE=require
|
||
|
|
```
|
||
|
|
|
||
|
|
Run `npm run prod:migrate` as a release step, then run `npm run prod`.
|
||
|
|
|
||
|
|
## MaskanX Integration
|
||
|
|
|
||
|
|
MaskanX connects to `/api/v1/integrations` with a revocable `mcrm_` service key
|
||
|
|
and idempotency keys. This reliable REST path is the normal product
|
||
|
|
integration. MCP tools are an optional agent interface and do not replace the
|
||
|
|
service-to-service API.
|
||
|
|
|
||
|
|
## Database Policy
|
||
|
|
|
||
|
|
PostgreSQL is the configured database for local, development, testing
|
||
|
|
migrations, staging, and production. A small in-memory SQLite fixture is used
|
||
|
|
inside isolated unit tests only and is rejected as an application runtime
|
||
|
|
database outside the explicit `testing` environment.
|