Кейс
malin.kiev.ua: сайт міського транспорту, звірений із десятьма принципами
Малин — місто в Житомирській області, на північний захід від Києва. Його табло зупинок і розклади автобусів живуть на malin.kiev.ua. У жовтні 2026 року ми звірили сайт із маніфестом, принцип за принципом, і виправили те, що змогли. Ця сторінка каже, що зроблено, що зроблено наполовину і чого ми вирішили не робити.
З чого все почалося
Рецензент цього маніфесту вказав на принцип 5: кожна важлива система має коректно деградувати та працювати без центральних серверів. Якщо табло зупинок malin.kiev.ua не відкривається без мережі, сильна фраза на цьому сайті обертається проти його автора. 15 жовтня 2026 року перевірка була чесною: ні service worker, ні маніфесту застосунку, розклад жив лише у відкритій вкладці. Чотири етапи роботи по тому сайт інший — і ця сторінка є останнім етапом: сказати рівно те, що правдиве зараз.
Десять принципів, чесно
Статуси: зроблено — перевірено на бойовому сайті й має адресу, яку можна відкрити; частково — код є, але відомі межі лишаються; не стосується — принцип про апаратуру.
| Принцип | Статус | На чому тримається |
|---|---|---|
| 1. Цифрова власність — справжня власність | частково | Встановлений застосунок і збережений розклад працюють, коли наш сервер лежить, — і коли перестає відповідати сам домен: табло, розклади й схема відкриваються з власного кешу браузера (перевірено із зупиненим хостом: smoke, «Без домену»); усю базу можна забрати як GTFS або JSON. Межі чесні: лише в тому браузері, де застосунок встановили, поки він тримає кеш, без оновлень і без живих даних. Домен і хостинг і далі наші. |
| 2. Пристрої мають працювати без дозволу | не стосується | Апаратури нема. Розділ транспорту не потребує акаунта й ставиться з браузера без магазину застосунків: власний банер Chrome на Android, картка з трьома кроками на iPhone. |
| 3. ПЗ — це інфраструктура | зроблено | Відкриті стандарти наскрізь: GTFS Static (валідатор MobilityData: 0 помилок), OpenAPI 3.1 зі сторінкою довідки, RSS, iCalendar для кожного маршруту (приклад), HTTP-кеш з ETag. |
| 4. Дані належать людині | зроблено | Розклад — так: GTFS і JSON під зазначеною ліцензією, з журналом ревізій кожної зміни. Власні дані людини — теж: на сторінці профілю (вхід через Telegram) одна кнопка завантажує все, що сайт і бот знають про вас, одним JSON-файлом, друга видаляє акаунт (ім'я, телефон і Telegram стираються одразу, майбутні бронювання й оголошення знімаються, минулі поїздки лишаються без прив'язки до вас); те саме в боті — /mydata і /deleteme. Збережені зупинки планера живуть лише у браузері, їх можна зберегти у файл, відновити або стерти без сервера. Що зберігається і скільки — у політиці конфіденційності. |
| 5. Спочатку офлайн | зроблено для /transport | Табло зупинок, розклади маршрутів, схема і планер /transport відкриваються без мережі й без бекенду після першого відвідування; те, що людина відмічає на табло (факт прибуття, сканування наклейок), чекає в черзі й відправляється, коли мережа повернеться. Карта, міжміське табло та бронювання потребують мережі — див. нижче. |
| 6. Сумісність — право | зроблено | Фід подано в Transitland і Mobility Database (на розгляді); id зупинок і маршрутів — опублікований контракт, злита зупинка відповідає 301 (мапа перенаправлень). |
| 7. Прозорість замість довіри | зроблено | Код сайту, бекенду й бота відкритий, кожне рішення записане (див. «Документація по-чесному»), кожна зміна даних лишає рядок у журналі. Бандл підписано subresource integrity (у джерелі сторінки — integrity="sha384-…"), а /about#build показує хеш завантаженої збірки, BUILD_ID service worker і ревізію збережених даних — ті самі значення кожен прочитає через curl -s https://malin.kiev.ua/transport-sw.js | grep BUILD_ID і на /transport/revisions. |
| 8. Ремонт, зміна, форк | частково | Ми не забороняємо: репозиторій і дані відкриті під OwnNet Source License 1.1, яка дозволяє ремонт, зміни й форк на тих самих умовах, репозиторій повний. Ми не полегшуємо й не закликаємо — інструкції «підняти свою копію» нема і не планується; це рішення, а не прогалина, яку ми збираємось закрити. |
| 9. Протоколи важливіші за платформи | зроблено для /transport | Дані виходять із сайту через GTFS, RSS, iCal і звичайний HTTP — щоб ними користуватися, не потрібні ні наш застосунок, ні наш бот; Telegram-бот — один канал із кількох. Дошка попутників досі бере джерело з груп Viber і Telegram, але публікує у відкритому вебі. |
| 10. Цифровий суверенітет — громадянський суверенітет | частково | Базу зібрали мешканці, а не купили в платформи; місто може безкоштовно взяти фід і розмістити в себе. Хостинг орендований (Railway, Cloudflare): дані й код переносні, інфраструктура не наша. |
Звідки дані
Структурованого розкладу для Малина не було. Автор сайту стояв на зупинці «Прожектор» і не знав, які автобуси тут зупиняються і коли прийде наступний. Те, що було відкрите, — назви зупинок, приблизний перелік маршрутів, сфотографовані «листочки» міськради — зібрали вручну, структурували й перевірили на місці; QR-наклейки на зупинках тепер ведуть на табло цієї зупинки. Історію розповіла місцева газета: «Стояв на зупинці й не знав, який автобус чекати» (malyn.media, 7 жовтня 2026) і її продовження (14 жовтня 2026).
Ця зібрана руками база — причина, чому ліцензія OwnNet, а не Creative Commons: вільно для людей, навчання, міста й малого бізнесу; похідні бази лишаються на тих самих умовах; корпораціям і платним застосункам — за договором. Ціна відома і прийнята: Google Maps і Apple Maps не беруть фідів з такими умовами. Самі факти — що автобус №5 відправляється о 7:10 — нікому не належать; ліцензія стосується зібраної бази, а не фактів.
Що працює без мережі, а що ні
Без інтернету й без нашого сервера (після одного відвідування онлайн, у вкладці браузера або у встановленому застосунку «Як доїхати»): табло зупинки, розклад маршруту, планер між зупинками, схема маршрутів. Смужка стану каже правду — «Без мережі — розклад станом на …» або «Сервер не відповідає — показуємо збережений розклад»; коли мережа повертається, дані оновлюються самі, а нова версія сайту ніколи не ламає відкриту сторінку.
Потребує мережі: підкладка карти (тайли OpenStreetMap не кешуємо — їхня політика використання; карту замінює схема), міжміське табло (попутки, маршрутки, електрички — живі дані), бронювання, довідка, адмінка й найперше відкриття. «Розклад» — планова таблиця станом на останню синхронізацію, а не живе положення автобусів: його на сайті й не було.
Чого ми свідомо не зробили
- Карта офлайн: тайли OpenStreetMap не кешуємо за їхньою політикою; цю роботу робить схема маршрутів.
- Google Maps і Apple Maps: їм потрібна ліцензія без share-alike; для зібраної руками бази ми лишили умови OwnNet.
- GTFS-Realtime: даних про те, де автобуси, нема — лише відмітки пасажирів «автобус тут» на сайті.
- Міжміські рейси у GTFS: фід покриває лише міські автобуси.
- Інструкція «підняти свою копію»: ліцензія не забороняє форк і ремонт, репозиторій відкритий — цього достатньо; ми не полегшуємо й не закликаємо.
Документація по-чесному
Кожен етап вівся з «файлу відновлення» в репозиторії: проблема як є, рішення з причинами, чекліст і знахідки — включно з тим, що пішло не так. Це і є документація кейсу: табло без мережі й застосунок, записи без мережі, відкриті дані й рішення про ліцензію, відкриті протоколи, журнал ревізій, перевірювана збірка, ця сторінка. Для тих, кому потрібні дані: transport-open-data.md.