Files
maskanx_cm_backend/README.md
T
AFFAANhandClaude Opus 5 4d205c1086 docs(campaigns): document phase 1 campaign management
Records what Phase 1 does and deliberately does not do: no Meta writes, no
launch or sync endpoint, previews rendered without creating objects, budget
minimums enforced locally, and the fact that a payment method can only be
attached in Meta Business Manager.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 19:06:14 +05:30

172 lines
6.2 KiB
Markdown

# MaskanX Backend
Independent Python and FastAPI backend for MaskanX.
## Service Contract
- Default API URL: `http://127.0.0.1:8088`
- PostgreSQL database: `campaign`
- Frontend origin: configured with `MASKANX_CORS_ORIGINS`
- Maskan CRM: connected through its versioned REST API and optional MCP tools
This repository never connects directly to the Maskan CRM PostgreSQL database.
## Local Setup
1. Create the database:
```sql
CREATE DATABASE campaign;
```
2. Install dependencies and configure the environment:
```powershell
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -e ".[dev]"
npm install
Copy-Item .env.local.example .env.local
```
3. Migrate, seed, and start:
```powershell
npm run local:migrate
npm run local:seed
npm run local
```
Open API documentation at `http://127.0.0.1:8088/docs` when documentation is
enabled.
### Upgrading from JSON storage
Chats and cron jobs were originally stored as JSON files in the working
directory (`~/.adclaw/chats.json` and `~/.adclaw/jobs.json`). PostgreSQL is now
the default backend, so those records are no longer read and existing chats,
sessions, and scheduled jobs appear to be missing even though nothing was
deleted.
Copy them into PostgreSQL once:
```powershell
npm run local:import-json -- --dry-run # report what would be imported
npm run local:import-json # perform the import
```
The import upserts by id and never deletes, so it is safe to re-run. The JSON
files are left untouched as a backup.
## Campaigns
Campaign records live in PostgreSQL. Apply the schema before first use:
```powershell
npm run local:migrate
```
Set `META_ADS_ACCESS_TOKEN` in Settings > Environments, and enable the
`meta_ads` MCP client if you also want campaign tools in chat.
### What Phase 1 does and does not do
Phase 1 owns campaign records, the approval workflow, budget guardrails and ad
preview. **It creates nothing in Meta.** The only Meta calls are two reads:
- `GET /act_<id>` for balance, spend and `min_daily_budget`
- `GET /act_<id>/generatepreviews` to render ad previews
There is deliberately no launch or sync endpoint. A campaign moves
`draft -> pending_approval -> approved` and stops there; pushing objects to
Meta arrives in Phase 2.
Ad previews are rendered from a creative spec and create no Meta objects, so
the wizard can show exactly how an ad will look across desktop feed, mobile
feed, Instagram feed, Instagram story, Facebook story and right column before
anything exists.
### Budget minimums
Each ad account publishes a `min_daily_budget` in minor units. The API rejects
a lower daily budget with `422` and a readable message rather than letting Meta
reject it opaquely later. If the account cannot be read (no token, rate limit),
the check is skipped and a warning is logged: the budget guardrail is not
enforced in that case.
### Delivery requires a payment method
Meta will not deliver ads until a funding source is attached to the ad account.
**This cannot be done from MaskanX** — the Marketing API does not allow
creating funding instruments, so it must be done in Meta Business Manager. The
Campaigns page shows a warning when no payment method is present.
### Clearing and restoring credentials
**Stop MaskanX before clearing credentials.** A running app holds its
configuration in memory and can rewrite `config.json` and `providers.json`
after the clear, silently restoring the values that were just removed. The
clear script now verifies the result and exits non-zero if anything
secret-looking survives.
Credentials live in three places, and all of them are cleared:
- `~/.adclaw.secret/providers.json` - LLM provider keys
- `~/.adclaw.secret/envs.json` - integration keys
- `~/.adclaw/companies/<id>/` - a per-company copy of both, plus LinkedIn OAuth
Because each company keeps its own copy, an intact company store can be used to
recover the active one:
```powershell
npm run secrets:restore -- --from default --dry-run
npm run secrets:restore -- --from default
```
Credential files are copied wholesale; `config.json` is patched surgically, so
only missing MCP env values and disabled clients are restored and
company-specific settings are preserved. A backup is written to
`~/.adclaw.secret/restore-backups/` first.
## Commands
| Command | Purpose |
| --- | --- |
| `npm start` | Start using `.env` or injected environment variables |
| `npm run build` | Build a Python wheel in `dist/` |
| `npm run local` | Local API with reload |
| `npm run local:migrate` | Apply local PostgreSQL migrations |
| `npm run local:migrate:undo` | Roll back the newest migration |
| `npm run local:migrate:undo:all` | Roll back every migration |
| `npm run local:seed` | Add starter data |
| `npm run local:seed:undo` | Remove starter data |
| `npm run local:import-json` | Import legacy JSON chats/cron jobs into PostgreSQL |
| `npm run secrets:dry-run` | Report which credentials a clear would remove |
| `npm run secrets:clear` | Clear runtime credentials (creates a backup) |
| `npm run secrets:clear:all` | Also blank secret lines in `.env` files (creates a backup) |
| `npm run secrets:delete:all` | Clear everything including `.env` files (creates a backup) |
| `npm run secrets:delete:all:no-backup` | Same, with **no backup** - irreversible |
| `npm run secrets:restore` | Restore credentials from an intact company store |
| `npm run local:reset` | Rebuild and seed the local schema |
| `npm run dev` | Development API with reload |
| `npm run dev:migrate` | Apply development migrations |
| `npm run dev:reset` | Reset the development schema |
| `npm test` | Run Pytest using `.env.testing` |
| `npm run test:migrate` | Apply test database migrations |
| `npm run test:reset` | Reset the test schema |
| `npm run prod` | Start the production API |
| `npm run prod:migrate` | Apply production migrations |
| `npm run prod:seed` | Apply production starter data |
The command names match the platform deployment contract. They invoke the
native MaskanX Python migration runner, not Sequelize.
## Docker
```powershell
Copy-Item .env.local.example .env
docker compose up -d --build
```
For a managed PostgreSQL deployment, provide `DATABASE_URL` through the hosting
secret manager and run `npm run prod:migrate` as a release step.