Ограничения (Constraints)
Правила, которые агенты обязаны учитывать при генерации артефактов. Каждое ограничение имеет уникальный ID для ссылок в user stories и спеках.
C-001: Один слот — одно бронирование на мастера
- Источник: бизнес-логика
- Правило: Два бронирования одного мастера не могут пересекаться по времени (start_at..end_at). Слот считается занятым на всю длительность услуги.
- Для агента: При генерации user stories и API спек учитывать, что проверка overlap обязательна. В текущем коде проверка на стороне бэкенда отсутствует (TODO в коде) — фронтенд полагается на данные GET /slots, но race condition возможен.
- Нарушение: Двойное бронирование (double booking). Клиент приходит, а мастер занят другим клиентом.
C-002: Персональные данные клиентов не в логах
- Источник: безопасность / GDPR-like
- Правило: Телефон клиента, имя и Telegram ID не должны появляться в production-логах в открытом виде. Допустимо: маскированный формат (7***7001) или ID записи.
- Для агента: При проектировании логирования и error-handling — маскировать PII. При генерации тест-кейсов — проверять, что логи не содержат PII.
- Нарушение: Утечка персональных данных через лог-файлы. ⚠️ В текущем коде это ограничение НАРУШАЕТСЯ — telegram_handler.py логирует полные телефоны и chat_id.
C-003: Telegram Bot API — лимиты отправки
- Источник: Telegram API
- Правило: Telegram Bot API ограничивает отправку: не более 30 сообщений в секунду в разные чаты, не более 1 сообщения в секунду в один чат. Inline-keyboard максимум 8 кнопок в ряд, callback_data до 64 байт.
- Для агента: При проектировании массовых уведомлений (напоминания) необходим rate limiter / очередь. callback_data формат: короткие префиксы (confirm_, reject_, ra_, rd_) + UUID (36 байт) = 43-45 байт — укладывается в лимит.
- Нарушение: HTTP 429 от Telegram API, сообщения не доставляются. При превышении — временная блокировка бота.
C-004: Минимальная длительность услуги — 1 минута
- Источник: бизнес-логика / валидация
- Правило: Длительность услуги (Service.duration) ≥ 1 минуты. При регистрации: max(1, int(service_in.duration or 30)). Максимум не ограничен в коде, но разумный предел — 480 минут (8 часов, полный рабочий день).
- Для агента: При генерации API спек и валидационных правил: duration ∈ [1, 480]. Дефолт: 30 минут. Слот не может быть короче длительности услуги.
- Нарушение: duration=0 → booking с start_at == end_at, сломанная логика busy intervals.
C-005: Расписание — 7 дней, приоритет мастера над бизнесом
- Источник: бизнес-логика
- Правило: Расписание состоит из ровно 7 записей (0=Mon..6=Sun). Два уровня: бизнес (master_id=NULL) и мастер. При расчёте слотов: если у мастера есть своё расписание на этот день — используется оно, иначе — fallback на бизнес-расписание.
- Для агента: При генерации user stories о расписании — всегда учитывать двухуровневую иерархию. При тест-кейсах — проверять fallback.
- Нарушение: Мастер работает по бизнес-расписанию, хотя у него свои часы. Или наоборот: нет ни мастерского, ни бизнес-расписания → слоты не генерируются.
C-006: RescheduleProposal истекает через 24 часа
- Источник: бизнес-логика
- Правило: Предложение переноса (RescheduleProposal) действует 24 часа (expires_at = created_at + 24h). Если клиент не ответил — статус переходит в EXPIRED при следующем GET-запросе (lazy expiration). Одновременно может существовать только один PENDING proposal на booking.
- Для агента: При проектировании уведомлений о переносе — учитывать TTL. При user stories — описывать сценарий timeout. При API спеках — документировать идемпотентность и lazy expiration.
- Нарушение: Провайдер создаёт второй proposal, пока первый PENDING → HTTP 409.
C-007: Slug — уникальный идентификатор бизнеса в URL
- Источник: архитектура / UX
- Правило: Business.slug уникален в системе. По умолчанию — нормализованный телефон (10 цифр, без +7/8). Используется в URL: cita.kz/{slug}. Может быть изменён через PUT /business, но проверяется на уникальность. Формат: [a-z0-9-]+.
- Для агента: При генерации user stories о регистрации — учитывать дедупликацию slug (суффикс -2, -3...). При API спеках — slug в URL path, не в query.
- Нарушение: Два бизнеса с одинаковым slug → один из них недоступен по URL.
C-008: JWT токен — 8 дней для админа, 24 часа для суперадмина
- Источник: безопасность
- Правило: Access token для Admin/Staff: ACCESS_TOKEN_EXPIRE_MINUTES = 60 * 24 * 8 = 11520 минут (8 дней). Для SuperAdmin: 24 часа. Refresh token отсутствует. Алгоритм: HS256.
- Для агента: При проектировании security-sensitive фич — учитывать, что токен живёт 8 дней без refresh. При API спеках — документировать, что 401 = нужен повторный логин. При user stories — UX при истечении токена.
- Нарушение: Пользователь внезапно теряет сессию после 8 дней без re-login.
C-009: reCAPTCHA обязательна для публичных мутаций
- Источник: безопасность / anti-spam
- Правило: Google reCAPTCHA v3 проверяется при: создании бронирования (POST /public/{slug}/booking) и регистрации бизнеса (POST /auth/register). Если recaptcha_token не передан или невалиден — операция отклоняется.
- Для агента: При генерации API спек для публичных endpoints — включать recaptcha_token в request body. При тест-кейсах — мокать reCAPTCHA в test env.
- Нарушение: Спам-записи, DoS через массовое создание бронирований.
C-010: Цена фиксируется в момент записи
- Источник: бизнес-логика
- Правило: При создании бронирования цена услуги копируется в booking.price_snapshot. Дальнейшие изменения Service.price не влияют на существующие бронирования. Формат: float, валюта: ₸ (тенге).
- Для агента: При генерации user stories о ценообразовании — учитывать snapshot-семантику. При аналитике — использовать price_snapshot, не Service.price.
- Нарушение: Клиенту выставляется новая цена, хотя записывался по старой.
C-011: Автоназначение мастера при отсутствии выбора
- Источник: бизнес-логика / UX
- Правило: Если клиент не выбрал мастера (master_id=null в booking request): 1) ищется мастер, привязанный к выбранной услуге (M2M), 2) если нет — любой мастер бизнеса, 3) если мастеров нет вообще — HTTP 400. Алгоритм: первый найденный (LIMIT 1), без учёта загруженности.
- Для агента: При user stories «запись к любому мастеру» — описывать fallback-цепочку. При тест-кейсах — покрывать все 3 ветки. При улучшениях — предлагать load balancing (наименее загруженный мастер).
- Нарушение: Все записи попадают к одному мастеру (первому в БД), остальные простаивают.