- Add OAuthCredential model for storing Google/Microsoft OAuth tokens
- Add email provider auto-detection endpoint (Gmail, Outlook, Yahoo, etc.)
- Add EmailConfigWizard frontend component with step-by-step setup
- Add OAuth flow endpoints for Google and Microsoft XOAUTH2
- Update production settings to make AWS, Sentry, Mailgun optional
- Update Traefik config for wildcard subdomain routing
- Add logo resize utility script
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add SMTP fields to TicketEmailSettings model (host, port, TLS/SSL, credentials, from email/name)
- Update serializers with SMTP fields and is_smtp_configured flag
- Add TicketEmailTestSmtpView for testing SMTP connections
- Update frontend API types and hooks for SMTP settings
- Add collapsible IMAP and SMTP configuration sections with "Configured" badges
- Fix TypeScript errors in mockData.ts (missing required fields, type mismatches)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add GlobalEventPlugin model for auto-attaching plugins to all events
- Create signals for auto-attachment on new events and rescheduling
- Add API endpoints for global event plugins (CRUD, toggle, reapply)
- Update CreateTaskModal with "Scheduled Task" vs "Event Automation" choice
- Add option to apply to all events or future events only
- Display event automations in Tasks page alongside scheduled tasks
- Add EditEventAutomationModal for editing trigger and timing
- Handle event reschedule - update Celery task timing on time/duration changes
- Add Marketplace to Plugins menu in sidebar
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
## Backend Changes:
- Enhanced PluginTemplate.save() to auto-parse template variables from plugin code
- Updated PluginInstallationSerializer to expose template metadata (description, category, version, author, logo, template_variables)
- Fixed template variable parser to handle nested {{ }} braces in default values
- Added brace-counting algorithm to properly extract variables with insertion codes
- Fixed explicit type parameter detection (textarea, text, email, etc.)
- Made scheduled_task optional on PluginInstallation model
- Added EventPlugin through model for event-plugin relationships
- Added Event.execute_plugins() method for plugin automation
## Frontend Changes:
- Created Tasks.tsx page for managing scheduled tasks
- Enhanced MyPlugins page with clickable plugin cards
- Added edit configuration modal with dynamic form generation
- Implemented escape sequence handling (convert \n, \', etc. for display)
- Added plugin logos to My Plugins page
- Updated type definitions for PluginInstallation interface
- Added insertion code documentation to Plugin Docs
## Plugin System:
- All platform plugins now have editable email templates with textarea support
- Template variables properly parsed with full default values
- Insertion codes ({{CUSTOMER_NAME}}, {{BUSINESS_NAME}}, etc.) documented
- Plugin logos displayed in marketplace and My Plugins
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changes:
1. Changed "Install" button to "View" button with Eye icon
- Removed separate "Details" button
- Single "View" button now opens the details modal
2. Fixed author mapping to use author_name from API
3. Fixed rating field to use rating_average from API
4. Set isVerified based on visibility === 'PLATFORM'
The modal now correctly displays:
- Plugin name with verified badge for platform plugins
- Author name (e.g., "Smooth Schedule")
- Version number
- Full description with formatting
- Category, ratings, and install count
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The description field is now included in marketplace listing responses,
allowing the frontend to display full plugin descriptions with formatting,
bullet points, and detailed benefits.
All 6 platform plugins now return complete information:
- Name, author (Smooth Schedule), version (1.0.0)
- Short description (one-line summary)
- Full description (multi-paragraph with bullets)
- Category, ratings, install count
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changes:
1. Added version field to PluginTemplate model (default: 1.0.0)
2. Updated platform plugins with detailed descriptions
3. Changed author_name from "SmoothSchedule Platform" to "Smooth Schedule"
4. Enhanced seed_platform_plugins command with comprehensive descriptions
Plugin descriptions now include:
- Detailed explanations of functionality
- Benefits and use cases
- Key features in bullet points
All 6 platform plugins now have:
- Version: 1.0.0
- Author: Smooth Schedule
- Rich, marketing-friendly descriptions
Migration: 0016_plugintemplate_version
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changes:
1. Updated PluginTemplateViewSet.get_queryset() to include PLATFORM
visibility plugins in marketplace view alongside approved PUBLIC plugins
2. Fixed PluginTemplateListSerializer read_only_fields from string '__all__'
to proper list reference
Platform plugins are now visible in the marketplace API:
- 6 platform-created plugins seeded via seed_platform_plugins command
- Categories: EMAIL, REPORTS, CUSTOMER, BOOKING
- All marked as visibility=PLATFORM, is_approved=True
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Users can access the marketplace via the "Browse Marketplace" button
on the My Plugins page, so the redundant sidebar link has been removed.
The Plugins dropdown now contains:
- My Plugins
- Plugin Docs
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit completes the plugin system UI by adding two key pages:
1. Plugin Marketplace (/plugins/marketplace):
- Browse and search platform-provided plugins
- Filter by category (EMAIL, REPORTS, CUSTOMER, BOOKING, etc.)
- View plugin details including ratings, install count, description
- Install plugins with one click
- Modal view for detailed plugin information
2. My Plugins (/plugins/my-plugins):
- View all installed plugins
- Manage plugin activation status
- Update plugins when new versions available
- Rate and review installed plugins
- Uninstall plugins with confirmation
- Links to create custom plugins and browse marketplace
Additional changes:
- Added plugin routes to App.tsx with owner/manager access control
- Updated HelpPluginDocs.tsx with navigation callout boxes
- Added TypeScript interfaces for PluginTemplate and PluginInstallation
- Both pages feature full dark mode support
- Professional UI with Tailwind CSS styling
- React Query integration for data fetching
The pages are accessible from the Plugins dropdown menu in the sidebar.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Added Plugins collapsible menu with 3 items:
- Plugin Marketplace (/plugins/marketplace)
- My Plugins (/plugins/my-plugins)
- Plugin Docs (/help/plugins)
- Moved Plugin Docs from Help dropdown to Plugins dropdown
- Added Plug, ShoppingBag, Package icons from lucide-react
- Added translations for plugin navigation items
- Auto-opens dropdown when on /plugins/* routes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Backend Features:
- Created PluginTemplate and PluginInstallation models
- Built complete REST API with marketplace, my plugins, install/uninstall endpoints
- Platform plugins supported (PLATFORM visibility, no whitelisting required)
- Template variable extraction and compilation
- Plugin approval workflow for marketplace publishing
- Rating and review system
- Update detection and version management
- Install count tracking
API Endpoints:
- GET /api/plugin-templates/ - Browse marketplace (view=marketplace/my_plugins/platform)
- POST /api/plugin-templates/ - Create new plugin
- POST /api/plugin-templates/{id}/install/ - Install plugin as ScheduledTask
- POST /api/plugin-templates/{id}/publish/ - Publish to marketplace
- POST /api/plugin-templates/{id}/approve/ - Approve for marketplace (admins)
- POST /api/plugin-installations/{id}/rate/ - Rate and review
- POST /api/plugin-installations/{id}/update_to_latest/ - Update plugin
- DELETE /api/plugin-installations/{id}/ - Uninstall plugin
Platform Plugins:
- Created seed_platform_plugins management command
- 6 starter plugins ready: daily summary, no-show tracker, birthdays, revenue reports, reminders, re-engagement
- Platform plugins bypass whitelist validation
- Pre-approved and available to all businesses
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implemented static code analysis to detect and validate HTTP calls in plugins
before they are uploaded or approved for the marketplace.
**New Functions:**
1. **analyze_plugin_http_calls(script):**
- Parses plugin code using Python AST
- Detects all api.http_* method calls (GET, POST, PUT, PATCH, DELETE)
- Extracts URL from first argument if it's a string literal
- Handles dynamic URLs (f-strings, variables) with appropriate warnings
- Returns list of HTTP calls with method, URL, and line number
2. **validate_plugin_whitelist(script, scheduled_task):**
- Analyzes plugin code for HTTP calls
- Validates each detected URL against WhitelistedURL model
- Checks both platform-wide and plugin-specific whitelists
- Returns validation results with errors, warnings, and detected calls
- Provides clear error messages with line numbers
**Validation Logic:**
- **Static URLs** (string literals): Validated against whitelist, error if not found
- **Dynamic URLs** (f-strings, variables): Warning issued, runtime validation required
- **Syntax Errors**: Caught and reported as validation errors
- **Line Numbers**: All errors/warnings include line number for debugging
**Use Cases:**
1. Pre-upload validation: Check plugin before saving to database
2. Approval workflow: Platform staff can see which URLs need whitelisting
3. Marketplace submission: Reject plugins with non-whitelisted URLs
4. Security audit: Analyze existing plugins for HTTP call patterns
**Error Messages:**
- Clear, actionable messages with line numbers
- Direct users to pluginaccess@smoothschedule.com for whitelisting
- Warns about dynamic URLs that can't be statically validated
This enables proactive security enforcement before plugins are executed,
preventing runtime failures and improving user experience.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updated all references to "Platform" in the licensing documentation to use
"SmoothSchedule" for better branding consistency:
- Changed "Platform Rights" to "SmoothSchedule Rights"
- Changed "Platform Service Rights" to "SmoothSchedule Service Rights"
- Changed "Platform Use" table header to "SmoothSchedule Use"
- Updated all inline references from "Platform" to "SmoothSchedule"
This makes the licensing terms more specific and branded while maintaining
the same legal structure and protections.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added new "Plugin Licensing" section to plugin documentation that covers:
**SmoothSchedule Community Plugin License (SCPL):**
- Custom license for marketplace plugins
- Grants platform rights to use, execute, host, and distribute code
- Grants users rights to install, use, and modify for their business
- Requires attribution to original author
- Allows users to adapt code but not republish without permission
- Permits authors to unpublish anytime (existing installs continue)
- Authors retain copyright and can license elsewhere
- Similar to MIT License + Platform Service Rights
**Private vs. Marketplace Plugins:**
- Private plugins: Full ownership, any license (or none), private to business
- Marketplace plugins: Must use SCPL, visible to all users, author credited
- Both types: Platform can execute code to provide automation service
**Key Features:**
- Comparison table showing differences between private and marketplace plugins
- Code verification and security requirements documented
- Decision guide for when to publish vs. keep private
- Important notices about warranties, compliance, and data privacy
- Platform service rights clearly explained
**Legal Protections:**
- Platform has rights to execute user code for service delivery
- No warranty disclaimer (plugins "as-is")
- User compliance responsibility for laws and regulations
- Data privacy obligations (GDPR, CCPA compliance)
The SCPL is designed to be marketplace-friendly while protecting both
the platform and plugin authors, similar to how npm/PyPI handle packages
but with added platform service rights for SaaS execution.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Backend Changes:
- Extended SafeScriptAPI to support all HTTP methods (GET, POST, PUT, PATCH, DELETE)
- Created WhitelistedURL model for per-plugin and platform-wide URL whitelisting
- Added _validate_url() method with SSRF protection and private IP blocking
- Updated SafeScriptAPI to accept scheduled_task parameter for whitelist checking
- All HTTP methods now validate against whitelist before making requests
WhitelistedURL Model:
- Supports two scopes: PLATFORM (all plugins) and PLUGIN (specific plugin)
- Stores URL patterns with wildcard support (e.g., https://api.example.com/*)
- Tracks allowed HTTP methods per URL
- Includes approval workflow (approved_by, approved_at)
- Stores original plugin code for verification
- Domain-based indexing for fast lookup
- Database constraint ensures platform-wide entries have no plugin assigned
Security Features:
- SSRF prevention: blocks localhost, loopback, and private IP ranges
- Per-plugin whitelist: each ScheduledTask can only access its whitelisted URLs
- Platform-wide whitelist: approved URLs accessible by all plugins
- HTTP method validation: URLs must explicitly allow each method
- URL pattern matching with wildcard support
Related Models:
- WhitelistedURL.scheduled_task -> ScheduledTask (plugin that owns the whitelist)
- WhitelistedURL.approved_by -> User (platform user who approved the URL)
Migration: schedule/migrations/0014_whitelistedurl.py
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added complete plugin documentation with visual mockups and expanded template
variable system with CONTEXT, DATE helpers, and default values.
Backend Changes:
- Extended template_parser.py to support all new template types
- Added PROMPT with default values: {{PROMPT:var|desc|default}}
- Added CONTEXT variables: {{CONTEXT:business_name}}, {{CONTEXT:owner_email}}
- Added DATE helpers: {{DATE:today}}, {{DATE:+7d}}, {{DATE:monday}}
- Implemented date expression evaluation for relative dates
- Updated compile_template to handle all template types
- Added context parameter for business data auto-fill
Frontend Changes:
- Created comprehensive HelpPluginDocs.tsx with Stripe-style API docs
- Added visual mockup of plugin configuration form
- Documented all template types with examples and benefits
- Added Command Reference section with allowed/blocked Python commands
- Documented all HTTP methods (GET, POST, PUT, PATCH, DELETE)
- Added URL whitelisting requirements and approval process
- Created Platform Staff management page with edit modal
- Added can_approve_plugins and can_whitelist_urls permissions
Platform Staff Features:
- List all platform_manager and platform_support users
- Edit user details with role-based permissions
- Superusers can edit anyone
- Platform managers can only edit platform_support users
- Permission cascade: users can only grant permissions they have
- Real-time updates via React Query cache invalidation
Documentation Highlights:
- 4 template types: PROMPT, CONTEXT, DATE, and automatic validation
- Visual form mockup showing exactly what users see
- All allowed control flow (if/elif/else, for, while, try/except, etc.)
- All allowed built-in functions (len, range, min, max, etc.)
- All blocked operations (import, exec, eval, class/function defs)
- Complete HTTP API reference with examples
- URL whitelisting process: contact pluginaccess@smoothschedule.com🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit adds major features for sandbox isolation, public API access, and platform support ticketing.
## Sandbox Mode
- Add sandbox mode toggle for businesses to test features without affecting live data
- Implement schema-based isolation for tenant data (appointments, resources, services)
- Add is_sandbox field filtering for shared models (customers, staff, tickets)
- Create sandbox middleware to detect and set sandbox mode from cookies
- Add sandbox context and hooks for React frontend
- Display sandbox banner when in test mode
- Auto-reload page when switching between live/test modes
- Prevent platform support tickets from being created in sandbox mode
## Public API System
- Full REST API for external integrations with businesses
- API token management with sandbox/live token separation
- Test tokens (ss_test_*) show full plaintext for easy testing
- Live tokens (ss_live_*) are hashed and secure
- Security validation prevents live token plaintext storage
- Comprehensive test suite for token security
- Rate limiting and throttling per token
- Webhook support for real-time event notifications
- Scoped permissions system (read/write per resource type)
- API documentation page with interactive examples
- Token revocation with confirmation modal
## Platform Support
- Dedicated support page for businesses to contact SmoothSchedule
- View all platform support tickets in one place
- Create new support tickets with simplified interface
- Reply to existing tickets with conversation history
- Platform tickets have no admin controls (no priority/category/assignee/status)
- Internal notes hidden for platform tickets (business can't see them)
- Quick help section with links to guides and API docs
- Sandbox warning prevents ticket creation in test mode
- Business ticketing retains full admin controls (priority, assignment, internal notes)
## UI/UX Improvements
- Add notification dropdown with real-time updates
- Staff permissions UI for ticket access control
- Help dropdown in sidebar with Platform Guide, Ticketing Help, API Docs, and Support
- Update sidebar "Contact Support" to "Support" with message icon
- Fix navigation links to use React Router instead of anchor tags
- Remove unused language translations (Japanese, Portuguese, Chinese)
## Technical Details
- Sandbox middleware sets request.sandbox_mode from cookies
- ViewSets filter data by is_sandbox field
- API authentication via custom token auth class
- WebSocket support for real-time ticket updates
- Migration for sandbox fields on User, Tenant, and Ticket models
- Comprehensive documentation in SANDBOX_MODE_IMPLEMENTATION.md
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Assignee Dropdown:
- Fix useUsers hook to fetch from /api/staff/ endpoint
- Add useStaffForAssignment hook for formatted dropdown data
- Update TicketModal to use new hook for assignee selection
Staff Permissions UI:
- Add "Can access support tickets" permission to invite modal for both managers and staff
- Add permission to edit modal for both managers and staff
- Managers default to having ticket access enabled
- Staff default to having ticket access disabled (must be explicitly granted)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
WebSocket Updates:
- Create useTicketWebSocket hook for real-time ticket list updates
- Hook invalidates React Query cache when tickets are created/updated
- Shows toast notifications for new tickets and comments
- Auto-reconnect with exponential backoff
Staff Permissions:
- Add can_access_tickets() method to User model
- Owners and managers always have ticket access
- Staff members need explicit can_access_tickets permission
- Update Sidebar to conditionally show Tickets menu based on permission
- Add can_access_tickets to API user response
Backend Updates:
- Update ticket signals to broadcast updates to all relevant users
- Check ticket access permission in views
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Platform admins now only see PLATFORM tickets from business users
(tickets where business owners/staff ask for platform help)
- Business owners/managers see CUSTOMER, STAFF_REQUEST, INTERNAL tickets
for their tenant, plus their own PLATFORM tickets to track support requests
- Removed test platform tickets that were incorrectly created by platform staff
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add availability check for notifications app to avoid database errors
when the notifications table doesn't exist.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add ticket categories (billing, technical, feature_request, etc.) with type-specific options
- Add TicketTemplate and CannedResponse models for quick ticket creation
- Implement SLA tracking with due_at and first_response_at fields
- Add is_platform_admin and is_customer helper functions to fix permission checks
- Register models in Django admin with filters and fieldsets
- Enhance signals with error handling for WebSocket notifications
- Fix frontend API URLs for templates and canned responses
- Update PlatformSupport page to use real ticketing API
- Add comprehensive i18n translations for all ticket fields
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Major features:
- Add drag-and-drop photo gallery to Service create/edit modals
- Add Resource Types management section to Settings (CRUD for custom types)
- Add edit icon consistency to Resources table (pencil icon in actions)
- Improve Services page with drag-to-reorder and customer preview mockup
Backend changes:
- Add photos JSONField to Service model with migration
- Add ResourceType model with category (STAFF/OTHER), description fields
- Add ResourceTypeViewSet with CRUD operations
- Add service reorder endpoint for display order
Frontend changes:
- Services page: two-column layout, drag-reorder, photo upload
- Settings page: Resource Types tab with full CRUD modal
- Resources page: Edit icon in actions column instead of row click
- Sidebar: Payments link visibility based on role and paymentsEnabled
- Update types.ts with Service.photos and ResourceTypeDefinition
Note: Removed photos from ResourceType (kept only for Service)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fix backend type comparison in AvailabilityService (int vs string)
- Add durationMinutes to month overlay drop to fix end_time calculation
- Add live preview of dragged appointment in overlay with lane splitting
- Implement horizontal auto-scroll when dragging to overlay edges
- Add 1-second delay before overlay appears for easier date navigation
- Remove redundant drop zone highlight (preview shows position)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Backend:
- Add /api/customers/ endpoint (CustomerViewSet, CustomerSerializer)
- Add /api/services/ endpoint with Service model and migrations
- Add Resource.type field (STAFF, ROOM, EQUIPMENT) with migration
- Fix EventSerializer to return resource_id, customer_id, service_id
- Add date range filtering to EventViewSet (start_date, end_date params)
- Add create_demo_appointments management command
- Set default brand colors in business API
Frontend:
- Add calendar grid view for month mode in OwnerScheduler
- Fix sidebar navigation active link contrast (bg-white/10)
- Add default primaryColor/secondaryColor fallbacks in useBusiness
- Disable WebSocket (backend not implemented) to stop reconnect loop
- Fix Resource.type.toLowerCase() error by adding type to backend
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Convert CSP settings to lists
- Add 'unsafe-eval' and 'unsafe-inline' to script-src
- Add 'blob:' to default-src as fallback
- Update connect-src to include Stripe domains
- Add CSP settings explicitly to local.py to ensure they are active
- Implement logout API endpoint (view and url) to fix 404
- Add min-height to chart container in PlatformDashboard to fix recharts error
- Update API to return lowercase roles for frontend compatibility
- Fix Tenant owner lookup in platform admin serializer
- Update frontend App.tsx to match tarball implementation
- Prioritize vite.config.js for HMR support
- Include pending CSP and CORS configuration updates
This commit includes:
- Django backend with multi-tenancy (django-tenants)
- React + TypeScript frontend with Vite
- Platform administration API with role-based access control
- Authentication system with token-based auth
- Quick login dev tools for testing different user roles
- CORS and CSRF configuration for local development
- Docker development environment setup
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>