Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
5.3 KiB
directory-policy Specification
Purpose
Политика видимости справочников поверх прав: что именно из ГК/ЮЛ/ГСК видит пользователь, определяется данными о его
филиале, а не кодом роли (§10.1 05-domain-rules.md).
Requirements
Requirement: Область видимости вычисляется из филиала пользователя
Для каждого запроса ядро SHALL вычислять область видимости из Principal: если regional_office.is_head_office = true —
вся система; иначе — ГК с company_group.base_regional_office_id = app_user.regional_office_id, их ЮЛ и ГСК/ГСЗ, а также
монозаёмщики с legal_entity.regional_office_id = app_user.regional_office_id. Код роли (role.code) MUST NOT участвовать
в вычислении; business_segment в Срезе 1 не используется (ASSUMPTION(OQ-86)).
Scenario: Пользователь филиала видит только своё
- WHEN есть ГК А (филиал X) и ГК Б (филиал Y), пользователь
KA_RFфилиала X запрашивает список ГК - THEN в ответе только ГК А,
total = 1
Scenario: Пользователь ГО видит всё
- WHEN пользователь с
is_head_office = trueзапрашивает список ГК - THEN в ответе обе ГК
Requirement: Объект вне видимости неотличим от несуществующего
Чтение, изменение и любые операции над ГК/ЮЛ/ГСК вне области видимости SHALL возвращать 404 с тем же телом, что и для несуществующего идентификатора; 403 для этого случая MUST NOT использоваться.
Scenario: Чужая ГК по id
- WHEN пользователь филиала X запрашивает
GET /directories/company-groups/{id}ГК Б - THEN ответ 404, текст совпадает с ответом на случайный
uuid
Requirement: Политика применяется до прав на изменение
Проверка права (require) и проверка видимости SHALL выполняться обе; порядок: право → видимость → операция. Создание ГК
пользователем филиала SHALL привязывать её к его филиалу, если base_regional_office_id не указан; указание чужого филиала
пользователем филиала → 422 OFFICE_NOT_ALLOWED.
Scenario: Создание ГК из филиала
- WHEN пользователь филиала X с
DIRECTORY_EDITсоздаёт ГК без филиала - THEN у ГК
base_regional_office_id= X, и она видна создателю
Requirement: Видимость консолидаций и редактируемость версии
Консолидация и её версии SHALL быть видимы тем же пользователям, что и её ГК (company_group); чужие и
несуществующие — 404 с одинаковым телом (код NOT_FOUND, сообщение CONSOLIDATION_NOT_FOUND / VERSION_NOT_FOUND;
так устроены все 404 этого среза: NotFoundError несёт только текст сообщения). Правка версии (периметр,
ручная смена статуса, сопоставление контрагента) SHALL проходить проверки в порядке: право → видимость → статус
версии ∈ {INITIATED, DOCUMENTS_PROCESSING, DATA_CORRECTION} (иначе 409 VERSION_NOT_EDITABLE) → активная
consolidation_lock есть (иначе 409 LOCK_REQUIRED) и принадлежит пользователю (иначе 409 LOCKED_BY_OTHER с
владельцем). Проверка реализуется чистой функцией в domain/policy.py без обращения к коду роли. Чтение (карточка,
свод, чек-лист, экспорт, кандидаты) и загрузка/подтверждение документов от статуса блокировки MUST NOT зависеть.
Зоны ответственности не учитываются (ASSUMPTION(OQ-86)).
Scenario: Чужая блокировка
- WHEN версию держит А, Б с
CONSOLIDATION_EDITвызываетPUT …/members - THEN 409
LOCKED_BY_OTHER,detail.locked_by = A
Scenario: Аннулированная версия
- WHEN версия в
CANCELLED, владелец прежней блокировки вызываетPOST …/osv/entries/{id}/counterparty - THEN 409
VERSION_NOT_EDITABLE
Scenario: Куратор ГО читает
- WHEN
curator_go(толькоCONSOLIDATION_VIEW) запрашивает свод версии любого филиала - THEN 200