Домен, стек, слои, команды, тесты, базовая ветка test. .claude/code-paths: api/src/, api/alembic/, web/src/. Refs #198 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5.4 KiB
5.4 KiB
Архитектура
Монорепозиторий: api/ (FastAPI) отдаёт REST, WebSocket и собранный фронт; web/ — SPA на React. Основная бизнес-логика — PL/pgSQL-функции схемы v3 в Postgres. Python-слой проверяет роли, валидирует запрос, вызывает функцию и маппит её ошибки.
Поток редактирования ячейки: RealtimeTable → WebSocket /api/v1/ws/form/{id}/sheet/{sheet} (cell_edit_start — блокировка, cell_updated) → SheetService → v3.upd_form_cell(s). Функция проверяет роль и окно этапа и пишет аудит v3.log_event, после чего изменение рассылается остальным подключённым.
Модули
| Модуль | Ответственность | Зависит от |
|---|---|---|
api/src/api/v1/ |
Роутеры: auth, users, admin, audit, forms, projects, form_phases (/stages), phase_template, export, websocket, org_unit, vsp (/dict/info), expense_item, summary (/svod) |
services, deps |
api/src/api/v1/deps.py |
Текущий пользователь из JWT, гарды ролей | repository.user_repository, core.security |
api/src/api/v1/websocket.py |
ConnectionManager, блокировки ячеек в памяти, события форм и FORM_4/проектов, синхронизация сателлитов AHR | services |
api/src/services/ |
Сервисы по сущностям, контроль доступа (access_control_service.py) |
repository |
api/src/services/export_service/ |
Фоновые выгрузки в Excel: ProcessPool, таблица export_job, файлы в tmp/exports, маппинг колонок export_mappings.py |
repository, openpyxl/XlsxWriter |
api/src/repository/ |
SQLAlchemy-запросы и вызовы SQL-функций v3.*, SET LOCAL app.user_id |
db |
api/src/db/ |
engine, Base, сессия, ORM-модели (36) |
core.config |
api/src/domain/ |
pydantic-схемы API, enums | — |
api/src/core/ |
Настройки, JWT/argon2, исключения и маппинг ошибок Postgres в HTTP | — |
api/alembic/ |
Миграции (около 49 ревизий); versions/sql/*.sql — DDL, функции, сиды, около 43 тыс. строк |
Postgres |
web/src/app/ |
Роуты, AuthProvider (токены в localStorage) | pages |
web/src/pages/ |
Задачи (формы), карточка формы или проекта, проекты и их своды, свод 1 и 2, админка, справочники | components, api |
web/src/components/RealtimeTable/ |
Редактируемая таблица листа: WebSocket, блокировки, конфиги колонок constants/FORM_* |
api |
web/src/api/ |
axios-клиент /api/v1, модули по сущностям, WebSocket выгрузок |
— |
Границы
- Роутеры не ходят в БД напрямую, только через сервисы и репозитории. Сейчас нарушают
admin.py,main.py(engine) иwebsocket.py(бизнес-логика в слое API). - Проверка прав на ячейки и окна этапов — в SQL. Python её не дублирует, только маппит ошибки.
- Изменения схемы и функций — только новой миграцией alembic; старые миграции не правятся.
- Фронт обращается только к
/api/v1черезweb/src/api/.
Открытые вопросы
- Prod-авторизация через Keycloak (
raisa_fastapi_protected_api) закомментирована вmain.py,deps.py,auth.py; сейчас всегда работает локальный JWT. Как будет устроен prod? websocket.py:333,:357: условиеform_key != form_keyвсегда ложно, поэтому блокировки сравниваются поline_idмежду всеми формами;release_locks_for_rowничего не возвращает.- Раскладка колонок дублируется:
web/.../constants/FORM_1|2|4/*.js(около 4 тыс. строк каждый) иapi/.../export_mappings.py. Источник правды не определён. - Названия форм в БД и UI расходятся (FORM_2, FORM_4).
- Мёртвый код фронта:
pages/TablePage.jsx,FormsPage.jsx,TablesTest.jsx,TableTempPage/,api/tables.js,api/client_form.js,api/ws.js,constants/FORM_1/*_NO_LOCAL.js. - В
package.jsonне объявлены@mui/x-date-pickers,@mui/icons-material; tailwind/daisyui не используются. Settings.CORS_ORIGINSне применяется (вmain.pyallow_origins=["*"]),APP_ENVне читается,JWT_SECRETпо умолчанию небезопасный./монтируется дважды вapi/src/main.py:289и:291.- Интеграционные тесты зависят от данных в общей БД и не изолированы;
downgrade()в миграциях пустые. - Python-линтеров и проверок CI в репозитории нет.