Comprehensive fixes to prevent customer ID mismatches:
1. **Checkout creation now passes customer_id** (lines 13669, 13064, 13503):
- All checkouts (subscription, topup, PAYG) now call ensureDodoCustomer() first
- Pass existing customer_id to checkout body to prevent Dodo from creating duplicates
- Added customerId to metadata for tracking
2. **Subscription confirmation validates customer consistency** (line 13843):
- Logs warning when checkout returns different customer_id than stored
- Tracks which customer_id was used in checkout metadata
- Prevents silent customer ID overwrites
3. **ensureDodoCustomer handles multiple customers per email** (line 6774):
- Logs warning when multiple customers found for same email
- Checks ALL customers for active subscriptions
- Selects customer with active subscriptions if multiple exist
- Returns first customer only if no active subscriptions found
4. **Added missing return statements** (lines 12417, 12448):
- Prevents double response errors after successful plan changes
This ensures that:
- New subscriptions use existing customers instead of creating duplicates
- Plan changes work correctly even with multiple subscriptions
- Customer ID mismatches are detected and logged
- The correct customer (one with active subscriptions) is always used
- Added return statement after successful paid-to-free cancellation (line 12417)
- Added return statement after successful paid-to-paid plan change (line 12448)
- Prevents 'Cannot write headers after they are sent' error
- Each plan change now returns immediately with the updated account data
- Removed hardcoded subscription ID from code
- Rely on API queries to find subscriptions by customer or through fallback search
- Added proper logging to diagnose customer/subscription mismatches
- Add direct API call to fetch subscription sub_0NYKZRvba3g5KJfp8R5jp
- Log customer ID comparison to detect mismatches
- Update user record if subscription belongs to different customer
- This will help identify if duplicate customers exist in Dodo
- Query ALL subscriptions for customer without status filter first
- This handles customers with multiple subscriptions across different statuses
- Returns first active subscription found, or most recent if none active
- Added detailed logging to show all subscription IDs and statuses found
- Fallback to check individual statuses including cancelled/expired
Add comprehensive DEBUG logs to trace through:
- Customer lookup by email (request and response details)
- Subscription lookup by customer ID (for each status)
- Entry point when plan change is initiated
This will help identify exactly where the lookup is failing.
- Modified ensureDodoCustomer() to query existing customers by email before creating new ones
- This prevents duplicate customer records when dodoCustomerId is missing from database
- Added logging for both found existing customers and new customer creation
- Updated subscription lookup to check multiple statuses (active, pending, on_hold)
- Should resolve paid-to-paid and paid-to-free plan change issues for users missing subscription IDs
- Fix getBaseUrl() ReferenceError by changing to resolveBaseUrl(req) for free-to-paid upgrades
- Add subscription lookup by customer email when dodoSubscriptionId is missing
- Log critical issues when paid users have no subscription ID in database or Dodo
- Return clear error message to contact support when subscription cannot be found
- Prevent silent failures in plan changes from settings page
- Moved sticky positioning from mobile-only to global CSS for .top-left-actions
- Buttons now stay fixed at top above content on all screen sizes
- Includes various other app updates (version management, server improvements)
- Add 'cohere' to DEFAULT_PROVIDERS and PLANNING_PROVIDERS arrays in admin.js
- Add Cohere option to provider limits dropdown in admin.html
- Add 'cohere' to DEFAULT_PROVIDER_SEEDS, PLANNING_PROVIDERS, and KNOWN_USAGE_PROVIDERS in server.js
Cohere was already integrated in the opencode backend (SDK installed, provider registered, icons defined). These changes make it available in the admin panel for build message configuration.
- Parse model names like 'chutes/deepseek-ai/DeepSeek-V3.2-TEE'
- Extract provider prefix before '/' to detect chutes, cerebras, etc.
- This fixes provider detection when admin panel sets wrong provider
- Support providers as array of strings: [opencode, chutes]
- Support providers as array of objects: [{provider: opencode}]
- This fixes provider detection for Chutes and other providers
- Move loadAdminModelStore() before loadState() in bootstrap()
- This ensures adminModels is available when ensureOpencodeConfig is called
- Fixes issue where Chutes provider was not being configured
- Add check to load adminModels if not already loaded
- Add error handling for models.dev fetch failures
- Log provider source (models.dev vs built-in) for debugging
- Add fetchModelsDevProviderModels() function with 1-hour caching
- Update ensureOpencodeConfig() to dynamically load all models for configured providers
- Support Chutes, Cerebras, Groq, Google, and Nvidia providers
- Only fetch models for providers actually used in adminModels
- Cache models.dev data to reduce API calls and improve performance
This allows any model from models.dev to work when added in the admin panel,
instead of requiring hardcoded model definitions.
When models from providers like Chutes or Cerebras were added via the admin panel,
they didn't work in the builder page because the opencode.json config file only
included the Ollama provider configuration.
This fix adds Chutes and Cerebras provider configurations to the opencode.json
file when their respective API keys are available in environment variables
(CHUTES_API_KEY and CEREBRAS_API_KEY).
Fixes the issue where chutes/deepseek-ai/DeepSeek-V3.2-TEE and similar models
would fail to load from the builder page.
- Add multiple fallback global variable names for Editor.js plugins
- Add debug logging to track plugin availability
- Add error handling for editor initialization
- Ensure at least paragraph tool is available before initializing
- Fix ReferenceError: List is not defined when opening post modal
- Update data model to include status, adminReply, and updatedAt fields
- Hide user emails from public API responses for privacy
- Add admin-only endpoints: list, reply, update status, delete
- Create admin-feature-requests.html with full management UI
- Add status badges and admin replies to public feature requests page
- Add Feature Requests link to all admin page sidebars
Admin capabilities:
- View all feature requests with author emails (admin only)
- Reply to feature requests with admin responses visible to public
- Update status: pending, planned, in-progress, completed, declined
- Delete feature requests
- Filter and sort by status, votes, date
- Changed default display from flex to none to prevent modal from appearing at bottom of page
- Modal now properly hidden until View All button is clicked
Add dual-source blog system with Editor.js integration:
- Blog storage supporting repo-based (JSON) and database sources
- Admin panel with rich text editor using Editor.js
- Public news page with infinite scroll
- Individual blog post viewer page
- Categories management in admin
- Image upload functionality
- 4 SEO blog posts about WordPress with PluginCompass promotion
- 3 News blog posts about Plugin Compass
- API endpoints for CRUD operations
- Security and validation for admin operations
Closes blog feature request
- Changed INVOICES_PER_PAGE from 10 to 5
- Modal properly opens from Invoices section when clicking 'View All'
- Supports pagination with multiple pages in the popup
- Modified handleUndoMessage in server.js to remove the undone message from session history
- Added persistState() call to save the updated session state after undo
- Message is now removed from UI when undo is completed
- Works for opencode/build messages that are completed, errored, or cancelled