Files
k1nq 63d065011b Update manifest.json and infra README
- 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.
2026-09-23 10:57:27 +05:00
..

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; lint ruff, types ty, tests pytest.
  • API: uvicorn app.main:app, health endpoint GET /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 in VITE_* — 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.