Skip to content
This repository was archived by the owner on Apr 29, 2026. It is now read-only.
j8dPublic archive

About

Resources

Stars

1 star

Watchers

1 watching

Forks

Repository files navigation

Karate Debug API

Licensing and subscription management API for the Karate Debug VS Code Extension. This serverless API handles user authentication, subscription management, and license validation.

🏗️ Architecture Overview

┌─────────────────┐     ┌──────────────────┐     ┌─────────────────┐
│   VS Code       │────▶│  Karate Debug    │────▶│   Supabase      │
│   Extension     │     │  API (Vercel)    │     │   (PostgreSQL)  │
└─────────────────┘     └──────────────────┘     └─────────────────┘
                               │
                               ▼
                        ┌──────────────────┐
                        │     Stripe       │
                        │  (Payments)      │
                        └──────────────────┘

Tech Stack

Component Technology Purpose
Runtime Vercel Serverless Functions API hosting
Language TypeScript Type-safe development
Database Supabase (PostgreSQL) User data, subscriptions, machine activations
Payments Stripe Subscription billing
Auth GitHub OAuth User authentication
Tokens JWT License validation tokens

Core Features

  • GitHub OAuth Authentication - Users sign in with GitHub
  • Anonymous Machine Trials - 30-day trial without requiring signup
  • Stripe Subscriptions - Monthly/annual billing
  • Machine Licensing - Limit of 5 machines per user
  • JWT License Tokens - 24-hour tokens for offline validation (configurable)

📁 Project Structure

karate-debug-api/
├── api/                    # Vercel serverless functions
│   ├── admin/             # Admin endpoints
│   │   └── user-reset.ts  # Delete user for testing
│   ├── auth/              # Authentication endpoints
│   │   ├── callback.ts    # GitHub OAuth callback
│   │   └── github.ts      # GitHub token exchange
│   ├── license/           # License management
│   │   ├── activate.ts    # Activate machine
│   │   ├── deactivate.ts  # Deactivate machine
│   │   ├── machines.ts    # List user's machines
│   │   ├── refresh.ts     # Refresh expired/expiring token
│   │   └── validate.ts    # Validate license & get token
│   ├── subscription/      # Subscription management
│   │   ├── checkout.ts    # Create Stripe checkout
│   │   ├── portal.ts      # Stripe billing portal
│   │   └── result.ts      # Post-checkout result page
│   ├── trial/             # Anonymous trial management
│   │   ├── start.ts       # Start anonymous machine trial
│   │   └── status.ts      # Check trial status
│   ├── webhooks/          # External webhooks
│   │   └── stripe.ts      # Stripe webhook handler
│   └── health.ts          # Health check endpoint
├── lib/                   # Shared utilities
│   ├── config.ts          # Environment config & validation
│   ├── supabase.ts        # Supabase client & types
│   ├── stripe.ts          # Stripe client
│   ├── jwt.ts             # License token signing/verification
│   ├── sanitize.ts        # XSS protection utilities
│   ├── validation.ts      # Zod request validation schemas
│   ├── sentry.ts          # Error tracking
│   └── api-handler.ts     # API wrapper with error handling
├── tests/                 # Test files
│   ├── helpers/           # Test utilities
│   │   ├── mock-request.ts   # Mock Vercel request/response
│   │   └── mock-supabase.ts  # Mock data factories
│   ├── integration/       # Integration tests
│   │   └── license-validate.test.ts
│   ├── jwt.test.ts        # JWT token tests
│   ├── sanitize.test.ts   # XSS sanitization tests
│   └── validation.test.ts # Schema validation tests
├── supabase/              # Database
│   └── migrations/        # SQL migration files
├── scripts/               # Development scripts
│   ├── reset-dev-user.sh  # Reset user for testing (DB + local state + VS Code)
│   └── reset-user.js      # Node script for DB-only reset
└── .env.example           # Environment template

🚀 Getting Started

Prerequisites

  • Node.js 18+
  • npm or yarn
  • Vercel CLI (npm i -g vercel)
  • Stripe CLI (for webhook testing)

1. Clone and Install

git clone https://github.com/j8d-org/karate-debug-api.git
cd karate-debug-api
npm install

2. Configure Environment

Copy the development environment file for local use:

cp .env.development .env.local

Environment Files:

File Purpose Committed
.env.example Template with placeholders ✅ Yes
.env.development Dev credentials (dev Supabase, dev GitHub OAuth, Stripe test) ❌ No
.env.production Prod credentials (prod Supabase, prod GitHub OAuth, Stripe live) ❌ No
.env.local Local overrides (copy from .env.development) ❌ No

See Environment Variables below for details on each variable.

3. Run Locally

npm run dev

This starts the Vercel development server at http://localhost:3000.

4. Run Tests

npm run test           # Run tests once
npm run test:watch     # Watch mode
npm run test:coverage  # With coverage report

5. Test Stripe Webhooks Locally

In a separate terminal, forward Stripe webhooks to your local server:

stripe listen --forward-to localhost:3000/api/webhooks/stripe

The webhook secret in .env.development is pre-configured for stripe listen. If you get a different secret, update STRIPE_WEBHOOK_SECRET in .env.local.

6. Reset User for Testing

To completely reset a user for fresh trial testing:

./scripts/reset-dev-user.sh [github_username] [vscode_profile]
# Defaults: j8d j8d

This script:

  1. Deletes the user from the dev Supabase database (users, subscriptions, machine_activations)
  2. Deletes the local license backup file (~/.karate-debug-license)
  3. Clears VS Code extension globalState for all profiles
  4. Sends a reload command to VS Code

For shorter trial testing, set TRIAL_MINUTES=5 in .env.local (overrides TRIAL_DAYS).

🌍 Environments

The project uses separate environments for development and production:

Environment Supabase Project GitHub OAuth App Stripe Mode Vercel Scope
Local Dev karate-debug-dev Karate Debug (Dev) Test Development
Preview karate-debug-dev Karate Debug (Dev) Test Preview
Production karate-debug Karate Debug Test* Production

*Switch to Stripe Live mode before public launch.

Vercel Environment Scopes

Scope When Used Where Runs
Production Deploys from main branch Vercel servers
Preview Deploys from PRs/feature branches Vercel servers
Development vercel dev command Local machine

Supabase Projects

Project Reference ID Purpose
karate-debug vcpilqkjckjpoeqjiyxl Production
karate-debug-dev baxumzctorjohrrqshbp Development & Preview

⚙️ Environment Variables

Variable Required Description
SUPABASE_URL ✅ Your Supabase project URL
SUPABASE_SERVICE_ROLE_KEY ✅ Supabase service role key (has admin access)
GITHUB_CLIENT_ID ✅ GitHub OAuth App client ID
GITHUB_CLIENT_SECRET ✅ GitHub OAuth App client secret
STRIPE_SECRET_KEY ✅ Stripe secret key (use sk_test_ for dev)
STRIPE_PRICE_ID ✅ Stripe Price ID for subscription
STRIPE_WEBHOOK_SECRET ✅ Stripe webhook signing secret
JWT_SECRET ✅ Secret for signing license tokens (min 32 chars)
APP_URL ❌ Base URL (defaults to Vercel URL)
SENTRY_DSN ❌ Sentry DSN for error tracking
SENTRY_DEBUG ❌ Set to true to send errors to Sentry in dev
TRIAL_DAYS ❌ Trial period length in days (default: 30)
TRIAL_MINUTES ❌ Trial period in minutes - overrides TRIAL_DAYS if set (for testing)
MAX_MACHINES ❌ Machine limit per user (default: 5)
TOKEN_EXPIRY_HOURS ❌ JWT token expiry in hours (default: 24)
WEBSITE_URL ❌ Website URL for purchase redirects (default: https://www.karatedebug.com)
ADMIN_API_KEY ❌ Admin API key for protected operations (required in prod)

Generating a JWT Secret

openssl rand -hex 32

📡 API Endpoints

Authentication

Endpoint Method Description
/api/auth/github POST Exchange GitHub code for access token
/api/auth/callback GET OAuth callback (redirects to extension)

License Management

Endpoint Method Description
/api/license/validate POST Validate license, return JWT token
/api/license/refresh POST Refresh an expired/expiring token
/api/license/activate POST Activate a machine
/api/license/deactivate POST Deactivate a machine
/api/license/machines GET List user's activated machines

Anonymous Trials

Endpoint Method Description
/api/trial/start POST Start anonymous machine trial (30 days)
/api/trial/status GET Check trial status for a machine

Subscription

Endpoint Method Description
/api/subscription/checkout POST Create Stripe checkout session
/api/subscription/portal POST Create Stripe billing portal session
/api/subscription/result GET Post-checkout result page (success/cancel)

Website Purchase

Endpoint Method Description
/api/purchase/start GET Initiate purchase from website (redirects to GitHub OAuth)
/api/purchase/callback GET Handle OAuth callback, create user, redirect to Stripe

Webhooks & Health

Endpoint Method Description
/api/webhooks/stripe POST Stripe webhook handler
/api/health GET Health check with DB connectivity

Admin (Protected)

Endpoint Method Description
/api/admin/user-reset POST Delete user, subscription, and machines (requires X-Admin-Key header)

🗄️ Database Schema

The API uses Supabase (PostgreSQL) with the following tables:

  • users - GitHub user info, Stripe customer ID
  • subscriptions - Subscription status, trial dates
  • machine_activations - Activated machines per user (max 5)
  • anonymous_trials - Machine-based anonymous trials (pre-signup)
  • webhook_events - Processed Stripe events (idempotency)

See supabase/migrations/ for full schema.

🚢 Deployment

Vercel Deployment

  1. Install Vercel CLI: npm i -g vercel
  2. Link project: vercel link
  3. Set environment variables in Vercel dashboard
  4. Deploy: vercel --prod

Database Migrations

Option 1: Using Supabase CLI (Recommended)

# Link to your project (dev or prod)
supabase link --project-ref <project-ref>

# Push migrations
supabase db push

Option 2: Manual via Dashboard

  1. Go to your Supabase Dashboard
  2. Navigate to SQL Editor
  3. Run each file in supabase/migrations/ in order

Migration Files

File Description
000_initial_schema.sql Users, subscriptions, machines tables + triggers
001_webhook_events.sql Webhook idempotency table
002_rename_machines_table.sql Rename machines to machine_activations
003_enable_rls.sql Enable Row Level Security on tables
004_fix_function_search_path.sql Fix function search path security
005_drop_old_machines_table.sql Drop deprecated machines table
006_anonymous_trials.sql Anonymous machine-based trials table
007_analytics_platform_tracking.sql Platform tracking + analytics views
008_backfill_platform_from_user_agent.sql Backfill platform data
009_fix_analytics_views_security.sql Fix SECURITY INVOKER on analytics views
010_client_version_tracking.sql Client version tracking for extensions/plugins

🧪 Testing

The project uses Vitest for fast, TypeScript-native testing.

Running Tests

npm run test           # Run all tests once
npm run test:watch     # Watch mode (re-runs on file changes)
npm run test:coverage  # Run with coverage report

Test Structure

File Coverage
tests/jwt.test.ts Token signing, verification, expiration
tests/sanitize.test.ts XSS prevention utilities
tests/validation.test.ts Zod schema validation
tests/integration/license-validate.test.ts License validation API flow

Writing Tests

Tests are located in the tests/ directory. Example:

import { describe, it, expect } from 'vitest';
import { escapeHtml } from '../lib/sanitize';

describe('escapeHtml', () => {
    it('should escape HTML special characters', () => {
        expect(escapeHtml('<script>')).toBe('&lt;script&gt;');
    });
});

🔒 Security

  • XSS Protection: All user inputs sanitized before HTML output
  • Webhook Idempotency: Stripe events tracked to prevent duplicate processing
  • Environment Validation: Required variables validated at startup
  • Error Tracking: Sentry integration for production monitoring

📊 Error Tracking (Sentry)

The API uses Sentry for error tracking and monitoring.

Setup

  1. Create a Sentry project at sentry.io
  2. Copy your DSN from Settings → Projects → [Your Project] → Client Keys (DSN)
  3. Add to your environment:
    SENTRY_DSN=https://your-key@your-org.ingest.sentry.io/your-project-id

How It Works

All API endpoints use the withApiHandler wrapper which automatically:

  • Captures unhandled exceptions to Sentry
  • Adds request context (method, URL, timing)
  • Includes a unique requestId for tracing
  • Flushes events before responding

Development vs Production

Environment Behavior
development Errors logged locally only (unless SENTRY_DEBUG=true)
production All errors sent to Sentry

To test Sentry locally, add SENTRY_DEBUG=true to your .env.

Using in Code

import { withApiHandler } from '../lib/api-handler';

// Wrap your handler - errors are automatically captured
export default withApiHandler(async (req, res) => {
    // Your code here
    // Any thrown errors go to Sentry automatically
});

For manual error capture:

import { captureException, captureMessage } from '../lib/sentry';

// Capture an error
captureException(error, { userId, action: 'checkout' });

// Capture a message
captureMessage('User exceeded rate limit', 'warning');

npm Audit Warnings

You may see vulnerabilities reported when running npm audit. These are in the vercel CLI package (esbuild, path-to-regexp, undici) which is a devDependency only and does not affect production deployments.

Package Severity Production Risk
esbuild Moderate ❌ None - dev only
path-to-regexp High ❌ None - dev only
undici Moderate ❌ None - dev only

The suggested fix (npm audit fix --force) would downgrade to an older Vercel CLI version, which is not recommended. These will be resolved when Vercel updates their CLI.

📝 License

Private - All rights reserved.

About

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages