From eb0f79be82f625e9555300a34dff4299dbe86c34 Mon Sep 17 00:00:00 2001 From: tiennm99 Date: Sun, 10 May 2026 00:23:16 +0700 Subject: [PATCH] chore: drop migration leftovers, refresh env examples + secret-leak scope - remove MONGODB_URI from .env.example (Atlas migration done; deleted from Vercel cloud env too) - trim .env.deploy.example to vars actually consumed by deploy scripts (Upstash creds were only needed by the now-deleted migration script) - README config table: drop ENV / SOURCE_COMMIT / SCHEDULE_CHECK_APP_TIME (never read by code; Java-era leftovers) - check-secret-leaks: drop MONGODB_URI; add UPSTASH/KV/CRON tokens; widen scan roots to include api/ - add scripts/list-upstash-keys.js read-only ops helper --- .env.deploy.example | 15 ++++-------- .env.example | 3 --- README.md | 7 ++---- scripts/check-secret-leaks.js | 11 +++++++-- scripts/list-upstash-keys.js | 43 +++++++++++++++++++++++++++++++++++ 5 files changed, 58 insertions(+), 21 deletions(-) create mode 100644 scripts/list-upstash-keys.js diff --git a/.env.deploy.example b/.env.deploy.example index 9463356..d4dab8d 100644 --- a/.env.deploy.example +++ b/.env.deploy.example @@ -1,18 +1,11 @@ -# Operator-only file: holds the credentials the deploy + migrate scripts need. +# Operator-only file: holds the credentials the deploy scripts need. # Copy to .env.deploy and fill in. NEVER commit .env.deploy. -# Telegram (must match values set as Vercel env vars) +# Telegram (must match values set as Vercel env vars). +# Used by: scripts/register-webhook.js, scripts/set-bot-description.js TELEGRAM_BOT_TOKEN= TELEGRAM_WEBHOOK_SECRET= -# Where Telegram should send webhook updates after Phase 6 cutover. +# Where Telegram should send webhook updates. # Format: https:///api/webhook -# Variable name kept as WORKER_URL for register-webhook.js compatibility. WORKER_URL=https://store-scraper-bot.vercel.app/api/webhook - -# Upstash Redis credentials — required by migrate-atlas-to-upstash.js. -# If the Vercel Marketplace Upstash integration is set up, the bot also -# accepts KV_REST_API_URL / KV_REST_API_TOKEN as fallbacks (see upstash.js). -UPSTASH_REDIS_REST_URL= -UPSTASH_REDIS_REST_TOKEN= -KEY_PREFIX=store-scraper-bot: diff --git a/.env.example b/.env.example index 4878d05..b6b5e6f 100644 --- a/.env.example +++ b/.env.example @@ -19,6 +19,3 @@ CRON_SECRET=generate_another_random_string_at_least_32_chars ADMIN_IDS=123456789,987654321 APP_CACHE_SECONDS=600 NUM_DAYS_WARNING_NOT_UPDATED=30 - -# One-shot migration only (Phase 5: legacy Atlas → Upstash). Remove after migration done. -MONGODB_URI=mongodb+srv://user:pass@cluster.mongodb.net/dbname diff --git a/README.md b/README.md index c3a37d0..0ad9d92 100644 --- a/README.md +++ b/README.md @@ -36,13 +36,10 @@ Vercel env vars: | `UPSTASH_REDIS_REST_TOKEN` | Upstash REST token (or `KV_REST_API_TOKEN` fallback) | | `KEY_PREFIX` | Namespace for all Redis keys (default `store-scraper-bot:`) | | `CRON_SECRET` | ≥32 chars random; required by Vercel Cron handler | -| `ENV` | `DEVELOPMENT` or `PRODUCTION` | -| `SOURCE_COMMIT` | Optional; shown on startup | | `APP_CACHE_SECONDS` | Cache TTL for upstream API responses (default 600) | -| `NUM_DAYS_WARNING_NOT_UPDATED` | Threshold for daily warning (default 30) | -| `SCHEDULE_CHECK_APP_TIME` | Cron expression in Vietnam timezone (default `0 7 * * *`) | +| `NUM_DAYS_WARNING_NOT_UPDATED` | Default warning threshold in days (default 30; per-group override via `/setdayswarning`) | -Operator-only `.env.deploy` (used by `npm run register`) — see `.env.deploy.example`. +Operator-only `.env.deploy` (used by `npm run register` + `npm run describe`) — see `.env.deploy.example`. ## Run diff --git a/scripts/check-secret-leaks.js b/scripts/check-secret-leaks.js index bbc2327..64fdf99 100644 --- a/scripts/check-secret-leaks.js +++ b/scripts/check-secret-leaks.js @@ -4,8 +4,15 @@ import { readdirSync, readFileSync, statSync } from 'node:fs'; import { join } from 'node:path'; -const SECRETS = ['MONGODB_URI', 'TELEGRAM_BOT_TOKEN', 'TELEGRAM_WEBHOOK_SECRET', 'ADMIN_IDS']; -const ROOTS = ['src', 'scripts']; +const SECRETS = [ + 'TELEGRAM_BOT_TOKEN', + 'TELEGRAM_WEBHOOK_SECRET', + 'UPSTASH_REDIS_REST_TOKEN', + 'KV_REST_API_TOKEN', + 'CRON_SECRET', + 'ADMIN_IDS', +]; +const ROOTS = ['src', 'scripts', 'api']; function* walk(dir) { let entries; diff --git a/scripts/list-upstash-keys.js b/scripts/list-upstash-keys.js new file mode 100644 index 0000000..54a694a --- /dev/null +++ b/scripts/list-upstash-keys.js @@ -0,0 +1,43 @@ +#!/usr/bin/env node +// One-shot inspector: lists every Redis key the bot can see. +// Run via: node --env-file=.env.deploy scripts/list-upstash-keys.js +// Read-only. + +import { Redis } from '@upstash/redis'; + +const url = process.env.UPSTASH_REDIS_REST_URL ?? process.env.KV_REST_API_URL; +const token = process.env.UPSTASH_REDIS_REST_TOKEN ?? process.env.KV_REST_API_TOKEN; +const prefix = process.env.KEY_PREFIX ?? 'store-scraper-bot:'; + +if (!url || !token) { + console.error('Upstash credentials not found in env'); + process.exit(1); +} + +const redis = new Redis({ url, token }); + +let cursor = 0; +const keys = []; +do { + const [next, batch] = await redis.scan(cursor, { match: '*', count: 100 }); + cursor = Number(next); + keys.push(...batch); +} while (cursor !== 0); + +keys.sort(); + +const inPrefix = keys.filter((k) => k.startsWith(prefix)); +const orphan = keys.filter((k) => !k.startsWith(prefix)); + +console.log(`KEY_PREFIX: ${prefix}`); +console.log(`Total keys: ${keys.length}`); +console.log(`In-prefix: ${inPrefix.length}`); +console.log(`Orphan: ${orphan.length}`); +console.log(); +console.log('In-prefix keys:'); +for (const k of inPrefix) console.log(` ${k}`); +if (orphan.length) { + console.log(); + console.log('Orphan keys (NOT under KEY_PREFIX):'); + for (const k of orphan) console.log(` ${k}`); +}