From 22fde0fd5b8be4b04c85e9481e3144320b1c6f90 Mon Sep 17 00:00:00 2001
From: larryro <371767072@qq.com>
Date: Thu, 11 Dec 2025 09:25:16 +0800
Subject: [PATCH 1/2] docs: remove outdated documentation files
Remove 33 documentation files that are no longer needed:
- Admin setup and deployment guides
- Workflow-related documentation (architecture, patterns, types)
- Integration guides (OneDrive, email providers, Shopify/Circuly)
- API documentation
- Internal design documents
These docs have become stale and are being consolidated or deprecated.
---
docs/admin_setup.md | 164 ----
docs/ai-workflow-assistant.md | 606 --------------
docs/api/create-conversation-message.md | 416 ---------
docs/convex-local-setup.md | 149 ----
docs/convex-self-hosted-setup.md | 203 -----
docs/deployment-modes.md | 164 ----
docs/email-api-sending.md | 289 -------
docs/email-providers.md | 659 ---------------
docs/integration-health-checks.md | 199 -----
docs/integrations-schema.md | 315 -------
docs/management-dashboard-user-guide.md | 289 -------
docs/onedrive-background-sync.md | 302 -------
docs/onedrive-debugging-guide.md | 203 -----
docs/onedrive-integration-guide.md | 565 -------------
docs/onedrive-parent-directory-tracking.md | 106 ---
docs/row-level-security-guide.md | 651 ---------------
docs/tale-db-deployment.md | 574 -------------
docs/tale-rag-deployment.md | 348 --------
docs/tone-of-voice-implementation.md | 278 ------
docs/url-configuration.md | 231 -----
docs/workflows/REFACTORING_SUMMARY.md | 232 -----
docs/workflows/architecture.md | 755 -----------------
docs/workflows/auto-processing-pattern.md | 355 --------
docs/workflows/data-spec.md | 516 ------------
docs/workflows/database-operations.md | 179 ----
docs/workflows/developer-guide.md | 680 ---------------
docs/workflows/entity-finder-prompt-design.md | 279 -------
.../find-unprocessed-entities-tool.md | 331 --------
docs/workflows/manual-configuration.md | 224 -----
docs/workflows/version-management.md | 44 -
docs/workflows/workflow-patterns-guide.md | 790 ------------------
docs/workflows/workflow-types.md | 385 ---------
.../platform/convex/lib/variables/DESIGN.md | 528 ------------
33 files changed, 12009 deletions(-)
delete mode 100644 docs/admin_setup.md
delete mode 100644 docs/ai-workflow-assistant.md
delete mode 100644 docs/api/create-conversation-message.md
delete mode 100644 docs/convex-local-setup.md
delete mode 100644 docs/convex-self-hosted-setup.md
delete mode 100644 docs/deployment-modes.md
delete mode 100644 docs/email-api-sending.md
delete mode 100644 docs/email-providers.md
delete mode 100644 docs/integration-health-checks.md
delete mode 100644 docs/integrations-schema.md
delete mode 100644 docs/management-dashboard-user-guide.md
delete mode 100644 docs/onedrive-background-sync.md
delete mode 100644 docs/onedrive-debugging-guide.md
delete mode 100644 docs/onedrive-integration-guide.md
delete mode 100644 docs/onedrive-parent-directory-tracking.md
delete mode 100644 docs/row-level-security-guide.md
delete mode 100644 docs/tale-db-deployment.md
delete mode 100644 docs/tale-rag-deployment.md
delete mode 100644 docs/tone-of-voice-implementation.md
delete mode 100644 docs/url-configuration.md
delete mode 100644 docs/workflows/REFACTORING_SUMMARY.md
delete mode 100644 docs/workflows/architecture.md
delete mode 100644 docs/workflows/auto-processing-pattern.md
delete mode 100644 docs/workflows/data-spec.md
delete mode 100644 docs/workflows/database-operations.md
delete mode 100644 docs/workflows/developer-guide.md
delete mode 100644 docs/workflows/entity-finder-prompt-design.md
delete mode 100644 docs/workflows/find-unprocessed-entities-tool.md
delete mode 100644 docs/workflows/manual-configuration.md
delete mode 100644 docs/workflows/version-management.md
delete mode 100644 docs/workflows/workflow-patterns-guide.md
delete mode 100644 docs/workflows/workflow-types.md
delete mode 100644 services/platform/convex/lib/variables/DESIGN.md
diff --git a/docs/admin_setup.md b/docs/admin_setup.md
deleted file mode 100644
index bb2de9630c..0000000000
--- a/docs/admin_setup.md
+++ /dev/null
@@ -1,164 +0,0 @@
-# Admin User Setup Guide
-
-This guide explains how to set up the initial admin user for the Lanserhof application.
-
-## 🚀 Quick Start (Development)
-
-For local development, the system automatically creates a default admin user:
-
-- **Email**: `admin@lanserhof.local`
-- **Password**: `admin123`
-- **Role**: `Admin`
-
-⚠️ **IMPORTANT**: Change this password after first login!
-
-## 🔐 Production Setup
-
-For production environments, you should create a secure admin user:
-
-### Step 1: Generate Secure Password
-
-```bash
-# Generate a random secure password and hash
-pnpm admin:generate-password
-
-# Or use your own password
-pnpm admin:generate-password "YourSecurePassword123!"
-```
-
-This will output:
-
-- The password (store this securely!)
-- The bcrypt hash
-- Environment variables to set
-
-### Step 2: Set Environment Variables
-
-Add these to your production environment:
-
-```bash
-ADMIN_EMAIL="admin@yourdomain.com"
-ADMIN_NAME="System Administrator"
-ADMIN_PASSWORD_HASH="$2b$12$..."
-```
-
-### Step 3: Deploy and Reset Database
-
-When you deploy with these environment variables, the seed script will create the admin user with your secure credentials.
-
-## 🛠️ Manual Admin User Creation
-
-If you need to manually create an admin user, you can use SQL:
-
-```sql
--- Generate a password hash first using the script
--- Then insert the user
-INSERT INTO next_auth.users (
- id,
- name,
- email,
- "emailVerified",
- password_hash,
- role,
- created_at,
- updated_at
-) VALUES (
- gen_random_uuid(),
- 'Your Name',
- 'your-email@domain.com',
- NOW(),
- 'your-bcrypt-hash-here',
- 'Admin',
- NOW(),
- NOW()
-);
-```
-
-## 🔄 Changing Admin Password
-
-### Method 1: Through the Application (Recommended)
-
-1. Log in with current admin credentials
-2. Go to Profile/Settings
-3. Change password through the UI
-
-### Method 2: Database Update
-
-```sql
--- Generate new hash using the script first
-UPDATE next_auth.users
-SET password_hash = 'new-bcrypt-hash-here',
- updated_at = NOW()
-WHERE email = 'admin@yourdomain.com' AND role = 'Admin';
-```
-
-## 🔍 Verifying Admin User
-
-To check if the admin user exists:
-
-```sql
-SELECT id, name, email, role, created_at
-FROM next_auth.users
-WHERE role = 'Admin';
-```
-
-## 🏗️ Role Hierarchy
-
-The system uses a hierarchical role system:
-
-- **Member** (Level 1) - Basic access
-- **Editor** (Level 2) - Can edit content + Member permissions
-- **Developer** (Level 3) - Can access dev tools + Editor permissions
-- **Admin** (Level 4) - Full system access + Developer permissions
-
-## 🔒 Security Best Practices
-
-1. **Use Strong Passwords**: Minimum 12 characters with mixed case, numbers, and symbols
-2. **Change Default Passwords**: Always change the default `admin123` password
-3. **Limit Admin Users**: Only create admin users when necessary
-4. **Regular Password Updates**: Update admin passwords regularly
-5. **Monitor Admin Activity**: Keep track of admin user actions
-
-## 🚨 Troubleshooting
-
-### Admin User Not Created
-
-If the admin user isn't created during database initialization:
-
-1. Check the seed.sql file is present
-2. Verify environment variables are set correctly
-3. Check database logs for errors
-4. Manually run the seed script
-
-### Can't Log In
-
-1. Verify the email and password are correct
-2. Check if the user exists in the database
-3. Ensure the password hash is valid
-4. Check Auth.js configuration
-
-### Password Hash Issues
-
-If you're having issues with password hashes:
-
-```bash
-# Test password hashing
-node -e "
-const bcrypt = require('bcryptjs');
-bcrypt.hash('your-password', 12).then(hash => {
- console.log('Hash:', hash);
- bcrypt.compare('your-password', hash).then(valid => {
- console.log('Valid:', valid);
- });
-});
-"
-```
-
-## 📞 Support
-
-If you encounter issues with admin user setup, check:
-
-1. Database migration logs
-2. Supabase dashboard for user data
-3. Application logs for authentication errors
-4. Environment variable configuration
diff --git a/docs/ai-workflow-assistant.md b/docs/ai-workflow-assistant.md
deleted file mode 100644
index ee396a2f1e..0000000000
--- a/docs/ai-workflow-assistant.md
+++ /dev/null
@@ -1,606 +0,0 @@
-# AI Workflow Assistant - Complete Guide
-
-## Overview
-
-The AI-powered workflow assistant enables users to create, modify, and understand workflows through natural language conversations. It combines AI intelligence with workflow automation to make complex automation accessible to all users.
-
-## Architecture
-
-### Components
-
-1. **Workflow Tools** (`convex/agent_tools/convex_tools/workflows/`)
-
- - `get_workflow_structure.ts` - Retrieves complete workflow structure
- - `update_workflow_step.ts` - Updates existing steps (for small, targeted edits)
- - `generate_workflow_from_description.ts` - AI-powered initial workflow generation
- - `save_workflow_definition.ts` - Saves/updates an entire workflow (metadata + all steps) in one atomic operation
- - `list_available_actions.ts` - Discovers all available action types
- - `search_workflow_examples.ts` - Searches existing workflows for examples
-
-2. **Workflow Assistant Agent** (`convex/workflow_assistant_agent.ts`)
-
- - Main entry point for AI conversations
- - Automatically loads workflow context
- - Handles tool execution and response generation
-
-3. **Agent Configuration** (`convex/lib/create_workflow_agent.ts`)
-
- - Specialized agent with workflow-specific instructions
- - Lower temperature (0.3) for consistent generation
- - Comprehensive system prompt with examples
-
-4. **Frontend Integration** (`app/.../automation-sidepanel.tsx`)
- - Real-time chat interface
- - Connects to workflow assistant backend
- - Context-aware conversations
-
-## Features
-
-### 1. Workflow Understanding
-
-The AI can analyze and explain existing workflows:
-
-- Reads workflow structure and steps
-- Explains what each step does
-- Identifies potential improvements
-
-### 2. Workflow Creation
-
-Generate complete workflows from natural language:
-
-```
-User: "Create a workflow that sends product recommendations to inactive customers"
-AI: [Generates complete workflow with trigger, data fetching, AI analysis, and email steps]
-```
-
-### 3. Workflow Modification
-
-Make targeted changes to existing workflows:
-
-- Add new steps
-- Update step configurations
-- Remove unnecessary steps
-- Modify step connections
-
-### 4. Context Awareness
-
-The assistant automatically:
-
-- Loads current workflow structure when workflowId is provided
-- Maintains conversation context across messages
-- Provides relevant suggestions based on workflow state
-
-### 5. Knowledge Discovery
-
-Two powerful knowledge tools help the AI discover and learn:
-
-#### `list_available_actions` 🔧
-
-Discovers all available action types that can be used in workflow steps.
-
-**Returns:**
-
-- Action type (e.g., `customer`, `product`, `conversation`, `email_provider`)
-- Title and description
-- All operations supported (e.g., `create`, `query`, `update`)
-- All parameters (required and optional)
-- Category (customer, product, email, conversation, etc.)
-- Usage example with proper syntax
-
-**Categories available:**
-
-- `customer` - Customer management operations
-- `product` - Product management operations
-- `email` - Email sending operations
-- `conversation` - Conversation/messaging operations
-- `document` - Document management operations
-- `integration` - Third-party integrations (Shopify, Circuly, OneDrive)
-- `workflow` - Workflow-specific operations (approvals, processing records)
-- `knowledge` - Knowledge base operations (RAG)
-- `web` - Web crawling and website operations
-
-#### `search_workflow_examples` 📚
-
-Searches existing workflows to find examples and learn from existing structures.
-
-**Returns:**
-
-- Workflow name and description
-- Status (active/inactive)
-- Step count
-- Step structure (includes full config)
- - Step ID, name, type, order
- - Full step config
- - Next steps connections
-
-**Search tips:**
-
-- Use keywords like "email", "customer", "product", "recommendation"
-- Set `includeInactive: true` to see draft/inactive workflows
-- Adjust `limit` to control number of results (default: 5)
-
-## Usage Examples
-
-### Creating a New Workflow
-
-**User:** "I want to create a workflow that finds customers who haven't purchased in 30 days and sends them personalized product recommendations"
-
-**AI Response:**
-
-1. Searches for similar examples using `search_workflow_examples`
-2. Discovers available actions using `list_available_actions`
-3. Analyzes the requirement and breaks it down into logical steps
-4. Uses `generate_workflow_from_description` tool
-5. Creates workflow with:
- - Trigger (scheduled daily)
- - Find inactive customers (action)
- - Analyze purchase history (LLM)
- - Generate recommendations (LLM)
- - Send email (action)
-
-### Modifying an Existing Workflow
-
-**User:** "Add a step that checks if customers have opened previous emails"
-
-**AI Response:**
-
-1. Uses `get_workflow_structure` to understand current workflow
-2. Identifies where to insert the new step
-3. Regenerates the full list of steps (including the new email engagement check)
-4. Uses `save_workflow_definition` to replace the workflow's steps atomically
-5. Confirms the changes
-
-### Understanding a Workflow
-
-**User:** "What does this workflow do?"
-
-**AI Response:**
-
-1. Uses `get_workflow_structure` to load workflow
-2. Analyzes each step
-3. Provides clear explanation of:
- - Overall purpose
- - Each step's function
- - How steps connect
- - Potential improvements
-
-## Technical Details
-
-### Tool Registry Integration
-
-All workflow tools are registered in `convex/agent_tools/tool_registry.ts`:
-
-```typescript
-export const TOOL_REGISTRY = [
- // ... existing tools
- getWorkflowStructureTool,
- updateWorkflowStepTool,
- generateWorkflowFromDescriptionTool,
- saveWorkflowDefinitionTool,
- listAvailableActionsTool,
- searchWorkflowExamplesTool,
-] as const;
-```
-
-### Workflow Context Loading
-
-When a `workflowId` is provided, the assistant automatically loads:
-
-- Workflow name, description, and status
-- All steps with their configurations
-- Step connections and order
-- This context is injected into the conversation
-
-### AI Model Configuration
-
-- **Model:** GPT-4o (configurable via `OPENAI_MODEL` env var)
-- **Temperature:** 0.3 (lower for consistent workflow generation)
-- **Max Steps:** 15 (allows complex multi-step operations)
-
-### Available Step Types
-
-1. **trigger** - Starts workflow (manual, scheduled, event-based)
-2. **llm** - AI agent with tools and decision-making
-3. **action** - Database queries, API calls, operations
-4. **condition** - Branching logic based on expressions
-5. **loop** - Iteration over collections
-
-### Workflow Creation Flow
-
-1. **User requests a workflow**
-
- ```
- User: "Create a workflow that sends abandoned cart emails"
- ```
-
-2. **AI searches for similar examples**
-
- ```
- AI: search_workflow_examples({ query: "abandoned cart email" })
- ```
-
-3. **AI discovers available actions**
-
- ```
- AI: list_available_actions({ category: "email" })
- AI: list_available_actions({ category: "customer" })
- ```
-
-4. **AI generates the workflow**
- - Uses patterns from examples
- - Uses correct action types and operations
- - Includes all required parameters
- - Follows best practices
-
-### Benefits
-
-✅ **Consistency** - AI learns from existing workflows and maintains consistent patterns
-✅ **Accuracy** - AI knows exactly what actions and operations are available
-✅ **Completeness** - AI includes all required parameters
-✅ **Best Practices** - AI follows patterns that have been proven to work
-
-## Best Practices
-
-### For Users
-
-1. **Be Specific** - Provide clear descriptions of what you want
-2. **Ask Questions** - The AI will clarify if needed
-3. **Review Changes** - Always review AI-generated workflows
-4. **Iterate** - Start simple and add complexity gradually
-
-### For Developers
-
-1. **Tool Design** - Keep tools focused and single-purpose
-2. **Error Handling** - Always return success/failure status
-3. **Context** - Pass organizationId and workflowId in context
-4. **Validation** - Validate AI-generated configurations
-5. **Testing** - Test with various natural language inputs
-
-## Testing Guide
-
-### Quick Start Testing
-
-#### 1. Test Workflow Creation
-
-Open the workflow editor and click the AI Assistant button. Try these prompts:
-
-**Simple Workflow:**
-
-```
-Create a workflow that sends a welcome email to new customers
-```
-
-**Expected Result:**
-
-- Workflow with trigger step
-- Action to send email
-- Proper step connections
-
-**Complex Workflow:**
-
-```
-Create a workflow that:
-1. Finds customers who haven't purchased in 30 days
-2. Analyzes their purchase history using AI
-3. Generates 3-5 product recommendations
-4. Sends a personalized email with recommendations
-```
-
-**Expected Result:**
-
-- Multi-step workflow with trigger, actions, and LLM steps
-- Proper tool configuration for LLM steps
-- Logical step ordering and connections
-
-#### 2. Test Workflow Modification
-
-Open an existing workflow and ask:
-
-```
-Add a step that checks if the customer has opened previous emails before sending
-```
-
-**Expected Result:**
-
-- AI loads current workflow structure
-- Adds condition step in appropriate location
-- Updates step connections
-- Confirms the change
-
-#### 3. Test Workflow Understanding
-
-Open an existing workflow and ask:
-
-```
-What does this workflow do?
-```
-
-**Expected Result:**
-
-- Clear explanation of workflow purpose
-- Description of each step
-- How steps connect together
-- Potential suggestions for improvement
-
-#### 4. Test Context Awareness
-
-In an existing workflow, ask:
-
-```
-How many steps does this workflow have?
-```
-
-**Expected Result:**
-
-- Accurate count of steps
-- Brief description of step types
-
-Then ask:
-
-```
-Can you add a loop to process multiple customers?
-```
-
-**Expected Result:**
-
-- AI understands the current workflow context
-- Suggests where to add the loop
-- Creates the loop step with proper configuration
-
-### Test Scenarios
-
-#### Scenario 1: E-commerce Re-engagement
-
-**Prompt:**
-
-```
-Create a customer re-engagement workflow that:
-- Runs daily at 9 AM
-- Finds customers inactive for 30+ days
-- Uses AI to analyze their browsing and purchase history
-- Generates personalized product recommendations
-- Sends email only if customer has good email engagement
-```
-
-**Validation:**
-
-- [ ] Trigger step with schedule configuration
-- [ ] Action step to find inactive customers
-- [ ] LLM step with appropriate tools (customer_search, list_products)
-- [ ] Condition step for email engagement check
-- [ ] Action step to send email
-- [ ] All steps properly connected
-
-#### Scenario 2: Product Recommendation
-
-**Prompt:**
-
-```
-I need a workflow that recommends products based on what customers viewed but didn't buy
-```
-
-**Validation:**
-
-- [ ] Workflow created with logical steps
-- [ ] Uses customer and product tools
-- [ ] Includes AI analysis step
-- [ ] Has email/notification step
-
-#### Scenario 3: Workflow Modification
-
-**Setup:** Open existing workflow with 3 steps
-
-**Prompt:**
-
-```
-Add a step between step 2 and step 3 that validates the data
-```
-
-**Validation:**
-
-- [ ] AI loads current workflow
-- [ ] Creates new step with order 2.5 or reorders existing steps
-- [ ] Updates connections properly
-- [ ] Confirms the change
-
-#### Scenario 4: Error Handling
-
-**Prompt:**
-
-```
-Add error handling to this workflow
-```
-
-**Validation:**
-
-- [ ] AI suggests adding condition steps
-- [ ] Adds failure paths in nextSteps
-- [ ] Suggests error notification steps
-
-### Manual Testing Checklist
-
-#### Backend Tests
-
-- [ ] `get_workflow_structure` tool returns correct data
-- [ ] `create_workflow_step` tool creates steps successfully
-- [ ] `update_workflow_step` tool updates configurations
-- [ ] `delete_workflow_step` tool removes steps
-- [ ] `generate_workflow_from_description` creates valid workflows
-- [ ] `list_available_actions` returns all action types
-- [ ] `search_workflow_examples` finds relevant workflows
-- [ ] Workflow context loads automatically when workflowId provided
-- [ ] organizationId is properly passed to tools
-
-#### Frontend Tests
-
-- [ ] AI Assistant panel opens/closes correctly
-- [ ] Welcome message appears when panel opens
-- [ ] User messages display correctly
-- [ ] AI responses stream/display properly
-- [ ] Loading state shows during AI processing
-- [ ] Error messages display when API fails
-- [ ] Thread ID is unique per workflow
-- [ ] Panel is resizable
-
-#### Integration Tests
-
-- [ ] Created workflows appear in workflow list
-- [ ] Modified workflows update in real-time
-- [ ] Deleted steps are removed from database
-- [ ] Workflow execution works with AI-generated workflows
-- [ ] Tool calls are logged and visible
-- [ ] Context is maintained across multiple messages
-
-### Performance Testing
-
-#### Response Time
-
-- [ ] Simple queries respond in < 3 seconds
-- [ ] Complex workflow generation completes in < 10 seconds
-- [ ] Workflow structure loading is fast (< 1 second)
-
-#### Reliability
-
-- [ ] AI consistently generates valid workflow structures
-- [ ] Tool calls succeed reliably
-- [ ] Error handling works for invalid inputs
-- [ ] Context loading handles missing workflows gracefully
-
-### Edge Cases
-
-#### Test Invalid Inputs
-
-1. **Empty workflow description**
-
- ```
- Create a workflow
- ```
-
- Expected: AI asks for more details
-
-2. **Ambiguous request**
-
- ```
- Make it better
- ```
-
- Expected: AI asks what to improve
-
-3. **Non-existent workflow**
-
- - Open AI chat without workflowId
- - Ask about "this workflow"
- Expected: AI explains no workflow is loaded
-
-4. **Invalid step configuration**
- ```
- Add a step with type "invalid_type"
- ```
- Expected: AI suggests valid step types
-
-### Debugging Tips
-
-#### Enable Verbose Logging
-
-Check browser console for:
-
-- Tool execution logs
-- API call responses
-- Error messages
-
-Check Convex logs for:
-
-- Agent execution traces
-- Tool call results
-- Workflow creation/modification logs
-
-#### Common Issues
-
-**Issue:** AI doesn't create workflow
-
-- Check: organizationId is provided
-- Check: OPENAI_API_KEY is set
-- Check: Tool registry includes workflow tools
-
-**Issue:** Context not loading
-
-- Check: workflowId is valid
-- Check: Workflow exists in database
-- Check: User has access to workflow
-
-**Issue:** Tools not executing
-
-- Check: Tool names match registry
-- Check: Context includes organizationId
-- Check: Tool handlers don't throw errors
-
-### Success Criteria
-
-The AI Workflow Assistant is working correctly when:
-
-✅ Users can create workflows from natural language descriptions
-✅ AI generates valid, executable workflow structures
-✅ Workflow modifications work reliably
-✅ Context is maintained throughout conversations
-✅ Error messages are clear and helpful
-✅ Response times are acceptable (< 10s for complex operations)
-✅ Tool calls succeed consistently
-✅ Generated workflows execute successfully
-
-## Troubleshooting
-
-### Common Issues
-
-**Issue:** AI doesn't understand the request
-
-- **Solution:** Be more specific, provide examples
-
-**Issue:** Workflow generation fails
-
-- **Solution:** Check logs, verify organizationId is provided
-
-**Issue:** Tools not executing
-
-- **Solution:** Verify tool registry, check context variables
-
-**Issue:** Context not loading
-
-- **Solution:** Ensure workflowId is valid and workflow exists
-
-## API Reference
-
-### `chatWithWorkflowAssistant`
-
-```typescript
-action({
- args: {
- threadId: v.string(),
- organizationId: v.string(),
- workflowId: v.optional(v.id('wfDefinitions')),
- message: v.string(),
- maxSteps: v.optional(v.number()),
- },
- returns: v.object({
- response: v.string(),
- toolCalls: v.optional(v.array(...)),
- }),
-})
-```
-
-## Future Enhancements
-
-Potential improvements to consider:
-
-1. **Undo/Redo** - Track AI actions for easy reversal
-2. **Templates** - Pre-built workflow templates
-3. **Visual Feedback** - Highlight changes in the workflow canvas
-4. **Validation** - Pre-execution workflow validation
-5. **Testing** - AI-assisted workflow testing
-6. **Optimization** - AI suggestions for performance improvements
-7. **Documentation** - Auto-generate workflow documentation
-
-## Conclusion
-
-The AI Workflow Assistant provides a powerful, intuitive way to create and manage workflows through natural language. It combines the flexibility of AI with the structure of workflow automation, making complex automation accessible to all users.
-
-The knowledge tools (`list_available_actions` and `search_workflow_examples`) ensure the AI generates consistent, accurate workflows by learning from existing patterns and understanding available capabilities.
diff --git a/docs/api/create-conversation-message.md b/docs/api/create-conversation-message.md
deleted file mode 100644
index bde7164f61..0000000000
--- a/docs/api/create-conversation-message.md
+++ /dev/null
@@ -1,416 +0,0 @@
-# Conversation API - Convex Functions
-
-## Overview
-
-This document describes the Convex functions available for managing conversations and messages. All functions can be called directly from client components using Convex React hooks or from server components using `fetchQuery`/`fetchMutation`.
-
-## Mutations
-
-### `createConversation`
-
-Creates a new parent conversation.
-
-**Parameters:**
-
-```typescript
-{
- organizationId: Id<'organizations'>;
- customerId?: Id<'customers'>;
- subject?: string;
- status?: string; // Default: 'open'
- priority?: string; // Default: 'medium'
- metadata?: any;
-}
-```
-
-**Returns:** `Id<'conversations'>`
-
-**Usage (Client):**
-
-```typescript
-import { useMutation } from 'convex/react';
-import { api } from '@/convex/_generated/api';
-
-const createConv = useMutation(api.conversations.createConversation);
-
-await createConv({
- organizationId: orgId,
- customerId: custId,
- subject: 'Customer inquiry',
- status: 'open',
- priority: 'high',
-});
-```
-
----
-
-### `addMessageToConversation`
-
-Adds a message as a child conversation to an existing conversation.
-
-**Parameters:**
-
-```typescript
-{
- conversationId: Id<'conversations'>;
- organizationId: Id<'organizations'>;
- sender: string;
- content: string;
- isCustomer: boolean;
- status?: string; // Default: 'sent'
- attachment?: any;
-}
-```
-
-**Returns:** `Id<'conversations'>` (message ID)
-
-**Usage (Client):**
-
-```typescript
-const addMessage = useMutation(api.conversations.addMessageToConversation);
-
-await addMessage({
- conversationId: convId,
- organizationId: orgId,
- sender: 'Agent Name',
- content: 'Thank you for contacting us...',
- isCustomer: false,
- status: 'sent',
-});
-```
-
----
-
-### `closeConversation`
-
-Closes a conversation.
-
-**Parameters:**
-
-```typescript
-{
- conversationId: Id<'conversations'>;
- resolvedBy?: string;
-}
-```
-
-**Returns:** `null`
-
----
-
-### `reopenConversation`
-
-Reopens a resolved conversation.
-
-**Parameters:**
-
-```typescript
-{
- conversationId: Id<'conversations'>;
-}
-```
-
-**Returns:** `null`
-
----
-
-### `markConversationAsSpam`
-
-Marks a conversation as spam.
-
-**Parameters:**
-
-```typescript
-{
- conversationId: Id<'conversations'>;
-}
-```
-
-**Returns:** `null`
-
----
-
-### `markConversationAsRead`
-
-Marks a conversation as read and resets unread count.
-
-**Parameters:**
-
-```typescript
-{
- conversationId: Id<'conversations'>;
-}
-```
-
-**Returns:** `null`
-
----
-
-### `bulkCloseConversations`
-
-Closes multiple conversations at once.
-
-**Parameters:**
-
-```typescript
-{
- conversationIds: Id<'conversations'>[];
- resolvedBy?: string;
-}
-```
-
-**Returns:**
-
-```typescript
-{
- successCount: number;
- failedCount: number;
-}
-```
-
----
-
-### `bulkReopenConversations`
-
-Reopens multiple conversations at once.
-
-**Parameters:**
-
-```typescript
-{
- conversationIds: Id < 'conversations' > [];
-}
-```
-
-**Returns:**
-
-```typescript
-{
- successCount: number;
- failedCount: number;
-}
-```
-
----
-
-## Queries
-
-### `getConversations`
-
-Gets conversations for an organization with filtering and pagination.
-
-**Parameters:**
-
-```typescript
-{
- organizationId: Id<'organizations'>;
- status?: string;
- priority?: string;
- search?: string;
- page?: number; // Default: 1
- limit?: number; // Default: 20
-}
-```
-
-**Returns:**
-
-```typescript
-{
- conversations: Conversation[]; // Array of conversations with messages
- total: number;
- page: number;
- limit: number;
- totalPages: number;
-}
-```
-
-**Usage (Client):**
-
-```typescript
-import { useQuery } from 'convex/react';
-import { api } from '@/convex/_generated/api';
-
-const conversations = useQuery(api.conversations.getConversations, {
- organizationId: orgId,
- status: 'open',
- page: 1,
- limit: 20,
-});
-```
-
-**Usage (Server):**
-
-```typescript
-import { fetchQuery } from 'convex/nextjs';
-import { api } from '@/convex/_generated/api';
-
-const conversations = await fetchQuery(api.conversations.getConversations, {
- organizationId: orgId,
- status: 'open',
-});
-```
-
----
-
-### `getConversation`
-
-Gets a single conversation by ID (without messages).
-
-**Parameters:**
-
-```typescript
-{
- conversationId: Id<'conversations'>;
-}
-```
-
-**Returns:** `Conversation | null`
-
----
-
-### `getConversationWithMessages`
-
-Gets a conversation with all its messages and customer data.
-
-**Parameters:**
-
-```typescript
-{
- conversationId: Id<'conversations'>;
-}
-```
-
-**Returns:** `ConversationWithMessages | null`
-
-**Usage (Client):**
-
-```typescript
-const conversation = useQuery(api.conversations.getConversationWithMessages, {
- conversationId: convId,
-});
-```
-
----
-
-## Data Model
-
-### Conversation Structure
-
-Conversations use a hierarchical model where:
-
-- **Parent conversations** represent the main conversation thread
-- **Child conversations** (where `parentId` is set) represent individual messages
-
-### Key Fields
-
-- `organizationId` - ID of the organization
-- `customerId` - Optional customer ID
-- `subject` - Conversation subject/title
-- `status` - Status: 'pending', 'resolved', 'spam', 'archived'
-- `priority` - Priority: 'low', 'medium', 'high'
-- `parentId` - For child conversations (messages), references parent
-- `metadata` - Flexible JSON field for additional data
-
-### Metadata Fields (Parent Conversations)
-
-```typescript
-{
- description?: string;
- channel?: string; // e.g., 'Email'
- category?: string; // e.g., 'General', 'ProductRecommendation'
- unread_count?: number;
- last_message_at?: number;
- last_read_at?: string;
- resolved_at?: string;
- resolved_by?: string;
- marked_spam_at?: string;
-}
-```
-
-### Metadata Fields (Child Conversations/Messages)
-
-```typescript
-{
- sender: string;
- content: string;
- isCustomer: boolean;
- attachment?: any;
-}
-```
-
----
-
-## Best Practices
-
-1. **Use `useMutation` for writes**: In client components, use the `useMutation` hook for all mutations.
-
-2. **Use `useQuery` for reads**: In client components, use the `useQuery` hook for reactive queries.
-
-3. **Use `fetchQuery`/`fetchMutation` in Server Components**: For Next.js server components or actions.
-
-4. **Refresh after mutations**: Call `router.refresh()` after mutations in server-rendered pages to update the UI.
-
-5. **Handle errors**: Always wrap mutations in try-catch blocks and provide user feedback.
-
-6. **Batch operations**: Use bulk mutations when performing operations on multiple conversations.
-
-## Example: Complete Conversation Flow
-
-```typescript
-'use client';
-
-import { useMutation, useQuery } from 'convex/react';
-import { api } from '@/convex/_generated/api';
-import { useRouter } from 'next/navigation';
-
-export function ConversationComponent({ orgId, customerId }) {
- const router = useRouter();
-
- // Queries
- const conversations = useQuery(api.conversations.getConversations, {
- organizationId: orgId,
- status: 'open',
- });
-
- // Mutations
- const createConv = useMutation(api.conversations.createConversation);
- const addMessage = useMutation(api.conversations.addMessageToConversation);
- const close = useMutation(api.conversations.closeConversation);
-
- const handleCreateAndReply = async () => {
- try {
- // Create conversation
- const convId = await createConv({
- organizationId: orgId,
- customerId: customerId,
- subject: 'New inquiry',
- });
-
- // Add message
- await addMessage({
- conversationId: convId,
- organizationId: orgId,
- sender: 'Agent',
- content: 'Hello! How can we help?',
- isCustomer: false,
- });
-
- // Close after reply
- await close({ conversationId: convId });
-
- router.refresh();
- } catch (error) {
- console.error('Error:', error);
- }
- };
-
- return (
-
-
- {/* Render conversations */}
-
- );
-}
-```
diff --git a/docs/convex-local-setup.md b/docs/convex-local-setup.md
deleted file mode 100644
index 82468a9f15..0000000000
--- a/docs/convex-local-setup.md
+++ /dev/null
@@ -1,149 +0,0 @@
-# Convex Local Development Setup
-
-This guide explains how to set up Convex for local development in this project.
-
-## 🔧 Important: Always Use Local Mode
-
-This project is configured to use **Convex in local development mode**. This means:
-
-- ✅ No cloud account required
-- ✅ All data stored locally on your machine
-- ✅ Faster development iteration
-- ✅ Works completely offline
-- ✅ No external dependencies or API keys needed for basic development
-
-## First-Time Setup
-
-**✅ No Setup Required!**
-
-This project is configured to automatically skip the Convex login prompt using `CONVEX_AGENT_MODE=anonymous`. You will **NOT** see any setup prompts when running the development server.
-
-The system automatically:
-
-- Skips authentication prompts
-- Runs in anonymous local mode
-- Creates a local-only development environment
-
-### Why Local Development?
-
-1. **Simplicity**: No need to create cloud accounts or manage API keys
-2. **Speed**: Faster startup and iteration times
-3. **Privacy**: All your data stays on your local machine
-4. **Reliability**: No network dependencies for core development
-
-## Running the Development Server
-
-The recommended way to start development is:
-
-```bash
-npm run dev
-```
-
-This script will:
-
-1. 🔧 Start Convex backend in local mode (port 3210)
-2. ⏳ Wait for the backend to be ready
-3. 🔄 Sync environment variables from `.env.local`
-4. ✅ Generate Convex code and types
-5. 🚀 Start Next.js dev server (port 3000)
-
-You'll see helpful messages like:
-
-```
-[dev] 🔧 Using LOCAL development mode for Convex
-[dev] 💡 If this is your first time running Convex and you see a setup prompt:
-[dev] Please choose "Local development" or "Local" option
-[dev] This ensures you're running in local mode without cloud dependencies
-```
-
-## Manual Convex Commands
-
-If you need to run Convex commands manually, always use the `CONVEX_AGENT_MODE=anonymous` environment variable:
-
-```bash
-# Start Convex backend only (no login prompt, automatically local)
-CONVEX_AGENT_MODE=anonymous npx convex dev
-
-# Generate code and types
-npx convex codegen
-
-# Deploy functions to local backend (no login prompt, automatically local)
-CONVEX_AGENT_MODE=anonymous npx convex deploy
-```
-
-## Package.json Scripts
-
-The following npm scripts are available and pre-configured for anonymous local development:
-
-```bash
-# Main development server (recommended)
-npm run dev
-
-# Convex-only commands (all use CONVEX_AGENT_MODE=anonymous)
-npm run convex:dev # Starts Convex in anonymous mode (automatically local)
-npm run convex:deploy # Deploys to anonymous backend (automatically local)
-npm run convex:codegen # Generates types and API
-```
-
-## Troubleshooting
-
-### "Convex backend did not start listening within 30s"
-
-This usually happens if:
-
-1. You chose "Cloud development" instead of "Local development" in the setup prompt
-2. There's a port conflict on port 3210
-
-**Solution**:
-
-- Kill any existing processes and restart
-- Make sure to choose "Local development" if prompted again
-- Check that port 3210 is available
-
-### "Setup prompt appears despite configuration"
-
-If you somehow still see a setup prompt (this should not happen with the current configuration):
-
-**Solution**:
-
-1. Stop all development servers
-2. Run `CONVEX_AGENT_MODE=anonymous npx convex dev --local` manually
-3. The prompt should be automatically skipped
-4. If it still appears, check that the environment variable is properly set
-
-### Port 3210 already in use
-
-If you see an error about port 3210 being in use:
-
-```bash
-# Find and kill the process using port 3210
-lsof -ti:3210 | xargs kill -9
-
-# Or restart your development server
-npm run dev
-```
-
-## Data Storage
-
-In local mode, Convex stores all data in a local directory. Your data persists between restarts, so you don't lose your development data when stopping and starting the server.
-
-## Environment Variables
-
-The development script automatically syncs environment variables from your `.env.local` file to the Convex backend. This includes:
-
-- `SITE_URL`
-- Authentication keys
-- API keys for external services
-
-Make sure your `.env.local` file is properly configured before starting development.
-
-## Next Steps
-
-Once you have Convex running locally:
-
-1. Your Next.js app will be available at `http://localhost:3000`
-2. Convex dashboard (if needed) at `http://localhost:3210`
-3. Make changes to Convex functions in the `convex/` directory
-4. Changes will automatically reload and sync
-
-Happy coding! 🚀
diff --git a/docs/convex-self-hosted-setup.md b/docs/convex-self-hosted-setup.md
deleted file mode 100644
index 3c1f01362d..0000000000
--- a/docs/convex-self-hosted-setup.md
+++ /dev/null
@@ -1,203 +0,0 @@
-# Convex Self-Hosted Setup Guide
-
-This guide explains how to configure and use Convex self-hosted backend with PostgreSQL in the Tale platform.
-
-## Overview
-
-The Tale platform uses Convex self-hosted backend for real-time data synchronization and serverless functions. The backend is configured to use PostgreSQL as the persistence layer.
-
-## Configuration
-
-### Environment Variables
-
-The following environment variables are required in your `.env` file:
-
-```bash
-# PostgreSQL connection for Convex backend
-# IMPORTANT: Do NOT include database name or query parameters
-POSTGRES_URL=postgresql://tale:tale_password_change_me@db:5432
-
-# Instance name (also used as database name)
-INSTANCE_NAME=tale_platform
-
-# Optional: Disable SSL requirement for local development
-DO_NOT_REQUIRE_SSL=1
-```
-
-### Key Points
-
-1. **POSTGRES_URL Format**:
-
- - ✅ **Correct**: `postgresql://user:password@host:port`
- - ❌ **Wrong**: `postgresql://user:password@host:port/database_name`
- - Do NOT include database name or query parameters
-
-2. **Database Name**:
-
- - The database name is specified by `INSTANCE_NAME`
- - Default: `tale_platform`
-
-3. **Database Creation**:
- - The database is automatically created by the init script using the `INSTANCE_NAME` variable
- - Default database name: `tale_platform`
- - Location: `services/db/init-scripts/02-create-convex-database.sql`
- - To use a different database name, set `INSTANCE_NAME` in your `.env` file
-
-## Docker Compose Configuration
-
-The `compose.yml` file is configured to pass the correct environment variables to the platform service:
-
-```yaml
-environment:
- # PostgreSQL connection (without database name)
- POSTGRES_URL: ${POSTGRES_URL:-postgresql://tale:tale_password_change_me@db:5432}
-
- # Instance configuration
- INSTANCE_NAME: ${INSTANCE_NAME:-tale_platform}
- INSTANCE_SECRET: ${INSTANCE_SECRET}
-
- # Convex URLs
- CONVEX_CLOUD_ORIGIN: ${CONVEX_CLOUD_ORIGIN:-http://127.0.0.1:3210}
- CONVEX_SITE_ORIGIN: ${CONVEX_SITE_ORIGIN:-http://127.0.0.1:3211}
-
- # Security
- DO_NOT_REQUIRE_SSL: ${DO_NOT_REQUIRE_SSL:-false}
-```
-
-## Verification
-
-### 1. Check Database Creation
-
-After starting the services, verify the database was created:
-
-```bash
-# Connect to PostgreSQL
-docker compose exec db psql -U tale -d tale_platform
-
-# List tables (should show Convex tables after first deployment)
-\dt
-```
-
-### 2. Check Convex Backend Logs
-
-```bash
-# View platform service logs
-docker compose logs platform
-
-# Look for successful database connection
-# Expected log: "Connected to Postgres"
-```
-
-### 3. Generate Admin Key
-
-```bash
-# Generate an admin key for CLI access
-docker compose exec platform ./generate_admin_key.sh
-```
-
-## Usage
-
-### Deploy Convex Functions
-
-```bash
-# In your project directory
-npx convex dev
-```
-
-### Environment Variables for Development
-
-Create a `.env.local` file in your project root:
-
-```bash
-CONVEX_SELF_HOSTED_URL='http://localhost:3210'
-CONVEX_SELF_HOSTED_ADMIN_KEY=''
-```
-
-## Troubleshooting
-
-### Issue: "Failed to connect to database"
-
-**Solution**: Verify that:
-
-1. `POSTGRES_URL` does NOT include the database name
-2. The database `tale_platform` exists
-3. The PostgreSQL service is running
-
-### Issue: "Database not found"
-
-**Solution**:
-
-1. Check that `INSTANCE_NAME` matches the database name (with `-` → `_`)
-2. Verify the init script ran successfully:
- ```bash
- docker compose logs db | grep "Convex database"
- ```
-
-### Issue: "SSL connection required"
-
-**Solution**: Set `DO_NOT_REQUIRE_SSL=1` in your `.env` file for local development
-
-## Migration from SQLite
-
-If you're migrating from SQLite to PostgreSQL:
-
-1. Export your data:
-
- ```bash
- npx convex export --path backup.zip
- ```
-
-2. Update environment variables to use PostgreSQL
-
-3. Restart the backend:
-
- ```bash
- docker compose down
- docker compose up -d
- ```
-
-4. Import your data:
- ```bash
- npx convex import --replace-all backup.zip
- ```
-
-## References
-
-- [Convex Self-Hosted Documentation](https://github.com/get-convex/convex-backend/blob/main/self-hosted/README.md)
-- [Convex PostgreSQL Setup](https://github.com/get-convex/convex-backend/blob/main/self-hosted/README.md#connecting-to-postgres-on-neon)
-- [Convex Environment Variables](https://github.com/get-convex/convex-backend/blob/main/self-hosted/README.md#optional-configurations)
-
-## Production Considerations
-
-For production deployments:
-
-1. **Use a managed PostgreSQL service** (e.g., AWS RDS, Google Cloud SQL, Neon)
-2. **Enable SSL**: Remove `DO_NOT_REQUIRE_SSL` and configure SSL certificates
-3. **Set a strong `INSTANCE_SECRET`**: Generate with `openssl rand -hex 32`
-4. **Configure proper backup strategy**: Use PostgreSQL backup tools
-5. **Monitor database performance**: Ensure backend and database are in the same region
-6. **Set up proper authentication**: Configure admin keys securely
-
-## Database Schema
-
-Convex manages its own schema automatically. You don't need to create tables manually. The backend will create the necessary tables on first run:
-
-- `_tables`: Metadata about Convex tables
-- `_documents`: Document storage
-- `_indexes`: Index definitions
-- `_modules`: Convex function modules
-- And other internal tables
-
-## Performance Tips
-
-1. **Co-locate backend and database**: Deploy in the same region/datacenter
-2. **Monitor query performance**: Use PostgreSQL's `pg_stat_statements`
-3. **Adjust connection pool**: Configure based on your workload
-4. **Regular maintenance**: Run `VACUUM` and `ANALYZE` periodically
-
-## Support
-
-For issues and questions:
-
-- [Convex Discord](https://discord.gg/convex) - `#self-hosted` channel
-- [GitHub Issues](https://github.com/get-convex/convex-backend/issues)
diff --git a/docs/deployment-modes.md b/docs/deployment-modes.md
deleted file mode 100644
index a37374b3c8..0000000000
--- a/docs/deployment-modes.md
+++ /dev/null
@@ -1,164 +0,0 @@
-# Deployment Modes
-
-Tale supports two deployment modes: **Local Development** (without HTTPS) and **Production** (with HTTPS via Caddy proxy).
-
-## Local Development Mode (Default)
-
-**Use case:** Running Tale on your local machine for development or testing.
-
-### Setup
-
-1. Create `.env` file:
-
-```bash
-DOMAIN=http://localhost
-DB_NAME=tale
-DB_USER=tale
-DB_PASSWORD=change_me
-OPENAI_API_KEY=sk-...
-```
-
-2. Start services:
-
-```bash
-docker compose up --build
-```
-
-3. Access the platform:
-
-- **Main app:** http://localhost:3000
-- **Other services:** See README.md for port mappings
-
-### What happens
-
-- ✅ All services start EXCEPT the proxy
-- ✅ Platform is directly accessible on port 3000
-- ✅ No SSL certificates needed
-- ✅ Simple and fast for development
-
-## Production Mode (With HTTPS)
-
-**Use case:** Deploying Tale on a server with a domain name and HTTPS.
-
-### Setup
-
-1. Create `.env` file:
-
-```bash
-DOMAIN=https://yourdomain.com
-ACME_EMAIL=you@example.com
-DB_NAME=tale
-DB_USER=tale
-DB_PASSWORD=change_me
-OPENAI_API_KEY=sk-...
-```
-
-2. Start services with production profile:
-
-```bash
-docker compose --profile production up -d --build
-```
-
-3. Access the platform:
-
-- **Main app:** https://yourdomain.com (via Caddy on ports 80/443)
-
-### What happens
-
-- ✅ All services start INCLUDING the proxy
-- ✅ Caddy handles HTTPS termination
-- ✅ Automatic SSL certificate from Let's Encrypt
-- ✅ Auto-renewal of certificates
-- ✅ HTTP→HTTPS redirect
-- ✅ Security headers added
-
-### Prerequisites
-
-- Domain name pointing to your server's IP
-- Ports 80 and 443 open in firewall
-- Valid email for ACME registration
-
-## Switching Between Modes
-
-### From Local to Production
-
-1. Update `.env`:
-
-```bash
-DOMAIN=https://yourdomain.com
-ACME_EMAIL=you@example.com
-```
-
-2. Restart with production profile:
-
-```bash
-docker compose down
-docker compose --profile production up -d --build
-```
-
-### From Production to Local
-
-1. Update `.env`:
-
-```bash
-DOMAIN=http://localhost
-```
-
-2. Restart without profile:
-
-```bash
-docker compose down
-docker compose up --build
-```
-
-## Architecture Differences
-
-### Local Mode
-
-```
-[Browser] → http://localhost:3000 → [Platform (Next.js)]
- ↓
- [Convex Backend]
- ↓
- [Other Services]
-```
-
-### Production Mode
-
-```
-[Browser] → https://yourdomain.com → [Proxy (Caddy)] → [Platform (Next.js)]
- ↓
- [Convex Backend]
- ↓
- [Other Services]
-```
-
-## Troubleshooting
-
-### Local Mode Issues
-
-**Problem:** Can't access http://localhost:3000
-
-- Check if platform service is running: `docker ps | grep tale-platform`
-- Check logs: `docker logs tale-platform`
-- Verify port 3000 is not in use: `lsof -i :3000`
-
-### Production Mode Issues
-
-**Problem:** Proxy not starting
-
-- Ensure you're using the production profile: `docker compose --profile production up`
-- Check proxy logs: `docker logs tale-proxy`
-
-**Problem:** SSL certificate errors
-
-- Verify domain DNS points to your server
-- Check ACME_EMAIL is set in .env
-- Try staging first: `ACME_CA=https://acme-staging-v02.api.letsencrypt.org/directory`
-- Check ports 80/443 are open: `sudo netstat -tlnp | grep -E ':(80|443)'`
-
-**Problem:** "Connection refused" errors
-
-- Ensure platform service is healthy: `docker ps` (check STATUS column)
-- Check platform logs: `docker logs tale-platform`
-- Verify internal networking: `docker network inspect tale_internal`
diff --git a/docs/email-api-sending.md b/docs/email-api-sending.md
deleted file mode 100644
index 4936183577..0000000000
--- a/docs/email-api-sending.md
+++ /dev/null
@@ -1,289 +0,0 @@
-# Email API Sending (Gmail API & Microsoft Graph)
-
-This document explains how to use API-based email sending instead of SMTP to avoid port blocking issues on cloud providers like DigitalOcean.
-
-## Overview
-
-The system now supports two methods for sending emails:
-
-1. **SMTP** - Traditional email sending via SMTP protocol (ports 25, 465, 587)
-2. **API** - Modern API-based sending via Gmail API or Microsoft Graph API (HTTPS only)
-
-## Why Use API Sending?
-
-- ✅ **No port blocking** - Uses HTTPS (port 443) which is never blocked
-- ✅ **Better for cloud providers** - Works on DigitalOcean, AWS, etc. without special configuration
-- ✅ **No DNS setup needed** - When sending from Gmail/Outlook accounts (e.g., `support@gmail.com`, `larry.luo@tale.dev`)
-- ✅ **Full threading support** - Maintains email conversations with `In-Reply-To` and `References` headers
-- ✅ **Message ID tracking** - Returns Internet Message ID for tracking and threading
-- ✅ **OAuth2 security** - Uses secure OAuth2 tokens instead of passwords
-
-## How It Works
-
-### Architecture
-
-```
-Email Provider (with sendMethod: 'api')
- ↓
-send_message_via_email.ts (checks sendMethod)
- ↓
-sendMessageViaAPIInternal (routes to correct API)
- ↓
-Gmail API or Microsoft Graph API
- ↓
-Returns Internet Message ID for threading
-```
-
-### Supported Providers
-
-| Provider | API | OAuth2 Required | DNS Setup Required |
-|----------|-----|-----------------|-------------------|
-| Gmail | Gmail API | Yes | No (if sending from @gmail.com) |
-| Outlook/Microsoft 365 | Microsoft Graph API | Yes | No (if domain already on M365) |
-
-## Setup Instructions
-
-### 1. Create Email Provider with API Sending
-
-When creating an email provider, set `sendMethod: 'api'`:
-
-```typescript
-import { api } from '@/convex/_generated/api';
-
-// Create Gmail provider with API sending
-const providerId = await ctx.runAction(api.email_providers.createOAuth2Provider, {
- organizationId: 'your-org-id',
- name: 'Gmail API',
- vendor: 'gmail',
- sendMethod: 'api', // ← Use API instead of SMTP
- oauth2Auth: {
- provider: 'gmail',
- clientId: 'your-client-id',
- clientSecret: 'your-client-secret',
- authorizationCode: 'auth-code-from-oauth-flow',
- },
- // No smtpConfig needed for API sending!
- imapConfig: {
- host: 'imap.gmail.com',
- port: 993,
- secure: true,
- },
-});
-```
-
-```typescript
-// Create Outlook/Microsoft 365 provider with API sending
-const providerId = await ctx.runAction(api.email_providers.createOAuth2Provider, {
- organizationId: 'your-org-id',
- name: 'Outlook API',
- vendor: 'outlook',
- sendMethod: 'api', // ← Use API instead of SMTP
- oauth2Auth: {
- provider: 'microsoft',
- clientId: 'your-client-id',
- clientSecret: 'your-client-secret',
- authorizationCode: 'auth-code-from-oauth-flow',
- accountType: 'organizational', // or 'personal'
- },
- // No smtpConfig needed for API sending!
- imapConfig: {
- host: 'outlook.office365.com',
- port: 993,
- secure: true,
- },
-});
-```
-
-### 2. OAuth2 Scopes Required
-
-**Gmail:**
-- `https://mail.google.com/` - Full Gmail access (send + read)
-
-**Microsoft:**
-- `https://graph.microsoft.com/Mail.Send` - Send emails
-- `https://outlook.office.com/IMAP.AccessAsUser.All` - IMAP access (for receiving)
-- `https://graph.microsoft.com/User.Read` - Get user info
-- `offline_access` - Refresh tokens
-
-### 3. Sending Emails
-
-Once configured, sending works exactly the same as before:
-
-```typescript
-import { api } from '@/convex/_generated/api';
-
-// Send email (automatically uses API if sendMethod is 'api')
-await ctx.runMutation(api.conversations.sendMessage, {
- conversationId: 'conversation-id',
- organizationId: 'your-org-id',
- content: 'Email body',
- to: ['recipient@example.com'],
- subject: 'Hello from API',
- html: '
Email body
',
- // Threading headers work the same
- inReplyTo: '',
- references: ['', ''],
-});
-```
-
-## Features
-
-### ✅ Message ID Tracking
-
-Both Gmail API and Microsoft Graph API return the Internet Message ID:
-
-```typescript
-// After sending, the message is updated with:
-{
- externalMessageId: '', // Internet Message ID
- deliveryState: 'sent',
- sentAt: 1234567890,
-}
-```
-
-### ✅ Email Threading
-
-Threading works exactly like SMTP:
-
-```typescript
-// Reply to an existing email
-await ctx.runMutation(api.conversations.sendMessage, {
- conversationId: 'conversation-id',
- organizationId: 'your-org-id',
- content: 'Reply message',
- to: ['recipient@example.com'],
- subject: 'Re: Original Subject',
- html: '
Reply message
',
- inReplyTo: '',
- references: ['', ''],
-});
-```
-
-### ✅ HTML and Plain Text
-
-Both content types are supported:
-
-```typescript
-await ctx.runMutation(api.conversations.sendMessage, {
- // ... other fields
- html: '
Hello
This is HTML
',
- text: 'Hello\n\nThis is plain text',
-});
-```
-
-### ✅ CC, BCC, Reply-To
-
-All standard email fields work:
-
-```typescript
-await ctx.runMutation(api.conversations.sendMessage, {
- // ... other fields
- to: ['recipient@example.com'],
- cc: ['cc@example.com'],
- bcc: ['bcc@example.com'],
- replyTo: 'reply-to@example.com',
-});
-```
-
-## Migration from SMTP to API
-
-### Option 1: Update Existing Provider
-
-```typescript
-// Update an existing provider to use API
-await ctx.runMutation(api.email_providers.update, {
- providerId: 'existing-provider-id',
- sendMethod: 'api', // Switch from SMTP to API
- // Remove smtpConfig if no longer needed
- smtpConfig: undefined,
-});
-```
-
-### Option 2: Create New Provider
-
-Create a new provider with `sendMethod: 'api'` and set it as default.
-
-## Troubleshooting
-
-### Error: "API sending requires OAuth2 authentication"
-
-**Solution:** API sending only works with OAuth2. Password authentication is not supported for API sending.
-
-### Error: "Unsupported provider for API sending"
-
-**Solution:** Only Gmail and Microsoft providers support API sending. For other providers, use SMTP.
-
-### Error: "Gmail API error: 401 Unauthorized"
-
-**Solution:** OAuth2 token expired. The system should automatically refresh it. If not, re-authorize the provider.
-
-### Error: "Microsoft Graph API error: 403 Forbidden"
-
-**Solution:** Check that the OAuth2 app has the required scopes (`Mail.Send`).
-
-## Comparison: SMTP vs API
-
-| Feature | SMTP | API |
-|---------|------|-----|
-| **Port blocking** | ❌ Often blocked | ✅ Never blocked (HTTPS) |
-| **DNS setup** | ⚠️ Required for custom domains | ✅ Not needed for Gmail/M365 |
-| **OAuth2 support** | ✅ Yes (XOAUTH2) | ✅ Yes (native) |
-| **Password auth** | ✅ Yes | ❌ No |
-| **Threading** | ✅ Yes | ✅ Yes |
-| **Message ID** | ✅ Yes | ✅ Yes |
-| **Attachments** | ✅ Yes | ⚠️ Not yet implemented |
-| **Rate limits** | ⚠️ Provider-specific | ✅ Higher limits |
-
-## Best Practices
-
-1. **Use API for cloud deployments** - Avoid port blocking issues
-2. **Use SMTP for on-premise** - If you control the network
-3. **Keep OAuth2 tokens fresh** - System handles this automatically
-4. **Monitor token expiry** - Check provider status regularly
-5. **Test before production** - Send test emails to verify configuration
-
-## Example: Complete Setup
-
-```typescript
-// 1. Create OAuth2 provider with API sending
-const providerId = await ctx.runAction(api.email_providers.createOAuth2Provider, {
- organizationId: 'org-123',
- name: 'Company Outlook',
- vendor: 'outlook',
- sendMethod: 'api',
- oauth2Auth: {
- provider: 'microsoft',
- clientId: process.env.MICROSOFT_CLIENT_ID,
- clientSecret: process.env.MICROSOFT_CLIENT_SECRET,
- authorizationCode: authCode,
- accountType: 'organizational',
- },
- imapConfig: {
- host: 'outlook.office365.com',
- port: 993,
- secure: true,
- },
-});
-
-// 2. Send email (automatically uses API)
-const messageId = await ctx.runMutation(api.conversations.sendMessage, {
- conversationId: conversationId,
- organizationId: 'org-123',
- providerId: providerId,
- content: 'Hello from API!',
- to: ['customer@example.com'],
- subject: 'Welcome',
- html: '
Welcome!
Thanks for signing up.
',
-});
-
-// 3. Message is sent via Microsoft Graph API
-// 4. Internet Message ID is stored for threading
-```
-
-## Next Steps
-
-- [ ] Add attachment support for API sending
-- [ ] Add delivery status tracking via webhooks
-- [ ] Add read receipt support
-- [ ] Add batch sending optimization
-
diff --git a/docs/email-providers.md b/docs/email-providers.md
deleted file mode 100644
index 35da1a1ee5..0000000000
--- a/docs/email-providers.md
+++ /dev/null
@@ -1,659 +0,0 @@
-# Email Providers – Convex Integration Guide
-
-A single, concise guide for developers to understand and integrate the email providers feature using Convex. English-only. Follows Convex best practices.
-
-## What you need to know
-
-- Providers supported: Resend (fallback), SMTP (send), IMAP (receive), OAuth2 (Gmail, Microsoft), Password auth
-- If both SMTP and IMAP are configured, both are validated and used
-- Local dev uses Inbucket (see Local Development Setup section below)
-- All data stored in Convex with proper encryption for secrets
-- Uses Convex mutations for writes and queries for reads
-- **Automatic default**: When creating the first email provider for an organization, it will automatically be set as the default provider, even if `isDefault: false` is specified
-
-## Convex Schema
-
-The `emailProviders` table is defined in `convex/schema.ts`:
-
-```typescript
-emailProviders: defineTable({
- organizationId: v.id('organizations'),
- name: v.string(),
- vendor: v.union(
- v.literal('gmail'),
- v.literal('outlook'),
- v.literal('smtp'),
- v.literal('resend'),
- v.literal('other'),
- ),
- authMethod: v.union(
- v.literal('password'),
- v.literal('oauth2'),
- ),
-
- // Auth configurations (encrypted in metadata)
- passwordAuth: v.optional(v.object({
- user: v.string(),
- passEncrypted: v.string(), // encrypted password
- })),
-
- oauth2Auth: v.optional(v.object({
- provider: v.string(), // 'gmail' | 'microsoft'
- clientId: v.string(),
- clientSecretEncrypted: v.string(), // encrypted secret
- accessTokenEncrypted: v.optional(v.string()),
- refreshTokenEncrypted: v.optional(v.string()),
- tokenExpiry: v.optional(v.number()),
- })),
-
- // SMTP configuration
- smtpConfig: v.optional(v.object({
- host: v.string(),
- port: v.number(),
- secure: v.boolean(),
- })),
-
- // IMAP configuration
- imapConfig: v.optional(v.object({
- host: v.string(),
- port: v.number(),
- secure: v.boolean(),
- })),
-
- // Status and metadata
- isActive: v.boolean(),
- isDefault: v.boolean(),
- status: v.optional(v.union(
- v.literal('active'),
- v.literal('error'),
- v.literal('testing'),
- )),
- lastTestedAt: v.optional(v.number()),
- lastSyncAt: v.optional(v.number()),
- errorMessage: v.optional(v.string()),
-
- metadata: v.optional(v.any()),
-})
- .index('by_organizationId', ['organizationId'])
- .index('by_organizationId_and_vendor', ['organizationId', 'vendor'])
- .index('by_organizationId_and_isDefault', ['organizationId', 'isDefault'])
- .index('by_organizationId_and_status', ['organizationId', 'status']),
-```
-
-## UI flows (recommended)
-
-1. Providers list page (simplified)
-
-- Show table of providers (name, vendor, status, default, last tested)
-- Buttons: Create, Set Default, Test, Edit, Delete
-
-2. Create provider page (dedicated)
-
-- Tabs are not required; use a single page with radio for Auth Method: Password or OAuth2
-- Show vendor presets (Gmail/Outlook) to prefill hostnames/ports
-- If OAuth2 + Microsoft (use existing login) is selected, we redirect to consent
-
-3. Test provider action
-
-- Call mutation to test; show SMTP and IMAP results separately
-
-4. Receive email sync
-
-- Manual "Sync now" triggers action; show results (processed/total/errors)
-
-## Convex Functions (import paths)
-
-All functions are in `convex/emailProviders.ts`:
-
-### Queries
-
-```typescript
-import { api } from '@/convex/_generated/api';
-
-// List all providers for an organization
-api.emailProviders.list;
-
-// Get single provider by ID
-api.emailProviders.get;
-
-// Get default provider for an organization
-api.emailProviders.getDefault;
-```
-
-### Mutations
-
-```typescript
-// Update provider configuration
-api.emailProviders.update;
-
-// Delete provider
-api.emailProviders.delete;
-
-// Set provider as default
-api.emailProviders.setDefault;
-```
-
-### Actions
-
-```typescript
-// Create email provider (password or OAuth2) - with encryption
-api.emailProviders.create;
-
-// Test SMTP/IMAP connectivity
-api.emailProviders.test;
-
-// Send email using provider
-api.emailProviders.sendEmail;
-
-// Sync received emails via IMAP
-api.emailProviders.syncEmails;
-
-// Initialize OAuth2 flow (returns auth URL)
-api.emailProviders.initOAuth2;
-
-// Handle OAuth2 callback
-api.emailProviders.handleOAuth2Callback;
-```
-
-## Quick start – examples
-
-### Using from React components
-
-```typescript
-'use client';
-
-import { useQuery, useMutation, useAction } from 'convex/react';
-import { api } from '@/convex/_generated/api';
-import type { Id } from '@/convex/_generated/dataModel';
-
-function EmailProvidersPage({ organizationId }: { organizationId: Id<'organizations'> }) {
- // List providers
- const providers = useQuery(api.emailProviders.list, { organizationId });
-
- // Create provider action (handles encryption)
- const createProvider = useAction(api.emailProviders.create);
-
- // Handle create
- const handleCreate = async () => {
- await createProvider({
- organizationId,
- name: 'Gmail (App Password)',
- vendor: 'gmail',
- authMethod: 'password',
- passwordAuth: {
- user: 'you@gmail.com',
- pass: 'app-password' // will be encrypted
- },
- smtpConfig: { host: 'smtp.gmail.com', port: 587, secure: false },
- imapConfig: { host: 'imap.gmail.com', port: 993, secure: true },
- isActive: true,
- isDefault: true,
- });
- };
-
- return (
-
- );
-}
-```
-
-### Key UI Principles
-
-- **Mask secrets**: Never render passwords or tokens in the UI
-- **Show separate results**: Display SMTP and IMAP test results independently
-- **Real-time updates**: Use Convex's reactive queries for live status updates
-- **Error handling**: Show clear error messages for failed operations
-- **Loading states**: Use Convex's loading states for better UX
-- **Sync button**: Offer a "Sync now" button with result summary
-
-## Local Development Setup
-
-For local development, use Inbucket as a local SMTP server instead of real email services.
-
-### Quick Setup
-
-1. **Install Inbucket:**
-
-```bash
-# Using Docker (recommended)
-docker run -d -p 9000:9000 -p 2500:2500 --name inbucket inbucket/inbucket
-
-# Using Homebrew (macOS)
-brew install inbucket && inbucket
-
-# Using Go
-go install github.com/inbucket/inbucket@latest && inbucket
-```
-
-2. **Create local provider:**
-
-```typescript
-import { useAction } from 'convex/react';
-import { api } from '@/convex/_generated/api';
-
-const createProvider = useAction(api.emailProviders.create);
-
-await createProvider({
- organizationId,
- name: 'Local Dev (Inbucket)',
- vendor: 'smtp',
- authMethod: 'password',
- passwordAuth: {
- user: 'dev@local',
- pass: 'any', // Inbucket accepts any password (automatically encrypted by action)
- },
- smtpConfig: {
- host: 'localhost',
- port: 2500,
- secure: false,
- },
- isActive: true,
- isDefault: true,
-});
-```
-
-3. **View emails:** Open http://localhost:9000
-
-That's it! No special configuration needed - it's just another email provider pointing to localhost.
-
-**Pro tip:** Use different Convex deployments for dev and production. Each deployment has its own `emailProviders` table, so your local Inbucket provider stays in dev only.
-
-## Additional Resources
-
-- [Convex Schema Documentation](https://docs.convex.dev/database/schemas)
-- [Convex Queries and Mutations](https://docs.convex.dev/functions)
-- [Convex Actions](https://docs.convex.dev/functions/actions)
-- [Gmail OAuth2 Setup](https://developers.google.com/identity/protocols/oauth2)
-- [Microsoft Graph OAuth2](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow)
-- [Inbucket Email Testing](https://www.inbucket.org/)
diff --git a/docs/integration-health-checks.md b/docs/integration-health-checks.md
deleted file mode 100644
index e70cfa8268..0000000000
--- a/docs/integration-health-checks.md
+++ /dev/null
@@ -1,199 +0,0 @@
-# Integration Health Checks
-
-## Overview
-
-This document describes the health check system implemented for Shopify and Circuly integrations. Health checks are automatically run when creating or updating integrations to ensure credentials are valid before saving them to the database.
-
-**Note:** Gmail and Outlook are managed separately through the `emailProviders` system and do not use the `integrations` table. They have their own authentication flow using OAuth2.
-
-## Implementation
-
-### Key Features
-
-1. **Automatic Health Checks on Create**: When creating a new Shopify or Circuly integration, the credentials are validated against the actual API before the integration is saved.
-
-2. **Automatic Health Checks on Update**: When updating credentials for an existing integration, the new credentials are validated before being saved.
-
-3. **Fail-Fast Behavior**: If a health check fails, an error is thrown and the integration is NOT created/updated. This prevents invalid integrations from being stored.
-
-4. **User-Friendly Error Messages**: Detailed error messages help users understand what went wrong:
- - "Shopify authentication failed. Please check your access token."
- - "Shopify store not found. Please verify your domain."
- - "Circuly authentication failed. Please check your username and password."
-
-5. **Active Status on Success**: When a health check passes during creation, the integration is automatically set to `status: 'active'` and `isActive: true`.
-
-### Health Check Functions
-
-#### `testShopifyConnection(domain, accessToken)`
-
-Tests a Shopify connection by calling the `/admin/api/2024-01/shop.json` endpoint.
-
-**Validates:**
-
-- Access token is valid
-- Store domain exists
-- API permissions are correct
-
-**Error Codes:**
-
-- 401: Invalid access token
-- 403: Insufficient permissions
-- 404: Store not found
-
-#### `testCirculyConnection(username, password)`
-
-Tests a Circuly connection by calling the `/v1/account` endpoint with basic authentication.
-
-**Validates:**
-
-- Username and password are correct
-- Account has proper permissions
-
-**Error Codes:**
-
-- 401: Invalid credentials
-- 403: Insufficient permissions
-
-### Integration Points
-
-The health checks are integrated into three key functions:
-
-1. **`create` action**: Runs health check before creating a new integration
-2. **`update` action**: Runs health check when credentials are being updated
-3. **`testConnection` action**: Uses the same health check functions for manual testing
-
-## Usage
-
-### Creating an Integration
-
-```typescript
-// Shopify
-const integrationId = await ctx.runAction(api.integrations.create, {
- organizationId: 'org123',
- provider: 'shopify',
- authMethod: 'api_key',
- apiKeyAuth: {
- key: 'shpat_abc123...',
- keyPrefix: 'shpat_',
- },
- connectionConfig: {
- domain: 'mystore.myshopify.com',
- },
-});
-// If health check fails, an error is thrown and no integration is created
-
-// Circuly
-const integrationId = await ctx.runAction(api.integrations.create, {
- organizationId: 'org123',
- provider: 'circuly',
- authMethod: 'basic_auth',
- basicAuth: {
- username: 'myusername',
- password: 'mypassword',
- },
-});
-// If health check fails, an error is thrown and no integration is created
-```
-
-### Updating Credentials
-
-```typescript
-await ctx.runAction(api.integrations.update, {
- integrationId: 'int123',
- apiKeyAuth: {
- key: 'new_token_here',
- },
- connectionConfig: {
- domain: 'newstore.myshopify.com',
- },
-});
-// Health check runs automatically when credentials are changed
-```
-
-### Manual Testing
-
-```typescript
-const result = await ctx.runAction(api.integrations.testConnection, {
- integrationId: 'int123',
-});
-// Returns { success: boolean, message: string }
-```
-
-## Error Handling
-
-When a health check fails:
-
-1. An error is thrown with a descriptive message
-2. The integration is NOT created or updated
-3. The error propagates to the UI where it's displayed to the user
-4. For existing integrations being updated, the old credentials remain unchanged
-
-## Logging
-
-Health checks log their progress:
-
-```
-[Integration Create] Running health check for shopify...
-[Shopify Health Check] Successfully connected to My Store Name
-[Integration Create] Health check passed for shopify
-[Integration Create] Successfully created shopify integration with ID: xyz
-```
-
-Failed health checks log errors:
-
-```
-[Integration Create] Running health check for shopify...
-[Integration Create] Health check failed for shopify: Shopify authentication failed. Please check your access token.
-```
-
-## Architecture Notes
-
-### Integration Types
-
-**Integrations Table (with Health Checks):**
-
-- Shopify - API key authentication
-- Circuly - Basic authentication
-
-**Email Providers Table (OAuth2):**
-
-- Gmail - OAuth2 authentication
-- Outlook - OAuth2 authentication
-- SMTP/IMAP - Custom configurations
-
-Email providers use a separate system (`emailProviders` table) because they have different authentication requirements (OAuth2), connection patterns (SMTP/IMAP), and use cases (email sending/receiving).
-
-## Future Enhancements
-
-Potential improvements:
-
-1. Implement periodic health checks to detect stale credentials
-2. Add retry logic with exponential backoff
-3. Store health check history for debugging
-4. Add more granular permission checks
-5. Add webhook verification for supported integrations
-
-## Related Files
-
-**Integration System:**
-
-- `/convex/integrations.ts` - Main integration management file with health checks
-- `/convex/schema.ts` - Integration table schema (Shopify, Circuly)
-- `/app/(app)/dashboard/[id]/settings/integrations/components/shopify-integration-dialog.tsx` - Shopify UI
-- `/app/(app)/dashboard/[id]/settings/integrations/components/circuly-integration-dialog.tsx` - Circuly UI
-
-**Email Provider System:**
-
-- `/convex/emailProviders.ts` - Email provider management (Gmail, Outlook, SMTP)
-- `/app/(app)/dashboard/[id]/settings/integrations/components/gmail-integration-dialog.tsx` - Gmail UI
-- `/app/(app)/dashboard/[id]/settings/integrations/components/outlook-integration-dialog.tsx` - Outlook UI
-
-## Testing
-
-To test the health check system:
-
-1. **Valid Credentials**: Create an integration with valid credentials - should succeed
-2. **Invalid Token**: Use an invalid access token - should fail with authentication error
-3. **Invalid Domain**: Use a non-existent domain - should fail with store not found error
-4. **Network Issues**: Simulate network failures to ensure proper error handling
diff --git a/docs/integrations-schema.md b/docs/integrations-schema.md
deleted file mode 100644
index a587d726ab..0000000000
--- a/docs/integrations-schema.md
+++ /dev/null
@@ -1,315 +0,0 @@
-# Integrations Schema Documentation
-
-## Overview
-
-The `integrations` table has been redesigned from a generic, unstructured table to a fully-typed, structured system for managing third-party service connections (Shopify, Circuly, Stripe, etc.).
-
-## Key Improvements
-
-### Before
-
-```typescript
-integrations: defineTable({
- organizationId: v.id('organizations'),
- provider: v.string(), // Too generic
- status: v.optional(v.string()), // Too generic
- metadata: v.optional(v.any()), // Everything in unstructured metadata
-});
-```
-
-### After
-
-```typescript
-integrations: defineTable({
- organizationId: v.id('organizations'),
-
- // Structured provider identification
- provider: v.union(
- v.literal('shopify'),
- v.literal('circuly'),
- v.literal('stripe'),
- v.literal('firmhouse'),
- ),
- name: v.string(),
-
- // Typed status
- status: v.union(
- v.literal('active'),
- v.literal('inactive'),
- v.literal('error'),
- v.literal('testing'),
- ),
-
- // Structured authentication
- authMethod: v.union(
- v.literal('api_key'),
- v.literal('bearer_token'),
- v.literal('basic_auth'),
- v.literal('oauth2'),
- ),
-
- // Encrypted credentials (like emailProviders pattern)
- apiKeyAuth: v.optional({ keyEncrypted, keyPrefix }),
- basicAuth: v.optional({ username, passwordEncrypted }),
- oauth2Auth: v.optional({ accessTokenEncrypted, ... }),
-
- // Provider-specific config (structured, not v.any())
- connectionConfig: v.optional({
- domain, apiVersion, apiEndpoint, timeout, rateLimit
- }),
-
- // Health tracking
- lastSyncedAt, lastTestedAt, lastSuccessAt, lastErrorAt, errorMessage,
-
- // Sync statistics
- syncStats: { totalRecords, lastSyncCount, failedSyncCount },
-
- // Capabilities
- capabilities: { canSync, canPush, canWebhook, syncFrequency },
-
- // Only truly unstructured data
- metadata: v.optional(v.any()),
-})
-```
-
-## Benefits
-
-### 1. Type Safety
-
-- IDE autocomplete for all fields
-- Compile-time validation
-- No runtime surprises
-
-### 2. Security
-
-- Credentials encrypted at rest (follows `emailProviders` pattern)
-- Clear separation between config and secrets
-- Audit trail with timestamps
-
-### 3. Observability
-
-- Health metrics (lastSuccessAt, lastErrorAt)
-- Sync statistics
-- Error messages
-
-### 4. Flexibility
-
-- Provider-specific config in structured object
-- Capabilities flag for feature toggles
-- Still extensible via `metadata`
-
-## Usage Examples
-
-### Creating a Shopify Integration
-
-```typescript
-const integrationId = await ctx.runAction(api.integrations.create, {
- organizationId: args.organizationId,
- provider: 'shopify',
- name: 'Main Store',
- authMethod: 'api_key',
- apiKeyAuth: {
- key: 'shpat_1234...', // Will be encrypted
- keyPrefix: 'shpat_',
- },
- connectionConfig: {
- domain: 'mystore.myshopify.com',
- apiVersion: '2024-01',
- timeout: 30000,
- },
- capabilities: {
- canSync: true,
- canPush: false,
- canWebhook: true,
- syncFrequency: 'hourly',
- },
-});
-```
-
-### Creating a Circuly Integration
-
-```typescript
-const integrationId = await ctx.runAction(api.integrations.create, {
- organizationId: args.organizationId,
- provider: 'circuly',
- name: 'Circuly Subscriptions',
- authMethod: 'bearer_token',
- apiKeyAuth: {
- key: apiKey, // Will be encrypted
- },
- connectionConfig: {
- apiEndpoint: 'https://api.circuly.io/api/2025-01',
- },
- capabilities: {
- canSync: true,
- canPush: false,
- syncFrequency: 'daily',
- },
-});
-```
-
-### Querying Integrations
-
-```typescript
-// Get all integrations for an organization
-const integrations = await ctx.runQuery(api.integrations.list, {
- organizationId,
-});
-
-// Get specific provider integration
-const shopifyIntegration = await ctx.runQuery(api.integrations.getByProvider, {
- organizationId,
- provider: 'shopify',
-});
-
-// Get decrypted credentials (for actions)
-const credentials = await ctx.runAction(
- api.integrations.getDecryptedCredentials,
- {
- integrationId,
- }
-);
-// Returns: { apiKey, domain, connectionConfig, ... }
-```
-
-### Testing Connection
-
-```typescript
-const result = await ctx.runAction(api.integrations.testConnection, {
- integrationId,
-});
-
-if (result.success) {
- // Integration is active and working
- console.log(result.message);
-} else {
- // Integration has errors
- console.error(result.message);
-}
-```
-
-### Updating Sync Stats
-
-```typescript
-await ctx.runMutation(api.integrations.updateSyncStats, {
- integrationId,
- totalRecords: 1500,
- lastSyncCount: 150,
- failedSyncCount: 2,
-});
-```
-
-## API Reference
-
-### Queries
-
-- `list(organizationId, provider?)` - List integrations
-- `get(integrationId)` - Get single integration
-- `getByProvider(organizationId, provider)` - Get by provider
-
-### Actions
-
-- `create(...)` - Create integration with encryption
-- `update(integrationId, ...)` - Update integration
-- `testConnection(integrationId)` - Test integration
-- `getDecryptedCredentials(integrationId)` - Get decrypted creds
-
-### Mutations
-
-- `deleteIntegration(integrationId)` - Delete integration
-- `updateSyncStats(integrationId, ...)` - Update sync stats
-
-## Integration with Workflows
-
-The Shopify workflow action now supports loading credentials from the integrations table:
-
-### Priority Order
-
-1. Direct parameters (`domain`, `accessToken`)
-2. `variables.shopify`
-3. `variables.workflow.shopify`
-4. Integration table (via `shopifyIntegrationId` or `organizationId`)
-
-### Example Workflow Usage
-
-```typescript
-// Option 1: Direct parameters (existing)
-{
- domain: 'mystore.myshopify.com',
- accessToken: 'shpat_...',
- resource: 'products',
-}
-
-// Option 2: Via variables (existing)
-variables: {
- shopify: {
- domain: 'mystore.myshopify.com',
- accessToken: 'shpat_...',
- }
-}
-
-// Option 3: From integration table (new - TODO)
-variables: {
- shopifyIntegrationId: 'j1234...', // Load from specific integration
- // OR
- organizationId: 'k5678...', // Auto-find Shopify integration
-}
-```
-
-## Security Considerations
-
-### Encryption
-
-- All credentials encrypted using `oauth2.encrypt/decrypt` actions
-- Same pattern as `emailProviders`
-- Encryption keys stored in environment variables
-
-### Access Control
-
-- Integration credentials only decrypted in actions
-- Mutations work with encrypted values
-- Queries never return decrypted credentials
-
-### Audit Trail
-
-- `lastTestedAt` - When connection was last tested
-- `lastSyncedAt` - When last sync occurred
-- `lastSuccessAt` / `lastErrorAt` - Success/failure tracking
-- `errorMessage` - Last error details
-
-## Migration Path
-
-For existing systems using variables for credentials:
-
-1. **Phase 1**: Keep using variables (fully backward compatible)
-2. **Phase 2**: Create integrations through UI
-3. **Phase 3**: Workflows automatically use integration table as fallback
-4. **Phase 4**: Remove inline credentials from variables
-
-## Comparison with EmailProviders
-
-| Feature | emailProviders | integrations |
-| --------------------- | ------------------------- | ---------------------------------- |
-| Schema Structure | ✅ Fully structured | ✅ Fully structured |
-| Encryption | ✅ Encrypted credentials | ✅ Encrypted credentials |
-| Multiple Auth Methods | ✅ Password, OAuth2, SMTP | ✅ API Key, Basic, OAuth2 |
-| Health Tracking | ✅ Status, last tested | ✅ Status, last tested, sync stats |
-| Provider Config | ✅ SMTP/IMAP config | ✅ Connection config |
-| Multiple per Org | ✅ Multiple providers | ✅ Multiple providers |
-
-## Next Steps
-
-1. ✅ Schema updated
-2. ✅ Backend API created (`convex/integrations.ts`)
-3. ✅ Shopify workflow action updated
-4. 🔄 UI integration handlers (placeholder TODOs)
-5. ⏳ Actual connection testing implementation
-6. ⏳ Sync job integration
-7. ⏳ Webhook support
-
-## Files Changed
-
-- `convex/schema.ts` - Updated integrations table
-- `convex/integrations.ts` - New integration management API
-- `convex/workflow/nodes/action/actions/shopify.ts` - Updated to support integration lookup
-- `app/(app)/dashboard/[id]/settings/integrations/integrations.tsx` - Placeholder handlers
diff --git a/docs/management-dashboard-user-guide.md b/docs/management-dashboard-user-guide.md
deleted file mode 100644
index 89e2d999e8..0000000000
--- a/docs/management-dashboard-user-guide.md
+++ /dev/null
@@ -1,289 +0,0 @@
-# Management Dashboard User Guide
-
-## Overview
-
-This documentation provides operations staff with a comprehensive guide to understanding and using the management dashboard system's features and capabilities. The dashboard serves as a central hub for managing customer relationships, product recommendations, automated communications, and business insights.
-
-## System Architecture
-
-The management dashboard features a modern interface designed to streamline business operations through integrated modules:
-
-- **Home Dashboard** - Central command center displaying key business metrics, customer lifecycle trends, and quick access to critical functions
-- **Customer Management** - Comprehensive customer database with import tools, status tracking, and detailed customer profiles for managing your entire customer base
-- **Product Management** - Product catalog management with recommendation engine configuration, inventory tracking, and cross-selling relationship setup
-- **Conversations** - Unified communication hub that manages all customer interactions including automated product recommendations, churn prevention surveys, and customer service requests across multiple channels
-- **Task Management** - Automated business process monitoring and manual task execution for streamlined operations
-- **Settings Center** - System-wide configuration including branding, integrations, communication templates, and team management
-- **AI Assistant** - Intelligent business advisor providing data insights, trend analysis, and operational recommendations
-
-## Feature Modules
-
-### 1. Home Dashboard
-
-The Home Dashboard serves as your business command center, providing at-a-glance insights into customer health, business performance, and automated campaign management. This centralized view helps you make data-driven decisions and quickly identify areas requiring attention.
-
-**Main Features:**
-
-- **Customer Lifecycle Chart** - Visual representation of how customers move through different stages (Active → Potential → Churned), helping you identify trends in customer retention and acquisition patterns over time
-
-- **Customer Metrics Overview** - Real-time display of critical business KPIs including total customer count, active customer percentage, churn rate, and growth metrics to monitor business health
-
-- **Churn Survey Configuration** - Quick setup interface for automated retention campaigns, allowing you to configure when and how churn prevention surveys are sent to at-risk customers
-
-- **Business Task Processing** - Monitor and trigger automated business processes such as recommendation generation, email campaigns, and data synchronization tasks
-
-**Use Cases:**
-
-- **Business Health Monitoring**: Get instant visibility into customer retention trends and overall business performance
-- **Trend Analysis**: Track customer lifecycle changes to identify seasonal patterns or business impact events
-- **Campaign Management**: Configure and monitor automated marketing and retention campaigns from a central location
-- **Operational Oversight**: Keep track of automated processes and ensure business operations are running smoothly
-
-### 2. Customer Management
-
-**Core Features:**
-
-#### 2.1 Customer List Management
-
-- **Customer Information Display**: Name, email, status, source, locale, creation date
-- **Customer Status Categories**:
- - `Active` - Active customers
- - `Potential` - Potential customers
- - `Churned` - Churned customers
-- **Search and Filter**: Search by name/email, filter by status
-- **Pagination**: Customizable page size (10/20/50 items)
-
-#### 2.2 Customer Import Functionality
-
-- **Manual Import**: Direct input of customer email lists
- - Format: `customer@example.com` or `customer@example.com,locale`
- - Supports batch import of multiple customers
-- **File Import**: Supports Excel and CSV files
- - Required fields: email
- - Optional fields: locale (language setting)
- - Supported formats: .xlsx, .xls, .csv
- - Multi-language support: en, de, fr, zh, etc. and extended formats (en-US, de-DE, etc.)
-
-#### 2.3 Customer Operations
-
-- **View Subscriptions**: View customer product subscription details
-- **Delete Customer**: Only manually imported customers can be deleted
-- **Customer Details**: View complete customer profile information
-
-**Operation Guide:**
-
-1. Click "Import Churned" button to import churned customers
-2. Select import method (manual input or file upload)
-3. Input or upload customer data according to format requirements
-4. System automatically validates and imports customer information
-
-### 3. Product Management
-
-**Main Features:**
-
-#### 3.1 Product Information Management
-
-- **Product Display**: Images, name, description, stock, creation date
-- **Product Search**: Search by name or description
-- **Product Details**: Expandable view for complete product information
-- **External Links**: Direct navigation to product pages
-
-#### 3.2 Product Recommendation Settings
-
-- **Related Product Configuration**: Set recommendation relationships between products
-- **Recommendation Metadata Management**: Configure recommendation algorithm parameters
-- **Multi-language Support**: Multi-language translations for product names
-
-#### 3.3 Product Data Management
-
-- **Batch Import**: Import products from platforms like Shopify
-- **Data Export**: Export product lists for analysis
-- **Inventory Management**: Track product stock status
-- **Product Types**: Distinguish between physical items and services
-
-**Operation Guide:**
-
-1. Use search box to quickly locate specific products
-2. Click product name to expand detailed information
-3. Use "Relationships" column to configure product recommendation associations
-4. Access product pages through external link buttons
-
-### 4. Conversations Management
-
-The Conversations module serves as your central communication hub, managing all customer interactions across different channels and purposes. This system replaces traditional email management by providing a unified interface for automated marketing campaigns, customer service requests, and retention efforts.
-
-**What is the Conversations System?**
-The Conversations feature consolidates all customer communications into organized threads, whether they're automated product recommendations sent to active customers, churn prevention surveys for at-risk customers, or service requests. Each conversation represents a complete communication thread with a specific customer, allowing you to track the entire interaction history and manage follow-ups effectively.
-
-**Core Features:**
-
-#### 4.1 Conversation List Management
-
-The conversation list provides a comprehensive view of all customer interactions with intelligent organization:
-
-- **Conversation Status Workflow**:
- - `Pending` - New conversations awaiting staff review or customer response
- - `Resolved` - Completed conversations where the customer's needs have been addressed
- - `Spam` - Filtered unwanted or irrelevant messages
- - `Archived` - Conversations automatically archived after 30 days of inactivity to keep the active list manageable
-
-#### 4.2 Conversation Categories and Organization
-
-The system automatically categorizes conversations based on their purpose and business context:
-
-- **Category Management**:
-
- - `Product Recommendation` - Automated recommendations sent to active customers based on their purchase history and preferences, designed to increase cross-selling and upselling opportunities
- - `Service Request` - Customer-initiated inquiries about products, orders, support issues, or general questions requiring staff attention
- - `Churn Survey` - Targeted retention campaigns sent to customers showing signs of disengagement, including feedback surveys and win-back offers
-
-- **Priority Settings**: Conversations are automatically assigned priority levels (High, Medium, Low) based on customer value, urgency indicators, and business rules to help staff focus on the most important interactions first
-
-- **Channel Management**: Supports multiple communication channels including Email, WhatsApp, and other messaging platforms, with plans for website chat integration
-
-#### 4.3 Message Management and Workflow
-
-Advanced message handling capabilities ensure efficient communication processing:
-
-- **Message Status Tracking**:
-
- - `Draft` - Messages being composed
- - `Pending Approval` - Automated messages awaiting staff review before sending
- - `Approved` - Messages cleared for delivery
- - `Sent` - Successfully delivered messages
- - `Failed` - Messages that couldn't be delivered
-
-- **Bulk Operations**: Streamline workflow with batch actions:
-
- - Bulk resolve multiple conversations simultaneously
- - Mass send approved messages to multiple customers
- - Batch update conversation status or priority
- - Export conversation data for analysis
-
-- **Rich Media Support**: Handle various content types including images, videos, audio files, and documents to provide comprehensive customer support
-
-**Operation Guide:**
-
-1. **Filtering and Organization**: Use the filter system to view conversations by status (Pending, Resolved), category (Product Recommendation, Service Request, Churn Survey), priority level, or communication channel
-2. **Conversation Details**: Click on any conversation to view the complete message thread, customer context, and interaction history
-3. **Efficient Processing**: Utilize bulk operations to handle multiple similar conversations simultaneously, improving response times and operational efficiency
-4. **Quick Search**: Use the search function to instantly locate specific conversations by customer name, email, keywords, or conversation content
-5. **Approval Workflow**: Review and approve automated messages before they're sent to ensure quality and brand consistency
-
-### 5. Task Management
-
-**Features:**
-
-- **Task Status Tracking**: Pending, Resolved
-- **Task Search**: Search tasks by keywords
-- **Task Details**: View task execution details and results
-- **Automated Processing**: System automatically executes business tasks
-
-**Usage Instructions:**
-
-- Monitor automated task execution status
-- View task processing results and error information
-- Manually trigger specific business processes
-
-### 6. Settings Center
-
-#### 6.1 General Settings
-
-- **Theme Settings**:
- - Light Mode - Bright mode
- - Dark Mode - Dark mode
- - System - Follow system settings
-
-#### 6.2 Organization Settings
-
-- **Organization Information Management**: Name, logo, etc.
-- **Website Settings**: Configure business website URL
-- **Member Management**: Manage team member permissions
-
-#### 6.3 Channels Settings
-
-- **Email Settings**: Configure email sending parameters
-- **Website Integration**: Website chatbot (in development)
-- **API Integration**: API interface configuration (in development)
-- **Teams Integration**: Team collaboration tools (in development)
-
-#### 6.4 Tone of Voice Settings
-
-- **Template Management**:
- - Product recommendation templates
- - Churn survey templates
- - Potential customer recommendation templates
-- **Tone Analysis**: Generate brand tone based on example emails
-- **Multi-language Templates**: Support creating multi-language content
-
-#### 6.5 Integrations Settings
-
-- **Shopify Integration**: Connect Shopify store
-- **Circuly Integration**: Connect Circuly platform
-- **Third-party Services**: Other business system integrations
-
-**Configuration Guide:**
-
-1. Upload brand email examples in tone of voice settings
-2. System automatically analyzes and generates brand tone description
-3. Create and manage various message templates
-4. Configure integration services to sync data
-
-### 7. AI Assistant (Ask AI)
-
-The AI Assistant is your intelligent business advisor, powered by advanced AI technology that understands your business data and can provide actionable insights, answer complex questions, and suggest optimization strategies. Think of it as having a data analyst and business consultant available 24/7.
-
-**What Can the AI Assistant Do?**
-The AI Assistant has access to your complete business data including customer information, product catalog, conversation history, and performance metrics. It can analyze patterns, identify trends, and provide recommendations based on your specific business context.
-
-**Intelligent Features:**
-
-- **Business Q&A**: Ask natural language questions about your business data and receive detailed, contextual answers. Examples: "Which products have the highest churn rate?" or "What's our customer acquisition trend this quarter?"
-
-- **Conversation History**: Maintains a complete record of your AI interactions, allowing you to reference previous analyses and build upon earlier insights for deeper understanding
-
-- **Intelligent Analysis**: Performs complex data analysis and pattern recognition to identify business opportunities, potential issues, and optimization areas you might not have considered
-
-- **Operation Suggestions**: Provides AI-powered recommendations for improving business processes, customer engagement strategies, and operational efficiency based on your data patterns
-
-**Usage Tips and Examples:**
-
-- **Customer Analytics**: "Show me customer retention rates by product category" or "Which customers are most likely to churn next month?"
-- **Business Performance**: "What's driving our recent sales increase?" or "Compare this quarter's performance to last quarter"
-- **Marketing Optimization**: "Which product recommendations have the highest conversion rates?" or "What's the best time to send churn surveys?"
-- **Operational Guidance**: "How can I improve our customer response times?" or "What automation opportunities exist in our workflow?"
-- **Trend Analysis**: "What seasonal patterns do you see in our customer behavior?" or "How has our product mix changed over time?"
-
-## Permission Management
-
-The system supports role-based access control:
-
-- **Owner** - Organization owner with full permissions
-- **Admin** - Administrator who can manage business settings
-- **Developer** - Developer with access to technical settings
-- **Member** - Regular member with basic operation permissions
-
-## Data Security
-
-- **Row Level Security**: Ensures users can only access their own business data
-- **Permission Verification**: All operations undergo strict permission checks
-- **Data Encryption**: Sensitive information is stored encrypted
-- **Audit Logs**: Records audit trails of important operations
-
-## Frequently Asked Questions
-
-**Q: How to import customer data?**
-A: Go to customer management page, click "Import Churned" button, select manual input or file upload method.
-
-**Q: How to set product recommendation relationships?**
-A: In the product management page, click the "Relationships" column of the product row to configure.
-
-**Q: How to configure email templates?**
-A: Go to Settings > Tone of Voice, select the corresponding template type to edit.
-
-**Q: What languages does the system support?**
-A: Supports English, German, French, Chinese, and other languages. Check the support list when importing customers.
-
-## Technical Support
-
-For technical issues or feature consultation, please contact the technical support team. The system will be continuously updated and optimized, with usage guidance provided for new features upon release.
diff --git a/docs/onedrive-background-sync.md b/docs/onedrive-background-sync.md
deleted file mode 100644
index c43f2a9da6..0000000000
--- a/docs/onedrive-background-sync.md
+++ /dev/null
@@ -1,302 +0,0 @@
-# OneDrive Background Sync
-
-This document explains how the OneDrive background sync system works, including how member credentials are stored and used for scheduled syncs.
-
-## Overview
-
-When a user enables auto-sync for OneDrive files or folders, the system stores:
-
-1. The OneDrive item configuration (file/folder ID, path, etc.)
-2. The **user ID** (Better Auth userId) of the member who enabled the sync
-3. Sync settings and status
-
-When a background sync job runs (via cron or scheduled workflow), it:
-
-1. Queries active sync configurations
-2. For each configuration, retrieves the Microsoft Graph access token for the **stored userId**
-3. Uses that user's credentials to sync files from OneDrive
-
-## Schema Changes
-
-### onedriveSyncConfigs Table
-
-The `onedriveSyncConfigs` table now includes a `userId` field:
-
-```typescript
-onedriveSyncConfigs: defineTable({
- organizationId: v.string(), // Better Auth organization ID
- userId: v.string(), // Better Auth user ID (whose credentials to use for sync)
- itemType: v.union(v.literal('file'), v.literal('folder')),
- itemId: v.string(), // OneDrive item ID
- itemName: v.string(), // File or folder name
- itemPath: v.optional(v.string()),
- targetBucket: v.string(),
- storagePrefix: v.optional(v.string()),
- status: v.union(
- v.literal('active'),
- v.literal('inactive'),
- v.literal('error'),
- ),
- lastSyncAt: v.optional(v.number()),
- lastSyncStatus: v.optional(v.string()),
- errorMessage: v.optional(v.string()),
- metadata: v.optional(v.any()),
-});
-```
-
-## How It Works
-
-### 1. User Enables Auto-Sync
-
-When a user enables auto-sync through the UI:
-
-```typescript
-import { enableAutoSync } from '@/actions/onedrive/config/enable-auto-sync';
-
-// User clicks "Enable Auto-Sync" on a folder
-const result = await enableAutoSync(organizationId, {
- itemType: 'folder',
- folderId: 'folder-123',
- folderName: 'Documents',
- folderPath: '/Documents',
- targetBucket: 'documents',
-});
-```
-
-The `enableAutoSync` action:
-
-1. Gets the current authenticated user
-2. Creates a sync configuration with the user's ID
-3. Stores it in the `onedriveSyncConfigs` table
-
-```typescript
-// Inside enableAutoSync
-const user = await getCurrentUser();
-if (!user) {
- return { success: false, error: 'User not authenticated' };
-}
-
-await fetchMutation(api.documents.createOneDriveSyncConfig, {
- organizationId: organizationId,
- userId: user._id, // Store the user's ID
- itemType: 'folder',
- itemId: params.folderId,
- itemName: params.folderName,
- // ... other fields
-});
-```
-
-### 2. Background Sync Job Runs
-
-When a background sync job (cron or scheduled workflow) runs:
-
-```typescript
-import { getMicrosoftGraphTokenForUser } from '@/lib/microsoft-graph-client-for-user';
-import { MicrosoftGraphClient } from '@/lib/microsoft-graph-client';
-
-// Get all active sync configurations
-const configs = await ctx.db
- .query('onedriveSyncConfigs')
- .withIndex('by_organizationId_and_status', (q) =>
- q.eq('organizationId', organizationId).eq('status', 'active'),
- )
- .collect();
-
-// Process each configuration
-for (const config of configs) {
- // Get Microsoft Graph token for the user who created this sync config
- const token = await getMicrosoftGraphTokenForUser(config.userId);
-
- if (!token) {
- console.error(`No token available for user ${config.userId}`);
- continue;
- }
-
- // Create Microsoft Graph client with the user's token
- const graphClient = new MicrosoftGraphClient(token);
-
- // Sync files using the user's credentials
- if (config.itemType === 'file') {
- const fileContent = await graphClient.readFile(config.itemId);
- // Upload to storage...
- } else {
- const files = await graphClient.listFiles({ folderId: config.itemId });
- // Process files...
- }
-}
-```
-
-### 3. Token Management
-
-The system automatically handles token refresh:
-
-```typescript
-// getMicrosoftGraphTokenForUser checks if token is expired
-export async function getMicrosoftGraphTokenForUser(
- userId: string,
-): Promise {
- // Query Microsoft account for the specific user
- const microsoftAccount = await fetchQuery(
- api.accounts.getMicrosoftAccountByUserId,
- { userId },
- );
-
- // Check if token is expired
- if (microsoftAccount.accessTokenExpiresAt < Date.now() + 5 * 60 * 1000) {
- // Refresh the token if expired
- const refreshed = await refreshMicrosoftTokenForUser(
- microsoftAccount.refreshToken,
- microsoftAccount.accountId,
- );
- return refreshed.accessToken;
- }
-
- return microsoftAccount.accessToken;
-}
-```
-
-## API Reference
-
-### New Functions
-
-#### `getMicrosoftGraphTokenForUser(userId: string)`
-
-Retrieves the Microsoft Graph access token for a specific user (not the current authenticated user).
-
-**Location:** `services/platform/lib/microsoft-graph-client-for-user.ts`
-
-**Usage:**
-
-```typescript
-import { getMicrosoftGraphTokenForUser } from '@/lib/microsoft-graph-client-for-user';
-
-const token = await getMicrosoftGraphTokenForUser('user-123');
-if (token) {
- // Use token to access Microsoft Graph API
-}
-```
-
-#### `api.accounts.getMicrosoftAccountByUserId`
-
-Convex query to get Microsoft OAuth account for a specific user.
-
-**Usage:**
-
-```typescript
-const account = await ctx.runQuery(api.accounts.getMicrosoftAccountByUserId, {
- userId: 'user-123',
-});
-```
-
-### Updated Functions
-
-#### `createOneDriveSyncConfig`
-
-Now requires `userId` parameter:
-
-```typescript
-await fetchMutation(api.documents.createOneDriveSyncConfig, {
- organizationId: 'org-123',
- userId: 'user-123', // NEW: Required field
- itemType: 'file',
- itemId: 'file-456',
- itemName: 'document.pdf',
- targetBucket: 'documents',
-});
-```
-
-#### `getOneDriveSyncConfigs`
-
-Now returns `userId` in the config objects:
-
-```typescript
-const result = await fetchQuery(api.documents.getOneDriveSyncConfigs, {
- organizationId: 'org-123',
- status: 'active',
-});
-
-// result.configs[0].userId is now available
-```
-
-## Example: Background Sync Workflow
-
-Here's a complete example of a background sync workflow:
-
-```typescript
-// services/platform/workflows/onedrive-sync.ts
-import type { InlineWorkflowDefinition } from './types';
-
-export const onedriveSyncWorkflow: InlineWorkflowDefinition = {
- workflowConfig: {
- name: 'OneDrive Auto Sync',
- description: 'Sync files from OneDrive based on active sync configurations',
- version: '1.0.0',
- workflowType: 'predefined',
- config: {
- timeout: 300000, // 5 minutes
- retryPolicy: { maxRetries: 3, backoffMs: 2000 },
- variables: {
- organizationId: 'org_demo',
- },
- },
- },
- stepsConfig: [
- {
- stepSlug: 'start',
- name: 'start',
- stepType: 'trigger',
- order: 1,
- config: {
- type: 'schedule',
- schedule: '0 */1 * * *', // Every hour
- timezone: 'UTC',
- },
- nextSteps: { success: 'get_sync_configs' },
- },
- {
- stepSlug: 'get_sync_configs',
- name: 'Get Active Sync Configurations',
- stepType: 'action',
- order: 2,
- config: {
- type: 'custom',
- // Query active sync configs and process each one
- },
- nextSteps: { success: 'sync_files' },
- },
- // ... more steps
- ],
-};
-```
-
-## Security Considerations
-
-1. **User Credentials**: Each sync configuration uses the credentials of the user who created it. If that user's Microsoft account is disconnected or their token expires and cannot be refreshed, the sync will fail.
-
-2. **Token Storage**: Microsoft Graph access tokens and refresh tokens are stored securely in the Better Auth accounts table.
-
-3. **Token Refresh**: The system automatically refreshes expired tokens before using them for sync operations.
-
-4. **Error Handling**: If a user's credentials are no longer valid, the sync configuration should be marked as 'error' status and the user should be notified to reconnect their Microsoft account.
-
-## Migration Notes
-
-If you have existing `onedriveSyncConfigs` records without a `userId` field, you'll need to:
-
-1. Run a migration to add the `userId` field to existing records
-2. Either assign a default user or mark them as inactive until a user re-enables them
-
-Example migration:
-
-```typescript
-// Mark all existing configs without userId as inactive
-const configs = await ctx.db.query('onedriveSyncConfigs').collect();
-for (const config of configs) {
- if (!config.userId) {
- await ctx.db.patch(config._id, {
- status: 'inactive',
- errorMessage: 'Please re-enable sync to assign user credentials',
- });
- }
-}
-```
diff --git a/docs/onedrive-debugging-guide.md b/docs/onedrive-debugging-guide.md
deleted file mode 100644
index 78e976da1f..0000000000
--- a/docs/onedrive-debugging-guide.md
+++ /dev/null
@@ -1,203 +0,0 @@
-# OneDrive Integration Debugging Guide
-
-## Overview
-
-This guide explains how to debug "item not found" errors and other issues in the OneDrive integration. The debugging system provides detailed logging and error tracking to help identify root causes.
-
-## Potential Causes of "Item Not Found" Error
-
-### 1. File/Folder Deletion
-- **Cause**: Items were deleted after being listed but before being accessed
-- **Symptoms**: Error occurs when clicking on specific files/folders
-- **Debug Info**: Check the debug logs for the specific file ID and name
-
-### 2. Permission Changes
-- **Cause**: User permissions changed between listing and accessing files
-- **Symptoms**: Intermittent access issues, especially in shared folders
-- **Debug Info**: Look for 403 Forbidden errors in the logs
-
-### 3. Invalid File IDs
-- **Cause**: File/folder IDs became invalid due to OneDrive sync issues
-- **Symptoms**: Consistent errors for specific items
-- **Debug Info**: Compare file IDs between different API calls
-
-### 4. Token Expiration
-- **Cause**: Microsoft access token expired during the session
-- **Symptoms**: Authentication errors, "session has expired" messages
-- **Debug Info**: Check for token expiration errors in logs
-
-### 5. Race Conditions
-- **Cause**: Multiple requests trying to access the same item simultaneously
-- **Symptoms**: Sporadic errors, especially during rapid navigation
-- **Debug Info**: Look for overlapping API calls in the logs
-
-### 6. OneDrive Sync Issues
-- **Cause**: Items not properly synced between OneDrive and Graph API
-- **Symptoms**: Files visible in OneDrive web but not accessible via API
-- **Debug Info**: Check for 404 errors with valid-looking file IDs
-
-## Debug Panel Features
-
-### Development Mode Only
-The debug panel only appears when `NODE_ENV=development` to avoid cluttering the production interface.
-
-### Real-time Logging
-- **API Calls**: All Microsoft Graph API requests are logged with timing
-- **Errors**: Detailed error information including status codes and messages
-- **User Actions**: File clicks, folder navigation, and search operations
-- **Authentication**: Token status and refresh attempts
-
-### Debug Information Displayed
-- Current folder ID
-- Authentication status
-- Total number of logs
-- Error count
-- Recent errors with expandable details
-- Complete log history (last 20 entries)
-
-### Interactive Features
-- **Expand/Collapse**: Click on log entries to see detailed information
-- **Copy to Clipboard**: Copy error details for sharing or analysis
-- **Clear Logs**: Reset the debug log history
-- **Refresh Auth**: Force authentication refresh
-
-## Enhanced Error Handling
-
-### Microsoft Graph Service Improvements
-- **Detailed Error Logging**: Captures HTTP status codes, error codes, and messages
-- **Performance Tracking**: Measures API call duration
-- **Enhanced Error Objects**: Includes additional context for debugging
-
-### Component-Level Debugging
-- **Operation Tracking**: Logs all user interactions and their outcomes
-- **Error Context**: Provides file names, IDs, and operation details
-- **Timing Information**: Tracks how long operations take
-
-## How to Use the Debug Panel
-
-### 1. Enable Development Mode
-```bash
-# Make sure you're running in development mode
-NODE_ENV=development npm run dev
-```
-
-### 2. Access the Debug Panel
-- Navigate to the OneDrive demo page
-- The debug panel will appear at the top of the page
-- Click the chevron icon to expand/collapse the panel
-
-### 3. Reproduce the Issue
-- Perform the actions that trigger the "item not found" error
-- Watch the debug logs populate in real-time
-- Note any error entries that appear
-
-### 4. Analyze the Logs
-- Look for error entries (red background)
-- Click on error entries to expand details
-- Check the timing of operations
-- Look for patterns in failed requests
-
-### 5. Common Debug Scenarios
-
-#### Scenario 1: File Access Error
-```json
-{
- "type": "error",
- "operation": "Failed to read file content",
- "details": {
- "fileId": "01BYE5RZ...",
- "fileName": "document.txt",
- "error": "Microsoft Graph API error: Item not found"
- }
-}
-```
-**Action**: Check if the file still exists in OneDrive web interface
-
-#### Scenario 2: Authentication Error
-```json
-{
- "type": "error",
- "operation": "Failed to load files",
- "details": {
- "error": "Your Microsoft session has expired. Please sign in again."
- }
-}
-```
-**Action**: Use the "Refresh Auth" button or reload the page
-
-#### Scenario 3: Permission Error
-```json
-{
- "type": "error",
- "operation": "Failed to load files",
- "details": {
- "error": "Microsoft Graph API error: Access denied",
- "folderId": "01BYE5RZ..."
- }
-}
-```
-**Action**: Check folder permissions in OneDrive
-
-## Troubleshooting Steps
-
-### Step 1: Check Authentication
-1. Look for authentication errors in the debug panel
-2. Verify the user is signed in with Microsoft
-3. Try refreshing authentication using the debug panel button
-
-### Step 2: Verify File/Folder Existence
-1. Note the file ID from the error logs
-2. Check if the file exists in OneDrive web interface
-3. Try accessing the file directly in OneDrive
-
-### Step 3: Check Permissions
-1. Verify the user has access to the folder/file
-2. Check if it's a shared folder with restricted access
-3. Try accessing as the file owner
-
-### Step 4: Monitor API Calls
-1. Watch the debug logs for API call patterns
-2. Look for failed requests and their error codes
-3. Check if errors are consistent or intermittent
-
-### Step 5: Test Different Scenarios
-1. Try different files and folders
-2. Test with different user accounts
-3. Compare behavior between file types
-
-## Production Considerations
-
-### Logging in Production
-- Debug panel is automatically hidden in production
-- Server-side logging still captures errors
-- Use application monitoring tools for production debugging
-
-### Error Handling
-- Users see friendly error messages
-- Detailed errors are logged server-side
-- Automatic retry mechanisms for transient errors
-
-### Performance
-- Debug logging has minimal performance impact
-- Logs are limited to prevent memory issues
-- Only essential information is captured in production
-
-## Getting Help
-
-If you continue to experience "item not found" errors:
-
-1. **Collect Debug Information**:
- - Copy error details from the debug panel
- - Note the specific files/folders affected
- - Record the sequence of actions that trigger the error
-
-2. **Check Microsoft Graph API Status**:
- - Visit the Microsoft 365 Service Health Dashboard
- - Look for known issues with OneDrive or Graph API
-
-3. **Contact Support**:
- - Provide the debug information collected
- - Include screenshots of the debug panel
- - Describe the user's OneDrive setup and permissions
-
-This debugging system should help identify the root cause of "item not found" errors and provide the information needed to resolve them effectively.
diff --git a/docs/onedrive-integration-guide.md b/docs/onedrive-integration-guide.md
deleted file mode 100644
index ab9c5fe662..0000000000
--- a/docs/onedrive-integration-guide.md
+++ /dev/null
@@ -1,565 +0,0 @@
-# OneDrive Integration Guide
-
-This guide explains how to use OneDrive file synchronization features in the frontend, including manual upload and automatic sync functionality.
-
-## Overview
-
-Our OneDrive integration provides two distinct sync methods:
-
-1. **Manual Upload (One-time)** - Direct file selection and immediate sync without persistent configuration
-2. **Auto Sync** - Persistent sync configurations that can be triggered manually or run automatically
-
-## 🔄 Manual Upload (One-time Sync)
-
-### What is Manual Upload?
-
-Manual upload allows users to browse OneDrive files, select specific files/folders, and sync them immediately to Supabase storage without creating any persistent auto-sync configuration.
-
-### Frontend Implementation
-
-#### 1. Using OneDrive File Browser Component
-
-```tsx
-import OneDriveFileBrowser from '@/components/onedrive/onedrive-file-browser';
-
-function DocumentsPage({ businessId }: { businessId: string }) {
- return (
-
-
Documents
-
-
- );
-}
-```
-
-#### 2. Using OneDrive Import Dialog
-
-```tsx
-import OneDriveImportDialog from '@/app/(app)/dashboard/[id]/documents/components/onedrive-import-dialog';
-
-function ImportButton({ businessId }: { businessId: string }) {
- const [isOpen, setIsOpen] = useState(false);
-
- const handleSuccess = () => {
- // Handle successful import
- setIsOpen(false);
- // Refresh your document list
- };
-
- return (
-
- );
-}
-```
-
-#### 3. Direct API Call (Advanced)
-
-```tsx
-async function syncSelectedFiles(
- businessId: string,
- selectedFiles: Array<{
- id: string;
- name: string;
- size?: number;
- relativePath?: string;
- }>,
-) {
- const response = await fetch('/api/documents/onedrive', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({
- items: selectedFiles,
- businessId,
- importType: 'one-time', // Important: Use 'one-time' for manual upload
- }),
- });
-
- if (!response.ok) {
- throw new Error('Sync failed');
- }
-
- // Handle streaming response
- const reader = response.body?.getReader();
- // Process SSE events...
-}
-```
-
-### Key Features
-
-- ✅ No persistent configuration required
-- ✅ Immediate file sync
-- ✅ User selects files directly from OneDrive browser
-- ✅ Real-time progress updates via SSE
-- ✅ Support for both files and folders
-
-## ⚙️ Auto Sync Configuration
-
-### What is Auto Sync?
-
-Auto sync creates persistent configurations that can sync OneDrive files/folders automatically on a schedule or be triggered manually. These configurations are stored in the `OneDriveAutoSync` table.
-
-### Frontend Implementation
-
-#### 1. Using Auto Sync Manager Component
-
-```tsx
-import AutoSyncManager from '@/components/onedrive/auto-sync-manager';
-
-function OneDriveSettingsPage({ businessId }: { businessId: string }) {
- return (
-