Архитектура
Технологический стек, роли и RBAC, условный UI, потоки данных заказа и ключевые модули приложения Чуйгун.
Стек
Подтверждён решениями #57 и #58.
- Frontend: Next.js 15.5.20 (App Router) + React 19 + TypeScript. Апгрейд с Next 14.2.15 / React 18 сделан ради Cloudflare-адаптера OpenNext (#57).
- UI: shadcn/ui + Tailwind + Framer Motion. Иконки — Lucide React, графики — Recharts, drag&drop —
@dnd-kit. - State: Zustand + persist (корзина работает offline). Валидация — Zod (клиент + сервер).
- i18n: next-intl, локали
ru(default) /en/uz. Конфигapps/web/src/i18n/routing.ts, переводыapps/web/messages/{locale}.json. - Backend: Supabase (Postgres + Auth + Realtime + Storage). Своего бэка нет — всё из коробки за 20 дней (#1).
- Realtime: Supabase Realtime (Postgres CDC → WebSocket), бесплатно до 200 connections.
- Печать: локальный Node.js print-agent на ноутбуке кассы (см. Печать).
- Hosting: Cloudflare Workers (фронт) + Supabase (бэк) + Cloudflare DNS.
Роли и RBAC
Роли: admin, manager, waiter, cook. Роль waiter заменила cashier (#22, migration 044 мигрирует данные + RLS + JWT).
Матрица доступа (middleware apps/web/src/lib/auth/rbac.ts):
| Маршрут | Кто имеет доступ |
|---|---|
/admin/orders | waiter / manager / admin |
/admin/menu, /admin/tables | manager / admin |
/admin/users | admin |
/kitchen | cook / manager / admin |
Три независимых слоя защиты (defence in depth):
- middleware RBAC — проверка роли на маршруте.
- RLS policies — построчная защита в Postgres.
- SECURITY DEFINER RPC — ре-проверка роли на сервере (
current_is_order_staff).
stripLocale() нормализует путь до канонического перед проверкой RBAC-матрицы.
Условный UI по ролям
Решения #47, #48, #52.
ConditionalHeader/ConditionalFooter: официант видитWaiterHeaderс табами столов, гость — стандартный хедер.- Отдельная страница
/menu-waiterдля официанта (не адаптация/menu— попытка адаптации давала бесконечные редиректы). Middleware редиректит waiter с/menuна/menu-waiter(только роль waiter, без QR-параметров). - После логина: waiter →
/menu(→/menu-waiter), остальные →/admin/orders.
Потоки данных
Заказ со стола (QR)
Гость → QR /menu?table=N&token=UUID → middleware валидирует через RPC validate_table_qr → HttpOnly-cookie table_session → корзина (Zustand persist) → /checkout → RPC create_order → Realtime CDC → кассир принимает (status accepted) → print-agent печатает + кухня видит карточку.
Онлайн-заказ (доставка / самовывоз)
/menu без table → корзина → /checkout (source delivery / pickup, имя / телефон / адрес) → create_order → кассир.
Статусы заказа
new → accepted → cooking/preparing → ready → closed, плюс cancelled. Переход только через RPC update_order_status (forward-only в UI, но есть откат ready → preparing, #26).
Ключевые модули
Каталог apps/web/src/:
| Модуль | Назначение |
|---|---|
lib/cart/ | Zustand-стор корзины с persist |
lib/orders/ | бизнес-логика заказов, канбан |
lib/auth/ | RBAC, сессии, middleware-хелперы |
lib/qr/ | валидация QR, table sessions |
lib/reports/ | агрегации для отчётов |
lib/api/ | обёртки над Supabase RPC |
components/admin/, components/menu/ | админ-панель, карточки блюд и категории |