Инструменты пользователя

Инструменты сайта


sharixopen:knowledge:scenarios:access_request_accepted

ACCESS_REQUEST в ACCEPTED: требования и активация права

Назначение: Сценарий процесса. Продукт: ShariX Open.

Для кого: Разработчик · Администратор · Поддержка · Рецензент и приёмщик · Нейросеть.

Темы: Обработчики → ACCESS_REQUEST · Доступ → Полномочия · Доступ → Требования.

Область: ShariX Open. Обработчик: open_access_request_accepted, тип ACCESS_REQUEST (3), рабочий статус ACCEPTED (321). 31.10.2026 исходники повторно получены из Git. Обе Python-копии совпали с новой канонической генерацией Blockly; проверены 11 исходников генераторов. Сам обработчик и его внешние действия не запускались. Выбранная версия и работающая установка проверяются отдельно.

Назначение и границы

ACCEPTED означает одобренный запрос. Для active permission ещё требуются:

  • существующая связанная Permissions;
  • выполненные обязательные требования;
  • успешный ответ канонической активации.

Отсутствующая permission этим handler не создаётся. ACCREQ_AUTOACCEPT здесь не проверяется: требования действуют независимо от способа принятия PENDING.

Порядок runtime:

  1. Прочитать связанную permission.
  2. Проверить requirements.
  3. Запросить активацию с повторным backend gate.
  4. Только после успеха запросить CLOSED.

Общей транзакции этих запросов нет. Предварительный ok не позволяет пропустить повторную оценку внутри активации.

BPMN имеют isExecutable=false. Wiki не запускает код: runtime выполняет выбранный проверенный Python из Blockly. End event завершает показанную операцию; defer-узел на первой схеме завершает текущий проход и передаёт ожидание планировщику.

Решения одного прохода (BPMN)

Схема BPMN

Загрузка схемы…

Исходник схемы
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_access_accepted_decisions" targetNamespace="urn:sharix:knowledge:handlers">
  <bpmn:process id="accepted_Process_accepted" name="open_access_request_accepted: проверить требования, активировать permission, закрыть Ticket" isExecutable="false">
    <bpmn:documentation>{"notes": ["BPMN isExecutable=false. Генератор не исполняет handler.", "ACCEPTED — одобрение запроса, а не уже активное право.", "deferred_until — символ текущего локального срока; не имя параметра."], "sources": [{"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_access_request_accepted.py", "repository": "sharix-open-handlers-examples", "sha256": "de79926339c168601129401449b8dfdb1fb31baeaa4a0e6bb44200ea6047f237"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "generated_handler_blocks/open_access_request_accepted.json", "repository": "sharix-open-handlers-examples", "sha256": "f7a8543767cda70ad17092719edccd1d19b50de18fd31b93606767425fbe32ec"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "catalog.py", "repository": "sharix-open-handlers-examples", "sha256": "e3dcb72b7e620e2837adacd7af053f35b04cdff475789496d9c114e17d57dfde"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/blockly_runtime.py", "repository": "sharix-open-handlers-backend", "sha256": "3e222150cbff315077c6c9b160d46e59856cedf6d6591d213e958c63cb2f2428"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/handler_operations.py", "repository": "sharix-open-handlers-backend", "sha256": "28620658501c375f556e24437871620b84a17a88d0b62b2d1a3cc5deb2f14b1e"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/data_parsers.py", "repository": "sharix-open-handlers-backend", "sha256": "d7f26f172f68e4b390f675de88fbfb3c37a58fb29d4bf3d6687b31bd7953f9e4"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/ejabberd_muc.py", "repository": "sharix-open-handlers-backend", "sha256": "35c2eba89fab36b5c444439a87beaa516b55133991136d5370418d92a18d7bcd"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/requesters.py", "repository": "sharix-open-handlers-backend", "sha256": "965a348cea477722bbaf4c8c6b06023eb238b71664a332f7ea8c90bfe72ea808"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "classes/AccessRequestTicket.py", "repository": "sharix-open-handlers-backend", "sha256": "3f3a498ae76b3d878b19a8f32170fc2a71c6c6c182bf34a6ecc50edf7b0f5eff"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "ticket_blockly_codegen.py", "repository": "sharix-open-handlers-backend", "sha256": "bce71eab622922f8dd0954222842349799b60e18a0ab6310cc3e5f305603661e"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "ticket_codegen_contract.json", "repository": "sharix-open-handlers-backend", "sha256": "0bfd2b0ebb07bd380ed3c867386536ab88ef7dfa6e13f1cd8c91d32bb02c1ae9"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "lib/tickets.py", "repository": "sharix-open-tickets", "sha256": "0d260c17947f9a186d07af2749159780e3c7354a95b4bafe9d67493663c96883"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "api/views/handler_workflow.py", "repository": "sharix-open-tickets", "sha256": "f97c4b467a9a30749f5c4b86b39a833c430e57aaa1f030f70030d9b5c609d368"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "api/handler_auth.py", "repository": "sharix-open-tickets", "sha256": "ac76dc45aaa9742e5e1da0b98aae914bb2e287048d33e97b4a245a6997bc8425"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "utils.py", "repository": "sharix-open-tickets", "sha256": "a5680205c6522e1d9a74d9d267fe9ee96faf6f06436b00877fc0a93d80234bf5"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "views/ticket_detail.py", "repository": "sharix-open-tickets", "sha256": "05d344b0fba14cf895400694d4a18f486c800fef08dd1acb43ea46909b9e7e59"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "signals.py", "repository": "sharix-open-tickets", "sha256": "39aad8690a2e7d35cebfb052127a8130a951cbb4eea316c4f767a0a59fc5fa7e"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "services/handler_wakeup.py", "repository": "sharix-open-tickets", "sha256": "c9fdc62a18301fd7c075395c697d5b1c738c77713aa71fcbb5ab097e173d98de"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "apiviews/handler_workflow.py", "repository": "sharix-open-backend", "sha256": "0f699a4e16760cbbdd09d894093c685ba69073fedf0522852cb1fdc9811636e3"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/activation.py", "repository": "sharix-open-backend", "sha256": "f78d4e219a5b83c7952bd366a4e7a711589b1d382af653a0c453c0524e4220f7"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/requirement_actions.py", "repository": "sharix-open-backend", "sha256": "717ef0f3e02ff8e6da103b5fdbae584b01d84d177f6e62ae677a1c5a366b71de"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/requirement_checks.py", "repository": "sharix-open-backend", "sha256": "5a73a6e71307e734f0c0e480fd14a825a7a22242811e2523b7f25157224cf34c"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/document_drafts.py", "repository": "sharix-open-backend", "sha256": "383b117f01fdd9d16de3ceb9afb1ccf0bf3104c4966b23e987b8a90e9a46f071"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/verification_workflow.py", "repository": "sharix-open-backend", "sha256": "9fe62f8344d7fd78e5af0ce025c82ba4f7d21759e71f518df1186a1d6a4a0644"}]}</bpmn:documentation>
    <bpmn:laneSet id="accepted_Lanes_accepted">
      <bpmn:lane id="accepted_Lane_worker" name="Один проход Python: ожидание означает возврат Ticket с defer">
        <bpmn:flowNodeRef>accepted_start</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>accepted_status</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>accepted_lookup</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>accepted_exists</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>accepted_requirements</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>accepted_met</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>accepted_activate</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>accepted_active</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>accepted_close</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>accepted_confirmed</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>accepted_remove</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>accepted_done</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>accepted_stale</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>accepted_stale_end</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>accepted_missing</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>accepted_missing_wait</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>accepted_need</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>accepted_need_wait</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>accepted_inconsistent</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>accepted_activation_wait</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>accepted_not_found</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>accepted_lookup_error</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>accepted_requirements_error</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>accepted_activate_error</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>accepted_close_error</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>accepted_retry</bpmn:flowNodeRef>
      </bpmn:lane>
    </bpmn:laneSet>
    <bpmn:startEvent id="accepted_start" name="Ticket готов к проходу">
      <bpmn:outgoing>accepted_Flow_0</bpmn:outgoing>
    </bpmn:startEvent>
    <bpmn:exclusiveGateway id="accepted_status" name="Статус ACCEPTED?">
      <bpmn:incoming>accepted_Flow_0</bpmn:incoming>
      <bpmn:outgoing>accepted_Flow_1</bpmn:outgoing>
      <bpmn:outgoing>accepted_Flow_2</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:serviceTask id="accepted_lookup" name="Scoped API: найти permission">
      <bpmn:incoming>accepted_Flow_1</bpmn:incoming>
      <bpmn:outgoing>accepted_Flow_4</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:exclusiveGateway id="accepted_exists" name="Permission найдена?">
      <bpmn:incoming>accepted_Flow_4</bpmn:incoming>
      <bpmn:outgoing>accepted_Flow_5</bpmn:outgoing>
      <bpmn:outgoing>accepted_Flow_6</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:serviceTask id="accepted_requirements" name="API: ensure actions + проверить requirements">
      <bpmn:incoming>accepted_Flow_5</bpmn:incoming>
      <bpmn:outgoing>accepted_Flow_8</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:exclusiveGateway id="accepted_met" name="Все требования ok?">
      <bpmn:incoming>accepted_Flow_8</bpmn:incoming>
      <bpmn:outgoing>accepted_Flow_9</bpmn:outgoing>
      <bpmn:outgoing>accepted_Flow_10</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:serviceTask id="accepted_activate" name="API: активировать permission с повторным gate">
      <bpmn:incoming>accepted_Flow_9</bpmn:incoming>
      <bpmn:outgoing>accepted_Flow_12</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:exclusiveGateway id="accepted_active" name="Активация подтверждена?">
      <bpmn:incoming>accepted_Flow_12</bpmn:incoming>
      <bpmn:outgoing>accepted_Flow_13</bpmn:outgoing>
      <bpmn:outgoing>accepted_Flow_14</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:serviceTask id="accepted_close" name="Scoped Ticket API: CLOSED">
      <bpmn:incoming>accepted_Flow_13</bpmn:incoming>
      <bpmn:outgoing>accepted_Flow_16</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:exclusiveGateway id="accepted_confirmed" name="Переход подтверждён?">
      <bpmn:incoming>accepted_Flow_16</bpmn:incoming>
      <bpmn:outgoing>accepted_Flow_17</bpmn:outgoing>
      <bpmn:outgoing>accepted_Flow_18</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:serviceTask id="accepted_remove" name="Убрать Ticket и комнату">
      <bpmn:incoming>accepted_Flow_17</bpmn:incoming>
      <bpmn:outgoing>accepted_Flow_19</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:endEvent id="accepted_done" name="Этот проход завершён">
      <bpmn:incoming>accepted_Flow_19</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:serviceTask id="accepted_stale" name="Убрать Ticket и комнату">
      <bpmn:incoming>accepted_Flow_2</bpmn:incoming>
      <bpmn:outgoing>accepted_Flow_3</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:endEvent id="accepted_stale_end" name="Прежний владелец освобождён">
      <bpmn:incoming>accepted_Flow_3</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:sendTask id="accepted_missing" name="ALERT администраторам: permission не найдена">
      <bpmn:incoming>accepted_Flow_6</bpmn:incoming>
      <bpmn:outgoing>accepted_Flow_7</bpmn:outgoing>
    </bpmn:sendTask>
    <bpmn:serviceTask id="accepted_missing_wait" name="related_permission_missing; defer">
      <bpmn:documentation>ACCESS_REQUEST_INCONSISTENCY_RECHECK_SECONDS</bpmn:documentation>
      <bpmn:incoming>accepted_Flow_7</bpmn:incoming>
    </bpmn:serviceTask>
    <bpmn:sendTask id="accepted_need" name="Уведомить автора и администраторов о требованиях">
      <bpmn:incoming>accepted_Flow_10</bpmn:incoming>
      <bpmn:outgoing>accepted_Flow_11</bpmn:outgoing>
    </bpmn:sendTask>
    <bpmn:serviceTask id="accepted_need_wait" name="requirements_pending; defer">
      <bpmn:documentation>ACCESS_REQUEST_INCONSISTENCY_RECHECK_SECONDS</bpmn:documentation>
      <bpmn:incoming>accepted_Flow_11</bpmn:incoming>
    </bpmn:serviceTask>
    <bpmn:sendTask id="accepted_inconsistent" name="ALERT: активация не подтверждена">
      <bpmn:incoming>accepted_Flow_14</bpmn:incoming>
      <bpmn:outgoing>accepted_Flow_15</bpmn:outgoing>
    </bpmn:sendTask>
    <bpmn:serviceTask id="accepted_activation_wait" name="related_permission_inconsistent; 900 с">
      <bpmn:incoming>accepted_Flow_15</bpmn:incoming>
    </bpmn:serviceTask>
    <bpmn:endEvent id="accepted_not_found" name="404: очистка уже запрошена">
      <bpmn:incoming>accepted_Flow_18</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:boundaryEvent id="accepted_lookup_error" name="Ошибка read API" attachedToRef="accepted_lookup" cancelActivity="true">
      <bpmn:outgoing>accepted_Flow_20</bpmn:outgoing>
      <bpmn:errorEventDefinition />
    </bpmn:boundaryEvent>
    <bpmn:boundaryEvent id="accepted_requirements_error" name="Ошибка requirements API" attachedToRef="accepted_requirements" cancelActivity="true">
      <bpmn:outgoing>accepted_Flow_21</bpmn:outgoing>
      <bpmn:errorEventDefinition />
    </bpmn:boundaryEvent>
    <bpmn:boundaryEvent id="accepted_activate_error" name="401/403/429/5xx" attachedToRef="accepted_activate" cancelActivity="true">
      <bpmn:outgoing>accepted_Flow_22</bpmn:outgoing>
      <bpmn:errorEventDefinition />
    </bpmn:boundaryEvent>
    <bpmn:boundaryEvent id="accepted_close_error" name="Ошибка перехода" attachedToRef="accepted_close" cancelActivity="true">
      <bpmn:outgoing>accepted_Flow_23</bpmn:outgoing>
      <bpmn:errorEventDefinition />
    </bpmn:boundaryEvent>
    <bpmn:serviceTask id="accepted_retry" name="Общий processing_error + defer">
      <bpmn:documentation>DEFERRED_TICKET_RECHECK_SECONDS. Ошибки уведомлений также попадают сюда.</bpmn:documentation>
      <bpmn:incoming>accepted_Flow_20</bpmn:incoming>
      <bpmn:incoming>accepted_Flow_21</bpmn:incoming>
      <bpmn:incoming>accepted_Flow_22</bpmn:incoming>
      <bpmn:incoming>accepted_Flow_23</bpmn:incoming>
    </bpmn:serviceTask>
    <bpmn:sequenceFlow id="accepted_Flow_0" sourceRef="accepted_start" targetRef="accepted_status" name="" />
    <bpmn:sequenceFlow id="accepted_Flow_1" sourceRef="accepted_status" targetRef="accepted_lookup" name="Да" />
    <bpmn:sequenceFlow id="accepted_Flow_2" sourceRef="accepted_status" targetRef="accepted_stale" name="Нет" />
    <bpmn:sequenceFlow id="accepted_Flow_3" sourceRef="accepted_stale" targetRef="accepted_stale_end" name="" />
    <bpmn:sequenceFlow id="accepted_Flow_4" sourceRef="accepted_lookup" targetRef="accepted_exists" name="" />
    <bpmn:sequenceFlow id="accepted_Flow_5" sourceRef="accepted_exists" targetRef="accepted_requirements" name="Да" />
    <bpmn:sequenceFlow id="accepted_Flow_6" sourceRef="accepted_exists" targetRef="accepted_missing" name="Нет" />
    <bpmn:sequenceFlow id="accepted_Flow_7" sourceRef="accepted_missing" targetRef="accepted_missing_wait" name="" />
    <bpmn:sequenceFlow id="accepted_Flow_8" sourceRef="accepted_requirements" targetRef="accepted_met" name="" />
    <bpmn:sequenceFlow id="accepted_Flow_9" sourceRef="accepted_met" targetRef="accepted_activate" name="Да" />
    <bpmn:sequenceFlow id="accepted_Flow_10" sourceRef="accepted_met" targetRef="accepted_need" name="Нет" />
    <bpmn:sequenceFlow id="accepted_Flow_11" sourceRef="accepted_need" targetRef="accepted_need_wait" name="" />
    <bpmn:sequenceFlow id="accepted_Flow_12" sourceRef="accepted_activate" targetRef="accepted_active" name="" />
    <bpmn:sequenceFlow id="accepted_Flow_13" sourceRef="accepted_active" targetRef="accepted_close" name="Да" />
    <bpmn:sequenceFlow id="accepted_Flow_14" sourceRef="accepted_active" targetRef="accepted_inconsistent" name="Нет" />
    <bpmn:sequenceFlow id="accepted_Flow_15" sourceRef="accepted_inconsistent" targetRef="accepted_activation_wait" name="" />
    <bpmn:sequenceFlow id="accepted_Flow_16" sourceRef="accepted_close" targetRef="accepted_confirmed" name="" />
    <bpmn:sequenceFlow id="accepted_Flow_17" sourceRef="accepted_confirmed" targetRef="accepted_remove" name="Да" />
    <bpmn:sequenceFlow id="accepted_Flow_18" sourceRef="accepted_confirmed" targetRef="accepted_not_found" name="Нет (404)" />
    <bpmn:sequenceFlow id="accepted_Flow_19" sourceRef="accepted_remove" targetRef="accepted_done" name="" />
    <bpmn:sequenceFlow id="accepted_Flow_20" sourceRef="accepted_lookup_error" targetRef="accepted_retry" name="" />
    <bpmn:sequenceFlow id="accepted_Flow_21" sourceRef="accepted_requirements_error" targetRef="accepted_retry" name="" />
    <bpmn:sequenceFlow id="accepted_Flow_22" sourceRef="accepted_activate_error" targetRef="accepted_retry" name="" />
    <bpmn:sequenceFlow id="accepted_Flow_23" sourceRef="accepted_close_error" targetRef="accepted_retry" name="" />
  </bpmn:process>
  <bpmn:collaboration id="Collaboration_access_accepted_decisions">
    <bpmn:participant id="accepted_Pool_accepted" name="open_access_request_accepted: проверить требования, активировать permission, закрыть Ticket" processRef="accepted_Process_accepted" />
  </bpmn:collaboration>
  <bpmndi:BPMNDiagram id="Diagram_access_accepted_decisions">
    <bpmndi:BPMNPlane id="Plane_access_accepted_decisions" bpmnElement="Collaboration_access_accepted_decisions">
      <bpmndi:BPMNShape id="accepted_DI_Pool_accepted" bpmnElement="accepted_Pool_accepted" isHorizontal="true">
        <dc:Bounds x="0.0" y="0.0" width="2980" height="610" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="accepted_DI_Lane_worker" bpmnElement="accepted_Lane_worker" isHorizontal="true">
        <dc:Bounds x="30.0" y="0.0" width="2950" height="610" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="accepted_DI_start" bpmnElement="accepted_start">
        <dc:Bounds x="132.0" y="92.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="accepted_DI_status" bpmnElement="accepted_status">
        <dc:Bounds x="325.0" y="85.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="accepted_DI_lookup" bpmnElement="accepted_lookup">
        <dc:Bounds x="515.0" y="75.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="accepted_DI_exists" bpmnElement="accepted_exists">
        <dc:Bounds x="815.0" y="85.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="accepted_DI_requirements" bpmnElement="accepted_requirements">
        <dc:Bounds x="1015.0" y="75.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="accepted_DI_met" bpmnElement="accepted_met">
        <dc:Bounds x="1315.0" y="85.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="accepted_DI_activate" bpmnElement="accepted_activate">
        <dc:Bounds x="1515.0" y="75.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="accepted_DI_active" bpmnElement="accepted_active">
        <dc:Bounds x="1815.0" y="85.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="accepted_DI_close" bpmnElement="accepted_close">
        <dc:Bounds x="2015.0" y="75.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="accepted_DI_confirmed" bpmnElement="accepted_confirmed">
        <dc:Bounds x="2315.0" y="85.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="accepted_DI_remove" bpmnElement="accepted_remove">
        <dc:Bounds x="2515.0" y="75.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="accepted_DI_done" bpmnElement="accepted_done">
        <dc:Bounds x="2802.0" y="92.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="accepted_DI_stale" bpmnElement="accepted_stale">
        <dc:Bounds x="275.0" y="275.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="accepted_DI_stale_end" bpmnElement="accepted_stale_end">
        <dc:Bounds x="572.0" y="292.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="accepted_DI_missing" bpmnElement="accepted_missing">
        <dc:Bounds x="765.0" y="275.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="accepted_DI_missing_wait" bpmnElement="accepted_missing_wait">
        <dc:Bounds x="765.0" y="475.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="accepted_DI_need" bpmnElement="accepted_need">
        <dc:Bounds x="1265.0" y="275.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="accepted_DI_need_wait" bpmnElement="accepted_need_wait">
        <dc:Bounds x="1265.0" y="475.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="accepted_DI_inconsistent" bpmnElement="accepted_inconsistent">
        <dc:Bounds x="1765.0" y="275.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="accepted_DI_activation_wait" bpmnElement="accepted_activation_wait">
        <dc:Bounds x="1765.0" y="475.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="accepted_DI_not_found" bpmnElement="accepted_not_found">
        <dc:Bounds x="2322.0" y="292.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="accepted_DI_lookup_error" bpmnElement="accepted_lookup_error">
        <dc:Bounds x="622.0" y="127.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="accepted_DI_requirements_error" bpmnElement="accepted_requirements_error">
        <dc:Bounds x="1122.0" y="127.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="accepted_DI_activate_error" bpmnElement="accepted_activate_error">
        <dc:Bounds x="1622.0" y="127.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="accepted_DI_close_error" bpmnElement="accepted_close_error">
        <dc:Bounds x="2122.0" y="127.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="accepted_DI_retry" bpmnElement="accepted_retry">
        <dc:Bounds x="2515.0" y="475.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="accepted_DI_Flow_0" bpmnElement="accepted_Flow_0">
        <di:waypoint x="168.0" y="110.0" />
        <di:waypoint x="325.0" y="110.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="accepted_DI_Flow_1" bpmnElement="accepted_Flow_1">
        <di:waypoint x="375.0" y="110.0" />
        <di:waypoint x="515.0" y="110.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="accepted_DI_Flow_2" bpmnElement="accepted_Flow_2">
        <di:waypoint x="350.0" y="135.0" />
        <di:waypoint x="350.0" y="275.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="accepted_DI_Flow_3" bpmnElement="accepted_Flow_3">
        <di:waypoint x="425.0" y="310.0" />
        <di:waypoint x="572.0" y="310.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="accepted_DI_Flow_4" bpmnElement="accepted_Flow_4">
        <di:waypoint x="665.0" y="110.0" />
        <di:waypoint x="815.0" y="110.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="accepted_DI_Flow_5" bpmnElement="accepted_Flow_5">
        <di:waypoint x="865.0" y="110.0" />
        <di:waypoint x="1015.0" y="110.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="accepted_DI_Flow_6" bpmnElement="accepted_Flow_6">
        <di:waypoint x="840.0" y="135.0" />
        <di:waypoint x="840.0" y="275.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="accepted_DI_Flow_7" bpmnElement="accepted_Flow_7">
        <di:waypoint x="840.0" y="345.0" />
        <di:waypoint x="840.0" y="475.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="accepted_DI_Flow_8" bpmnElement="accepted_Flow_8">
        <di:waypoint x="1165.0" y="110.0" />
        <di:waypoint x="1315.0" y="110.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="accepted_DI_Flow_9" bpmnElement="accepted_Flow_9">
        <di:waypoint x="1365.0" y="110.0" />
        <di:waypoint x="1515.0" y="110.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="accepted_DI_Flow_10" bpmnElement="accepted_Flow_10">
        <di:waypoint x="1340.0" y="135.0" />
        <di:waypoint x="1340.0" y="275.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="accepted_DI_Flow_11" bpmnElement="accepted_Flow_11">
        <di:waypoint x="1340.0" y="345.0" />
        <di:waypoint x="1340.0" y="475.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="accepted_DI_Flow_12" bpmnElement="accepted_Flow_12">
        <di:waypoint x="1665.0" y="110.0" />
        <di:waypoint x="1815.0" y="110.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="accepted_DI_Flow_13" bpmnElement="accepted_Flow_13">
        <di:waypoint x="1865.0" y="110.0" />
        <di:waypoint x="2015.0" y="110.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="accepted_DI_Flow_14" bpmnElement="accepted_Flow_14">
        <di:waypoint x="1840.0" y="135.0" />
        <di:waypoint x="1840.0" y="275.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="accepted_DI_Flow_15" bpmnElement="accepted_Flow_15">
        <di:waypoint x="1840.0" y="345.0" />
        <di:waypoint x="1840.0" y="475.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="accepted_DI_Flow_16" bpmnElement="accepted_Flow_16">
        <di:waypoint x="2165.0" y="110.0" />
        <di:waypoint x="2315.0" y="110.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="accepted_DI_Flow_17" bpmnElement="accepted_Flow_17">
        <di:waypoint x="2365.0" y="110.0" />
        <di:waypoint x="2515.0" y="110.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="accepted_DI_Flow_18" bpmnElement="accepted_Flow_18">
        <di:waypoint x="2340.0" y="135.0" />
        <di:waypoint x="2340.0" y="292.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="accepted_DI_Flow_19" bpmnElement="accepted_Flow_19">
        <di:waypoint x="2665.0" y="110.0" />
        <di:waypoint x="2802.0" y="110.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="accepted_DI_Flow_20" bpmnElement="accepted_Flow_20">
        <di:waypoint x="658.0" y="145.0" />
        <di:waypoint x="700.0" y="145.0" />
        <di:waypoint x="700.0" y="590.0" />
        <di:waypoint x="2590.0" y="590.0" />
        <di:waypoint x="2590.0" y="475.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="accepted_DI_Flow_21" bpmnElement="accepted_Flow_21">
        <di:waypoint x="1158.0" y="145.0" />
        <di:waypoint x="1200.0" y="145.0" />
        <di:waypoint x="1200.0" y="570.0" />
        <di:waypoint x="2590.0" y="570.0" />
        <di:waypoint x="2590.0" y="475.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="accepted_DI_Flow_22" bpmnElement="accepted_Flow_22">
        <di:waypoint x="1658.0" y="145.0" />
        <di:waypoint x="1700.0" y="145.0" />
        <di:waypoint x="1700.0" y="550.0" />
        <di:waypoint x="2590.0" y="550.0" />
        <di:waypoint x="2590.0" y="475.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="accepted_DI_Flow_23" bpmnElement="accepted_Flow_23">
        <di:waypoint x="2158.0" y="145.0" />
        <di:waypoint x="2200.0" y="145.0" />
        <di:waypoint x="2590.0" y="145.0" />
        <di:waypoint x="2590.0" y="475.0" />
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn:definitions>
  • Не свой статус — запросить удаление локального Ticket и комнаты.
  • Permission не найдена — уведомить администраторов, записать related_permission_missing, ждать по ACCESS_REQUEST_INCONSISTENCY_RECHECK_SECONDS. Отсутствующую permission этот handler не создаёт.
  • Permission есть, но requirements не выполнены — уведомить автора и администраторов, записать requirements_pending и назначить тот же именованный повтор. Ticket остаётся в ACCEPTED.
  • Requirements выполнены — запросить активацию. При подтверждённом успехе запросить CLOSED; после подтверждённого перехода убрать локальный Ticket и комнату.
  • Операция активации вернула обработанный отрицательный результат — уведомить администраторов, записать related_permission_inconsistent и отложить на 900 секунд. Это текущая константа Python, а не отдельный параметр окружения.

Связь ищется по ticket_status_id с чтением максимум двух записей:

  • Нет записи: 404.
  • Несколько записей: 409, требуется разбор данных.
  • Ticket вышел из scope: read также может вернуть 404.

По одному 404 нельзя доказать физическое отсутствие permission. Сначала сверить актуальный Ticket и его рабочую область.

Backend: подготовка действий и повторный gate (BPMN)

Схема BPMN

Загрузка схемы…

Исходник схемы
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_access_accepted_gate" targetNamespace="urn:sharix:knowledge:handlers">
  <bpmn:process id="gate_Process_gate" name="Backend: два последовательных scoped запроса с разными задачами" isExecutable="false">
    <bpmn:documentation>{"notes": ["BPMN isExecutable=false. Генератор не исполняет handler.", "ACCEPTED — одобрение запроса, а не уже активное право.", "deferred_until — символ текущего локального срока; не имя параметра.", "GET requirements здесь имеет side effects подготовки действий.", "Ни прямой status=0, ни исходный ok не обходят повторный gate."], "sources": [{"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_access_request_accepted.py", "repository": "sharix-open-handlers-examples", "sha256": "de79926339c168601129401449b8dfdb1fb31baeaa4a0e6bb44200ea6047f237"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "generated_handler_blocks/open_access_request_accepted.json", "repository": "sharix-open-handlers-examples", "sha256": "f7a8543767cda70ad17092719edccd1d19b50de18fd31b93606767425fbe32ec"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "catalog.py", "repository": "sharix-open-handlers-examples", "sha256": "e3dcb72b7e620e2837adacd7af053f35b04cdff475789496d9c114e17d57dfde"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/blockly_runtime.py", "repository": "sharix-open-handlers-backend", "sha256": "3e222150cbff315077c6c9b160d46e59856cedf6d6591d213e958c63cb2f2428"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/handler_operations.py", "repository": "sharix-open-handlers-backend", "sha256": "28620658501c375f556e24437871620b84a17a88d0b62b2d1a3cc5deb2f14b1e"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/data_parsers.py", "repository": "sharix-open-handlers-backend", "sha256": "d7f26f172f68e4b390f675de88fbfb3c37a58fb29d4bf3d6687b31bd7953f9e4"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/ejabberd_muc.py", "repository": "sharix-open-handlers-backend", "sha256": "35c2eba89fab36b5c444439a87beaa516b55133991136d5370418d92a18d7bcd"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/requesters.py", "repository": "sharix-open-handlers-backend", "sha256": "965a348cea477722bbaf4c8c6b06023eb238b71664a332f7ea8c90bfe72ea808"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "classes/AccessRequestTicket.py", "repository": "sharix-open-handlers-backend", "sha256": "3f3a498ae76b3d878b19a8f32170fc2a71c6c6c182bf34a6ecc50edf7b0f5eff"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "ticket_blockly_codegen.py", "repository": "sharix-open-handlers-backend", "sha256": "bce71eab622922f8dd0954222842349799b60e18a0ab6310cc3e5f305603661e"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "ticket_codegen_contract.json", "repository": "sharix-open-handlers-backend", "sha256": "0bfd2b0ebb07bd380ed3c867386536ab88ef7dfa6e13f1cd8c91d32bb02c1ae9"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "lib/tickets.py", "repository": "sharix-open-tickets", "sha256": "0d260c17947f9a186d07af2749159780e3c7354a95b4bafe9d67493663c96883"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "api/views/handler_workflow.py", "repository": "sharix-open-tickets", "sha256": "f97c4b467a9a30749f5c4b86b39a833c430e57aaa1f030f70030d9b5c609d368"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "api/handler_auth.py", "repository": "sharix-open-tickets", "sha256": "ac76dc45aaa9742e5e1da0b98aae914bb2e287048d33e97b4a245a6997bc8425"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "utils.py", "repository": "sharix-open-tickets", "sha256": "a5680205c6522e1d9a74d9d267fe9ee96faf6f06436b00877fc0a93d80234bf5"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "views/ticket_detail.py", "repository": "sharix-open-tickets", "sha256": "05d344b0fba14cf895400694d4a18f486c800fef08dd1acb43ea46909b9e7e59"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "signals.py", "repository": "sharix-open-tickets", "sha256": "39aad8690a2e7d35cebfb052127a8130a951cbb4eea316c4f767a0a59fc5fa7e"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "services/handler_wakeup.py", "repository": "sharix-open-tickets", "sha256": "c9fdc62a18301fd7c075395c697d5b1c738c77713aa71fcbb5ab097e173d98de"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "apiviews/handler_workflow.py", "repository": "sharix-open-backend", "sha256": "0f699a4e16760cbbdd09d894093c685ba69073fedf0522852cb1fdc9811636e3"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/activation.py", "repository": "sharix-open-backend", "sha256": "f78d4e219a5b83c7952bd366a4e7a711589b1d382af653a0c453c0524e4220f7"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/requirement_actions.py", "repository": "sharix-open-backend", "sha256": "717ef0f3e02ff8e6da103b5fdbae584b01d84d177f6e62ae677a1c5a366b71de"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/requirement_checks.py", "repository": "sharix-open-backend", "sha256": "5a73a6e71307e734f0c0e480fd14a825a7a22242811e2523b7f25157224cf34c"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/document_drafts.py", "repository": "sharix-open-backend", "sha256": "383b117f01fdd9d16de3ceb9afb1ccf0bf3104c4966b23e987b8a90e9a46f071"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/verification_workflow.py", "repository": "sharix-open-backend", "sha256": "9fe62f8344d7fd78e5af0ce025c82ba4f7d21759e71f518df1186a1d6a4a0644"}]}</bpmn:documentation>
    <bpmn:laneSet id="gate_Lanes_gate">
      <bpmn:lane id="gate_Lane_read" name="GET requirements: подготовка действий и оценка">
        <bpmn:flowNodeRef>gate_start</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>gate_scope</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>gate_ensure</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>gate_evaluate</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>gate_response</bpmn:flowNodeRef>
      </bpmn:lane>
      <bpmn:lane id="gate_Lane_activate" name="POST permission set_status=0: каноническая активация">
        <bpmn:flowNodeRef>gate_request</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>gate_lock</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>gate_gate</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>gate_ok</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>gate_save</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>gate_event</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>gate_end</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>gate_deny</bpmn:flowNodeRef>
      </bpmn:lane>
    </bpmn:laneSet>
    <bpmn:startEvent id="gate_start" name="GET requirements?model=permission">
      <bpmn:outgoing>gate_Flow_0</bpmn:outgoing>
      <bpmn:messageEventDefinition />
    </bpmn:startEvent>
    <bpmn:serviceTask id="gate_scope" name="Identity, capability, Ticket scope">
      <bpmn:incoming>gate_Flow_0</bpmn:incoming>
      <bpmn:outgoing>gate_Flow_1</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:serviceTask id="gate_ensure" name="Создать / переиспользовать недостающие действия">
      <bpmn:documentation>Обязательные черновики документов и попытки проверок, связанные ST_REQUEST при наличии настроенной очереди.</bpmn:documentation>
      <bpmn:incoming>gate_Flow_1</bpmn:incoming>
      <bpmn:outgoing>gate_Flow_2</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:serviceTask id="gate_evaluate" name="Read-only evaluate_requirements">
      <bpmn:incoming>gate_Flow_2</bpmn:incoming>
      <bpmn:outgoing>gate_Flow_3</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:endEvent id="gate_response" name="ok, required, present, missing, details">
      <bpmn:incoming>gate_Flow_3</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:startEvent id="gate_request" name="POST permission set_status=0">
      <bpmn:outgoing>gate_Flow_4</bpmn:outgoing>
      <bpmn:messageEventDefinition />
    </bpmn:startEvent>
    <bpmn:serviceTask id="gate_lock" name="Scope и блокировки Ticket / permission">
      <bpmn:incoming>gate_Flow_4</bpmn:incoming>
      <bpmn:outgoing>gate_Flow_5</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:serviceTask id="gate_gate" name="ensure actions + повторная оценка требований">
      <bpmn:incoming>gate_Flow_5</bpmn:incoming>
      <bpmn:outgoing>gate_Flow_6</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:exclusiveGateway id="gate_ok" name="Все обязательные требования ok?">
      <bpmn:incoming>gate_Flow_6</bpmn:incoming>
      <bpmn:outgoing>gate_Flow_7</bpmn:outgoing>
      <bpmn:outgoing>gate_Flow_8</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:serviceTask id="gate_save" name="Сохранить permission active и audit-поля">
      <bpmn:documentation>status=0, check_date; checked_by из assigned_to при наличии. Для METASERVICE-CLIENT/CORP-CLIENT синхронизировать соответствующую доменную запись.</bpmn:documentation>
      <bpmn:incoming>gate_Flow_7</bpmn:incoming>
      <bpmn:outgoing>gate_Flow_9</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:serviceTask id="gate_event" name="Записать Event, вернуть успешный ответ">
      <bpmn:incoming>gate_Flow_9</bpmn:incoming>
      <bpmn:outgoing>gate_Flow_10</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:endEvent id="gate_end" name="Активация зафиксирована">
      <bpmn:incoming>gate_Flow_10</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:endEvent id="gate_deny" name="Ошибка: активация не разрешена">
      <bpmn:incoming>gate_Flow_8</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:sequenceFlow id="gate_Flow_0" sourceRef="gate_start" targetRef="gate_scope" name="" />
    <bpmn:sequenceFlow id="gate_Flow_1" sourceRef="gate_scope" targetRef="gate_ensure" name="" />
    <bpmn:sequenceFlow id="gate_Flow_2" sourceRef="gate_ensure" targetRef="gate_evaluate" name="" />
    <bpmn:sequenceFlow id="gate_Flow_3" sourceRef="gate_evaluate" targetRef="gate_response" name="" />
    <bpmn:sequenceFlow id="gate_Flow_4" sourceRef="gate_request" targetRef="gate_lock" name="" />
    <bpmn:sequenceFlow id="gate_Flow_5" sourceRef="gate_lock" targetRef="gate_gate" name="" />
    <bpmn:sequenceFlow id="gate_Flow_6" sourceRef="gate_gate" targetRef="gate_ok" name="" />
    <bpmn:sequenceFlow id="gate_Flow_7" sourceRef="gate_ok" targetRef="gate_save" name="Да" />
    <bpmn:sequenceFlow id="gate_Flow_8" sourceRef="gate_ok" targetRef="gate_deny" name="Нет" />
    <bpmn:sequenceFlow id="gate_Flow_9" sourceRef="gate_save" targetRef="gate_event" name="" />
    <bpmn:sequenceFlow id="gate_Flow_10" sourceRef="gate_event" targetRef="gate_end" name="" />
  </bpmn:process>
  <bpmn:collaboration id="Collaboration_access_accepted_gate">
    <bpmn:participant id="gate_Pool_gate" name="Backend: два последовательных scoped запроса с разными задачами" processRef="gate_Process_gate" />
  </bpmn:collaboration>
  <bpmndi:BPMNDiagram id="Diagram_access_accepted_gate">
    <bpmndi:BPMNPlane id="Plane_access_accepted_gate" bpmnElement="Collaboration_access_accepted_gate">
      <bpmndi:BPMNShape id="gate_DI_Pool_gate" bpmnElement="gate_Pool_gate" isHorizontal="true">
        <dc:Bounds x="0.0" y="0.0" width="1960" height="700" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="gate_DI_Lane_read" bpmnElement="gate_Lane_read" isHorizontal="true">
        <dc:Bounds x="30.0" y="0.0" width="1930" height="250.0" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="gate_DI_Lane_activate" bpmnElement="gate_Lane_activate" isHorizontal="true">
        <dc:Bounds x="30.0" y="250.0" width="1930" height="450.0" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="gate_DI_start" bpmnElement="gate_start">
        <dc:Bounds x="132.0" y="92.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="gate_DI_scope" bpmnElement="gate_scope">
        <dc:Bounds x="345.0" y="75.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="gate_DI_ensure" bpmnElement="gate_ensure">
        <dc:Bounds x="625.0" y="75.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="gate_DI_evaluate" bpmnElement="gate_evaluate">
        <dc:Bounds x="905.0" y="75.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="gate_DI_response" bpmnElement="gate_response">
        <dc:Bounds x="1242.0" y="92.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="gate_DI_request" bpmnElement="gate_request">
        <dc:Bounds x="132.0" y="372.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="gate_DI_lock" bpmnElement="gate_lock">
        <dc:Bounds x="345.0" y="355.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="gate_DI_gate" bpmnElement="gate_gate">
        <dc:Bounds x="625.0" y="355.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="gate_DI_ok" bpmnElement="gate_ok">
        <dc:Bounds x="955.0" y="365.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="gate_DI_save" bpmnElement="gate_save">
        <dc:Bounds x="1185.0" y="355.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="gate_DI_event" bpmnElement="gate_event">
        <dc:Bounds x="1465.0" y="355.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="gate_DI_end" bpmnElement="gate_end">
        <dc:Bounds x="1782.0" y="372.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="gate_DI_deny" bpmnElement="gate_deny">
        <dc:Bounds x="962.0" y="582.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="gate_DI_Flow_0" bpmnElement="gate_Flow_0">
        <di:waypoint x="168.0" y="110.0" />
        <di:waypoint x="345.0" y="110.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="gate_DI_Flow_1" bpmnElement="gate_Flow_1">
        <di:waypoint x="495.0" y="110.0" />
        <di:waypoint x="625.0" y="110.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="gate_DI_Flow_2" bpmnElement="gate_Flow_2">
        <di:waypoint x="775.0" y="110.0" />
        <di:waypoint x="905.0" y="110.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="gate_DI_Flow_3" bpmnElement="gate_Flow_3">
        <di:waypoint x="1055.0" y="110.0" />
        <di:waypoint x="1242.0" y="110.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="gate_DI_Flow_4" bpmnElement="gate_Flow_4">
        <di:waypoint x="168.0" y="390.0" />
        <di:waypoint x="345.0" y="390.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="gate_DI_Flow_5" bpmnElement="gate_Flow_5">
        <di:waypoint x="495.0" y="390.0" />
        <di:waypoint x="625.0" y="390.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="gate_DI_Flow_6" bpmnElement="gate_Flow_6">
        <di:waypoint x="775.0" y="390.0" />
        <di:waypoint x="955.0" y="390.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="gate_DI_Flow_7" bpmnElement="gate_Flow_7">
        <di:waypoint x="1005.0" y="390.0" />
        <di:waypoint x="1185.0" y="390.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="gate_DI_Flow_8" bpmnElement="gate_Flow_8">
        <di:waypoint x="980.0" y="415.0" />
        <di:waypoint x="980.0" y="582.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="gate_DI_Flow_9" bpmnElement="gate_Flow_9">
        <di:waypoint x="1335.0" y="390.0" />
        <di:waypoint x="1465.0" y="390.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="gate_DI_Flow_10" bpmnElement="gate_Flow_10">
        <di:waypoint x="1615.0" y="390.0" />
        <di:waypoint x="1782.0" y="390.0" />
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn:definitions>

GET dbsynce/api/handler/ticket/{ticket_id}/requirements/?model=permission требует capability related.requirements.read и текущий Ticket scope. В этой реализации GET не является чистым чтением: перед оценкой он вызывает ensure_requirement_actions. Канонический evaluator остаётся read-only, а orchestration подготавливает недостающие обязательные черновики документов, попытки RequirementCheck и связанные профильные ST_REQUEST там, где это предусмотрено настройками.

Подготовка действий соблюдает доменные правила:

  • создаёт или переиспользует необходимые действия;
  • не навязывает необязательные требования;
  • не считает отсутствие CheckDefinition успехом;
  • требует правильно настроенной очереди для ручной проверки;
  • направляет проверку в очередь, соответствующую её области.

Необязательный публичный порт может подготовить сведения о встрече. Это организация, а не положительный результат проверки.

После ok=true runtime запрашивает dbsynce/api/handler/ticket/{ticket_id}/permission/ с действием set_status и status=0. Backend проверяет capability related.permission.status, scope, единственность связи и блокирует строки Ticket/permission. Установка active через совместимый set_status проходит тот же activate_object_if_requirements_met, что и явная activate-операция: повторная подготовка действий и новая оценка обязательных требований. Прямой status=0 не является обходом gate.

Успешная активация сохраняет:

  • active у permission;
  • дату проверки;
  • checked_by из assigned_to, когда он задан;
  • Event операции.

Для METASERVICE-CLIENT и CORP-CLIENT синхронизируются соответствующие Client/CorpClient с учётом связи Ticket. Источником права остаётся Permissions; доступ к интерфейсам определяется их ACL.

Внешний цикл выполнения требований и пробуждение (BPMN)

Схема BPMN

Загрузка схемы…

Исходник схемы
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_access_accepted_waiting" targetNamespace="urn:sharix:knowledge:handlers">
  <bpmn:process id="queue_Process_queue" name="Ожидание требований и повторная проверка ACCEPTED" isExecutable="false">
    <bpmn:documentation>{"notes": ["BPMN isExecutable=false. Генератор не исполняет handler.", "ACCEPTED — одобрение запроса, а не уже активное право.", "deferred_until — символ текущего локального срока; не имя параметра."], "sources": [{"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_access_request_accepted.py", "repository": "sharix-open-handlers-examples", "sha256": "de79926339c168601129401449b8dfdb1fb31baeaa4a0e6bb44200ea6047f237"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "generated_handler_blocks/open_access_request_accepted.json", "repository": "sharix-open-handlers-examples", "sha256": "f7a8543767cda70ad17092719edccd1d19b50de18fd31b93606767425fbe32ec"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "catalog.py", "repository": "sharix-open-handlers-examples", "sha256": "e3dcb72b7e620e2837adacd7af053f35b04cdff475789496d9c114e17d57dfde"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/blockly_runtime.py", "repository": "sharix-open-handlers-backend", "sha256": "3e222150cbff315077c6c9b160d46e59856cedf6d6591d213e958c63cb2f2428"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/handler_operations.py", "repository": "sharix-open-handlers-backend", "sha256": "28620658501c375f556e24437871620b84a17a88d0b62b2d1a3cc5deb2f14b1e"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/data_parsers.py", "repository": "sharix-open-handlers-backend", "sha256": "d7f26f172f68e4b390f675de88fbfb3c37a58fb29d4bf3d6687b31bd7953f9e4"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/ejabberd_muc.py", "repository": "sharix-open-handlers-backend", "sha256": "35c2eba89fab36b5c444439a87beaa516b55133991136d5370418d92a18d7bcd"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/requesters.py", "repository": "sharix-open-handlers-backend", "sha256": "965a348cea477722bbaf4c8c6b06023eb238b71664a332f7ea8c90bfe72ea808"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "classes/AccessRequestTicket.py", "repository": "sharix-open-handlers-backend", "sha256": "3f3a498ae76b3d878b19a8f32170fc2a71c6c6c182bf34a6ecc50edf7b0f5eff"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "ticket_blockly_codegen.py", "repository": "sharix-open-handlers-backend", "sha256": "bce71eab622922f8dd0954222842349799b60e18a0ab6310cc3e5f305603661e"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "ticket_codegen_contract.json", "repository": "sharix-open-handlers-backend", "sha256": "0bfd2b0ebb07bd380ed3c867386536ab88ef7dfa6e13f1cd8c91d32bb02c1ae9"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "lib/tickets.py", "repository": "sharix-open-tickets", "sha256": "0d260c17947f9a186d07af2749159780e3c7354a95b4bafe9d67493663c96883"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "api/views/handler_workflow.py", "repository": "sharix-open-tickets", "sha256": "f97c4b467a9a30749f5c4b86b39a833c430e57aaa1f030f70030d9b5c609d368"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "api/handler_auth.py", "repository": "sharix-open-tickets", "sha256": "ac76dc45aaa9742e5e1da0b98aae914bb2e287048d33e97b4a245a6997bc8425"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "utils.py", "repository": "sharix-open-tickets", "sha256": "a5680205c6522e1d9a74d9d267fe9ee96faf6f06436b00877fc0a93d80234bf5"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "views/ticket_detail.py", "repository": "sharix-open-tickets", "sha256": "05d344b0fba14cf895400694d4a18f486c800fef08dd1acb43ea46909b9e7e59"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "signals.py", "repository": "sharix-open-tickets", "sha256": "39aad8690a2e7d35cebfb052127a8130a951cbb4eea316c4f767a0a59fc5fa7e"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "services/handler_wakeup.py", "repository": "sharix-open-tickets", "sha256": "c9fdc62a18301fd7c075395c697d5b1c738c77713aa71fcbb5ab097e173d98de"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "apiviews/handler_workflow.py", "repository": "sharix-open-backend", "sha256": "0f699a4e16760cbbdd09d894093c685ba69073fedf0522852cb1fdc9811636e3"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/activation.py", "repository": "sharix-open-backend", "sha256": "f78d4e219a5b83c7952bd366a4e7a711589b1d382af653a0c453c0524e4220f7"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/requirement_actions.py", "repository": "sharix-open-backend", "sha256": "717ef0f3e02ff8e6da103b5fdbae584b01d84d177f6e62ae677a1c5a366b71de"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/requirement_checks.py", "repository": "sharix-open-backend", "sha256": "5a73a6e71307e734f0c0e480fd14a825a7a22242811e2523b7f25157224cf34c"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/document_drafts.py", "repository": "sharix-open-backend", "sha256": "383b117f01fdd9d16de3ceb9afb1ccf0bf3104c4966b23e987b8a90e9a46f071"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/verification_workflow.py", "repository": "sharix-open-backend", "sha256": "9fe62f8344d7fd78e5af0ce025c82ba4f7d21759e71f518df1186a1d6a4a0644"}]}</bpmn:documentation>
    <bpmn:laneSet id="queue_Lanes_queue">
      <bpmn:lane id="queue_Lane_worker" name="Между проходами worker свободен">
        <bpmn:flowNodeRef>queue_start</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>queue_wait</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>queue_timer</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>queue_revision</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>queue_ready</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>queue_again</bpmn:flowNodeRef>
      </bpmn:lane>
    </bpmn:laneSet>
    <bpmn:startEvent id="queue_start" name="Назначен локальный defer">
      <bpmn:outgoing>queue_Flow_0</bpmn:outgoing>
    </bpmn:startEvent>
    <bpmn:eventBasedGateway id="queue_wait" name="Что наступило раньше?">
      <bpmn:incoming>queue_Flow_0</bpmn:incoming>
      <bpmn:outgoing>queue_Flow_1</bpmn:outgoing>
      <bpmn:outgoing>queue_Flow_2</bpmn:outgoing>
    </bpmn:eventBasedGateway>
    <bpmn:intermediateCatchEvent id="queue_timer" name="Наступил deferred_until">
      <bpmn:incoming>queue_Flow_1</bpmn:incoming>
      <bpmn:outgoing>queue_Flow_3</bpmn:outgoing>
      <bpmn:timerEventDefinition>
        <bpmn:timeDate xsi:type="bpmn:tFormalExpression">deferred_until</bpmn:timeDate>
      </bpmn:timerEventDefinition>
    </bpmn:intermediateCatchEvent>
    <bpmn:intermediateCatchEvent id="queue_revision" name="Получена новая ревизия Ticket">
      <bpmn:incoming>queue_Flow_2</bpmn:incoming>
      <bpmn:outgoing>queue_Flow_4</bpmn:outgoing>
      <bpmn:messageEventDefinition />
    </bpmn:intermediateCatchEvent>
    <bpmn:serviceTask id="queue_ready" name="Снять defer, вернуть в ready FIFO">
      <bpmn:incoming>queue_Flow_3</bpmn:incoming>
      <bpmn:incoming>queue_Flow_4</bpmn:incoming>
      <bpmn:outgoing>queue_Flow_5</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:endEvent id="queue_again" name="Новый проход с актуальным снимком">
      <bpmn:incoming>queue_Flow_5</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:sequenceFlow id="queue_Flow_0" sourceRef="queue_start" targetRef="queue_wait" name="" />
    <bpmn:sequenceFlow id="queue_Flow_1" sourceRef="queue_wait" targetRef="queue_timer" name="" />
    <bpmn:sequenceFlow id="queue_Flow_2" sourceRef="queue_wait" targetRef="queue_revision" name="" />
    <bpmn:sequenceFlow id="queue_Flow_3" sourceRef="queue_timer" targetRef="queue_ready" name="" />
    <bpmn:sequenceFlow id="queue_Flow_4" sourceRef="queue_revision" targetRef="queue_ready" name="" />
    <bpmn:sequenceFlow id="queue_Flow_5" sourceRef="queue_ready" targetRef="queue_again" name="" />
  </bpmn:process>
  <bpmn:process id="checks_Process_checks" name="Профильные ST_REQUEST-проверки: пользователь / проверяющий / алгоритм" isExecutable="false">
    <bpmn:documentation>{"notes": ["BPMN isExecutable=false. Генератор не исполняет handler.", "ACCEPTED — одобрение запроса, а не уже активное право.", "deferred_until — символ текущего локального срока; не имя параметра."], "sources": [{"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_access_request_accepted.py", "repository": "sharix-open-handlers-examples", "sha256": "de79926339c168601129401449b8dfdb1fb31baeaa4a0e6bb44200ea6047f237"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "generated_handler_blocks/open_access_request_accepted.json", "repository": "sharix-open-handlers-examples", "sha256": "f7a8543767cda70ad17092719edccd1d19b50de18fd31b93606767425fbe32ec"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "catalog.py", "repository": "sharix-open-handlers-examples", "sha256": "e3dcb72b7e620e2837adacd7af053f35b04cdff475789496d9c114e17d57dfde"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/blockly_runtime.py", "repository": "sharix-open-handlers-backend", "sha256": "3e222150cbff315077c6c9b160d46e59856cedf6d6591d213e958c63cb2f2428"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/handler_operations.py", "repository": "sharix-open-handlers-backend", "sha256": "28620658501c375f556e24437871620b84a17a88d0b62b2d1a3cc5deb2f14b1e"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/data_parsers.py", "repository": "sharix-open-handlers-backend", "sha256": "d7f26f172f68e4b390f675de88fbfb3c37a58fb29d4bf3d6687b31bd7953f9e4"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/ejabberd_muc.py", "repository": "sharix-open-handlers-backend", "sha256": "35c2eba89fab36b5c444439a87beaa516b55133991136d5370418d92a18d7bcd"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/requesters.py", "repository": "sharix-open-handlers-backend", "sha256": "965a348cea477722bbaf4c8c6b06023eb238b71664a332f7ea8c90bfe72ea808"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "classes/AccessRequestTicket.py", "repository": "sharix-open-handlers-backend", "sha256": "3f3a498ae76b3d878b19a8f32170fc2a71c6c6c182bf34a6ecc50edf7b0f5eff"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "ticket_blockly_codegen.py", "repository": "sharix-open-handlers-backend", "sha256": "bce71eab622922f8dd0954222842349799b60e18a0ab6310cc3e5f305603661e"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "ticket_codegen_contract.json", "repository": "sharix-open-handlers-backend", "sha256": "0bfd2b0ebb07bd380ed3c867386536ab88ef7dfa6e13f1cd8c91d32bb02c1ae9"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "lib/tickets.py", "repository": "sharix-open-tickets", "sha256": "0d260c17947f9a186d07af2749159780e3c7354a95b4bafe9d67493663c96883"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "api/views/handler_workflow.py", "repository": "sharix-open-tickets", "sha256": "f97c4b467a9a30749f5c4b86b39a833c430e57aaa1f030f70030d9b5c609d368"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "api/handler_auth.py", "repository": "sharix-open-tickets", "sha256": "ac76dc45aaa9742e5e1da0b98aae914bb2e287048d33e97b4a245a6997bc8425"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "utils.py", "repository": "sharix-open-tickets", "sha256": "a5680205c6522e1d9a74d9d267fe9ee96faf6f06436b00877fc0a93d80234bf5"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "views/ticket_detail.py", "repository": "sharix-open-tickets", "sha256": "05d344b0fba14cf895400694d4a18f486c800fef08dd1acb43ea46909b9e7e59"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "signals.py", "repository": "sharix-open-tickets", "sha256": "39aad8690a2e7d35cebfb052127a8130a951cbb4eea316c4f767a0a59fc5fa7e"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "services/handler_wakeup.py", "repository": "sharix-open-tickets", "sha256": "c9fdc62a18301fd7c075395c697d5b1c738c77713aa71fcbb5ab097e173d98de"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "apiviews/handler_workflow.py", "repository": "sharix-open-backend", "sha256": "0f699a4e16760cbbdd09d894093c685ba69073fedf0522852cb1fdc9811636e3"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/activation.py", "repository": "sharix-open-backend", "sha256": "f78d4e219a5b83c7952bd366a4e7a711589b1d382af653a0c453c0524e4220f7"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/requirement_actions.py", "repository": "sharix-open-backend", "sha256": "717ef0f3e02ff8e6da103b5fdbae584b01d84d177f6e62ae677a1c5a366b71de"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/requirement_checks.py", "repository": "sharix-open-backend", "sha256": "5a73a6e71307e734f0c0e480fd14a825a7a22242811e2523b7f25157224cf34c"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/document_drafts.py", "repository": "sharix-open-backend", "sha256": "383b117f01fdd9d16de3ceb9afb1ccf0bf3104c4966b23e987b8a90e9a46f071"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/verification_workflow.py", "repository": "sharix-open-backend", "sha256": "9fe62f8344d7fd78e5af0ce025c82ba4f7d21759e71f518df1186a1d6a4a0644"}]}</bpmn:documentation>
    <bpmn:laneSet id="checks_Lanes_checks">
      <bpmn:lane id="checks_Lane_worker" name="Внешний цикл по документам и RequirementCheck">
        <bpmn:flowNodeRef>checks_start</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>checks_result</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>checks_complete</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>checks_ok</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>checks_wake</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>checks_done</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>checks_not_yet</bpmn:flowNodeRef>
      </bpmn:lane>
    </bpmn:laneSet>
    <bpmn:startEvent id="checks_start" name="Не хватает обязательного подтверждения">
      <bpmn:outgoing>checks_Flow_0</bpmn:outgoing>
    </bpmn:startEvent>
    <bpmn:task id="checks_result" name="Получить результат профильной проверки">
      <bpmn:documentation>Отдельный ручной либо автоматический ST_REQUEST-процесс; он раскрыт на связанных страницах. Загрузка черновика и проверенная версия — разные факты.</bpmn:documentation>
      <bpmn:incoming>checks_Flow_0</bpmn:incoming>
      <bpmn:outgoing>checks_Flow_1</bpmn:outgoing>
    </bpmn:task>
    <bpmn:serviceTask id="checks_complete" name="Доменный complete: пересчитать потребителей">
      <bpmn:incoming>checks_Flow_1</bpmn:incoming>
      <bpmn:outgoing>checks_Flow_2</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:exclusiveGateway id="checks_ok" name="Требования permission теперь ok?">
      <bpmn:incoming>checks_Flow_2</bpmn:incoming>
      <bpmn:outgoing>checks_Flow_3</bpmn:outgoing>
      <bpmn:outgoing>checks_Flow_4</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:sendTask id="checks_wake" name="Возобновить одобренную активацию: wakeup">
      <bpmn:documentation>Для ACCESS_REQUEST обновить Ticket.updated_at и после commit отправить ticket.changed, не активировать permission прямо в ST_REQUEST.</bpmn:documentation>
      <bpmn:incoming>checks_Flow_3</bpmn:incoming>
      <bpmn:outgoing>checks_Flow_5</bpmn:outgoing>
    </bpmn:sendTask>
    <bpmn:endEvent id="checks_done" name="Текущий handler получит новое состояние">
      <bpmn:incoming>checks_Flow_5</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:endEvent id="checks_not_yet" name="Остаются другие невыполненные требования">
      <bpmn:incoming>checks_Flow_4</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:sequenceFlow id="checks_Flow_0" sourceRef="checks_start" targetRef="checks_result" name="" />
    <bpmn:sequenceFlow id="checks_Flow_1" sourceRef="checks_result" targetRef="checks_complete" name="" />
    <bpmn:sequenceFlow id="checks_Flow_2" sourceRef="checks_complete" targetRef="checks_ok" name="" />
    <bpmn:sequenceFlow id="checks_Flow_3" sourceRef="checks_ok" targetRef="checks_wake" name="Да" />
    <bpmn:sequenceFlow id="checks_Flow_4" sourceRef="checks_ok" targetRef="checks_not_yet" name="Нет" />
    <bpmn:sequenceFlow id="checks_Flow_5" sourceRef="checks_wake" targetRef="checks_done" name="" />
  </bpmn:process>
  <bpmn:collaboration id="Collaboration_access_accepted_waiting">
    <bpmn:participant id="queue_Pool_queue" name="Ожидание требований и повторная проверка ACCEPTED" processRef="queue_Process_queue" />
    <bpmn:participant id="checks_Pool_checks" name="Профильные ST_REQUEST-проверки: пользователь / проверяющий / алгоритм" processRef="checks_Process_checks" />
    <bpmn:messageFlow id="Message_access_accepted_waiting_0" sourceRef="checks_wake" targetRef="queue_revision" name="ticket.changed после commit → scoped refresh" />
  </bpmn:collaboration>
  <bpmndi:BPMNDiagram id="Diagram_access_accepted_waiting">
    <bpmndi:BPMNPlane id="Plane_access_accepted_waiting" bpmnElement="Collaboration_access_accepted_waiting">
      <bpmndi:BPMNShape id="queue_DI_Pool_queue" bpmnElement="queue_Pool_queue" isHorizontal="true">
        <dc:Bounds x="0.0" y="0.0" width="1360" height="410" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="queue_DI_Lane_worker" bpmnElement="queue_Lane_worker" isHorizontal="true">
        <dc:Bounds x="30.0" y="0.0" width="1330" height="410" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="queue_DI_start" bpmnElement="queue_start">
        <dc:Bounds x="132.0" y="92.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="queue_DI_wait" bpmnElement="queue_wait">
        <dc:Bounds x="375.0" y="85.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="queue_DI_timer" bpmnElement="queue_timer">
        <dc:Bounds x="642.0" y="92.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="queue_DI_revision" bpmnElement="queue_revision">
        <dc:Bounds x="642.0" y="292.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="queue_DI_ready" bpmnElement="queue_ready">
        <dc:Bounds x="865.0" y="75.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="queue_DI_again" bpmnElement="queue_again">
        <dc:Bounds x="1182.0" y="92.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="queue_DI_Flow_0" bpmnElement="queue_Flow_0">
        <di:waypoint x="168.0" y="110.0" />
        <di:waypoint x="375.0" y="110.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="queue_DI_Flow_1" bpmnElement="queue_Flow_1">
        <di:waypoint x="425.0" y="110.0" />
        <di:waypoint x="642.0" y="110.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="queue_DI_Flow_2" bpmnElement="queue_Flow_2">
        <di:waypoint x="425.0" y="110.0" />
        <di:waypoint x="533.5" y="110.0" />
        <di:waypoint x="533.5" y="310.0" />
        <di:waypoint x="642.0" y="310.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="queue_DI_Flow_3" bpmnElement="queue_Flow_3">
        <di:waypoint x="678.0" y="110.0" />
        <di:waypoint x="865.0" y="110.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="queue_DI_Flow_4" bpmnElement="queue_Flow_4">
        <di:waypoint x="678.0" y="310.0" />
        <di:waypoint x="771.5" y="310.0" />
        <di:waypoint x="771.5" y="110.0" />
        <di:waypoint x="865.0" y="110.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="queue_DI_Flow_5" bpmnElement="queue_Flow_5">
        <di:waypoint x="1015.0" y="110.0" />
        <di:waypoint x="1182.0" y="110.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="checks_DI_Pool_checks" bpmnElement="checks_Pool_checks" isHorizontal="true">
        <dc:Bounds x="0.0" y="550.0" width="1690" height="380" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="checks_DI_Lane_worker" bpmnElement="checks_Lane_worker" isHorizontal="true">
        <dc:Bounds x="30.0" y="550.0" width="1660" height="380" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="checks_DI_start" bpmnElement="checks_start">
        <dc:Bounds x="132.0" y="632.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="checks_DI_result" bpmnElement="checks_result">
        <dc:Bounds x="345.0" y="615.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="checks_DI_complete" bpmnElement="checks_complete">
        <dc:Bounds x="645.0" y="615.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="checks_DI_ok" bpmnElement="checks_ok">
        <dc:Bounds x="975.0" y="625.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="checks_DI_wake" bpmnElement="checks_wake">
        <dc:Bounds x="1205.0" y="615.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="checks_DI_done" bpmnElement="checks_done">
        <dc:Bounds x="1512.0" y="632.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="checks_DI_not_yet" bpmnElement="checks_not_yet">
        <dc:Bounds x="982.0" y="812.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="checks_DI_Flow_0" bpmnElement="checks_Flow_0">
        <di:waypoint x="168.0" y="650.0" />
        <di:waypoint x="345.0" y="650.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="checks_DI_Flow_1" bpmnElement="checks_Flow_1">
        <di:waypoint x="495.0" y="650.0" />
        <di:waypoint x="645.0" y="650.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="checks_DI_Flow_2" bpmnElement="checks_Flow_2">
        <di:waypoint x="795.0" y="650.0" />
        <di:waypoint x="975.0" y="650.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="checks_DI_Flow_3" bpmnElement="checks_Flow_3">
        <di:waypoint x="1025.0" y="650.0" />
        <di:waypoint x="1205.0" y="650.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="checks_DI_Flow_4" bpmnElement="checks_Flow_4">
        <di:waypoint x="1000.0" y="675.0" />
        <di:waypoint x="1000.0" y="812.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="checks_DI_Flow_5" bpmnElement="checks_Flow_5">
        <di:waypoint x="1355.0" y="650.0" />
        <di:waypoint x="1512.0" y="650.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="DI_Message_access_accepted_waiting_0" bpmnElement="Message_access_accepted_waiting_0">
        <di:waypoint x="1280" y="685" />
        <di:waypoint x="1400" y="685" />
        <di:waypoint x="1400" y="450" />
        <di:waypoint x="660" y="450" />
        <di:waypoint x="660" y="328" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="875" y="405" width="260" height="42" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn:definitions>

Пользователь/проверяющий либо настроенный алгоритм выполняет отдельный профильный процесс. Загрузка черновика документа, создание заявки проверки и проверенная версия документа — разные состояния. Подробные решения описаны в IN_PROCESS и DONE. Здесь показана их связь с ожидающим ACCESS_REQUEST, а не исполнение всех действий внутри этого handler.

Когда профильный complete пересчитывает потребителей и требования permission удовлетворены, resume_approved_activation для ACCESS_REQUEST не активирует право скрыто. Он обновляет ревизию Ticket и после commit отправляет ticket.changed текущему handler. Runtime получает scoped актуальный снимок, снимает прежний defer и снова проходит явные Blockly-проверки. При потере сообщения повтор обеспечивают таймер и periodic reconciliation.

Если остаются другие невыполненные требования, completion одной проверки не означает готовность всего права. Отрицательный результат либо незавершённые документы не должны заменяться ручным выставлением active в обход gate.

Ошибки, уведомления и раздельная фиксация

Первоначальный ok и результат активации могут различаться: между запросами меняются данные, требования или scope. Runtime обрабатывает часть отрицательных ответов операции активации как false и ждёт 900 секунд; 401/403/429 и 5xx вызывают исключение и общий processing_error. Ошибки read/requirements API и неожиданные ошибки уведомлений также идут в общий retry. Если проблема постоянна, один таймер её не устраняет: нужно разобрать причину и данные.

404 при переходе в CLOSED запрашивает локальную очистку как для устаревшего scope. Если permission уже активировалась, а закрытие Ticket не удалось, активное право не откатывается. Следующий проход заново проверяет ту же связь и gate; он не должен считаться созданием нового права. Для диагностики различайте статус Ticket, status/check_date/checked_by permission, requirements и Event операции.

Уведомления этой ветви:

  • Автор: legacy helper с локальным Django-поиском пользователя и XMPP-реквизитов; отсутствие получателя логируется.
  • Администраторы: MUC-комната по правилам PENDING — активные METASERVICE-ADMIN, текущий bot и report JID.

Это не адресный reviewer API профильных ST_REQUEST. Durable verification ack здесь нет, повторные проходы допускают повтор сообщения; send не доказывает прочтения.

Интервалы и внешнее решение

Причина Повтор
related_permission_missing ACCESS_REQUEST_INCONSISTENCY_RECHECK_SECONDS
requirements_pending ACCESS_REQUEST_INCONSISTENCY_RECHECK_SECONDS
related_permission_inconsistent 900 секунд, константа Python
processing_error DEFERRED_TICKET_RECHECK_SECONDS
Восстановление состава очереди INTERVAL_TIME_BD_REQ

Defer хранится в памяти и освобождает worker. Новая authoritative revision снимает ожидание, дубликат того же снимка — нет. Срок означает готовность к проходу, не точное время запуска. При ошибке scoped списка прежний снимок не удаляется как будто backend подтвердил отсутствие Ticket.

Для ручного изменения самого Ticket текущий lifecycle из ACCEPTED разрешает DECLINED либо CLOSED при соответствующих правах; авторство само по себе не даёт права принять/отозвать решение. Перевод Ticket в DECLINED не равен автоматическому удалению уже active permission: соответствующий handler отдельно обрабатывает несогласованность.

Диагностика

Порядок диагностики:

  1. Проверить единственную permission, связанную с Ticket.
  2. Прочитать реально missing requirements и созданные действия.
  3. Проверить состояния внешних проверок и обратный wakeup.
  4. Прочитать результат повторного activation gate.
  5. Отдельно проверить CLOSED и Event операции.

Если permission уже active, а требования стали missing, текущий handler сам её не деактивирует: он ждёт. Текст уведомления «право пока не активировано» не заменяет чтение фактического status.

Проверенные источники

Git SHA/SHA-256 и параметры моделей закреплены в metadata и documentation BPMN. Код обработчиков при анализе не исполнялся. Изменение Blockly, runtime, API/ACL или доменного gate требует повторного сопоставления, а не только смены хешей.

Связанные материалы

sharixopen/knowledge/scenarios/access_request_accepted.txt · Последнее изменение: — sx_knowledge_api_open

© 2022 ShariX