ЗОРЯ

Завдання/ТЗ частини 1

Зоря. Частина 1: Вихід на зв'язок

Технічне завдання першого тижня. Результат тижня - ваш клієнт мережі Зоря.нет і реєстрація в просвіт. Далі йдуть жеребкування і частина 2 (правила гри та SDK) . Поруч: легенда, специфікація клієнта, OpenAPI, оцінювання, календар.

опубліковано 21.09

1Що ви будуєте

Клієнт мережі Зоря.нет - ваш застосунок на React + TypeScript у репозиторії вашої заявки. Через нього ви реєструєтеся, бачите статус доступу до репозиторію, отримуєте новини, особисті листи та наступні частини завдання. З нього ж виросте ігровий штаб у частині 3.

Видається: цей пакет, контракт API в OpenAPI 3.1, живий сервер мережі в режимі ефіру з і навчальний стенд. Не видається: SDK, опис гри, готовий клієнт. Вбудований вебклієнт сервера для учасників закритий.

Обов'язковий мінімум клієнта: реєстрація; отримувач запрошення й статус доступу до репозиторію; опитування сповіщень; читання частин завдання. Реєстрація потрібна в просвіт, решта - до виходу частини 2 (): вона приходить у мережу частиною завдання. Інше в специфікації позначено як рекомендація (специфікація, розділ 1).

Реєстрація будь-яким HTTP-клієнтом зараховується. Запит із curl, Postman чи скрипта сервер не відрізняє від запиту вашого застосунку й не намагається відрізняти. Це не лазівка: сам клієнт у частині 1 не перевіряється, його перевіряє оцінювання штабу пізніше, за документом оцінювання. Клієнт, якого немає, не покаже частину 2 і не стане штабом.

схема
  ваш клієнт (браузер або Node)            сервер Зоря.нет
  +----------------------------+  HTTPS   +--------------------------+
  | реєстрація, статус,        | -------> | /api/v1: ефір, акаунт,   |
  | новини, листи, частини     | <------- | новини, листи, частини   |
  +----------------------------+ опитув.  +------------+-------------+
                                                       | бот допуску
  ви --- запрошення ---> ваш репозиторій <-- читання --+
         (GitHub)        + файл .zoria

2Тиждень: від публікації до частини 2

Від публікації сервер працює в режимі ефіру. До просвіту він шумить: майже всі відповіді - перешкоди, зрідка проходить справжній кадр із печаткою станції. У легенді це вихід на зв'язок: мережа мовчить під Шумом, і тільки станція пробивається крізь перешкоди. За 6 годин до просвіту в шумі проступає зв'язок: несуча, потім позивні, потім станція на частоті. Технічно це провісник - поле harbinger у кожному справжньому кадрі: opensIn, точна кількість секунд до відкриття, і text, голос станції українською і російською, без чисел. Якщо клієнт слухав ефір і провісника не було, найближчі 6 годин просвіту не буде.

схема
 2026-09-21            початок просвіту: 2026-09-24 05:00 - 2026-09-25 09:00     09-26         09-28
     |                                     |                                       |             |
     v                                     v                                       v             v
   [ шум ......................| провісник 6 год | ПРОСВІТ, не менше 10 год | після ] жеребкування частина 2
     перешкоди, печатка,         строк відкриття   перешкод немає,          реєстрацію
     глушіння; реєстрації немає  у кадрах          реєстрація відкрита      закрито
КолиСерверВиЩо видно в клієнті
Від до провісникаШум: на маршрутах частини 1 перешкоди або справжні кадри; реєстрація не працюєПишете клієнт, перевіряєте його на стенді; можна заздалегідь запросити акаунт організаторів і покласти .zoriaКадри ефіру, уривки листа Доглядача
За 6 год до просвітуПровісник у справжніх кадрахПлануєте час реєстраціїВідлік до відкриття
Просвіт, не менше 10 годПерешкод немає, реєстрація відкрита; кожна реєстрація - запис у журналі виходу на зв'язокРеєструєтеся, запрошуєте акаунт організаторів, кладете .zoriaФорма реєстрації, потім статус доступу
Після просвітуРеєстрацію закрито, решта API працюєДоводите доступ до verifiedСтатус доступу, листи, новини
ЖеребкуванняПеревіряєте своє місце (розділ 7)Новина
Частина 2 у списку частин завданняЧитаєте частину 2Нова частина

Два проходи очима учасника.

Вручну:

  1. До просвіту ви відкриваєте клієнт раз на кілька годин, не рідше ніж раз на 10 годин.
  2. Клієнт показує шум, із провісником - відлік у вашому місцевому часі.
  3. У просвіт ви вводите логін, відображуване ім'я, пароль і репозиторій.
  4. Клієнт показує, кого запросити; ви запрошуєте й кладете .zoria.
  5. За кілька хвилин статус стає verified, приходить лист.

Автоматично:

  1. Клієнт слухає GET /ether не частіше ніж раз на 15 с і перевіряє печатку.
  2. З провісника він знає момент відкриття: at кадру плюс opensIn.
  3. На першому справжньому кадрі з phase: "window" він надсилає заготовлену заявку.
  4. Відповідь 429 authentication-busy означає, що черга перевірки паролів зайнята: почекати Retry-After секунд і повторити заявку. Це не відмова і до ліміту адреси не йде.
  5. Якщо відповідь загублено, він входить тими самими логіном і паролем, а не реєструється вдруге.
  6. Далі він опитує зведення й показує статус доступу.

3Дати й адреси

ЩоЗначення
Публікація частини 1 і початок ефіру
Початок просвітуміж і ; точний момент заздалегідь не оголошується
Тривалість просвітуне менше 10 год; кінець - поле window.closesAt у кадрі ефіру
Провісникза 6 год до початку просвіту; тільки в ефірі, на сайті не дублюється
ЧасUTC у текстах і в API; клієнт показує місцевий час
Адреса APIhttps://zoria.net/api/v1
Ефір і журнал виходу на зв'язокGET /ether, GET /ether/roll
Відкритий ключ печаткиGET /ether/key; відбиток (SHA-256 ключа): буде опубліковано 21.09
Навчальний стендhttps://stand.zoria.net/api/v1
Акаунт для запрошення до репозиторіюzoria-net-bot; його ж називає GET /public/config
Жеребкування, час - у календарі
Строк підтвердження доступу до репозиторіюу календарі
Частина 2

Київський час у ці дати - UTC+3.

4Вимоги допуску

P1-01

Реєстрація в просвіт. Акаунт створюється запитом POST /auth/register у фазі window. До просвіту реєстрація відповідає шумом, після - 403 registration-closed. Перевірка: акаунт існує і є в журналі виходу на зв'язок.

P1-02

Репозиторій із заявки. Поле repositoryUrl - репозиторій, який ви вказали в заявці на конкурс: owner/repo або адреса на github.com. Репозиторій не зі списку заявок - 422 repository-not-eligible; якщо в заявці помилка, пишіть на пошту з розділу 3. Перевірка: сервер звіряє адресу зі списком заявок під час реєстрації та зміни репозиторію.

P1-03

Один учасник - один акаунт, один репозиторій - один учасник. Перевірка: файл .zoria прив'язує репозиторій рівно до одного акаунта; решта заявок на той самий репозиторій отримують needs-attention.

P1-04

Запрошення акаунта організаторів. Запросіть до репозиторію GitHub-акаунт із розділу 3 (поле repositoryAccess.githubUsername). Репозиторій може бути приватним. В особистому репозиторії GitHub немає ролі "тільки читання": запрошений співавтор отримує право запису. У репозиторії організації достатньо ролі Read. Наш акаунт - окремий бот із двофакторною автентифікацією; його токен зберігається тільки на сервері мережі у файлі з правами 0600. Бот у репозиторій не пише: він приймає запрошення й читає .zoria, у наступних частинах - код. Якщо у вашій заявці вказано GitHub-логін, запрошення має прийти від нього. Перевірка: бот приймає запрошення.

P1-05

Файл .zoria. У корені гілки за замовчуванням лежить файл .zoria. Його перший непорожній рядок - логін вашого акаунта в мережі; регістр і початковий @ значення не мають. Перевірка: бот читає файл після прийняття запрошення, після кожної зміни заявки й кожні 10 хвилин, доки заявку не підтверджено або доки рішення не виніс організатор.

P1-06

Доступ підтверджено до строку. До строку підтвердження доступу з календаря GET /me/repository віддає accessStatus: "verified". Перевірка: статус на сервері в момент строку.

P1-07

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

P1-08

Клієнт у репозиторії заявки. React + TypeScript; README з командами встановлення й запуску; lockfile; жодних токенів, паролів чи ключів в історії репозиторію. Перевірка: у частині 1 не перевіряється; перевіряється оцінюванням штабу.

P1-09

Чесна гра в мережі. Заборонено: реєструвати чужий репозиторій; заводити другий акаунт; розподіляти запити між кількома адресами, щоб обійти ліміт ефіру. Дозволено: вийти в мережу з іншої адреси, якщо вашу заглушив сусід за спільною адресою. Перевірка: журнал сервера; санкції - розділ "Чесна гра" документа оцінювання.

5Приймання

Частину 1 приймає машина за двома умовами:

  1. Реєстрація відбулася в просвіт. Поза просвітом акаунт створити не можна, тож умову виконано, якщо акаунт є.
  2. До строку підтвердження доступу статус репозиторію - verified (P1-06).

Де це видно:

  • GET /me/repository: accessStatus, reason, checkedAt;
  • лист із notice.type: "repository" на кожну зміну статусу чи причини;
  • GET /ether/roll: ваш номер під вашим відображуваним ім'ям.
СтатусЩо означаєЩо робити
pendingЗаявка є, бот ще не вирішив. Поки запрошення немає, reason порожній; запрошення прийнято, а .zoria немає - reason просить покласти файлЗапросити акаунт, покласти .zoria
verifiedЗапрошення прийнято, .zoria називає ваш акаунтНічого; тримати доступ (P1-07)
needs-attention.zoria називає інший акаунт, запрошення прийшло не від логіна із заявки або рішення ухвалив організатор; reason пояснюєВиправити за reason; якщо причина не у файлі й не в запрошенні - пошта

verifiedElsewhere: true означає, що той самий репозиторій уже підтверджено за іншим акаунтом, і ваша заявка підтвердитися не може: перевірте .zoria і пишіть на пошту.

Після виправлення бот переглядає заявку сам: під час зміни заявки або чергового читання .zoria, не рідше ніж раз на 10 хвилин. Рішення організатора бот не переглядає. Строк виправлення - той самий строк підтвердження доступу.

Балів частина 1 не дає. Її підсумок - місце в жеребкуванні та допуск до наступних частин.

6Вибування і збій на нашому боці

Вибуває учасник:

  • який не зареєструвався в просвіт;
  • чий доступ не підтверджено до строку з календаря;
  • знятий за розділом "Чесна гра" документа оцінювання.

Збій на нашому боці. Якщо за час просвіту за нашим моніторингом сумарно понад 30 хвилин GET /ether не віддавав справжніх кадрів або реєстрація відповідала 5xx, просвіт подовжується на сумарну тривалість збою. Новий кінець приходить у полі window.closesAt кадру ефіру; подовження оголошується на сайті й новиною в мережі. Збій сумарно на 30 хвилин і менше просвіт не подовжує.

Про збій пишіть в офіційний канал із часом в UTC і значенням заголовка X-Request-Id відповіді.

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

7Що далі

Жеребкування . Публікується перестановка всіх зареєстрованих, виведена із солі жеребкування. Схема - commit-reveal із публічним маяком випадковості drand: публікується хеш секрету організаторів (буде опубліковано 21.09); сіль - SHA-256 від секрету та значення маяка drand на заздалегідь оголошений раунд після просвіту; на жеребкуванні секрет розкривається, і перестановку може перерахувати кожен. Групи нарізаються з цієї перестановки пізніше. Правило й спосіб перевірити свою групу - оцінювання, дати - календар. Результат жеребкування приходить у клієнт новиною.

Частина 2, . Правила гри, SDK, протокол, шаблон бота і наказ. Частина з'являється в списку частин завдання (GET /stages); клієнт дізнається про неї за лічильником releasedStages у зведенні GET /me/summary.

8Поза частиною 1

  • Гра, її правила, SDK, бот, ігрові функції штабу.
  • WebSocket і push-сповіщення: обмін тільки опитуванням.
  • Готовий клієнт: вбудований вебклієнт сервера закритий.
  • Бали.

9Питання учасників

Реєструватися вручну чи доручити клієнту? Як зручніше. Зараховується будь-яка реєстрація в просвіт, зокрема через curl.

Просвіт припаде на ніч? Він триває не менше 10 годин: досить заходити в мережу раз на 10 годин. Або клієнт слухає ефір і реєструється сам за кадром відкриття.

Чи дає щось рання реєстрація? Ні. Номер у журналі виходу на зв'язок балів не дає й на жеребкування не впливає.

Чи можна підготувати запрошення і .zoria до просвіту? Так. Запрошення до репозиторію зі списку заявок бот приймає й до реєстрації; заявку буде вирішено на першому проході бота після неї. Логін у .zoria має збігатися з тим, під яким ви зареєструєтеся.

Чи можна змінити репозиторій? Так: PUT /me/repository із сесії входу, тільки на репозиторій зі списку заявок. Статус скидається в pending. Якщо в самій заявці вказано не той репозиторій - пошта.

Хтось зареєстрував мій репозиторій. Заявку вирішує .zoria: підтверджується акаунт, названий у файлі, чужа заявка отримує needs-attention. Покладіть файл зі своїм логіном. Якщо запрошення вже прийнято, а статус не сходиться, - пошта.

Що робити у разі needs-attention? Прочитати reason у GET /me/repository або в листі й виправити назване. Бот перегляне заявку сам.

Чи обов'язковий React? Так, стек конкурсу - React + TypeScript. Решту бібліотек і будову застосунку обираєте ви.

Чи можна клієнту власний бекенд? Так. З Node до API можна звертатися без CORS. Пароль і токен до репозиторію не потрапляють.

Мене заглушили, хоча клієнт опитує рідко. Ліміт рахується за адресою, клієнти за спільною адресою (офіс, NAT) ділять його. Вийдіть у мережу з іншої адреси або домовтеся із сусідами про частоту опитування.

Як перевірити клієнт до просвіту? На навчальному стенді: той самий протокол, коло щогодини за UTC - шум, з :20 провісник, з :30 до :50 просвіт; навчальний список репозиторіїв, база стирається раз на добу (специфікація, розділ 6).

Якою мовою приходять листи сервера? Мовою акаунта: uk за замовчуванням або en. Мову задає поле lang під час реєстрації, змінює PATCH /me. Голос провісника в ефірі приходить одразу обома мовами.