NumberVault

Python-only operations platform for a legitimate phone-number inventory shop:

  • aiogram 3 Telegram bot β€” mandatory channel membership, service/country browsing, 5 listings per page, random number, reservation, UPI QR + payment instructions, screenshot upload, account and order history.
  • Gradio 6 admin dashboard β€” overview, inventory + bulk TXT import, orders and manual payment review, customers, pricing rules, analytics, broadcasts, settings, backup/restore, activity logs and system health.
  • FastAPI /health β€” public UptimeRobot-friendly probe. Database failure returns HTTP 503; degraded states (no bucket, stale backup, bot offline) return HTTP 200 with "status": "degraded".

Storage model (important)

The live SQLite database is local (DATA_DIR), never on the bucket. The Hugging Face bucket is object storage mounted at /data; it does not provide the locking/atomic-rename behaviour SQLite needs. The bucket is used only for consistent SQLite snapshots, manifests and payment-proof files.

Write transactions use SQLite WAL, synchronous=FULL, BEGIN IMMEDIATE, busy_timeout=30000 and bounded retries. Reservations use conditional UPDATE ... WHERE status='AVAILABLE' plus partial unique indexes, so two buyers cannot reserve one number.

On startup the app verifies the local DB. If it is missing/corrupt it restores the newest verified backup from the bucket. Backups are created after commits (debounced), periodically, and at shutdown. RPO is the backup interval (or the last successful post-commit backup); local-only downtime between container replacement and restore is the honest limitation of ephemeral Space storage. Use persistent hardware if zero-RPO is required.

Configuration

Set these as Space secrets:

Secret Required Notes
ADMIN_PASSWORD yes β‰₯10 chars, not a default. Or set ADMIN_PASSWORD_HASH.
TELEGRAM_BOT_TOKEN for bot Without it the dashboard and /health still work; bot status is disabled.
ADMIN_TELEGRAM_IDS for bot admin Comma-separated Telegram user IDs.
ADMIN_CHAT_ID recommended Chat that receives payment-review notifications.
PAYMENT_UPI for payments UPI VPA, e.g. shop@bank.
REQUIRED_CHANNELS no Comma-separated channel usernames without @.

Space variables (non-secret): ENV=production, DATA_DIR=/tmp/numbervault, BUCKET_MOUNT=/data, CURRENCY=INR, TIMEZONE=Asia/Kolkata.

Mount the bucket as a volume:

hf spaces volumes set nezuhub/number-vault \
  -v hf://buckets/nezuhub/numbervault-storage:/data

The dashboard is protected by server-side Gradio auth. Secrets are never stored in SQLite or rendered in the UI.

Local run

python -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt
cp config.example.env .env
# edit .env (set ENV=test for a quick local password bypass)
uvicorn app:app --host 0.0.0.0 --port 7860
curl -fsS http://127.0.0.1:7860/health | python -m json.tool

The dashboard is at /. /healthz is a minimal liveness probe; /status is a small runtime status document.

Inventory import

Format, one number per line:

+919876543210 / 50
+14155552671 / 12.50

+ and country code are mandatory. Country/ISO is detected with phonenumbers; price is parsed as decimal and stored as integer minor units. Preview reports line-level valid/duplicate/invalid rows and offers a CSV error report. Commit re-validates and uses ON CONFLICT DO NOTHING, so a concurrent import cannot create duplicates.

Tests

pytest -q

The suite covers phone validation/country detection, import preview/commit and dedupe, 5-per-page browsing, concurrent reservations, one-active-order-per-user, payment approval/rejection, reservation expiry, settings validation, password hashing/authorization, backup verify/restore, cold-start recovery, dashboard construction and FastAPI health endpoints. See TEST_RESULTS.md.

Security / scope

  • Manual payment review; no account-session resale, credential distribution or authentication-code relay is implemented or supported.
  • Only JPEG/PNG/WebP payment screenshots are accepted, with server-side size and magic-byte validation.
  • Dashboard login is verified server-side against a PBKDF2 hash (or a production-length plaintext secret from the environment).
  • Uploaded proofs are written to local disk and mirrored to the bucket; the live database is never exposed through Gradio file paths.
Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support