- Updated timestamps and AST hashes in manifest.json for various backend and frontend files to reflect recent changes. - Added new files related to MCC categories and optional hold reasons in the manifest. - Modified the README in the infra directory to correct the linting tool from 'mypy' to 'ty' for type checking in the backend project.
3.1 KiB
infra/
Local development stack and provider-neutral production images. Root-owned dirs
(backend/, frontend/) are owned by their respective workstreams; this
directory owns only orchestration, images and proxy configuration.
infra/
├── docker-compose.yml # dev stack: api, worker, frontend proxy, pg, redis, minio, mailpit
├── .env.example # copy to infra/.env; placeholders only, no real secrets
├── docker/
│ ├── Dockerfile.backend # provider-neutral API/worker image (context: backend/)
│ └── Dockerfile.frontend # provider-neutral SPA+nginx image (context: frontend/)
└── nginx/
└── nginx.conf # same-origin /api/v1 reverse proxy + SPA static
Quickstart
cp infra/.env.example infra/.env # fill placeholders (no real secrets locally)
docker compose -f infra/docker-compose.yml up -d --wait
| Service | URL / port | Notes |
|---|---|---|
| Web app (nginx proxy) | http://127.0.0.1:8080 | serves SPA, proxies /api/v1 → api:8000 |
| API (direct) | http://127.0.0.1:8000 | FastAPI; GET /healthz |
| Mailpit UI | http://127.0.0.1:8025 | test SMTP sink; SMTP on 127.0.0.1:1025 |
| MinIO console | http://127.0.0.1:9001 | S3 API on 127.0.0.1:9000 |
| PostgreSQL | 127.0.0.1:5432 | named volume postgres_data |
| Redis | 127.0.0.1:6379 | AOF persistence, named volume redis_data |
Until backend/ and frontend/ exist, start infra services only:
docker compose -f infra/docker-compose.yml up -d --wait postgres redis minio mailpit
Contracts with backend/frontend workstreams
These entry points are referenced by the compose file and CI; coordinate changes through both sides:
Backend (backend/, build context of Dockerfile.backend):
- uv-managed project with
pyproject.toml+uv.lock; lintruff, typesty, testspytest. - API:
uvicorn app.main:app, health endpointGET /healthz. - Worker: Celery app importable as
app.worker.celery; tasks idempotent,acks_late,prefetch=1. - Statement parsing happens only in the worker; the local compose worker is attached only to the internal backend network, and production must enforce the equivalent no-egress policy.
Frontend (frontend/, build context of Dockerfile.frontend):
- pnpm project with
pnpm-lock.yaml; scripts:lint,typecheck,test(non-watch),build→dist/. - Calls the same-origin
/api/v1; no secrets inVITE_*— none are required.
CI
.github/workflows/ci.yml runs backend lint/type/test/build and frontend
lint/type/test/build once the workstreams provide the plan-required lockfiles
(backend/uv.lock, frontend/pnpm-lock.yaml; auto-detected), and always
validates the compose file, boots the infra services against their healthchecks,
and nginx -t-checks the proxy config.
Production
Production runs the same images on a platform in the Russian Federation that
supplies PostgreSQL, Redis, S3-compatible storage, SMTP and a secret manager.
See docs/adr/0004-provider-neutral-encrypted-data-boundary.md and
docs/operations/beta-release-runbook.md.