Commit Graph

213 Commits

Author SHA1 Message Date
NW
a71012680a docs: README — new Next.js admin panel (admin-next/), tor schema update, project structure 2026-08-08 11:55:52 +01:00
NW
9226871eb4 fix(bot): lead race condition — INSERT OR IGNORE + reselect on UNIQUE conflict
- getOrCreateLead: INSERT OR IGNORE prevents UNIQUE constraint race (parallel messages creating same telegram_id lead)
- On changes=0, reselect existing lead instead of failing
2026-08-08 11:51:18 +01:00
NW
e202b357dc chore: ignore admin-next/.env (secrets kept on server) 2026-08-08 04:52:19 +01:00
NW
d78c7aa502 fix(admin): add openssl+curl for Prisma SQLite and healthcheck in runner stage 2026-08-08 01:39:38 +01:00
NW
a4a5fd449d feat(admin): integrate Next.js admin panel (admin-next/) from feat/nextjs-admin
- Add admin-next/: full Next.js + Prisma + shadcn admin panel (45 API routes, 76 components)
- docker-compose: tg_shop_admin service (port 3000, shared db/shop.db, prisma), bot talks to it via ADMIN_CHAT_URL=http://tg_shop_admin:3000/api/chat
- tor-proxy now proxies onion admin to tg_shop_admin:3000 (new panel)
- chatbotService: ADMIN_CHAT_URL default = http://tg_shop_admin:3000/api/chat (removed localhost:3100 anachronism)
- .env admin secrets gitignored (admin-next/.env)
2026-08-08 01:31:45 +01:00
NW
62534dbe85 feat(bot): AI-chat integration — leads, chatbot service, sleep mode + migration 013
- 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
2026-08-08 01:12:10 +01:00
NW
a5ea99b39b fix(admin): issue #131 — dead callback buttons prod_district_/admin_users + no-op placeholders
- prod_district_: pipe-delimited format (multi-word names safe) + handleDistrictBack shows categories (admin sees disabled locations via getLocationsByCountryAndCityAdmin)
- admin_users: handleUserListBack (viewUserPage(0) edit)
- current_page/current_quantity/no_action: no-op exact routes (no 'No handler' warns)
- Audit: all 78 generated callbacks cross-checked — no overlaps, none missing
- 48 tests pass; bump v1.2.6
2026-08-05 12:46:37 +01:00
NW
61c7a90aeb fix(bot): issue #130 — crypto deposit photo-edit 400, chat cleanup via lastInlineMessageId
- depositHandler: handleDepositInstruction + handleDepositSelectWallet use editOrSendCallback (photo-safe fallback) — fixes 'no text in the message to edit' 400
- resetUserContext deletes lastInlineMessageId (stale inline menus cleaned on Reply Keyboard nav)
- showProducts/showProfile/showBalance/showPurchases store lastInlineMessageId on sendMessage
- answerCallbackQuery verified before dispatch (v1.2.4)
- 48 tests pass; bump v1.2.5
2026-08-05 12:20:16 +01:00
NW
f90af4c78e docs(admin): frontend spec for admin panel + endpoint architecture (issue #131) 2026-08-05 12:07:56 +01:00
NW
7a97d561a5 fix(bot): issue #129 — missing shop_district_/shop_subcategory_ handlers, answerCallbackQuery timing, state.location pipe format
- 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
2026-08-05 10:52:18 +01:00
NW
12c4cefc4c chore: ignore Kilo agent config files (kept on disk, system unaffected)
- 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
2026-08-04 22:57:03 +01:00
NW
04c358eb30 chore(agents): sync agent configs — model updates to nemotron-3-super
- Update agent model assignments (nemotron-3-ultra -> nemotron-3-super) across .kilo/agents, kilo-meta.json, kilo.jsonc, capability-index.yaml
- Sync agent descriptions in KILO_SPEC.md
2026-08-04 22:55:17 +01:00
NW
b58087f37b fix(bot): issue #128 — empty category menus, duplicate country lists, DB typo+desync migration
- getCategoriesWithProductsByLocationId: filter districts to categories with real in-stock/mono products; empty → no_categories message + back button + answerCallbackQuery
- Main-menu debounce (1200ms) in routes.js for products/profile/wallets/purchases — no duplicate Select-your-country on rapid taps
- Migration 012: fix typos (Centr→Center, Chiken→Chicken, Brusel→Brussels, Sever→North) + re-enable locations that have in-stock products (desync fix)
- Tests updated (48 pass); bump v1.2.3
2026-08-04 20:53:34 +01:00
NW
5c6760b180 ci: install docker-cli in alpine job container for build/push/save steps
All checks were successful
Release: ARM64 Docker Image / build-arm64 (push) Successful in 3m14s
v1.2.2
2026-08-04 19:21:04 +01:00
NW
eac2a0cd6c ci: use sh shell in release workflow (node:22-alpine has no bash)
Some checks failed
Release: ARM64 Docker Image / build-arm64 (push) Failing after 1m40s
2026-08-04 19:17:33 +01:00
NW
4186ebeab6 ci: fix checkout step - git in alpine + pass REGISTRY_TOKEN via env
Some checks failed
Release: ARM64 Docker Image / build-arm64 (push) Failing after 12s
2026-08-04 18:33:50 +01:00
NW
49d3f41686 ci: release workflow without GitHub actions (network blocked) - pure run steps
Some checks failed
Release: ARM64 Docker Image / build-arm64 (push) Failing after 12s
- GitHub unreachable on prod network; actions/checkout@v4 etc fail to download
- Rewrite release.yaml using only run: steps (git clone from Gitea, docker build/push)
- Clone uses REGISTRY_TOKEN (oauth2) from Gitea secrets
- Registry push is best-effort; always saves image tarball artifact
2026-08-04 18:30:35 +01:00
NW
9eca348d57 ci: ARM64 release workflow (Gitea Actions, native arm64 runner on Orange Pi)
Some checks failed
Release: ARM64 Docker Image / build-arm64 (push) Failing after 3s
- 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
2026-08-04 18:04:05 +01:00
NW
88a15acb29 fix(admin): delete feedback alerts + informative block errors (issue #127)
- 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
2026-08-04 17:05:06 +01:00
NW
bd3391c111 fix(bot): issue #127 — active-state sync, disabled-entity handling, double-tap lock, state reset
- BUG-01: getActiveLocationById + product availability checks (loc_active/cat_active) — disabled locations/categories filtered from bot menus
- BUG-02: graceful redirect to main menu (location_disabled notice) when entity disabled mid-flow, no crash in handleDistrictSelection/handleProductSelection/handleBuyProduct/handlePay
- BUG-03: per-user callback lock (LOCK_MS 1500ms debounce) in utils/callbackLock.js — duplicate taps dropped
- BUG-04: resetUserContext clears tracked photo/product messages + userStates on main-menu navigation and /start
- fix: handlePay uses validated numeric quantity (was raw string) for price/stock/purchase writes
- tests: 7 new (botBugFixes.test.js), updated userProductHandler tests — 30 total pass
- bump v1.2.2
2026-08-04 15:21:55 +01:00
NW
29ab8f9d34 chore(agents): sync agent configs, models, capability index; cleanup junk
- Update agent model assignments (minimax/glm -> nemotron-3-ultra, kimi-k2.7-code, qwen3.5:397b) in .kilo/agents, kilo-meta.json, kilo.jsonc, capability-index.yaml
- Update orchestrator/agent prompts (complexity fast-path, verification tests, close-loop audit)
- Add .kilo/KILO_SPEC.md (Kilo Code specification reference)
- AGENTS.md: consolidate smartadmin agent rows
- Remove screenshot-dash.cjs (unused, contained hardcoded admin token); gitignore it
- Remove empty .kilo/milestones/
2026-08-04 14:16:41 +01:00
NW
47c698aa42 fix(admin): make catalog CRUD management visible
- 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
2026-07-25 13:12:12 +01:00
NW
ca2ddefd7a feat(admin): full CRUD + enable/disable for locations, categories, subcategories
- Migration 011: add is_active INTEGER NOT NULL DEFAULT 1 to locations, categories, subcategories (idempotent)
- Admin routes: locations edit + toggle, categories toggle, subcategories edit + toggle (parallel endpoints on /catalog)
- Bot-side services: filter is_active=1 on locationService/categoryService read methods (getLocationById/getCategoryById left unfiltered for purchase display)
- Views: edit forms, toggle buttons, Active/Disabled badges, disabled row styling in locations.ejs, categories.ejs, catalog tree
- Add Categories nav item in sidebar (folder icon)
- Tests: 14 new tests for migration idempotency + service is_active filtering (23 total pass)
2026-07-19 23:22:21 +01:00
NW
776d0e8552 fix(bot): remove redundant deposit amount step, add Visa/MC label, Mercuryo auth note, enforce product completeness
- Remove deposit amount-selection step; deposit_wallet_<TYPE> now routes directly to instruction
- Add VISA / Mastercard text to Mercuryo card button (i18n en/es/de)
- Add deposit_important5: Mercuryo 1-payment-without-auth + top-up-reserve warning
- Admin validation: description + photo required on product create/update (products.js, catalogProducts.js)
- Cleanup orphan uploaded files on validation failure (catalogProducts.js)
- Bot guards: fallback to products.no_description / products.no_photo for incomplete products
- Add vitest + 7 purchase edge-case tests (src/__tests__/userProductHandler.test.js)
- Bump version to v1.2.1
2026-07-18 14:28:26 +01:00
NW
b6eb42ccfc fix: seed phrase modal, USDT address bug, CSV balance column, remove CSRF
- 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
2026-07-14 14:50:24 +01:00
NW
d03c8419e5 feat(admin): super admin role, seed phrase viewer with QR code, CSRF disabled for Tor
- 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
2026-07-09 16:40:15 +01:00
NW
83991f098b v1.2.0: disable CSRF for Tor, fix wallet type validation, add version history modal
- 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
2026-07-08 21:59:16 +01:00
NW
4997ca75ab fix(admin): header logo alignment + sidebar version tag
- 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
2026-07-08 14:00:20 +01:00
NW
f0afada884 feat: Mercuryo gateway, crypto QR deposit, mono products, wallet auto-refresh
- Replace Quickex/Guardarian with Mercuryo (https://mercuryo.io/)
- Add crypto QR code payment option in deposit flow (qrcode package)
- Add is_mono product flag for digital/infinite products
- Mono products: no quantity buttons in bot, always available
- Admin wallet page: auto-refresh balances from blockchain APIs
- Migration 010: add is_mono column to products
- i18n updates for en/de/es
2026-07-08 12:08:13 +01:00
NW
2b30bc4a91 fix(admin): CSRF cookie sameSite=false for Tor, auth cookie fix, async handlers, validation 2026-07-08 12:08:08 +01:00
NW
046c40349d chore: sync all changes 2026-07-07 18:48:40 +01:00
NW
e84c2af650 fix(admin/dashboard): charts rendering + realistic demo data
- Move ApexCharts script to <head> in app-head-css.ejs for global availability
- Remove conflicting apexchartsWrapper.js module from app-scripts.ejs
- dashboard.ejs: wrap charts init in window.addEventListener('load') for correct DOM timing
- Add inline height styles to chart containers (350px, 300px, 250px)
- Add CSS min-height fallback for .apex-charts in layout.ejs
- seed.js: realistic demo data with 30-day date spread, 10 users, 30 purchases,
  12 audit log entries, 2 commission payments, 10 wallets with 7 coin types
- dashboard.js: add days30 and revenueData30 to chartData for 30-day chart
2026-07-06 19:59:56 +01:00
NW
1648336511 fix(admin/dashboard): restore layout BEFORE SortableJS init
- Reorder DOM elements from localStorage BEFORE initializing SortableJS
- Initialize Sortable AFTER layout restoration so it tracks correct DOM
- Add console.log for save/restore debugging
2026-07-06 19:22:22 +01:00
NW
bc48334269 feat(admin): draggable dashboard panels + business KPI redesign
- Dashboard: 16 business-focused panels (KPIs, charts, tables, feeds)
- New data queries: AOV, conversion rate, revenue by category, top spenders,
  purchase funnel, 30-day trend, geography, wallet totals
- ApexCharts: 30-day revenue line, category bar, funnel bar, geo bar,
  conversion mini-donut, revenue sparkline
- SortableJS: draggable panels within rows, layout saved to localStorage
- Theme persistence: body classes (nav-dark, header-fixed, etc.) saved to
  localStorage and restored on load, MutationObserver syncs all toggles
- Panel data-panel-id attributes for layout persistence
- All panels use existing SmartAdmin panel-icon/card styling
2026-07-06 19:13:05 +01:00
NW
2a34b40411 fix(admin): button icon visibility and text wrapping
- Add CSS for svg.sa-icon fill on all button variants
- white-space: nowrap + inline-flex + gap for icon buttons
- Quick Actions: d-grid → d-flex flex-wrap for horizontal layout
- btn-secondary → btn-dark for Settings button (icon visibility)
2026-07-06 19:00:25 +01:00
NW
10f8138ce2 fix(admin): add me-2 margin to sa-icon SVGs in card headers and buttons 2026-07-06 18:55:47 +01:00
NW
c149c877f3 fix(admin): localization to English + padding fixes for tables, buttons, logo 2026-07-06 18:32:22 +01:00
NW
86c4e18752 fix(admin/wallets): user list styling + full-width Owner Summary
- User list: .list-group-item-action instead of .dropdown-item for proper
  row styling, clear layout with status badge and wallet count
- Owner Summary: moved to separate full-width row outside col-md-9,
  now spans entire content area independent of user/wallet panels
2026-07-06 17:59:22 +01:00
NW
d4c476002c feat(admin): SmartAdmin template redesign + security hardening
- Migrated all admin views from inline JS string templates to EJS
- Integrated SmartAdmin template with dark sidebar, fixed header, CSS grid
- Added express-ejs-layouts for master layout wrapper
- Security:
  - CSRF protection (double-submit cookie)
  - Rate limiting on /login (5/15min)
  - Token revocation via jti + globalLogoutTimestamp
  - Re-auth (reauth_token) for destructive endpoints
  - Settings whitelist (ALLOWED_KEYS) + removed process.exit
  - Seed phrases no longer rendered in HTML (CSV export only)
  - Multer fileFilter for image uploads + safe filename generation
  - SQL injection fix (currency column allowlist)
  - Global error handler + asyncHandler wrapper
- New files: csrf.js, errorHandler.js, error.ejs, all EJS templates
- SmartAdmin assets: CSS, icons, webfonts, plugins, scripts
2026-07-06 17:42:54 +01:00
NW
8d85776135 feat: add AI-powered visual regression testing infrastructure
- Add docker-compose.web-testing.yml with vlmkit service
- Add 5 test scripts: capture, compare, pipeline, console-monitor, link-checker
- Add vrt.config.json with 3 viewports + maskSelectors
- Add package.json with @mizchi/vlmkit and Node >=24
- Add tests/README.md with VRT documentation
- Update .gitignore for test artifacts

Based on APAW issue #144 / milestone #106
2026-06-30 21:09:30 +01:00
NW
f2d4d6d3b1 docs: update README with i18n section, language support, and project structure 2026-06-25 23:54:59 +01:00
NW
7db7a20a1d feat: always show language selector on /start, add change_language button in profile
- /start now always shows language picker (removed language_set check)
- Added 'Change Language' button in profile inline keyboard
- Added handleChangeLanguage callback handler
- Added profile.change_language locale key in en/es/de
- Registered change_language callback route
2026-06-25 23:06:58 +01:00
NW
3deddbc1b1 fix: make migrations idempotent, pass checkColumnExists to all migrations 2026-06-25 22:52:59 +01:00
NW
a8bf50df24 feat: add i18n localization system (en/es/de) with admin panel
- Add i18n module with tForUser/tForLang/t functions and {{param}} interpolation
- Add 3 locale files: en.json, es.json, de.json (201 keys each)
- Add language selection on /start and /language command with flag emojis
- Localize all bot user-facing strings (handlers, keyboards, errors)
- Localize messageRouter keyboard matching via locale keys
- Add DB migrations 008 (language column) and 009 (language_set column)
- Add localization admin tab at /locales for editing translations
- Add userService.getUserLanguage/setUserLanguage methods
- Cache user object on msg.__user to avoid triple DB fetch
- Idempotent migrations with checkColumnExists guards
- Error boundary on i18n locale file loading
- Admin locales route uses AVAILABLE_LANGUAGES import
2026-06-25 21:22:32 +01:00
NW
41ff2b8769 feat: add user-friendly deposit instructions with email/password explanation 2026-06-25 20:22:05 +01:00
NW
61aab8fed6 fix: add amount param to ChangeNOW URL 2026-06-25 19:54:02 +01:00
NW
7f6d797bfd fix: replace StealthEX with ChangeNOW for wallet deposits
- URL: https://changenow.io/exchange?from=eur&to={crypto}&fiatMode=true
- Removed amount selection from URL (ChangeNOW has it in UI)
- Renamed STEALTHEX_REF to CHANGENOW_REF in config
- Updated all UI labels from StealthEX to ChangeNOW
2026-06-25 19:47:24 +01:00
NW
d44a15064f feat: add StealthEX deposit integration for wallet top-up
- New depositHandler.js: wallet selection, amount picker, instruction page with StealthEX link
- Updated topUpHandler.js: shows deposit buttons per wallet + deposit via StealthEX
- Routes: deposit_select_wallet, deposit_wallet_, deposit_amount_, deposit_copy_
- Config: STEALTHEX_REF env var for optional referral
- Fixed archived wallets filter in deposit wallet query
2026-06-25 18:55:19 +01:00
NW
fcd7f063c2 feat: show full wallet addresses with click-to-copy in admin
- Wallet addresses now shown in full (not truncated to 24 chars)
- Click on any address or seed phrase copies it to clipboard
- Green flash animation confirms copy
- Commission wallet addresses also clickable
- Seed phrases in unlocked view also clickable
- Fallback for older browsers using execCommand
2026-06-25 16:56:40 +01:00
NW
19a275b8e0 fix: close event listener brackets in catalog tree JS 2026-06-25 13:02:25 +01:00