The backup system was hard-wired to Google Drive via googleapiclient and a service account — replaced with rclone (invoked as an external binary via subprocess, credentials passed as RCLONE_CONFIG_BACKUP_* env vars, never written to a config file on disk) so the destination isn't locked to one provider. The admin panel now has a storage-type picker (Google Drive / S3- compatible / custom) with real form fields for each — no rclone.conf to paste in, matching the same non-technical-friendly spirit as the previous Google-only settings form, just generalized. bober_bbq/utils/gdrive_backup.py -> bober_bbq/utils/backup_remote.py; Setting keys generalized from gdrive_* to backup_*/backup_remote_* (clean replacement, no migration needed — confirmed via production that Google Drive backup was never enabled there). Local backup create/list/download/ delete/restore is untouched. Removes the now-unused google-api-python- client/google-auth/google-auth-httplib2 dependencies. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|---|---|---|
| bober_bbq | ||
| bot | ||
| docs | ||
| scripts | ||
| tests | ||
| webapp | ||
| .env.example | ||
| .gitignore | ||
| deploy.sh | ||
| provision_client.sh | ||
| pytest.ini | ||
| README.md | ||
| requirements-dev.txt | ||
| requirements.txt | ||
| run_bot.py | ||
| run_web.py | ||
Bober BBQ — Telegram Bot + Mini App
Повноцінна система для кафе/доставки Bober BBQ: Telegram-бот, Mini App (меню, кошик, оформлення доставки/самовивозу/замовлення в закладі), адмін-панель для персоналу (включно з ручним створенням замовлень), оплата карткою через monobank з автоматичною страховкою на випадок збоїв, опційна фіскалізація чеків через Checkbox (ПРРО), промокоди, оцінки замовлень, налаштовувані кольори інтерфейсу і повний набір адмінських інструментів для щоденної роботи.
Живий продакшн:
- Бот: @BoberBBQ_bot
- Mini App: https://webapp.boberbbq.com/webapp/
- Адмінка: https://webapp.boberbbq.com/admin/
Що вміє система
Клієнт (Telegram-бот + Mini App)
- Перегляд меню за категоріями, кошик, оформлення доставки, самовивозу або замовлення в закладі («У закладі», з номером столика) — все в Mini App, без багатокрокового діалогу в чаті.
- Замовлення без Telegram: та сама вебапка за адресою
webapp.boberbbq.comпрацює і в звичайному браузері — гість без Telegram-акаунту отримує кошик/історію замовлень через анонімну сесійну cookie (без SMS-верифікації й без реєстрації), а посилання для відстеження статусу замовлення працює навіть якщо cookie загубилась. - Оплата карткою (monobank) або готівкою; знижка за самовивіз і мінімальна сума замовлення на доставку — обидва налаштовуються в адмінці.
- Промокоди — знижка у відсотках, з опційним обмеженням «лише перше замовлення клієнта», мінімальною сумою, лімітом використань і терміном дії. Поле застосування прямо на екрані оформлення.
- «Мої замовлення»: історія, самостійне скасування (поки замовлення ще не в роботі), повторна спроба оплати карткою в будь-який момент, і «Повторити замовлення» в один клік — товари з минулого замовлення повертаються в кошик (товари, яких більше немає в продажу, коректно пропускаються з попередженням).
- Після статусу «Виконано» клієнт отримує в Telegram коротке «Як вам замовлення?» з кнопками 1–5 — оцінка одразу зберігається і видна в адмінці. Функцію можна вимкнути одним перемикачем у Налаштуваннях.
- PWA: Mini App можна додати на головний екран телефону поза Telegram, іконка автоматично підхоплює лого закладу.
- Skeleton-заглушки замість «Завантаження…», ілюстровані порожні стани (порожній кошик/меню/список замовлень) замість голого тексту.
- Форс-мажор: коли в адмінці увімкнено «Тимчасово закрито», Mini App замість меню й кошика показує клієнту анімовану заглушку з поясненням і контактами закладу — на відміну від звичайного графіку роботи (де меню все ще можна переглянути поза годинами), це блокує весь застосунок.
- Оголошення: адмін може ввімкнути одноразовий спливаючий попап з довільним текстом (вихідний день, зміна графіка, акція тощо) — не блокує застосунок, клієнт закриває його сам, а редагування тексту показує попап повторно навіть тим, хто вже його закривав.
Адмін-панель
- Замовлення: список з фільтрами й пагінацією (три типи — доставка/самовивіз/у закладі), картка замовлення з візуальним степером статусу (Нове → Підтверджено → Готується → Готове → [Кур'єр] → Виконано), позначення оплати готівкою, скасування з причиною.
- Нове замовлення — адмін і менеджер можуть створити замовлення вручну (телефонний дзвінок, прийом на місці) прямо з адмінки, з тим самим набором товарів і трьома типами, що й у Mini App; такі замовлення враховуються в статистиці нарівні зі звичайними (атрибутуються спеціальному службовому «клієнту», а не реальному Telegram-акаунту).
- Товари й категорії: CRUD, сортування, фото, алергени (EU-14).
- Постачальники: облік поставок, оплат і боргу по кожному; додавання вручну або імпорт з Excel-файлів довільної структури — адмін сам зіставляє, яка колонка за що відповідає (з автопідбором за схожістю назв), рядки без товару (шаблонні/підсумкові) пропускаються самі. Поставку можна опційно одразу зарахувати на склад, якщо назва товару збігається з інгредієнтом. За замовчуванням доступно лише адміністратору — можна відкрити й менеджерам окремим перемикачем.
- Промокоди: створення, вимкнення/увімкнення, видалення, лічильник використань.
- Клієнти: список і картка клієнта з історією замовлень.
- Статистика: звіти за довільний період, графік виручки по днях.
- Відгуки: середня оцінка, розподіл 1★–5★ у вигляді діаграми, стрічка останніх відгуків просто на дашборді, окрема сторінка з фільтром по оцінці й пагінацією для повноцінного розбору фідбеку.
- Склад (опційно, вмикається одним перемикачем): інгредієнти з залишками, рецептура страв (скільки якого інгредієнта йде на 1 порцію), автоматичне списання при кожному замовленні й повернення при скасуванні, ручні коригування/списання з журналом рухів, і автоматичні заявки на поповнення — з'являються, коли інгредієнт опускається нижче порогу, і самі закриваються, коли поставку зараховано.
- Фіскалізація (опційно): інтеграція з Checkbox (ПРРО) — вимкнена за замовчуванням, нічого не змінює в роботі, поки не увімкнена в Налаштуваннях. Коли увімкнена — фіскальний чек формується автоматично в момент фактичної оплати (позначення «оплачено готівкою», підтвердження оплати карткою через monobank, оплачене замовлення створене вручну), клієнту чек надсилається в Telegram PDF-документом. Помилки фіскалізації ніколи не блокують замовлення — видно статус і причину на картці замовлення, є кнопка ручного повтору.
- Вигляд: колір інтерфейсу адмінки і окремо колір Mini App — один пікер кольору на кожен, решта відтінків (для кнопок, бейджів, градієнтів) підбирається автоматично.
- Розсилка повідомлення всім клієнтам бота.
- Резервні копії БД: створення, відновлення, видалення з адмінки, плюс опційні автоматичні бекапи в Google Drive через сервісний акаунт (без інтерактивного логіну) з ротацією — старі копії видаляються, коли їх стає більше за налаштовану кількість.
- Адміністратори: ролі admin/manager (RBAC) — менеджер не бачить Налаштування, Адміністраторів, Резервні копії, Статус системи й Журнал дій.
- Журнал дій (audit log) і Статус системи.
- CSRF-захист на всіх формах, доступність (контраст кольорів за WCAG AA, aria-label на іконках-кнопках, клавіатурна навігація), адаптивний дизайн під мобільні (бічне меню згортається, широкі таблиці стають списком карток).
/health— ендпоінт для зовнішнього uptime-моніторингу.
Структура проєкту
bober-bbq-bot/
├── bober_bbq/ # Flask backend: REST API + адмін-панель + БД
│ ├── api/
│ │ ├── menu.py # /api/categories, /api/products
│ │ ├── cart.py # /api/cart — спільний кошик бота й Mini App
│ │ ├── checkout.py # /api/checkout/delivery, /pickup, /dine-in, промокод-превʼю
│ │ ├── orders.py # /api/orders — історія, скасування, повторна оплата, повтор замовлення
│ │ ├── payments.py # вебхук monobank
│ │ ├── settings.py # /api/settings — публічні налаштування для Mini App
│ │ └── auth.py # перевірка підпису Telegram WebApp initData
│ ├── admin/ # Адмін-панель (Flask-Login + Jinja2)
│ │ ├── routes.py # дашборд, замовлення, товари, категорії, промокоди, відгуки, налаштування
│ │ ├── inventory.py # склад: інгредієнти, рецептура, заявки на поповнення
│ │ ├── customers.py # клієнти й статистика по них
│ │ ├── statistics.py # звіти за період + графік виручки
│ │ ├── system.py # статус системи, бекапи (локальні + Google Drive), очищення БД
│ │ ├── telegram_chats.py # перевірка підключення чатів доставки/самовивозу
│ │ ├── broadcast.py # розсилка повідомлення всім клієнтам
│ │ ├── admins.py # керування адміністраторами/менеджерами
│ │ └── authz.py # RBAC-декоратор (admin-only розділи)
│ ├── payments/monobank.py # створення інвойсу, статус, перевірка підпису вебхука, тест токена
│ ├── utils/
│ │ ├── reconciliation.py # фонові job'и: страховка оплати + health-check токена
│ │ ├── inventory.py # автосписання/повернення складу, автозаявки на поповнення
│ │ ├── gdrive_backup.py # автобекапи БД у Google Drive з ротацією
│ │ ├── notify_customer.py # авто-сповіщення клієнта про статус + запит оцінки
│ │ ├── notify_manager.py # сповіщення менеджера (нове/скасоване замовлення), staff_chat_id() по типу замовлення
│ │ ├── telegram_notify.py # низькорівневий sendMessage/sendDocument (HTTP, поза aiogram)
│ │ ├── checkbox_prro.py # опційна фіскалізація через Checkbox (ПРРО)
│ │ ├── theme.py # один колір → повна CSS-палітра (адмінка + Mini App)
│ │ ├── promo.py # пошук/валідація промокодів, розрахунок знижки
│ │ ├── formatting.py # текст замовлення для чату менеджера (3 типи)
│ │ ├── workhours.py # графік роботи, чи приймаються замовлення
│ │ └── pricing.py # доставка/знижка самовивозу/мінімальна сума
│ ├── templates/admin/ # HTML-шаблони адмінки (адаптивні під мобільні)
│ ├── static/ # CSS адмінки, завантажені лого/фото товарів
│ ├── models.py # SQLAlchemy-моделі + DEFAULT_SETTINGS
│ ├── migrate.py # ALTER TABLE для нових колонок (без Alembic, див. нижче)
│ └── app.py # Flask app factory, CSRF, роздача Mini App, /health
├── bot/ # Telegram-бот (aiogram 3) — тонкий шар
│ ├── handlers/ # /start, меню (кнопка Mini App), контакти, оцінка замовлення (callback)
│ ├── services/ # order_service, cart_service (спільні з чекаут-API)
│ └── main.py # точка входу (long polling)
├── webapp/ # Telegram Mini App (Vite + React + TypeScript)
│ ├── public/manifest.json # PWA-маніфест (Add to Home Screen поза Telegram)
│ └── src/
│ ├── pages/ # Menu, Cart, Checkout (+ промокод), Orders (+ повтор), Contacts
│ ├── components/ # Skeleton, EmptyState та інші перевикористовувані блоки
│ ├── telegram.ts # обгортка над Telegram WebApp SDK
│ └── icons.tsx # inline SVG-іконки (заміна емодзі, що криво рендерились)
├── run_web.py # Продакшн-запуск backend (waitress) + планувальник (APScheduler)
├── run_bot.py # Запуск бота
├── deploy.sh # Одна команда: git pull → deps → build → restart
└── requirements.txt
Ключові рішення
- Уся покупка — в Mini App. Перегляд меню, кошик і повне оформлення
замовлення (адреса/ім'я/телефон/час/спосіб оплати, промокод) —
звичайна форма в Mini App, без багатокрокового діалогу в чаті.
Кошик спільний для бота й Mini App (одна таблиця
cart_items, прив'язана доtelegram_id). - Бот — тонкий.
/start, меню з кнопкою Mini App, контакти, автосповіщення про статус замовлення й запит оцінки. Бот і backend працюють в одному Flask app-контексті напряму через SQLAlchemy, без зайвого HTTP-стрибка —bot/main.pyпушитьflask_app.app_context()один раз на старті, тож будь-який хендлер (включно з callback'ами на inline-кнопки оцінки) звертається доdb.sessionтак само, як і веб-бекенд. - Самообслуговування клієнта. У «Мої замовлення» клієнт може сам скасувати замовлення, поки воно ще не в роботі (статус «Нове» або «Підтверджено»), повторно відкрити оплату карткою в будь-який момент (кожен клік створює свіжий інвойс monobank, тож стара протухла сторінка оплати ніколи не блокує клієнта), і повторити минуле замовлення одним натисканням.
- Оплата картою (monobank) з подвійною страховкою.
- Вебхук monobank підтверджує оплату миттєво (підпис перевіряється ECDSA-ключем, який видає сам monobank).
- На випадок, якщо вебхук не дійшов (мережевий збій, зміна домену
тощо) — фоновий job раз на 10 хв напряму звіряє статус неоплачених
card-замовлень з API monobank і донараховує оплату сам
(
bober_bbq/utils/reconciliation.py). - Окремий job раз на годину перевіряє, чи досі робочий токен monobank, і одразу пише власнику в Telegram, якщо ні — щоб «тихий» збій оплати не залишився непоміченим.
- Тестовий режим оплати (окремий токен, перемикається в адмінці) — можна прогнати весь цикл оплати фейковою карткою без реальних грошей, перш ніж вмикати бойовий токен.
- Фіскалізація ніколи не блокує замовлення.
checkbox_prro.py— повністю опційний модуль: коли вимкнено — жодного мережевого виклику; коли увімкнено — будь-яка помилка Checkbox (мережа, неправильні дані, збій API) ловиться, пишеться вOrder.fiscal_status/fiscal_errorі не перериває обробку оплати. Триггер — момент фактичної оплати (не створення замовлення):orders_mark_paidдля готівки, вебхук і реконсиляція monobank для картки, ручне створення вже оплаченого замовлення в адмінці — усі три місця викликають один спільнийmaybe_fiscalize(). - Схема БД без Alembic.
db.create_all()створює нові таблиці, але ніколи не додає колонки до вже існуючих. Замість повноцінних міграцій —bober_bbq/migrate.py: списокALTER TABLE ... ADD COLUMN, кожен виконується лише якщо колонки ще немає. Викликається на кожному старті (run_web.pyіbot/main.py), безпечно й ідемпотентно. Додаючи нове поле в модель — не забути додати рядок сюди. - CSRF-захист.
Flask-WTFпід'єднано глобально; публічний/api/*явно виключений з CSRF-перевірки — кожен вкладений під-blueprint (menu,cart,checkout,orders,settings,payments,me) виключається окремо, боcsrf.exempt()на батьківському blueprint не гарантовано каскадується на дочірні. Усі форми адмінки містять прихованийcsrf_token. - Замовлення без Telegram (гість).
require_customer_auth(bober_bbq/api/auth.py) — те саме, що йrequire_telegram_auth(перевірка підписуX-Telegram-Init-Data), але коли підпису немає — замість 401 віддає доступ анонімному «гостю»:TelegramUserз від'ємнимtelegram_id(allocate_guest_telegram_id(),bober_bbq/models.py), прив'язаному до сесійної Flask-куки. Той самий принцип, що йWALKIN_TELEGRAM_ID = -1для ручних замовлень з адмінки, тільки кожен гість отримує свій унікальний id, щоб кошики різних людей не змішувались. Кожне замовлення (і гостьове, і Telegram) отримуєOrder.tracking_token— випадковий рядок для перегляду статусу за посиланням/webapp/?track=<token>(GET /api/checkout/track/<token>, без авторизації) — на випадок, якщо сесійна кука загубиться. Персонал/адмінка (розсилка, статистика клієнтів, PDF-чеки Checkbox) явно виключають і walk-in, і гостей — вони не «справжні» повторні клієнти. - Промокоди зберігають знижку у відсотках і опційно: мінімальну суму замовлення, ліміт використань, термін дії, обмеження «лише перше замовлення». Знижка від промокоду підсумовується зі знижкою за самовивіз (обидві незалежні), а не замінює її. Валідація єдина для превʼю-ендпоінту («Застосувати» в Mini App) і для реального оформлення замовлення — щоб клієнт ніколи не побачив «діє», а потім отримав відмову при оформленні з інших причин.
- Адмінка адаптивна під мобільні — бічне меню згортається в висувну панель, широкі таблиці на телефоні перетворюються на список карток замість горизонтального скролу.
Швидкий старт (локально)
- Залежності (Python 3.11+, Node 20+):
pip install -r requirements.txt
cd webapp && npm install && npm run build && cd ..
-
Скопіюйте
.env.example→.envі заповнітьBOT_TOKEN,OWNER_IDS,WEBAPP_URL/BACKEND_PUBLIC_URL(публічний HTTPS-домен — Telegram Mini App і вебхук monobank не працюють по HTTP). -
Запустіть backend (API + адмінка + Mini App):
python run_web.py
Адмінка: http://localhost:8000/admin. Перший запуск створює таблиці й
демо-меню (bober_bbq/seed.py) — заміните на реальне через адмінку.
Токен і решту налаштувань оплати monobank теж редагуються в адмінці
(Налаштування → Оплата карткою), .env-значення лише запасні на
випадок, якщо адмінка ще не налаштована.
- Бот (окремий процес):
python run_bot.py
Локальна розробка Mini App (гаряче перезавантаження)
cd webapp
npm run dev
Vite проксує /api/* на http://localhost:8000. Поза Telegram
справжнього initData немає — у режимі app.debug=True API приймає
?dev_user_id=<число> як заглушку (вимкнено в проді).
Продакшн-сервер
Проєкт розгорнутий на окремому VPS (Debian 13, публічна IP), домен
webapp.boberbbq.com, HTTPS — справжній сертифікат Let's Encrypt через
nginx + certbot (автопоновлення налаштоване стандартним certbot.timer).
Інтернет → nginx (443, TLS через Let's Encrypt) → 127.0.0.1:8000 (waitress)
Структура на сервері
/opt/bober-bbq-bot/ # git-клон репозиторію (власник: claude)
/opt/bober-bbq-bot/.venv/ # Python venv
/opt/bober-bbq-bot/.env # BOT_TOKEN / SECRET_KEY / запасні значення (не в git)
/etc/nginx/sites-available/bober-bbq # reverse proxy 443 → 127.0.0.1:8000
/etc/letsencrypt/live/webapp.boberbbq.com/ # TLS-сертифікат
/etc/systemd/system/bober-bbq-web.service
/etc/systemd/system/bober-bbq-bot.service
/var/log/bober-bbq-web.log
/var/log/bober-bbq-bot.log
Сервіси запускаються від імені користувача claude (не root), керування
через sudo.
Керування сервісами
ssh claude@<IP сервера>
# статус
sudo systemctl status bober-bbq-web bober-bbq-bot nginx
# логи наживо
tail -f /var/log/bober-bbq-web.log
tail -f /var/log/bober-bbq-bot.log
# перезапуск після зміни .env або коду
sudo systemctl restart bober-bbq-web bober-bbq-bot
Оновлення коду на сервері
Одна команда:
bash /opt/bober-bbq-bot/deploy.sh
Робить git pull, ставить Python- і npm-залежності, збирає Mini App і
перезапускає обидва сервіси (а разом з ними — migrate(), який
підхоплює нові колонки БД).
systemd-юніти запускають сервіси від імені
claude, тому командиsystemctlв них і вdeploy.shвиконуються зsudo— при інтерактивному запуску буде запит пароля.
Якщо змінювались лише шаблони/статика (без Python-коду) — рестарт сервісу не обов'язковий:
TEMPLATES_AUTO_RELOAD = Trueпідхоплює зміни на льоту. Але якщо змінювались і Python, і шаблони одночасно, варто рестартувати одразу післяgit pull, а не чекати — інакше в проміжку старий процес може спробувати відрендерити новий шаблон, що посилається на ще не зареєстрований роут, і віддати 500 на один випадковий запит.
Моніторинг
GET /health повертає {"status": "ok"} (200) після реальної
перевірки з'єднання з БД, або {"status": "error", ...} (503) — саме
цей ендпоінт має пінгувати зовнішній uptime-сервіс (UptimeRobot,
Better Uptime тощо), щоб дізнатись про падіння сайту раніше за скаргу
клієнта.
Фонові job'и (APScheduler, всередині bober-bbq-web)
Стартують разом з run_web.py, окремого сервісу не потребують:
| Job | Періодичність | Що робить |
|---|---|---|
reconcile_payments |
кожні 10 хв | звіряє неоплачені card-замовлення за останні 6 год напряму з monobank — страховка на випадок пропущеного вебхука |
monobank_token_health |
щогодини | пінгує токен monobank; якщо робочий токен раптом перестав діяти — пише власнику (OWNER_IDS) в Telegram |
gdrive_backup |
щогодини (перевіряє) | якщо увімкнено й минув налаштований інтервал — вивантажує свіжий бекап у Google Drive і чистить застарілі копії; при збої пише власнику в Telegram |
Налаштування в адмінці (без доступу до сервера)
Адмінка → Налаштування охоплює майже все, що раніше вимагало правки
.env і рестарту:
- Заклад: назва, лого (використовується і як іконка Mini App/PWA — оновлюється автоматично при зміні лого), телефон, адреса, графік роботи, Instagram/карта.
- Доставка й самовивіз: вартість доставки, поріг безкоштовної доставки, мінімальна сума замовлення на доставку, знижка самовивозу.
- Telegram-чати для сповіщень про нові замовлення (окремо доставка й самовивіз).
- Сповіщення клієнтів: автоповідомлення про зміну статусу замовлення і — окремим перемикачем — запит оцінки (1–5) після «Виконано».
- Оплата карткою (monobank): бойовий токен, тестовий токен + перемикач
тестового режиму, кнопка «Перевірити» (звіряє токен з monobank без
створення платежу), опис платежу (шаблон з
{number}), показ/приховання списку товарів на сторінці оплати monobank. - Вигляд: колір адмінки й колір Mini App окремо (по одному пікеру кольору — решта відтінків підбирається автоматично).
- Фіскалізація (ПРРО Checkbox): вимкнена за замовчуванням; логін, пароль касира, ліцензійний ключ каси, кнопка «Перевірити підключення», перемикач «надсилати чек клієнту в Telegram».
- Промокоди — окремий розділ («Промокоди» в меню): створення, вимкнення, видалення.
- Відгуки клієнтів — окремий розділ («Відгуки»): середня оцінка, розподіл по зірках, фільтр і пагінація.
- Розсилка повідомлення всім клієнтам бота.
- Резервні копії БД: створення, відновлення, видалення — прямо з адмінки, плюс автоматичні бекапи в Google Drive з ротацією (Адмінка → Резервні копії → секція «Google Drive», з покроковою інструкцією налаштування сервісного акаунта прямо на сторінці).
- Облік сировини: перемикач «Увімкнути облік сировини», нижче в тому ж розділі — при увімкненні в меню з'являється «Склад».
Чек-лист перед реальним запуском
Токен бота— вже бойовий (@BoberBBQ_bot).Пароль адмінки— вже змінено власником.- Токен monobank — перевірте кнопкою «Перевірити» в Налаштуваннях: на момент останньої перевірки бойовий токен був недійсний/без доступу до еквайрингу. Перевипустіть у застосунку Monobank (Ще → Мій бізнес → Прийом платежів → Токени) і вставте новий.
- Переконайтесь, що тестовий режим оплати вимкнено перед стартом реальних продажів (в Налаштуваннях є явне попередження, коли він активний).
- Наповніть реальне меню (категорії/товари) через адмінку, якщо ще не зроблено.
- Додайте бота адміністратором у чати доставки/самовивозу, звірте їх
chat_idв Налаштуваннях (Telegram інколи мігрує групу в супергрупу й міняє ID — якщо сповіщення раптом перестали приходити, це перша підозра). - Підключіть зовнішній uptime-моніторинг до
GET /health. - (Опційно) Якщо потрібна фіскалізація — зареєструйте ПРРО в податковій і касу в Checkbox (кроки й посилання обговорювались окремо), вставте логін/пароль/ліцензійний ключ у Налаштування → Фіскалізація, перевірте підключення і тільки тоді вмикайте перемикач.
Додатково
- Детальніше про перше розгортання з нуля —
docs/DEPLOYMENT.md(описує загальний процес; конкретні шляхи/сервер вище в цьому файлі — джерело правди для поточного продакшену). - Пункти, узгоджені із замовником у процесі розробки —
docs/OPEN_QUESTIONS.md. - Ідеї на майбутнє (нереалізовані, без дедлайну) —
docs/TODO.md.