# 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= DB_HOST= DB_PORT=5432 DB_NAME=maskan_crm DB_USER= DB_PASSWORD= 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.