Skip to content

Огляд платформи

Три списки адмінки: усі команди, усі люди, усі агенти. Це відповідь на питання, на яке продукт раніше відповісти не міг — що тут узагалі працює? — і вони суворо лише для читання.

Хто їх бачить: адміністратор платформи, роль окрема від будь-якої ролі всередині команди. Як ця роль влаштована і чим захищена — окрема сторінка; ця описує те, що вона відкриває.

Екран огляду платформи: підсумки за командами, людьми та агентами і дві розбивкиСписок людей в адмінці: значок адміністратора платформи та команди кожного облікового запису

Три списки

екранендпоінтщо каже рядок
КомандиGET admin/teamназва, скільки людей, скільки агентів, коли створена, коли остання активність
ЛюдиGET admin/userпошта, ім'я, усі команди та роль у кожній, коли зареєстрований
АгентиGET admin/agentназва, власник, команда, тип, статус, чи ввімкнено автозапуск, коли створений

Переходи між ними. admin/user і admin/agent приймають ?teamId=, тому рядок команди веде до її людей і до її агентів, а кожен рядок агента несе свою команду — і веде назад. Це вся модель навігації: один фільтр, а не другий набір екранів.

Будь-який список — це сторінка. ?page= і ?pageSize=, pageSize обмежений сотнею. Режиму «віддай усі рядки» немає, і це навмисно: команди й агенти — це саме те, чого стає багато.

Чого в списках немає і чому

Жодного вмісту. Адміністратор платформи бачить факти про речі — назви, лічильники, дати, статуси, ролі — і ніколи самі речі. Ні тексту повідомлень. Ні пам'яті агентів. Ні SOUL.md, USER.md чи HEARTBEAT.md. Ні значень секретів, ні хешів паролів.

Власник залишив цю розвилку відкритою («усе чи все, крім листувань?»); її вирішили в бік меншого, бо сторони коштують по-різному. Розширити видимість потім — це одне поле в одній відповіді. Забрати назад побачене чуже листування — ніщо.

Позначка часу — це факт, тому «коли команда востаннє була активна» показувати можна, і береться вона з часу найсвіжішого повідомлення. Саме повідомлення з бази не виходить.

Жодних дій. На жодному з цих екранів не можна нічого вимкнути, видалити чи увійти під кимось. Не тому, що цього ніхто не хоче, а тому що адміністративна дія не лишає сліду, поки немає журналу, а дія без сліду над чужим орендарем гірша за відсутню. Дії прийдуть разом із журналом, окремим завданням.

Немає «коли заходив». Списки показують, коли обліковий запис зареєстровано, а не коли його власник востаннє з'являвся, бо факт входу в системі ніхто не записує: немає ні такої колонки, ні таблиці сесій, і сам вхід не пише нічого. Правильний дім для цього — журнал: вхід це подія, і колонка відповідала б лише на «коли востаннє», а журнал відповідає ще й на «скільки разів», «звідки» і «а невдалі спроби?».

Як це влаштовано

Тонкі ендпоінти поверх перевірки ролі, а не друга копія продукту. У групі admin немає жодної копії продуктового слайсу. Це прямий урок 1.x, записаний у README самої групи: *«2.0 = thin admin endpoints

  • a role guard, NOT duplicate modules»*.

Дані читаються напряму через Prisma. Група admin стоїть нижче за runtime і agent у порядку груп, а отже імпортувати їх не може — див. Шари-слайси. Читання таблиць орендарів напряму — це те, що тримає порядок недоторканим, і це оголошений задум, а не обхід.

Захист — це префікс. Усі маршрути живуть під admin/, і одна гвардія, зареєстрована на всю групу, покриває все, що під цим префіксом. Жоден контролер слайсу не пише @UseGuards — і не повинен: перевірка, написана в кожному контролері, це перевірка, яку одного дня забудуть написати.

Ціна рядка — не запит

Зіпсувати такий список найпростіше так: отримати рядки, а потім поставити базі ще по одному питанню на кожен. Усі відповіді правильні, тому ніщо не виглядає зламаним — поки установка не стане справжньою. На цьому тут уже ловили.

Тому число запитів задано формою запиту, а не числом рядків:

списокзапитів на 1 рядкуна 12 рядкахна 20 рядках
Команди666
Люди444
Агенти444

Це виміряно, а не заявлено: тест проганяє кожен список на одній команді і на дванадцяти й вимагає, щоб числа були рівні. Запит на рядок такого порівняння не переживає, якою б не була константа.

Це наскрізні числа на весь запит, тому в кожне входить один пошук, який робить гвардія ролі перш ніж спрацює обробник.