О платформе SuraqHub Введение
SuraqHub — это корпоративная отказоустойчивая платформа для проектирования интерактивных электронных форм, проведения опросов, сбора структурированных данных, их валидации, антивирусной проверки и передачи во внешние аналитические хранилища в режиме реального времени.
⚡ Ключевые возможности
- Визуальный конструктор с поддержкой более 30 типов компонентов, адаптивных сеток и формул (полное руководство).
- Антивирусная защита: каждый загружаемый файл изолируется и проверяется через ClamAV до попадания в хранилище.
- Асинхронная архитектура: экспорт сотен тысяч анкет в Excel (XLSX) выполняется в фоне через RabbitMQ.
- Интеграции корпоративного уровня: синхронный GraphQL API по M2M-ключам, моментальные вебхуки с криптографической подписью HMAC-SHA256 и pull-канал аналитики для Power BI через выделенную схему БД.
- Соответствие стандартам: поддержка светлой/темной тем, accessibility WCAG 2.2 AA и строгие политики безопасности Content Security Policy (CSP).
Концепции и Базовые Сущности Архитектура
В основе архитектуры SuraqHub лежит четкое разделение между структурой вопросов (схемой) и точкой доступа к анкете (публикацией):
📝 Шаблон формы (Form Schema)
Это JSON-структура, которая описывает вопросы, валидацию, типы полей, выпадающие списки и условную логику. Шаблоны неизменяемы: при каждом сохранении создается новая ревизия в истории версий, что гарантирует целостность уже собранных ответов.
🌐 Публикация (Publication)
Это конфигурация веб-страницы анкеты. Содержит Slug (человекочитаемый адрес, например /f/feedback), статус доступности (Активна / Неактивна), брендинг (Header, Footer), тему оформления и привязку к конкретной версии шаблона формы.
💡 Преимущество разделения:
Вы можете заранее конструировать и тестировать новые версии формы, а затем в один клик переключить публикацию на новую версию без простоя пользователей или изменения адреса ссылки.
Жизненный цикл создания формы Workflow
Стандартный рабочий процесс от задумки до получения готовых отчетов состоит из 5 шагов:
- Создание публикации (Экран «Основное»): задайте название анкеты и ее будущий веб-адрес (Slug).
- Конструирование вопросов (Экран «Конструктор»): соберите структуру полей, настройте обязательность, подсказки и логику показа.
- Брендинг и локализация (Экраны «Дизайн» и «Переводы»): настройте шапку компании, подвал и добавьте перевод на казахский/английский языки.
- Предпросмотр и проверка (Экран «Предпросмотр»): заполните тестовую анкету, убедитесь в корректности расчетов и валидации.
- Активация и сбор ответов: включите тумблер «Статус: Активно» и анализируйте результаты на экране «Отчетность» либо через Webhooks/API.
Раздел «Основное» (Управление публикациями) Экран
Центральный экран для мониторинга всех опубликованных анкет и управления ревизиями.
Элементы управления
- Кнопка «Новая публикация»: Очищает форму создания и переводит менеджер в режим регистрации нового адреса.
- Поиск (Живой фильтр): Мгновенно фильтрует список публикаций по названию или слагу.
- Поле «Заголовок публикации»: Название, отображаемое пользователям в заголовке вкладки браузера и в шапке анкеты.
- Поле «URL (Адрес)» / Slug: Уникальная строка латиницей (например,
anketa-2026). Итоговая ссылка на форму:https://domain/f/anketa-2026. - Переключатель «Статус: Активно»: Если выключен, пользователям при попытке заполнения отобразится экран завершения приема ответов (Inactive Screen).
- История ревизий и Откат (Rollback): В нижней части карточки отображается таймлайн всех сохраненных версий с датой и автором. Клик по ревизии мгновенно загружает историческую версию формы в конструктор.
Административный список публикаций
Для администраторов доступен сквозной список «Публикации» со всеми анкетами платформы, включая созданные другими пользователями:
- Поиск: по названию публикации, слагу или названию формы.
- Фильтры: статус (активные/неактивные), тип доступа (публичные, приватные, по ролям) и владелец.
- Действия: переход к редактированию любой публикации, активация/деактивация; в таблице видны количество ответов и дата завершения приёма.
- Создатели без роли администратора видят в разделе «Основное» только свои публикации.
Раздел «Конструктор форм» Экран
Визуальный drag-and-drop редактор цифровых форм и интерактивных анкет.
Структура рабочей среды
- Левая палитра компонентов: Содержит базовые поля (Текст, Число, Чекбокс, Файлы) и разметку (Панели, Колонки). Перетащите их мышью в правую рабочую зону. Полный справочник всех компонентов — в руководстве конструктора.
- Рабочий холст: Отображает интерактивный макет будущей формы. При наведении на любой компонент доступна панель быстрых действий:
- Настройки: Открывает диалог с параметрами валидации, API-ключа и подсказок.
- Копировать: Клонирует поле со всеми его вложенными правилами.
- Вставить ниже: Вставляет ранее скопированный компонент.
- JSON: Прямое редактирование схемы поля (доступно в Продвинутом режиме).
- Переместить: Ручное перемещение компонента в другую позицию на холсте.
- Удалить: Удаляет компонент из схемы.
⚙️ Продвинутый режим (Advanced Mode)
Включается в разделе «Настройки». Позволяет опытным разработчикам настраивать кастомные формулы вычислений, JSONLogic, интеграцию с PDF и редактировать JSON схемы компонентов напрямую. Подробное руководство.
Раздел «Дизайн публикации» Экран
Управление внешним видом веб-страниц, отображаемых респондентам.
Возможности кастомизации
- Выбор готовых шаблонов (Ассетов): Быстрое подключение корпоративной шапки, подвала или экрана неактивности из централизованного справочника ассетов.
- Редактор кода (Ace Editor): Встроенный редактор с подсветкой синтаксиса HTML/CSS для написания собственного оформления.
- Панель живого предпросмотра (Preview Box): Рендерит верстку в реальном времени параллельно с вводом кода.
- Стилизация темы: Поддержка светлой темы (Corporate Light) и высококонтрастной темной темы (Dark Enterprise).
Встраивание формы на другой сайт
Публикацию можно встроить как фрейм на внешний сайт — например, на корпоративный портал, чтобы респонденты заполняли анкету, не покидая привычный сайт.
- На вкладке «Дизайн» включите переключатель «Разрешить встраивание формы на внешние сайты» в карточке «Встраивание (Embed)».
- Укажите разрешённые домены — по одному в строке в формате
https://www.ktz.kz. Форму можно встроить только на сайт, чей домен есть в этом списке (защита от встраивания на произвольные ресурсы через CSPframe-ancestors), до 10 доменов. - Нажмите «Сохранить дизайн» — настройка вступает в силу через несколько секунд.
- Скопируйте готовый код для встраивания кнопкой «Копировать код» и передайте его владельцу сайта. Код содержит фрейм и скрипт автоматической подгонки высоты.
Со стороны сайта-хоста больше ничего не нужно: разработчик просто вставляет полученный код на страницу — ключи, токены и регистрация не требуются. Собственный фрейм по адресу формы тоже сработает, но без скрипта из сниппета высоту придётся задать фиксированной. Важно соблюдать порядок: домен сайта должен оказаться в списке до публикации кода на их стороне, иначе браузер заблокирует фрейм.
Ограничения:
- Формы с ролевым доступом тоже встраиваются: внутри фрейма появится кнопка «Войти», вход откроется в отдельном окне (брендированная страница единого входа), после входа форма загрузится автоматически — без перезагрузки страницы сайта-хоста.
- Формы с обязательной подписью (NCALayer) во фрейме могут не получить доступ к программе подписи из-за браузерных ограничений (Private Network Access). В этом случае форма сама предложит «Открыть в новой вкладке» — в отдельной вкладке подпись работает. Проверяйте на целевом сайте.
- Если флаг включён, но список доменов пуст, встраивание запрещено — форма по-прежнему защищена от помещения во фрейм.
Модульный брендинг & White-label (КТЖ Forms) Платформа
Архитектура брендирования платформы под корпоративного заказчика по модели Co-branding / White-label («Powered by SuraqHub»).
Концепция «КТЖ Forms by SuraqHub»
Для корпоративного внедрения в АО «НК «ҚТЖ» платформа развернута в ко-брендинговом исполнении: для сотрудников и подразделений система позиционируется как доверенный внутренний сервис «КТЖ Forms» с указанием платформенного ядра «by SuraqHub».
- Без форков и дублирования кода: единая кодовая база SuraqHub обслуживает как стандартные установки, так и брендированные инстансы заказчиков.
- Конфигурация на лету: параметры брендинга управляются через Kubernetes ConfigMap (
suraqhub-frontend-env) и файл конфигурацииenv.js. - Zero Downtime & Мгновенное обновление: файл конфигурации защищён заголовками
no-cacheи монтируется как том, изменения вступают в силу без пересборки Docker-образа.
Где применяется брендинг
| Элемент интерфейса | Отображение для КТЖ | Параметр в конфигурации |
|---|---|---|
| Вкладка браузера (Title) | КТЖ Forms by SuraqHub | Корпоративная система форм |
PAGE_TITLE / APP_NAME |
| Фавикон во вкладке | Фирменная иконка КТЖ в тёмном контейнере (ktz-icon.svg) |
FAVICON_URL |
| Заставка загрузки (Preloader) | Логотип КТЖ, заголовок КТЖ Forms и бейдж powered by SuraqHub |
LOADER_BADGE, POWERED_BY |
| Шапка панели (Header) | Векторная эмблема КТЖ + название КТЖ Forms + бейдж powered by SuraqHub |
LOGO_URL, APP_NAME |
| Экран входа (Login Gate) | Логотип КТЖ, заголовок КТЖ Forms, плашка powered by SuraqHub и подсказка учетной записи |
LOGIN_HINTS (ru/kk/en) |
| Окно проверки сессии | Логотип КТЖ, заголовок КТЖ Forms, кнопка возврата |
APP_NAME |
| Корпоративная палитра | Основной синий акцент КТЖ (#0066b2) в CSS-токенах |
PRIMARY_COLOR |
Пример конфигурации в env.js
window.APP_CONFIG = {
AUTH_SERVER_URL: 'https://auth.ktz.dostyq.app',
AUTH_REALM: 'SuraqHub',
AUTH_CLIENT_ID: 'suraqhub-api',
BRANDING: {
APP_NAME: "КТЖ Forms",
POWERED_BY: "powered by SuraqHub",
PAGE_TITLE: "КТЖ Forms powered by SuraqHub | Корпоративная система форм",
LOADER_BADGE: null, // или "АО «НК «ҚТЖ»" при необходимости дополнительного префикса
LOGIN_HINTS: {
ru: "Корпоративная учётная запись ҚТЖ",
kk: "ҚТЖ корпоративтік тіркелгісі",
en: "KTZ Corporate Account"
},
LOGO_URL: "/static/ktz-emblem.svg",
FAVICON_URL: "/static/ktz-icon.svg",
PRIMARY_COLOR: "#0066b2",
COPYRIGHT: "© 2026 АО «НК «Қазақстан темір жолы» • На платформе SuraqHub"
}
};
Раздел «Переводы» (Локализация) Экран
Обеспечивает мультиязычность анкет для русскоязычной, казахскоязычной и международной аудитории.
Как работает локализация
- При переходе на вкладку система автоматически парсит текущую схему формы и находит все текстовые строки: метки полей, подсказки (placeholder), описания и тексты ошибок.
- В интерактивной таблице выводятся столбцы для языков: Русский (RU), Казахский (KK) и Английский (EN).
- Экспорт в CSV: Вы можете выгрузить таблицу в файл для передачи профессиональным переводчикам.
- При заполнении анкеты респондент выбирает удобный язык в переключателе, и все вопросы формы мгновенно переводятся без перезагрузки страницы.
Раздел «Справочники (НСИ)» Экран
Централизованное ведение нормативно-справочной информации: списки подразделений, регионов, категорий и других значений, которые используются в выпадающих списках форм.
Реестр и редактор справочников
- Реестр справочников: таблица всех справочников со статусом, прод-версией и датой обновления. Новый справочник создается кнопкой «Создать справочник».
- Встроенный редактор: табличное редактирование записей — добавление строк, живой поиск по таблице, редактирование двойным кликом по ячейке.
- Импорт и экспорт: массовая загрузка значений из Excel/CSV, выгрузка текущего черновика в Excel, вставка строк из буфера обмена (
Ctrl+Cв Excel → клик по таблице →Ctrl+V). - Черновик и публикация: правки сохраняются в черновик кнопкой «Сохранить черновик»; «Опубликовать» делает черновик прод-версией, из которой формы читают значения.
- Внешние справочники: в строке справочника с иконкой облака отображается статус последней синхронизации, а кнопка-молния запускает синхронизацию вручную.
Внешние справочники (автосинхронизация)
Справочник может получать значения из внешнего источника автоматически: платформа сама забирает данные (server-to-server), приводит их к контракту справочника и публикует новую прод-версию — только если данные действительно изменились. Типовой сценарий — транспортные справочники внешнего онтологического API (станции, категории поездов), ведение которых выполняется внешней системой.
- Настройка: кнопка-облако в строке справочника открывает карточку источника — URL ресурса, пароль/креды (Basic), трансформер (маппинг полей), переменная окружения (альтернатива паролю), интервал обновления в минутах, вкл/выкл.
- Ручная синхронизация: кнопка-молния в строке реестра (или в карточке источника) запускает внеочередное обновление сразу, не дожидаясь интервала.
- Журнал обновлений: в карточке источника виден журнал последних попыток — время, статус, HTTP-код, сколько записей получено и изменено, какая ревизия опубликована.
- Ревизии и консистентность: каждое изменение источника фиксируется как новая неизменяемая ревизия справочника с метаданными версии внешнего набора данных. Формы продолжают читать значения даже при недоступности внешнего источника — используется последняя опубликованная версия. Ручное редактирование черновика внешнего справочника заблокировано: следующий синк его перезапишет.
- Откат: к любой прошлой ревизии можно мгновенно вернуться через историю публикаций — так же, как для обычных справочников.
Автозаполнение полей по пользователю (префилл)
Поля формы могут заполняться автоматически из профиля пользователя, который её открыл: ФИО — из учётной записи (Keycloak), объекты (участки, станции) — из персональных назначений, которые ведутся во вкладке «Назначения».
- Как работает: у поля формы включается свойство
prefill— при открытии формы значение подставляется из профиля (ФИО при этом блокируется от правки), а варианты выпадающих списков фильтруются до назначенных пользователю объектов. - Гарантия на сервере: при отправке анкеты сервер проверяет данные независимо от браузера — ФИО всегда перезаписывается значением из учётной записи, а выбор объектов сверяется с назначениями. Подменить значение через DevTools невозможно.
- Если назначений нет: список объектов остаётся полным (режим fallback), а выбор пользователя помечается как ручной. Такие значения попадают во вкладку «Назначения» как кандидаты — администратор одобряет их, и со следующего рапорта поля заполняются автоматически.
- Вкладка «Назначения»: выдача объектов вручную (поиск пользователя по email), список активных назначений и кандидатов, одобрение и удаление. Кандидаты создаются автоматически из сабмитов, где пользователь выбрал объект вручную.
🔐 Безопасность внешних источников:
Пароль указывается отдельно для каждого справочника и хранится в защищенной таблице (как у вебхуков); интерфейс никогда не показывает его повторно и позволяет только заменить или удалить. Альтернатива — переменная окружения сервиса: в карточке указывается лишь имя переменной, а её значение не попадает в базу и интерфейс.
💡 Подключение справочника к форме:
В выпадающем списке конструктора укажите тип источника данных «URL» и адрес словаря /api/v1/dictionaries/{код}. При обновлении справочника форма подхватит новые значения автоматически — новая ревизия формы не требуется. Пошаговый рецепт — в разделе Практические сценарии руководства конструктора.
🔐 Доступ:
Вкладка доступна ролям admin и dictionary_manager — см. карточку «Роли и права доступа» в разделе Безопасность.
Раздел «Предпросмотр» Экран
Интерактивная среда для верификации готовой анкеты перед публикацией.
Экран рендерит точную копию боевого интерфейса респондента со всеми подключенными стилями, шрифтами, шапкой и подвалом. Позволяет протестировать отправку формы, обязательные поля, маски телефонов, прикрепление файлов и логику ветвления вопросов.
Раздел «Отчетность и Аналитика» Экран
Инструменты для визуализации данных и выгрузки собранных ответов.
Возможности аналитики
- Счетчики в реальном времени: Общее количество отправленных анкет (сабмишнов) и дата последнего ответа.
- График «Динамика ответов»: Временная шкала заполнения анкеты по дням.
- Географическая карта ответов: Интерактивная карта Казахстана с кластеризацией точек отправки анкет (для форм, собирающих геолокацию).
- Детализация по полям: Выберите один или несколько вопросов из выпадающего списка — система автоматически построит круговые и столбчатые диаграммы распределения вариантов ответов.
- Асинхронный экспорт в Excel (XLSX): При нажатии кнопки «Скачать Excel» задача передается воркерам RabbitMQ. Готовый отчет скачивается мгновенно, не блокируя работу интерфейса.
Раздел «Настройки системы» Экран
Параметры безопасности, антивируса и обслуживания платформы.
Системные параметры
- Максимальный размер загрузки: Ограничение размера файлов (в МБ), разрешенных к прикреплению в формах.
- Часовой пояс платформы: Определяет корректный расчет таймстемпов в аналитике и выгрузках Excel.
- Языки переводов форм: Управляет языками, доступными на вкладке «Переводы» и в опубликованных формах. Русский язык остаётся основным; казахский, кыргызский, английский и узбекский можно включать и выключать.
- Антивирусный сканер (ClamAV): Включение проверки файлов на вирусы и адрес сервиса.
- Справочник ролей Keycloak: Сопоставление системных ролей платформы (Admin, Creator, Viewer) с токенами Keycloak.
- Пакет диагностики: Формирует единый архив с логами микросервисов, состоянием очередей RabbitMQ и очередью ошибок DLQ для быстрой технической поддержки.
Панель «Состояние системы»
В разделе «Обслуживание» показываются живые параметры инфраструктуры. Панель обновляется кнопкой «Обновить» и при каждом открытии вкладки. Как читать показатели:
| Параметр | Норма и тревожные признаки |
|---|---|
| Рабочие очереди (form_submissions, templates.v1, publications.modular, reports.tasks, files.quarantine) | Глубина 0 — норма (рост на несколько сообщений на секунды допустим при пиковой нагрузке). Консьюмеров должно быть ≥ 1. Тревога: глубина растёт и не опускается либо консьюмеров 0 — обработчик упал или недоступна БД. |
| Retry-очереди (submissions_retry_queue и аналогичные) | Глубина 0 в спокойном состоянии; единицы сообщений — норма (повторы с задержкой). Консьюмеров 0 — норма: это парковка с таймером, их читает сам брокер по таймауту. |
| Очереди ошибок (DLQ) (dead_letter_queue, webhooks.failed, reports.failed) | Норма — строго 0. Любое значение больше нуля — сигнал разбираться: DLQ не разгружается сама. Строки подсвечиваются красным. |
| RabbitMQ / База данных / Redis | Зелёная отметка — компонент доступен. Красный крест — сервис недоступен; при наведении показывается причина. |
| Анкет за час / за 24 часа | Должно соответствовать ожидаемому трафику. Ноль при активном трафике — критичный признак: ответы заполняющих не сохраняются. |
| Записей идемпотентности | Монотонный рост — норма (защита от дублей). Десятки тысяч записей без чистки замедляют обработку — вопрос к администратору БД. |
| Активных webhook-подписок | Сколько подписок реально получают события. Ноль — события никуда не отправляются (проверьте вкладку «Интеграции»). Подписка с постоянно падающей доставкой копит ошибки в webhooks.failed. |
💡 Короткое правило
Рабочие очереди: 0 — хорошо, консьюмеры — обязательны. Retry: ноль и консьюмеров ноль — нормально. DLQ: только ноль. Счётчик анкет стоит на нуле, а люди заполняют формы, — срочно смотреть логи savetodb.
API-ключи (M2M Integration & GraphQL) Интеграции
Синхронный доступ внешних BI/ETL систем (PowerBI, Tableau, корпоративные CRM) к аналитике и выгрузкам без интерактивного входа через Keycloak.
Безопасность API-токенов
- Префикс
whsec_: Токен генерируется криптографически стойким генератором и выводится только один раз при создании. - Хэширование SHA-256: В БД платформы сохраняется только хэш токена. Даже в случае компрометации базы исходный ключ восстановить невозможно.
- Ограничение видимости (Scopes): Ключ можно сделать глобальным либо ограничить доступом только к выбранным публикациям.
Пример GraphQL-запроса через cURL
curl -X POST https://suraqhub.domain.com/graphql \
-H "Content-Type: application/json" \
-H "X-API-Key: whsec_your_secret_api_key_here" \
-d '{
"query": "query GetPubStats($id: UUID!) { publicationStats(publicationId: $id) { totalSubmissions lastSubmissionDate } }",
"variables": { "id": "16a5ff0e-f1ff-4b8a-9887-c5f907912ea1" }
}'
Вебхуки в реальном времени (Webhooks) Real-Time
Асинхронная отправка HTTP POST уведомлений на ваши серверы при наступлении событий в SuraqHub.
Типы событий:
submission.created— пользователь заполнил и успешно отправил форму.form.saved— изменена или сохранена структура вопросов формы.publication.saved— изменена или активирована публикация.
Спецификация JSON Payload:
{
"event": "submission.created",
"event_id": "9f1c2d3e-4b5a-6c7d-8e9f-0a1b2c3d4e5f",
"timestamp": "2026-09-02T15:30:00.000Z",
"publication_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"form_id": "f5e4d3c2-b1a0-9876-5432-10fedcba9876",
"submission_id": "77aa88bb-99cc-00dd-11ee-22ff33aa44bb",
"data": {
"fullName": "Алексей Смирнов",
"phoneNumber": "+77015554433",
"score": 5,
"comment": "Отличная скорость работы!"
}
}
Проверка подписи HMAC-SHA256 (Заголовок X-SuraqHub-Signature)
Каждый запрос подписывается вашим секретом подписки. Сервер-приемник обязан проверить подпись перед обработкой:
Пример на Python (FastAPI / Flask):
import hmac, hashlib
from fastapi import FastAPI, Request, HTTPException, Header
app = FastAPI()
WEBHOOK_SECRET = "whsec_your_secret_key"
@app.post("/webhook")
async def receive_webhook(request: Request, x_suraqhub_signature: str = Header(None)):
raw_body = await request.body()
expected = hmac.new(WEBHOOK_SECRET.encode("utf-8"), raw_body, hashlib.sha256).hexdigest()
if not x_suraqhub_signature or not hmac.compare_digest(expected, x_suraqhub_signature):
raise HTTPException(status_code=403, detail="Invalid HMAC signature")
payload = await request.json()
print(f"✅ Успешно получено событие {payload['event']}")
return {"status": "ok"}
Гарантии надежности (SRE Retry Policy):
- Manual ACK: Сообщение подтверждается в RabbitMQ только после получения от вашего сервера HTTP-кода
200 OK. - Экспоненциальный Retry: При сетевой ошибке или коде
5xxплатформа повторяет отправку до 5 раз с увеличивающимся интервалом. - Dead Letter Queue (DLQ): При фатальных ошибках (
404,403) сообщение безопасно сохраняется в очереди бракаsuraqhub.webhooks.failedдля ручного анализа.
Аналитика для BI (схема analytics)
Pull / BI
Прямое подключение Power BI (и любого инструмента с PostgreSQL-коннектором) к выделенной read-only схеме базы данных для построения дэшбордов и отчетов по накопленным анкетам.
Чем этот канал отличается от вебхуков и API-ключей:
- Вебхуки — мгновенные push-уведомления для систем-автоматизаций (реакция на событие за секунды).
- API-ключи — синхронные запросы к GraphQL API для внешних сервисов (детали конкретной анкеты, бизнес-логика).
- Схема
analytics— история для человека: дэшборды, воронки, сводные отчеты в Power BI с обновлением по расписанию.
Модель данных:
vw_submissions— шапки анкет: когда, какая публикация, язык, наличие подписи. Без содержимого ответов.vw_submission_answers— ответы в «длинном» формате (одна строка = один ответ). Универсален для любых форм: в Power BI разворачивается в широкую таблицу сводной таблицей (Pivot).vw_submission_geo— координаты устройств (широта, долгота, точность) для форм, собирающих геолокацию.vw_publications— справочник публикаций: названия, политики отправки, подписи и геолокации, периоды активности.
Безопасность и приватность:
- Подключение выполняется под выделенной read-only ролью
powerbi_reader, которой доступна только схемаanalytics. Служебные таблицы платформы (API-ключи, подписки, аудит) роли недоступны. - Персональные данные не отдаются: ИИН, криптографические подписи и сырые метаданные в вью не включены.
- Запись невозможна по определению — роль имеет только право чтения.
Подключение:
В Power BI Desktop: Получить данные → PostgreSQL, укажите адрес сервера и базы данных suraqhub, авторизация — под учетной записью powerbi_reader (выдается администратором платформы). Для опубликованных дэшбордов добавьте тот же источник в локальный Data Gateway.
Для развертываний с высокой нагрузкой платформа предусматривает read-only реплику БД: администратор может направить аналитические отчеты и BI-подключения на копию базы (DATABASE_RO_URL), оставив основную базу только для приема анкет. Подробности — в документе suraqhub-docs/analytics_powerbi.md.
Скачивание файлов и медиа (FileConductor API) File API
Безопасное программное и пользовательское скачивание вложений (фотографий, видеозаписей, сканов), прикрепленных респондентами в формах.
1. Как файлы передаются во внешние системы
При получении вебхука submission.created или выгрузке отчетов в Excel/CSV, вложения представлены массивом объектов внутри submission_data:
{
"event": "submission.created",
"submission_id": "123e4567-e89b-12d3-a456-426614174000",
"submission_data": {
"media_field": [
{
"file_id": "c0378e90-f99a-4c28-bb8d-d602ff59187a",
"originalName": "photo_bridge.jpg",
"size": 2450123,
"type": "image/jpeg",
"url": "/api/files/download/c0378e90-f99a-4c28-bb8d-d602ff59187a"
}
]
}
}
Каждый файл идентифицируется постоянным UUID (file_id) и содержит относительный URL для загрузки.
2. Способы аутентификации
Эндпоинт /api/files/download/{file_id} защищен и поддерживает следующие способы авторизации:
- M2M API-ключ (рекомендуется для скриптов/ETL): передается в заголовке
X-API-Key: whsec_...или параметром URL?api_key=whsec_.... Ключи создаются во вкладке «Интеграции» менеджера. - Keycloak Bearer JWT (для внутренних сервисов): передается в заголовке
Authorization: Bearer <token>или параметром?token=<token>.
3. Режимы скачивания
А. Прямой редирект (HTTP 302) — для браузеров и утилит
При передаче параметра ?redirect=true (или переходе из браузера) шлюз FileConductor мгновенно перенаправляет клиента (HTTP 302) на S3 Presigned URL с корректным заголовком Content-Disposition. Файл сразу скачивается с его оригинальным именем (например, photo_bridge.jpg):
# Пример скачивания через cURL с сохранением оригинального имени:
curl -L -O -J -H "X-API-Key: whsec_your_key_here" \
"https://suraqhub.dostyq.app/api/files/download/c0378e90-f99a-4c28-bb8d-d602ff59187a?redirect=true"
Б. JSON-режим (по умолчанию) — для двухэтапной интеграции
Без флага redirect=true эндпоинт возвращает JSON с метаданными и временной подписанной ссылкой на S3 (срок жизни 15 минут):
GET /api/files/download/c0378e90-f99a-4c28-bb8d-d602ff59187a
X-API-Key: whsec_your_key_here
Ответ:
{
"status": "success",
"file_id": "c0378e90-f99a-4c28-bb8d-d602ff59187a",
"filename": "photo_bridge.jpg",
"download_url": "https://s3.ktz.dostyq.app/suraqhub-clean/c0378e90-...?X-Amz-Signature=..."
}
4. Примеры интеграции
Python (requests / httpx)
import requests
FILE_URL = "https://suraqhub.dostyq.app/api/files/download/c0378e90-f99a-4c28-bb8d-d602ff59187a"
HEADERS = {"X-API-Key": "whsec_your_secret_api_key"}
# Вариант 1: Прямое скачивание с редиректом
response = requests.get(f"{FILE_URL}?redirect=true", headers=HEADERS, stream=True)
if response.status_code == 200:
with open("downloaded_media.jpg", "wb") as f:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
print("✅ Файл успешно сохранен!")
# Вариант 2: Получение метаданных и presigned URL
meta_resp = requests.get(FILE_URL, headers=HEADERS).json()
print("Имя файла:", meta_resp["filename"])
print("S3 ссылка:", meta_resp["download_url"])
Node.js / JavaScript (fetch)
const fs = require('fs');
const { pipeline } = require('stream/promises');
async function downloadFile(fileId, apiKey) {
const url = `https://suraqhub.dostyq.app/api/files/download/${fileId}?redirect=true`;
const res = await fetch(url, {
headers: { 'X-API-Key': apiKey }
});
if (!res.ok) throw new Error(`Download failed: ${res.statusText}`);
await pipeline(res.body, fs.createWriteStream('downloaded_media.jpg'));
console.log('✅ Файл успешно загружен');
}
🛡️ Политики безопасности и роль suraqhub_downloader
- Роль Keycloak: в системе заведена специализированная роль
suraqhub_downloader(Право на скачивание файлов и медиавложений). Вы можете назначить её доверенным сотрудникам или сервисному аккаунту внешней системы и выбрать в «Настройках системы». Администраторы (suraqhub_admin) имеют доступ к скачиванию всегда. - Антивирусный карантин: файл невозможно скачать до тех пор, пока служба ClamAV не присвоит ему статус
CLEAN. При попытке скачать зараженный файл возвращается ошибка403 Forbidden. - Управление доступом: в «Настройках системы» администратор может включить/отключить скачивание по M2M API-ключам и выбрать требуемую роль.
Выгрузка отчетов в собственное S3-хранилище Storage
Возможность сохранять сгенерированные отчеты напрямую в корпоративный бакет AWS S3, MinIO или Ceph.
🔒 Сквозное шифрование Fernet
Реквизиты доступа к вашему S3 (Access Key, Secret Key) на лету шифруются алгоритмом Fernet при вызове GraphQL-мутации createReport и расшифровываются исключительно внутри изолированного фонового воркера.
Безопасность, ClamAV и Доступность Security
🛡 Антивирусный барьер ClamAV
Файлы пользователей не сохраняются напрямую в общую файловую систему. Они проходят автоматическую проверку через изолированный демон ClamAV. Зараженные файлы блокируются до того, как они смогут попасть к операторам или в выгрузки.
🔐 Content Security Policy (CSP)
Интерфейс SuraqHub спроектирован по стандарту строгого CSP: исключены unsafe-inline скрипты, все события вынесены в модульные слушатели, что предотвращает XSS-атаки и кражу сессий.
♿ Доступность интерфейса (WCAG 2.2 AA)
Формы полностью доступны для людей с ограниченными возможностями: поддерживается навигация с клавиатуры, семантические WAI-ARIA атрибуты (aria-live, role="region"), экранные дикторы (Screen Readers) и контрастные цветовые палитры.
👥 Роли и права доступа
Роли назначаются администратором в Keycloak Admin Console; внутри платформы ведется read-only обзор пользователей:
- admin — полный доступ: настройки системы, интеграции, справочники, все публикации и отчёты;
- creator — создание форм и работа только со своими публикациями и отчётностью по ним;
- dictionary_manager — ведение справочников (НСИ) без прав создателя;
- suraqhub_downloader — право скачивать файлы и медиавложения через File API (см. Скачивание файлов).
Каждая публикация, кроме того, имеет уровень доступа: Public (доступна всем по ссылке) или Role Based (доступ только пользователям с выбранными ролями Keycloak). Периодическая отчётность доступна только в режиме Role Based.
Часто задаваемые вопросы (FAQ) База знаний
2. Убедитесь, что ваш сервер возвращает HTTP-код
200 OK.3. Проверьте правильность валидации подписи
X-SuraqHub-Signature с вашим секретом подписки.4. Скачайте пакет диагностики на экране «Настройки» для анализа очереди
suraqhub.webhooks.failed.
Периодическая отчётность
В «Настройках заполнения» можно включить ежедневную, еженедельную или ежемесячную отчётность. Эта настройка доступна только для публикаций с доступом Role Based.
- Продолжать текущий отчёт: при повторном открытии в том же периоде показывается последняя отправка; новая отправка сохраняется отдельной версией.
- Один раз: в периоде допускается одна отправка.
- Повторное заполнение: каждая отправка самостоятельна.
Начальные данные нового периода можно оставить пустыми или скопировать из прошлого периода. Эта настройка применяется только при первом открытии формы в новом периоде. Подробности для разработчиков: docs/periodic-reporting.md.