chore(openspec): рулинг R-20 (решения Task 13) в design.md
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
This commit is contained in:
parent
d76ca570d8
commit
a7502f6315
@ -161,3 +161,4 @@ WHERE is_current`; `ALTER TYPE audit_action ADD VALUE` ×2 (`LEGAL_ENTITY_CHANGE
|
||||
| 28 | 2026-10-04 | R-17 (SDD фаза 2, Task 10, приняты решения исполнителя): общие `apply_group_update`/`apply_entity_update(session, audit, obj, changes: dict, *, now, description=None)` принимают словарь изменений (PATCH и импорт делят одну реализацию), `snapshot_entity`/`touch_entity` — функции модуля; обновления ГК/ЮЛ импортом пишут собственные события `GROUP_CHANGE`/`ASSIGNMENT_CHANGE`/`LEGAL_ENTITY_CHANGE` с `description="импорт ЕЦП"` помимо одного `DIRECTORY_IMPORT` (создания — только сводным событием); тест `dry_run` — на отдельной БД с зафиксированным seed, т.к. `session.rollback()` под SAVEPOINT-фикстурой `app` сносит seed теста; `IMPORT_MAX_BYTES` также в `.env.test`; имя файла сводится к basename (путь отбрасывается, пустое/`.`/`..` → `import`) для формата, `description` и ключа S3; `s3_object.sha256` заполняется, `content_type` — по расширению; сначала строка `s3_object` + flush, затем `put_object` (ошибка S3 откатывает импорт); разбор файла в `asyncio.to_thread`; `created_date` ГСК/ГСЗ не заполняется; 413 проверяется в эндпоинте (до чтения) и в сервисе (`HTTPException` из сервиса, как в брифе); архивные ГК входят в снимок и при `update` не разархивируются; сообщение `LE_IN_OTHER_GROUP` называет ЮЛ из другой ГК независимо от филиала пользователя (импорт — только `DIRECTORY_ADMIN`, права — данные) | единообразие истории/аудита ручной правки и импорта; честная проверка rollback; безопасность ключа S3 | пересмотр — правка сервиса/теста; ограничить раскрытие имён при выдаче `DIRECTORY_ADMIN` филиальному пользователю — убрать имя из сообщения |
|
||||
| 29 | 2026-10-04 | R-18 (SDD фаза 2, Task 11, приняты решения исполнителя): сборка приложения в `tests/conftest.py` вынесена в приватные `_build_application`/`_client_factory`, добавлены фикстуры `committed_sessionmaker`/`committed_client`/`committed_app`/`committed_storage` (отдельная БД с зафиксированным seed — для тестов с явным `rollback`); `safe_filename`: убираются управляющие символы (Cc), имя ≤ 200 символов, суффикс ≤ 16 (иначе отбрасывается); замер ≤ 60 с — только HTTP-запрос полной выгрузки (факт 1,14 с) | не дублировать фабрику приложения; ключ S3 ≤ 1024 байт | косметика тестов; смена лимита имени — константа |
|
||||
| 30 | 2026-10-04 | R-19 (SDD фаза 2, Task 12, приняты решения исполнителя): R-13 реализован иерархией — `RegionalOfficeBrief` (`/me`, поля `id,name,is_head_office`) и `RegionalOfficeOut(RegionalOfficeBrief)` (+`is_active`; справочник и `UserOut`), одно определение в `schemas/directories.py` (буквальный импорт добавил бы `is_active` в `/me`); несуществующий филиал в теле — 422 `OFFICE_NOT_FOUND` (как R-8), не 404; email хранится в форме `EmailStr` (домен в нижнем регистре), сравнение `strip().lower()`; `UserCreate` тоже `extra=forbid` (явный 422 на `external_id`); аудит создания содержит и `employee_no`; `USER_ROLE_CHANGE`: before — коды по алфавиту, after — в порядке запроса без дублей, повтор набора — без аудита; `UNKNOWN_ROLE`/`UNKNOWN_PERMISSION` несут список кодов; LAST_ADMIN сериализуется блокировкой `FOR NO KEY UPDATE` строки права `USERS_ADMIN` (+ строка пользователя/роли), порядок «объект → право» без дедлоков (`FOR UPDATE` дедлочит с FK-проверкой вставки аудита); LAST_ADMIN считает активных пользователей с активными ролями, несущими право (код роли не читается) | безопасность администрирования; `/me` не меняется | вернуть локальную модель в `me.py`; сменить код 422↔404 — одна проверка; снять блокировку — риск остаться без администратора при гонке |
|
||||
| 31 | 2026-10-04 | R-20 (SDD фаза 2, Task 13, приняты решения исполнителя): условие dev-входа — литерал `process.env.NODE_ENV !== 'production'` прямо в `DevLogin` (rsbuild подменяет `process.env` объектом `REACT_APP_*`, через `Config` `NODE_ENV` недоступен; в prod-бандле формы и `dev/token` нет — проверено grep); `AuthGate` оборачивает весь `Layout` (а не только `Routes`), чтобы форма входа не рисовалась рядом с сайдбаром; профиль детям — `MeContext`/`useCurrentUser`; Redux Provider каркаса не удалён; токен: `sessionStorage` с запасным токеном в памяти при недоступном хранилище; клиент: сетевые ошибки → `ApiError(0,'NETWORK')`, не-JSON 2xx → `BAD_RESPONSE`; в prod ошибка `/me` показывается в `Alert` с кнопкой «Повторить»; типы `Permission.object_type/action` — union по enum бэкенда | D-9, безопасность prod-сборки, устойчивость клиента | вернуть `AuthGate` вокруг `Routes`; при смене сборщика пересмотреть условие `NODE_ENV` |
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user