- Update backend, frontend, scanner, deployment, amanat-assist service docs - Update System Overview, Scanner Architecture, Telegram Mini App flow - Update 10 - Services/README.md - Add Tenant data model, Tenant API reference, Tenant Storefront Flow - Add Multi-Shop Branch Project Scan (2026-06-10) - Add tenant.md service doc - Append activity log entry - Reflects archived/search/stats route fix and new E2E test suite Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
25 KiB
Backend Service — amn-backend
1. Overview
amn-backend is the Express 5 / TypeScript API server that powers the Amanat escrow marketplace. It is the single authoritative backend for the dev.amn.gg (escrow-dev) and multi.amn.gg (escrow-multi) stacks.
| Field | Value |
|---|---|
| Current version | 2.11.43 |
| Status | Production — receiving active feature development |
| Runtime | Node ≥ 22 |
| Framework | Express 5 (TypeScript) |
| Primary DB | PostgreSQL via Drizzle ORM |
| Mongo status | Removed — Mongoose was fully stripped; PostgreSQL is the sole persistence layer |
| Repo | git@git.tbs.amn.gg:escrow/backend.git |
| Dev stack host | root@89.58.32.32 — Arcane project escrow-dev |
2. Tech Stack
| Layer | Technology | Notes |
|---|---|---|
| HTTP framework | Express 5 | Async error propagation built in |
| Language | TypeScript (strict) | tsc gate on every CI push |
| Runtime | Node ≥ 22 | Also used for CI typecheck step |
| Database | PostgreSQL 15 via Drizzle ORM (drizzle-orm ^0.45.2, pg ^8.21.0) |
Single source of truth; 19+ migrations landed |
| Auth | JWT (access + refresh) + WebAuthn/Passkey + Google OAuth | JWT_SECRET, REFRESH_TOKEN_EXPIRES_IN |
| Session / Mini App | Telegram Mini App initData verification |
TELEGRAM_WEBAPP_URL |
| Realtime | Socket.IO with Redis adapter (@socket.io/redis-adapter) |
Room-scoped events |
| Cache / Pub-Sub | Redis | REDIS_URI |
| Rate limiting | express-rate-limit (in-memory; Redis adapter planned) | Auth 10/15 min, payment 30/15 min, AI 20/15 min, global 100/15 min |
| Security headers | Helmet | CSP, X-Frame-Options, etc. |
| File uploads | Multer | MIME validation, UPLOAD_PATH |
| Nodemailer (SMTP) + Resend | SMTP_* / RESEND_API_KEY |
|
| Price oracle | Chainlink + OffchainFX | Depeg protection, ORACLE_MAX_STALENESS_S |
| AML | Chainalysis + OFAC SDN | CHAINALYSIS_API_KEY, OFAC_SDN_URL |
| AI | OpenAI | Descriptions, moderation |
| CI | Woodpecker CI | .woodpecker/*.yml |
| Process model | Node cluster | CLUSTER_WORKERS workers + master |
3. Directory Structure
backend/
├── src/
│ ├── app.ts # Express bootstrap: middleware chain, route registration, server creation
│ ├── cluster.ts # Node cluster master — forks CLUSTER_WORKERS child processes
│ ├── controllers/ # Thin HTTP handlers that delegate to services
│ ├── db/ # Drizzle/Postgres layer
│ │ ├── schema/ # Per-table Drizzle schema files + index.ts barrel
│ │ ├── migrations/ # Numbered SQL migration files (0000–0018+)
│ │ └── repositories/ # DrizzleXxxRepo classes + factory.ts
│ ├── infrastructure/
│ │ └── socket/ # Socket.IO server init, room helpers, emit wrappers
│ ├── models/ # Legacy placeholder (Mongoose removed; schemas now in db/schema/)
│ ├── routes/ # Standalone Express Router files (dispute, blog, points, amn-scanner webhook)
│ ├── scripts/ # CLI utilities — seed:users, seed:categories, tg-notify.cjs (CI)
│ ├── seeds/ # Fixture data for local dev (Postgres-capable, idempotent)
│ ├── services/ # Domain service modules (see §4)
│ ├── shared/
│ │ ├── config/index.ts # Typed env-var loader — single import for all config
│ │ ├── middleware/ # authMiddleware, roleGuard, errorHandler, validators
│ │ ├── types/ # Cross-cutting TypeScript types and enums
│ │ └── utils/response-handler.ts # Standard success/error envelope
│ └── utils/ # Pure utility functions: logger, currencyUtils, etc.
├── .woodpecker/ # CI pipeline definitions (cleanup, development, manual, production)
├── Dockerfile.prod # Multi-stage production image
└── drizzle.config.ts # Drizzle Kit configuration
4. Key Services / Modules
| Service path | Description |
|---|---|
services/auth/ |
JWT issue/refresh, Google OAuth, WebAuthn/Passkey registration and assertion, password reset |
services/user/ |
User profile CRUD, preferences, address book |
services/marketplace/ |
PurchaseRequest, SellerOffer, RequestTemplate, ShopSettings — core escrow marketplace |
services/payment/ |
Payment orchestration: provider adapters, internal ledger (available/held/releasable), reconciliation, safety confirmations |
services/payment/adapters/ |
Provider-neutral adapter interface + registry; plugs in DePay, SHKeeper, amn.scanner, Request Network |
services/payment/requestNetwork/ |
Request Network pay-in creation, in-house checkout rehydration, HMAC-verified webhook |
services/payment/wallets/ |
HD-derived destination addresses, sweep orchestration, gas top-up |
services/payment/ledger/ |
Funds ledger tracking available / held / releasable balances per payment |
services/payment/safety/ |
Transaction Safety Provider: AML screening, min-confirmation thresholds |
services/blockchain/ |
Web3 read helpers: balance checks, tx verification across ETH / BSC / Base / TON |
services/chat/ |
Conversations, messages, attachments |
services/dispute/ |
Dispute lifecycle: open, evidence upload, mediator assignment, release-hold |
services/notification/ |
Template-based notification delivery (in-app + Telegram); mark-as-read |
services/telegram/ |
Bot webhook handler, Mini App initData verification, identity link/unlink, seller notifications |
services/points/ |
Loyalty points accrual, levels, referrals, redemption |
services/blog/ |
Blog posts, categories, comments (public read / admin write) |
services/digital-goods/ |
Encrypted digital-goods delivery; key stored under DIGITAL_GOODS_ENC_KEY |
services/file/ |
Multer multipart upload, MIME validation, static serving under /uploads |
services/email/ |
Nodemailer SMTP + Resend transport, templated emails |
services/ai/ |
OpenAI-backed request description generation and content moderation |
services/redis/ |
Redis client singleton, cache helpers, pub-sub wrappers |
services/admin/ |
Admin-only endpoints: data cleanup (provider-scoped), confirmation thresholds, awaiting-confirmation view |
services/collection/ |
Collection management (multi-seller feature) |
services/delivery/ |
Delivery tracking and status |
infrastructure/socket/ |
Socket.IO server attached to HTTP server; Redis adapter for multi-process pub-sub |
5. API Surface Summary
All API routes are mounted under /api/. The table below lists top-level route groups.
| Mount path | Service module | Auth | Purpose |
|---|---|---|---|
/api/auth |
services/auth/authRoutes.ts |
mixed | Login, register, refresh, OAuth, passkey |
/api/user / /api/users |
services/user/userRoutes.ts |
JWT | Profile, preferences |
/api/address |
services/user/addressRoutes.ts |
JWT | Address CRUD |
/api/marketplace/requests |
services/marketplace/ |
JWT | PurchaseRequest CRUD |
/api/marketplace/offers |
services/marketplace/ |
JWT (seller) | SellerOffer CRUD |
/api/marketplace/templates |
services/marketplace/ |
JWT (seller) | RequestTemplate CRUD |
/api/marketplace/categories |
services/marketplace/ |
public read | Category list |
/api/marketplace/shop-settings |
services/marketplace/shopSettingsController.ts |
JWT (seller) | Shop profile |
/api/payment |
services/payment/paymentControllerRoutes.ts |
JWT | Payment CRUD, status, export |
/api/payment/decentralized |
services/payment/decentralizedPaymentRoutes.ts |
mixed | Legacy/manual Web3 save and verify |
/api/payment/request-network |
services/payment/requestNetwork/ |
mixed + HMAC | RN pay-in, checkout rehydrate, webhook |
/api/payment/derived-destinations |
services/payment/wallets/ |
JWT (admin) | HD address list, sweeps, cron config |
/api/telegram |
services/telegram/telegramRoutes.ts |
mixed | Mini App session, bot webhook, identity link |
/api/chat |
services/chat/chatRoutes.ts |
JWT | Conversations, messages |
/api/notification |
services/notification/ |
JWT | List, mark-as-read |
/api/disputes |
services/dispute/ |
JWT | Dispute CRUD, evidence, release-hold |
/api/blog |
services/blog/blogRoutes.ts |
mixed | Public reads, admin writes |
/api/points |
services/points/pointsRoutes.ts |
JWT | Points, levels, referrals |
/api/ai |
services/ai/aiRoutes.ts |
JWT | OpenAI helpers |
/api/files |
services/file/fileRoutes.ts |
JWT | Multipart upload |
/api/email |
services/email/emailRoutes.ts |
JWT | Email dispatch |
/api/trezor |
services/trezor/trezorRoutes.ts |
JWT | Trezor hardware-wallet ops |
/api/admin/cleanup |
services/admin/dataCleanupRoutes.ts |
JWT (admin) | Data cleanup (must be provider-scoped) |
/api/admin/rn/networks |
services/payment/requestNetwork/networkRegistryRoutes.ts |
JWT (admin) | RN chain/token registry |
/api/admin/settings/confirmation-thresholds |
services/admin/confirmationThresholdRoutes.ts |
JWT (admin) | Runtime confirmation thresholds |
/health |
app.ts |
public | Docker healthcheck; surfaces active Postgres store modes |
Full per-endpoint details: 03 - API Reference/API Overview
6. Database
PostgreSQL (primary)
- Driver:
pg ^8.21.0via Drizzle ORM (drizzle-orm ^0.45.2) - Connection:
PG_URL(primary pool);PG_VITAL_URL/PG_NONVITAL_URLfor split-pool configuration - Pool tuning:
PG_POOL_MAX,PG_POOL_SIZE,PG_NONVITAL_POOL_MAX - Migrations: numbered SQL files in
src/db/migrations/(0000–0018+), applied via Drizzle Kit (npx drizzle-kit migrate) - Repositories:
DrizzleXxxRepoclasses insrc/db/repositories/; factory pattern viafactory.ts - Seeds: idempotent Postgres-capable seed scripts under
src/seeds/; auto-run on start whenAUTO_SEED_ON_START=true
MongoDB (retired)
MongoDB and Mongoose have been fully removed from the runtime. The MONGODB_URI and MIGRATION_MONGO_URL env vars exist only for optional data backfill tooling in src/db/repositories/migration/. No Mongo connection is established at server boot. MONGO_CONNECT_MODE=never is the effective runtime mode.
The DATABASE_URL / POSTGRES_URL aliases are accepted for compatibility; prefer PG_URL.
7. Auth Model
JWT
- Access tokens signed with
JWT_SECRET; expiry controlled byJWT_EXPIRES_IN - Refresh tokens with
REFRESH_TOKEN_EXPIRES_IN; stored and rotated server-side authMiddlewareinshared/middleware/verifies tokens and attachesreq.user- Role-based access via
roleGuard('admin' | 'seller' | 'buyer' | 'resolver' | 'guard')
WebAuthn / Passkey
- Passkey registration and assertion handled in
services/auth/ - Enables passwordless login on supported clients
Google OAuth
GOOGLE_CLIENT_IDenables Google OAuth 2.0 sign-in
Telegram Mini App
- Mini App sessions verified via Telegram
initDataHMAC inservices/telegram/ - Identity linking ties a Telegram user to a platform account
TELEGRAM_WEBAPP_URLcontrols the allowed Mini App origin
Rate limits on auth endpoints
- Login: 10 requests per 15-minute window (
LOGIN_RATE_LIMIT_ENABLEDto toggle) - Cloudflare Turnstile CAPTCHA support:
TURNSTILE_SECRET_KEY
8. Realtime (Socket.IO)
- Socket.IO server is attached to the HTTP server at bootstrap (
infrastructure/socket/socketService.ts) - Redis adapter (
@socket.io/redis-adapter) enables pub-sub across Node cluster workers - Room conventions:
user:<userId>— personal notifications, payment status updatespayment:<paymentId>— scoped payment lifecycle events (added in v2.8.4 to prevent global cart-wipe)dispute:<disputeId>— dispute chat and statuschat:<conversationId>— chat messages
- Key emitted events:
payment:update,notification:new,dispute:update,chat:message,offer:update - Server verifies JWT on
connectionand room join; frontend must join the correct room after authenticating
9. Payment Providers
| Provider | Type | Chains / Tokens | Notes |
|---|---|---|---|
| amn.scanner | In-house on-chain scanner | ETH, BSC (USDT/USDC) | Bearer auth via AMN_SCANNER_API_KEY; webhook secret AMN_SCANNER_WEBHOOK_SECRET; provider tag "amn.scanner" |
| Request Network | Decentralized invoicing | ETH, Base (USDC/DAI) | REQUEST_NETWORK_* env block; HMAC webhook signature; canonical proxy addresses differ per chain (ETH 0x370DE2…, Base 0x189219…) |
| SHKeeper | Self-hosted crypto gateway | BTC, ETH, BNB, USDT, others | SHKEEPER_NETWORK, SHKEEPER_NETWORKS, SHKEEPER_ALLOWED_TOKENS |
| DePay | Web3 payment widget | EVM chains | Legacy path; PAYMENT_CALLBACK_SECRET |
| Derived Destinations | HD-wallet receive addresses | ETH / BSC | DERIVED_DESTINATION_XPUB/XPRIV; sweep orchestration runs on configurable interval |
Payment orchestration
PAYMENT_PROVIDER_MODEselects active provider(s) at runtime- Internal ledger tracks
available,held, andreleasablebalances per payment record - Transaction Safety Provider: AML screening (Chainalysis / OFAC SDN), minimum on-chain confirmation thresholds configurable at runtime (
TRANSACTION_SAFETY_MIN_CONFIRMATIONS,TRANSACTION_SAFETY_AML_PROVIDER) GET /api/payment/:idis exempt from the payment rate limiter (polling-safe)- Cleanup endpoints must always be scoped by
provider:to avoid wiping unrelated payment records
Price Oracle
- Chainlink + OffchainFX feeds;
ORACLE_MAX_STALENESS_Ssets maximum acceptable quote age - Depeg protection rejects or flags stablecoin payments when peg deviation exceeds threshold
ORACLE_BYPASS_ENABLED=truedisables staleness check (dev/test only)
10. CI/CD (Woodpecker)
Four Woodpecker pipeline files under .woodpecker/:
| File | Trigger | Purpose |
|---|---|---|
production.yml |
push to main / master |
Typecheck → build Docker image locally on host → docker compose up -d backend |
development.yml |
cron (parked) | Was the dev-stack auto-deploy; currently inactive |
manual.yml |
manual trigger | Builds image to git.tbs.amn.gg registry (escrow-dev stack ignores registry pulls) |
cleanup.yml |
scheduled | Housekeeping tasks (prune old images, stale data) |
Production pipeline steps
- get-version — reads
package.jsonversion, writesdev-<version>to.tags - typecheck —
npm ci(cached at/opt/woodpecker-cache/backend-npm) thennpm run typecheck; push is blocked if tsc errors exist - build-and-deploy —
docker build -f Dockerfile.prod -t escrow-backend-local:dev .on the agent co-located with the stack; thendocker compose up -d --no-deps --pull never backend - notify —
node scripts/ci/tg-notify.cjsposts success/failure to Telegram (noparse_modeto avoid HTML/Markdown breakage)
escrow-multi stack
The escrow-multi stack (branch feature/white-label-shops) uses .woodpecker/multi.yml. Always deploy via git push forgejo feature/white-label-shops — never via manual SSH or rsync. Woodpecker CLI credentials are in ~/CascadeProjects/escrow/.env.
Version bump requirement
Bump package.json version before every CI-triggering push, or the deployed image will not be distinguishable from the previous build. See memory note version_bump_before_ci.md.
11. Local Development Quick-Start
# 1. Clone
git clone git@git.tbs.amn.gg:escrow/backend.git
cd backend
# 2. Install dependencies
npm install
# 3. Copy and populate env
cp .env.example .env.development
# Edit .env.development — minimum required: PG_URL, REDIS_URI, JWT_SECRET, FRONTEND_URL
# 4. Start Postgres and Redis (Docker)
docker compose up -d postgres redis
# 5. Run migrations
npx drizzle-kit migrate
# 6. Start dev server (seeds run automatically if SEED_USERS=true)
npm run dev
# Server starts on process.env.PORT
# 7. Type-check only (no run)
npm run typecheck
The pre-push git hook runs a full
tsccheck. If a parallel agent's mid-refactor tree is checked out, this hook may block your push. Stage only your specific files — nevergit add -Ablindly. See memory notebackend_prepush_tsc_hook.md.
12. Environment Variables
| Variable | Description |
|---|---|
PORT |
HTTP listen port |
NODE_ENV |
development / production / test |
FRONTEND_URL |
Allowed CORS origin (frontend base URL) |
BACKEND_URL |
Self-referential base URL (used for webhook callback construction) |
PG_URL |
Primary Postgres connection string |
PG_VITAL_URL |
Postgres connection for vital (write-path) pool |
PG_NONVITAL_URL |
Postgres connection for non-vital (read-path) pool |
PG_POOL_MAX |
Max connections in primary pool |
PG_POOL_SIZE |
Pool size alias |
PG_NONVITAL_POOL_MAX |
Max connections in non-vital pool |
DATABASE_URL / POSTGRES_URL |
Compatibility aliases for PG_URL |
REDIS_URI |
Redis connection string (sessions, pub-sub, Socket.IO adapter) |
JWT_SECRET |
HMAC secret for JWT signing |
JWT_EXPIRES_IN |
Access token TTL (e.g. 15m) |
REFRESH_TOKEN_EXPIRES_IN |
Refresh token TTL (e.g. 7d) |
GOOGLE_CLIENT_ID |
Google OAuth 2.0 client ID |
TELEGRAM_WEBAPP_URL |
Allowed Telegram Mini App origin |
TG_NOTIFY_BOT_TOKEN |
Telegram bot token for CI/admin notifications |
TG_NOTIFY_CHATS |
Comma-separated Telegram chat IDs for notifications |
SMTP_HOST |
SMTP server hostname |
SMTP_PORT |
SMTP port |
SMTP_SECURE |
true for TLS |
SMTP_USER |
SMTP auth username |
SMTP_PASS |
SMTP auth password |
SMTP_FROM |
From address for outbound email |
RESEND_API_KEY |
Resend email API key |
RESEND_WEBHOOK_SECRET |
Resend webhook signature secret |
PAYMENT_PROVIDER_MODE |
Active payment provider(s) |
PAYMENT_CALLBACK_SECRET |
DePay callback HMAC secret |
AMN_SCANNER_URL |
amn.scanner service base URL |
AMN_SCANNER_API_KEY |
Bearer token for amn.scanner API |
AMN_SCANNER_WEBHOOK_SECRET |
HMAC secret for amn.scanner webhook verification |
REQUEST_NETWORK_API_BASE_URL |
Request Network API base URL |
REQUEST_NETWORK_API_KEY |
Request Network API key |
REQUEST_NETWORK_CLIENT_ID |
RN client identifier |
REQUEST_NETWORK_NETWORK |
RN chain name (mainnet / sepolia / etc.) |
REQUEST_NETWORK_RECEIVER_ADDRESS |
Merchant wallet for RN payments |
REQUEST_NETWORK_PAYMENT_CURRENCY |
Payment token symbol |
REQUEST_NETWORK_PAYMENT_TOKEN_ADDRESS |
Payment token contract address |
REQUEST_NETWORK_INVOICE_CURRENCY |
Invoice denomination currency |
REQUEST_NETWORK_WEBHOOK_CALLBACK_URL |
RN webhook delivery URL |
REQUEST_NETWORK_WEBHOOK_SECRET |
HMAC secret for RN webhook |
REQUEST_NETWORK_MERCHANT_REFERENCE |
RN merchant reference string |
REQUEST_NETWORK_ORIGIN |
RN request origin header |
RN_API_KEY |
Alias for REQUEST_NETWORK_API_KEY |
RN_API_URL |
Alias for REQUEST_NETWORK_API_BASE_URL |
RN_CLIENT_ID |
Alias for REQUEST_NETWORK_CLIENT_ID |
RN_WEBHOOK_SECRET |
Alias for REQUEST_NETWORK_WEBHOOK_SECRET |
SHKEEPER_NETWORK |
SHKeeper primary network identifier |
SHKEEPER_NETWORKS |
SHKeeper supported networks (comma-separated) |
SHKEEPER_ALLOWED_TOKENS |
Token allowlist for SHKeeper |
DERIVED_DESTINATION_XPUB |
HD wallet extended public key for address derivation |
DERIVED_DESTINATION_XPRIV |
HD wallet extended private key (for sweep signing) |
DERIVED_DESTINATION_BASE_PATH |
BIP-44 derivation base path |
DERIVED_DESTINATION_CHAIN_ID |
EVM chain ID for derived address sweeps |
DERIVED_DESTINATION_MIN_SWEEP_AMOUNT |
Minimum balance to trigger a sweep |
DERIVED_DESTINATION_SWEEP_INTERVAL_MS |
Sweep polling interval in milliseconds |
DERIVED_DESTINATION_SWEEP_BALANCE_CONCURRENCY |
Parallel balance-check concurrency |
DERIVED_DESTINATION_SWEEP_SIGNER |
Sweep transaction signing mode |
DERIVED_DESTINATION_SWEEP_AUTOSTART |
Auto-start sweep cron on boot |
SWEEP_MASTER_PRIVKEY |
Master private key for sweep gas top-up |
SWEEP_GAS_MIN_BNB |
Minimum BNB balance before gas top-up is triggered |
SWEEP_GAS_TOP_UP_BNB |
Amount of BNB to top up for sweep gas |
ESCROW_WALLET_ADDRESS |
Platform escrow wallet address |
RECEIVER_WALLET_ADDRESS |
Platform receiver wallet address |
INFURA_KEY |
Infura RPC key (ETH mainnet) |
BSC_RPC_URL |
BSC mainnet RPC endpoint |
BSC_TESTNET_RPC_URL |
BSC testnet RPC endpoint |
BNB_TESTNET_RPC_URL |
BNB testnet RPC endpoint |
RPC_URL_CHAIN_56 |
BSC mainnet RPC (chain ID 56) |
RPC_URL_CHAIN_97 |
BSC testnet RPC (chain ID 97) |
ENABLE_TESTNET_CHAINS |
Enable testnet chain support |
TRANSACTION_SAFETY_AML_PROVIDER |
AML provider: chainalysis / ofac / none |
TRANSACTION_SAFETY_MIN_CONFIRMATIONS |
Default minimum on-chain confirmations |
CHAINALYSIS_API_KEY |
Chainalysis KYT API key |
OFAC_SDN_URL |
OFAC SDN list endpoint |
AML_CHECK_COST_USD |
Cost per AML check (for billing/reporting) |
ORACLE_MAX_STALENESS_S |
Maximum age (seconds) for oracle price quotes |
ORACLE_BYPASS_ENABLED |
Disable oracle staleness check (true in dev/test only) |
DIGITAL_GOODS_ENC_KEY |
AES encryption key for digital goods delivery |
TREZOR_SAFEKEEPING_REQUIRED |
Require Trezor safekeeping confirmation |
TURNSTILE_SECRET_KEY |
Cloudflare Turnstile CAPTCHA secret |
RATE_LIMIT_WINDOW_MS |
Rate limit window in milliseconds |
RATE_LIMIT_MAX_REQUESTS |
Max requests per window (global limiter) |
RATE_LIMIT_BYPASS_IPS |
Comma-separated IPs exempt from rate limiting |
LOGIN_RATE_LIMIT_ENABLED |
Enable/disable login rate limiter |
TRUST_PROXY_HOPS |
trust proxy hop count for X-Forwarded-For behind Traefik |
UPLOAD_PATH |
Filesystem path for uploaded files (default /app/uploads) |
MAX_FILE_SIZE |
Maximum upload size in bytes |
CLUSTER_WORKERS |
Number of Node cluster worker processes |
SEED_USERS |
Seed default dev users on start |
AUTO_SEED_ON_START |
Auto-run all seeds on process start |
SEED_DIGITAL_GOODS_ON_START |
Seed digital goods fixtures on start |
SEED_MOCK_SHOPS_ON_START |
Seed mock shop fixtures on start |
FORCE_SEED_TEMPLATES |
Force re-seed request templates even if already present |
SEED_PASSWORD_SELLER |
Password for seeded seller account |
SEED_PASSWORD_MOCK_SELLER |
Password for seeded mock seller account |
SEED_PASSWORD_SUPPORT |
Password for seeded support account |
ADMIN_EMAIL |
Seeded admin user email |
ADMIN_PASSWORD |
Seeded admin user password |
ADMIN_FIRST_NAME |
Seeded admin first name |
ADMIN_LAST_NAME |
Seeded admin last name |
MIGRATION_MONGO_URL |
Mongo URL used only by migration/backfill tooling (not runtime) |
MIGRATION_PG_URL |
Postgres URL used by migration tooling (may differ from PG_URL) |
MONGODB_URI |
Legacy Mongo URI retained for backfill scripts only |
DB_NAME |
Database name (legacy config field) |
Store-mode env vars (
AUTH_STORE,USER_STORE,BLOG_STORE, etc.) were part of the dual-write migration scaffolding. All domains are now Postgres-only; these can be left unset or set topostgres.
13. Known Issues / Open Items
| Issue | Status | Reference |
|---|---|---|
| Rate limit counters are in-memory | Not multi-process safe across cluster workers; Redis adapter planned | backend_rate_limits.md |
pgId vs legacy _id mismatch |
Auth _id is a legacy ObjectId; marketplace FKs use Postgres UUID (pgId); match offers on pgId |
pgid_vs_legacy_id.md |
| Socket.IO room scoping for payments | Backend room-scoping for payment events is an open follow-up (frontend gate added in v2.8.4) | cart_wipe_global_socket_events.md |
| Performance is WAN-bound | Profiling shows 300–800ms on external routes = WAN RTT (~235ms); server-side is 3–12ms; PG migration does not fix this | perf_is_network_bound_not_db.md |
RN webhook event field |
Request Network sends discriminator as payload.event not eventType; parser must include event in fallback chain |
rn_webhook_event_field.md |
| RN canonical proxy addresses per chain | ETH 0x370DE2…, Base 0x189219… — not the same CREATE2 address; always probe before using hardcoded addresses |
rn_proxy_addresses_per_chain.md |
| JSON assets not copied to dist | tsc does not copy .json files; any fs.readFileSync on JSON needs explicit postbuild copy step |
feedback_json_assets_copy_to_dist.md |
Woodpecker ${VAR} template collision |
Woodpecker eats ${VAR} in commands; use $VAR or $$VAR |
woodpecker_template_collision.md |
| CI silent build fail | Green CI does not guarantee image was pushed to registry; verify dev-<version> tag exists before trusting |
woodpecker_silent_build_fail.md |
| Admin cleanup must be provider-scoped | Any payment cleanup query must filter by provider: or it silently destroys multi-seller/RN records |
feedback_payment_cleanup_provider_filter.md |
| Store-mode env vars | Legacy dual-write *_STORE vars still present in codebase but are no-ops; can be pruned in a future cleanup |
— |
| Mongo backfill tooling | MIGRATION_MONGO_URL / MONGODB_URI retained for backfill scripts only; server never connects to Mongo at runtime |
mongo_retirement_status.md |