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

70 lines
3.1 KiB
Markdown

# 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
```sh
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:
```sh
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`.