Общие соглашения¶
Де-факто стандарты, которые повторяются во всех репозиториях экосистемы. Они выросли не из формальной спецификации — это правила, устоявшиеся после того, как одни и те же реальные проблемы были решены по нескольку раз. Новая платформа должна следовать им с самого начала.
Identity casing¶
Правило: хранить весь текст идентичности в базе данных в нижнем регистре. Поиск регистронезависим. К отображению приводить в стандартный вид (регистрационные номера — в верхнем регистре, имена — Title Case).
Поля-исключения — они хранятся ровно так, как получены:
| Поле | Почему |
|---|---|
etsi_identifier |
Формат задан стандартом |
| DN сертификата | Входит в криптографическую подпись, изменять нельзя |
Поля *_latin |
Латинская транслитерация — сохраняет исходный вид |
document_number |
Номер официального документа |
| Значения хеша | Значим каждый бит |
Откуда взялось это правило
Гражданин регистрировался как АБ12345678, а затем пытался войти как
аб12345678 — система видела другого человека, и появлялась дублирующая
учётная запись. Нормализация регистра на уровне хранения убирает весь этот
класс ошибок.
Иерархия ролей¶
Жёсткие правила:
| Роль | Может | НЕ может |
|---|---|---|
superadmin |
Добавлять/удалять учётные записи admin | — |
admin |
Выдавать права manager | Управлять учётными записями admin |
manager |
Повседневные операции | Добавлять людей |
user |
Собственные действия | Выдавать права |
Super admin — отдельная учётная запись с MFA. Создаётся через onboarding-мастер: allow-list приглашений → Google → eID → OTP по почте → TOTP + коды восстановления. Хранится в отдельной таблице с ключом по Google-идентичности.
Практическое следствие: один человек может быть и админом по eID, и Google super admin — две разные учётные записи, два разных входа. Каждый вход super admin защищён MFA.
Права admin выдаются по регистрационному номеру, против пользователя, зарегистрированного в локальном eID.
Выдача прав, подтверждённая подписью¶
Правило: при выдаче кому-либо прав manager в организации этому человеку
уходит eID SIGN push, и права становятся ACTIVE только после подтверждения
через PIN2.
Почему: выдача прав — действие с юридическими последствиями. Если администратор в одностороннем порядке сделал кого-то руководителем, тот может впоследствии это отрицать. Подпись PIN2 обеспечивает неотрекаемость и закрывает возражение «я на это не соглашался».
Правила callback¶
Правило: callback возвращается только в same-device потоках. Во всех остальных случаях сессия опрашивается (poll).
| Ситуация | Механизм |
|---|---|
| Пользователь на одном устройстве (deep-link) | Callback |
| QR-код — второе устройство | Опрос сессии (long-poll) |
| Push-уведомление | Опрос сессии |
Причина: в потоке, начатом на другом устройстве, callback не знает, куда возвращаться. Опрос делает исходный браузер источником истины и оставляет поток однозначным.
Deep-link третьей стороны — передаётся параметром callback; по завершении соответствующее приложение выводится на передний план.
Привязка Google¶
Правило: перед привязкой Google-аккаунта пользователь обязан пройти проверку через eID. Первая привязка связывает аккаунт с реальным человеком; дальше можно входить прямо через Google. Отвязка возможна.
Причина: Google-аккаунт может создать кто угодно. Сам по себе он не может приниматься как идентификация гражданина. После однократной привязки через eID этот Google-аккаунт указывает на конкретного гражданина.
RP ↔ rp_app¶
Правило: в eID регистрируется только RP.
Несколько приложений или подсистем под одним RP передаются через поля
rp_app / rp_app_url.
Тогда в логах и на экране пользователя видно, какое приложение сделало запрос, — без регистрации отдельного RP на каждое приложение и без раздачи credential по сторонам.
Выход завершается на том домене, где начался¶
Правило: при выходе пользователь возвращается на тот домен, с которого
начал, а не выбрасывается на /login в SSO.
Почему: пользователь находился в приложении RP. Оказаться после выхода на странице входа совершенно незнакомого домена — дезориентирует. Выход должен завершаться внутри того приложения, в котором начался.
У credential один источник¶
Правило: OAuth-клиенты и client secret создаются только в SSO и живут только там. Никакая другая система их не создаёт, не хранит и не показывает.
Developer Portal — проверочный пример этого правила: он даёт инструкции по регистрации приложения, но не создаёт клиентов, а лишь даёт глубокую ссылку в консоль SSO.
Документация — это код¶
Правило: у каждого репозитория свой каталог docs/ и сайт MkDocs.
Документация живёт в том же репозитории, что и код, и меняется вместе с ним
в одном PR.
Языковой охват: как минимум MN + EN; в основных репозиториях добавляются ZH · RU. Подробности — на странице Многоязычность.
Clean Architecture — без обратных импортов¶
Правило: handler → usecase → repository → domain. Зависимости идут
только в одну сторону. Бизнес-ядро (domain, usecase) никогда не
импортирует веб-фреймворк.
Простая проверка: если в файле внутри domain/ есть импорт net/http или
chi, правило нарушено.
Чек-лист для добавления новой платформы¶
- [ ] Аутентификация — через SSO как OIDC RP, собственной системы паролей нет
- [ ] Иерархия ролей
superadmin → admin → manager → user - [ ] Текст идентичности в БД в нижнем регистре, поля-исключения определены
- [ ] Postgres RLS включён + boot-time enforceability guard
- [ ] Журнал аудита — связанный хеш-цепочкой
- [ ] Security-заголовки, allow-list CORS и rate limit настроены
- [ ]
/metrics,/swaggerзакрыты в production - [ ]
docs/+ сайт MkDocs, MN/EN - [ ] CI: сборка + тесты + строгая проверка документации