5.3 KiB
DashCaddy License Server Implementation Plan
Goal
Connect live Stripe billing to DashCaddy Premium licensing without inventing a second license model.
Existing DashCaddy integration points
The main DashCaddy app already has the core license hooks:
dashcaddy-api/license-keygen.jsdashcaddy-api/license-manager.jsdashcaddy-api/routes/license.js
The app already supports:
LICENSE_SERVER_URL- online validation at
/api/license/validate - online deactivation at
/api/license/deactivate - offline HMAC validation fallback
- premium feature checks for:
ssorecipesswarm
Locked product decisions
Free tier
Everything works without a license except premium-gated features. There is no Premium free trial. Premium is simply locked until a paid subscription activates a license.
Premium tier
Paid subscriptions unlock:
ssorecipesswarm
Stripe plans
- 1 month — $25
- 3 months — $50
- 6 months — $65
- 12 months — $99
Subscription policy
- recurring subscriptions
- 7-day grace period on failed payment
- cancel at period end
- one active machine at a time
- transfer requires deactivation from previous machine
- no public lifetime plan
Recommended system shape
Website (dashcaddy.net)
Responsibilities:
- show Premium pricing cards
- create Stripe Checkout sessions through the license server
- redirect to Stripe Checkout
- return users to success/cancel pages
License server (dashcaddy-license-server)
Responsibilities:
- create Stripe Checkout sessions
- ingest Stripe webhooks
- maintain customer/license/subscription state
- issue and renew DashCaddy-compatible licenses
- validate license activations
- enforce one-active-machine policy
- accept deactivation requests
- provide admin support tooling later
Stripe
Source of truth for:
- customers
- subscriptions
- invoices
- payment state
- cancellation state
Proposed API surface
Public endpoints for website
POST /api/checkout/sessionGET /api/public/plans
DashCaddy app endpoints
POST /api/license/validatePOST /api/license/deactivate
Stripe webhook endpoint
POST /api/stripe/webhook
Future admin endpoints
GET /api/admin/licenses/:codePOST /api/admin/licenses/:code/overridePOST /api/admin/licenses/:code/reset-activation
Data model
customers
- id
- stripe_customer_id
- created_at
- updated_at
subscriptions
- id
- customer_id
- stripe_subscription_id
- stripe_price_id
- plan_code
- status
- current_period_start
- current_period_end
- cancel_at_period_end
- grace_until
- created_at
- updated_at
licenses
- id
- customer_id
- subscription_id
- license_code
- tier
- features_json
- status
- expires_at
- last_validated_at
- created_at
- updated_at
activations
- id
- license_id
- machine_fingerprint
- hostname
- platform
- arch
- cpu
- mac_hash
- activated_at
- deactivated_at
- status
stripe_events
- id
- stripe_event_id
- type
- processed_at
- payload_json
Stripe plan mapping
One Premium product, four recurring prices, with no trial period:
premium_monthlypremium_3monthpremium_6monthpremium_12month
All plans unlock the same Premium features. Only the billing interval differs.
Activation logic
Validation request from DashCaddy
Expected inputs:
- license code
- machine fingerprint
- machine metadata
Validation rules:
- license exists and is active
- subscription is active or in grace period
- license not expired
- no active activation on a different machine
- if first activation, bind to this machine
- if same machine, refresh validation
- if different machine while old activation still active, reject
Deactivation request
- find active activation for license
- mark activation deactivated
- free license for reuse on another machine
Renewal logic
On successful Stripe renewal:
- keep same customer/license relationship
- extend effective entitlement through subscription period
- license remains active continuously
On payment failure:
- mark subscription past_due-like state
- set
grace_until = current time + 7 days
On cancellation:
- keep access until current_period_end
- then expire
Website integration plan
The dashcaddy.net marketing site should be updated to:
- add Premium pricing section buttons
- each button POSTs to
/api/checkout/sessionwith a plan code - redirect to returned Stripe Checkout URL
- success page explains license delivery/activation flow
- cancellation page returns user to pricing
Deployment target
Deploy dashcaddy-license-server on Contabo.
Initial env expected:
STRIPE_SECRET_KEYSTRIPE_WEBHOOK_SECRETSTRIPE_PUBLISHABLE_KEYAPP_BASE_URLDASHCADDY_WEBSITE_URLDATABASE_URLLICENSE_SIGNING_SECRETor reused DashCaddy-compatible secret path
Immediate next build steps
- Scaffold Node service for
dashcaddy-license-server - Add Stripe SDK, Express, and SQLite/Postgres adapter layer
- Build
/api/public/plans - Build
/api/checkout/session - Build
/api/stripe/webhook - Port/reuse DashCaddy-compatible license generation/validation helpers
- Build
/api/license/validate - Build
/api/license/deactivate - Wire pricing CTA buttons into
dashcaddy.net - Test with Stripe test mode flow before flipping deployed env to live operation