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

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


sharixopen:knowledge:scenarios:st_request_inprocess

Это старая версия документа!


ST_REQUEST в работе: обычное обращение и профильная проверка

Область: ShariX Open. Обработчик: open_st_request_inprocess, тип ST_REQUEST (1), рабочий статус IN_PROCESS. Описана опубликованная встроенная реализация и изученные внешние контракты на 28.10.2026. Сгенерированный Python побайтово совпадает с результатом канонического renderer Blockly workspace. Выбранная версия на конкретной установке, её настройки и доступность API/XMPP проверяются отдельно.

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

Обработчик сопровождает обращение на стадии выполнения. Сначала он проверяет рабочий статус, затем стабильный контракт в Ticket.json. Контракты document-verification-v1 и requirement-check-v1 идут в профильный workflow до проверки STREQ_AUTOACCEPT. При REST-снимке контракт читается непосредственно из metadata; при первоначальном XMPP-конверте учитывается вложенное поле json. Название карточки не определяет её контракт.

Для обычного обращения отключённый STREQ_AUTOACCEPT означает ожидание работы пользователя, включённый — запрос перехода в DONE. Сам обработчик не исполняет текст обращения, не доказывает устранение проблемы и не выполняет ручную проверку. Для профильных контрактов autoaccept не заменяет решение проверяющего или доменную политику результата.

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

Алгоритм одного прохода и ожидание (BPMN)

Схема BPMN

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

Исходник схемы
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:ns2="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:ns3="http://www.omg.org/spec/DD/20100524/DC" xmlns:ns4="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_st_inprocess_logic" targetNamespace="urn:sharix:knowledge:handlers">
  <bpmn:process id="ip_Process_ip" name="open_st_request_inprocess: один проход Python и локальное ожидание" isExecutable="false">
    <bpmn:documentation>{"notes": ["Опубликованный Git built-in; не подтверждение выбранной версии на любом сервере.", "Процессы не исполняются просмотрщиком. End event завершает показанную операцию, не всю заявку.", "deferred_until — символ локального срока, не имя параметра конфигурации."], "sources": [{"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "generated_handler_blocks/open_st_request_inprocess.json", "repository": "sharix-open-handlers-examples", "sha256": "aedf573066b509bc1d7177d08530ae2ed1a5e896c8745e02edaed27e3d561313"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_st_request_inprocess.py", "repository": "sharix-open-handlers-examples", "sha256": "7dc2424c827ba4dc04971a8691d0e624566c6b4cb409cffec2e552dcad2aca4d"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_st_request_done.py", "repository": "sharix-open-handlers-examples", "sha256": "b6ae4733904d9ba8e691f43235d4836d201ac019ff99982d532816bfdc89bf31"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_st_request_wontfix.py", "repository": "sharix-open-handlers-examples", "sha256": "ece9fb7e09ee0e401e91d5d274d6b151b51d1364ba698b835c929e6416f90f03"}, {"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/requesters.py", "repository": "sharix-open-handlers-backend", "sha256": "965a348cea477722bbaf4c8c6b06023eb238b71664a332f7ea8c90bfe72ea808"}, {"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": "services/verification_results.py", "repository": "sharix-open-tickets", "sha256": "682c5f6869373e649d6d62f44e63e8fb3bb34cf6bfc85d0187b26b2c96984e91"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "services/st_request_contracts.py", "repository": "sharix-open-tickets", "sha256": "9c1553437dbff63c608504ee000fa67a9be6e9887b1df0599552aa4d9141276c"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "views/ticket_detail.py", "repository": "sharix-open-tickets", "sha256": "05d344b0fba14cf895400694d4a18f486c800fef08dd1acb43ea46909b9e7e59"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "utils.py", "repository": "sharix-open-tickets", "sha256": "a5680205c6522e1d9a74d9d267fe9ee96faf6f06436b00877fc0a93d80234bf5"}, {"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": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "api/views/handler_workflow.py", "repository": "sharix-open-tickets", "sha256": "f97c4b467a9a30749f5c4b86b39a833c430e57aaa1f030f70030d9b5c609d368"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "apiviews/handler_workflow.py", "repository": "sharix-open-backend", "sha256": "0f699a4e16760cbbdd09d894093c685ba69073fedf0522852cb1fdc9811636e3"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/verification_workflow.py", "repository": "sharix-open-backend", "sha256": "9fe62f8344d7fd78e5af0ce025c82ba4f7d21759e71f518df1186a1d6a4a0644"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/verification_algorithms.py", "repository": "sharix-open-backend", "sha256": "9e55e4119051847bb3596c3563b9b151ee92b660e89c39c533b16ed6b4a2099e"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/verification_responsibility.py", "repository": "sharix-open-backend", "sha256": "7919b83c89cb4214545ea2c2db0cffac09af892b190ce3af72348d688abb9cf4"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/requirement_checks.py", "repository": "sharix-open-backend", "sha256": "5a73a6e71307e734f0c0e480fd14a825a7a22242811e2523b7f25157224cf34c"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/integration_ports.py", "repository": "sharix-open-backend", "sha256": "d079ec56e6709b29d7755e47d2a88d423235fe8eb1bf7a92851ae25d74bf1066"}]}</bpmn:documentation>
    <bpmn:laneSet id="ip_Lanes_ip">
      <bpmn:lane id="ip_Lane_worker" name="Worker: канонический Python из Blockly">
        <bpmn:flowNodeRef>ip_start</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>ip_status</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>ip_contract</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>ip_organize</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>ip_advance</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>ip_special_end</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>ip_stale</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>ip_stale_end</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>ip_auto</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>ip_manual</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>ip_transition</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>ip_confirmed</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>ip_remove</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>ip_done</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>ip_not_found</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>ip_api_error</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>ip_workflow_error</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>ip_notify_error</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>ip_retry</bpmn:flowNodeRef>
      </bpmn:lane>
      <bpmn:lane id="ip_Lane_queue" name="Планировщик: ожидание без занятого worker">
        <bpmn:flowNodeRef>ip_wait</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>ip_timer</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>ip_revision</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>ip_ready</bpmn:flowNodeRef>
      </bpmn:lane>
    </bpmn:laneSet>
    <bpmn:startEvent id="ip_start" name="Ticket готов к проходу">
      <bpmn:outgoing>ip_Flow_0</bpmn:outgoing>
    </bpmn:startEvent>
    <bpmn:exclusiveGateway id="ip_status" name="Статус IN_PROCESS?">
      <bpmn:incoming>ip_Flow_0</bpmn:incoming>
      <bpmn:incoming>ip_Flow_23</bpmn:incoming>
      <bpmn:outgoing>ip_Flow_1</bpmn:outgoing>
      <bpmn:outgoing>ip_Flow_2</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:exclusiveGateway id="ip_contract" name="Контракт проверки?">
      <bpmn:incoming>ip_Flow_1</bpmn:incoming>
      <bpmn:outgoing>ip_Flow_4</bpmn:outgoing>
      <bpmn:outgoing>ip_Flow_7</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:serviceTask id="ip_organize" name="Подготовить организацию проверки">
      <bpmn:documentation>Только requirement-check-v1; документ — no-op. Ошибка API/JSON логируется, затем advance всё равно вызывается.</bpmn:documentation>
      <bpmn:incoming>ip_Flow_4</bpmn:incoming>
      <bpmn:outgoing>ip_Flow_5</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:serviceTask id="ip_advance" name="Вызвать профильный workflow">
      <bpmn:documentation>Scoped verification API, уведомления, ожидание либо DONE/WONTFIX. Подробно — на следующей схеме.</bpmn:documentation>
      <bpmn:incoming>ip_Flow_5</bpmn:incoming>
      <bpmn:outgoing>ip_Flow_6</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:endEvent id="ip_special_end" name="Проход завершён по профильной ветви">
      <bpmn:incoming>ip_Flow_6</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:serviceTask id="ip_stale" name="Удалить локальный Ticket и комнату">
      <bpmn:incoming>ip_Flow_2</bpmn:incoming>
      <bpmn:outgoing>ip_Flow_3</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:endEvent id="ip_stale_end" name="Этот handler больше не владелец">
      <bpmn:incoming>ip_Flow_3</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:exclusiveGateway id="ip_auto" name="STREQ_AUTOACCEPT?">
      <bpmn:incoming>ip_Flow_7</bpmn:incoming>
      <bpmn:outgoing>ip_Flow_8</bpmn:outgoing>
      <bpmn:outgoing>ip_Flow_9</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:serviceTask id="ip_manual" name="Причина: support_execution; defer">
      <bpmn:documentation>ST_REQUEST_IN_PROCESS_RECHECK_SECONDS. В журнале defer: st_request_in_process. Содержание обращения не выполняется.</bpmn:documentation>
      <bpmn:incoming>ip_Flow_8</bpmn:incoming>
      <bpmn:outgoing>ip_Flow_14</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:serviceTask id="ip_transition" name="Scoped API: перевести в DONE">
      <bpmn:documentation>Без явного send_to_handler: новый владелец получает backend wakeup, с periodic fallback.</bpmn:documentation>
      <bpmn:incoming>ip_Flow_9</bpmn:incoming>
      <bpmn:outgoing>ip_Flow_10</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:exclusiveGateway id="ip_confirmed" name="Переход подтверждён?">
      <bpmn:incoming>ip_Flow_10</bpmn:incoming>
      <bpmn:outgoing>ip_Flow_11</bpmn:outgoing>
      <bpmn:outgoing>ip_Flow_13</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:serviceTask id="ip_remove" name="Удалить локальный Ticket и комнату">
      <bpmn:incoming>ip_Flow_11</bpmn:incoming>
      <bpmn:outgoing>ip_Flow_12</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:endEvent id="ip_done" name="Этот проход завершён">
      <bpmn:incoming>ip_Flow_12</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:endEvent id="ip_not_found" name="404: очистка уже запрошена">
      <bpmn:incoming>ip_Flow_13</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:boundaryEvent id="ip_api_error" name="Ошибка API" attachedToRef="ip_transition" cancelActivity="true">
      <bpmn:outgoing>ip_Flow_15</bpmn:outgoing>
      <bpmn:errorEventDefinition />
    </bpmn:boundaryEvent>
    <bpmn:boundaryEvent id="ip_workflow_error" name="Иная ошибка" attachedToRef="ip_advance" cancelActivity="true">
      <bpmn:outgoing>ip_Flow_16</bpmn:outgoing>
      <bpmn:errorEventDefinition />
    </bpmn:boundaryEvent>
    <bpmn:boundaryEvent id="ip_notify_error" name="Ошибка уведомления" attachedToRef="ip_organize" cancelActivity="true">
      <bpmn:outgoing>ip_Flow_17</bpmn:outgoing>
      <bpmn:errorEventDefinition />
    </bpmn:boundaryEvent>
    <bpmn:serviceTask id="ip_retry" name="Общий retry: processing_error + defer">
      <bpmn:documentation>DEFERRED_TICKET_RECHECK_SECONDS; исключение не откатывает уже committed доменные изменения или статус.</bpmn:documentation>
      <bpmn:incoming>ip_Flow_15</bpmn:incoming>
      <bpmn:incoming>ip_Flow_16</bpmn:incoming>
      <bpmn:incoming>ip_Flow_17</bpmn:incoming>
      <bpmn:outgoing>ip_Flow_18</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:eventBasedGateway id="ip_wait" name="Что наступило раньше?">
      <bpmn:incoming>ip_Flow_14</bpmn:incoming>
      <bpmn:incoming>ip_Flow_18</bpmn:incoming>
      <bpmn:outgoing>ip_Flow_19</bpmn:outgoing>
      <bpmn:outgoing>ip_Flow_20</bpmn:outgoing>
    </bpmn:eventBasedGateway>
    <bpmn:intermediateCatchEvent id="ip_timer" name="Локальный срок defer">
      <bpmn:incoming>ip_Flow_19</bpmn:incoming>
      <bpmn:outgoing>ip_Flow_21</bpmn:outgoing>
      <bpmn:timerEventDefinition>
        <bpmn:timeDate xsi:type="bpmn:tFormalExpression">deferred_until</bpmn:timeDate>
      </bpmn:timerEventDefinition>
    </bpmn:intermediateCatchEvent>
    <bpmn:intermediateCatchEvent id="ip_revision" name="Получена новая ревизия Ticket">
      <bpmn:incoming>ip_Flow_20</bpmn:incoming>
      <bpmn:outgoing>ip_Flow_22</bpmn:outgoing>
      <bpmn:messageEventDefinition />
    </bpmn:intermediateCatchEvent>
    <bpmn:serviceTask id="ip_ready" name="Снять defer, вернуть в ready FIFO">
      <bpmn:documentation>Дубликат ревизии не снимает ожидание. Запуск при готовом XMPP и свободном worker.</bpmn:documentation>
      <bpmn:incoming>ip_Flow_21</bpmn:incoming>
      <bpmn:incoming>ip_Flow_22</bpmn:incoming>
      <bpmn:outgoing>ip_Flow_23</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:sequenceFlow id="ip_Flow_0" sourceRef="ip_start" targetRef="ip_status" name="" />
    <bpmn:sequenceFlow id="ip_Flow_1" sourceRef="ip_status" targetRef="ip_contract" name="Да" />
    <bpmn:sequenceFlow id="ip_Flow_2" sourceRef="ip_status" targetRef="ip_stale" name="Нет" />
    <bpmn:sequenceFlow id="ip_Flow_3" sourceRef="ip_stale" targetRef="ip_stale_end" name="" />
    <bpmn:sequenceFlow id="ip_Flow_4" sourceRef="ip_contract" targetRef="ip_organize" name="Да" />
    <bpmn:sequenceFlow id="ip_Flow_5" sourceRef="ip_organize" targetRef="ip_advance" name="" />
    <bpmn:sequenceFlow id="ip_Flow_6" sourceRef="ip_advance" targetRef="ip_special_end" name="" />
    <bpmn:sequenceFlow id="ip_Flow_7" sourceRef="ip_contract" targetRef="ip_auto" name="Нет" />
    <bpmn:sequenceFlow id="ip_Flow_8" sourceRef="ip_auto" targetRef="ip_manual" name="Нет" />
    <bpmn:sequenceFlow id="ip_Flow_9" sourceRef="ip_auto" targetRef="ip_transition" name="Да" />
    <bpmn:sequenceFlow id="ip_Flow_10" sourceRef="ip_transition" targetRef="ip_confirmed" name="" />
    <bpmn:sequenceFlow id="ip_Flow_11" sourceRef="ip_confirmed" targetRef="ip_remove" name="Да" />
    <bpmn:sequenceFlow id="ip_Flow_12" sourceRef="ip_remove" targetRef="ip_done" name="" />
    <bpmn:sequenceFlow id="ip_Flow_13" sourceRef="ip_confirmed" targetRef="ip_not_found" name="Нет (404)" />
    <bpmn:sequenceFlow id="ip_Flow_14" sourceRef="ip_manual" targetRef="ip_wait" name="" />
    <bpmn:sequenceFlow id="ip_Flow_15" sourceRef="ip_api_error" targetRef="ip_retry" name="" />
    <bpmn:sequenceFlow id="ip_Flow_16" sourceRef="ip_workflow_error" targetRef="ip_retry" name="" />
    <bpmn:sequenceFlow id="ip_Flow_17" sourceRef="ip_notify_error" targetRef="ip_retry" name="" />
    <bpmn:sequenceFlow id="ip_Flow_18" sourceRef="ip_retry" targetRef="ip_wait" name="" />
    <bpmn:sequenceFlow id="ip_Flow_19" sourceRef="ip_wait" targetRef="ip_timer" name="" />
    <bpmn:sequenceFlow id="ip_Flow_20" sourceRef="ip_wait" targetRef="ip_revision" name="" />
    <bpmn:sequenceFlow id="ip_Flow_21" sourceRef="ip_timer" targetRef="ip_ready" name="" />
    <bpmn:sequenceFlow id="ip_Flow_22" sourceRef="ip_revision" targetRef="ip_ready" name="" />
    <bpmn:sequenceFlow id="ip_Flow_23" sourceRef="ip_ready" targetRef="ip_status" name="Следующий проход" />
  </bpmn:process>
  <bpmn:collaboration id="Collaboration_st_inprocess_logic">
    <bpmn:participant id="ip_Pool_ip" name="open_st_request_inprocess: один проход Python и локальное ожидание" processRef="ip_Process_ip" />
  </bpmn:collaboration>
  <ns2:BPMNDiagram id="Diagram_st_inprocess_logic">
    <ns2:BPMNPlane id="Plane_st_inprocess_logic" bpmnElement="Collaboration_st_inprocess_logic">
      <ns2:BPMNShape id="ip_DI_Pool_ip" bpmnElement="ip_Pool_ip" isHorizontal="true">
        <ns3:Bounds x="0.0" y="0.0" width="1920.0" height="1060.0" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="ip_DI_Lane_worker" bpmnElement="ip_Lane_worker" isHorizontal="true">
        <ns3:Bounds x="30.0" y="0.0" width="1890.0" height="700.0" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="ip_DI_Lane_queue" bpmnElement="ip_Lane_queue" isHorizontal="true">
        <ns3:Bounds x="30.0" y="700.0" width="1890.0" height="360.0" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="ip_DI_start" bpmnElement="ip_start">
        <ns3:Bounds x="132.0" y="92.0" width="36" height="36" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="ip_DI_status" bpmnElement="ip_status">
        <ns3:Bounds x="325.0" y="85.0" width="50" height="50" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="ip_DI_contract" bpmnElement="ip_contract">
        <ns3:Bounds x="555.0" y="85.0" width="50" height="50" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="ip_DI_organize" bpmnElement="ip_organize">
        <ns3:Bounds x="755.0" y="75.0" width="150" height="70" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="ip_DI_advance" bpmnElement="ip_advance">
        <ns3:Bounds x="1005.0" y="75.0" width="150" height="70" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="ip_DI_special_end" bpmnElement="ip_special_end">
        <ns3:Bounds x="1302.0" y="92.0" width="36" height="36" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="ip_DI_stale" bpmnElement="ip_stale">
        <ns3:Bounds x="275.0" y="265.0" width="150" height="70" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="ip_DI_stale_end" bpmnElement="ip_stale_end">
        <ns3:Bounds x="562.0" y="282.0" width="36" height="36" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="ip_DI_auto" bpmnElement="ip_auto">
        <ns3:Bounds x="805.0" y="275.0" width="50" height="50" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="ip_DI_manual" bpmnElement="ip_manual">
        <ns3:Bounds x="1005.0" y="265.0" width="150" height="70" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="ip_DI_transition" bpmnElement="ip_transition">
        <ns3:Bounds x="755.0" y="445.0" width="150" height="70" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="ip_DI_confirmed" bpmnElement="ip_confirmed">
        <ns3:Bounds x="1055.0" y="455.0" width="50" height="50" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="ip_DI_remove" bpmnElement="ip_remove">
        <ns3:Bounds x="1245.0" y="445.0" width="150" height="70" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="ip_DI_done" bpmnElement="ip_done">
        <ns3:Bounds x="1542.0" y="462.0" width="36" height="36" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="ip_DI_not_found" bpmnElement="ip_not_found">
        <ns3:Bounds x="1062.0" y="612.0" width="36" height="36" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="ip_DI_api_error" bpmnElement="ip_api_error">
        <ns3:Bounds x="862.0" y="497.0" width="36" height="36" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="ip_DI_workflow_error" bpmnElement="ip_workflow_error">
        <ns3:Bounds x="1112.0" y="127.0" width="36" height="36" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="ip_DI_notify_error" bpmnElement="ip_notify_error">
        <ns3:Bounds x="862.0" y="127.0" width="36" height="36" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="ip_DI_retry" bpmnElement="ip_retry">
        <ns3:Bounds x="1485.0" y="265.0" width="150" height="70" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="ip_DI_wait" bpmnElement="ip_wait">
        <ns3:Bounds x="1055.0" y="805.0" width="50" height="50" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="ip_DI_timer" bpmnElement="ip_timer">
        <ns3:Bounds x="1302.0" y="752.0" width="36" height="36" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="ip_DI_revision" bpmnElement="ip_revision">
        <ns3:Bounds x="1302.0" y="942.0" width="36" height="36" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="ip_DI_ready" bpmnElement="ip_ready">
        <ns3:Bounds x="1485.0" y="795.0" width="150" height="70" />
      </ns2:BPMNShape>
      <ns2:BPMNEdge id="ip_DI_Flow_0" bpmnElement="ip_Flow_0">
        <ns4:waypoint x="168.0" y="110.0" />
        <ns4:waypoint x="325.0" y="110.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="ip_DI_Flow_1" bpmnElement="ip_Flow_1">
        <ns4:waypoint x="375.0" y="110.0" />
        <ns4:waypoint x="555.0" y="110.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="ip_DI_Flow_2" bpmnElement="ip_Flow_2">
        <ns4:waypoint x="350.0" y="135.0" />
        <ns4:waypoint x="350.0" y="265.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="ip_DI_Flow_3" bpmnElement="ip_Flow_3">
        <ns4:waypoint x="425.0" y="300.0" />
        <ns4:waypoint x="562.0" y="300.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="ip_DI_Flow_4" bpmnElement="ip_Flow_4">
        <ns4:waypoint x="605.0" y="110.0" />
        <ns4:waypoint x="755.0" y="110.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="ip_DI_Flow_5" bpmnElement="ip_Flow_5">
        <ns4:waypoint x="905.0" y="110.0" />
        <ns4:waypoint x="1005.0" y="110.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="ip_DI_Flow_6" bpmnElement="ip_Flow_6">
        <ns4:waypoint x="1155.0" y="110.0" />
        <ns4:waypoint x="1302.0" y="110.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="ip_DI_Flow_7" bpmnElement="ip_Flow_7">
        <ns4:waypoint x="605.0" y="110.0" />
        <ns4:waypoint x="700.0" y="110.0" />
        <ns4:waypoint x="700.0" y="245.0" />
        <ns4:waypoint x="830.0" y="245.0" />
        <ns4:waypoint x="830.0" y="275.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="ip_DI_Flow_8" bpmnElement="ip_Flow_8">
        <ns4:waypoint x="855.0" y="300.0" />
        <ns4:waypoint x="1005.0" y="300.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="ip_DI_Flow_9" bpmnElement="ip_Flow_9">
        <ns4:waypoint x="830.0" y="325.0" />
        <ns4:waypoint x="830.0" y="445.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="ip_DI_Flow_10" bpmnElement="ip_Flow_10">
        <ns4:waypoint x="905.0" y="480.0" />
        <ns4:waypoint x="1055.0" y="480.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="ip_DI_Flow_11" bpmnElement="ip_Flow_11">
        <ns4:waypoint x="1105.0" y="480.0" />
        <ns4:waypoint x="1245.0" y="480.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="ip_DI_Flow_12" bpmnElement="ip_Flow_12">
        <ns4:waypoint x="1395.0" y="480.0" />
        <ns4:waypoint x="1542.0" y="480.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="ip_DI_Flow_13" bpmnElement="ip_Flow_13">
        <ns4:waypoint x="1080.0" y="505.0" />
        <ns4:waypoint x="1080.0" y="612.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="ip_DI_Flow_14" bpmnElement="ip_Flow_14">
        <ns4:waypoint x="1155.0" y="300.0" />
        <ns4:waypoint x="1190.0" y="300.0" />
        <ns4:waypoint x="1190.0" y="705.0" />
        <ns4:waypoint x="1080.0" y="705.0" />
        <ns4:waypoint x="1080.0" y="805.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="ip_DI_Flow_15" bpmnElement="ip_Flow_15">
        <ns4:waypoint x="898.0" y="515.0" />
        <ns4:waypoint x="940.0" y="515.0" />
        <ns4:waypoint x="940.0" y="570.0" />
        <ns4:waypoint x="1740.0" y="570.0" />
        <ns4:waypoint x="1740.0" y="235.0" />
        <ns4:waypoint x="1560.0" y="235.0" />
        <ns4:waypoint x="1560.0" y="265.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="ip_DI_Flow_16" bpmnElement="ip_Flow_16">
        <ns4:waypoint x="1148.0" y="145.0" />
        <ns4:waypoint x="1190.0" y="145.0" />
        <ns4:waypoint x="1470.0" y="145.0" />
        <ns4:waypoint x="1470.0" y="235.0" />
        <ns4:waypoint x="1560.0" y="235.0" />
        <ns4:waypoint x="1560.0" y="265.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="ip_DI_Flow_17" bpmnElement="ip_Flow_17">
        <ns4:waypoint x="898.0" y="145.0" />
        <ns4:waypoint x="940.0" y="145.0" />
        <ns4:waypoint x="940.0" y="210.0" />
        <ns4:waypoint x="1560.0" y="210.0" />
        <ns4:waypoint x="1560.0" y="265.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="ip_DI_Flow_18" bpmnElement="ip_Flow_18">
        <ns4:waypoint x="1635.0" y="300.0" />
        <ns4:waypoint x="1710.0" y="300.0" />
        <ns4:waypoint x="1800.0" y="300.0" />
        <ns4:waypoint x="1800.0" y="700.0" />
        <ns4:waypoint x="1080.0" y="700.0" />
        <ns4:waypoint x="1080.0" y="805.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="ip_DI_Flow_19" bpmnElement="ip_Flow_19">
        <ns4:waypoint x="1105.0" y="830.0" />
        <ns4:waypoint x="1203.5" y="830.0" />
        <ns4:waypoint x="1203.5" y="770.0" />
        <ns4:waypoint x="1302.0" y="770.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="ip_DI_Flow_20" bpmnElement="ip_Flow_20">
        <ns4:waypoint x="1105.0" y="830.0" />
        <ns4:waypoint x="1203.5" y="830.0" />
        <ns4:waypoint x="1203.5" y="960.0" />
        <ns4:waypoint x="1302.0" y="960.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="ip_DI_Flow_21" bpmnElement="ip_Flow_21">
        <ns4:waypoint x="1338.0" y="770.0" />
        <ns4:waypoint x="1411.5" y="770.0" />
        <ns4:waypoint x="1411.5" y="830.0" />
        <ns4:waypoint x="1485.0" y="830.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="ip_DI_Flow_22" bpmnElement="ip_Flow_22">
        <ns4:waypoint x="1338.0" y="960.0" />
        <ns4:waypoint x="1411.5" y="960.0" />
        <ns4:waypoint x="1411.5" y="830.0" />
        <ns4:waypoint x="1485.0" y="830.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="ip_DI_Flow_23" bpmnElement="ip_Flow_23">
        <ns4:waypoint x="1635.0" y="830.0" />
        <ns4:waypoint x="1770.0" y="830.0" />
        <ns4:waypoint x="1880.0" y="830.0" />
        <ns4:waypoint x="1880.0" y="25.0" />
        <ns4:waypoint x="350.0" y="25.0" />
        <ns4:waypoint x="350.0" y="85.0" />
        <ns2:BPMNLabel>
          <ns3:Bounds x="1460.0" y="5.0" width="180" height="26" />
        </ns2:BPMNLabel>
      </ns2:BPMNEdge>
    </ns2:BPMNPlane>
  </ns2:BPMNDiagram>
</bpmn:definitions>
  • Снимок уже не в IN_PROCESS — запросить удаление Ticket из локальной очереди и удаление комнаты.
  • Профильный контракт — явно вызвать подготовку организации, затем advance_verification_workflow и завершить этот проход.
  • Обычное обращение, autoaccept отключён — записать локальную причину support_execution, назначить повтор по ST_REQUEST_IN_PROCESS_RECHECK_SECONDS и освободить worker. Строка st_request_in_process передаётся как причина для журнала defer; она не подменяет сохранённую локальную support_execution и не является комментарием Ticket.
  • Обычное обращение, autoaccept включён — запросить DONE через scoped Ticket API. При подтверждённом переходе удалить локальный Ticket и комнату. В этой ветви нет явного send_to_handler: новый владелец получает backend wakeup; periodic reconciliation восстанавливает очередь при потере сообщения.

404 при scoped смене статуса означает, что текущий контекст больше не может продолжать работу с Ticket: runtime запрашивает очистку. Остальные ошибки перехода, отправки либо неожиданные исключения передаются общему восстановлению processing_error и DEFERRED_TICKET_RECHECK_SECONDS. Уже committed статус или доменный результат от этого не откатывается.

Профильный workflow: backend и ответ обработчику (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_st_inprocess_verification" targetNamespace="urn:sharix:knowledge:handlers">
  <bpmn:process id="backend_Process_backend" name="dbsynce: scoped verification.workflow API (action=advance)" isExecutable="false">
    <bpmn:documentation>{"notes": ["Опубликованный Git built-in; не подтверждение выбранной версии на любом сервере.", "Процессы не исполняются просмотрщиком. End event завершает показанную операцию, не всю заявку.", "deferred_until — символ локального срока, не имя параметра конфигурации.", "Это раскрытие примитива advance и backend-контракта. Ошибки organize не подавляют advance.", "60/300 секунд — текущие константы Python, а не обещание точного времени запуска."], "sources": [{"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "generated_handler_blocks/open_st_request_inprocess.json", "repository": "sharix-open-handlers-examples", "sha256": "aedf573066b509bc1d7177d08530ae2ed1a5e896c8745e02edaed27e3d561313"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_st_request_inprocess.py", "repository": "sharix-open-handlers-examples", "sha256": "7dc2424c827ba4dc04971a8691d0e624566c6b4cb409cffec2e552dcad2aca4d"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_st_request_done.py", "repository": "sharix-open-handlers-examples", "sha256": "b6ae4733904d9ba8e691f43235d4836d201ac019ff99982d532816bfdc89bf31"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_st_request_wontfix.py", "repository": "sharix-open-handlers-examples", "sha256": "ece9fb7e09ee0e401e91d5d274d6b151b51d1364ba698b835c929e6416f90f03"}, {"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/requesters.py", "repository": "sharix-open-handlers-backend", "sha256": "965a348cea477722bbaf4c8c6b06023eb238b71664a332f7ea8c90bfe72ea808"}, {"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": "services/verification_results.py", "repository": "sharix-open-tickets", "sha256": "682c5f6869373e649d6d62f44e63e8fb3bb34cf6bfc85d0187b26b2c96984e91"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "services/st_request_contracts.py", "repository": "sharix-open-tickets", "sha256": "9c1553437dbff63c608504ee000fa67a9be6e9887b1df0599552aa4d9141276c"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "views/ticket_detail.py", "repository": "sharix-open-tickets", "sha256": "05d344b0fba14cf895400694d4a18f486c800fef08dd1acb43ea46909b9e7e59"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "utils.py", "repository": "sharix-open-tickets", "sha256": "a5680205c6522e1d9a74d9d267fe9ee96faf6f06436b00877fc0a93d80234bf5"}, {"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": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "api/views/handler_workflow.py", "repository": "sharix-open-tickets", "sha256": "f97c4b467a9a30749f5c4b86b39a833c430e57aaa1f030f70030d9b5c609d368"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "apiviews/handler_workflow.py", "repository": "sharix-open-backend", "sha256": "0f699a4e16760cbbdd09d894093c685ba69073fedf0522852cb1fdc9811636e3"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/verification_workflow.py", "repository": "sharix-open-backend", "sha256": "9fe62f8344d7fd78e5af0ce025c82ba4f7d21759e71f518df1186a1d6a4a0644"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/verification_algorithms.py", "repository": "sharix-open-backend", "sha256": "9e55e4119051847bb3596c3563b9b151ee92b660e89c39c533b16ed6b4a2099e"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/verification_responsibility.py", "repository": "sharix-open-backend", "sha256": "7919b83c89cb4214545ea2c2db0cffac09af892b190ce3af72348d688abb9cf4"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/requirement_checks.py", "repository": "sharix-open-backend", "sha256": "5a73a6e71307e734f0c0e480fd14a825a7a22242811e2523b7f25157224cf34c"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/integration_ports.py", "repository": "sharix-open-backend", "sha256": "d079ec56e6709b29d7755e47d2a88d423235fe8eb1bf7a92851ae25d74bf1066"}]}</bpmn:documentation>
    <bpmn:laneSet id="backend_Lanes_backend">
      <bpmn:lane id="backend_Lane_worker" name="Backend: durable состояние проверки и политика">
        <bpmn:flowNodeRef>backend_request</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>backend_acl</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>backend_doc</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>backend_manual</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>backend_check</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>backend_terminal</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>backend_pending</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>backend_algorithm</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>backend_outcome</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>backend_completed</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>backend_other</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>backend_waiting</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>backend_missing</bpmn:flowNodeRef>
      </bpmn:lane>
    </bpmn:laneSet>
    <bpmn:startEvent id="backend_request" name="Вызов advance">
      <bpmn:outgoing>backend_Flow_0</bpmn:outgoing>
      <bpmn:messageEventDefinition />
    </bpmn:startEvent>
    <bpmn:serviceTask id="backend_acl" name="Проверить API identity, capability и Ticket scope">
      <bpmn:incoming>backend_Flow_0</bpmn:incoming>
      <bpmn:outgoing>backend_Flow_1</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:exclusiveGateway id="backend_doc" name="Проверка документа?">
      <bpmn:incoming>backend_Flow_1</bpmn:incoming>
      <bpmn:outgoing>backend_Flow_2</bpmn:outgoing>
      <bpmn:outgoing>backend_Flow_3</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:serviceTask id="backend_manual" name="Ответ manual_required + уведомления">
      <bpmn:documentation>DocumentVersion здесь не создаётся.</bpmn:documentation>
      <bpmn:incoming>backend_Flow_2</bpmn:incoming>
    </bpmn:serviceTask>
    <bpmn:serviceTask id="backend_check" name="Загрузить RequirementCheck">
      <bpmn:incoming>backend_Flow_3</bpmn:incoming>
      <bpmn:outgoing>backend_Flow_4</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:exclusiveGateway id="backend_terminal" name="PASSED / FAILED?">
      <bpmn:incoming>backend_Flow_4</bpmn:incoming>
      <bpmn:outgoing>backend_Flow_5</bpmn:outgoing>
      <bpmn:outgoing>backend_Flow_6</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:exclusiveGateway id="backend_pending" name="PENDING?">
      <bpmn:incoming>backend_Flow_6</bpmn:incoming>
      <bpmn:outgoing>backend_Flow_7</bpmn:outgoing>
      <bpmn:outgoing>backend_Flow_8</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:serviceTask id="backend_algorithm" name="Алгоритм, ответственный и политика результата">
      <bpmn:documentation>Ручной режим/нет алгоритма/ответственного/исполнителя → manual_required. Нетерминальный результат → pending. Доменные правила могут отклонить результат.</bpmn:documentation>
      <bpmn:incoming>backend_Flow_7</bpmn:incoming>
      <bpmn:outgoing>backend_Flow_9</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:exclusiveGateway id="backend_outcome" name="После алгоритма результат терминальный?">
      <bpmn:incoming>backend_Flow_9</bpmn:incoming>
      <bpmn:outgoing>backend_Flow_10</bpmn:outgoing>
      <bpmn:outgoing>backend_Flow_11</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:serviceTask id="backend_completed" name="Ответ completed: passed→DONE, failed→WONTFIX">
      <bpmn:incoming>backend_Flow_5</bpmn:incoming>
      <bpmn:incoming>backend_Flow_10</bpmn:incoming>
    </bpmn:serviceTask>
    <bpmn:serviceTask id="backend_other" name="Ответ с текущим иным состоянием">
      <bpmn:documentation>Не-PENDING и не PASSED/FAILED не превращается автоматически в отрицательный результат.</bpmn:documentation>
      <bpmn:incoming>backend_Flow_8</bpmn:incoming>
    </bpmn:serviceTask>
    <bpmn:serviceTask id="backend_waiting" name="Ответ pending или manual_required">
      <bpmn:incoming>backend_Flow_11</bpmn:incoming>
    </bpmn:serviceTask>
    <bpmn:boundaryEvent id="backend_missing" name="Нет check / ошибка API" attachedToRef="backend_check" cancelActivity="true">
      <bpmn:errorEventDefinition />
    </bpmn:boundaryEvent>
    <bpmn:sequenceFlow id="backend_Flow_0" sourceRef="backend_request" targetRef="backend_acl" name="" />
    <bpmn:sequenceFlow id="backend_Flow_1" sourceRef="backend_acl" targetRef="backend_doc" name="" />
    <bpmn:sequenceFlow id="backend_Flow_2" sourceRef="backend_doc" targetRef="backend_manual" name="Да" />
    <bpmn:sequenceFlow id="backend_Flow_3" sourceRef="backend_doc" targetRef="backend_check" name="Нет" />
    <bpmn:sequenceFlow id="backend_Flow_4" sourceRef="backend_check" targetRef="backend_terminal" name="" />
    <bpmn:sequenceFlow id="backend_Flow_5" sourceRef="backend_terminal" targetRef="backend_completed" name="Да" />
    <bpmn:sequenceFlow id="backend_Flow_6" sourceRef="backend_terminal" targetRef="backend_pending" name="Нет" />
    <bpmn:sequenceFlow id="backend_Flow_7" sourceRef="backend_pending" targetRef="backend_algorithm" name="Да" />
    <bpmn:sequenceFlow id="backend_Flow_8" sourceRef="backend_pending" targetRef="backend_other" name="Нет" />
    <bpmn:sequenceFlow id="backend_Flow_9" sourceRef="backend_algorithm" targetRef="backend_outcome" name="" />
    <bpmn:sequenceFlow id="backend_Flow_10" sourceRef="backend_outcome" targetRef="backend_completed" name="Да" />
    <bpmn:sequenceFlow id="backend_Flow_11" sourceRef="backend_outcome" targetRef="backend_waiting" name="Нет" />
  </bpmn:process>
  <bpmn:process id="runtime_Process_runtime" name="HandlerContext: обработка ответа advance" isExecutable="false">
    <bpmn:documentation>{"notes": ["Опубликованный Git built-in; не подтверждение выбранной версии на любом сервере.", "Процессы не исполняются просмотрщиком. End event завершает показанную операцию, не всю заявку.", "deferred_until — символ локального срока, не имя параметра конфигурации.", "Это раскрытие примитива advance и backend-контракта. Ошибки organize не подавляют advance.", "60/300 секунд — текущие константы Python, а не обещание точного времени запуска."], "sources": [{"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "generated_handler_blocks/open_st_request_inprocess.json", "repository": "sharix-open-handlers-examples", "sha256": "aedf573066b509bc1d7177d08530ae2ed1a5e896c8745e02edaed27e3d561313"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_st_request_inprocess.py", "repository": "sharix-open-handlers-examples", "sha256": "7dc2424c827ba4dc04971a8691d0e624566c6b4cb409cffec2e552dcad2aca4d"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_st_request_done.py", "repository": "sharix-open-handlers-examples", "sha256": "b6ae4733904d9ba8e691f43235d4836d201ac019ff99982d532816bfdc89bf31"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_st_request_wontfix.py", "repository": "sharix-open-handlers-examples", "sha256": "ece9fb7e09ee0e401e91d5d274d6b151b51d1364ba698b835c929e6416f90f03"}, {"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/requesters.py", "repository": "sharix-open-handlers-backend", "sha256": "965a348cea477722bbaf4c8c6b06023eb238b71664a332f7ea8c90bfe72ea808"}, {"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": "services/verification_results.py", "repository": "sharix-open-tickets", "sha256": "682c5f6869373e649d6d62f44e63e8fb3bb34cf6bfc85d0187b26b2c96984e91"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "services/st_request_contracts.py", "repository": "sharix-open-tickets", "sha256": "9c1553437dbff63c608504ee000fa67a9be6e9887b1df0599552aa4d9141276c"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "views/ticket_detail.py", "repository": "sharix-open-tickets", "sha256": "05d344b0fba14cf895400694d4a18f486c800fef08dd1acb43ea46909b9e7e59"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "utils.py", "repository": "sharix-open-tickets", "sha256": "a5680205c6522e1d9a74d9d267fe9ee96faf6f06436b00877fc0a93d80234bf5"}, {"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": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "api/views/handler_workflow.py", "repository": "sharix-open-tickets", "sha256": "f97c4b467a9a30749f5c4b86b39a833c430e57aaa1f030f70030d9b5c609d368"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "apiviews/handler_workflow.py", "repository": "sharix-open-backend", "sha256": "0f699a4e16760cbbdd09d894093c685ba69073fedf0522852cb1fdc9811636e3"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/verification_workflow.py", "repository": "sharix-open-backend", "sha256": "9fe62f8344d7fd78e5af0ce025c82ba4f7d21759e71f518df1186a1d6a4a0644"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/verification_algorithms.py", "repository": "sharix-open-backend", "sha256": "9e55e4119051847bb3596c3563b9b151ee92b660e89c39c533b16ed6b4a2099e"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/verification_responsibility.py", "repository": "sharix-open-backend", "sha256": "7919b83c89cb4214545ea2c2db0cffac09af892b190ce3af72348d688abb9cf4"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/requirement_checks.py", "repository": "sharix-open-backend", "sha256": "5a73a6e71307e734f0c0e480fd14a825a7a22242811e2523b7f25157224cf34c"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/integration_ports.py", "repository": "sharix-open-backend", "sha256": "d079ec56e6709b29d7755e47d2a88d423235fe8eb1bf7a92851ae25d74bf1066"}]}</bpmn:documentation>
    <bpmn:laneSet id="runtime_Lanes_runtime">
      <bpmn:lane id="runtime_Lane_worker" name="Python runtime">
        <bpmn:flowNodeRef>runtime_receive</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>runtime_notify</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>runtime_complete</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>runtime_status</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>runtime_ok</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>runtime_handoff</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>runtime_remove</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>runtime_end</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>runtime_defer</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>runtime_wait_end</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>runtime_false</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>runtime_api_error</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>runtime_retry</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>runtime_error_end</bpmn:flowNodeRef>
      </bpmn:lane>
    </bpmn:laneSet>
    <bpmn:startEvent id="runtime_receive" name="Успешный ответ API">
      <bpmn:outgoing>runtime_Flow_0</bpmn:outgoing>
      <bpmn:messageEventDefinition />
    </bpmn:startEvent>
    <bpmn:sendTask id="runtime_notify" name="Отправить уведомления и подтвердить ключи">
      <bpmn:documentation>Подробно в тексте: ack не подтверждает прочтение человеком.</bpmn:documentation>
      <bpmn:incoming>runtime_Flow_0</bpmn:incoming>
      <bpmn:outgoing>runtime_Flow_1</bpmn:outgoing>
    </bpmn:sendTask>
    <bpmn:exclusiveGateway id="runtime_complete" name="completed и есть target_status?">
      <bpmn:incoming>runtime_Flow_1</bpmn:incoming>
      <bpmn:outgoing>runtime_Flow_2</bpmn:outgoing>
      <bpmn:outgoing>runtime_Flow_3</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:serviceTask id="runtime_status" name="Scoped переход в target_status">
      <bpmn:incoming>runtime_Flow_2</bpmn:incoming>
      <bpmn:outgoing>runtime_Flow_5</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:exclusiveGateway id="runtime_ok" name="Переход подтверждён?">
      <bpmn:incoming>runtime_Flow_5</bpmn:incoming>
      <bpmn:outgoing>runtime_Flow_6</bpmn:outgoing>
      <bpmn:outgoing>runtime_Flow_7</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:sendTask id="runtime_handoff" name="passed→DONE handler, иначе WONTFIX">
      <bpmn:incoming>runtime_Flow_6</bpmn:incoming>
      <bpmn:outgoing>runtime_Flow_8</bpmn:outgoing>
    </bpmn:sendTask>
    <bpmn:serviceTask id="runtime_remove" name="Убрать Ticket, комнату сохранить">
      <bpmn:incoming>runtime_Flow_8</bpmn:incoming>
      <bpmn:outgoing>runtime_Flow_9</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:endEvent id="runtime_end" name="Передача завершена">
      <bpmn:incoming>runtime_Flow_9</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:serviceTask id="runtime_defer" name="defer: pending 60 с, иначе 300 с">
      <bpmn:documentation>Причина журнала verification_&lt;state&gt;, пустое состояние → verification_waiting. completed без target_status тоже ждёт 300 с.</bpmn:documentation>
      <bpmn:incoming>runtime_Flow_3</bpmn:incoming>
      <bpmn:outgoing>runtime_Flow_4</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:endEvent id="runtime_wait_end" name="Ожидание: worker освобождён">
      <bpmn:incoming>runtime_Flow_4</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:endEvent id="runtime_false" name="404: локальная очистка запрошена">
      <bpmn:incoming>runtime_Flow_7</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:startEvent id="runtime_api_error" name="Ошибка запроса/JSON ответа">
      <bpmn:outgoing>runtime_Flow_10</bpmn:outgoing>
      <bpmn:messageEventDefinition />
    </bpmn:startEvent>
    <bpmn:serviceTask id="runtime_retry" name="defer 60 с: verification_backend_error">
      <bpmn:incoming>runtime_Flow_10</bpmn:incoming>
      <bpmn:outgoing>runtime_Flow_11</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:endEvent id="runtime_error_end" name="Следующий проход позже">
      <bpmn:incoming>runtime_Flow_11</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:sequenceFlow id="runtime_Flow_0" sourceRef="runtime_receive" targetRef="runtime_notify" name="" />
    <bpmn:sequenceFlow id="runtime_Flow_1" sourceRef="runtime_notify" targetRef="runtime_complete" name="" />
    <bpmn:sequenceFlow id="runtime_Flow_2" sourceRef="runtime_complete" targetRef="runtime_status" name="Да" />
    <bpmn:sequenceFlow id="runtime_Flow_3" sourceRef="runtime_complete" targetRef="runtime_defer" name="Нет" />
    <bpmn:sequenceFlow id="runtime_Flow_4" sourceRef="runtime_defer" targetRef="runtime_wait_end" name="" />
    <bpmn:sequenceFlow id="runtime_Flow_5" sourceRef="runtime_status" targetRef="runtime_ok" name="" />
    <bpmn:sequenceFlow id="runtime_Flow_6" sourceRef="runtime_ok" targetRef="runtime_handoff" name="Да" />
    <bpmn:sequenceFlow id="runtime_Flow_7" sourceRef="runtime_ok" targetRef="runtime_false" name="Нет (404)" />
    <bpmn:sequenceFlow id="runtime_Flow_8" sourceRef="runtime_handoff" targetRef="runtime_remove" name="" />
    <bpmn:sequenceFlow id="runtime_Flow_9" sourceRef="runtime_remove" targetRef="runtime_end" name="" />
    <bpmn:sequenceFlow id="runtime_Flow_10" sourceRef="runtime_api_error" targetRef="runtime_retry" name="" />
    <bpmn:sequenceFlow id="runtime_Flow_11" sourceRef="runtime_retry" targetRef="runtime_error_end" name="" />
  </bpmn:process>
  <bpmn:collaboration id="Collaboration_st_inprocess_verification">
    <bpmn:participant id="backend_Pool_backend" name="dbsynce: scoped verification.workflow API (action=advance)" processRef="backend_Process_backend" />
    <bpmn:participant id="runtime_Pool_runtime" name="HandlerContext: обработка ответа advance" processRef="runtime_Process_runtime" />
    <bpmn:messageFlow id="Message_st_inprocess_verification_0" sourceRef="backend_manual" targetRef="runtime_receive" name="manual_required" />
    <bpmn:messageFlow id="Message_st_inprocess_verification_1" sourceRef="backend_completed" targetRef="runtime_receive" name="completed, outcome, target_status" />
    <bpmn:messageFlow id="Message_st_inprocess_verification_2" sourceRef="backend_waiting" targetRef="runtime_receive" name="pending / manual_required" />
    <bpmn:messageFlow id="Message_st_inprocess_verification_3" sourceRef="backend_other" targetRef="runtime_receive" name="Иное состояние" />
    <bpmn:messageFlow id="Message_st_inprocess_verification_4" sourceRef="backend_missing" targetRef="runtime_api_error" name="Ошибка ответа API" />
  </bpmn:collaboration>
  <bpmndi:BPMNDiagram id="Diagram_st_inprocess_verification">
    <bpmndi:BPMNPlane id="Plane_st_inprocess_verification" bpmnElement="Collaboration_st_inprocess_verification">
      <bpmndi:BPMNShape id="backend_DI_Pool_backend" bpmnElement="backend_Pool_backend" isHorizontal="true">
        <dc:Bounds x="0.0" y="0.0" width="1880" height="780" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_Lane_worker" bpmnElement="backend_Lane_worker" isHorizontal="true">
        <dc:Bounds x="30.0" y="0.0" width="1850" height="780" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_request" bpmnElement="backend_request">
        <dc:Bounds x="132.0" y="92.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_acl" bpmnElement="backend_acl">
        <dc:Bounds x="315.0" y="75.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_doc" bpmnElement="backend_doc">
        <dc:Bounds x="625.0" y="85.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_manual" bpmnElement="backend_manual">
        <dc:Bounds x="855.0" y="75.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_check" bpmnElement="backend_check">
        <dc:Bounds x="575.0" y="265.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_terminal" bpmnElement="backend_terminal">
        <dc:Bounds x="905.0" y="275.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_pending" bpmnElement="backend_pending">
        <dc:Bounds x="905.0" y="465.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_algorithm" bpmnElement="backend_algorithm">
        <dc:Bounds x="1115.0" y="455.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_outcome" bpmnElement="backend_outcome">
        <dc:Bounds x="1435.0" y="465.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_completed" bpmnElement="backend_completed">
        <dc:Bounds x="1385.0" y="265.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_other" bpmnElement="backend_other">
        <dc:Bounds x="855.0" y="645.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_waiting" bpmnElement="backend_waiting">
        <dc:Bounds x="1645.0" y="645.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_missing" bpmnElement="backend_missing">
        <dc:Bounds x="682.0" y="317.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="backend_DI_Flow_0" bpmnElement="backend_Flow_0">
        <di:waypoint x="168.0" y="110.0" />
        <di:waypoint x="315.0" y="110.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="backend_DI_Flow_1" bpmnElement="backend_Flow_1">
        <di:waypoint x="465.0" y="110.0" />
        <di:waypoint x="625.0" y="110.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="backend_DI_Flow_2" bpmnElement="backend_Flow_2">
        <di:waypoint x="675.0" y="110.0" />
        <di:waypoint x="855.0" y="110.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="backend_DI_Flow_3" bpmnElement="backend_Flow_3">
        <di:waypoint x="650.0" y="135.0" />
        <di:waypoint x="650.0" y="265.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="backend_DI_Flow_4" bpmnElement="backend_Flow_4">
        <di:waypoint x="725.0" y="300.0" />
        <di:waypoint x="905.0" y="300.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="backend_DI_Flow_5" bpmnElement="backend_Flow_5">
        <di:waypoint x="955.0" y="300.0" />
        <di:waypoint x="1385.0" y="300.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="backend_DI_Flow_6" bpmnElement="backend_Flow_6">
        <di:waypoint x="930.0" y="325.0" />
        <di:waypoint x="930.0" y="465.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="backend_DI_Flow_7" bpmnElement="backend_Flow_7">
        <di:waypoint x="955.0" y="490.0" />
        <di:waypoint x="1115.0" y="490.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="backend_DI_Flow_8" bpmnElement="backend_Flow_8">
        <di:waypoint x="930.0" y="515.0" />
        <di:waypoint x="930.0" y="645.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="backend_DI_Flow_9" bpmnElement="backend_Flow_9">
        <di:waypoint x="1265.0" y="490.0" />
        <di:waypoint x="1435.0" y="490.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="backend_DI_Flow_10" bpmnElement="backend_Flow_10">
        <di:waypoint x="1485.0" y="490.0" />
        <di:waypoint x="1435.0" y="490.0" />
        <di:waypoint x="1435.0" y="300.0" />
        <di:waypoint x="1385.0" y="300.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="backend_DI_Flow_11" bpmnElement="backend_Flow_11">
        <di:waypoint x="1485.0" y="490.0" />
        <di:waypoint x="1570.0" y="490.0" />
        <di:waypoint x="1720.0" y="490.0" />
        <di:waypoint x="1720.0" y="645.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="runtime_DI_Pool_runtime" bpmnElement="runtime_Pool_runtime" isHorizontal="true">
        <dc:Bounds x="0.0" y="900.0" width="2080" height="600" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="runtime_DI_Lane_worker" bpmnElement="runtime_Lane_worker" isHorizontal="true">
        <dc:Bounds x="30.0" y="900.0" width="2050" height="600" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="runtime_DI_receive" bpmnElement="runtime_receive">
        <dc:Bounds x="132.0" y="992.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="runtime_DI_notify" bpmnElement="runtime_notify">
        <dc:Bounds x="325.0" y="975.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="runtime_DI_complete" bpmnElement="runtime_complete">
        <dc:Bounds x="645.0" y="985.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="runtime_DI_status" bpmnElement="runtime_status">
        <dc:Bounds x="855.0" y="975.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="runtime_DI_ok" bpmnElement="runtime_ok">
        <dc:Bounds x="1165.0" y="985.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="runtime_DI_handoff" bpmnElement="runtime_handoff">
        <dc:Bounds x="1375.0" y="975.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="runtime_DI_remove" bpmnElement="runtime_remove">
        <dc:Bounds x="1635.0" y="975.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="runtime_DI_end" bpmnElement="runtime_end">
        <dc:Bounds x="1902.0" y="992.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="runtime_DI_defer" bpmnElement="runtime_defer">
        <dc:Bounds x="595.0" y="1175.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="runtime_DI_wait_end" bpmnElement="runtime_wait_end">
        <dc:Bounds x="912.0" y="1192.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="runtime_DI_false" bpmnElement="runtime_false">
        <dc:Bounds x="1172.0" y="1192.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="runtime_DI_api_error" bpmnElement="runtime_api_error">
        <dc:Bounds x="132.0" y="1382.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="runtime_DI_retry" bpmnElement="runtime_retry">
        <dc:Bounds x="325.0" y="1365.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="runtime_DI_error_end" bpmnElement="runtime_error_end">
        <dc:Bounds x="652.0" y="1382.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="runtime_DI_Flow_0" bpmnElement="runtime_Flow_0">
        <di:waypoint x="168.0" y="1010.0" />
        <di:waypoint x="325.0" y="1010.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="runtime_DI_Flow_1" bpmnElement="runtime_Flow_1">
        <di:waypoint x="475.0" y="1010.0" />
        <di:waypoint x="645.0" y="1010.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="runtime_DI_Flow_2" bpmnElement="runtime_Flow_2">
        <di:waypoint x="695.0" y="1010.0" />
        <di:waypoint x="855.0" y="1010.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="runtime_DI_Flow_3" bpmnElement="runtime_Flow_3">
        <di:waypoint x="670.0" y="1035.0" />
        <di:waypoint x="670.0" y="1175.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="runtime_DI_Flow_4" bpmnElement="runtime_Flow_4">
        <di:waypoint x="745.0" y="1210.0" />
        <di:waypoint x="912.0" y="1210.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="runtime_DI_Flow_5" bpmnElement="runtime_Flow_5">
        <di:waypoint x="1005.0" y="1010.0" />
        <di:waypoint x="1165.0" y="1010.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="runtime_DI_Flow_6" bpmnElement="runtime_Flow_6">
        <di:waypoint x="1215.0" y="1010.0" />
        <di:waypoint x="1375.0" y="1010.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="runtime_DI_Flow_7" bpmnElement="runtime_Flow_7">
        <di:waypoint x="1190.0" y="1035.0" />
        <di:waypoint x="1190.0" y="1192.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="runtime_DI_Flow_8" bpmnElement="runtime_Flow_8">
        <di:waypoint x="1525.0" y="1010.0" />
        <di:waypoint x="1635.0" y="1010.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="runtime_DI_Flow_9" bpmnElement="runtime_Flow_9">
        <di:waypoint x="1785.0" y="1010.0" />
        <di:waypoint x="1902.0" y="1010.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="runtime_DI_Flow_10" bpmnElement="runtime_Flow_10">
        <di:waypoint x="168.0" y="1400.0" />
        <di:waypoint x="325.0" y="1400.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="runtime_DI_Flow_11" bpmnElement="runtime_Flow_11">
        <di:waypoint x="475.0" y="1400.0" />
        <di:waypoint x="652.0" y="1400.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="DI_Message_st_inprocess_verification_0" bpmnElement="Message_st_inprocess_verification_0">
        <di:waypoint x="930" y="145" />
        <di:waypoint x="930" y="220" />
        <di:waypoint x="40" y="220" />
        <di:waypoint x="40" y="975" />
        <di:waypoint x="132" y="975" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="45" y="815" width="260" height="42" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="DI_Message_st_inprocess_verification_1" bpmnElement="Message_st_inprocess_verification_1">
        <di:waypoint x="1460" y="335" />
        <di:waypoint x="1460" y="400" />
        <di:waypoint x="30" y="400" />
        <di:waypoint x="30" y="1010" />
        <di:waypoint x="132" y="1010" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="35" y="845" width="260" height="42" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="DI_Message_st_inprocess_verification_2" bpmnElement="Message_st_inprocess_verification_2">
        <di:waypoint x="1720" y="715" />
        <di:waypoint x="1720" y="820" />
        <di:waypoint x="150" y="820" />
        <di:waypoint x="150" y="992" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="1100" y="790" width="260" height="42" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="DI_Message_st_inprocess_verification_3" bpmnElement="Message_st_inprocess_verification_3">
        <di:waypoint x="930" y="715" />
        <di:waypoint x="930" y="780" />
        <di:waypoint x="75" y="780" />
        <di:waypoint x="75" y="1010" />
        <di:waypoint x="132" y="1010" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="420" y="750" width="260" height="42" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="DI_Message_st_inprocess_verification_4" bpmnElement="Message_st_inprocess_verification_4">
        <di:waypoint x="700" y="353" />
        <di:waypoint x="700" y="380" />
        <di:waypoint x="10" y="380" />
        <di:waypoint x="10" y="1400" />
        <di:waypoint x="132" y="1400" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="15" y="1260" width="260" height="42" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn:definitions>

Схема раскрывает advance; подготовка организации предшествует ему и описана ниже. Внешний вызов проходит через dbsynce/api/handler/ticket/{ticket_id}/verification/. Backend требует handler identity, capability verification.workflow и доступ к конкретному Ticket в scope обработчика; состояние хранится на стороне backend. Доверенный ключ не означает произвольный доступ ко всем Ticket.

Проверка документа

Для document-verification-v1 вызов advance возвращает manual_required и первоначальные уведомления. Он не создаёт DocumentVersion и не подтверждает документ автоматически. Решение вносит пользователь с соответствующим доступом. Применение результата, проверка ожидаемой редакции документа и дальнейшее закрытие принадлежат следующему DONE/WONTFIX workflow.

Проверка требования

Для requirement-check-v1 backend загружает конкретную попытку RequirementCheck по стабильному public id из Ticket. Отсутствующая попытка — ошибка, а не положительный результат.

  • Уже PASSED или FAILED — вернуть completed, outcome и целевой статус соответственно DONE или WONTFIX.
  • PENDING — вызвать зарегистрированный алгоритм подтверждения. Ручной режим, отсутствующий/недоступный алгоритм, необходимый неназначенный ответственный либо неподключённый executor ведут к manual_required. Ответственный, когда он требуется политикой, должен быть активным пользователем.
  • Нетерминальный результат алгоритма оставляет ожидание. При терминальном результате backend применяет доменные правила: баллы и порог, ответственного, допустимость завершения попытки. Ошибка валидации не становится успехом: возвращается ожидание с ошибкой. Фактически сохранённый PASSED/FAILED имеет приоритет над одним словом outcome, полученным от алгоритма.
  • Иное уже сохранённое состояние попытки возвращается как состояние ожидания; оно не приравнивается автоматически к FAILED.

Runtime сначала доставляет возвращённые уведомления. При state=completed и непустом target_status он запрашивает указанный переход, затем явно передаёт Ticket: outcome=passed — в open_st_request_done, остальные outcome — в open_st_request_wontfix. После успешной передачи Ticket удаляется из текущей очереди с сохранением комнаты. Backend текущего контракта возвращает согласованные пары passed/DONE и failed/WONTFIX; схема не вводит дополнительного ручного решения по статусу.

Если completed пришёл без target_status, переход не выполняется: остаётся повторная проверка. Не следует по одному слову completed считать заявку окончательно закрытой.

Организация встречи не является результатом проверки

Примитив prepare_verification_organization действует только для requirement-check-v1; для проверки документа он ничего не меняет. Он вызывает действие organize и публичный интеграционный порт подготовки встречи. Отсутствие подключённого провайдера или ответ available=false не блокирует последующий advance и не означает отрицательную проверку.

При доступной организации backend сохраняет сведения о booking в RequirementCheck.organization_data и Ticket.json.organization. Если активной записи ещё нет, наличие self-booking URL может породить уведомление автору, а assignment URL — уведомление проверяющим. Этот шаг не меняет результат RequirementCheck. Наличие ссылки не доказывает, что пользователь записался, встреча состоялась или проверка пройдена.

Ошибка HTTP/разбора ответа organize логируется; проход продолжается с advance. Ошибка отправки уведомления вне этого локального catch может попасть в общий retry. Внутреннее устройство необязательного провайдера встреч здесь не описывается: закреплён именно публичный порт backend.

Внешнее решение и смена владельца (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_st_inprocess_external" targetNamespace="urn:sharix:knowledge:handlers">
  <bpmn:process id="reviewer_Process_reviewer" name="Пользователь с доступом к Ticket и правом смены статуса" isExecutable="false">
    <bpmn:documentation>{"notes": ["Опубликованный Git built-in; не подтверждение выбранной версии на любом сервере.", "Процессы не исполняются просмотрщиком. End event завершает показанную операцию, не всю заявку.", "deferred_until — символ локального срока, не имя параметра конфигурации.", "XMPP — best effort; acknowledge означает сохранение ключа после send, не прочтение.", "Два wakeup-события публикуются после commit. Потерю доставки восстанавливает scoped periodic reconciliation."], "sources": [{"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "generated_handler_blocks/open_st_request_inprocess.json", "repository": "sharix-open-handlers-examples", "sha256": "aedf573066b509bc1d7177d08530ae2ed1a5e896c8745e02edaed27e3d561313"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_st_request_inprocess.py", "repository": "sharix-open-handlers-examples", "sha256": "7dc2424c827ba4dc04971a8691d0e624566c6b4cb409cffec2e552dcad2aca4d"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_st_request_done.py", "repository": "sharix-open-handlers-examples", "sha256": "b6ae4733904d9ba8e691f43235d4836d201ac019ff99982d532816bfdc89bf31"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_st_request_wontfix.py", "repository": "sharix-open-handlers-examples", "sha256": "ece9fb7e09ee0e401e91d5d274d6b151b51d1364ba698b835c929e6416f90f03"}, {"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/requesters.py", "repository": "sharix-open-handlers-backend", "sha256": "965a348cea477722bbaf4c8c6b06023eb238b71664a332f7ea8c90bfe72ea808"}, {"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": "services/verification_results.py", "repository": "sharix-open-tickets", "sha256": "682c5f6869373e649d6d62f44e63e8fb3bb34cf6bfc85d0187b26b2c96984e91"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "services/st_request_contracts.py", "repository": "sharix-open-tickets", "sha256": "9c1553437dbff63c608504ee000fa67a9be6e9887b1df0599552aa4d9141276c"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "views/ticket_detail.py", "repository": "sharix-open-tickets", "sha256": "05d344b0fba14cf895400694d4a18f486c800fef08dd1acb43ea46909b9e7e59"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "utils.py", "repository": "sharix-open-tickets", "sha256": "a5680205c6522e1d9a74d9d267fe9ee96faf6f06436b00877fc0a93d80234bf5"}, {"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": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "api/views/handler_workflow.py", "repository": "sharix-open-tickets", "sha256": "f97c4b467a9a30749f5c4b86b39a833c430e57aaa1f030f70030d9b5c609d368"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "apiviews/handler_workflow.py", "repository": "sharix-open-backend", "sha256": "0f699a4e16760cbbdd09d894093c685ba69073fedf0522852cb1fdc9811636e3"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/verification_workflow.py", "repository": "sharix-open-backend", "sha256": "9fe62f8344d7fd78e5af0ce025c82ba4f7d21759e71f518df1186a1d6a4a0644"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/verification_algorithms.py", "repository": "sharix-open-backend", "sha256": "9e55e4119051847bb3596c3563b9b151ee92b660e89c39c533b16ed6b4a2099e"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/verification_responsibility.py", "repository": "sharix-open-backend", "sha256": "7919b83c89cb4214545ea2c2db0cffac09af892b190ce3af72348d688abb9cf4"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/requirement_checks.py", "repository": "sharix-open-backend", "sha256": "5a73a6e71307e734f0c0e480fd14a825a7a22242811e2523b7f25157224cf34c"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/integration_ports.py", "repository": "sharix-open-backend", "sha256": "d079ec56e6709b29d7755e47d2a88d423235fe8eb1bf7a92851ae25d74bf1066"}]}</bpmn:documentation>
    <bpmn:laneSet id="reviewer_Lanes_reviewer">
      <bpmn:lane id="reviewer_Lane_worker" name="Действие проверяющего / исполнителя">
        <bpmn:flowNodeRef>reviewer_start</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>reviewer_form</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>reviewer_send</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>reviewer_end</bpmn:flowNodeRef>
      </bpmn:lane>
    </bpmn:laneSet>
    <bpmn:startEvent id="reviewer_start" name="Работа или проверка выполнена">
      <bpmn:outgoing>reviewer_Flow_0</bpmn:outgoing>
    </bpmn:startEvent>
    <bpmn:userTask id="reviewer_form" name="Выбрать допустимый DONE / WONTFIX">
      <bpmn:documentation>В форме специализированной проверки — комментарий и применимые баллы. Авторство Ticket само по себе не даёт право менять статус.</bpmn:documentation>
      <bpmn:incoming>reviewer_Flow_0</bpmn:incoming>
      <bpmn:outgoing>reviewer_Flow_1</bpmn:outgoing>
    </bpmn:userTask>
    <bpmn:sendTask id="reviewer_send" name="Отправить результат через карточку Ticket">
      <bpmn:incoming>reviewer_Flow_1</bpmn:incoming>
      <bpmn:outgoing>reviewer_Flow_2</bpmn:outgoing>
    </bpmn:sendTask>
    <bpmn:endEvent id="reviewer_end" name="Дождаться результата сохранения">
      <bpmn:incoming>reviewer_Flow_2</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:sequenceFlow id="reviewer_Flow_0" sourceRef="reviewer_start" targetRef="reviewer_form" name="" />
    <bpmn:sequenceFlow id="reviewer_Flow_1" sourceRef="reviewer_form" targetRef="reviewer_send" name="" />
    <bpmn:sequenceFlow id="reviewer_Flow_2" sourceRef="reviewer_send" targetRef="reviewer_end" name="" />
  </bpmn:process>
  <bpmn:process id="ticket_Process_ticket" name="Tickets: права, metadata результата и переход статуса" isExecutable="false">
    <bpmn:documentation>{"notes": ["Опубликованный Git built-in; не подтверждение выбранной версии на любом сервере.", "Процессы не исполняются просмотрщиком. End event завершает показанную операцию, не всю заявку.", "deferred_until — символ локального срока, не имя параметра конфигурации.", "XMPP — best effort; acknowledge означает сохранение ключа после send, не прочтение.", "Два wakeup-события публикуются после commit. Потерю доставки восстанавливает scoped periodic reconciliation."], "sources": [{"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "generated_handler_blocks/open_st_request_inprocess.json", "repository": "sharix-open-handlers-examples", "sha256": "aedf573066b509bc1d7177d08530ae2ed1a5e896c8745e02edaed27e3d561313"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_st_request_inprocess.py", "repository": "sharix-open-handlers-examples", "sha256": "7dc2424c827ba4dc04971a8691d0e624566c6b4cb409cffec2e552dcad2aca4d"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_st_request_done.py", "repository": "sharix-open-handlers-examples", "sha256": "b6ae4733904d9ba8e691f43235d4836d201ac019ff99982d532816bfdc89bf31"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_st_request_wontfix.py", "repository": "sharix-open-handlers-examples", "sha256": "ece9fb7e09ee0e401e91d5d274d6b151b51d1364ba698b835c929e6416f90f03"}, {"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/requesters.py", "repository": "sharix-open-handlers-backend", "sha256": "965a348cea477722bbaf4c8c6b06023eb238b71664a332f7ea8c90bfe72ea808"}, {"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": "services/verification_results.py", "repository": "sharix-open-tickets", "sha256": "682c5f6869373e649d6d62f44e63e8fb3bb34cf6bfc85d0187b26b2c96984e91"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "services/st_request_contracts.py", "repository": "sharix-open-tickets", "sha256": "9c1553437dbff63c608504ee000fa67a9be6e9887b1df0599552aa4d9141276c"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "views/ticket_detail.py", "repository": "sharix-open-tickets", "sha256": "05d344b0fba14cf895400694d4a18f486c800fef08dd1acb43ea46909b9e7e59"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "utils.py", "repository": "sharix-open-tickets", "sha256": "a5680205c6522e1d9a74d9d267fe9ee96faf6f06436b00877fc0a93d80234bf5"}, {"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": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "api/views/handler_workflow.py", "repository": "sharix-open-tickets", "sha256": "f97c4b467a9a30749f5c4b86b39a833c430e57aaa1f030f70030d9b5c609d368"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "apiviews/handler_workflow.py", "repository": "sharix-open-backend", "sha256": "0f699a4e16760cbbdd09d894093c685ba69073fedf0522852cb1fdc9811636e3"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/verification_workflow.py", "repository": "sharix-open-backend", "sha256": "9fe62f8344d7fd78e5af0ce025c82ba4f7d21759e71f518df1186a1d6a4a0644"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/verification_algorithms.py", "repository": "sharix-open-backend", "sha256": "9e55e4119051847bb3596c3563b9b151ee92b660e89c39c533b16ed6b4a2099e"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/verification_responsibility.py", "repository": "sharix-open-backend", "sha256": "7919b83c89cb4214545ea2c2db0cffac09af892b190ce3af72348d688abb9cf4"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/requirement_checks.py", "repository": "sharix-open-backend", "sha256": "5a73a6e71307e734f0c0e480fd14a825a7a22242811e2523b7f25157224cf34c"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/integration_ports.py", "repository": "sharix-open-backend", "sha256": "d079ec56e6709b29d7755e47d2a88d423235fe8eb1bf7a92851ae25d74bf1066"}]}</bpmn:documentation>
    <bpmn:laneSet id="ticket_Lanes_ticket">
      <bpmn:lane id="ticket_Lane_worker" name="Backend и commit">
        <bpmn:flowNodeRef>ticket_request</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>ticket_acl</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>ticket_allowed</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>ticket_save</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>ticket_publish</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>ticket_end</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>ticket_denied</bpmn:flowNodeRef>
      </bpmn:lane>
    </bpmn:laneSet>
    <bpmn:startEvent id="ticket_request" name="Запрос из карточки">
      <bpmn:outgoing>ticket_Flow_0</bpmn:outgoing>
      <bpmn:messageEventDefinition />
    </bpmn:startEvent>
    <bpmn:serviceTask id="ticket_acl" name="Проверить права, переход и границы заказа">
      <bpmn:incoming>ticket_Flow_0</bpmn:incoming>
      <bpmn:outgoing>ticket_Flow_1</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:exclusiveGateway id="ticket_allowed" name="Переход разрешён?">
      <bpmn:incoming>ticket_Flow_1</bpmn:incoming>
      <bpmn:outgoing>ticket_Flow_2</bpmn:outgoing>
      <bpmn:outgoing>ticket_Flow_3</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:serviceTask id="ticket_save" name="Сохранить результат и разрешённый статус">
      <bpmn:documentation>В одной atomic-секции; это ещё не применение доменного результата проверки.</bpmn:documentation>
      <bpmn:incoming>ticket_Flow_2</bpmn:incoming>
      <bpmn:outgoing>ticket_Flow_4</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:sendTask id="ticket_publish" name="После commit: changed и moved">
      <bpmn:incoming>ticket_Flow_4</bpmn:incoming>
      <bpmn:outgoing>ticket_Flow_5</bpmn:outgoing>
    </bpmn:sendTask>
    <bpmn:endEvent id="ticket_end" name="Статус сохранён">
      <bpmn:incoming>ticket_Flow_5</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:endEvent id="ticket_denied" name="Отказ: бизнес-переход не выполнен">
      <bpmn:incoming>ticket_Flow_3</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:sequenceFlow id="ticket_Flow_0" sourceRef="ticket_request" targetRef="ticket_acl" name="" />
    <bpmn:sequenceFlow id="ticket_Flow_1" sourceRef="ticket_acl" targetRef="ticket_allowed" name="" />
    <bpmn:sequenceFlow id="ticket_Flow_2" sourceRef="ticket_allowed" targetRef="ticket_save" name="Да" />
    <bpmn:sequenceFlow id="ticket_Flow_3" sourceRef="ticket_allowed" targetRef="ticket_denied" name="Нет" />
    <bpmn:sequenceFlow id="ticket_Flow_4" sourceRef="ticket_save" targetRef="ticket_publish" name="" />
    <bpmn:sequenceFlow id="ticket_Flow_5" sourceRef="ticket_publish" targetRef="ticket_end" name="" />
  </bpmn:process>
  <bpmn:collaboration id="Collaboration_st_inprocess_external">
    <bpmn:participant id="reviewer_Pool_reviewer" name="Пользователь с доступом к Ticket и правом смены статуса" processRef="reviewer_Process_reviewer" />
    <bpmn:participant id="ticket_Pool_ticket" name="Tickets: права, metadata результата и переход статуса" processRef="ticket_Process_ticket" />
    <bpmn:participant id="old_Participant" name="IN_PROCESS: убрать прежний локальный снимок; reconciliation при потере события" />
    <bpmn:participant id="next_Participant" name="DONE / WONTFIX handler: complete workflow; доменные проверки, затем CLOSED" />
    <bpmn:messageFlow id="Message_st_inprocess_external_0" sourceRef="reviewer_send" targetRef="ticket_request" name="Запрос разрешённого перехода" />
    <bpmn:messageFlow id="Message_st_inprocess_external_1" sourceRef="ticket_publish" targetRef="old_Participant" name="ticket.moved: прежний IN_PROCESS" />
    <bpmn:messageFlow id="Message_st_inprocess_external_2" sourceRef="ticket_publish" targetRef="next_Participant" name="ticket.changed: новый DONE / WONTFIX" />
  </bpmn:collaboration>
  <bpmndi:BPMNDiagram id="Diagram_st_inprocess_external">
    <bpmndi:BPMNPlane id="Plane_st_inprocess_external" bpmnElement="Collaboration_st_inprocess_external">
      <bpmndi:BPMNShape id="reviewer_DI_Pool_reviewer" bpmnElement="reviewer_Pool_reviewer" isHorizontal="true">
        <dc:Bounds x="0.0" y="0.0" width="1110" height="200" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="reviewer_DI_Lane_worker" bpmnElement="reviewer_Lane_worker" isHorizontal="true">
        <dc:Bounds x="30.0" y="0.0" width="1080" height="200" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="reviewer_DI_start" bpmnElement="reviewer_start">
        <dc:Bounds x="132.0" y="82.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="reviewer_DI_form" bpmnElement="reviewer_form">
        <dc:Bounds x="345.0" y="65.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="reviewer_DI_send" bpmnElement="reviewer_send">
        <dc:Bounds x="625.0" y="65.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="reviewer_DI_end" bpmnElement="reviewer_end">
        <dc:Bounds x="932.0" y="82.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="reviewer_DI_Flow_0" bpmnElement="reviewer_Flow_0">
        <di:waypoint x="168.0" y="100.0" />
        <di:waypoint x="345.0" y="100.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="reviewer_DI_Flow_1" bpmnElement="reviewer_Flow_1">
        <di:waypoint x="495.0" y="100.0" />
        <di:waypoint x="625.0" y="100.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="reviewer_DI_Flow_2" bpmnElement="reviewer_Flow_2">
        <di:waypoint x="775.0" y="100.0" />
        <di:waypoint x="932.0" y="100.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="ticket_DI_Pool_ticket" bpmnElement="ticket_Pool_ticket" isHorizontal="true">
        <dc:Bounds x="0.0" y="270.0" width="1630" height="370" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="ticket_DI_Lane_worker" bpmnElement="ticket_Lane_worker" isHorizontal="true">
        <dc:Bounds x="30.0" y="270.0" width="1600" height="370" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="ticket_DI_request" bpmnElement="ticket_request">
        <dc:Bounds x="132.0" y="352.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="ticket_DI_acl" bpmnElement="ticket_acl">
        <dc:Bounds x="345.0" y="335.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="ticket_DI_allowed" bpmnElement="ticket_allowed">
        <dc:Bounds x="675.0" y="345.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="ticket_DI_save" bpmnElement="ticket_save">
        <dc:Bounds x="875.0" y="335.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="ticket_DI_publish" bpmnElement="ticket_publish">
        <dc:Bounds x="1145.0" y="335.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="ticket_DI_end" bpmnElement="ticket_end">
        <dc:Bounds x="1452.0" y="352.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="ticket_DI_denied" bpmnElement="ticket_denied">
        <dc:Bounds x="682.0" y="522.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="ticket_DI_Flow_0" bpmnElement="ticket_Flow_0">
        <di:waypoint x="168.0" y="370.0" />
        <di:waypoint x="345.0" y="370.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="ticket_DI_Flow_1" bpmnElement="ticket_Flow_1">
        <di:waypoint x="495.0" y="370.0" />
        <di:waypoint x="675.0" y="370.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="ticket_DI_Flow_2" bpmnElement="ticket_Flow_2">
        <di:waypoint x="725.0" y="370.0" />
        <di:waypoint x="875.0" y="370.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="ticket_DI_Flow_3" bpmnElement="ticket_Flow_3">
        <di:waypoint x="700.0" y="395.0" />
        <di:waypoint x="700.0" y="522.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="ticket_DI_Flow_4" bpmnElement="ticket_Flow_4">
        <di:waypoint x="1025.0" y="370.0" />
        <di:waypoint x="1145.0" y="370.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="ticket_DI_Flow_5" bpmnElement="ticket_Flow_5">
        <di:waypoint x="1295.0" y="370.0" />
        <di:waypoint x="1452.0" y="370.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="DI_old_Participant" bpmnElement="old_Participant" isHorizontal="true">
        <dc:Bounds x="0" y="820" width="760" height="100" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="DI_next_Participant" bpmnElement="next_Participant" isHorizontal="true">
        <dc:Bounds x="850" y="820" width="850" height="100" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="DI_Message_st_inprocess_external_0" bpmnElement="Message_st_inprocess_external_0">
        <di:waypoint x="700" y="135" />
        <di:waypoint x="700" y="225" />
        <di:waypoint x="150" y="225" />
        <di:waypoint x="150" y="352" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="220" y="190" width="260" height="42" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="DI_Message_st_inprocess_external_1" bpmnElement="Message_st_inprocess_external_1">
        <di:waypoint x="1220" y="405" />
        <di:waypoint x="1220" y="640" />
        <di:waypoint x="380" y="640" />
        <di:waypoint x="380" y="820" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="220" y="680" width="260" height="42" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="DI_Message_st_inprocess_external_2" bpmnElement="Message_st_inprocess_external_2">
        <di:waypoint x="1280" y="405" />
        <di:waypoint x="1650" y="405" />
        <di:waypoint x="1650" y="700" />
        <di:waypoint x="1275" y="700" />
        <di:waypoint x="1275" y="820" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="1030" y="735" width="260" height="42" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn:definitions>

Пользователь открывает карточку Ticket и выбирает допустимый переход. Форма профильной проверки позволяет передать комментарий и, для requirement-check-v1, применимые баллы. View сохраняет metadata результата вместе с разрешённой сменой статуса в atomic-секции. Это запись решения для последующего потребителя; сама форма не импортирует dbsynce и не применяет доменный результат напрямую.

Чтение Ticket и право менять его статус проверяются отдельно. Авторство само по себе не даёт право менять статус; учитываются права управления Ticket и доступные переходы. Связанные с заказом Ticket не должны обходить lifecycle заказа через универсальную форму. Наличие API для смены статуса не доказывает, что произвольный API-клиент сохраняет все поля ручной проверки так же, как эта форма.

После commit канонический backend направляет ticket.changed новому владельцу и ticket.moved прежнему IN_PROCESS. Прежний runtime исключает локальный снимок; для in-flight worker удаление откладывается до его завершения. Потеря XMPP-события восстанавливается периодическим scoped списком. Действие пользователя и доставка wakeup — разные операции: сохранённый статус не означает мгновенного запуска следующего worker.

Следующий DONE/WONTFIX handler для профильного контракта вызывает complete: применяет/сверяет доменный результат, переоценивает связанные требования и при успешном завершении переводит Ticket в CLOSED. Для обычного обращения эти стадии имеют другое поведение. Поэтому переход из IN_PROCESS в DONE нельзя трактовать как безусловное завершение всех связанных проверок и активаций.

Уведомления и подтверждение отправки

Backend возвращает audience, текст и ключ уведомления. Runtime получает JID автора через защищённый API; получатели reviewers — активные участники группы списка Ticket, полученные через отдельный защищённый endpoint. Повторяющиеся JID убираются. При наличии фактической попытки отправки сохраняется ack_notification для ключа; уже подтверждённые ключи backend не возвращает.

Это защита от обычных повторных отправок, а не гарантия exactly-once или прочтения человеком. Ошибка сохранения ack после отправки может привести к повтору уведомления. Отсутствие получателя не превращается в подтверждённую доставку. Сообщение проверяющему не выдаёт ему права на Ticket и не заменяет его решение.

Таймеры и восстановление

Ситуация Повтор / причина
Обычное обращение в ручном режиме ST_REQUEST_IN_PROCESS_RECHECK_SECONDS; локальная support_execution, журнал defer st_request_in_process
Ошибка HTTP/разбора advance 60 секунд; verification_backend_error
Ответ pending 60 секунд; verification_pending
manual_required и другие нетерминальные состояния 300 секунд; verification_<state>; при пустом state — verification_waiting
completed без target_status 300 секунд; verification_completed
Необработанное локальными catch исключение DEFERRED_TICKET_RECHECK_SECONDS; processing_error
Сверка состава очереди INTERVAL_TIME_BD_REQ; scoped список текущего владельца

60 и 300 секунд — константы изученной версии Python, а не отдельные настройки окружения. Все интервалы задают момент готовности к новому проходу; свободный worker, соединение XMPP и доступность backend влияют на фактический запуск. Defer хранится в памяти процесса. После рестарта runtime заново получает актуальное состояние. Новая authoritative revision может снять прежний defer, повтор того же снимка — нет. Ошибка scoped списка не должна очищать локальную очередь как будто backend вернул пустой результат.

Что проверить при зависшем IN_PROCESS

  • Какая опубликованная/локальная версия действительно выбрана, совпадают ли её workspace и сгенерированный Python.
  • Верно ли указан стабильный контракт, существует ли связанный документ или попытка RequirementCheck.
  • Для обычного обращения — режим autoaccept и значение именованного интервала; для профильного — состояние проверки, алгоритм, ответственный и необходимость ручного решения.
  • Для встречи — подключён ли провайдер и есть ли реальная запись; наличие организации не считать результатом проверки.
  • Успешны ли scoped API, отправка и ack, получает ли runtime новые снимки и wakeup-события. Уже committed результат после сетевой ошибки сначала перечитать, не принимать повторное бизнес-решение вслепую.
  • После DONE/WONTFIX — завершился ли отдельный complete и прошли ли доменные проверки. Статус Ticket и факт закрытия workflow различать.

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

Версии и SHA-256 файлов сохранены в metadata страницы и documentation BPMN. Алгоритм сверяется по workspace и каноническому Python, внешние действия — по view/API/ACL, runtime и доменным операциям. При изменении источников требуется повторный анализ; изменение одних хешей не доказывает актуальность схемы.

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

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

© 2022 ShariX