Skip to content

Phase 2: Monetization MVP — Stripe, license keys, Pro feature gating#2

Merged
Gavand1969 merged 4 commits into
mainfrom
monetization
May 12, 2026
Merged

Phase 2: Monetization MVP — Stripe, license keys, Pro feature gating#2
Gavand1969 merged 4 commits into
mainfrom
monetization

Conversation

@Gavand1969

Copy link
Copy Markdown
Owner

What this adds

Turns Sim2Sim from a free demo into a paid product, ready to deploy in one afternoon.

New

  • Excel + PDF exports for queuing, inventory, and LP results (Pro)
  • License key systemLIC-XXXX-XXXX-XXXX-XXXX, HMAC-signed, SQLite-backed
  • Stripe webhook at /api/billing/webhook — stdlib-only signature verification, no SDK dependency
  • Resend email sends license key automatically on checkout.session.completed
  • Pricing page at /pricing — three-tier card layout (Free, $49 Pro, $249 Team)
  • Account page at /account — paste-key activation, no login required
  • Pro gating — Free users see locked export buttons + upgrade modal
  • Tier pill in header reflects live license status

Tests

Was 64 → now 111 passing:

  • 24 new in tests/test_billing.py — key generation/validation, activation, webhook signature, idempotency, end-to-end license creation
  • 23 from the export module commit — xlsx integrity, PDF magic bytes, route gating

Files

 src/billing/{__init__,db,licenses,email,webhook,schemas}.py   new
 src/export/{__init__,excel,pdf}.py                             from f42b1b6
 src/api/routes.py                                              + billing routes
 main.py                                                        + /pricing, /account routes; init_db()
 static/{pricing,account}.html                                  new
 static/js/{license,exports}.js                                 new
 static/css/billing.css                                         new
 static/index.html + static/js/app.js                           wiring
 tests/{test_billing,test_exports}.py                           new
 LAUNCH.md                                                      30-min deploy checklist
 .env.example                                                   full prod config

Operator checklist before going live

See LAUNCH.md for the full 30-minute walkthrough:

  1. Buy domain (recommended: sim2sim.app)
  2. Create two Stripe Payment Links ($49 Pro, $249 Team)
  3. Add webhook endpoint → /api/billing/webhook
  4. Sign up for Resend (free tier: 100 emails/day)
  5. Paste secrets into Replit Secrets
  6. Test with Stripe test card 4242 4242 4242 4242
  7. Flip Stripe to live mode

Notes

  • Dev bypass: with ENVIRONMENT=development, the license key dev (or empty header) unlocks Pro endpoints, so the demo still runs without Stripe.
  • License DB is SQLite at sim2sim.db. Replit's filesystem persists this across deploys. Excluded from git via .gitignore.
  • Webhook handler is idempotent on stripe_session_id — Stripe's retries won't double-issue keys.
  • No login system. License key is the only credential. Trades convenience (no signup friction) for the limitation that lost keys must be recovered via email.

- Rename Sim2Real -> Sim2Sim across README, page, hero, docstrings, CSS, JS
- Add GitHub Actions CI workflow (fixes broken badge)
- Fix solve_base_stock dead code; correct Type-II fill-rate formula
  (1 - E[B per cycle] / mu_L, not E_B * D / D)
- Standardize inventory lead-time to DAYS everywhere
  (lead_time_days param; sigma_L = sigma_d * sqrt(L_days)) for unit consistency
- Add _little_law_residual: relative Little's Law diagnostic instead of absolute
- Simulation: fix warm-up off-by-one; raise default warmup to max(100, N/5)
- Production CORS: require ALLOWED_ORIGIN (fail loudly on empty)
- Cache Anthropic client lazily at module level
- Add pyproject.toml with ruff + mypy + pytest config
- README polish: live demo placeholder, screenshot, monetization note
- Add 7 new tests for reorder-point and base-stock (57 -> 64 passing)
- src/export/excel.py: queuing, inventory, LP workbook builders (openpyxl)
- src/export/pdf.py: ReportLab Platypus templates with clean Sim2Sim branding
- 6 new POST /api/export/* endpoints gated by require_pro dependency
- Stub src/billing/licenses.py:require_pro (real impl in billing branch)
- 7 new tests in tests/test_exports.py
Billing
- src/billing/licenses.py — HMAC-signed LIC-XXXX-XXXX-XXXX-XXXX keys
- src/billing/db.py — SQLite storage with idempotency on stripe session id
- src/billing/webhook.py — checkout.session.completed handler with
  stdlib-only Stripe signature verification (no SDK dependency)
- src/billing/email.py — Resend integration with graceful no-op when key
  is unset, so failed emails never block paid customers
- src/billing/schemas.py — Pydantic models
- 24 new tests covering key generation, activation, webhook signature
  verification, idempotency, and end-to-end license creation

Endpoints
- POST /api/billing/activate  — paste key, get tier
- GET  /api/billing/status    — header-based status check
- POST /api/billing/webhook   — Stripe receiver

Frontend
- static/pricing.html — three-tier card layout (Free / 49 Pro / 249 Team)
- static/account.html — paste-key flow + clear-license button
- static/js/license.js — localStorage handling, status fetch, activation
- static/js/exports.js — Excel + PDF buttons attached after each result;
  Free users see a locked button + Upgrade modal
- static/css/billing.css — pricing grid, account card, modal, tier pill
- index.html — Pricing/Account nav links, tier pill, exports.js wiring
- app.js — Sim2SimExports.attach() called after each render call site

Plumbing
- main.py — explicit /pricing and /account routes (catch-all served SPA);
  lifespan now calls billing_db.init_db()
- .env.example — full launch config (Stripe, Resend, license secret, app URL)
- .gitignore — exclude sim2sim.db and its WAL/journal files
- LAUNCH.md — 30-minute deployment checklist (domain, Stripe, Resend, Replit)

Tests: 111 passed (was 64 → +47: 24 billing + 23 from export module)
@Gavand1969 Gavand1969 merged commit dabf598 into main May 12, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant