access: демо-QR — многоразовое приглашение для презентации #55

Closed
opened 2026-10-22 18:06:13 +03:00 by Eleboba · 1 comment
Owner

Описание

На защите (docs/DEMO.md) хотим, чтобы любой из зала отсканировал один QR с экрана и попробовал бота. Сейчас приглашение одноразовое (SPEC A-3, ADR-011): первый, кто отсканирует, его «забирает», остальные получают отказ. Нужно многоразовое демо-приглашение с лимитом и сроком, а после показа — отключение всех вошедших по нему одной кнопкой.

Желаемый результат

  • Админ в «👥 Участники» жмёт «🎤 Демо-QR» → QR на N входов (по умолчанию 50), живёт несколько часов (по умолчанию 3 ч); в подписи — лимит и срок.
  • По этому QR входят до N разных людей; N+1-й, или после срока, — тот же отказ, что сейчас.
  • Обычное «➕ Пригласить» по-прежнему одноразовое.
  • «🧹 Отключить гостей демо» (с подтверждением) отзывает доступ у всех, кто вошёл по демо-приглашению; админы не затрагиваются.

Подзадачи

  • app/db/models.py: Invite.max_uses (1), Invite.uses (0); User.invite_id → invites.id — миграция alembic, существующие использованные приглашения → uses=1
  • app/access/service.py: create_invite(max_uses, ttl), атомарный захват uses < max_uses, revoke_demo_guests()
  • app/config.py: DEMO_INVITE_MAX_USES, DEMO_INVITE_TTL_HOURS
  • app/bot/routers/members.py, config/texts.yaml: кнопки «Демо-QR» и «Отключить гостей демо»
  • Тесты: лимит, гонка за последний вход, срок, отзыв гостей, миграция
  • SPEC A-3, ADR-011 (дополнение), docs/DEMO.md

Анализ

Затрагиваемые файлы

Файл Что меняется
app/db/models.py, app/db/migrations/versions/ поля лимита и связь участник → приглашение
app/access/service.py многоразовый захват, массовый отзыв
app/bot/routers/members.py, config/texts.yaml UI админа
app/config.py, .env.example лимит и срок демо-QR
docs/SPEC.md, docs/DECISIONS.md, docs/DEMO.md исключение из одноразовости

Ограничения и риски

  • Гость = обычный участник: может коммитить (код идёт только в песочницу tgit-runner, guardrail 2), получает алерты, спрашивает агента (дневной лимит на человека уже есть).
  • QR на экране может сфотографировать кто угодно → короткий срок + лимит + массовый отзыв после показа.
  • Захват атомарный (UPDATE … WHERE uses < max_uses), как сейчас для одноразовых.

Как проверить

make lint && make test; на dev: админ создаёт демо-QR → 2–3 аккаунта входят → «Отключить гостей демо» → их кнопки перестают работать.


Лог выполнения

## Описание На защите (`docs/DEMO.md`) хотим, чтобы любой из зала отсканировал **один QR** с экрана и попробовал бота. Сейчас приглашение одноразовое (SPEC A-3, ADR-011): первый, кто отсканирует, его «забирает», остальные получают отказ. Нужно многоразовое демо-приглашение с лимитом и сроком, а после показа — отключение всех вошедших по нему одной кнопкой. ## Желаемый результат - Админ в «👥 Участники» жмёт «🎤 Демо-QR» → QR на N входов (по умолчанию 50), живёт несколько часов (по умолчанию 3 ч); в подписи — лимит и срок. - По этому QR входят до N разных людей; N+1-й, или после срока, — тот же отказ, что сейчас. - Обычное «➕ Пригласить» по-прежнему одноразовое. - «🧹 Отключить гостей демо» (с подтверждением) отзывает доступ у всех, кто вошёл по демо-приглашению; админы не затрагиваются. ## Подзадачи - [ ] `app/db/models.py`: `Invite.max_uses` (1), `Invite.uses` (0); `User.invite_id` → `invites.id` — миграция alembic, существующие использованные приглашения → `uses=1` - [ ] `app/access/service.py`: `create_invite(max_uses, ttl)`, атомарный захват `uses < max_uses`, `revoke_demo_guests()` - [ ] `app/config.py`: `DEMO_INVITE_MAX_USES`, `DEMO_INVITE_TTL_HOURS` - [ ] `app/bot/routers/members.py`, `config/texts.yaml`: кнопки «Демо-QR» и «Отключить гостей демо» - [ ] Тесты: лимит, гонка за последний вход, срок, отзыв гостей, миграция - [ ] SPEC A-3, ADR-011 (дополнение), `docs/DEMO.md` ## Анализ ### Затрагиваемые файлы | Файл | Что меняется | |------|--------------| | `app/db/models.py`, `app/db/migrations/versions/` | поля лимита и связь участник → приглашение | | `app/access/service.py` | многоразовый захват, массовый отзыв | | `app/bot/routers/members.py`, `config/texts.yaml` | UI админа | | `app/config.py`, `.env.example` | лимит и срок демо-QR | | `docs/SPEC.md`, `docs/DECISIONS.md`, `docs/DEMO.md` | исключение из одноразовости | ### Ограничения и риски - Гость = обычный участник: может коммитить (код идёт только в песочницу `tgit-runner`, guardrail 2), получает алерты, спрашивает агента (дневной лимит на человека уже есть). - QR на экране может сфотографировать кто угодно → короткий срок + лимит + массовый отзыв после показа. - Захват атомарный (`UPDATE … WHERE uses < max_uses`), как сейчас для одноразовых. ## Как проверить `make lint && make test`; на dev: админ создаёт демо-QR → 2–3 аккаунта входят → «Отключить гостей демо» → их кнопки перестают работать. --- ## Лог выполнения
Eleboba added the botfeaturesize/1 labels 2026-10-22 18:06:17 +03:00
Author
Owner

2026-10-22

  • Многоразовое приглашение: invites.max_uses/uses, флаг users.guest вместо users.invite_id (иначе цикл FK users ↔ invites).
  • revoke_guests() заодно гасит действующие демо-QR.
  • Миграция 0003: batch на SQLite пересоздавал users и валил FK с данными → обычный ADD COLUMN. Проверено на Postgres 16.
  • ADR-017. make lint && make test — 368 passed. PR #56.
### 2026-10-22 - Многоразовое приглашение: `invites.max_uses/uses`, флаг `users.guest` вместо `users.invite_id` (иначе цикл FK users ↔ invites). - `revoke_guests()` заодно гасит действующие демо-QR. - Миграция 0003: batch на SQLite пересоздавал `users` и валил FK с данными → обычный ADD COLUMN. Проверено на Postgres 16. - ADR-017. `make lint && make test` — 368 passed. PR #56.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: HSE/tgit#55