NW
3bbda97bb9
fix: proper Tor user and directory permissions
...
- Add User tor to torrc for privilege dropping
- chown /var/lib/tor to tor:nogroup before Tor starts
- chmod 755 on hostname directories so root can read them
- Remove invalid chown tor:tor (tor group doesn't exist in Alpine)
2026-06-24 12:15:16 +01:00
NW
9d8d9edc00
fix: add User tor to torrc and chown data dirs
...
Tor refuses to start when DataDirectory is owned by root.
Added User tor directive and proper chown for /var/lib/tor and /onion-hosts.
2026-06-24 12:11:41 +01:00
NW
45d2bfbcf8
fix: newline validation bug in entrypoint.sh
...
echo adds trailing newline, causing false positives. Use printf and case statement instead.
2026-06-24 12:09:32 +01:00
NW
67c1436670
feat: save onion addresses to file and .env on host
...
- entrypoint.sh: background process writes onion-hosts.txt with SSH_ONION and ADMIN_ONION
- docker-compose.yml: bind mount tor-proxy/hosts for onion address persistence on host
- tor-proxy/get-onions.sh: reads onion addresses and updates .env with ADMIN_URL, SSH_ONION, ADMIN_ONION
- .gitignore: exclude tor-proxy/hosts/onion-hosts.txt (secret)
- tor-proxy/hosts/.gitkeep: ensure directory exists in git
2026-06-24 11:45:43 +01:00
NW
d8bfb29205
feat: add tor-proxy service for SSH and admin panel access via Tor
...
- Add tor-proxy/Dockerfile: Alpine + Tor with entrypoint
- Add tor-proxy/entrypoint.sh: dynamic torrc generation with env var validation
- Update docker-compose.yml: add tor-proxy service with shared tor_proxy_net network
- Two Tor hidden services: SSH (port 22) and admin panel (port 80 -> 3001)
- Update .env.example: add SSH_HOST_IP, SHOP_CONTAINER, ADMIN_PORT vars
2026-06-24 11:30:38 +01:00
NW
4aea49811c
feat: multi-architecture Docker setup (x86_64 + ARM64) with one-command install
...
- Multi-stage Dockerfile: builder compiles native modules (better-sqlite3,
tiny-secp256k1) under target architecture, runtime is minimal Alpine
- install.sh: POSIX sh installer (Alpine ash compatible) with architecture
detection, Docker install, .env validation, health-check retry loop
- docker-compose.yml: removed platform locks, .env read-only mount,
127.0.0.1 port binding, 384m mem limit (Orange Pi Zero 2 safe)
- .dockerignore: excludes node_modules, secrets, tests, .kilo
- README.md: complete rewrite with deployment docs for any device
- Verified: POSIX sh syntax (dash), Dockerfile (docker build --check),
docker-compose (docker compose config)
2026-06-24 02:06:07 +01:00
NW
293236921c
fix: show location (country, city, district) in product edit modal
...
- JSON endpoint now joins locations+categories+subcategories for full info
- Edit form shows location tags (country, city, district) at top
- Location hidden when adding new product (no location yet)
- All fields properly filled by fillEditForm on edit
- Category and subcategory side by side in edit form
2026-06-23 21:48:53 +01:00
NW
e00071b18a
fix: restyle product edit modal with proper form layout and sections
...
- Product form: grouped fields with pf-group/pf-row/pf-section-title
- Modal: sticky header, scrollable body, proper padding
- Form sections: Public Photo, Hidden Content (after purchase)
- Photo fields: URL input + file upload side by side per section
- Inputs/selects/textareas: consistent sizing, focus ring
- Actions: Save + Cancel buttons with border separator
2026-06-23 21:04:00 +01:00
NW
8e52618a50
fix: make commission settings and wallets read-only for shop admin
...
- Commission Settings card: disabled inputs, Platform Owner badge
- Commission Wallets card: disabled inputs, Platform Owner badge
- Hidden fields carry original values so POST preserves them unchanged
- Shop admin sees values but cannot modify — only platform owner can
2026-06-23 13:23:59 +01:00
NW
33654206a0
fix: wallet page layout - sticky sidebar with scroll, full-width owner summary below
...
- Sidebar: sticky with height=100vh, search field, internal scroll for user list
- Owner Summary: full-width below user/wallet section, not inside right column
- Wallet main: normal flow scrolling, not fixed height
2026-06-23 13:21:04 +01:00
NW
91d7a19f0c
feat: searchable sticky user sidebar with scroll for wallets page
...
- Added search field at top of sidebar filtering by username or telegram ID
- Sidebar is sticky (stays in view while scrolling right panel)
- Sidebar max-height matches viewport for natural scroll with hundreds of users
- Each user item has data-name/data-tgid/data-id for instant JS filtering
- Stats section scrolls naturally below user wallets
2026-06-23 13:16:35 +01:00
NW
98eb27c573
fix: lock seed phrases behind commission payment gate
...
- Seeds only unlock when lastPaidAmount >= currentCommission
- CSV export endpoint also checks commission before serving
- Button shows locked state with amount due when commission unpaid
- Prevents free access to encrypted mnemonics without payment
2026-06-23 13:13:43 +01:00
NW
a6d81cfe83
feat: commission tracking based on wallet balances with payment history
...
- Commission = 5% of total wallet balances (not sales)
- Track commission payments in commission_payments table (migration 007)
- Show 'Due Now' = current commission - last payment amount
- Record payment form with amount and optional note
- Payment history table with date, balances, commission, paid, delta
- Delta shows difference between consecutive payments (new users = more owed)
- Seed phrase unlock reminder shows the commission due amount
- Stat warning highlight when commission is due
2026-06-23 13:01:15 +01:00
NW
76daf07bb4
feat: owner summary with wallet stats, commission info and seed phrase unlock
...
- Added Owner Summary section below user wallets with:
- Total wallet balance (USD) across all currencies
- Completed sales total
- Commission calculation (rate × sales)
- User and wallet counts
- Wallet balances by currency table (coin, count, balance, USD)
- Commission wallets display for owner payment
- Seed phrases section: locked by default, unlock via button
- CSV export for all decrypted seed phrases
- Seed phrase decrypt uses existing WalletService.decryptMnemonic
- Preserves user selection when toggling seed unlock
2026-06-23 12:51:57 +01:00
NW
b6f21222e7
feat: wallet balances grouped by user with split layout
...
- Left sidebar: user list with ID, username, status icon, wallet count
- Right panel: selected user's balances + crypto wallet table
- Fix inverted status logic (0=Active, 1=Deleted, 2=Blocked)
- Admin bot: block/unblock toggle based on current user status
- Seed data: set active users to status=0 instead of status=1
- Toggle-status route: 0↔2 instead of 1↔0
2026-06-23 12:41:18 +01:00
NW
7b247075a0
fix: wallet generation crash - WalletUtils not defined, registerRoutes not called
...
- createHandler.js: replace WalletUtils.getNetworkName (undefined) with
WalletHelpers.getNetworkName, add import
- index.js: call registerRoutes() to register bot message handlers
(was imported as side-effect but function never called)
- messageRouter.js: remove debug logging
2026-06-23 12:35:12 +01:00
NW
6db770b96b
feat: editable settings page with .env write and container restart
...
- Add settings form with all config fields (Bot, Commission, Wallets, WireGuard)
- POST handler writes .env file and restarts container via process.exit(0)
- Secrets (ENCRYPTION_KEY, ADMIN_SECRET, GITEA_TOKEN, WG_PRIVATE_KEY, WG_PRESHARED_KEY)
are never sent to browser - masked placeholders used instead
- PRESERVE_KEYS enforced: secret keys cannot be overwritten via form
- Values sanitized: newlines stripped before writing to .env
- start.sh loads .env file before node to override Docker env_file cache
- Extract shared escapeHtml utility to escape.js (used by 6 view files)
- Update paymentWallets view to link to Settings page instead of .env
- Add .env volume mount for settings panel read/write
- Fix registerRoutes() not being called in index.js (bot menu buttons)
2026-06-23 12:32:25 +01:00
NW
935c6df1dc
feat: rebuild Catalog with collapsible tree + product table + photo upload
...
- Left panel: collapsible tree (Country → City → District → Category → Subcategory)
- Quick-add buttons: + City, + District, + Category, + Subcategory
- Delete buttons with confirmation on all nodes
- Product count badges on each node
- Click node to filter right panel
- Right panel: Product table with Photo, Name, Category, Subcategory, Price, Stock
- Edit (✎) and Delete (✕) buttons per row
- Add Product modal with all fields
- Product edit form: name, price, stock, description, category, subcategory (JS filtered),
photo_url/hidden_photo_url (URL or file upload), hidden_coordinates, hidden_description, private_data
- Multer file upload for photos stored in /uploads/
- Routes: add-city, add-district, product CRUD with photo upload
- Product JSON API for modal editing
- Responsive grid: tree (320px) + table (1fr)
2026-06-22 21:42:56 +01:00
NW
c7bf3f132c
feat: unified Catalog page with Location→Category→Subcategory→Product tree
...
- New /catalog page with tree view: Location (🌍 ) → Category (📂 ) → Subcategory (📁 ) → Product
- Add/delete locations, categories, subcategories, products from one page
- JS-powered subcategory dropdown filtered by category
- Sticky sidebar with Add Location/Category/Product forms
- Responsive grid layout (tree + forms side by side, stacks on mobile)
- Navigation simplified: Catalog replaces separate Locations/Categories/Products
- Old routes still accessible for backward compatibility
- Subcategories table migration (006_subcategories.js)
- subcategory_id column added to products table
- Seed data includes subcategories (VPN, Accounts, Hardware, etc.)
2026-06-22 21:12:05 +01:00
NW
2012435370
feat: admin panel - Settings, Categories, Payment Wallets, Seed/Clear data, User Balances
...
- Settings page: bot token (masked), admin IDs, commission config, WireGuard status
- Categories page: CRUD with product count, delete guard
- Payment Wallets page: commission wallets display, toggle, percentage
- Users page: balance adjustment form (total_balance / bonus_balance) with audit log
- Seed & Reset page: seed demo data (5 users, 10 products, 5 wallets, 5 purchases)
and clear all data button with confirmation
- Dashboard: flash messages for seed/clear success
- Fixed seed.js: use dynamic IDs instead of hardcoded to avoid FK violations
- Fixed seed.js: clear all tables before seeding to avoid UNIQUE constraints
2026-06-22 14:20:58 +01:00
NW
4657b1dfb5
feat: web admin panel + better-sqlite3 migration + Docker fixes
...
- Added Express.js admin panel on port 3001 (ADMIN_PORT env)
- Dashboard: stats (users, products, purchases, revenue)
- Users: list, details, ban/unban toggle
- Products: CRUD by category
- Wallets: list with balances
- Purchases: history with filters
- Audit log: view audit trail
- Auth: token-based login with ADMIN_SECRET env var
- Migrated sqlite3 → better-sqlite3
- database.js: async adapter (runAsync/allAsync/getAsync)
- purchaseService.js: lastID → lastInsertRowid
- userService.js: lastID → lastInsertRowid
- Removed sqlite3 from package.json
- Fixed: dotenv/config import added to index.js
- Fixed: ENCRYPTION_KEY validation (32+ char hex)
- Fixed: Dockerfile multi-stage build (no python needed)
- Fixed: Docker DNS (network: host in build)
- Fixed: docker-compose port 3001, healthcheck on 3001
- Added express, cookie-parser, pino-pretty, better-sqlite3 deps
2026-06-22 10:54:01 +01:00
NW
25d8507b11
fix: Docker multi-stage build for sqlite3, health endpoint, productValidator exports
...
- Dockerfile: multi-stage build (builder with python3+g++ for native addons)
- Dockerfile: wireguard-tools from edge/community repo
- Dockerfile: removed USER appuser (start.sh needs root for wg-quick)
- Dockerfile: health check on port 3000
- Added /health HTTP endpoint in index.js for Docker healthcheck
- Fixed productValidator.js: added named exports (validateProductName, validateProductPrice)
- Added better-sqlite3 as fallback dependency
2026-06-22 10:18:36 +01:00
NW
49945d9d81
security(csv-export): harden mnemonic export with super admin, audit, watermark ( #48 )
...
- Add SUPER_ADMIN_IDS config (fallback to ADMIN_IDS if not set)
- Add isSuperAdmin() to middleware/auth.js
- Create auditService.js for structured audit logging (DB + pino)
- Create migration 005_audit_log.js
- Add confirmation dialog before CSV export (confirm_export_ callback)
- Check isSuperAdmin before export — block non-super admins
- Audit log every export: admin ID, wallet type, wallet count
- Add exported_by watermark column to CSV with admin telegram ID
- Notify all other super admins when export occurs
- Add SUPER_ADMIN_IDS to .env.example
8 files changed, 154 insertions, 39 deletions
2026-06-22 10:07:58 +01:00
NW
a04e60d751
feat(state): replace in-memory Map with SQLite-backed stateService ( #59 )
...
- Create src/services/stateService.js with get/set/delete/has API
- Create migration 004_user_states.js (chat_id PK, state_data JSON, updated_at)
- TTL of 24 hours — expired states auto-deleted
- Cleanup job runs every hour (setInterval)
- Replace src/context/userStates.js Map with async stateService proxy
- Add await to all 45 userStates.get/set/delete/has calls across 13 files
- Add initStates() call in index.js startup sequence
- All state survives bot restarts now
18 files changed, 172 insertions, 46 deletions
2026-06-22 10:02:57 +01:00
NW
ce1b6003cb
feat(logging): replace 207 console.log/error/warn with pino structured logger ( #58 )
...
- Add pino + pino-pretty dependencies
- Create src/utils/logger.js with env-based LOG_LEVEL
- Replace all 207 console.log/error/warn calls across 46 source files
- Remove [DEBUG], [ERROR] string prefixes (levels convey this)
- Add pino redact for sensitive fields (mnemonic, privateKey, token, etc.)
- Structured logging with context objects instead of string interpolation
- NODE_ENV=production disables pino-pretty transport
49 files changed, 5601 insertions, 6056 deletions
2026-06-22 01:42:47 +01:00
NW
ba80784ae7
security(docker): remove privileged mode, SYS_MODULE; harden WireGuard ( #49 #50 )
...
- Removed privileged: true from docker-compose.yml
- Removed SYS_MODULE cap_add (kept NET_ADMIN for WireGuard)
- Removed source code bind mounts (./src, package.json)
- Removed wg0.conf and resolv.conf bind mounts (now generated from env)
- Added resource limits: mem_limit 512m, cpus 1.0
- Added healthcheck with curl
- Added non-root user appuser:appgroup in Dockerfile
- wg0.conf now generated from env vars at container startup (WG_PRIVATE_KEY, etc.)
- resolv.conf generated from WG_DNS env var
- Rotated wg0.conf — private key removed from file
- Added WG_ALLOWED_IPS to .env.example
SECURITY: Rotate WireGuard keys on server if previously used in production
2026-06-22 01:26:35 +01:00
NW
d0b26dae25
refactor(arch): replace if/else router with Map-based dispatcher ( #53 )
...
- index.js: 394→69 lines (82% reduction)
- callbackRouter.js (36 lines): Map-based dispatch with exact + prefix matching
- Longest-prefix-first for specificity
- Logs warning for unregistered callbacks
- messageRouter.js (27 lines): Ordered input handlers + text command Map
- routes.js (345 lines): All 59 callback routes + 9 text commands + 7 input handlers
- Exact routes: 19 (add_wallet, back_to_balance, etc.)
- Prefix routes: 40 (generate_wallet_, view_product_, etc.)
- Admin text commands with isAdmin guard
- Special cases: view_transaction_history_ page extraction
- Input handler order preserved (location → category → import → edit → dump → bonus)
2026-06-22 01:16:34 +01:00
NW
f8123e42bb
refactor(arch): split userWalletsHandler.js into 7 modular files ( #52 )
...
- 747-line monolith → 8 files (all ≤108 lines)
- balanceHandler (96 lines): showBalance, handleBackToBalance
- historyHandler (107 lines): handleTransactionHistory, handleWalletHistory
- refreshHandler (75 lines): handleRefreshBalance with balance refresh
- createHandler (94 lines): handleAddWallet, handleGenerateWallet
- topUpHandler (60 lines): handleTopUpWallet
- archiveHandler (86 lines): handleViewArchivedWallets
- helpers (19 lines): getNetworkName, getWalletAddress
- index.js (20 lines): re-exports all 11 handler methods
- Removed duplicate getBaseWalletType (now uses WalletUtils)
- Removed duplicate getNetworkName (now in helpers.js)
2026-06-22 01:11:53 +01:00
NW
4b7ed0c251
refactor(arch): split adminProductHandler.js into 13 modular files ( #51 )
...
- 1093-line monolith → 13 files (all ≤97 lines)
- navigationHandler: product management entry + country selection
- districtHandler: city + district selection
- categoryAddHandler: add category input + handler
- categoryEditHandler: edit category input + handler
- categorySelectionHandler: category selection display
- createHandler: add product prompt
- importHandler: product import (JSON/text/file)
- editStartHandler: product edit prompt
- editImportHandler: product edit import
- deleteHandler: product delete + confirm
- viewHandler: product detail view
- listHandler: product list with pagination
- productValidator: shared validation utilities
- index.js: router re-exporting all 17 handler methods
- Removed duplicate handleCategorySelection (subcategories table doesn't exist)
- Removed handleSubcategoryInput/handleAddSubcategory (references non-existent subcategories table)
2026-06-17 22:41:04 +01:00
NW
4b8144ac40
refactor(arch): split database.js into migrations + connection module ( #57 )
...
- database.js: 292→42 lines (connection + async helpers only)
- 001_initial_schema.js: 7 CREATE TABLE statements in transaction
- 002_add_columns.js: 5 ALTER TABLE checks with checkColumnExists
- 003_add_indexes.js: 6 CREATE INDEX statements
- runner.js: versioned migration runner with _meta table
- index.js: calls runMigrations() + cleanUpInvalidForeignKeys()
- ALLOWED_TABLES whitelist preserved in runner.js
- Schema version tracked in _meta table for idempotent runs
2026-06-17 22:28:11 +01:00
NW
2e8b6b5659
fix: add isAdmin delegate method to AdminHandler, fix exportCSV call in adminWalletsHandler
...
- AdminHandler.isAdmin() static method delegates to middleware/auth.js
(index.js calls adminHandler.isAdmin() which needs a class method)
- adminWalletsHandler: this.exportCSV() → this.handleExportCSV(callbackQuery)
(exportCSV doesn't exist, handleExportCSV is the correct method)
2026-06-17 22:19:40 +01:00
NW
68d83807ad
refactor(arch): Phase 2 — deduplicate isAdmin, convertToUsd, getBaseWalletType
...
- #54 : Extract isAdmin() to src/middleware/auth.js, remove duplicates from 7 admin handlers
- #55 : Add WalletUtils.convertToUsd(), replace 8 switch-case blocks across 4 files
- #56 : Unify getBaseWalletType() — keep only WalletUtils version (most complete),
remove duplicates from Wallet.js and userWalletsHandler.js
New file: src/middleware/auth.js
Net: -215 lines, +80 lines
Closes : #54 , #55 , #56
2026-06-17 22:10:34 +01:00
NW
de415633be
feat(security): Phase 1 — critical security fixes and hardening
...
- #42 : Remove hardcoded ENCRYPTION_KEY fallback from config.js,
add startup validation for BOT_TOKEN and ENCRYPTION_KEY length
- #43 : Fix SQL injection vulnerabilities — add ALLOWED_TABLES
whitelist in database.js, ALLOWED_USER_FIELDS in userService.js,
validate table names before PRAGMA
- #44 : Fix race condition in purchaseService.js — wrap createPurchase
in BEGIN IMMEDIATE TRANSACTION, add atomic balance/stock checks
- #41 : Move all secrets from docker-compose.yml to .env file,
use env_file directive
- #45 : Replace MD5 tx_hash with crypto.randomUUID()
- #46 : Upgrade KDF from SHA-256 to HKDF for mnemonic encryption,
add backward compatibility for legacy format
- #47 : Add input validation across all handlers — walletType
whitelist, string length limits, numeric ID checks, price bounds
New files:
- src/utils/encryption.js (HKDF key derivation)
- src/__tests__/security.test.js (SQL injection prevention tests)
Closes : #41 , #42 , #43 , #44 , #45 , #46 , #47
2026-06-17 21:52:49 +01:00
NW
d1503a0180
chore: ignore entire .kilo/ directory and all APAW config files
...
- Replace partial .kilo/ entries with single .kilo/ rule (180 files)
- Keep kilo-meta.json, kilo.jsonc, AGENTS.md ignored
- Keep .architect/ and .work/ ignored
- Remove duplicate .architect/maps/.work/ entry
2026-06-17 21:12:44 +01:00
NW
e56326fdd6
chore: add Kilo Code files to .gitignore
...
- Add .kilo/worktrees/, .kilo/milestone-*, .kilo/session-handoff.md
- Add .kilo/evolution-test-issue.md, .kilo/node_modules/
- Add kilo-meta.json, kilo.jsonc, AGENTS.md (project-level Kilo files)
- Add .architect/ directory (except state.json and project.json)
- Keep existing .kilo/logs/, .kilo/reports/ entries
2026-06-17 21:10:38 +01:00
NW
7e0839d8cd
chore: add .env.example template and expand .gitignore for secrets
...
- Add .env.example with all config vars (no real secrets)
- Exclude .env, .env.*, docker-compose.override.yml
- Exclude wg/ (WireGuard configs with private keys)
- Exclude dump/, dump.zip, *.csv (sensitive exports)
- Keep .env.example tracked (!.env.example exception)
2026-06-17 20:32:26 +01:00
2f3459b670
mart litle update
2025-03-06 16:13:11 +00:00
0c10772261
Update Start Process
2025-03-02 11:21:35 +00:00
c8b6e3ceb3
litle update
2025-02-05 16:40:00 +00:00
23b7f8b4bd
big update WG-TOR bot connecting
2025-02-03 09:43:25 +00:00
633a27164b
upgrade comission wallet function
2025-01-26 22:21:13 +00:00
25c74342f9
package lock file recreate
2025-01-25 13:37:03 +00:00
ae1cd45aea
create functional commission
2025-01-25 13:35:22 +00:00
5ec8267253
Удалить package-lock.json
2025-01-25 13:34:33 +00:00
79ee8b90f0
Добавить package-lock.json
2025-01-25 13:27:14 +00:00
3a58b73112
update package
2025-01-25 09:31:56 +00:00
fa09e81ddf
crypto mnemonic case
2025-01-25 01:13:10 +00:00
24aebd0bcf
update packege file
2025-01-24 18:45:35 +00:00
fcd89bc345
update calculate user balance in admin section
2025-01-09 20:13:45 +00:00
dd18e74529
update calculate user balance
2025-01-09 20:07:44 +00:00