- categories dialog: red hint with count + Deactivate button when products>0
- locations dialog: red hint + Deactivate button when categories/products>0
- catalog dialog: deleteError shown on 400/409; Deactivate for category/subcategory/location, Edit for product
- Deactivate calls existing PATCH toggle, closes dialog, reloads
- tsc clean
- compose: pass bot env (BOT_TOKEN, SUPPORT_LINK, ADMIN_IDS, SUPER_ADMIN_IDS, WG_*, ADMIN_*, GITEA_API_URL) to tg_shop_admin
- settings API: reads real env values; POST /api/settings reveals secret value by key (auth required)
- settings-page: eye/eye-off button on masked fields, shows real value on click (BOT_TOKEN, ADMIN_IDS, etc.)
- wallets/seeds: move user relation into nested select (was select+include -> PrismaClientValidationError 500)
- wallets/export-seeds: same fix (CSV export)
- Verified no other top-level select+include conflicts in api routes
- tsc clean
- remove stale docs/admin-frontend-spec.md (old Express/EJS admin), unused templates/ (SmartAdmin copy), dead scripts/sync-agents.cjs, committed dev.pid
- add docs/API.md (admin REST API reference) and docs/DATABASE.md (DB schema)
- refresh .env.example: drop stale ADMIN_PORT/SHOP_CONTAINER, add ADMIN_URL, HEALTH_PORT, DEFAULT_LANGUAGE, CHATBOT_API_*
- add npm run lint so Gitea workflows pass
- rebrand web-testing suite from APAW to telegram-shop
- keyboard.products in sleep mode: language_set=0 -> language keyboard first, then AI in chosen language
- message handler in sleep mode: same language_set check before AI
- AI context verified: chat_sessions history (max 20) + LANGUAGE_INSTRUCTIONS[lang] in system prompt
- 30 tests pass
- New API /api/chatbot/models: fetches model list from configured endpoint (/models, OpenAI/Ollama format)
- Uses saved site_settings endpoint+key, or accepts endpoint/apiKey query params (unsaved custom provider)
- UI: 'Загрузить модели' button in Provider tab — loads models into select
- Manual model input always available for Custom providers
- No more hardcoded Ollama-only model list
- window.location.href='/' after login (was window.location.hash='/' which stayed on /login#/)
- checkSession on mount: already-authenticated users skip login form
- Old .env had ADMIN_PORT=3001/SHOP_CONTAINER=telegram_shop_prod overriding compose defaults
- Tor onion was proxying to old Express admin; now hardcoded to new Next.js admin
- getOrCreateLead: INSERT OR IGNORE prevents UNIQUE constraint race (parallel messages creating same telegram_id lead)
- On changes=0, reselect existing lead instead of failing
- chatbotService: bridge to Next.js admin chat API (localhost:3100) — sleep mode, welcome, LLM replies
- leadService: lead sync from every user message, interaction logging to audit_log
- index.js: unhandled messages route to AI when chatbot_enabled; lead sync on every message
- userHandler/routes: lead capture on /start and catalog; sleep mode redirects to AI dialog
- Migration 013: leads, site_settings, chat_sessions tables (idempotent, chatbot_enabled/sleep_mode default 0)
- messageRouter.dispatch returns boolean (handled/not) for AI fallback
- gitignore db backups
- Register shop_district_ (handleDistrictBack) + shop_subcategory_ (handleSubcategorySelection) in routes.js — Back button in empty categories now works
- state.location pipe-delimited with encodeURIComponent — multi-word names (Saint Petersburg) no longer break nav
- answerCallbackQuery moved to start of callback handling — no stuck spinner
- Empty city fallback (district_unknown) in Select district
- Guard against stale underscore-format state.location
- 48 tests pass; bump v1.2.4
- Add .kilo/, kilo-meta.json, kilo.jsonc, AGENTS.md to .gitignore
- git rm --cached: files remain on disk, only removed from version control
- Agent pipeline (orchestrator, agents, capability-index) keeps working locally
- Runs on tag push (v*) on arm64 runner (orange-pi-arm64, label: arm64)
- Native ARM64 docker build (no QEMU), consistent with prod Orange Pi Zero 2
- Best-effort push to Gitea Container Registry (git.softuniq.eu/telegram-market/telegram-shop)
- Falls back to saving image tarball if registry auth unavailable
- locations/categories GET pass req.query.error/success to views
- locations/categories EJS render dismissible error/success alerts (modeled on catalog.ejs)
- Delete errors include blocking counts + 'Remove X first' hints
- 🔒 lock hint on rows with linked categories/products/subcategories
- 18 new tests (adminDeleteFeedback.test.js); 48 total pass
- Add management toolbar on /catalog with links to /locations and /categories
- Expand catalog tree by default (all levels visible, no collapsed accordion)
- Add Back to Catalog link on /locations and /categories pages
- Edit/toggle/delete buttons for locations/categories/subcategories now immediately accessible
- Fix seed phrase reveal modal: use classList instead of style.display
to properly toggle d-none/d-flex on Bootstrap elements
- Fix USDT/USDC wallet creation bug: was using ETH address (index 0)
instead of correct derivation path address (index 1/2)
- Add Balance column to CSV seed export
- Remove CSRF tokens from wallets.ejs (incompatible with Tor/onion)
- Super admin CSV export: no commission check required
- Audit logging for CSV seed exports
- Use window.addEventListener('load') for seed modal JS to ensure
Bootstrap is loaded before initializing bootstrap.Modal
- Add super admin role system (SUPER_ADMIN_SECRET env var)
- requireSuperAuth middleware for sensitive routes
- isSuperAdminWeb() helper for template access
- Role badge in header (Super Admin / Admin)
- Seed Viewer nav item visible only to super admins
- Add seed phrase viewer with QR code generation
- GET /wallets/seed/:walletId — JSON seed phrase (super admin only)
- GET /wallets/seed-qr/:walletId — QR PNG image (super admin only)
- Modal UI with reveal-on-click, 60s auto-hide countdown
- Copy-to-clipboard and download QR as PNG
- Audit logging for every seed phrase access
- Disable CSRF completely for Tor/onion compatibility
- csrfMiddleware no longer sets _csrf cookie
- validateCsrf and validateCsrfFromBody are no-ops
- res.locals.csrfToken set to empty string (prevents template errors)
- .env.example: document SUPER_ADMIN_SECRET variable
- fix(admin/csrf): completely disable CSRF checks for Tor/onion compatibility
- fix(validators): add 'main' and 'bonus' to WALLET_TYPES for purchase flow
- feat(admin): add clickable version tag with version history modal in sidebar
- docs: add VERSION.md with changelog and update instructions
- Move app-logo out of flex-grow-1 div to be direct child of app-header
(matches SmartAdmin CSS expectations for .app-header .app-logo)
- Remove inline style padding-left from logo, rely on SCSS padding
- Remove data-prefix attribute that positioned version text absolutely
- Override .app-logo > svg.sa-icon min-width (was 11rem) to natural
icon size (1.5rem) so icon and text align inline
- Add .logo-text class for proper text sizing and nowrap
- Fix conflicting responsive classes on header buttons
(d-sm-block d-sm-none → d-none d-lg-block)
- Fix fullscreen button aria-label (was 'Toggle Dark Mode')
- Remove w-100 from header inner div that pushed buttons off-screen
- Replace wifi icon in nav-footer with tag icon + version text v1.0