metatroncubeswdev 65a01af4d3
Some checks failed
CI / ci (push) Has been cancelled
CI / docker-build (push) Has been cancelled
Publish Docker image / docker (push) Has been cancelled
Upload sourcemaps / upload (push) Has been cancelled
Fix critical billing bugs, add local usage caps, publish sales demo
Three launch blockers from the Oct 17 direct-Stripe billing work:

- verifyStripeCheckoutSession defaulted an unconfirmed checkout session
  to "active"/isPaying:true, and had no billing permission check, so an
  abandoned (unpaid) checkout marked the org as a paying subscriber for
  free. Now defaults to "incomplete" and only trusts a real subscription
  status or a confirmed paid payment_status; also pins org id to the
  caller's own organization instead of trusting session metadata.
- The Stripe webhook fell back to parsing an unsigned request body as a
  real event whenever STRIPE_WEBHOOK_SECRET was unset, letting anyone POST
  a fake checkout.session.completed and grant any org a paid plan.
  STRIPE_WEBHOOK_SECRET is now required; unsigned requests are refused.
  Also maps Stripe's subscription.status properly (trialing counted as
  active) instead of collapsing anything but "active" to "canceled".
- meterDataforseoCall and every credit-check in subscription.ts skipped
  all usage metering/capping whenever AUTUMN_SECRET_KEY was unset — which
  is exactly the mode the Oct 17 work introduced for self-host direct
  Stripe billing. Added a local per-org monthly usage ledger
  (usage_ledger table, sqlite + pg) checked against each plan's monthly
  data budget (src/shared/crawlerxPlanBudgets.ts, from the PRD's unit
  economics table) so DataForSEO spend is capped even without Autumn.

Also: documented STRIPE_SECRET_KEY/STRIPE_WEBHOOK_SECRET/AUTUMN_SECRET_KEY
in .env.example, and published the CrawlerX product demo as a static page
at /demo.html (self-contained, no backend dependency).

Verified: tsc --noEmit clean, schema-parity test green, full vitest suite
green except two pre-existing unrelated failures (confirmed via stash),
knip/oxlint show no new findings over the pre-change baseline.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-17 16:24:38 -04:00

188 lines
3.8 KiB
JSON

{
"version": "7",
"dialect": "postgresql",
"entries": [
{
"idx": 0,
"version": "7",
"when": 1780611624042,
"tag": "0000_fixed_nico_minoru",
"breakpoints": true
},
{
"idx": 1,
"version": "7",
"when": 1781809009342,
"tag": "0001_striped_bulldozer",
"breakpoints": true
},
{
"idx": 2,
"version": "7",
"when": 1781902417326,
"tag": "0002_clean_moira_mactaggert",
"breakpoints": true
},
{
"idx": 3,
"version": "7",
"when": 1782833725049,
"tag": "0003_sturdy_may_parker",
"breakpoints": true
},
{
"idx": 4,
"version": "7",
"when": 1782851683039,
"tag": "0004_dashing_betty_ross",
"breakpoints": true
},
{
"idx": 5,
"version": "7",
"when": 1783117905771,
"tag": "0005_talented_wild_pack",
"breakpoints": true
},
{
"idx": 6,
"version": "7",
"when": 1783438455708,
"tag": "0006_location_name",
"breakpoints": true
},
{
"idx": 7,
"version": "7",
"when": 1783306049167,
"tag": "0007_same_marvel_zombies",
"breakpoints": true
},
{
"idx": 8,
"version": "7",
"when": 1783630716543,
"tag": "0008_yummy_annihilus",
"breakpoints": true
},
{
"idx": 9,
"version": "7",
"when": 1783699015488,
"tag": "0009_supreme_captain_stacy",
"breakpoints": true
},
{
"idx": 10,
"version": "7",
"when": 1784070000325,
"tag": "0010_overrated_amazoness",
"breakpoints": true
},
{
"idx": 11,
"version": "7",
"when": 1784410131656,
"tag": "0011_friendly_morlun",
"breakpoints": true
},
{
"idx": 12,
"version": "7",
"when": 1784423181488,
"tag": "0012_dashboard",
"breakpoints": true
},
{
"idx": 13,
"version": "7",
"when": 1784426969390,
"tag": "0013_sleepy_black_tarantula",
"breakpoints": true
},
{
"idx": 14,
"version": "7",
"when": 1784588248793,
"tag": "0014_solid_centennial",
"breakpoints": true
},
{
"idx": 15,
"version": "7",
"when": 1784610564142,
"tag": "0015_sticky_dagger",
"breakpoints": true
},
{
"idx": 16,
"version": "7",
"when": 1785608388841,
"tag": "0016_panoramic_blob",
"breakpoints": true
},
{
"idx": 17,
"version": "7",
"when": 1786066279773,
"tag": "0017_ga4_connections",
"breakpoints": true
},
{
"idx": 18,
"version": "7",
"when": 1786208325786,
"tag": "0018_drop_reddit_attributions",
"breakpoints": true
},
{
"idx": 19,
"version": "7",
"when": 1786209409297,
"tag": "0019_clammy_selene",
"breakpoints": true
},
{
"idx": 20,
"version": "7",
"when": 1787099999115,
"tag": "0020_project_memory",
"breakpoints": true
},
{
"idx": 21,
"version": "7",
"when": 1787594239250,
"tag": "0021_user_last_active_organization",
"breakpoints": true
},
{
"idx": 22,
"version": "7",
"when": 1787773500453,
"tag": "0022_third_supernaut",
"breakpoints": true
},
{
"idx": 23,
"version": "7",
"when": 1788983569510,
"tag": "0023_clever_prowler",
"breakpoints": true
},
{
"idx": 24,
"version": "7",
"when": 1789226958095,
"tag": "0024_heavy_arachne",
"breakpoints": true
},
{
"idx": 25,
"version": "7",
"when": 1792268181660,
"tag": "0025_oval_korg",
"breakpoints": true
}
]
}