Commit Graph

18 Commits

Author SHA1 Message Date
1f878b61a1 feat(chat): персистентные черновики сообщений — текст переживает перезагрузку страницы 2026-09-21 15:14:30 +03:00
aa316141be feat(reminders): получатели в отложенных/входящих, приватные сообщения чата, календарь, бейдж уведомлений 2026-09-21 10:26:53 +03:00
d0112657b8 fix(auth): живая сессия на устройстве — рефреш на холодном старте, grace-окно ротации, без логаута при временных ошибках
- /api/auth/me при 401 делает одну попытку refresh (раньше refresh-retry был
  отключён для всех /api/auth/* — холодный старт после 15 мин простоя = логаут)
- ротация: повтор старого refresh-токена в пределах RACE_TOLERANCE_MS (5 мин)
  выдаёт новую пару от successor вместо deny; cookie больше не стираются при
  stale-токенах (разлогинивались все вкладки устройства); reuse после окна —
  revoke family как раньше (тесты обновлены)
- refreshSession различает 401/403/400 (сессия мертва) vs 429/5xx/сеть
  (transient — нет logout, отложенный retry)
- единый рефреш: useAuth keep-alive и useOfflineSync переведены на refreshSession;
  межвкладочная дедупликация через BroadcastChannel('auth-refresh')
- refreshLimiter: keyGenerator buildRateLimitKey (per-user, не общий IP-бакет офиса)
2026-09-17 21:59:51 +03:00
c1d5b1cbee fix(gps): остановлен 429-шторм — throttle SSE gps_asset_moved (3 сек/asset) и клиентских инвалидаций (60 сек), polling позиций 60 сек, статусов 5 мин
Каждая точка ingest (~1/сек) broadcast'илась SSE всем клиентам орг., клиент
на каждое событие делал invalidateQueries без throttle → 2+ GET/сек → исчерпание
per-user бакета apiLimiter (1500/15мин) → все API устройства 429 (формы не грузились).
Модель теперь как у нормальных трекеров: точки пишутся в БД, карта читает по интервалу.
+4 unit-теста троттла (server/gps/sse-throttle.ts)
2026-09-17 21:59:34 +03:00
c4fdfe4eab refactor(ui): фаза 3 — единый AppShell (Sidebar не размонтируется при навигации), Layout стал тонким контейнером, SPA-навигация вместо location.href (уведомления, тосты, TableEditor), scroll restoration, плавное появление биллинг-оверлея 2026-09-08 20:48:28 +03:00
5d219ac794 fix(ui): фаза 2 — стабилизация данных: throttle+invalidate вместо refetch-пачек на SSE, единый useUnreadBadges (polling только при обрыве SSE), TaskChat polling только при потере SSE, one-shot guard в safeLazy, плавная смена скина (transition цветов) 2026-09-08 20:38:01 +03:00
66f4e5ef53 DI2: удаление старого модуля финансов — пул БД и аудит перенесены в finance-di2
- server/finance/ (19 файлов) удалён: пул финансовой БД перенесён в server/finance-di2/db-core.ts, db-client.ts теперь реэкспортирует из ./db-core
- Шедулер аудита перенесён в server/finance-di2/audit-scheduler.ts (03:00 МСК, setInterval, без node-cron), запуск из registerDi2Routes с защитой от повторного старта
- История аудита DI2 теперь персистентна: загрузка/запись data/finance-audit-history.json в audit-agent.ts (порт из удалённого server/finance/audit.ts)
- registerFinanceRoutes убран из server/routes/index.ts, registerDi2Routes остался на его месте
- Клиент: удалены pages/finance/, components/finance/, hooks/useFinance.ts, hooks/useColumnLabels.ts, lib/format.ts, pages/salary.tsx; роуты /finance*, /income*, /expenses*, /salary и lazy-импорты убраны из App.tsx
- Навигация: «Финансы» в Sidebar и MobileBottomNav ведёт на субапп /di2 (внешняя ссылка), гейт moduleAccess.finance + finance.view сохранён
- index.css: удалён блок .hover-elevate/.hover-elevate-2/.active-elevate (использовался только старым модульным DataTable)
- FinanceBottomNav.tsx сохранён как референс для этапа 3 (.superpowers/sdd/di2-restyle/FinanceBottomNav.reference.tsx)
- Не тронуто: client-di2/, сиды прав finance.view/manage, finance_access (module-access)
2026-09-06 21:53:47 +03:00
7a8db03163 Финансы: дебиторка (vw_debt_active), расчёты НДС/налога на прибыль, аудит целостности с автопланировщиком, синхронизация зарплат из Google Sheets, миграция настроек Data-Insight2 2026-09-05 15:07:36 +03:00
60bd52b75a feat(gps): режим «потерян GPS» — LBS-точки помечаются (is_lbs), примерная позиция на карте, пунктир в треке; OSRM map matching трека (matched endpoint + переключатель «По дорогам») 2026-08-28 17:22:57 +03:00
5d45084af1 feat(gps): автообновление списка объектов каждые 30 сек (бейдж «Нет GPS» гаснет сам) 2026-08-28 16:09:14 +03:00
104b3ca422 feat: модуль GPS-мониторинга (карта Яндекс.Карт, Traccar, геозоны, маршруты, группы) 2026-08-24 19:30:11 +03:00
9a387c5db0 fix: бесконечный ретрай upload 400, скобки в именах файлов, тост batch-create
- useOfflineSync: tryUploadFile/trySendAttachmentMessage бросали ошибку без
  кода статуса — постоянная 400 не распознавалась regex \b400\b и вложение
  ретраилось бесконечно (спам POST /api/upload каждые ~30 сек).
- validateFilename: разрешены скобки () в именах (типично для фото с
  телефонов; сохраняемое имя всё равно генерируется), в текст 400 добавлено
  само имя файла для диагностики.
- BatchCreateDialog: тост ошибки показывает текст сервера (из BadRequestError
  или JSON в message 5xx) вместо общего «Ошибка создания задач».
2026-08-03 15:25:11 +03:00
6bb89b4cf8 feat(chat): typing indicator для ботов, кнопки ботов в мессенджере, VPN-бот с кнопками
- Добавлены SSE-события conv_typing_started/stopped и их обработка в Chat.tsx
- AI-бот публикует typing events перед/после генерации ответа
- Боты могут отправлять сообщения с кнопками через /api/bot/conversations/:id/messages
- Добавлен callback /api/messenger/messages/:id/callback для нажатий кнопок
- VPN-бот использует кнопки Android/iOS вместо текстового prompt
- Оптимистичное обновление unread count, ускоренный reportActiveChat, polling fallback,
  логирование SSE, push suppression для bot_direct
2026-07-17 11:25:25 +03:00
af8920f920 fix(auth): не выкидывать пользователя при сетевой ошибке refresh, access token 30 дней
- queryClient: refreshSession возвращает reason (network/unauthorized);
  при network-ошибке не делаем logout, а бросаем network_error_during_refresh.
- useAuth: checkAuth и refreshUser не сбрасывают сессию при network-ошибке
  во время refresh, переводят в офлайн-режим.
- auth.service: remember берётся из сессии, race tolerance 5 минут.
- access token lifetime унифицирован до 30 дней по умолчанию, cookie maxAge
  теперь совпадает с JWT expiry (было 15 минут fallback).
2026-07-10 10:04:12 +03:00
95279b8fcc feat: skin engine + Twenty CRM theme for iistwin
- Add client/src/themes/ with tokens, built-in skins (iistwin, twenty, omegaprom)
- Add ThemeProvider with data-skin/data-theme and runtime CSS for custom skins
- Add npm run skins:generate script for build-time CSS generation
- Add organization_skins table, migration and CRUD API
- Add activeSkinId to organizations and expose it in /api/auth/me
- Add skin switcher in /profile and admin skin editor in /settings/appearance
- Adapt index.css hardcoded colors to skin tokens
- Update AGENTS.md and Obsidian notes
2026-07-09 20:25:49 +03:00
7b830c658d Надёжная real-time доставка сообщений в чатах: SSE buffer, Last-Event-ID, polling fallback 2026-07-08 21:15:40 +03:00
6826d82850 feat(documents): папки шаблонов, маппинги и поле document_template; fix(batch): атомарное создание задач, idempotency и массовое удаление в реестре 2026-07-08 13:33:14 +03:00
1f5ecb6da4 fix(number-fields): избегаем потери точности длинных чисел
- number-поля теперь рендерятся как text + inputMode=numeric,
  чтобы браузер не округлял значения через input type=number
- пробелы при вставке в number-поля удаляются
- бэкенд нормализует значения number-полей в строку перед сохранением
- добавлен хелпер normalizeFieldValueForStorage

Closes: искажение расчётного счёта и других длинных числовых полей
2026-07-07 21:03:40 +03:00