Files
Bridge-and-Join-s/internal/lkgateway/web/templates/admin_help_lk.html
T
zuevav 222d48e740 Кабинет: веб-установщик и управление пользователями в ядре
- установщик в самом кабинете: до настройки любая страница ведёт в /install; три шага —
  проверка сервера (каталог данных, https), связь с ядром (режим, адрес, ключ; связь
  проверяется до сохранения, в режиме ожидания страница ждёт подключения ядра),
  администратор кабинета (заводится в ядре через /api/lk/admin/bootstrap, только пока
  администраторов нет); настройки в data/lk.json 0600, окружение перекрывает файл;
  после установки установщик закрыт
- настройки кабинета можно менять на ходу: Server за мьютексом, один mux на всё время
- ключ модуля больше не кладётся в архив: его вводят в установщике; на странице настроек
  ключ показан целиком 10 минут после создания, потом маска
- ядро: карточка «Пользователи кабинета» в настройках — список, заведение, смена пароля
  (гасит сессии), блокировка, права сотрудника, разрешение поручений, удаление; письма
  не отправляются
- инструкция /admin/help/lk дополнена шагами установщика и разделом о подходящем хостинге
- тесты: TestInstaller, TestNotConfigured, TestSetupPageLKUsersAndLink; установщик
  проверен вживую вторым экземпляром против боевого ядра

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 09:30:47 +03:00

143 lines
13 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{{define "content"}}
<p style="margin-bottom:16px"><a href="/admin/help">← все инструкции</a></p>
<div class="card">
<h2>Как разместить кабинет клиента на хостинге</h2>
<p class="muted">Речь о нашем модуле <code>bj-lk</code> — кабинете, который клиенты открывают в браузере. Он ставится отдельно от ядра: на веб-сервер депозитария или на обычный хостинг с выделенным именем. Своей базы у кабинета нет, данные клиентов он не хранит — берёт у ядра на время запроса.</p>
<h3>Шаг 1. Ключ и архив</h3>
<p>Настройки → «Личный кабинет» → «Кабинет клиента на своём сервере»: создайте ключ доступа (сразу после создания он показан целиком 10 минут — перепишите его для установщика) и скачайте архив. В архиве — исполняемый файл, служба systemd, файл настроек службы, установщик и README. Ключа в архиве нет.</p>
<h3>Шаг 2. Файлы на сервер и запуск</h3>
<pre>tar xzf bj-lk-ГГГГ-ММ-ДД.tar.gz
cd bj-lk
sudo ./install.sh # на своём сервере: заводит службу bj-lk
# или на хостинге, где можно держать программу запущенной:
LISTEN=127.0.0.1:8099 ./bj-lk</pre>
<p><code>install.sh</code> заводит системного пользователя <code>bjlk</code>, кладёт программу в <code>/opt/bj-lk</code>, каталог данных — <code>/var/lib/bj-lk</code>, и включает службу. Сам кабинет слушает только <code>127.0.0.1:8099</code>.</p>
<h3>Шаг 3. Установщик в браузере</h3>
<p>Откройте адрес кабинета — до настройки любая страница ведёт в установщик, как у обычных веб-приложений. Он делает три шага:</p>
<ol>
<li><b>Проверка сервера</b>: каталог данных доступен для записи, соединение защищено (https), адрес кабинета.</li>
<li><b>Связь с ядром</b>: способ связи (кабинет обращается к ядру / ядро подключается к кабинету), адрес ядра и ключ доступа. В прямом режиме связь проверяется до сохранения; в режиме ожидания страница ждёт, пока ядро подключится.</li>
<li><b>Администратор кабинета</b>: логин и пароль сотрудника, который будет видеть список клиентов. Учётная запись заводится в ядре; если администратор уже есть, шаг пропускается.</li>
</ol>
<p>Настройки сохраняются в <code>lk.json</code> (каталог данных, права 0600), после чего установщик закрывается. Чтобы пройти его заново — удалите этот файл. Установка без браузера: заполните <code>lk.env</code> — окружение перекрывает файл установщика.</p>
<h3>Шаг 4. Публикация наружу</h3>
<p>Перед кабинетом ставится nginx с сертификатом TLS — пример конфигурации есть в README архива. Наружу открыт только 443 порт сервера кабинета.</p>
<h3>Связь с ядром — два способа</h3>
<p><b>Кабинет обращается к ядру</b> (обычный случай). В настройках ядра укажите его адрес, кабинет ходит туда за данными. Требуется, чтобы сервер кабинета мог открыть соединение к ядру по https.</p>
<p><b>Ядро подключается к кабинету.</b> Если у ядра нет адреса в интернете — а так чаще всего и бывает, ядро стоит во внутренней сети депозитария, — порядок разворачивается. Кабинет ничего никуда не звонит: он копит запросы клиентов и ждёт. Ядро само подключается к кабинету по его доменному имени, забирает запрос, выполняет его у себя и возвращает ответ. Из сети депозитария идёт только исходящее соединение: ни белого адреса, ни проброса портов, ни правил для входящего трафика не нужно.</p>
<p>Включается в настройках ядра: «Личный кабинет» → «Как кабинет и ядро находят друг друга» → «Ядро подключается к кабинету», рядом — адрес кабинета. В файле кабинета при этом стоит <code>BJ_MODE=agent</code>, а <code>BJ_URL</code> не задан. Состояние связи видно там же: подключено ли ядро, когда был последний обмен, сколько запросов обслужено.</p>
<p>В обе стороны канал защищён тем же ключом модуля: запрос без ключа кабинет не отдаёт, ответ без ключа не принимает.</p>
<h3>Что с данными</h3>
<ul>
<li>Кабинет не хранит ни базы, ни файлов: портфель, операции и документы приходят из ядра на время показа страницы.</li>
<li>Пароли клиентов лежат только в ядре и только в виде bcrypt-хеша; кабинет их не видит.</li>
<li>Страница не обращается к сторонним сайтам — шрифты и оформление вшиты в программу.</li>
<li>Вход сотрудника в кабинет клиента записывается в журнал доступа (<code>lk.audit</code>) и поднимает оповещение.</li>
<li>Обновляется кабинет отдельно от ядра — через сервер обновлений, по лицензии модуля «Личный кабинет клиента».</li>
<li>Учётные записи кабинета (клиенты и сотрудники) заводятся здесь же, в карточке «Пользователи кабинета». Письма не отправляются — пароль сообщается лично.</li>
</ul>
<h3>Какой хостинг подходит</h3>
<p>Кабинет — одна программа (Linux, x86-64), которая должна быть постоянно запущена и слушать порт. Подходят: свой сервер или VPS, хостинг с поддержкой собственных приложений (Node/Go/Python через SSH или панель). Обычный PHP-хостинг «папка с файлами» программу запустить не сможет — там нужен либо тариф с приложениями, либо VPS у того же хостера.</p>
</div>
<div class="card">
<h2>API личного кабинета (ESIA Finance V1)</h2>
<p class="muted">Bridge-and-Join-s реализует контракт ESIA Finance V1 на стороне back-office. ЛК клиента отправляет нам заявку, мы возвращаем подтверждение и потом колбэк со статусом. Полная спецификация: <code>docs/lk-contract/v1/openapi.yaml</code>.</p>
</div>
<div class="card">
<h2>1. Аутентификация</h2>
<p>HTTP <strong>Basic</strong>. Учётные записи и пароли согласуются с командой ЛК.</p>
<pre>curl -u "lk-user:lk-password" \
-H "Content-Type: application/json" \
http://10.10.10.22:8080/api/v1/back_office/claims/</pre>
{{if .DevMode}}<p class="muted">На M2 (дев-стенд) аутентификация отключена; включится на M3 — параллельно с подключением реального ЛК.</p>{{end}}
</div>
<div class="card">
<h2>2. Создание заявки M2M</h2>
<p><code>POST /api/v1/back_office/claims/</code></p>
<p>Тело — JSON, кодировка UTF-8. Минимально нужно: анкета инвестора, ИНН передающего и принимающего депозитария, информация о стоимости, массив ценных бумаг с количеством и счетами, подписанный XML заявления (base64).</p>
<pre>curl -X POST http://10.10.10.22:8080/api/v1/back_office/claims/ \
-H "Content-Type: application/json" \
-d @docs/lk-contract/v1/examples/claim-request.json</pre>
<p>Ответ <code>201 Created</code>:</p>
<pre>{
"id": "c02a1d5e-c2af-4799-bab4-953f133c5133",
"status": "submitted_to_nsd",
"created_at": "2026-03-02T14:30:45Z",
"success": true
}</pre>
</div>
<div class="card">
<h2>3. Получение заявки и её статуса</h2>
<p><code>GET /api/v1/back_office/claims/{id}</code></p>
<pre>curl http://10.10.10.22:8080/api/v1/back_office/claims/c02a1d5e-c2af-4799-bab4-953f133c5133</pre>
<p>Возвращает полную карточку с историей FSM, ответом НРД и решением принимающей стороны (когда оно пришло).</p>
</div>
<div class="card">
<h2>4. Список заявок</h2>
<p><code>GET /api/v1/back_office/claims</code> с query-фильтрами: <code>status</code>, <code>investor_id</code>, <code>created_from</code>, <code>created_to</code>, <code>limit</code>, <code>offset</code>.</p>
<pre>curl "http://10.10.10.22:8080/api/v1/back_office/claims?status=confirmed&limit=20"</pre>
</div>
<div class="card">
<h2>5. Callback статуса (мы → ЛК)</h2>
<p>Когда сделка меняет статус (подтверждена принимающей стороной, отклонена, или произошёл таймаут), bj-server делает <code>PATCH {LK_BASE}/api/v1/back_office/claims/{id}</code>:</p>
<pre>{
"claim_id": "c02a1d5e-c2af-4799-bab4-953f133c5133",
"new_status": "confirmed",
"updated_at": "2026-03-02T14:38:12Z",
"nsd_response": {
"guid": "...",
"status_code": "INFO",
"responses": [{"reference_id": "M2M2026...", "code": "01", "text": "..."}]
}
}</pre>
<p>Адрес ЛК указывается в <a href="/admin/setup">Настройка → Callback в ЛК</a> или через переменную <code>BJ_LK_CALLBACK_URL</code>.</p>
</div>
<div class="card">
<h2>6. Формат ошибок</h2>
<p>Любая ошибка возвращается в формате, идентичном ESIA Finance V1:</p>
<pre>{
"error": true,
"status": 422,
"code": "invalid_signature",
"title": "Подпись заявления не прошла проверку",
"meta": {
"message": "Сертификат подписанта недействителен или цепочка доверия не построена.",
"errors": [{"field": "signed_document", "message": "..."}]
}
}</pre>
</div>
{{if .DevMode}}
<div class="card">
<h2>7. Эмулятор ЛК для тестов</h2>
<p>На дев-стенде доступен <strong>lk-emulator</strong> на порту 8083 — имитация ЛК. Он сам регистрирует свой URL в bj-server как callback-приёмник.</p>
<ul>
<li><code>http://10.10.10.22:8083/</code> — журнал моих заявок (автообновление 3 сек)</li>
<li><code>http://10.10.10.22:8083/new</code> — форма «подать заявку» с предустановленными инвесторами из seed-данных</li>
<li>При запуске реального ЛК эмулятор остаётся как QA-инструмент</li>
</ul>
</div>
{{end}}
<div class="card">
<h2>{{if .DevMode}}8{{else}}7{{end}}. Подписание заявления</h2>
<p>ЛК должен подписать заявление XMLDSig (ГОСТ или RSA) и положить в поле <code>signed_document</code> (base64). Мы проверяем подпись через crypto-service — см. <a href="/admin/help/crypto">инструкцию по криптографии</a>.</p>
{{if .DevMode}}<p class="muted">На M2 проверка подписи отключена (stub). На M3-M4 включится после подключения СКЗИ.</p>{{end}}
</div>
{{end}}