fix(aliases,consolidations): блокировка удаления алиаса, границы входов (T11.3, M-4, M-6) #26

Merged
aep merged 2 commits from fix/21-aliases-bounds into main 2026-10-06 14:01:21 +03:00
Owner

Refs #21 (issue остаётся открытой). Закрывает маркеры T11.3, M-4, M-6; остальные пункты #21 не затронуты.

Что сделано

  1. T11.3 — AliasService.remove берёт lock_alias_key(normalized_alias) (та же advisory-блокировка, что в add и ручном сопоставлении, design #66), затем перечитывает алиас (get_alias(..., refresh=True), populate_existing): если перенос (move_alias) уже удалил алиас — 404, фантомного события LEGAL_ENTITY_CHANGE об удалении нет (раньше вторая сторона писала событие и DELETE по 0 строк с SAWarning).
  2. M-4 — тест test_manual_mapping_waits_for_alias_advisory_lock: соседняя транзакция держит lock_alias_key, ручное сопоставление встаёт в ожидание и после commit завершается 200.
  3. M-6 — границы: MembersIn.legal_entity_ids ≤ 500, StatusIn.comment ≤ 1000, OsvFilters.q ≤ 500 (MAX_MEMBERS, MAX_STATUS_COMMENT, MAX_OSV_QUERY; 422 в формате приложения detail[].loc/msg); lock_visible_version: видимость (без блокировки) -> FOR UPDATE; тест test_foreign_version_is_hidden_without_waiting_for_row_lock.
  4. Спека consolidations-api: требование «Границы входных данных» (2 сценария). README: «Гонки уникальных ограничений» дополнено удалением алиаса.

Как проверить

make -C arm-core check
cd arm-core/api && .venv/bin/pytest -m integration tests/test_api_counterparty_mapping.py tests/test_api_consolidation_locks.py tests/test_api_aliases.py tests/test_api_input_bounds.py

Результаты: make check — 1108 passed (684 deselected); pytest -m "integration and not e2e" — 683 passed, 1109 deselected (4:25). Тест T11.3 и тест видимости до FOR UPDATE были красными до исправления (TimeoutError / 204 вместо 404).

Находки

Маркер Суть Статус
T11.3 aliases.remove без блокировки: фантомное событие при гонке с move_alias fixed 74be7d3
M-4 нет теста advisory-блокировки алиаса при ручном сопоставлении fixed 74be7d3
M-6 границы входов MembersIn/StatusIn/OsvFilters.q; lock_visible_version блокировал до проверки видимости fixed 5868b14
C21-1 q в admin.py (UsersFilters), directories.py (фильтры ЮЛ/ГК) тоже без max_length — вне пунктов #21 deferred

Decisions made without discussion

  • 06.10.2026: значения границ 500/1000/500 взяты по существующим в ядре (NAME_MAX_LENGTH, MAX_TAKEOVER_REASON); 500 ЮЛ в периметре — на порядок выше реальных ГК. Ошибка стоит ложного 422 на экстремальной группе; константа одна.
  • 06.10.2026: в lock_visible_version после FOR UPDATE повторная проверка видимости не делается (ГК и филиал версия не меняет), только проверка существования строки.
  • 06.10.2026: get_alias получил необязательный refresh вместо отдельной функции.

Что проверить человеку

Приемлемость значений границ (особенно 500 ЮЛ); нужны ли такие же границы для q справочников (C21-1).

🤖 Generated with Claude Code

Refs #21 (issue остаётся открытой). Закрывает маркеры **T11.3, M-4, M-6**; остальные пункты #21 не затронуты. ## Что сделано 1. **T11.3** — `AliasService.remove` берёт `lock_alias_key(normalized_alias)` (та же advisory-блокировка, что в `add` и ручном сопоставлении, design #66), затем перечитывает алиас (`get_alias(..., refresh=True)`, `populate_existing`): если перенос (`move_alias`) уже удалил алиас — 404, фантомного события `LEGAL_ENTITY_CHANGE` об удалении нет (раньше вторая сторона писала событие и DELETE по 0 строк с SAWarning). 2. **M-4** — тест `test_manual_mapping_waits_for_alias_advisory_lock`: соседняя транзакция держит `lock_alias_key`, ручное сопоставление встаёт в ожидание и после commit завершается 200. 3. **M-6** — границы: `MembersIn.legal_entity_ids` ≤ 500, `StatusIn.comment` ≤ 1000, `OsvFilters.q` ≤ 500 (`MAX_MEMBERS`, `MAX_STATUS_COMMENT`, `MAX_OSV_QUERY`; 422 в формате приложения `detail[].loc/msg`); `lock_visible_version`: видимость (без блокировки) -> `FOR UPDATE`; тест `test_foreign_version_is_hidden_without_waiting_for_row_lock`. 4. Спека `consolidations-api`: требование «Границы входных данных» (2 сценария). README: «Гонки уникальных ограничений» дополнено удалением алиаса. ## Как проверить ``` make -C arm-core check cd arm-core/api && .venv/bin/pytest -m integration tests/test_api_counterparty_mapping.py tests/test_api_consolidation_locks.py tests/test_api_aliases.py tests/test_api_input_bounds.py ``` Результаты: `make check` — 1108 passed (684 deselected); `pytest -m "integration and not e2e"` — 683 passed, 1109 deselected (4:25). Тест T11.3 и тест видимости до `FOR UPDATE` были красными до исправления (TimeoutError / 204 вместо 404). ## Находки | Маркер | Суть | Статус | |---|---|---| | T11.3 | `aliases.remove` без блокировки: фантомное событие при гонке с `move_alias` | fixed 74be7d3 | | M-4 | нет теста advisory-блокировки алиаса при ручном сопоставлении | fixed 74be7d3 | | M-6 | границы входов `MembersIn`/`StatusIn`/`OsvFilters.q`; `lock_visible_version` блокировал до проверки видимости | fixed 5868b14 | | C21-1 | `q` в `admin.py` (`UsersFilters`), `directories.py` (фильтры ЮЛ/ГК) тоже без `max_length` — вне пунктов #21 | deferred | ## Decisions made without discussion - 06.10.2026: значения границ 500/1000/500 взяты по существующим в ядре (`NAME_MAX_LENGTH`, `MAX_TAKEOVER_REASON`); 500 ЮЛ в периметре — на порядок выше реальных ГК. Ошибка стоит ложного 422 на экстремальной группе; константа одна. - 06.10.2026: в `lock_visible_version` после `FOR UPDATE` повторная проверка видимости не делается (ГК и филиал версия не меняет), только проверка существования строки. - 06.10.2026: `get_alias` получил необязательный `refresh` вместо отдельной функции. ## Что проверить человеку Приемлемость значений границ (особенно 500 ЮЛ); нужны ли такие же границы для `q` справочников (C21-1). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
aep added 2 commits 2026-10-06 12:06:27 +03:00
aliases.remove берёт lock_alias_key по normalized_alias и перечитывает алиас под блокировкой:
при гонке с move_alias ручного сопоставления отвечает 404 без фантомного события об удалении.
Тесты: удаление ∥ перенос алиаса; ручное сопоставление ждёт блокировку алиаса (design №66).

Refs #21

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
MembersIn.legal_entity_ids ≤ 500, StatusIn.comment ≤ 1000, OsvFilters.q ≤ 500 (422 со списком ошибок);
lock_visible_version проверяет видимость версии до FOR UPDATE. Спека consolidations-api: требование
«Границы входных данных».

Refs #21

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
aep merged commit 4879fdca88 into main 2026-10-06 14:01:21 +03:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: RSHB/arm-core#26
No description provided.