Образи зібрались із першого разу, але далі знайшлось три речі.
memlock без обмеження для Dragonfly дозволений не всюди: у контейнерній
віртуалізації ядро відмовляє, і контейнер не стартує взагалі. Швидкість
того не варта — обмеження знято.
Caddy нескінченно просив Let's Encrypt видати сертифікат на IP, чого той
не робить, і сайт лишався без TLS. Тепер порожня ACME_EMAIL означає
самопідписаний сертифікат. Плюс default_sni: SNI не містить IP-адрес,
тож без нього рукостискання обривалось «internal error».
У README команда заведення власника не працювала: у образу ENTRYPOINT, і
без --entrypoint ім'я команди йшло аргументом до netpulse-api. Заразом
netpulse-user навчився створювати перший кабінет — свіжа база не має
жодного, а користувач без кабінету нікуди не належить.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Логін:
- core.users.username замість пошти як ідентифікатор: у мережевій
інсталяції половина акаунтів технічні (noc, monitoring, oncall) і
скриньки не мають узагалі. Пошта лишилась необов'язковим полем
- наявним користувачам логін виведено з пошти, збіги розведено
суфіксом: мовчки злити admin@a.com і admin@b.com в один логін —
це втрата акаунта, а не міграція
- сервер шукає за логіном і за поштою, тому звичка вводити email
нікого не відхиляє
Групи (модель Zabbix):
- групи хостів і групи доступу; права read/write/deny на групу хостів
- роль каже, що вільно робити; група — над якими хостами. Інженер над
філією та інженер над усією мережею мають однакову роль і різний
доступ
- хто не входить у жодну групу, групами не обмежений — свідомо не
по-заббіксівськи: там кожна нова інсталяція починається з питання
«чому порожньо»
- заборона перемагає дозвіл, інакше її обійти додаванням у сусідню групу
- фільтр накладається в самому запиті, а не після вибірки
Хости: додавання, редагування, м'яке видалення, прив'язка до груп,
фільтр за групою в таблиці.
Мапа: створення мапи з транслітерацією slug, інспектор вузла — підпис,
значок, розмір, ширина, колір рамки, закріплення.
Виправлено за скаргами:
- перемикач вилазив на 14px за трек: у ручки не заданий left, а
статичну позицію зсуває типове text-align: center у <button>
- сторінка правил не оновлювала «активних»: після повернення правила
алерти піднімаються наступним тіком движка, тобто ПІСЛЯ нашого
перечитування — бракувало підписки на живі події
- канал із секретом показувався як «секрету немає»
Живий прогін: eng у групі з read на «Доступ» бачить 2 хости замість 3,
обидва без запису, алертів 1 замість 3, редагування чужого хоста 403.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Досі доступ давав машинний токен зі змінної збірки — одні права на всіх
і жодного способу відрізнити, хто що зробив. Тепер продукт уміє впустити
людину.
Сервер:
- argon2id для паролів, власний HS256 JWT (15 хв) + refresh-сесія в
httpOnly-кукі на 30 днів з ротацією при кожному обміні
- Principal зводить людину й машинний токен до одного набору прав;
права читаються з БД на кожному запиті, а не з claims, щоб відкликана
роль не жила до кінця TTL
- 9 ендпоїнтів: auth/login|refresh|logout|password, me, team CRUD, roles
- netpulse-user — CLI для першого власника: публічна реєстрація в B2B
це дірка, а «перший через веб, поки нікого немає» — нечесна гонка
- міграція 0012: три RLS-політики винятку для шляху входу (без них
вхід неможливий за побудовою — щоб знайти користувача за email,
треба знати тенант, який відомий лише після пошуку) і login_attempts
для тротлінгу
Фронтенд:
- сторінка входу з вибором організації, access-токен у замиканні
модуля замість localStorage, тихе відновлення сесії по кукі
- один refresh на всі паралельні запити: інакше ротація зробила б усі,
крім першого, недійсними й викинула б людину на вхід
- дії без права не показуються; полотно нередаговане для глядача
- мобільний адаптив: висувна бічна панель, інспектор нижнім аркушем
11 нових тестів (37 у httpapi), go vet і tsc чисто, живий прогін з
8 кроків проти netpulse_it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>