Skip to main content

Docs Access System

1. Summary

Goal: Многоуровневая система контроля доступа к документации. Позволяет делиться документацией с внешними пользователями без раскрытия конфиденциальной информации.

User Value: Owner может создать временную ссылку для партнёра/инвестора/коллеги с ограниченным доступом — без регистрации и паролей.


2. Business Logic

Access Levels

Получение доступа: Invite Link

Что видит: Только страницы с visibility: viewer (или без указания)

Срок действия: Определяется при создании ссылки (от 1 часа до 30 дней, дефолт 1 час)

Use case: Партнёры, инвесторы, внешние разработчики

Механизм создания временных ссылок для viewer доступа:

1. Генерация (Admin Panel)

  • Owner создаёт ссылку с параметрами: TTL, заметка, лимит использований
  • Генерируется stateless JWT-like токен с HMAC подписью

2. Активация (User)

  • Пользователь переходит по ссылке
  • Backend валидирует подпись и срок действия
  • Устанавливается docs_viewer cookie
Stateless Architecture

Токен содержит все данные (expiresAt, usageLimit, note). Не требует хранения в БД — только подпись гарантирует целостность.

3. Usage Tracking

ХранилищеДанныеTTL
RedisСчётчик использований= срок жизни токена
PostgreSQLНичего-

Hidden Activation

Секретные комбинации для активации режимов на docs-сайте:

РежимКомбинацияРезультат
Admin5 кликов за 3 секМодалка подтверждения
Owner10 кликов за 5 секМодалка 2FA
Security by Obscurity?

Нет. Это только UX — скрываем от обычных пользователей. Реальная защита:

  • Admin: требует предварительный логин в админку (docs_session cookie)
  • Owner: требует 2FA код (TOTP)

Edge Cases

Что происходит при ошибках:

СитуацияПоведение
Ссылка просроченаHTML страница "Ссылка недействительна"
Лимит исчерпанHTML страница "Лимит исчерпан"
Redis недоступенGraceful degradation — лимит не проверяется
Неверный 2FA код"Invalid code" в модалке
Backend Error Responses
ЭндпоинтОшибкаHTTPФормат
/docs/invite/*Invalid token400HTML
/docs/invite/*Usage limit400HTML
/docs/verify-ownerNo session401JSON
/docs/verify-ownerInvalid 2FA401JSON

3. ADR (Architectural Decisions)

Почему Stateless токены?

Проблема: Нужны временные ссылки без регистрации пользователей.

Решение: JWT-like токены с HMAC-SHA256 подписью. Вся информация в токене.

Альтернативы (отклонены):

  • Хранение в БД — overhead на запись/чтение при каждом переходе
  • UUID ссылки — требуют lookup в БД

Последствия:

  • Нельзя отозвать конкретную ссылку (только сменой JWT_SECRET)
  • Нет истории созданных ссылок
  • Минимальная нагрузка на БД

Почему Redis для счётчика?

Проблема: Нужно ограничить количество использований ссылки.

Решение: Атомарный INCR в Redis с TTL.

Альтернативы (отклонены):

  • PostgreSQL counter — блокировки при concurrent requests
  • In-memory counter — не работает при нескольких инстансах

Последствия: Зависимость от Redis, но graceful degradation при недоступности.

Почему Traefik ForwardAuth?

Проблема: Документация на отдельном домене (docs.goloot.online), нужна проверка доступа.

Решение: Traefik вызывает /admin-auth/verify-docs перед каждым запросом.

Альтернативы (отклонены):

  • Client-side проверка — легко обойти
  • Nginx auth_request — менее гибко чем Traefik

Последствия: Каждый запрос к docs проходит через backend проверку.


4. Architecture

Authentication Flow

Key Components

КомпонентПутьОписание
DocsVisibilityServicebackend/src/domains/admin/services/docs-visibility.service.tsГенерация/валидация токенов
DocsVisibilityRoutesbackend/src/domains/admin/routes/docs-visibility.routes.tsAPI эндпоинты
AdminAuthRoutesbackend/src/domains/admin/routes/admin-auth.routes.tsForwardAuth verify-docs
VisibilityContextdocs-site/src/contexts/VisibilityContext.tsxReact контекст уровня доступа
TwoFactorModaldocs-site/src/components/TwoFactorModal/UI для 2FA

5. Cookies & Storage

CookieИмяDomainMax-AgeHttpOnlySecure
Viewerdocs_viewer.goloot.online= TTL токенаYesYes
Admin Sessiondocs_session.goloot.online8 часовYesYes
Ownerdocs_owner.goloot.online4 часа (ENV)YesYes

Client Storage

ДанныеХранилищеTTL
Admin mode flaglocalStorage4 часа (ENV, проверяется при загрузке)
Click countersReact stateСессия

ENV Configuration

TTL для owner и admin сессий конфигурируется через переменные окружения:

ПеременнаяОписаниеДефолт
DOCS_OWNER_TTL_MINUTESTTL owner cookie240 (4 часа)
DOCS_ADMIN_TTL_MINUTESTTL admin localStorage240 (4 часа)
Development

Для разработки можно установить большие значения (например, 99999) чтобы не переавторизовываться.


6. API Endpoints

МетодЭндпоинтОписаниеAuth
POST/docs/inviteСоздать invite ссылкуJWT (Admin)
GET/docs/invite/*Активировать ссылкуNone

7. Security Considerations

Token Security

  • HMAC-SHA256 подпись предотвращает подделку
  • Expiration встроен в payload
  • Смена JWT_SECRET инвалидирует ВСЕ токены
  • HttpOnly — защита от XSS
  • Secure — только HTTPS
  • SameSite=Lax — защита от CSRF
  • Domain=.goloot.online — работает на всех поддоменах

Rate Limiting

Стандартный rate limit сервера применяется ко всем эндпоинтам.

Отзыв доступа

Invite-токены stateless — нет записи в БД, поэтому отозвать конкретный токен невозможно.

СпособЧто происходитПоследствия
Ждать TTLViewer cookie истекает автоматическиШтатный способ. Дефолт TTL — 1 час
Сменить JWT_SECRETВсе токены и cookies инвалидируются мгновенно"Ядерная кнопка": ломает ВСЕ сессии (viewer, admin, owner). После смены — перелогиниться в админке
JWT_SECRET — экстренный kill switch

Смена JWT_SECRET в Dokploy → Backend → Environment → Redeploy мгновенно инвалидирует:

  • Все docs_viewer cookies (invite-сессии)
  • Все docs_session cookies (admin-сессии)
  • Все docs_owner cookies (owner-сессии)
  • Все JWT-токены админки

Единственный пользователь JWT — админка (ты), поэтому последствия минимальны: просто перелогиниться.

Минимизация риска

При создании invite-ссылок ставь минимальный TTL (дефолт — 1 час). Так даже при утечке ссылки окно уязвимости минимальное.


  • Docs Deployment — CI/CD для docs site, visibility plugin
  • User Management — управление пользователями в админке
  • Analytics — дашборды и метрики