20 KiB
20 KiB
[0.4.6-beta] - 2026-09-26
Добавлено
- Email Anonymization on Delete: Полное обезличивание PII при удалении аккаунта — email заменяется на HMAC-SHA256 хеш,
registration_ipобнуляется,password_hashочищается. Соответствует требованиям GDPR (право на забвение). - Re-registration Prevention: Защита от повторной регистрации с тем же email после удаления аккаунта. При удалении email хешируется через
utils.HashIdentifierWithKey()с секретным ключом приложения, при регистрации проверяется наличие хеша в базе. - GetByEmailIncludingDeleted: Новый метод в
UserRepositoryдля поиска пользователей по email или его хешу, включая удалённые записи (без фильтраdeleted_at IS NULL). - PII Cleanup: При удалении аккаунта также обнуляется
registration_ipдля полного удаления персональных данных из базы. - Register Validation: Добавлена проверка на наличие удалённого аккаунта с тем же email через поиск хеша в базе. Возвращается новая ошибка
ErrEmailPreviouslyDeletedс HTTP 403 Forbidden. - Frontend i18n: Добавлены переводы для новой ошибки
email_previously_deleted(RU/EN) с объяснением причины блокировки регистрации.
Изменено
- DeleteAccount Flow: Переписан процесс удаления аккаунта — теперь email хешируется перед сохранением в БД вместо конкатенации
'deleted_' || id || '_' || email. - UserRepository Interface: Расширен интерфейс — добавлен метод
GetByEmailIncludingDeleted(ctx, emailOrHash)для поддержки поиска по хешу. - Error Handling: Новый тип ошибки
ErrEmailPreviouslyDeletedс понятным сообщением для пользователя: "This email was previously used for a deleted account and cannot be reused".
Безопасность
- HMAC-SHA256: Используется криптографически стойкий HMAC с секретным ключом приложения (
cfg.App.Secret) для хеширования email. Без знания секрета невозможно восстановить оригинальный email из хеша. - No PII Leaks: В случае утечки базы данных злоумышленник получит только необратимые хеши вместо реальных email-адресов удалённых пользователей.
- Abuse Prevention: Невозможно обойти лимиты или получить приветственные бонусы повторно через цикл "удаление → регистрация".
[0.4.5-beta] - 2026-09-25
Добавлено
- ConvertOptions: Четыре новые опции конвертации для гибкой настройки вывода:
include_title— добавляет заголовок страницы как H1 (# Title) в начало документаinclude_frontmatter— добавляет YAML-шапку с метаданными (title,source,bytes,tokens)strip_images— удаляет все<img>теги из результатаstrip_links— удаляет<a>теги, сохраняя текст ссылок
- Two-Level Cache Architecture: Двухуровневая система кэширования для экономии кредитов и снижения нагрузки:
- Уровень 1 — Raw HTML: сырой HTML кэшируется на 30 минут (ключ:
convert:html:{normalized_url}) - Уровень 2 — Final Markdown: финальный результат кэшируется на 5 минут (ключ:
convert:result:{url}:{params_hash}) - Хэш параметров (SHA-256) обеспечивает уникальный ключ для каждой комбинации опций
- Уровень 1 — Raw HTML: сырой HTML кэшируется на 30 минут (ключ:
- Smart Credit Deduction: Кредиты списываются только при реальном HTTP-запросе к внешнему сайту. При попадании в любой уровень кэша — конвертация бесплатна.
- Frontend Conversion Options: UI-контролы для всех 4 опций конвертации:
- Чекбоксы
Include Title,Include Frontmatter,Strip Images,Strip Links - Опции передаются в API через
POST /api/convertв теле запроса - Состояние опций сохраняется между конвертациями в рамках сессии
- Чекбоксы
- CachedHTML DTO: Новая структура
dto.CachedHTMLдля хранения сырого HTML с метаданными (html,title,fetched_at) в Redis.
Изменено
- ConverterService: Полная переработка метода
ConvertURLToMarkdown():- ШАГ 1: Проверка кэша финального результата (URL + параметры)
- ШАГ 2: Проверка кэша сырого HTML (только URL)
- ШАГ 3: Readability-парсинг выполняется один раз для обоих сценариев (кэш и свежий fetch)
- ШАГ 4: Конвертация HTML→Markdown с учётом текущих опций
- ШАГ 5: Списание кредитов только если
fromCache == false(реальный fetch) - ШАГ 6: Сохранение результата в оба уровня кэша
- API Contract: Тело запроса
POST /api/convertрасширено — добавлены опциональные поля:{ "url": "https://example.com", "include_title": true, "include_frontmatter": false, "strip_images": false, "strip_links": false } - Cache Key Generation: Ключ кэша финального результата теперь включает хэш параметров — изменение любой опции генерирует новый ключ, не перезаписывая предыдущие результаты.
- Readability Optimization: Устранён дубль вызова
readability.FromReader()— парсинг основного контента и извлечение заголовка выполняются строго один раз, независимо от источника HTML (кэш или fetch).
Производительность
- Credit Savings: Повторная конвертация того же URL с другими опциями не списывает кредиты — сырой HTML берётся из кэша, конвертируется заново бесплатно.
- Reduced External Requests: При попадании в HTML-кэш (TTL 30 мин) внешний HTTP-запрос не выполняется — экономия времени (30+ секунд) и снижение нагрузки на целевые сайты.
- Single Readability Pass: Оптимизация CPU —
readabilityвызывается один раз вместо двух при свежем fetch. - Compact Cache Keys: Хэш параметров (8 байт SHA-256 → 16 hex-символов) вместо полной сериализации опций — компактные ключи Redis.
UX Улучшения
- Instant Re-conversion: При изменении опций (например, включение
strip_images) результат появляется мгновенно — HTML уже в кэше, нужна только быстрая конвертация. - No Surprise Charges: Пользователь может экспериментировать с опциями для одного URL без страха потратить кредиты — списание происходит только при первом fetch.
- Flexible Output: Пользователь настраивает формат вывода под свои нужды:
- Для LLM:
strip_images: true+strip_links: true— чистый текст без мусора - Для документации:
include_frontmatter: true— метаданные для статических генераторов - Для быстрого чтения:
include_title: true— заголовок сразу виден
- Для LLM:
Сценарии кэширования
| Сценарий | Result Cache | HTML Cache | Fetch | Кредиты | Readability |
|---|---|---|---|---|---|
| Первый запрос | ❌ | ❌ | ✅ | −1 | 1× |
| Повтор с теми же опциями | ✅ | ✅ | ❌ | 0 | 0× |
| Повтор с другими опциями | ❌ | ✅ | ❌ | 0 | 1× |
| После истечения HTML cache (30 мин) | ❌ | ❌ | ✅ | −1 | 1× |
[0.4.4-beta] - 2026-09-24
Добавлено
- Smart History Deduplication: Умная дедупликация истории конвертаций — при повторной конвертации того же URL запись обновляется, а не создаётся дубликат. Добавлены поля
count_usage(количество конвертаций) иupdated_at(время последнего использования). - UPSERT Logic: Реализован UPSERT через
ON CONFLICT (user_id, target_url) WHERE user_id IS NOT NULL— для авторизованных пользователей одна запись на URL, для анонимов допускаются дубликаты (их история не показывается в UI). - Partial Unique Index: Создан partial unique index
idx_conversion_logs_user_url_uniqueна(user_id, target_url)с условиемWHERE user_id IS NOT NULLдля предотвращения дубликатов только для авторизованных пользователей. - Usage Counter: Счётчик
count_usageавтоматически инкрементируется при каждой повторной конвертации того же URL, позволяя видеть популярность страниц. - Smart Sorting: История теперь сортируется по
updated_at DESC— недавно использованные URL всегда сверху списка, а не по времени первой конвертации.
Изменено
- Database Schema: Добавлены колонки
count_usage INT NOT NULL DEFAULT 1иupdated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()в таблицуconversion_logs. Создан индексidx_conversion_logs_user_updatedдля быстрой сортировки. - ConversionLog Domain: Добавлены поля
CountUsage intиUpdatedAt time.Timeв структуруdomain.ConversionLog. - Repository Save Method: Переписан метод
Save()вpostgresConversionLogRepo— для авторизованных пользователей используется UPSERT с обновлением всех полей кромеid,user_id,target_url,created_atи инкрементомcount_usage. - Repository ListByUserID: Изменена сортировка с
ORDER BY created_at DESCнаORDER BY updated_at DESCдля отображения недавно использованных URL сверху. - DTO HistoryItem: Добавлены поля
CountUsageиUpdatedAtвdto.HistoryItemдля отображения в UI. - Frontend HistoryDrawer: Обновлён компонент для отображения
count_usage(badge с количеством конвертаций) иupdated_at(время последнего использования вместо первого).
Производительность
- Reduced Storage: Устранено бесконечное дублирование записей — один URL = одна запись для пользователя вместо N записей при N конвертациях.
- Index Optimization: Partial unique index и индекс для сортировки по
updated_atобеспечивают быстрые запросы даже при большом объёме данных. - Query Efficiency: UPSERT выполняется одним атомарным SQL-запросом вместо SELECT + INSERT/UPDATE, снижая нагрузку на БД.
UX Улучшения
- Frontend: Добавлен логотип с анимацией при наведении курсором.
- Recent First: Пользователь видит недавно использованные URL сверху списка, что упрощает доступ к часто конвертируемым страницам.
- No Clutter: История не забивается дубликатами — чистый и понятный список уникальных URL с метаданными.
[0.4.3-beta] - 2026-09-23
Добавлено
- Credit-Based Billing: Полная переработка биллинга — переход от подписок к системе кредитов. Платные кредиты не сгорают и не имеют срока действия, бесплатный дневной лимит (5 запросов/сутки) сбрасывается каждые 24 часа.
- Priority Deduction Logic: Двухуровневое списание с приоритетом — сначала расходуются платные кредиты, затем бесплатный дневной лимит. Атомарные SQL-операции гарантируют корректность при конкурентных запросах.
- Credit Packages: Три пакета кредитов для покупки — Старт (1 000 за 99 ₽), Оптимальный (3 000 за 199 ₽, −33%), Профи (8 000 за 399 ₽, −50%).
- Billing API v2: Новые эндпоинты
GET /api/billing/credits(баланс),GET /api/billing/packages(каталог пакетов),POST /api/billing/purchase(покупка). - Test Endpoints: Отладочные эндпоинты
POST /api/billing/test/add-credits(+100 кредитов) иPOST /api/billing/test/reset-daily(сброс дневного лимита) для упрощения разработки. - Skeleton Loaders: Плавные скелетон-загрузчики в
QuotaBadgeиUserDropdownпри ожидании данных биллинга. - i18n Expansion: Новые ключи переводов (RU/EN) для кредитной системы: баланс кредитов, дневной лимит, пакеты, покупка, цена за запрос, процент выгоды.
Изменено
- Database Schema: Удалены таблицы
subscriptionsиuser_current_usage. Добавлена таблицаuser_credits(credits, daily_used, daily_reset_at) с CHECK-ограничениями и каскадным удалением. - Domain Layer: Полная замена
Subscription/PlanLimits/UsageStatsнаUserCredits/CreditPackage/PackagesConfigс хелпер-методами (CanUseCredit,ShouldResetDaily,DeductCredit). - QuotaService: Переписан с нуля — убрана логика подписок и автопродления, добавлен автоматический сброс дневного лимита при проверке квоты (lazy reset через
time.Since). - Frontend Billing Store:
BillingStoreтеперь хранитCreditsResponseвместоSubscriptionResponse, оптимистичное обновление корректно обрабатывает приоритет (кредиты → дневной лимит). - QuotaBadge Component: Адаптивное отображение —
⚡ 1 234при наличии кредитов,📅 2/5при использовании дневного лимита. Мини-прогресс-бар показывается только при отсутствии кредитов. - UserDropdown: Новый блок квоты с прогресс-баром дневного использования, таймером сброса и кнопкой «Купить кредиты» с градиентным стилем.
- Pricing Page: Полная переработка — карточки пакетов вместо тарифных планов, отображение цены за запрос (в копейках), бейджи выгоды.
- Error Handling: Обновлён HTTP 402 ответ
quota_exceeded— сообщение теперь учитывает обе причины (нет кредитов + дневной лимит исчерпан). - Cache Strategy: Кэш баланса кредитов (TTL 5 мин) вместо кэша подписок (TTL 10 мин) — более агрессивная инвалидация для часто меняющихся данных.
- Removed: Удалены устаревшие
SubscriptionRepository,UsageRepository, feature flags инфраструктура, все эндпоинты тестового апгрейда планов.
[0.3.2-beta] - 2026-09-22
Добавлено
- Billing & Subscriptions: Модуль управления тарифными планами (
Free,Basic,Pro) с ежемесячными квотами и атомарным трекингом использования (usage tracking). - Auth & Security: Полноценный цикл аутентификации на
HttpOnlycookies, сброс пароля по OTP на email и защита от брутфорса. - Rate Limiting: Многоуровневое ограничение запросов (суточное для анонимных пользователей, месячное по тарифам для авторизованных).
- History & Logs: Пагинируемая история конвертаций в API и интерфейсе с разделением хранения логов и лимитов.
- UX & Frontend Integration: Уведомления об исчерпании лимитов, модальные окна регистрации и повторное использование сохраненных URL.
Изменено
- API v2: Переход бэкенда на новую версию архитектуры (Clean Architecture).
- Database Architecture: Миграция хранилища на PostgreSQL (управление миграциями через Goose) и Redis для кэширования и лимитов.
- CI/CD Pipeline: Автоматизация сборки Docker-образов и деплоя через приватный registry Gitea.
[0.2.1-alpha] - 2026-06-15
Добавлено
- Базовый API конвертации HTML в чистый Markdown для LLM.
- Поддержка первичного веб-интерфейса на SvelteKit.
- Базовая обработка ошибок и первичная валидация входных URL.
[0.1.0-alpha] - 2026-03-01
Добавлено
- Инициализация проекта MarkClean, MVP мотора конвертации текста.