Skip to content

Поля и валидация ​

Страница фиксирует фактическую серверную валидацию входных данных на 15 июля 2026 года. Источник истины — HTTP DTO в internal/modules/*/transport_http.go, общие правила из internal/transport/validation.go и дополнительные проверки сервисов.

IMPORTANT

Метка «не готово» означает, что API принимает поле, но не проверяет важный формат, диапазон, длину или допустимый набор значений. Это не описание желаемого поведения, а перечень текущих технических пробелов.

Как читать таблицы ​

МеткаЗначение
✅Основная проверка поля реализована
🟡Проверка есть, но покрывает поле не полностью или отличается между API
🔴Предметная валидация не готова; работает только JSON-тип или проверка БД

Общие правила всех JSON-запросов:

  • неизвестные поля отклоняются (DisallowUnknownFields);
  • неверный JSON-тип возвращает validation_error с указанием поля;
  • required проверяет присутствие/ненулевое значение, а notblank — строку после TrimSpace;
  • идентификаторы с правилом gt=0 должны быть положительными;
  • omitempty означает, что поле можно не передавать; если оно передано, остальные правила применяются;
  • денежный тип money.Money принимает JSON-число или строку с числом и округляет до 2 знаков. Знак и верхняя граница проверяются только там, где это отдельно делает сервис.

Подсказки под полем ​

Фронтенд показывает details[].message прямо под полем формы, поэтому это короткая русская подсказка без кодов полей и значений. Правила валидатора (internal/transport/validation.go, validationMessage) дают:

ПравилоПодсказка
required, notblank, gt=0 у строки или списка«Обязательное поле»
min / gte, max / lte у строки«Не короче 3 символов» / «Не длиннее 200 символов»
min / gte, max / lte у числа«Не меньше 3» / «Не больше 1000»
min, max у списка«Не меньше 2 элементов» / «Не больше 10 элементов»
gt, lt у числа«Больше 0» / «Меньше 24»
len«Ровно 9 символов»
email«Некорректная почта»
phone«Некорректный телефон»
inn / kpp«ИНН — 10 или 12 цифр» / «КПП — 9 цифр»
http_url«Ссылка должна начинаться с http:// или https://»
oneof и прочие правила«Недопустимое значение» (коды значений не перечисляются)
datetime=2006-01-02, даты в параметрах«Дата в формате ГГГГ-ММ-ДД»
неизвестное поле / неверный JSON-тип«Неизвестное поле» / «Неверный тип значения»

Ручные проверки в обработчиках и сервисах (transport.NewFieldError, (*apperr.Error).WithField, apperr.WithDetail) пишут подсказки в том же стиле; общие тексты — константы transport.Hint*. Правила текста проверяют тесты: internal/transport/field_hints_test.go прогоняет validationMessage по всем правилам, которые встречаются в DTO, а internal/app/error_texts_test.go — details всех зарегистрированных ошибок и все литералы подсказок в исходниках (см. Ошибки API).

Общие форматы ​

ФорматФактическое правилоСостояние
emailстандартная проверка validator/v10✅
phone+, цифры, пробелы, (), -; от 7 до 20 символов🟡 Нет нормализации и проверки реального телефонного плана
innровно 10 или 12 цифр🟡 Контрольные суммы не проверяются
kppровно 9 цифр🟡 Структура КПП не проверяется
http_urlабсолютный URL со схемой http или https✅
датагде указано — строго YYYY-MM-DD✅
дата-времягде указано — RFC 3339✅
Moneyчисло/числовая строка, округление до копеек🟡 Сам тип не запрещает отрицательные и очень большие суммы

Пользователи и авторизация ​

ПоляФактическая валидацияСостояние
emailобязательно, формат email✅
password при входеобязательно, без ограничения длины🔴 Не готов лимит длины
password при регистрации /auth/registerобязательно, минимум 6 символов🟡 Не совпадает с правилом создания пользователя
password при создании пользователя8–128 символов, не только пробелы✅
new_password при сбросеобязательно, минимум 6 символов🟡 Не совпадает с правилом создания пользователя
refresh_token, tokenобязательно🟡 Нет ограничения длины
full_nameесли передано: 2–150 символов, не только пробелы✅
first_name, last_name, middle_nameдо 80 символов; при создании не только пробелы🟡 При обновлении профиля пустые/пробельные значения допустимы
ФИО целикомтребуется full_name либо набор частей имени✅ Проверяется отдельным правилом
roleобязательно при создании, не пусто; существование роли проверяет сервис✅
department_id, department_ids[]каждый ID больше 0✅
phone, phone_workобщий формат телефона🟡 См. ограничения формата phone
bio, job_title, location, telegramмаксимум 500 / 100 / 100 / 50 символов🟡 Пробельные строки допустимы
timezoneтолько строковый тип🔴 Не готова проверка IANA timezone
show_in_directory, notification_preferences, is_activeтолько JSON-тип/структура🟡 Для настроек уведомлений нет полного набора предметных ограничений

CRM: компании, контакты и реквизиты ​

Модуль и поляФактическая валидацияСостояние
Компания: nameобязательно, 2–200 символов, не только пробелы✅
Компания: legal_nameдо 200, не только пробелы✅
Компания: inn, kpp10/12 цифр и 9 цифр соответственно🟡 Без контрольных сумм
Компания: ogrnне пусто, максимум 15 символов🔴 Не готовы точная длина, только цифры и контрольная сумма
Компания: typeне пусто, максимум 100🔴 Нет справочника допустимых типов
Компания: address, director_name, director_titleмаксимум 500 / 200 / 200, не только пробелы✅
Компания: email, phone, websiteemail / телефон / HTTP(S) URL✅
Компания: notes, manager_idдо 2000; ID больше 0✅
Контакт: company_idID больше 0✅
Контакт: first_name, last_nameдо 100, не только пробелы; сервис требует хотя бы одно имя✅
Контакт: email, phoneemail / телефон; сервис требует хотя бы один канал связи✅
Контакт: position, notesдо 150 / 2000, не только пробелы✅
Связь компании и контакта: contact_id, roleID больше 0; роль до 100 и не пустая✅
Реквизиты: owner_typeобязательно, только непустая строка🔴 Не готов список допустимых владельцев
Реквизиты: owner_idобязательно, больше 0✅
Реквизиты: name, legal_nameдо 200 / 500, не только пробелы✅
Реквизиты: inn, kppсервис проверяет 10/12 цифр и 9 цифр соответственно🟡 Проверка есть не в DTO и не включает контрольные суммы
Реквизиты: ogrnне пусто, максимум 15🔴 Нет проверки цифр, длины и контрольной суммы
Реквизиты: bik, account, corr_accountБИК — 9 цифр; счета — 20 цифр; р/с не начинается с 301, к/с начинается с 301; контрольный ключ по БИК и весам 7,1,3✅
Реквизиты: email, phoneemail / общий формат телефона✅
Реквизиты: vat_mode, vat_ratenone/included/on_top; ставка 0–100✅
Банковский счет: name, bank_nameдо 200 / 500, не только пробелы✅
Банковский счет: bikсервис требует ровно 9 цифр✅
Банковский счет: bank_inn, bank_kpp, account, corr_accountИНН/КПП пока проверяются базово; счета — 20 цифр, тип р/с/к/с и контрольный ключ проверяются общим валидатором по БИК🟡 Для ИНН/КПП банка нет контрольных сумм
Банковский счет: bank_addressне только пробелы🟡 Нет максимальной длины
Поставщик: nameобязательно; сервис отсекает пробельную строку🟡 Нет максимальной длины
Поставщик: email, innсервис проверяет email и ИНН из 10/12 цифр🟡 Для ИНН нет контрольной суммы
Поставщик: phone, kpp, notesстроки нормализуются, но формат и длина не проверяются🔴 Валидация не готова

Проекты, задачи и команда ​

Модуль и поляФактическая валидацияСостояние
Проект: nameобязательно, 2–200, не только пробелы✅
Проект: descriptionдо 2000🟡 Пробельная строка допустима
Проект: event_categoryexhibition, conference, presentation, meeting, forum, webinar, training, corporate_event, other✅
Проект: company_id, contact_id, location_id, department_id, manager_idпереданный ID больше 0; дополнительно требуется клиент и отдел по бизнес-правилам✅
Проект: statusplanned/estimating/approved/in_progress/done/closed/cancelled✅
Проект: payer_requisite_idдопускается 0 или положительный ID🟡 Ноль используется как специальное значение; контракт не объясняет его отдельно
Проект: vat_mode, vat_ratenone/included/on_top/inherit; 0–100✅
Спецификация: file_id, комментарий отказаID больше 0; комментарий обязателен, до 2000, не пустой✅
Задача: project_id, assignee_id, co_assignee_ids[]положительные ID✅
Задача: title, descriptionзаголовок 3–200; описание до 5000; не только пробелы✅
Задача: statustodo/in_progress/blocked/done/cancelled✅
Задача: planned_hours, spent_hoursбольше 0 и не более 1000✅
Задача: due_dateYYYY-MM-DD✅
Комментарий задачи: bodyобязательно, 1–4000, не только пробелы✅
Учет времени: project_id, user_idположительные ID✅
Учет времени: task_idтолько JSON-тип🔴 Не готово правило gt=0
Учет времени: date, hours, commentYYYY-MM-DD; часы (0;24]; комментарий до 2000✅
Заявка на команду: itemsобязательный массив🟡 Не проверяется минимальное число элементов
Заявка на команду: department_id, role_coderequired, но ID не проверяется на >0, код — на непустоту/справочник🔴 Валидация не готова
Заявка на команду: preferred_employees[], assignee_idтолько JSON-тип🔴 Не проверяются положительные ID
Заявка на команду: statusобязательно и не пусто🔴 Нет списка допустимых статусов
Команда проекта: project_id, user_idrequired, но без gt=0🟡 Путь проверяется как число, тело — слабее
Команда проекта: role_in_project, role_codes[], hourly_rate, reasonтолько JSON-тип🔴 Не готовы справочники, длины и неотрицательная ставка
Команда проекта: sourceдопустимость проверяется отдельным парсером✅
Секционное разрешение: permissionобязательно; допустимость проверяет сервис✅

Оборудование, локации, логистика и командировки ​

Модуль и поляФактическая валидацияСостояние
Оборудование: name, categoryобязательно; сервис отсекает пробелы🟡 Нет максимальной длины
Оборудование: location_id, supplier_id, project_idположительные ID✅
Оборудование: cost / unit_costсервис запрещает отрицательное и конфликт двух полей✅
Оборудование: quantityбольше 0✅
Оборудование: status, unit, conditionсервис нормализует и проверяет поддерживаемые значения✅
Оборудование: identifier, broken_description, notesтолько JSON-тип🔴 Нет длины/непустоты
Локация: nameобязательно; сервис отсекает пробелы🟡 Нет максимальной длины
Локация: typeсервис проверяет city/warehouse/venue/office/client_site/other✅
Локация: latitude, longitude, manager_id[-90;90], [-180;180], ID больше 0✅
Локация: contact_phoneтолько строковый тип🔴 Не используется валидатор телефона
Локация: адреса, инструкции, контакты, часы, заметкисервис проверяет только непустоту части переданных строк🔴 Нет единых ограничений длины и форматов
Заявка на оборудование: name, request_kind, typeимя обязательно до 200; значения из фиксированных списков✅
Заявка: ID локаций/ответственного/оборудования/источникапереданные ID больше 0✅
Заявка: количества, дни аренды, ценабольше 0; цена неотрицательна✅
Заявка: items, item_ids, operationsмассив обязателен🟡 Не везде есть min=1 и dive, поэтому пустые массивы/невалидные элементы могут пройти transport-слой
Заявка: planned_departure, planned_arrivalстроки без transport-формата🟡 Часть сценариев проверяет RFC 3339 глубже, единое правило отсутствует
Логистика: nameобязательно🟡 Нет notblank и максимальной длины при создании
Логистика: status, transport_typeстрока без oneof в DTO🔴 Нет единого списка на transport-слое
Логистика: fulfillment_type, carrier_typeфиксированные списки есть только в части create/update сценариев🟡 Валидация непоследовательна
Логистика: ID проекта/локаций и количества в create/auto-createчасть полей только JSON-тип🔴 Не готовы gt=0 и проверки количества для всех сценариев
Логистика: даты движенияRFC 3339 разбирается обработчиком✅
Логистика: перевозчик, водитель, номера, адреса, заметкиограничения длины есть в update/plan, но не во всех create-сценариях🟡 Валидация непоследовательна
Командировка: все *_idпереданные ID больше 0✅
Командировка: status, transport_typeфиксированные списки✅
Командировка: адреса/цель/детали/проживание/заметкимаксимум 500 / 1000 / 500 / 500 / 2000; значимые поля не только пробелы✅
Командировка: датыRFC 3339; сервис проверяет порядок дат✅
Командировка: planned_cost, actual_costсервис запрещает отрицательные суммы✅

Финансы, договоры, бюджет и зарплата ​

Модуль и поляФактическая валидацияСостояние
Бюджет: markup_percent0–10000✅
Бюджет: usn_percent0–100✅
Бюджет: usn_display_mode, vat_display_modeseparate/included✅
Бюджет: notesтолько JSON-тип🔴 Нет ограничения длины
Статья затрат: project_id, categoryID больше 0; категория из фиксированного списка✅
Статья затрат: planned_amount, actual_amountсервис запрещает отрицательные суммы✅
Статья затрат: notesдо 2000✅
Платежный счет: name, kind, company_bank_account_idимя обязательно до 200; bank/cash; ID больше 0✅
Платежный счет: currencyдо 8 символов🔴 Нет ISO 4217/списка допустимых валют
Платеж: account_id, directionположительный ID; incoming/outgoing✅
Платеж: dateYYYY-MM-DD, если передано✅
Платеж: counterparty_type, counterparty_idcompany/contact/employee/none; ID больше 0, согласованность проверяет сервис✅
Платеж: method, statusфиксированные списки✅
Платеж: суммы и распределенияпарсятся как Money, сервис проверяет положительность и баланс распределений✅
Договор: numberобязательно, не пусто, до 200✅
Договор: counterparty_type, counterparty_idcompany/contact; ID больше 0✅
Договор: subject, notesдо 2000 / 4000🟡 Пробельные строки допустимы
Договор: signed_at, effective_from, effective_to, due_dateYYYY-MM-DD✅
Договор: state, тип связи, тип дедлайнафиксированные списки✅
Договор: amountчисловой Money, сервис запрещает отрицательную сумму🟡 Не готова верхняя граница
Профиль зарплаты: user_id, kindID больше 0; salary/hourly✅
Профиль зарплаты: base_amountчисловой Money, сервис запрещает отрицательное значение🟡 Ноль разрешен, верхняя граница не задана
Профиль зарплаты: effective_from, effective_toYYYY-MM-DD✅
Расчет зарплаты: periodсервис проверяет YYYY-MM✅
Выплата зарплаты: account_idположительный ID✅

Системные модули ​

Модуль и поляФактическая валидацияСостояние
Чат: typedirect/group✅
Чат: title, project_id, participant_ids[]только JSON-тип🔴 Нет длины, положительных ID, уникальности и минимального состава
Сообщение: text, content, file_ids[], mention_user_ids[]сервис требует содержимое сообщения🟡 Нет длины текста и transport-проверок ID
Реакция: typeобязательно🔴 Нет списка допустимых реакций/длины
Реакция: target_type, target_idтолько JSON-тип🔴 Нет oneof и gt=0 для attachment
Пересылка: chat_ids[]минимум 1 элемент🟡 Элементы не проверяются на gt=0
Файлы: entity_type, categoryобязательные строки; категория не пустая🔴 Нет справочника типов/категорий и ограничений длины
Файлы: entity_idrequired, но без gt=0🔴 Положительный ID не гарантирован
Файлы: folder_id, bucket, keyтолько тип🔴 Нет gt=0, длины и безопасного формата ключа
Файлы: содержимоефайл обязателен🟡 Размер/MIME/расширение зависят от storage/service, единого allowlist в DTO нет
Связи сущностей: source_type, target_typeобязательно🔴 Нет списка типов сущностей
Связи сущностей: source_id, target_idположительные ID✅
Связи сущностей: relation_typeдо 100🔴 Нет списка типов связи
Отдел: nameобязательно; сервис отсекает пробелы🟡 Нет максимальной длины
Отдел: parent_idположительный ID; циклы контролирует сервис/БД✅
Должность: name, description, levelимя 1–120; описание до 500; уровень 1–100🟡 Для имени нет notblank
Должность: role_codes[]каждый код не пустой; существование проверяет сервис✅
RBAC: roles[], permission_codes[]поле должно присутствовать, элементы не пустые; пустой массив разрешен для очистки✅
RBAC: permissions[]поле должно присутствовать, структура элементов проверяется сервисом✅
RBAC: имя/описание ролиимя обязательно и не пусто; описание только строковый тип🟡 Нет ограничений длины

Что еще не готово ​

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

  1. Унифицировать пароль: один минимум и максимум для регистрации, создания пользователя и сброса.
  2. Унифицировать применение inn, kpp, а также строгих правил ОГРН, БИК и расчетных счетов во всех компаниях, поставщиках, реквизитах и банковских счетах.
  3. Добавить общий валидатор дат (date) и RFC 3339, чтобы правила не зависели от конкретного handler/service.
  4. Закрыть логистические DTO: статусы, тип транспорта, положительные ID/количества, непустые массивы и одинаковые правила create/update.
  5. Добавить ограничения строк и справочники для локаций, поставщиков, проектной команды, чатов, файлов и связей сущностей.
  6. Валидировать IANA timezone, ISO 4217 currency и допустимые настройки уведомлений.
  7. Добавить dive,gt=0 и min=1 во все массивы идентификаторов, где пустой список не является явной командой очистки.
  8. Зафиксировать допустимый знак и бизнес-диапазон для каждого денежного поля, прежде всего договоров и профилей зарплаты.
  9. Сделать правила create/update симметричными там, где поле имеет одинаковый смысл.
  10. Добавить проверки контрольных сумм ИНН/ОГРН и, при необходимости, нормализацию телефонов.

Поддержка страницы ​

При добавлении или изменении входного поля необходимо одновременно:

  1. обновить binding-правило или сервисную проверку;
  2. добавить позитивный и негативный тест;
  3. обновить эту страницу;
  4. при изменении API-контракта выполнить go run ./cmd/generate_contracts и go run ./cmd/generate_endpoints.

Загружаем документацию…