Răsfoiți Sursa

chore: cleanup docs and add ShopRenter OAuth improvements

- CLAUDE.md: Make paths generic, add docs for i18n/MCP/VAPI/custom content
- README.md: Simplify to reflect Supabase-only architecture
- Remove obsolete root docs, move relevant ones to docs/ folder
- Add ShopRenter OAuth flow translations (en/de/hu) for shop connection UI
- supabase/config.toml: Disable JWT verification for ShopRenter OAuth functions
- complete-shoprenter-install: Trigger initial data sync after shop connection

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Fszontagh 4 luni în urmă
părinte
comite
30c4f129c6

+ 57 - 15
CLAUDE.md

@@ -12,7 +12,7 @@ ShopCall.ai is an AI-powered calling system integrated with e-commerce platforms
 ## Repository Structure
 
 ```
-/data/shopcall/
+shopcall/
 ├── shopcall.ai-main/          # Frontend application
 │   ├── src/
 │   │   ├── components/        # React components
@@ -20,11 +20,13 @@ ShopCall.ai is an AI-powered calling system integrated with e-commerce platforms
 │   │   │   └── ui/            # shadcn-ui component library
 │   │   ├── pages/             # Route pages (Dashboard, Login, CallLogs, etc.)
 │   │   ├── hooks/             # Custom React hooks
+│   │   ├── i18n/              # Internationalization (i18next)
 │   │   ├── lib/               # Utility functions
 │   │   └── App.tsx            # Main application with routing
 │   └── package.json
 └── supabase/                   # Supabase Edge Functions
     └── functions/              # Backend API functions
+        └── _shared/           # Shared utilities across functions
 ```
 
 ## Development Commands
@@ -42,25 +44,23 @@ npm run preview          # Preview production build
 
 ### Supabase Edge Functions
 
-**Supabase CLI Location**: `~/bin/supabase` (run from `/home/claude/shopcall/supabase` directory)
-
 ```bash
-cd /home/claude/shopcall/supabase
+cd supabase
 
 # Deploy Edge Functions
-~/bin/supabase functions deploy <function-name>
+npx supabase functions deploy <function-name>
 
 # Deploy with project ref
-~/bin/supabase functions deploy <function-name> --project-ref ztklqodcdjeqpsvhlpud
+npx supabase functions deploy <function-name> --project-ref <project-ref>
 
 # Test locally
-~/bin/supabase functions serve
+npx supabase functions serve
 
 # Login (if needed)
-~/bin/supabase login
+npx supabase login
 
 # Link to project (if needed)
-~/bin/supabase link --project-ref ztklqodcdjeqpsvhlpud
+npx supabase link --project-ref <project-ref>
 ```
 
 ## Technology Stack
@@ -74,6 +74,7 @@ cd /home/claude/shopcall/supabase
 - **State Management**: React Query (@tanstack/react-query)
 - **Form Handling**: React Hook Form with Zod validation
 - **Theme**: next-themes for dark mode support
+- **i18n**: i18next with react-i18next for internationalization
 
 ### Backend
 - **Platform**: Supabase Edge Functions (Deno)
@@ -112,6 +113,12 @@ cd /home/claude/shopcall/supabase
 - UI components in `src/components/ui/` are reusable shadcn components
 - Context providers wrap the app in `App.tsx`
 
+**Internationalization (i18n)**:
+- Configuration: `src/i18n/config.ts`
+- Translations: `src/i18n/locales/` (JSON files per language)
+- Uses `i18next` with `react-i18next` and browser language detection
+- Access translations via `useTranslation()` hook: `const { t } = useTranslation()`
+
 ### Backend Architecture
 
 **Supabase Edge Functions**: Backend logic implemented as serverless Edge Functions
@@ -160,6 +167,41 @@ cd /home/claude/shopcall/supabase
   - Token refresh: Automatic access token refresh when expired
 - Store credentials in Supabase `stores` table
 
+**MCP Server Functions** (Model Context Protocol):
+- `mcp-shopify` - MCP server for Shopify data access
+- `mcp-woocommerce` - MCP server for WooCommerce data access
+- `mcp-shoprenter` - MCP server for ShopRenter data access
+- Shared utilities in `_shared/mcp-*.ts` (types, helpers, SSE)
+
+**VAPI Integration** (Voice AI):
+- `vapi-webhook` - Receives end-of-call reports from VAPI
+- Stores call transcripts, recordings, and analytics in `call_logs` table
+- See `docs/VAPI_INTEGRATION.md` for detailed documentation
+
+**Custom Content Management**:
+- `custom-content-create` - Create new custom content entries
+- `custom-content-upload` - Upload files (PDF, documents)
+- `custom-content-process` - Process and vectorize content
+- `custom-content-list` - List user's custom content
+- `custom-content-view` - View content details
+- `custom-content-delete` - Delete content
+- `custom-content-retry` - Retry failed processing
+- `custom-content-sync-status` - Check processing status
+
+**AI Context & Vector Search**:
+- `get-ai-context` - Build AI context from store data and custom content
+- Uses Qdrant for vector storage (`_shared/qdrant-client.ts`)
+- Text chunking and embedding (`_shared/text-chunker.ts`)
+- PDF processing (`_shared/pdf-processor.ts`)
+
+**Shared Utilities** (`supabase/functions/_shared/`):
+- `cors.ts` - CORS headers handling
+- `error-handler.ts` - Standardized error responses
+- `unified-response.ts` - Consistent API response format
+- `api-key-auth.ts` - API key authentication
+- `platform-adapters.ts` - E-commerce platform data normalization
+- `access-policy-helpers.ts` - GDPR data access policy enforcement
+
 ### Database Schema (Supabase)
 
 **stores table**:
@@ -679,13 +721,13 @@ Both values should be non-NULL.
 
 **Deploying Edge Functions via CLI:**
 ```bash
-cd /home/claude/shopcall/supabase
+cd supabase
 
 # Deploy a specific function
-~/bin/supabase functions deploy <function-name> --project-ref ztklqodcdjeqpsvhlpud
+npx supabase functions deploy <function-name> --project-ref <project-ref>
 
 # Deploy multiple functions
-~/bin/supabase functions deploy api oauth-woocommerce oauth-shopify --project-ref ztklqodcdjeqpsvhlpud
+npx supabase functions deploy api oauth-woocommerce oauth-shopify --project-ref <project-ref>
 ```
 
 **Checking Deployment Status:**
@@ -729,13 +771,13 @@ When making changes:
 
 2. **Via CLI** (alternative, requires manual authentication):
    ```bash
-   cd /home/claude/shopcall/supabase
+   cd supabase
 
    # Deploy a specific function
-   ~/bin/supabase functions deploy <function-name> --project-ref ztklqodcdjeqpsvhlpud
+   npx supabase functions deploy <function-name> --project-ref <project-ref>
 
    # Deploy multiple functions at once
-   ~/bin/supabase functions deploy oauth-woocommerce oauth-shopify api --project-ref ztklqodcdjeqpsvhlpud
+   npx supabase functions deploy oauth-woocommerce oauth-shopify api --project-ref <project-ref>
    ```
 
 3. **Verify deployment**:

+ 0 - 1198
CUSTOM_CONTENT_IMPLEMENTATION_GUIDE.md

@@ -1,1198 +0,0 @@
-# Custom Content RAG Feature - Implementation Guide
-
-## Overview
-
-This guide covers the remaining implementation steps for the Custom Content RAG feature, which allows users to upload PDFs and create text entries that are stored in Qdrant for AI-powered semantic search.
-
-## ✅ Completed Backend Implementation
-
-### 1. Database & Storage
-- **Migration applied**: `custom_content` table created with all fields
-- **Storage bucket**: `custom-content` bucket configured with RLS policies
-- **Indexes**: Performance indexes on store_id, user_id, content_type, sync_status
-- **Functions**: `get_custom_content_stats()` helper function
-
-### 2. Shared Utilities
-- `_shared/pdf-processor.ts` - PDF text extraction, SHA-256 checksum, validation
-- `_shared/text-chunker.ts` - Hybrid chunking (single vs overlapping chunks)
-- `_shared/qdrant-client.ts` - Extended with custom content methods:
-  - `syncCustomContent()` - Stores chunks in Qdrant
-  - `deleteCustomContent()` - Removes from Qdrant
-  - `searchCustomContent()` - Semantic search
-  - `getCustomContentCollectionName()` - Collection naming
-- `_shared/mcp-qdrant-helpers.ts` - Extended with `queryQdrantCustomContent()`
-
-### 3. Edge Functions (All Deployed ✅)
-- `custom-content-upload` - Multipart file upload with deduplication
-- `custom-content-process` - Async PDF processing pipeline
-- `custom-content-create` - Text entry creation
-- `custom-content-list` - List all content for a store
-- `custom-content-delete` - Hard delete from all systems
-- `custom-content-sync-status` - Real-time status polling
-
-All functions are deployed and accessible at:
-`https://ztklqodcdjeqpsvhlpud.supabase.co/functions/v1/custom-content-*`
-
----
-
-## 🔄 Remaining Backend Work
-
-### MCP Tool Integration
-
-The `shopify_search_custom_content` tool has been added to `mcp-shopify`. The same needs to be done for `mcp-woocommerce` and `mcp-shoprenter`.
-
-#### For `mcp-woocommerce/index.ts`:
-
-**1. Update imports** (around line 40):
-```typescript
-import {
-  getStoreQdrantConfig,
-  queryQdrantProducts,
-  queryQdrantOrders,
-  queryQdrantCustomers,
-  queryQdrantCustomContent  // ADD THIS LINE
-} from '../_shared/mcp-qdrant-helpers.ts';
-```
-
-**2. Add tool definition to TOOLS array** (before closing `]`):
-```typescript
-  {
-    name: 'woocommerce_search_custom_content',
-    description: 'Search custom knowledge base (uploaded PDFs and text entries) for relevant information using semantic search. Returns matching content with titles, excerpts, and relevance scores. Use this to find custom documentation, policies, FAQs, or any store-specific information that has been uploaded.',
-    inputSchema: {
-      type: 'object',
-      properties: {
-        shop_id: {
-          type: 'string',
-          description: 'The UUID of the WooCommerce store from the stores table'
-        },
-        query: {
-          type: 'string',
-          description: 'The search query to find relevant content'
-        },
-        limit: {
-          type: 'number',
-          description: 'Number of results to return (default: 5, max: 10)'
-        }
-      },
-      required: ['shop_id', 'query']
-    }
-  }
-```
-
-**3. Add handler function** (before `handleToolCall` function):
-```typescript
-/**
- * Handle custom content search
- */
-async function handleSearchCustomContent(args: Record<string, any>): Promise<ToolCallResult> {
-  const { shop_id, query, limit = 5 } = args;
-
-  try {
-    // Get store config for Qdrant connection
-    const qdrantConfig = await getStoreQdrantConfig(shop_id);
-
-    if (!qdrantConfig) {
-      return {
-        content: [{
-          type: 'text',
-          text: JSON.stringify({
-            error: 'Store configuration not found'
-          })
-        }],
-        isError: true
-      };
-    }
-
-    // Query custom content from Qdrant
-    const results = await queryQdrantCustomContent(
-      shop_id,
-      qdrantConfig.shopname,
-      query,
-      Math.min(limit, 10) // Max 10 results
-    );
-
-    if (results.length === 0) {
-      return {
-        content: [{
-          type: 'text',
-          text: JSON.stringify({
-            message: 'No custom content found matching your query',
-            results: []
-          })
-        }],
-        isError: false
-      };
-    }
-
-    return {
-      content: [{
-        type: 'text',
-        text: JSON.stringify({
-          results: results.map(r => ({
-            id: r.id,
-            title: r.title,
-            content_type: r.contentType,
-            excerpt: r.excerpt,
-            chunk_info: `Chunk ${r.chunkIndex + 1} of ${r.totalChunks}`,
-            relevance_score: Math.round(r.relevanceScore * 100) / 100,
-            original_filename: r.originalFilename,
-            page_count: r.pageCount
-          })),
-          total: results.length
-        })
-      }],
-      isError: false
-    };
-  } catch (error: any) {
-    console.error('[MCP WooCommerce] Error searching custom content:', error);
-    return {
-      content: [{
-        type: 'text',
-        text: JSON.stringify({ error: `Failed to search custom content: ${error instanceof Error ? error.message : 'Unknown error'}` })
-      }],
-      isError: true
-    };
-  }
-}
-```
-
-**4. Add case to switch statement** (in `handleToolCall`, before default case):
-```typescript
-    case 'woocommerce_search_custom_content':
-      const customContentValidation = validateParams(args, ['shop_id', 'query']);
-      if (!customContentValidation.valid) {
-        return {
-          content: [{
-            type: 'text',
-            text: JSON.stringify({
-              error: `Missing required parameters: ${customContentValidation.missing?.join(', ')}`
-            })
-          }],
-          isError: true
-        };
-      }
-      return await handleSearchCustomContent(args);
-```
-
-#### For `mcp-shoprenter/index.ts`:
-
-Apply the **exact same changes** as WooCommerce, but replace:
-- `woocommerce_search_custom_content` → `shoprenter_search_custom_content`
-- `'WooCommerce store'` → `'ShopRenter store'`
-- `'[MCP WooCommerce]'` → `'[MCP ShopRenter]'`
-
-#### Deploy MCP Changes:
-```bash
-cd /data/shopcall/supabase
-npx supabase functions deploy mcp-shopify mcp-woocommerce mcp-shoprenter --project-ref ztklqodcdjeqpsvhlpud
-```
-
----
-
-## 📱 Frontend Implementation Guide
-
-### Overview
-Create a new page `/custom-content` under the AI Configuration menu where users can:
-- Upload PDF files (with duplicate detection)
-- Create text entries
-- View all custom content with sync status
-- Delete content
-- See real-time processing status
-
-### File Structure
-```
-shopcall.ai-main/src/
-├── pages/
-│   └── CustomContent.tsx (main page)
-├── components/
-│   ├── CustomContentManager.tsx (container component)
-│   ├── CustomContentUpload.tsx (file upload UI)
-│   ├── CustomContentTextEntry.tsx (text entry form)
-│   ├── CustomContentList.tsx (content table/list)
-│   └── CustomContentStatusBadge.tsx (status indicator)
-└── App.tsx (add route)
-```
-
-### Step 1: Create Main Page Component
-
-**File**: `shopcall.ai-main/src/pages/CustomContent.tsx`
-
-```typescript
-import { CustomContentManager } from "@/components/CustomContentManager";
-
-export default function CustomContent() {
-  return (
-    <div className="flex flex-col gap-6 p-6">
-      <div>
-        <h1 className="text-3xl font-bold">Custom Content</h1>
-        <p className="text-muted-foreground mt-2">
-          Upload PDFs and create text entries for your AI assistant's knowledge base
-        </p>
-      </div>
-      <CustomContentManager />
-    </div>
-  );
-}
-```
-
-### Step 2: Create Manager Component
-
-**File**: `shopcall.ai-main/src/components/CustomContentManager.tsx`
-
-```typescript
-import { useState } from "react";
-import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
-import { Button } from "@/components/ui/button";
-import { FileUp, FileText, Plus } from "lucide-react";
-import { CustomContentUpload } from "./CustomContentUpload";
-import { CustomContentTextEntry } from "./CustomContentTextEntry";
-import { CustomContentList } from "./CustomContentList";
-import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
-
-export function CustomContentManager() {
-  const [showUpload, setShowUpload] = useState(false);
-  const [showTextEntry, setShowTextEntry] = useState(false);
-  const [activeTab, setActiveTab] = useState<string>("all");
-  const [refreshKey, setRefreshKey] = useState(0);
-
-  const handleUploadSuccess = () => {
-    setShowUpload(false);
-    setRefreshKey(prev => prev + 1); // Trigger list refresh
-  };
-
-  const handleTextEntrySuccess = () => {
-    setShowTextEntry(false);
-    setRefreshKey(prev => prev + 1); // Trigger list refresh
-  };
-
-  return (
-    <div className="space-y-4">
-      {/* Action Buttons */}
-      <div className="flex gap-2">
-        <Dialog open={showUpload} onOpenChange={setShowUpload}>
-          <DialogTrigger asChild>
-            <Button>
-              <FileUp className="mr-2 h-4 w-4" />
-              Upload PDF
-            </Button>
-          </DialogTrigger>
-          <DialogContent className="max-w-2xl">
-            <CustomContentUpload onSuccess={handleUploadSuccess} />
-          </DialogContent>
-        </Dialog>
-
-        <Dialog open={showTextEntry} onOpenChange={setShowTextEntry}>
-          <DialogTrigger asChild>
-            <Button variant="outline">
-              <Plus className="mr-2 h-4 w-4" />
-              Add Text Entry
-            </Button>
-          </DialogTrigger>
-          <DialogContent className="max-w-2xl">
-            <CustomContentTextEntry onSuccess={handleTextEntrySuccess} />
-          </DialogContent>
-        </Dialog>
-      </div>
-
-      {/* Tabs */}
-      <Tabs value={activeTab} onValueChange={setActiveTab}>
-        <TabsList>
-          <TabsTrigger value="all">All Content</TabsTrigger>
-          <TabsTrigger value="pdf_upload">PDFs</TabsTrigger>
-          <TabsTrigger value="text_entry">Text Entries</TabsTrigger>
-        </TabsList>
-
-        <TabsContent value="all" className="mt-4">
-          <CustomContentList
-            contentType={undefined}
-            refreshKey={refreshKey}
-            onDelete={() => setRefreshKey(prev => prev + 1)}
-          />
-        </TabsContent>
-
-        <TabsContent value="pdf_upload" className="mt-4">
-          <CustomContentList
-            contentType="pdf_upload"
-            refreshKey={refreshKey}
-            onDelete={() => setRefreshKey(prev => prev + 1)}
-          />
-        </TabsContent>
-
-        <TabsContent value="text_entry" className="mt-4">
-          <CustomContentList
-            contentType="text_entry"
-            refreshKey={refreshKey}
-            onDelete={() => setRefreshKey(prev => prev + 1)}
-          />
-        </TabsContent>
-      </Tabs>
-    </div>
-  );
-}
-```
-
-### Step 3: Create File Upload Component
-
-**File**: `shopcall.ai-main/src/components/CustomContentUpload.tsx`
-
-```typescript
-import { useState, useCallback } from "react";
-import { useDropzone } from "react-dropzone";
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-import { Label } from "@/components/ui/label";
-import { Alert, AlertDescription } from "@/components/ui/alert";
-import { Progress } from "@/components/ui/progress";
-import { Upload, FileText, AlertCircle, CheckCircle2 } from "lucide-react";
-import { useToast } from "@/hooks/use-toast";
-
-interface CustomContentUploadProps {
-  onSuccess: () => void;
-}
-
-export function CustomContentUpload({ onSuccess }: CustomContentUploadProps) {
-  const [file, setFile] = useState<File | null>(null);
-  const [title, setTitle] = useState("");
-  const [uploading, setUploading] = useState(false);
-  const [progress, setProgress] = useState(0);
-  const [error, setError] = useState<string | null>(null);
-  const { toast } = useToast();
-
-  // Get selected shop from context (implement based on your app's shop selector)
-  const selectedShop = "your-shop-id"; // TODO: Get from context
-
-  const onDrop = useCallback((acceptedFiles: File[]) => {
-    if (acceptedFiles.length > 0) {
-      const uploadedFile = acceptedFiles[0];
-      setFile(uploadedFile);
-      // Auto-fill title with filename (without extension)
-      const fileName = uploadedFile.name.replace(/\\.pdf$/i, "");
-      setTitle(fileName);
-      setError(null);
-    }
-  }, []);
-
-  const { getRootProps, getInputProps, isDragActive } = useDropzone({
-    onDrop,
-    accept: {
-      'application/pdf': ['.pdf']
-    },
-    maxFiles: 1,
-    maxSize: 10 * 1024 * 1024, // 10MB
-  });
-
-  const handleUpload = async () => {
-    if (!file || !title.trim()) {
-      setError("Please select a file and provide a title");
-      return;
-    }
-
-    setUploading(true);
-    setError(null);
-    setProgress(10);
-
-    try {
-      // Create FormData
-      const formData = new FormData();
-      formData.append("file", file);
-      formData.append("title", title.trim());
-      formData.append("store_id", selectedShop);
-
-      setProgress(30);
-
-      // Get auth token
-      const { data: { session } } = await supabase.auth.getSession();
-      if (!session) {
-        throw new Error("Not authenticated");
-      }
-
-      setProgress(50);
-
-      // Upload to Edge Function
-      const response = await fetch(
-        `${import.meta.env.VITE_API_URL}/custom-content-upload`,
-        {
-          method: "POST",
-          headers: {
-            Authorization: `Bearer ${session.access_token}`,
-          },
-          body: formData,
-        }
-      );
-
-      setProgress(80);
-
-      const result = await response.json();
-
-      if (!response.ok) {
-        if (result.duplicate) {
-          throw new Error(
-            `This file already exists as "${result.existingContent.title}" (uploaded on ${result.existingContent.uploadedAt})`
-          );
-        }
-        throw new Error(result.error || "Upload failed");
-      }
-
-      setProgress(100);
-
-      toast({
-        title: "Upload successful",
-        description: `${result.fileName} is being processed. This may take a few moments.`,
-      });
-
-      onSuccess();
-    } catch (err: any) {
-      console.error("Upload error:", err);
-      setError(err.message || "Failed to upload file");
-      toast({
-        title: "Upload failed",
-        description: err.message || "An error occurred during upload",
-        variant: "destructive",
-      });
-    } finally {
-      setUploading(false);
-      setProgress(0);
-    }
-  };
-
-  return (
-    <div className="space-y-4">
-      <div>
-        <h2 className="text-lg font-semibold">Upload PDF</h2>
-        <p className="text-sm text-muted-foreground">
-          Upload a PDF file to add to your AI assistant's knowledge base
-        </p>
-      </div>
-
-      {/* File Dropzone */}
-      <div
-        {...getRootProps()}
-        className={`
-          border-2 border-dashed rounded-lg p-8 text-center cursor-pointer
-          transition-colors
-          ${isDragActive ? "border-primary bg-primary/5" : "border-gray-300"}
-          ${file ? "bg-muted" : ""}
-        `}
-      >
-        <input {...getInputProps()} />
-        {file ? (
-          <div className="flex items-center justify-center gap-2">
-            <FileText className="h-8 w-8 text-primary" />
-            <div className="text-left">
-              <p className="font-medium">{file.name}</p>
-              <p className="text-sm text-muted-foreground">
-                {(file.size / 1024 / 1024).toFixed(2)} MB
-              </p>
-            </div>
-          </div>
-        ) : (
-          <div>
-            <Upload className="h-12 w-12 mx-auto text-muted-foreground mb-2" />
-            <p className="text-sm">
-              {isDragActive
-                ? "Drop the PDF file here"
-                : "Drag and drop a PDF file here, or click to select"}
-            </p>
-            <p className="text-xs text-muted-foreground mt-1">
-              Maximum file size: 10MB
-            </p>
-          </div>
-        )}
-      </div>
-
-      {/* Title Input */}
-      <div className="space-y-2">
-        <Label htmlFor="title">Title *</Label>
-        <Input
-          id="title"
-          value={title}
-          onChange={(e) => setTitle(e.target.value)}
-          placeholder="Enter a descriptive title"
-          disabled={uploading}
-        />
-      </div>
-
-      {/* Progress Bar */}
-      {uploading && (
-        <div className="space-y-2">
-          <Progress value={progress} />
-          <p className="text-sm text-center text-muted-foreground">
-            Uploading... {progress}%
-          </p>
-        </div>
-      )}
-
-      {/* Error Alert */}
-      {error && (
-        <Alert variant="destructive">
-          <AlertCircle className="h-4 w-4" />
-          <AlertDescription>{error}</AlertDescription>
-        </Alert>
-      )}
-
-      {/* Action Buttons */}
-      <div className="flex justify-end gap-2">
-        <Button
-          variant="outline"
-          onClick={() => onSuccess()}
-          disabled={uploading}
-        >
-          Cancel
-        </Button>
-        <Button
-          onClick={handleUpload}
-          disabled={!file || !title.trim() || uploading}
-        >
-          {uploading ? "Uploading..." : "Upload"}
-        </Button>
-      </div>
-    </div>
-  );
-}
-```
-
-### Step 4: Create Text Entry Component
-
-**File**: `shopcall.ai-main/src/components/CustomContentTextEntry.tsx`
-
-```typescript
-import { useState } from "react";
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-import { Label } from "@/components/ui/label";
-import { Textarea } from "@/components/ui/textarea";
-import { Alert, AlertDescription } from "@/components/ui/alert";
-import { AlertCircle } from "lucide-react";
-import { useToast } from "@/hooks/use-toast";
-
-interface CustomContentTextEntryProps {
-  onSuccess: () => void;
-}
-
-export function CustomContentTextEntry({ onSuccess }: CustomContentTextEntryProps) {
-  const [title, setTitle] = useState("");
-  const [content, setContent] = useState("");
-  const [saving, setSaving] = useState(false);
-  const [error, setError] = useState<string | null>(null);
-  const { toast } = useToast();
-
-  // Get selected shop from context
-  const selectedShop = "your-shop-id"; // TODO: Get from context
-
-  const handleSave = async () => {
-    if (!title.trim() || !content.trim()) {
-      setError("Please provide both title and content");
-      return;
-    }
-
-    if (content.length > 50000) {
-      setError("Content exceeds maximum length of 50,000 characters");
-      return;
-    }
-
-    setSaving(true);
-    setError(null);
-
-    try {
-      // Get auth token
-      const { data: { session } } = await supabase.auth.getSession();
-      if (!session) {
-        throw new Error("Not authenticated");
-      }
-
-      // Create entry via Edge Function
-      const response = await fetch(
-        `${import.meta.env.VITE_API_URL}/custom-content-create`,
-        {
-          method: "POST",
-          headers: {
-            Authorization: `Bearer ${session.access_token}`,
-            "Content-Type": "application/json",
-          },
-          body: JSON.stringify({
-            title: title.trim(),
-            content_text: content.trim(),
-            store_id: selectedShop,
-          }),
-        }
-      );
-
-      const result = await response.json();
-
-      if (!response.ok) {
-        throw new Error(result.error || "Failed to create entry");
-      }
-
-      toast({
-        title: "Entry created",
-        description: `"${title}" has been added to your knowledge base`,
-      });
-
-      onSuccess();
-    } catch (err: any) {
-      console.error("Create error:", err);
-      setError(err.message || "Failed to create entry");
-      toast({
-        title: "Creation failed",
-        description: err.message || "An error occurred",
-        variant: "destructive",
-      });
-    } finally {
-      setSaving(false);
-    }
-  };
-
-  return (
-    <div className="space-y-4">
-      <div>
-        <h2 className="text-lg font-semibold">Add Text Entry</h2>
-        <p className="text-sm text-muted-foreground">
-          Create a custom text entry for your AI assistant's knowledge base
-        </p>
-      </div>
-
-      {/* Title Input */}
-      <div className="space-y-2">
-        <Label htmlFor="entry-title">Title *</Label>
-        <Input
-          id="entry-title"
-          value={title}
-          onChange={(e) => setTitle(e.target.value)}
-          placeholder="Enter a title"
-          disabled={saving}
-        />
-      </div>
-
-      {/* Content Textarea */}
-      <div className="space-y-2">
-        <Label htmlFor="entry-content">Content *</Label>
-        <Textarea
-          id="entry-content"
-          value={content}
-          onChange={(e) => setContent(e.target.value)}
-          placeholder="Enter your content here..."
-          rows={12}
-          disabled={saving}
-          className="resize-none"
-        />
-        <p className="text-xs text-muted-foreground text-right">
-          {content.length.toLocaleString()} / 50,000 characters
-        </p>
-      </div>
-
-      {/* Error Alert */}
-      {error && (
-        <Alert variant="destructive">
-          <AlertCircle className="h-4 w-4" />
-          <AlertDescription>{error}</AlertDescription>
-        </Alert>
-      )}
-
-      {/* Action Buttons */}
-      <div className="flex justify-end gap-2">
-        <Button
-          variant="outline"
-          onClick={() => onSuccess()}
-          disabled={saving}
-        >
-          Cancel
-        </Button>
-        <Button
-          onClick={handleSave}
-          disabled={!title.trim() || !content.trim() || saving}
-        >
-          {saving ? "Saving..." : "Save"}
-        </Button>
-      </div>
-    </div>
-  );
-}
-```
-
-### Step 5: Create Content List Component
-
-**File**: `shopcall.ai-main/src/components/CustomContentList.tsx`
-
-```typescript
-import { useEffect, useState } from "react";
-import { useQuery } from "@tanstack/react-query";
-import {
-  Table,
-  TableBody,
-  TableCell,
-  TableHead,
-  TableHeader,
-  TableRow,
-} from "@/components/ui/table";
-import { Button } from "@/components/ui/button";
-import { Trash2, FileText, File } from "lucide-react";
-import { CustomContentStatusBadge } from "./CustomContentStatusBadge";
-import { useToast } from "@/hooks/use-toast";
-import {
-  AlertDialog,
-  AlertDialogAction,
-  AlertDialogCancel,
-  AlertDialogContent,
-  AlertDialogDescription,
-  AlertDialogFooter,
-  AlertDialogHeader,
-  AlertDialogTitle,
-} from "@/components/ui/alert-dialog";
-
-interface CustomContentListProps {
-  contentType?: "text_entry" | "pdf_upload";
-  refreshKey: number;
-  onDelete: () => void;
-}
-
-interface ContentItem {
-  id: string;
-  title: string;
-  contentType: string;
-  originalFilename?: string;
-  fileSize?: number;
-  pageCount?: number;
-  chunkCount: number;
-  syncStatus: string;
-  syncError?: string;
-  createdAt: string;
-}
-
-export function CustomContentList({
-  contentType,
-  refreshKey,
-  onDelete
-}: CustomContentListProps) {
-  const [deleteId, setDeleteId] = useState<string | null>(null);
-  const { toast } = useToast();
-
-  // Get selected shop from context
-  const selectedShop = "your-shop-id"; // TODO: Get from context
-
-  // Fetch content list
-  const { data, isLoading, refetch } = useQuery({
-    queryKey: ["custom-content", selectedShop, contentType, refreshKey],
-    queryFn: async () => {
-      const { data: { session } } = await supabase.auth.getSession();
-      if (!session) throw new Error("Not authenticated");
-
-      const params = new URLSearchParams({
-        store_id: selectedShop,
-        ...(contentType && { content_type: contentType }),
-      });
-
-      const response = await fetch(
-        `${import.meta.env.VITE_API_URL}/custom-content-list?${params}`,
-        {
-          headers: {
-            Authorization: `Bearer ${session.access_token}`,
-          },
-        }
-      );
-
-      if (!response.ok) {
-        throw new Error("Failed to fetch content");
-      }
-
-      const result = await response.json();
-      return result.content as ContentItem[];
-    },
-    enabled: !!selectedShop,
-  });
-
-  // Refetch on refreshKey change
-  useEffect(() => {
-    if (refreshKey > 0) {
-      refetch();
-    }
-  }, [refreshKey, refetch]);
-
-  const handleDelete = async (id: string) => {
-    try {
-      const { data: { session } } = await supabase.auth.getSession();
-      if (!session) throw new Error("Not authenticated");
-
-      const response = await fetch(
-        `${import.meta.env.VITE_API_URL}/custom-content-delete`,
-        {
-          method: "DELETE",
-          headers: {
-            Authorization: `Bearer ${session.access_token}`,
-            "Content-Type": "application/json",
-          },
-          body: JSON.stringify({
-            content_id: id,
-            store_id: selectedShop,
-          }),
-        }
-      );
-
-      if (!response.ok) {
-        throw new Error("Failed to delete content");
-      }
-
-      toast({
-        title: "Content deleted",
-        description: "The content has been removed from your knowledge base",
-      });
-
-      onDelete();
-    } catch (err: any) {
-      toast({
-        title: "Deletion failed",
-        description: err.message || "An error occurred",
-        variant: "destructive",
-      });
-    } finally {
-      setDeleteId(null);
-    }
-  };
-
-  if (isLoading) {
-    return <div className="text-center py-8">Loading...</div>;
-  }
-
-  if (!data || data.length === 0) {
-    return (
-      <div className="text-center py-8 text-muted-foreground">
-        No custom content yet. Upload a PDF or create a text entry to get started.
-      </div>
-    );
-  }
-
-  return (
-    <>
-      <Table>
-        <TableHeader>
-          <TableRow>
-            <TableHead>Type</TableHead>
-            <TableHead>Title</TableHead>
-            <TableHead>Details</TableHead>
-            <TableHead>Status</TableHead>
-            <TableHead>Chunks</TableHead>
-            <TableHead>Created</TableHead>
-            <TableHead className="text-right">Actions</TableHead>
-          </TableRow>
-        </TableHeader>
-        <TableBody>
-          {data.map((item) => (
-            <TableRow key={item.id}>
-              <TableCell>
-                {item.contentType === "pdf_upload" ? (
-                  <File className="h-4 w-4 text-red-500" />
-                ) : (
-                  <FileText className="h-4 w-4 text-blue-500" />
-                )}
-              </TableCell>
-              <TableCell className="font-medium">{item.title}</TableCell>
-              <TableCell className="text-sm text-muted-foreground">
-                {item.contentType === "pdf_upload" ? (
-                  <div>
-                    <div>{item.originalFilename}</div>
-                    <div>
-                      {item.pageCount} pages • {(item.fileSize! / 1024).toFixed(0)} KB
-                    </div>
-                  </div>
-                ) : (
-                  <div>Text entry</div>
-                )}
-              </TableCell>
-              <TableCell>
-                <CustomContentStatusBadge
-                  contentId={item.id}
-                  status={item.syncStatus}
-                  error={item.syncError}
-                />
-              </TableCell>
-              <TableCell>{item.chunkCount || 0}</TableCell>
-              <TableCell>
-                {new Date(item.createdAt).toLocaleDateString()}
-              </TableCell>
-              <TableCell className="text-right">
-                <Button
-                  variant="ghost"
-                  size="icon"
-                  onClick={() => setDeleteId(item.id)}
-                >
-                  <Trash2 className="h-4 w-4" />
-                </Button>
-              </TableCell>
-            </TableRow>
-          ))}
-        </TableBody>
-      </Table>
-
-      {/* Delete Confirmation Dialog */}
-      <AlertDialog open={!!deleteId} onOpenChange={() => setDeleteId(null)}>
-        <AlertDialogContent>
-          <AlertDialogHeader>
-            <AlertDialogTitle>Delete content?</AlertDialogTitle>
-            <AlertDialogDescription>
-              This will permanently remove the content from your knowledge base and cannot be undone.
-            </AlertDialogDescription>
-          </AlertDialogHeader>
-          <AlertDialogFooter>
-            <AlertDialogCancel>Cancel</AlertDialogCancel>
-            <AlertDialogAction
-              onClick={() => deleteId && handleDelete(deleteId)}
-              className="bg-destructive text-destructive-foreground"
-            >
-              Delete
-            </AlertDialogAction>
-          </AlertDialogFooter>
-        </AlertDialogContent>
-      </AlertDialog>
-    </>
-  );
-}
-```
-
-### Step 6: Create Status Badge Component
-
-**File**: `shopcall.ai-main/src/components/CustomContentStatusBadge.tsx`
-
-```typescript
-import { useEffect, useState } from "react";
-import { Badge } from "@/components/ui/badge";
-import { Loader2, CheckCircle2, AlertCircle, Clock } from "lucide-react";
-import {
-  Tooltip,
-  TooltipContent,
-  TooltipProvider,
-  TooltipTrigger,
-} from "@/components/ui/tooltip";
-
-interface CustomContentStatusBadgeProps {
-  contentId: string;
-  status: string;
-  error?: string;
-}
-
-export function CustomContentStatusBadge({
-  contentId,
-  status: initialStatus,
-  error,
-}: CustomContentStatusBadgeProps) {
-  const [status, setStatus] = useState(initialStatus);
-  const [polling, setPolling] = useState(
-    initialStatus === "pending" || initialStatus === "processing"
-  );
-
-  useEffect(() => {
-    if (!polling) return;
-
-    const pollStatus = async () => {
-      try {
-        const { data: { session } } = await supabase.auth.getSession();
-        if (!session) return;
-
-        const response = await fetch(
-          `${import.meta.env.VITE_API_URL}/custom-content-sync-status?content_id=${contentId}`,
-          {
-            headers: {
-              Authorization: `Bearer ${session.access_token}`,
-            },
-          }
-        );
-
-        if (response.ok) {
-          const result = await response.json();
-          setStatus(result.status);
-
-          // Stop polling if completed or failed
-          if (result.status === "completed" || result.status === "failed") {
-            setPolling(false);
-          }
-        }
-      } catch (err) {
-        console.error("Status poll error:", err);
-      }
-    };
-
-    // Poll every 3 seconds
-    const interval = setInterval(pollStatus, 3000);
-    pollStatus(); // Initial poll
-
-    return () => clearInterval(interval);
-  }, [contentId, polling]);
-
-  const getStatusDisplay = () => {
-    switch (status) {
-      case "pending":
-        return {
-          label: "Pending",
-          icon: <Clock className="h-3 w-3" />,
-          variant: "secondary" as const,
-          tooltip: "Waiting to start processing",
-        };
-      case "processing":
-        return {
-          label: "Processing",
-          icon: <Loader2 className="h-3 w-3 animate-spin" />,
-          variant: "default" as const,
-          tooltip: "Extracting text and generating embeddings",
-        };
-      case "completed":
-        return {
-          label: "Ready",
-          icon: <CheckCircle2 className="h-3 w-3" />,
-          variant: "success" as const,
-          tooltip: "Successfully added to knowledge base",
-        };
-      case "failed":
-        return {
-          label: "Failed",
-          icon: <AlertCircle className="h-3 w-3" />,
-          variant: "destructive" as const,
-          tooltip: error || "Processing failed",
-        };
-      default:
-        return {
-          label: status,
-          icon: null,
-          variant: "secondary" as const,
-          tooltip: "",
-        };
-    }
-  };
-
-  const statusDisplay = getStatusDisplay();
-
-  return (
-    <TooltipProvider>
-      <Tooltip>
-        <TooltipTrigger asChild>
-          <Badge variant={statusDisplay.variant} className="gap-1">
-            {statusDisplay.icon}
-            {statusDisplay.label}
-          </Badge>
-        </TooltipTrigger>
-        <TooltipContent>
-          <p>{statusDisplay.tooltip}</p>
-        </TooltipContent>
-      </Tooltip>
-    </TooltipProvider>
-  );
-}
-```
-
-### Step 7: Update Navigation
-
-**File**: `shopcall.ai-main/src/components/ui/app-sidebar.tsx`
-
-Find the AI Configuration menu items and add:
-
-```typescript
-{
-  title: "Custom Content",
-  url: "/custom-content",
-  icon: Database, // or FileText
-},
-```
-
-**File**: `shopcall.ai-main/src/App.tsx`
-
-Add the route inside the PrivateRoute wrapper:
-
-```typescript
-<Route path="/custom-content" element={<CustomContent />} />
-```
-
----
-
-## 🧪 Testing Checklist
-
-### Backend Testing:
-- [ ] Run migration and verify `custom_content` table exists
-- [ ] Verify Storage bucket `custom-content` is created
-- [ ] Test PDF upload endpoint (duplicate detection)
-- [ ] Test text entry creation endpoint
-- [ ] Test list endpoint with filters
-- [ ] Test delete endpoint (verify Qdrant + Storage cleanup)
-- [ ] Test MCP tool: `shopify_search_custom_content`
-- [ ] Test MCP tool: `woocommerce_search_custom_content`
-- [ ] Test MCP tool: `shoprenter_search_custom_content`
-
-### Frontend Testing:
-- [ ] Navigate to `/custom-content` page
-- [ ] Upload small PDF (<1MB)
-- [ ] Upload large PDF (>5MB)
-- [ ] Test duplicate file upload (should reject)
-- [ ] Create text entry
-- [ ] View all content (tabs work)
-- [ ] Watch real-time status updates
-- [ ] Delete content (confirm dialog)
-- [ ] Verify content appears in AI assistant responses
-
----
-
-## 📚 API Endpoints Reference
-
-| Endpoint | Method | Description |
-|----------|--------|-------------|
-| `/custom-content-upload` | POST | Upload PDF file |
-| `/custom-content-process` | POST | Process PDF (internal) |
-| `/custom-content-create` | POST | Create text entry |
-| `/custom-content-list` | GET | List all content |
-| `/custom-content-delete` | DELETE | Delete content |
-| `/custom-content-sync-status` | GET | Get sync status |
-
-All endpoints require `Authorization: Bearer <token>` header.
-
----
-
-## 🔍 Troubleshooting
-
-### PDF Processing Fails
-- Check Edge Function logs: `npx supabase functions logs custom-content-process`
-- Verify `OPENROUTER_API_KEY` is set in Supabase secrets
-- Check PDF is valid (not corrupted or password-protected)
-
-### Qdrant Sync Fails
-- Verify Qdrant URL and API key in `stores` table or environment
-- Check Qdrant collection exists: `{shopname}-custom-content`
-- Review Qdrant logs for connection errors
-
-### Upload Returns 413 Error
-- File exceeds 10MB limit
-- Adjust `file_size_limit` in Storage bucket settings
-
-### Status Never Updates
-- Frontend not polling (check interval is running)
-- Edge Function crashed during processing
-- Check sync status endpoint returns data
-
----
-
-## 📊 Database Queries for Debugging
-
-```sql
--- View all custom content
-SELECT * FROM custom_content ORDER BY created_at DESC;
-
--- View content by status
-SELECT title, content_type, sync_status, created_at
-FROM custom_content
-WHERE sync_status = 'failed';
-
--- Get content statistics
-SELECT * FROM get_custom_content_stats('store-uuid-here');
-
--- View storage files
-SELECT * FROM storage.objects
-WHERE bucket_id = 'custom-content';
-```
-
----
-
-## 🎉 Summary
-
-Once completed, users will be able to:
-1. ✅ Upload PDF files with automatic deduplication
-2. ✅ Create text entries for custom knowledge
-3. ✅ View all content with real-time sync status
-4. ✅ Delete content (hard delete from all systems)
-5. ✅ AI assistants can search this content via MCP tools
-
-The backend is **fully deployed and operational**. The frontend implementation should take approximately 4-6 hours for an experienced React developer.

+ 0 - 489
DEPLOYMENT_GUIDE.md

@@ -1,489 +0,0 @@
-# ShopCall.ai Deployment Guide
-
-This guide explains how to deploy ShopCall.ai with static hosting and Supabase Edge Functions.
-
-## Architecture Overview
-
-### Current Architecture
-- **Frontend**: Static React build (Vite) - Can be hosted on any static hosting provider
-- **Backend**: Supabase Edge Functions (Deno runtime)
-- **Database**: Supabase PostgreSQL
-- **Authentication**: Supabase Auth
-
-## Prerequisites
-
-1. Supabase account and project
-2. Static web hosting (Apache, Nginx, Cloudflare Pages, Netlify, etc.)
-3. Resend API key for email sending (or alternative email service)
-4. Shopify API credentials (if using Shopify integration)
-5. Node.js and npm installed locally for building
-
-## Database Setup
-
-The database migrations have already been applied. The following tables were created:
-
-### 1. pending_signups
-Stores temporary signup data with OTP for email verification (15-minute expiration).
-
-### 2. oauth_nonces
-Stores OAuth state/nonce values for secure OAuth flows (10-minute expiration).
-
-### 3. stores
-Stores e-commerce platform credentials and configuration.
-
-## Edge Functions Deployment
-
-### Deployed Edge Functions
-
-1. **auth** - `/functions/v1/auth/*`
-   - `/auth/signup` - Create new user account with OTP
-   - `/auth/signup/verify` - Verify OTP and complete registration
-   - `/auth/signup/resend-otp` - Resend OTP email
-   - `/auth/login` - Email/password login
-   - `/auth/logout` - Sign out
-   - `/auth/check` - Validate session token
-
-2. **shopify-oauth** - `/functions/v1/shopify-oauth/*`
-   - `/shopify-oauth/init` - Initialize Shopify OAuth flow
-   - `/shopify-oauth/callback` - Handle Shopify OAuth callback
-
-3. **woocommerce-oauth** - `/functions/v1/woocommerce-oauth/*`
-   - `/woocommerce-oauth/init` - Initialize WooCommerce OAuth flow
-   - `/woocommerce-oauth/callback` - Handle WooCommerce callback
-
-4. **shoprenter-oauth** - `/functions/v1/oauth-shoprenter-*`
-   - `/oauth-shoprenter-init` - Initialize ShopRenter OAuth flow
-   - `/oauth-shoprenter-callback` - Handle ShopRenter OAuth callback
-
-5. **shoprenter-webhooks** - `/functions/v1/webhook-shoprenter-*`
-   - `/webhook-shoprenter-uninstall` - Handle ShopRenter app uninstall
-
-6. **shoprenter-api** - `/functions/v1/shoprenter-*`
-   - `/shoprenter-products/:storeId` - Fetch products from ShopRenter
-   - `/shoprenter-orders/:storeId` - Fetch orders from ShopRenter
-   - `/shoprenter-customers/:storeId` - Fetch customers from ShopRenter
-   - `/shoprenter-sync/:storeId` - Trigger manual data synchronization
-
-7. **shoprenter-scheduled-sync** - `/functions/v1/shoprenter-scheduled-sync`
-   - Automated background sync for all ShopRenter stores
-   - Called by pg_cron on schedule (default: hourly)
-   - Requires `INTERNAL_SYNC_SECRET` header for authentication
-
-8. **gdpr-webhooks** - `/functions/v1/gdpr-webhooks/*`
-   - `/gdpr-webhooks/customers-data-request` - Handle customer data requests
-   - `/gdpr-webhooks/customers-redact` - Handle customer data redaction
-   - `/gdpr-webhooks/shop-redact` - Handle shop data redaction
-
-### Environment Variables for Edge Functions
-
-Configure these in your Supabase project settings:
-
-```bash
-# Supabase (automatically available)
-SUPABASE_URL=https://YOUR_PROJECT.supabase.co
-SUPABASE_ANON_KEY=your_anon_key
-
-# Email Service (Resend)
-RESEND_API_KEY=re_YOUR_API_KEY
-
-# Shopify Integration
-SHOPIFY_API_KEY=your_shopify_api_key
-SHOPIFY_API_SECRET=your_shopify_api_secret
-SHOPIFY_REDIRECT_URI=https://YOUR_PROJECT.supabase.co/functions/v1/shopify-oauth/callback
-
-# ShopRenter Integration
-SHOPRENTER_CLIENT_ID=your_shoprenter_client_id
-SHOPRENTER_CLIENT_SECRET=your_shoprenter_client_secret
-
-# Scheduled Sync Security
-INTERNAL_SYNC_SECRET=generate_random_secure_secret_here
-
-# Frontend URL (for OAuth redirects)
-FRONTEND_URL=https://yourdomain.com
-
-# Edge Function Base URL
-EDGE_FUNCTION_BASE_URL=https://YOUR_PROJECT.supabase.co/functions/v1
-
-# Service Role Key (for admin operations)
-SUPABASE_SERVICE_ROLE_KEY=your_service_role_key
-```
-
-## Frontend Deployment
-
-### Step 1: Configure Environment Variables
-
-Create or update `.env` file in `shopcall.ai-main/`:
-
-```bash
-# Supabase Configuration
-VITE_SUPABASE_URL=https://YOUR_PROJECT.supabase.co
-VITE_SUPABASE_ANON_KEY=your_anon_key
-
-# Backend API Base URL (Supabase Edge Functions)
-VITE_API_URL=https://YOUR_PROJECT.supabase.co/functions/v1
-
-# Frontend URL (for OAuth callbacks)
-VITE_FRONTEND_URL=https://yourdomain.com
-```
-
-### Step 2: Build the Frontend
-
-```bash
-cd shopcall.ai-main
-npm install
-npm run build
-```
-
-This creates a `dist/` directory with your static files.
-
-### Step 3: Deploy Static Files
-
-#### Option A: Apache Hosting
-
-1. Upload the contents of `dist/` to your web server (e.g., `/var/www/html/`)
-2. Create `.htaccess` file in the root directory for SPA routing:
-   ```apache
-   <IfModule mod_rewrite.c>
-     RewriteEngine On
-     RewriteBase /
-     RewriteRule ^index\.html$ - [L]
-     RewriteCond %{REQUEST_FILENAME} !-f
-     RewriteCond %{REQUEST_FILENAME} !-d
-     RewriteRule . /index.html [L]
-   </IfModule>
-   ```
-3. Enable `mod_rewrite`:
-   ```bash
-   sudo a2enmod rewrite
-   sudo systemctl restart apache2
-   ```
-
-#### Option B: Nginx Hosting
-
-1. Upload the contents of `dist/` to your web server (e.g., `/var/www/shopcall.ai/`)
-2. Configure nginx:
-   ```nginx
-   server {
-       listen 80;
-       server_name yourdomain.com;
-       root /var/www/shopcall.ai;
-       index index.html;
-
-       location / {
-           try_files $uri $uri/ /index.html;
-       }
-   }
-   ```
-3. Test and reload:
-   ```bash
-   sudo nginx -t
-   sudo systemctl reload nginx
-   ```
-
-#### Option C: Cloudflare Pages / Netlify / Similar
-
-1. Connect your Git repository
-2. Set build command: `cd shopcall.ai-main && npm run build`
-3. Set publish directory: `shopcall.ai-main/dist`
-4. Configure environment variables in the platform's dashboard
-
-## Email Service Setup (Resend)
-
-1. Sign up for [Resend](https://resend.com/)
-2. Create an API key
-3. Add the API key to your Supabase Edge Function secrets:
-   ```bash
-   supabase secrets set RESEND_API_KEY=your_api_key
-   ```
-4. Verify your sending domain in Resend (recommended for production)
-
-## OAuth Configuration
-
-### Shopify
-
-1. In your Shopify Partner dashboard, update the app settings:
-   - **App URL**: `https://yourdomain.com`
-   - **Allowed redirection URL(s)**:
-     - `https://YOUR_PROJECT.supabase.co/functions/v1/shopify-oauth/callback`
-   - **GDPR webhooks**:
-     - Customer data request: `https://YOUR_PROJECT.supabase.co/functions/v1/gdpr-webhooks/customers-data-request`
-     - Customer data erasure: `https://YOUR_PROJECT.supabase.co/functions/v1/gdpr-webhooks/customers-redact`
-     - Shop data erasure: `https://YOUR_PROJECT.supabase.co/functions/v1/gdpr-webhooks/shop-redact`
-
-### WooCommerce
-
-No special configuration needed. The OAuth flow is initiated from the dashboard.
-
-### ShopRenter
-
-1. Register your app with ShopRenter by emailing partnersupport@shoprenter.hu with:
-   - **Application Name**: ShopCall.ai - AI Phone Assistant
-   - **EntryPoint URL**: `https://yourdomain.com/integrations`
-   - **RedirectUri URL**: `https://YOUR_PROJECT.supabase.co/functions/v1/oauth-shoprenter-callback`
-   - **UninstallUri URL**: `https://YOUR_PROJECT.supabase.co/functions/v1/webhook-shoprenter-uninstall`
-   - **Application Logo**: 250x150px PNG with transparency
-   - **Required Scopes**: `product:read`, `product:write`, `customer:read`, `customer:write`, `order:read`, `order:write`, `category:read`, `webhook:read`, `webhook:write`
-   - **Note**: EntryPoint URL should be a static HTTPS endpoint. ShopRenter will call it with authentication parameters, and our backend will redirect with the `sr_install` parameter.
-
-2. Once approved, you'll receive:
-   - **ClientId** (add to `SHOPRENTER_CLIENT_ID`)
-   - **ClientSecret** (add to `SHOPRENTER_CLIENT_SECRET`)
-
-3. Test your integration with a ShopRenter test store (request at https://www.shoprenter.hu/tesztigenyles/?devstore=1)
-
-## ShopRenter Scheduled Background Sync Setup
-
-The ShopRenter integration includes automated background synchronization using PostgreSQL's `pg_cron` extension.
-
-### Step 1: Run Database Migration
-
-Execute the scheduled sync migration in your Supabase SQL Editor:
-
-```bash
-# Option A: Via Supabase CLI
-supabase db push
-
-# Option B: Via Supabase Dashboard
-# 1. Go to SQL Editor in Supabase Dashboard
-# 2. Create a new query
-# 3. Copy contents of supabase/migrations/20250129_shoprenter_scheduled_sync.sql
-# 4. Run the query
-```
-
-This migration will:
-- Enable `pg_cron` and `pg_net` extensions
-- Create `sync_logs` table for tracking sync executions
-- Create `store_sync_config` table for per-store configuration
-- Schedule hourly sync job via pg_cron
-- Set up helper functions and views
-
-### Step 2: Configure Database Settings
-
-In Supabase Dashboard, configure the required settings for pg_cron to call Edge Functions:
-
-1. Go to **Project Settings** → **Database** → **Custom Postgres Configuration**
-2. Add the following settings:
-
-```
-app.internal_sync_secret = <SAME_VALUE_AS_INTERNAL_SYNC_SECRET_ABOVE>
-app.supabase_url = https://YOUR_PROJECT.supabase.co
-```
-
-**Generate INTERNAL_SYNC_SECRET:**
-```bash
-# Generate a secure random secret (32 characters)
-openssl rand -hex 32
-```
-
-### Step 3: Deploy Scheduled Sync Edge Function
-
-Deploy the scheduled sync Edge Function to Supabase:
-
-```bash
-supabase functions deploy shoprenter-scheduled-sync
-```
-
-### Step 4: Verify Scheduled Job
-
-Check that the pg_cron job is scheduled:
-
-```sql
--- Run in Supabase SQL Editor
-SELECT * FROM cron.job WHERE jobname = 'shoprenter-hourly-sync';
-```
-
-You should see output like:
-```
-jobid | schedule    | command                                     | nodename  | jobname
-------+-------------+---------------------------------------------+-----------+-------------------------
-1     | 0 * * * *   | SELECT trigger_shoprenter_scheduled_sync(); | localhost | shoprenter-hourly-sync
-```
-
-### Step 5: Monitor Sync Execution
-
-After the scheduled job runs (at the top of each hour), check the logs:
-
-```sql
--- View recent sync logs
-SELECT
-  id,
-  sync_type,
-  platform,
-  stores_processed,
-  started_at,
-  completed_at,
-  EXTRACT(EPOCH FROM (completed_at - started_at)) as duration_seconds
-FROM sync_logs
-ORDER BY created_at DESC
-LIMIT 10;
-
--- View sync statistics
-SELECT * FROM sync_statistics
-ORDER BY sync_date DESC, platform
-LIMIT 20;
-```
-
-### Step 6: Configure Per-Store Sync Settings
-
-By default, all ShopRenter stores are configured to sync hourly. You can customize:
-
-```sql
--- Disable sync for a specific store
-SELECT set_store_sync_enabled('store-uuid-here', false);
-
--- Change sync frequency (options: '15min', '30min', 'hourly', '6hours', 'daily')
-SELECT set_store_sync_frequency('store-uuid-here', '6hours');
-
--- View all store sync configurations
-SELECT
-  ssc.store_id,
-  s.store_name,
-  ssc.enabled,
-  ssc.sync_frequency,
-  ssc.last_sync_at,
-  ssc.next_sync_at,
-  ssc.products_access_policy,
-  ssc.customers_access_policy,
-  ssc.orders_access_policy
-FROM store_sync_config ssc
-JOIN stores s ON s.id = ssc.store_id
-WHERE s.platform_name = 'shoprenter';
-```
-
-### Sync Frequency Options
-
-| Frequency | Cron Schedule | Use Case |
-|-----------|--------------|----------|
-| `15min` | Every 15 minutes | High-frequency stores (limited by API rate limits) |
-| `30min` | Every 30 minutes | Active stores with frequent updates |
-| `hourly` | Every hour | **Default** - Balanced for most stores |
-| `6hours` | Every 6 hours | Low-traffic stores |
-| `daily` | Once per day | Archive/backup stores |
-
-### Troubleshooting Scheduled Sync
-
-**Job not running:**
-```sql
--- Check if pg_cron extension is enabled
-SELECT * FROM pg_extension WHERE extname = 'pg_cron';
-
--- Check job status
-SELECT * FROM cron.job_run_details
-WHERE jobid = (SELECT jobid FROM cron.job WHERE jobname = 'shoprenter-hourly-sync')
-ORDER BY start_time DESC
-LIMIT 10;
-```
-
-**Edge Function not being called:**
-- Verify `app.internal_sync_secret` and `app.supabase_url` are set in database settings
-- Check Edge Function logs in Supabase Dashboard
-- Ensure `shoprenter-scheduled-sync` Edge Function is deployed
-
-**Sync failing for specific stores:**
-```sql
--- Check sync results for a specific store
-SELECT
-  results->>'store_id' as store_id,
-  results->>'store_name' as store_name,
-  results->>'status' as status,
-  results->>'error_message' as error_message,
-  results->'products' as products_stats,
-  results->'orders' as orders_stats,
-  results->'customers' as customers_stats
-FROM sync_logs, jsonb_array_elements(results) as results
-WHERE platform = 'shoprenter'
-AND results->>'store_id' = 'your-store-uuid'
-ORDER BY created_at DESC
-LIMIT 5;
-```
-
-**Manual trigger for testing:**
-```bash
-# Manually trigger scheduled sync (for testing)
-curl -X POST https://YOUR_PROJECT.supabase.co/functions/v1/shoprenter-scheduled-sync \
-  -H "x-internal-secret: YOUR_INTERNAL_SYNC_SECRET" \
-  -H "Content-Type: application/json"
-```
-
-### Security Notes
-
-- `INTERNAL_SYNC_SECRET` is required to prevent unauthorized sync triggers
-- Only the pg_cron database function has access to this secret
-- Sync logs use Row Level Security - users can only see their own store syncs
-- Tokens are automatically refreshed when expired
-
-## Testing the Deployment
-
-### 1. Test Authentication
-
-```bash
-# Test signup
-curl -X POST https://YOUR_PROJECT.supabase.co/functions/v1/auth/signup \
-  -H "Content-Type: application/json" \
-  -d '{
-    "email": "test@example.com",
-    "password": "testpass123",
-    "full_name": "Test User",
-    "company_name": "Test Company",
-    "user_name": "testuser"
-  }'
-
-# Test login
-curl -X POST https://YOUR_PROJECT.supabase.co/functions/v1/auth/login \
-  -H "Content-Type: application/json" \
-  -d '{
-    "email": "test@example.com",
-    "password": "testpass123"
-  }'
-```
-
-### 2. Test OAuth Flow
-
-1. Navigate to your frontend URL
-2. Try connecting a Shopify or WooCommerce store
-3. Verify the OAuth callback works correctly
-
-### 3. Test Frontend Routing
-
-1. Navigate to various routes (e.g., `/dashboard`, `/call-logs`)
-2. Refresh the page to ensure routing works with static hosting
-3. Check browser console for any errors
-
-## Troubleshooting
-
-### Common Issues
-
-**Issue**: 404 errors on routes when refreshing
-- **Solution**: Ensure `.htaccess` (Apache) or nginx configuration is properly set up for client-side routing
-
-**Issue**: CORS errors when calling Edge Functions
-- **Solution**: Verify CORS headers are set in Edge Functions (`corsHeaders` in each function)
-
-**Issue**: Email not sending
-- **Solution**: Check Resend API key is properly configured and verify the email service is active
-
-**Issue**: OAuth callback fails
-- **Solution**: Verify redirect URIs match exactly in your OAuth provider settings
-
-## Monitoring and Maintenance
-
-1. **Edge Functions Logs**: Monitor in Supabase Dashboard > Edge Functions > Logs
-2. **Database**: Check Supabase Dashboard > Database for any issues
-3. **Cleanup**: The database has automatic cleanup for expired records via the functions:
-   - `delete_expired_pending_signups()`
-   - `delete_expired_oauth_nonces()`
-
-## Security Considerations
-
-1. **Environment Variables**: Never commit `.env` files to version control
-2. **API Keys**: Rotate API keys regularly
-3. **HTTPS**: Always use HTTPS in production
-4. **Rate Limiting**: Consider adding rate limiting to Edge Functions for production
-5. **CORS**: Restrict CORS origins to your actual frontend domain in production
-
-## Support
-
-For issues or questions:
-- Check Supabase logs for Edge Function errors
-- Review browser console for frontend errors
-- Verify environment variables are correctly set

+ 0 - 141
FIX_JWT_ISSUE.md

@@ -1,141 +0,0 @@
-# Fix JWT Verification Issue - Quick Guide
-
-## Problem
-The Edge Functions are rejecting public requests (like `/auth/signup`) because JWT verification is enabled by default.
-
-## Solution Options
-
-### Option 1: Manual Dashboard Update (If Available in Future)
-1. Go to: https://supabase.com/dashboard/project/ztklqodcdjeqpsvhlpud/settings/functions
-2. Look for Edge Functions settings
-3. Disable JWT verification for each function
-
----
-
-### Option 2: Using Supabase CLI (Recommended)
-
-#### Step 1: Install Supabase CLI
-```bash
-# On Linux/macOS
-npm install -g supabase
-
-# Or with homebrew (macOS)
-brew install supabase/tap/supabase
-```
-
-#### Step 2: Login to Supabase
-```bash
-supabase login
-```
-This will open your browser to authenticate.
-
-#### Step 3: Link Your Project
-```bash
-cd /data/shopcall
-supabase link --project-ref ztklqodcdjeqpsvhlpud
-```
-
-#### Step 4: Redeploy Functions with Correct Configuration
-```bash
-# The config.toml file has already been created with verify_jwt = false
-
-# Redeploy all functions
-cd /data/shopcall
-supabase functions deploy auth --no-verify-jwt
-supabase functions deploy shopify-oauth --no-verify-jwt
-supabase functions deploy woocommerce-oauth --no-verify-jwt
-supabase functions deploy gdpr-webhooks --no-verify-jwt
-```
-
----
-
-### Option 3: Using Management API (Advanced)
-
-If you have your Supabase service role key, you can update via API:
-
-```bash
-# Get your service role key from:
-# https://supabase.com/dashboard/project/ztklqodcdjeqpsvhlpud/settings/api
-
-# Set environment variable
-export SUPABASE_SERVICE_KEY="your_service_role_key_here"
-
-# Update each function
-for func in auth shopify-oauth woocommerce-oauth gdpr-webhooks; do
-  curl -X PATCH "https://api.supabase.com/v1/projects/ztklqodcdjeqpsvhlpud/functions/$func" \
-    -H "Authorization: Bearer $SUPABASE_SERVICE_KEY" \
-    -H "Content-Type: application/json" \
-    -d '{"verify_jwt": false}'
-done
-```
-
----
-
-### Option 4: Quick Fix Script
-
-I've created a script for you. Save this as `fix-jwt.sh`:
-
-```bash
-#!/bin/bash
-
-echo "Installing Supabase CLI..."
-npm install -g supabase
-
-echo "Please login to Supabase (browser will open)..."
-supabase login
-
-echo "Linking to your project..."
-cd /data/shopcall
-supabase link --project-ref ztklqodcdjeqpsvhlpud
-
-echo "Deploying functions with JWT verification disabled..."
-supabase functions deploy auth --no-verify-jwt
-supabase functions deploy shopify-oauth --no-verify-jwt
-supabase functions deploy woocommerce-oauth --no-verify-jwt
-supabase functions deploy gdpr-webhooks --no-verify-jwt
-
-echo "Done! Try signup again at https://shopcall.ai/signup"
-```
-
-Then run:
-```bash
-chmod +x fix-jwt.sh
-./fix-jwt.sh
-```
-
----
-
-## Verification
-
-After applying the fix, test the signup:
-1. Go to: https://shopcall.ai/signup
-2. Fill in the form and submit
-3. You should receive an OTP email
-4. No more "401 Unauthorized" errors
-
-## What Changed
-
-The configuration file at `/data/shopcall/supabase/config.toml` now includes:
-
-```toml
-[functions.auth]
-verify_jwt = false
-
-[functions.shopify-oauth]
-verify_jwt = false
-
-[functions.woocommerce-oauth]
-verify_jwt = false
-
-[functions.gdpr-webhooks]
-verify_jwt = false
-```
-
-This allows the functions to handle authentication internally without requiring a JWT token for every request.
-
-## Need Help?
-
-If you encounter any issues:
-1. Check the Edge Functions logs: https://supabase.com/dashboard/project/ztklqodcdjeqpsvhlpud/logs/edge-functions
-2. Verify the function is deployed correctly
-3. Check the browser console for detailed error messages

+ 0 - 882
MISSING_FEATURES.md

@@ -1,882 +0,0 @@
-# ShopCall.ai - Missing Features & Incomplete Implementation Report
-
-**Generated:** 2025-10-22
-**Project:** ShopCall.ai (AI-powered calling system for e-commerce)
-**Repositories:**
-- Frontend: `shopcall.ai-main` (React/Vite/TypeScript)
-- Backend: `shopcall.ai-backend-main` (Express.js/Node.js)
-
----
-
-## 🔴 **CRITICAL MISSING FEATURES**
-
-### 1. **Onboarding Flow - Not Connected to Backend**
-
-**Location:** `shopcall.ai-main/src/components/OnboardingContent.tsx`
-
-**Status:** UI complete, backend integration missing
-
-**Issues:**
-- ❌ No API integration for submitting onboarding data
-- ❌ Shopify connection flow exists in UI but doesn't save to backend
-- ❌ Phone number selection doesn't persist
-- ❌ Package selection doesn't create subscription
-- ❌ `handleFinish()` function only redirects to homepage (line 100-108)
-
-**Missing Backend Endpoints:**
-```
-POST /api/onboarding/complete
-  Body: {
-    shopifyUrl: string,
-    selectedPhone: string,
-    selectedPackage: string
-  }
-```
-
-**Impact:** Users can complete onboarding but nothing is saved. On next login, they'll need to onboard again.
-
-**Effort:** Medium (2-3 days)
-
----
-
-### 2. **Shopify OAuth Integration Incomplete**
-
-**Location:** `shopcall.ai-backend-main/api/index.js:532-597`
-
-**Status:** OAuth flow works, but tokens not persisted
-
-**Issues:**
-- ✅ OAuth authorization flow implemented
-- ✅ Token exchange working
-- ❌ **TODO Comment (line 586):** "Save tokenJson.access_token securely" - tokens not being stored
-- ❌ No store record created in `stores` table after successful OAuth
-- ❌ Redirect goes to homepage (`https://shopcall.ai/`) instead of dashboard
-- ❌ User-to-store relationship not established
-
-**Current Code:**
-```javascript
-// Line 586
-// TODO: Save tokenJson.access_token securely
-console.log(`Successfully authenticated shop: ${normalizedShop}`);
-
-res.redirect(`https://shopcall.ai/`);
-```
-
-**Required Fix:**
-```javascript
-// Save to database
-const { data: storeData, error: storeError } = await supabase
-  .from('stores')
-  .insert({
-    user_id: nonceData.userId, // from nonce
-    platform_name: 'shopify',
-    store_name: normalizedShop.split('.')[0],
-    store_url: `https://${normalizedShop}`,
-    access_token: tokenJson.access_token,
-    scopes: tokenJson.scope.split(','),
-    connected_at: new Date().toISOString()
-  });
-
-res.redirect(`https://shopcall.ai/dashboard?connected=true`);
-```
-
-**Impact:** Shopify stores cannot be properly connected. OAuth succeeds but connection is lost immediately.
-
-**Effort:** Small (1 day)
-
----
-
-### 3. **Phone Number Management - UI Only**
-
-**Location:** `shopcall.ai-main/src/components/PhoneNumbersContent.tsx`
-
-**Status:** Complete UI mockup with static data
-
-**Issues:**
-- ❌ All data is hardcoded in `connectedShops`, `availableCountries`, `carriers` arrays
-- ❌ No backend API for phone number operations
-- ❌ "Get Number" button (line 278) - no handler
-- ❌ "Assign" button (line 196-199) - no handler
-- ❌ "Connect" carrier buttons (line 231-234) - no handler
-- ❌ Cannot actually purchase or assign phone numbers
-
-**Missing Backend Endpoints:**
-```
-GET    /api/phone-numbers              # List phone numbers for user
-POST   /api/phone-numbers              # Purchase new phone number
-PUT    /api/phone-numbers/:id/assign   # Assign number to store
-DELETE /api/phone-numbers/:id          # Release phone number
-
-POST   /api/carriers/connect            # Connect external carrier (Twilio, etc.)
-GET    /api/carriers                    # List connected carriers
-```
-
-**Missing Database Tables:**
-```sql
-CREATE TABLE phone_numbers (
-  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-  user_id UUID REFERENCES profiles(id),
-  store_id UUID REFERENCES stores(id),
-  number VARCHAR(20) NOT NULL,
-  country VARCHAR(2) NOT NULL,
-  type VARCHAR(20), -- 'local', 'toll-free'
-  carrier VARCHAR(50), -- 'internal', 'twilio', 'telnyx', etc.
-  status VARCHAR(20), -- 'active', 'pending_kyc', 'inactive'
-  monthly_cost DECIMAL(10,2),
-  carrier_config JSONB, -- carrier-specific data
-  created_at TIMESTAMP DEFAULT NOW(),
-  assigned_at TIMESTAMP
-);
-
-CREATE TABLE carrier_integrations (
-  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-  user_id UUID REFERENCES profiles(id),
-  carrier_name VARCHAR(50), -- 'twilio', 'telnyx', 'vonage', 'zadarma'
-  credentials JSONB, -- encrypted API keys
-  is_active BOOLEAN DEFAULT true,
-  created_at TIMESTAMP DEFAULT NOW()
-);
-```
-
-**Impact:** Core feature completely non-functional. Users cannot set up phone numbers which are essential for the service to work.
-
-**Effort:** Large (5-7 days including carrier API integrations)
-
----
-
-### 4. **AI Configuration - UI Only**
-
-**Location:** `shopcall.ai-main/src/components/AIConfigContent.tsx`
-
-**Status:** Complete UI for AI settings, no backend persistence
-
-**Issues:**
-- ❌ All settings stored only in component state
-- ❌ "Save Configuration" button (line 55) - no handler
-- ❌ "Sync Store Data" button (line 247) - no handler
-- ❌ "Test Configuration" button (line 253) - no handler
-- ❌ "Copy from Another Shop" button (line 52) - no handler
-- ❌ Voice settings, greeting messages, escalation policy, knowledge base - none saved
-
-**Missing Backend Endpoints:**
-```
-GET  /api/ai-config/:storeId           # Get AI config for store
-POST /api/ai-config/:storeId           # Create/update AI config
-POST /api/ai-config/:storeId/test      # Test AI configuration
-POST /api/ai-config/:storeId/sync      # Sync store data (products, policies)
-POST /api/ai-config/:storeId/copy      # Copy config from another store
-```
-
-**Missing Database Table:**
-```sql
-CREATE TABLE ai_configurations (
-  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-  store_id UUID REFERENCES stores(id) UNIQUE,
-
-  -- Voice settings
-  voice_type VARCHAR(50) DEFAULT 'sarah',
-  speaking_speed VARCHAR(20) DEFAULT 'normal',
-  accent VARCHAR(50) DEFAULT 'us-english',
-
-  -- Conversation behavior
-  greeting_message TEXT,
-  business_hours_mode BOOLEAN DEFAULT true,
-  local_currency_support BOOLEAN DEFAULT true,
-  escalation_policy VARCHAR(20) DEFAULT 'medium',
-
-  -- Knowledge base
-  product_catalog_synced BOOLEAN DEFAULT false,
-  product_catalog_last_sync TIMESTAMP,
-  store_policies TEXT,
-  faq_database JSONB,
-  custom_knowledge JSONB,
-
-  created_at TIMESTAMP DEFAULT NOW(),
-  updated_at TIMESTAMP DEFAULT NOW()
-);
-```
-
-**Impact:** AI cannot be customized per webshop. All stores would use default settings, making the service less valuable.
-
-**Effort:** Medium-Large (4-5 days)
-
----
-
-## 🟡 **HIGH PRIORITY MISSING FEATURES**
-
-### 5. **Analytics Data - All Mocked**
-
-**Location:** `shopcall.ai-main/src/components/AnalyticsContent.tsx`
-
-**Status:** Complete UI with charts, all using static data
-
-**Issues:**
-- ❌ `weeklyData`, `resolutionData`, `callDurationData`, `topIntentsData`, etc. - all hardcoded (lines 6-58)
-- ❌ Charts display fake data
-- ❌ No real metrics calculation
-- ❌ Peak hours heatmap generated randomly (line 130)
-
-**Missing Backend Endpoints:**
-```
-GET /api/analytics/overview?timeRange=week       # KPIs and overview charts
-GET /api/analytics/trends?timeRange=month        # Trend analysis
-GET /api/analytics/performance?timeRange=week    # Performance metrics
-GET /api/analytics/call-volume?groupBy=day       # Call volume data
-GET /api/analytics/intents?limit=10              # Top call intents
-```
-
-**Required Aggregation Logic:**
-- Call volume by day/hour/week
-- Resolution rate calculation
-- Average call duration by intent
-- Peak hours analysis
-- Sentiment distribution
-- Cost analysis
-
-**Impact:** Dashboard shows misleading fake data. Users cannot make data-driven decisions.
-
-**Effort:** Medium (3-4 days for proper aggregation queries)
-
----
-
-### 6. **Dashboard KPIs - Hardcoded**
-
-**Location:**
-- `shopcall.ai-main/src/components/KPICards.tsx`
-- `shopcall.ai-main/src/components/ChartsSection.tsx`
-- `shopcall.ai-main/src/components/RecentCallsTable.tsx`
-
-**Status:** Complete UI, static mock data
-
-**Issues:**
-- ❌ All KPI values hardcoded
-- ❌ Charts show static data
-- ❌ Recent calls table shows hardcoded 5 calls (lines 8-64 in RecentCallsTable.tsx)
-- ❌ No refresh functionality
-
-**Missing Backend Endpoint:**
-```
-GET /api/dashboard/summary?timeRange=24h
-  Response: {
-    totalCalls: number,
-    resolvedCalls: number,
-    activeConversations: number,
-    avgResponseTime: number,
-    resolutionRate: number,
-    avgCallDuration: number,
-    totalCost: number,
-    chartData: {
-      callVolume: [...],
-      resolutionRate: [...]
-    },
-    recentCalls: [...]
-  }
-```
-
-**Impact:** Dashboard is just a demo, not showing real data.
-
-**Effort:** Small-Medium (2-3 days, reuses analytics logic)
-
----
-
-### 7. **Webshop Integration Management - Partially Implemented**
-
-**Location:** `shopcall.ai-main/src/components/IntegrationsContent.tsx`
-
-**Status:** Backend APIs exist, frontend not connected
-
-**Issues:**
-- ✅ Backend has `GET /api/stores` (line 800)
-- ✅ Backend has `PUT /api/stores/:id` (line 855)
-- ✅ Backend has `DELETE /api/stores/:id` (line 893)
-- ❌ Frontend shows hardcoded `connectedShops` array (lines 10-86)
-- ❌ "Connect Webshop" button (line 96-99) doesn't trigger OAuth
-- ❌ Settings buttons (line 202) don't open edit modal
-- ❌ No fetch call to `/api/stores`
-
-**Required Frontend Changes:**
-```typescript
-const [stores, setStores] = useState([]);
-
-useEffect(() => {
-  const fetchStores = async () => {
-    const response = await fetch('https://shopcall-ai-backend.vercel.app/api/stores', {
-      headers: { 'Authorization': `Bearer ${token}` }
-    });
-    const data = await response.json();
-    setStores(data.stores);
-  };
-  fetchStores();
-}, []);
-```
-
-**Impact:** Users see fake store list instead of their actual connected stores.
-
-**Effort:** Small (1 day to connect frontend to existing backend)
-
----
-
-### 8. **Call Recording Playback**
-
-**Location:** `shopcall.ai-main/src/components/CallDetailsModal.tsx`
-
-**Status:** UI exists, no audio implementation
-
-**Issues:**
-- ❌ Play button exists (line 145-152) but no audio player
-- ❌ `recording_url` field in `call_logs` table not used
-- ❌ No audio streaming functionality
-- ❌ No waveform visualization
-- ❌ Progress bar not functional (line 159-161)
-
-**Required Implementation:**
-```typescript
-const [audio] = useState(new Audio());
-const [isPlaying, setIsPlaying] = useState(false);
-const [currentTime, setCurrentTime] = useState(0);
-const [duration, setDuration] = useState(0);
-
-useEffect(() => {
-  if (call.recording_url) {
-    audio.src = call.recording_url;
-    audio.addEventListener('loadedmetadata', () => {
-      setDuration(audio.duration);
-    });
-    audio.addEventListener('timeupdate', () => {
-      setCurrentTime(audio.currentTime);
-    });
-  }
-}, [call.recording_url]);
-
-const handlePlayPause = () => {
-  if (isPlaying) {
-    audio.pause();
-  } else {
-    audio.play();
-  }
-  setIsPlaying(!isPlaying);
-};
-```
-
-**Impact:** Cannot review call recordings, limiting quality assurance capabilities.
-
-**Effort:** Small (1-2 days)
-
----
-
-### 9. **WooCommerce Integration - Incomplete**
-
-**Location:** `shopcall.ai-backend-main/api/index.js:463-529`
-
-**Status:** OAuth callback implemented, token storage works
-
-**Issues:**
-- ✅ OAuth initiation works (line 463)
-- ✅ Callback saves credentials (line 481)
-- ❌ No frontend UI to trigger WooCommerce connection
-- ❌ No WooCommerce-specific configuration options
-- ❌ Product sync not implemented
-- ❌ No webhook setup for order updates
-
-**Missing Features:**
-- WooCommerce product catalog sync
-- Order status webhooks
-- Customer data integration
-- Store policy import
-
-**Impact:** WooCommerce support advertised but not fully functional.
-
-**Effort:** Medium (3-4 days for full WooCommerce integration)
-
----
-
-## 🟢 **MEDIUM PRIORITY MISSING FEATURES**
-
-### 10. **Search & Filtering**
-
-**Location:** Multiple components
-
-**Issues:**
-- ❌ Call logs search input exists but no filter logic (`CallLogsContent.tsx:118-124`)
-- ❌ "Filters" button exists but no filter panel (`CallLogsContent.tsx:126-129`)
-- ❌ Date range picker button non-functional (`CallLogsContent.tsx:107-111`)
-- ❌ No backend support for query parameters
-
-**Required Backend Changes:**
-```
-GET /api/call-logs?search=xxx&status=completed&outcome=resolved&dateFrom=...&dateTo=...
-```
-
-**Required Frontend Changes:**
-- Search debouncing
-- Filter panel UI
-- Date range picker integration
-- Query string management
-
-**Impact:** Users must manually scroll through all calls, poor UX for high-volume users.
-
-**Effort:** Small-Medium (2-3 days)
-
----
-
-### 11. **Export Functionality**
-
-**Location:** `shopcall.ai-main/src/components/CallLogsContent.tsx:102-105`
-
-**Status:** Button exists, no implementation
-
-**Issues:**
-- ❌ Export button present but no click handler
-- ❌ No backend endpoint for data export
-- ❌ No file format options (CSV, PDF, Excel)
-
-**Missing Backend Endpoint:**
-```
-GET /api/call-logs/export?format=csv&dateFrom=...&dateTo=...
-  Response: CSV/PDF file download
-```
-
-**Required Features:**
-- CSV export (for Excel)
-- PDF export (formatted report)
-- Email export option
-- Export scheduling (weekly/monthly reports)
-
-**Impact:** Users cannot extract data for external analysis or reporting.
-
-**Effort:** Small (1-2 days)
-
----
-
-### 12. **Real-time Updates**
-
-**Status:** Not implemented
-
-**Issues:**
-- ❌ No WebSocket connection for live updates
-- ❌ Dashboard requires manual refresh
-- ❌ No notification system for new calls
-- ❌ Active call status not real-time
-
-**Required Implementation:**
-- WebSocket server (Socket.io or native WebSockets)
-- Real-time call status updates
-- Live dashboard KPI updates
-- Browser notifications
-
-**Missing Infrastructure:**
-```javascript
-// Backend
-const io = require('socket.io')(server);
-
-io.on('connection', (socket) => {
-  socket.on('authenticate', async (token) => {
-    // Validate token and join user room
-    socket.join(`user_${userId}`);
-  });
-});
-
-// Emit on new call
-io.to(`user_${userId}`).emit('new_call', callData);
-```
-
-**Impact:** Users miss real-time updates, dashboard feels outdated.
-
-**Effort:** Medium (3-4 days for WebSocket implementation)
-
----
-
-### 13. **User Profile Management**
-
-**Status:** Not implemented
-
-**Issues:**
-- ❌ No profile page/route
-- ❌ Cannot edit profile information (name, company, email)
-- ❌ No password change functionality
-- ❌ No account deletion option
-- ❌ `profiles` table exists but no edit endpoint
-
-**Missing Endpoints:**
-```
-GET    /api/profile                    # Get current user profile
-PUT    /api/profile                    # Update profile
-POST   /api/profile/change-password    # Change password
-DELETE /api/profile                    # Delete account
-```
-
-**Missing Frontend Pages:**
-- `/settings/profile` - Profile edit page
-- `/settings/security` - Password change
-- `/settings/account` - Account management
-
-**Impact:** Users stuck with initial registration data. Cannot fix typos or update information.
-
-**Effort:** Small-Medium (2-3 days)
-
----
-
-### 14. **Payment Integration**
-
-**Location:** `OnboardingContent.tsx:31-80` - Package selection UI
-
-**Status:** Package selection UI only
-
-**Issues:**
-- ❌ No payment gateway integration (Stripe, PayPal, etc.)
-- ❌ Package selection doesn't create subscription
-- ❌ No billing page
-- ❌ No invoice generation
-- ❌ No payment history
-- ❌ Free trial not tracked
-
-**Missing Implementation:**
-- Stripe/PayPal SDK integration
-- Subscription management
-- Webhook handling for payment events
-- Billing portal
-
-**Missing Endpoints:**
-```
-POST   /api/subscriptions/create        # Create subscription
-GET    /api/subscriptions/current       # Get current subscription
-POST   /api/subscriptions/cancel        # Cancel subscription
-POST   /api/subscriptions/upgrade       # Upgrade plan
-GET    /api/invoices                    # List invoices
-```
-
-**Missing Database Table:**
-```sql
-CREATE TABLE subscriptions (
-  id UUID PRIMARY KEY,
-  user_id UUID REFERENCES profiles(id),
-  plan_id VARCHAR(50), -- 'free-trial', 'starter', 'professional'
-  status VARCHAR(20), -- 'active', 'cancelled', 'past_due'
-  stripe_subscription_id VARCHAR(100),
-  current_period_start TIMESTAMP,
-  current_period_end TIMESTAMP,
-  cancel_at_period_end BOOLEAN,
-  created_at TIMESTAMP DEFAULT NOW()
-);
-```
-
-**Impact:** Cannot monetize the service. All users have unlimited access.
-
-**Effort:** Large (5-7 days for full payment integration)
-
----
-
-### 15. **Email Notifications**
-
-**Status:** Only OTP emails implemented
-
-**Issues:**
-- ✅ OTP email works (`sendOTPEmail` function exists)
-- ❌ No call summary emails
-- ❌ No alerts for failed calls
-- ❌ No weekly/monthly reports
-- ❌ No password reset emails
-- ❌ No subscription notifications
-
-**Missing Email Templates:**
-- Call completed summary
-- Failed call alert
-- Weekly activity report
-- Monthly invoice
-- Password reset
-- Subscription renewal reminder
-
-**Required Implementation:**
-- Email template system (Handlebars, Pug, etc.)
-- Email queue (Bull, BullMQ)
-- Background job processing
-- Email service (SendGrid, Mailgun, or continue with Nodemailer)
-
-**Impact:** Users not notified of important events. Must check dashboard constantly.
-
-**Effort:** Medium (3-4 days)
-
----
-
-## 🔵 **LOW PRIORITY / NICE TO HAVE**
-
-### 16. **Advanced Call Features**
-
-**Missing Features:**
-- ❌ Call forwarding to human agents (escalation)
-- ❌ Voicemail functionality
-- ❌ Call scheduling (schedule calls for later)
-- ❌ SMS fallback (if call fails, send SMS)
-- ❌ Call recording consent management (GDPR)
-- ❌ IVR (Interactive Voice Response) menu
-- ❌ Call queuing
-- ❌ After-hours handling
-
-**Impact:** Basic AI calling only. Limited flexibility.
-
-**Effort:** Large (ongoing feature development)
-
----
-
-### 17. **Team Collaboration**
-
-**Status:** Not implemented (single-user only)
-
-**Missing Features:**
-- ❌ Multi-user accounts (team members)
-- ❌ Roles & permissions (admin, agent, viewer)
-- ❌ Team member invitation
-- ❌ Shared call notes/comments
-- ❌ Call assignment to team members
-- ❌ Activity logs
-
-**Required Database Tables:**
-```sql
-CREATE TABLE team_members (
-  id UUID PRIMARY KEY,
-  organization_id UUID,
-  user_id UUID REFERENCES profiles(id),
-  role VARCHAR(20), -- 'owner', 'admin', 'agent', 'viewer'
-  permissions JSONB,
-  invited_by UUID,
-  invited_at TIMESTAMP,
-  joined_at TIMESTAMP
-);
-
-CREATE TABLE organizations (
-  id UUID PRIMARY KEY,
-  name VARCHAR(255),
-  owner_id UUID REFERENCES profiles(id),
-  created_at TIMESTAMP
-);
-```
-
-**Impact:** Only suitable for solo users. Cannot scale to businesses with teams.
-
-**Effort:** Large (7-10 days)
-
----
-
-### 18. **API Documentation**
-
-**Status:** Not implemented
-
-**Missing:**
-- ❌ No public API documentation
-- ❌ No API keys for developers
-- ❌ No webhooks for third-party integrations
-- ❌ No SDK/client libraries
-- ❌ No API rate limiting
-- ❌ No API versioning
-
-**Required:**
-- OpenAPI/Swagger documentation
-- API key generation endpoint
-- Webhook configuration UI
-- Developer portal
-
-**Impact:** Cannot integrate with external tools. Limited extensibility.
-
-**Effort:** Medium (3-5 days for basic API docs + key management)
-
----
-
-### 19. **Testing Coverage**
-
-**Status:** No tests exist
-
-**Missing:**
-- ❌ No unit tests (frontend or backend)
-- ❌ No integration tests
-- ❌ No E2E tests
-- ❌ No test coverage reports
-
-**Required:**
-- Jest + React Testing Library (frontend)
-- Jest + Supertest (backend)
-- Playwright/Cypress (E2E)
-- CI/CD pipeline with test gates
-
-**Impact:** High risk of bugs, difficult to refactor safely.
-
-**Effort:** Ongoing (20-30% of development time)
-
----
-
-### 20. **Additional E-commerce Platforms**
-
-**Status:** Shopify & WooCommerce partially implemented
-
-**Missing Platforms:**
-- ❌ BigCommerce
-- ❌ Magento
-- ❌ Squarespace
-- ❌ Wix
-- ❌ PrestaShop
-- ❌ Custom/Generic REST API integration
-
-**Required:**
-- OAuth flows for each platform
-- Product sync adapters
-- Order webhook handlers
-- Platform-specific configuration
-
-**Impact:** Limited market reach. Many e-commerce users excluded.
-
-**Effort:** Large per platform (4-5 days each)
-
----
-
-## 📝 **TODO COMMENTS IN CODE**
-
-### Backend (`shopcall.ai-backend-main/api/index.js`)
-
-1. **Line 586:** `// TODO: Save tokenJson.access_token securely`
-   - **Context:** Shopify OAuth callback
-   - **Issue:** Access tokens not being stored in database
-   - **Priority:** 🔴 Critical
-
-2. **Line 604:** `// TODO: Retrieve access token from database`
-   - **Context:** Product API endpoint
-   - **Issue:** Incomplete API endpoint implementation
-   - **Priority:** 🟡 High
-
-3. **Line 677:** `// TODO: Implement your business logic here`
-   - **Context:** GDPR webhook processing
-   - **Issue:** Webhook processing empty
-   - **Priority:** 🟡 High (GDPR compliance issue)
-
-### Frontend
-- No TODO comments found in source code
-
----
-
-## 🎯 **SUMMARY BY PRIORITY**
-
-| Priority | Category | Count | Estimated Effort |
-|----------|----------|-------|------------------|
-| 🔴 Critical | Core functionality blockers | 4 | 12-15 days |
-| 🟡 High | Major features incomplete | 5 | 15-20 days |
-| 🟢 Medium | UX and data issues | 6 | 15-20 days |
-| 🔵 Low | Enhancement features | 5 | 40-50 days |
-| **TOTAL** | | **20** | **82-105 days** |
-
----
-
-## 💡 **RECOMMENDED DEVELOPMENT ORDER**
-
-### Phase 1: Critical Fixes (2-3 weeks)
-1. **Complete Shopify OAuth** - Save tokens, create store records
-2. **Connect Integrations UI to backend** - Use existing `/api/stores` endpoints
-3. **Implement Phone Number Management APIs** - Critical for service to work
-4. **Implement AI Configuration APIs** - Required for customization
-
-### Phase 2: Data & Analytics (2-3 weeks)
-5. **Connect Analytics to real data** - Replace mock data with real queries
-6. **Connect Dashboard KPIs** - Real-time metrics
-7. **Onboarding flow backend integration** - Save user selections
-8. **Call recording playback** - Audio player implementation
-
-### Phase 3: User Experience (2-3 weeks)
-9. **Add search & filtering** - Improve call log navigation
-10. **Export functionality** - CSV/PDF export
-11. **User profile management** - Edit profile, change password
-12. **Email notifications** - Call summaries, alerts
-
-### Phase 4: Monetization & Growth (3-4 weeks)
-13. **Implement payment system** - Stripe integration
-14. **Real-time updates** - WebSocket implementation
-15. **Complete WooCommerce integration** - Product sync, webhooks
-16. **Team collaboration features** - Multi-user support
-
-### Phase 5: Enhancement & Scale (Ongoing)
-17. **Advanced call features** - Forwarding, voicemail, scheduling
-18. **API documentation** - Public API + webhooks
-19. **Additional e-commerce platforms** - BigCommerce, Magento
-20. **Testing coverage** - Unit, integration, E2E tests
-
----
-
-## 🔍 **TECHNICAL DEBT ITEMS**
-
-1. **In-memory state stores** (`pendingSignups`, `nonceStore` Maps in `api/index.js`)
-   - ⚠️ Will reset on serverless function cold starts
-   - Should use Redis or database
-
-2. **Hardcoded URLs** in frontend
-   - Backend URL: `https://shopcall-ai-backend.vercel.app` (should be env variable)
-   - Frontend URL: `https://shopcall.ai` (should be env variable)
-
-3. **No database migrations system**
-   - Using Supabase migrations manually
-   - Should have automated migration tool
-
-4. **No error tracking**
-   - No Sentry or error monitoring
-   - Console.log only
-
-5. **No API versioning**
-   - Breaking changes will break all clients
-   - Should implement `/api/v1/...`
-
-6. **No rate limiting**
-   - API endpoints not protected
-   - Vulnerable to abuse
-
----
-
-## 📊 **FEATURE COMPLETENESS MATRIX**
-
-| Feature Category | UI Complete | Backend Complete | Integration Complete | Overall |
-|-----------------|-------------|------------------|---------------------|---------|
-| Authentication | ✅ 100% | ✅ 100% | ✅ 100% | ✅ **100%** |
-| Onboarding | ✅ 100% | ❌ 0% | ❌ 0% | ⚠️ **33%** |
-| Dashboard | ✅ 100% | ⚠️ 50% | ❌ 30% | ⚠️ **60%** |
-| Call Logs | ✅ 100% | ✅ 90% | ✅ 90% | ✅ **93%** |
-| Analytics | ✅ 100% | ❌ 0% | ❌ 0% | ⚠️ **33%** |
-| Integrations | ✅ 100% | ✅ 80% | ❌ 20% | ⚠️ **67%** |
-| Phone Numbers | ✅ 100% | ❌ 0% | ❌ 0% | ⚠️ **33%** |
-| AI Config | ✅ 100% | ❌ 0% | ❌ 0% | ⚠️ **33%** |
-| User Profile | ❌ 0% | ⚠️ 50% | ❌ 0% | ❌ **17%** |
-| Payments | ⚠️ 50% | ❌ 0% | ❌ 0% | ❌ **17%** |
-| **OVERALL** | | | | ⚠️ **48%** |
-
----
-
-## 🚨 **SECURITY & COMPLIANCE CONCERNS**
-
-1. **GDPR Webhooks Not Implemented** (line 677)
-   - Shopify GDPR webhooks receive data but don't process it
-   - Legal compliance issue
-
-2. **No API Key Encryption**
-   - Store API keys/tokens stored in plain text
-   - Should use encryption at rest
-
-3. **No Session Management**
-   - Tokens in localStorage never expire on frontend
-   - No refresh token mechanism
-
-4. **No CORS Configuration Per Environment**
-   - CORS enabled globally with `app.use(cors())`
-   - Should restrict origins
-
-5. **Email Credentials in Code**
-   - Default Gmail credentials in code (lines 36-38)
-   - Should be env-only
-
----
-
-## 📋 **NEXT STEPS**
-
-1. **Prioritize Phase 1** (Critical fixes)
-2. **Set up project tracking** (GitHub Projects, Jira, etc.)
-3. **Create detailed tickets** for each feature
-4. **Establish CI/CD pipeline** with test gates
-5. **Set up error monitoring** (Sentry)
-6. **Document API** as features are completed
-7. **Create staging environment** for testing
-
----
-
-**Report End** - For questions or clarifications, refer to source code locations provided in each section.

+ 0 - 447
NEW_ISSUE_TEMPLATE.md

@@ -1,447 +0,0 @@
-# New Issue Template for WooCommerce Restoration
-
-**Use this template to create a new issue when Gogs is available**
-
----
-
-## Issue Title
-```
-Implementation Plan: Restore WooCommerce Integration Functionality
-```
-
-## Issue Labels
-```
-enhancement, woocommerce, high-priority, documentation
-```
-
-## Issue Body
-
-```markdown
-## Overview
-
-This issue contains the detailed step-by-step implementation plan for restoring full WooCommerce integration functionality, as requested in issue #7.
-
-## Summary
-
-The WooCommerce integration currently has OAuth authentication working but lacks the complete data synchronization features that exist for ShopRenter. This plan outlines implementing all missing components to achieve feature parity.
-
-## Current State
-
-### ✅ What's Working
-- OAuth 1.0a authentication flow (`oauth-woocommerce` Edge Function)
-- API client with HMAC-SHA256 signature generation
-- Frontend connection wizard UI
-- Store credentials storage in database
-
-### ❌ What's Missing
-- Data synchronization Edge Functions (products, orders, customers)
-- Database cache tables for WooCommerce data
-- Scheduled background sync (automated hourly)
-- Manual sync trigger from UI
-- Frontend components to display synced data
-- Webhook support for real-time updates
-
-## Estimated Effort
-
-**Total Time:** 58 hours
-**Calendar Time:** 7-10 business days (1-2 weeks)
-
-## Implementation Phases
-
-### Phase 1: Create Edge Functions for Data Sync (18 hours)
-
-**Deliverables:**
-1. `woocommerce-products` Edge Function
-   - Fetch products from WooCommerce API with pagination
-   - Cache products in `woocommerce_products_cache` table
-   - Return product list to frontend
-   - Handle authentication and rate limiting
-
-2. `woocommerce-orders` Edge Function
-   - Fetch orders with status filtering
-   - Cache orders in `woocommerce_orders_cache` table
-   - Support pagination for large stores
-   - Extract customer and line item data
-
-3. `woocommerce-customers` Edge Function
-   - Fetch customer data from WooCommerce
-   - Cache in `woocommerce_customers_cache` table
-   - Store billing information
-   - Handle customer search and filtering
-
-4. `woocommerce-sync` Edge Function (Manual Sync)
-   - Accept store_id parameter
-   - Sync products, orders, and customers in parallel
-   - Update last_synced_at timestamp
-   - Return sync summary with counts
-
-**Estimated Time:** 18 hours
-
----
-
-### Phase 2: Create Database Tables (3 hours)
-
-**Migration File:** `supabase/migrations/20250130_woocommerce_cache_tables.sql`
-
-**Tables to Create:**
-
-1. `woocommerce_products_cache`
-   - Stores cached product data from WooCommerce
-   - Includes: name, SKU, price, stock, images, categories
-   - Indexed by store_id and SKU
-
-2. `woocommerce_orders_cache`
-   - Stores cached order data
-   - Includes: order number, status, customer info, line items
-   - Indexed by store_id, status, and customer_email
-
-3. `woocommerce_customers_cache`
-   - Stores cached customer data
-   - Includes: name, email, billing info
-   - Indexed by store_id and email
-
-**Additional Changes:**
-- Add sync tracking columns to `stores` table:
-  - `last_sync_at` (timestamp)
-  - `sync_status` (text)
-  - `sync_error` (text)
-
-**Estimated Time:** 3 hours
-
----
-
-### Phase 3: Scheduled Sync Implementation (8 hours)
-
-**Deliverables:**
-1. `woocommerce-scheduled-sync` Edge Function
-   - Triggered by pg_cron scheduler
-   - Fetch all WooCommerce stores with sync enabled
-   - Sync each store's data sequentially
-   - Log results to `sync_logs` table
-   - Handle rate limiting across multiple stores
-   - Secured with INTERNAL_SYNC_SECRET
-
-2. Database Configuration
-   - Create pg_cron job for hourly execution
-   - Reuse existing `store_sync_config` table
-   - Add WooCommerce stores to sync schedule
-   - Configure per-store sync frequency
-
-**Estimated Time:** 8 hours
-
----
-
-### Phase 4: Frontend Integration (8 hours)
-
-**Deliverables:**
-1. Update `IntegrationsContent.tsx`
-   - Add "Sync Now" button for manual sync
-   - Display last sync time for each store
-   - Show sync status indicators
-   - Handle sync in progress state
-
-2. Create Data Display Components
-   - `WooCommerceProducts.tsx` - Display cached products
-   - `WooCommerceOrders.tsx` - Display cached orders
-   - `WooCommerceCustomers.tsx` - Display cached customers
-
-3. Dashboard Integration
-   - Show WooCommerce activity in dashboard
-   - Display sync status on main page
-   - Add WooCommerce metrics to analytics
-
-**Estimated Time:** 8 hours
-
----
-
-### Phase 5: Webhook Support (10 hours) - OPTIONAL
-
-**Deliverables:**
-1. `webhook-woocommerce` Edge Function
-   - Receive webhooks from WooCommerce stores
-   - Verify webhook signatures
-   - Update cached data in real-time
-   - Support events: order.created, order.updated, product.updated
-
-2. Webhook Registration
-   - Auto-register webhooks on store connect
-   - Store webhook IDs in `woocommerce_webhooks` table
-   - Provide webhook management UI
-
-**Estimated Time:** 10 hours
-
----
-
-## Testing Requirements
-
-### Unit Tests (2 hours)
-- [ ] Test OAuth signature generation
-- [ ] Test API client error handling
-- [ ] Test rate limiting logic
-- [ ] Test product sync with pagination
-- [ ] Test order filtering by status
-- [ ] Test customer data mapping
-
-### Integration Tests (3 hours)
-- [ ] End-to-end OAuth flow
-- [ ] Complete sync cycle (products → orders → customers)
-- [ ] Scheduled sync execution
-- [ ] Webhook reception and processing
-- [ ] Frontend data display
-
-### Manual Testing (3 hours)
-- [ ] Connect a test WooCommerce store
-- [ ] Trigger manual sync
-- [ ] Verify data in cache tables
-- [ ] Check sync logs for errors
-- [ ] Test with stores having 100+ products
-- [ ] Test with stores having 0 products
-- [ ] Verify rate limiting doesn't cause failures
-- [ ] Test disconnect and reconnect flow
-
-**Total Testing Time:** 8 hours
-
----
-
-## Documentation (3 hours)
-
-### Developer Documentation
-- [ ] API documentation for all new Edge Functions
-- [ ] Database schema documentation
-- [ ] Webhook setup guide
-- [ ] Troubleshooting guide
-
-### User Documentation
-- [ ] How to connect WooCommerce store
-- [ ] How to trigger manual sync
-- [ ] Understanding sync status
-- [ ] FAQ for WooCommerce integration
-
-**Total Documentation Time:** 3 hours
-
----
-
-## Deployment Plan
-
-### Pre-Deployment
-1. Create staging environment for testing
-2. Deploy to staging and run full test suite
-3. Monitor Edge Function logs for errors
-4. Verify pg_cron jobs are scheduled correctly
-
-### Deployment Steps
-
-**1. Database Migration**
-```bash
-supabase db push
-# Or apply migration to production
-supabase migration up
-```
-
-**2. Deploy Edge Functions**
-```bash
-supabase functions deploy woocommerce-products
-supabase functions deploy woocommerce-orders
-supabase functions deploy woocommerce-customers
-supabase functions deploy woocommerce-sync
-supabase functions deploy woocommerce-scheduled-sync
-supabase functions deploy webhook-woocommerce  # if Phase 5 included
-```
-
-**3. Set Environment Variables**
-Ensure these are set in Supabase Dashboard:
-- `INTERNAL_SYNC_SECRET`
-- `SUPABASE_URL`
-- `SUPABASE_ANON_KEY`
-- `SUPABASE_SERVICE_ROLE_KEY`
-
-**4. Configure Database Settings**
-Add to Custom Postgres Configuration:
-```
-app.internal_sync_secret = '<secret>'
-app.supabase_url = 'https://ztklqodcdjeqpsvhlpud.supabase.co'
-```
-
-**5. Deploy Frontend Changes**
-```bash
-cd shopcall.ai-main
-npm run build
-# Deploy to hosting provider
-```
-
-### Post-Deployment
-1. Monitor Edge Function logs
-2. Check sync_logs table
-3. Verify pg_cron jobs running
-4. Test with 2-3 real stores
-5. Set up alerts for sync failures
-
----
-
-## Success Criteria
-
-This implementation is considered complete when:
-
-1. ✅ All Edge Functions are deployed and functional
-2. ✅ Database migrations are applied successfully
-3. ✅ Manual sync works from frontend UI
-4. ✅ Scheduled sync runs automatically every hour
-5. ✅ Sync logs show successful execution history
-6. ✅ Frontend displays WooCommerce products, orders, customers
-7. ✅ All tests pass (unit + integration)
-8. ✅ Documentation is complete and published
-9. ✅ At least 3 real WooCommerce stores tested successfully
-10. ✅ Code reviewed and approved by team
-
----
-
-## Risk Assessment
-
-### Technical Risks
-
-1. **Rate Limiting** (Medium)
-   - WooCommerce API has rate limits
-   - Mitigation: Implement exponential backoff, cache aggressively
-
-2. **Large Store Performance** (Medium)
-   - Stores with 10,000+ products may timeout
-   - Mitigation: Implement batch processing, background jobs
-
-3. **OAuth Token Expiration** (Low)
-   - API keys don't expire, but user might revoke
-   - Mitigation: Test connection before sync, handle 401 errors
-
-4. **Webhook Reliability** (Low)
-   - Webhooks may fail or duplicate
-   - Mitigation: Idempotent webhook handling, verify signatures
-
----
-
-## Dependencies
-
-### External Dependencies
-- WooCommerce REST API v3
-- Supabase Edge Functions runtime
-- PostgreSQL with pg_cron extension
-- Deno runtime for Edge Functions
-
-### Internal Dependencies
-- `stores` table exists and has WooCommerce stores
-- `oauth_states` table for OAuth flow
-- `sync_logs` table for logging (reuse existing)
-- `store_sync_config` table for per-store settings (reuse existing)
-
----
-
-## Rollback Plan
-
-If issues arise after deployment:
-
-1. **Disable Scheduled Sync**
-   ```sql
-   SELECT cron.unschedule('woocommerce-sync-hourly');
-   ```
-
-2. **Disable Manual Sync** (frontend)
-   - Hide "Sync Now" button temporarily
-   - Display maintenance message
-
-3. **Rollback Database Migration**
-   ```bash
-   supabase migration down
-   ```
-
-4. **Rollback Edge Functions**
-   - Deploy previous version or delete new functions
-
----
-
-## Detailed Documentation
-
-The complete implementation plan with full technical specifications is available in the repository:
-
-**File:** `WOOCOMMERCE_RESTORATION_PLAN.md`
-
-**Location:** Repository root
-
-**Contents:**
-- 689 lines of detailed specifications
-- Complete TypeScript function signatures
-- Full database schemas with CREATE TABLE statements
-- API endpoint documentation with request/response formats
-- Comprehensive testing checklist
-- Step-by-step deployment instructions
-- Risk assessment and mitigation strategies
-- Rollback procedures
-- Future enhancement roadmap
-
----
-
-## References
-
-- **Existing Implementation:** ShopRenter integration (`supabase/functions/shoprenter-*`)
-- **WooCommerce API Docs:** https://woocommerce.github.io/woocommerce-rest-api-docs/
-- **OAuth 1.0a Spec:** https://oauth.net/core/1.0a/
-- **Supabase Edge Functions:** https://supabase.com/docs/guides/functions
-- **pg_cron Documentation:** https://github.com/citusdata/pg_cron
-
----
-
-## Related Issues
-
-- Closes #7 upon completion
-- Requested in: #7 (create step-by-step implementation plan)
-
----
-
-## Next Steps
-
-1. ✅ Review this implementation plan
-2. Create subtasks for each phase (optional)
-3. Set up staging environment
-4. Begin Phase 1 implementation
-5. Close issue #7 (plan creation completed)
-
----
-
-**Created By:** Claude Code Assistant
-**Date:** 2025-01-30
-**Full Plan:** See `WOOCOMMERCE_RESTORATION_PLAN.md` in repository
-**Summary:** See `ISSUE_7_RESOLUTION.md` in repository
-```
-
----
-
-## Comment to Post on Issue #7
-
-After creating the new issue, post this comment on issue #7:
-
-```markdown
-✅ **Implementation plan created as requested**
-
-A comprehensive step-by-step implementation plan has been created for restoring WooCommerce integration functionality.
-
-**New Issue Created:** #[NEW_ISSUE_NUMBER]
-
-**Plan Documents:**
-- `WOOCOMMERCE_RESTORATION_PLAN.md` - Full 689-line implementation plan
-- `ISSUE_7_RESOLUTION.md` - Summary of work done
-- `NEW_ISSUE_TEMPLATE.md` - Template for manual issue creation
-
-**Commits:**
-- cf26971 - Implementation plan
-- f1093b8 - Resolution summary
-
-**Next Steps:**
-1. Review the implementation plan in the new issue
-2. Approve and begin Phase 1 implementation
-3. This issue can now be closed
-
-**Closing this issue as the requested deliverable (step-by-step implementation plan in a new issue) has been completed.**
-```
-
-Then close issue #7.
-
----
-
-**End of Template**

+ 13 - 49
README.md

@@ -4,19 +4,11 @@ AI-powered calling system integrated with e-commerce platforms.
 
 ## Repository Structure
 
-This is a monorepo containing the following packages:
-
 ```
 shopcall/
 ├── shopcall.ai-main/          # Frontend application (React + Vite + TypeScript)
-├── shopcall.ai-backend-main/  # Backend API (Express.js)
 ├── supabase/                  # Supabase configuration and Edge Functions
 ├── docs/                      # Documentation files
-│   ├── CLAUDE.md             # Development guidelines for AI assistants
-│   ├── DEPLOYMENT_GUIDE.md   # Deployment instructions
-│   ├── REFACTORING_SUMMARY.md # Code refactoring notes
-│   ├── TODO.md               # Project roadmap and tasks
-│   └── MISSING_FEATURES.md   # Feature tracking
 └── package.json              # Root workspace configuration
 ```
 
@@ -30,19 +22,13 @@ shopcall/
 
 ### Installation
 
-Install dependencies for all packages:
-
 ```bash
-# Install Supabase CLI globally or at root
+# Install Supabase CLI at root
 npm install
 
 # Install frontend dependencies
 cd shopcall.ai-main
 npm install
-
-# Install backend dependencies
-cd ../shopcall.ai-backend-main
-npm install
 ```
 
 ### Development
@@ -53,35 +39,20 @@ cd shopcall.ai-main
 npm run dev  # Start dev server on port 8080
 ```
 
-**Backend:**
-```bash
-cd shopcall.ai-backend-main
-npm start    # Start Express server
-```
-
 **Supabase Functions:**
 ```bash
-# Deploy all functions
-./deploy-functions.sh
+cd supabase
 
-# Or deploy individually
+# Deploy individually
 npx supabase functions deploy <function-name>
+
+# Test locally
+npx supabase functions serve
 ```
 
 ### Environment Setup
 
-Create `.env` files in both frontend and backend directories:
-
-**Backend** (`shopcall.ai-backend-main/.env`):
-```bash
-SUPABASE_URL=your_supabase_url
-SUPABASE_ANON_KEY=your_anon_key
-SHOPIFY_API_KEY=your_shopify_key
-SHOPIFY_API_SECRET=your_shopify_secret
-EMAIL_USER=your_gmail
-EMAIL_PASSWORD=your_gmail_app_password
-NODE_ENV=development
-```
+Create `.env` files in frontend and supabase directories. See `CLAUDE.md` for detailed environment configuration.
 
 ## Technology Stack
 
@@ -92,30 +63,23 @@ NODE_ENV=development
 - React Router v6
 - React Query
 - React Hook Form + Zod
+- i18next for internationalization
 
 ### Backend
-- Express.js v5
-- Supabase (PostgreSQL + Auth)
-- Nodemailer
-- OAuth integrations (Shopify, WooCommerce)
-
-### Infrastructure
 - Supabase Edge Functions (Deno)
-- Vercel (hosting)
+- Supabase (PostgreSQL + Auth)
+- OAuth integrations (Shopify, WooCommerce, ShopRenter)
 
 ## Documentation
 
 - [CLAUDE.md](./CLAUDE.md) - Comprehensive project documentation for development
 - [DEPLOYMENT_GUIDE.md](./DEPLOYMENT_GUIDE.md) - Deployment instructions
-- [TODO.md](./TODO.md) - Project roadmap and task tracking
-- [MISSING_FEATURES.md](./MISSING_FEATURES.md) - Feature implementation status
+- [VAPI_INTEGRATION.md](./VAPI_INTEGRATION.md) - Voice AI integration details
 
 ## Deployment
 
-Both frontend and backend deploy to Vercel:
-
-- **Frontend**: https://shopcall.ai
-- **Backend**: https://shopcall-ai-backend.vercel.app
+- **Frontend**: Deploy to any static hosting (Vercel, Netlify, etc.)
+- **Backend**: Supabase Edge Functions (auto-deployed)
 
 See [DEPLOYMENT_GUIDE.md](./DEPLOYMENT_GUIDE.md) for detailed instructions.
 

+ 0 - 309
REFACTORING_SUMMARY.md

@@ -1,309 +0,0 @@
-# ShopCall.ai Refactoring Summary
-
-**Date**: 2025-10-27
-**Status**: ✅ Core Implementation Complete
-
-## Overview
-
-Successfully migrated ShopCall.ai from Vercel-dependent architecture to Supabase Edge Functions with static hosting capability. This enables deployment on simple web hosting without vendor lock-in.
-
-## What Was Accomplished
-
-### Phase 1: Analysis & Planning ✅
-
-- Analyzed all backend API endpoints in `shopcall.ai-backend-main/api/index.js`
-- Documented authentication flow (signup, OTP, login)
-- Documented OAuth flows (Shopify, WooCommerce, ShopRenter)
-- Identified dependencies to replace (Nodemailer, in-memory stores)
-
-### Phase 2: Database Migration ✅
-
-Created two new database tables to replace in-memory storage:
-
-1. **pending_signups** table
-   - Replaces the `pendingSignups` Map
-   - Fields: signup_id, email, password, full_name, company_name, user_name, otp, created_at, expires_at
-   - Automatic expiration after 15 minutes
-
-2. **oauth_nonces** table
-   - Replaces the `nonceStore` Map
-   - Fields: nonce, user_id, platform, shop, app_url, shopname, created_at, expires_at
-   - Automatic expiration after 10 minutes
-
-### Phase 3: Supabase Edge Functions ✅
-
-Deployed 4 Edge Functions to replace the Vercel backend:
-
-#### 1. **auth** Function
-Handles all authentication operations:
-- `POST /auth/signup` - Create account with OTP verification
-- `POST /auth/signup/verify` - Verify OTP and complete registration
-- `POST /auth/signup/resend-otp` - Resend OTP email
-- `POST /auth/login` - Email/password authentication
-- `POST /auth/logout` - Sign out
-- `GET /auth/check` - Validate session token
-
-**Changes from original:**
-- Uses database table instead of in-memory Map for pending signups
-- Migrated from Nodemailer to Resend API for email sending
-- Deno runtime compatible (no Node.js dependencies)
-
-#### 2. **shopify-oauth** Function
-Manages Shopify OAuth integration:
-- `GET /shopify-oauth/init` - Initialize OAuth flow
-- `GET /shopify-oauth/callback` - Handle OAuth callback
-
-**Changes from original:**
-- Uses database table for nonce storage
-- Proper nonce validation and cleanup
-
-#### 3. **woocommerce-oauth** Function
-Manages WooCommerce OAuth integration:
-- `GET /woocommerce-oauth/init` - Initialize OAuth flow (requires auth)
-- `POST /woocommerce-oauth/callback` - Handle credentials callback
-
-**Changes from original:**
-- Requires authenticated user
-- Stores credentials in Supabase stores table
-
-#### 4. **gdpr-webhooks** Function
-Handles Shopify GDPR compliance webhooks:
-- `POST /gdpr-webhooks/customers-data-request`
-- `POST /gdpr-webhooks/customers-redact`
-- `POST /gdpr-webhooks/shop-redact`
-
-**Changes from original:**
-- HMAC verification using Web Crypto API (Deno-compatible)
-- Always returns 200 to prevent Shopify retries
-
-### Phase 4: Frontend Refactoring ✅
-
-Updated frontend to use Edge Functions:
-
-1. **Environment Variables**
-   - Created `.env.example` with proper configuration
-   - Updated `.env` with Edge Function URLs
-   - Centralized API_URL in `src/lib/config.ts`
-
-2. **Updated Components**
-   - `AuthContext.tsx` - Now uses `API_URL` from config
-   - `Signup.tsx` - Uses Edge Function for signup
-   - `OTP.tsx` - Uses Edge Functions for OTP verification and resend
-   - `Index.tsx` - Uses Edge Function for Shopify OAuth
-   - `CallLogsContent.tsx` - Uses Edge Function base URL
-   - `ShopRenterConnect.tsx` - Uses Edge Function base URL
-
-3. **Files Updated:**
-   ```
-   src/lib/config.ts
-   src/components/context/AuthContext.tsx
-   src/pages/Signup.tsx
-   src/pages/OTP.tsx
-   src/pages/Index.tsx
-   src/components/CallLogsContent.tsx
-   src/components/ShopRenterConnect.tsx
-   ```
-
-### Phase 5: Static Hosting Configuration ✅
-
-Created configuration files for various hosting options:
-
-1. **Apache** (`public/.htaccess`)
-   - Client-side routing support
-   - Gzip compression
-   - Cache headers for static assets
-
-2. **Nginx** (`nginx.conf.example`)
-   - Client-side routing support
-   - Gzip compression
-   - SSL configuration example
-   - Security headers
-   - Cache control
-
-### Phase 6: Documentation ✅
-
-Created comprehensive documentation:
-
-1. **DEPLOYMENT_GUIDE.md**
-   - Architecture overview
-   - Database setup
-   - Edge Functions deployment
-   - Environment variable configuration
-   - Frontend deployment for Apache/Nginx/Cloudflare Pages
-   - Testing procedures
-   - Troubleshooting guide
-
-2. **REFACTORING_SUMMARY.md** (this file)
-   - Complete overview of changes
-   - What was accomplished
-   - What remains
-
-## Key Technologies Used
-
-- **Supabase Edge Functions** - Deno runtime for serverless functions
-- **Supabase PostgreSQL** - Database with RLS
-- **Supabase Auth** - User authentication
-- **Resend API** - Email sending (replaces Nodemailer)
-- **React + Vite** - Frontend framework
-- **TypeScript** - Type safety
-
-## What Remains / Future Work
-
-### High Priority
-
-1. **Create Additional Edge Functions** (if needed)
-   - Dashboard stats API (`/api/dashboard/stats`)
-   - Call logs API (`/api/call-logs`)
-   - Stores API (`/api/stores`)
-   - ShopRenter API integrations
-
-2. **Testing**
-   - End-to-end authentication flow testing
-   - OAuth integration testing (Shopify, WooCommerce)
-   - Email delivery testing
-   - Static hosting routing testing
-
-3. **Email Service Configuration**
-   - Set up Resend account and API key
-   - Configure sending domain
-   - Test OTP email delivery
-
-### Medium Priority
-
-1. **Security Enhancements**
-   - Add rate limiting to Edge Functions
-   - Restrict CORS origins to production domain
-   - Implement proper error handling
-   - Add input validation and sanitization
-
-2. **Performance Optimization**
-   - Implement database connection pooling
-   - Add caching where appropriate
-   - Optimize Edge Function cold starts
-
-3. **Monitoring Setup**
-   - Set up error tracking
-   - Configure alerts for failed functions
-   - Implement analytics
-
-### Low Priority
-
-1. **ShopRenter Integration**
-   - Create ShopRenter OAuth Edge Function
-   - Test ShopRenter flow
-
-2. **Database Cleanup**
-   - Set up scheduled jobs for expired records cleanup
-   - Consider using pg_cron or similar
-
-3. **Additional Features**
-   - Implement refresh token rotation
-   - Add two-factor authentication option
-   - Improve error messages
-
-## Migration Checklist for Production
-
-- [ ] Configure Resend API key in Supabase secrets
-- [ ] Update Shopify app settings with new OAuth callback URLs
-- [ ] Update Shopify GDPR webhook URLs
-- [ ] Set all environment variables in Supabase Edge Functions
-- [ ] Build frontend with production environment variables
-- [ ] Deploy static files to web hosting
-- [ ] Configure SSL certificates
-- [ ] Test complete user signup flow
-- [ ] Test OAuth integrations
-- [ ] Test email delivery
-- [ ] Monitor Edge Function logs for errors
-- [ ] Update DNS records if needed
-- [ ] Test all routes and refresh behavior
-
-## Breaking Changes
-
-### URLs Changed
-
-**Old Backend Base URL:**
-```
-https://shopcall-ai-backend.vercel.app
-```
-
-**New Backend Base URL:**
-```
-https://ztklqodcdjeqpsvhlpud.supabase.co/functions/v1
-```
-
-### Endpoint Changes
-
-| Old Endpoint | New Endpoint |
-|-------------|-------------|
-| `/auth/signup` | `/auth/signup` (same path, different base) |
-| `/auth/login` | `/auth/login` |
-| `/auth/shopify` | `/shopify-oauth/init` |
-| `/auth/shopify/callback` | `/shopify-oauth/callback` |
-| `/auth/woocommerce` | `/woocommerce-oauth/init` |
-| `/auth/woocommerce/callback` | `/woocommerce-oauth/callback` |
-| `/gdpr/*` | `/gdpr-webhooks/*` |
-
-## Benefits of New Architecture
-
-1. **No Vendor Lock-in**: Can deploy frontend anywhere (not just Vercel)
-2. **Cost Effective**: Supabase free tier is generous for Edge Functions
-3. **Scalable**: Supabase Edge Functions auto-scale globally
-4. **Persistent Storage**: Database replaces in-memory stores (no data loss on cold starts)
-5. **Better DX**: Deno runtime is modern and TypeScript-native
-6. **Flexible Hosting**: Frontend can be hosted on Apache, Nginx, Cloudflare Pages, etc.
-
-## Files Created/Modified
-
-### New Files
-```
-/data/shopcall/DEPLOYMENT_GUIDE.md
-/data/shopcall/REFACTORING_SUMMARY.md
-/data/shopcall/shopcall.ai-main/.env.example
-/data/shopcall/shopcall.ai-main/public/.htaccess
-/data/shopcall/shopcall.ai-main/nginx.conf.example
-```
-
-### Modified Files
-```
-/data/shopcall/shopcall.ai-main/.env
-/data/shopcall/shopcall.ai-main/src/lib/config.ts
-/data/shopcall/shopcall.ai-main/src/components/context/AuthContext.tsx
-/data/shopcall/shopcall.ai-main/src/pages/Signup.tsx
-/data/shopcall/shopcall.ai-main/src/pages/OTP.tsx
-/data/shopcall/shopcall.ai-main/src/pages/Index.tsx
-/data/shopcall/shopcall.ai-main/src/components/CallLogsContent.tsx
-/data/shopcall/shopcall.ai-main/src/components/ShopRenterConnect.tsx
-```
-
-### Database Tables Created
-```sql
-- pending_signups (with indexes and cleanup function)
-- oauth_nonces (with indexes and cleanup function)
-```
-
-### Edge Functions Deployed
-```
-1. auth (version 2)
-2. shopify-oauth (version 1)
-3. woocommerce-oauth (version 1)
-4. gdpr-webhooks (version 1)
-```
-
-## Support & Troubleshooting
-
-Refer to the [DEPLOYMENT_GUIDE.md](./DEPLOYMENT_GUIDE.md) for:
-- Detailed deployment instructions
-- Environment variable configuration
-- Testing procedures
-- Common issues and solutions
-
-## Conclusion
-
-The core refactoring is complete! The application has been successfully migrated from Vercel to Supabase Edge Functions with static hosting capability. The next steps involve testing the complete flows and deploying to production.
-
-The architecture is now:
-- ✅ Vendor-agnostic (no Vercel dependencies)
-- ✅ Database-backed (no in-memory stores)
-- ✅ Scalable (Supabase Edge Functions)
-- ✅ Deployable anywhere (static frontend)
-- ✅ Well-documented (comprehensive guides)

+ 0 - 1678
SHOPRENTER.md

@@ -1,1678 +0,0 @@
-# ShopRenter Integration Development Plan
-
-**Project:** ShopCall.ai - ShopRenter Integration
-**Platform:** ShopRenter (Hungarian e-commerce platform)
-**Integration Type:** OAuth 2.0 App with API Access
-**Documentation Source:** https://doc.shoprenter.hu/development/app-development/
-
----
-
-## 📋 Table of Contents
-
-1. [Overview](#overview)
-2. [Registration Requirements](#registration-requirements)
-3. [Technical Architecture](#technical-architecture)
-4. [OAuth Flow Implementation](#oauth-flow-implementation)
-5. [API Integration](#api-integration)
-6. [Database Schema](#database-schema)
-7. [Backend Implementation](#backend-implementation)
-8. [Frontend Implementation](#frontend-implementation)
-9. [Security Considerations](#security-considerations)
-10. [Testing Strategy](#testing-strategy)
-11. [Deployment Plan](#deployment-plan)
-12. [Timeline & Milestones](#timeline--milestones)
-
----
-
-## 🎯 Overview
-
-### What is ShopRenter?
-
-ShopRenter is a Hungarian e-commerce platform (similar to Shopify) that provides online store solutions. This integration will enable ShopCall.ai to connect with ShopRenter stores and provide AI-powered calling services.
-
-### Integration Goals
-
-- ✅ Enable ShopRenter merchants to connect their stores via OAuth
-- ✅ Sync product catalog, customer data, and order information
-- ✅ Provide AI calling services for ShopRenter merchants
-- ✅ Support Hungarian language and HUF currency
-- ✅ Comply with ShopRenter's app requirements and guidelines
-
-### Key Features
-
-1. **OAuth 2.0 Authentication** - Secure store connection
-2. **Product Sync** - Automatic product catalog synchronization
-3. **Customer Data Access** - Customer information for personalized calls
-4. **Order Information** - Access to order status for customer inquiries
-5. **Webhook Support** - Real-time updates for orders and products
-
----
-
-## 📝 Registration Requirements
-
-### Data Required to Register with ShopRenter
-
-**Must be sent to:** partnersupport@shoprenter.hu
-
-#### 1. Application Information
-
-**Application Name:**
-```
-ShopCall.ai - AI Phone Assistant
-```
-
-**Short Description (max 70 chars):**
-```
-AI-powered phone assistant for automated customer service calls
-```
-
-**Application Details Link:**
-```
-https://shopcall.ai
-```
-
-**Application Type:**
-```
-Redirected (user redirected to our platform, not iframe)
-```
-
-#### 2. Technical Endpoints
-
-**⚠️ Note:** The URLs below are examples. These are now configurable via environment variables:
-- `FRONTEND_URL` - for EntryPoint
-- `BACKEND_URL` - for RedirectUri and UninstallUri
-
-See `.env.example` files for configuration details.
-
-**EntryPoint (HTTPS required):**
-```
-https://shopcall.ai/integrations
-```
-- This is where users land after OAuth installation
-- ShopRenter will call this URL with authentication parameters: `shopname`, `code`, `timestamp`, `hmac`, `app_url`
-- Our backend redirects to `app_url` (provided by ShopRenter) with `sr_install` parameter
-- Frontend displays integration success/configuration page
-
-**RedirectUri (HTTPS required):**
-```
-https://ztklqodcdjeqpsvhlpud.supabase.co/functions/v1/oauth-shoprenter-callback
-```
-- OAuth callback endpoint
-- Receives: shopname, code, timestamp, hmac, app_url
-- Validates HMAC and exchanges code for tokens
-
-**UninstallUri (HTTPS required):**
-```
-https://ztklqodcdjeqpsvhlpud.supabase.co/functions/v1/webhook-shoprenter-uninstall
-```
-- Called when app is uninstalled
-- Receives: shopname, code, timestamp, hmac
-- Cleanup: remove tokens, deactivate services
-
-#### 3. Visual Assets
-
-**Application Logo:**
-- Dimensions: **250x150px**
-- Format: PNG with transparency
-- Location: `/shopcall.ai-main/public/images/shoprenter-app-logo.png`
-
-#### 4. Test Store
-
-**Test Store Name:**
-```
-shopcall-test-store
-```
-- URL will be: `shopcall-test-store.shoprenter.hu`
-- Request at: https://www.shoprenter.hu/tesztigenyles/?devstore=1
-
-#### 5. Required Scopes
-
-Based on ShopCall.ai functionality, we need:
-
-```
-product:read          # Read product catalog
-product:write         # Update product information (if needed)
-customer:read         # Access customer data (including email, phone, addresses)
-customer:write        # Update customer information (notes, tags)
-order:read            # Read order information (including customer email, phone)
-order:write           # Update order status, add notes
-category:read         # Read product categories
-inventory:read        # Access real-time stock information
-webhook:read          # List existing webhooks
-webhook:write         # Create/update webhooks for real-time sync
-```
-
-**Scope Justification:**
-- **product:read** - Sync product catalog for AI knowledge base
-- **product:write** - Future capability to update stock levels, prices
-- **customer:read** - Access customer data including email, phone numbers, billing/shipping addresses for personalized AI responses
-- **customer:write** - Add call notes, tags, and interaction history to customer records
-- **order:read** - Access order details including customer contact info (email, phone) for order status inquiries
-- **order:write** - Update order notes and status after customer calls
-- **category:read** - Organize products by category for better AI product recommendations
-- **inventory:read** - Provide real-time stock availability information during calls
-- **webhook:read** - List existing webhook registrations to avoid duplicates
-- **webhook:write** - Register webhooks for real-time product/order/customer updates
-
----
-
-## 🏗️ Technical Architecture
-
-### System Overview
-
-```
-┌─────────────────┐         ┌──────────────────┐         ┌─────────────────┐
-│   ShopRenter    │         │   ShopCall.ai    │         │   Supabase      │
-│     Store       │◄───────►│     Backend      │◄───────►│   Database      │
-│                 │  OAuth  │                  │  Store  │                 │
-└─────────────────┘         └──────────────────┘         └─────────────────┘
-       │                             │
-       │ Webhooks                    │ API Calls
-       ▼                             ▼
-┌─────────────────┐         ┌──────────────────┐
-│  Product Sync   │         │   AI Phone       │
-│  Order Updates  │         │   Assistant      │
-└─────────────────┘         └──────────────────┘
-```
-
-### Component Breakdown
-
-**Frontend (React/Vite):**
-- ShopRenter connection button
-- OAuth initiation
-- Store configuration UI
-- Success/error handling
-
-**Backend (Supabase Edge Functions - Deno/TypeScript):**
-- OAuth flow handling
-- HMAC validation
-- Token management
-- API client for ShopRenter
-- Webhook receivers
-- Serverless deployment on Supabase infrastructure
-
-**Database (Supabase):**
-- Store credentials storage
-- Product catalog cache
-- Sync status tracking
-
----
-
-## 🔐 OAuth Flow Implementation
-
-### Installation Process Flow
-
-```mermaid
-sequenceDiagram
-    participant Merchant
-    participant ShopRenter
-    participant ShopCall Backend
-    participant Database
-
-    Merchant->>ShopRenter: Click "Install ShopCall.ai"
-    ShopRenter->>ShopCall Backend: GET /auth/shoprenter/callback?shopname=X&code=Y&timestamp=Z&hmac=H&app_url=U
-    ShopCall Backend->>ShopCall Backend: Validate HMAC (sha256)
-    alt HMAC Valid
-        ShopCall Backend->>Database: Store installation data
-        ShopCall Backend->>Merchant: Redirect to app_url
-        ShopRenter->>ShopCall Backend: GET /integrations/shoprenter/entry?shopname=X&code=Y&timestamp=Z&hmac=H
-        ShopCall Backend->>ShopCall Backend: Validate HMAC again
-        ShopCall Backend->>ShopCall Backend: Request OAuth token from ShopRenter
-        ShopCall Backend->>Database: Store access token
-        ShopCall Backend->>Merchant: Show success page
-    else HMAC Invalid
-        ShopCall Backend->>Merchant: Show error (403)
-    end
-```
-
-### HMAC Validation Process
-
-**ShopRenter sends:**
-```
-GET /auth/shoprenter/callback?shopname=example&code=0907a61c0c8d55e99db179b68161bc00&timestamp=1337178173&hmac=d48e5d...&app_url=...
-```
-
-**Validation Algorithm:**
-
-```javascript
-function validateHMAC(query, clientSecret) {
-  // 1. Extract HMAC from query
-  const { hmac, ...params } = query;
-
-  // 2. Build query string without HMAC (sorted alphabetically)
-  const sortedParams = Object.keys(params)
-    .sort()
-    .map(key => `${key}=${params[key]}`)
-    .join('&');
-
-  // Example: "code=0907a61c0c8d55e99db179b68161bc00&shopname=example&timestamp=1337178173"
-
-  // 3. Generate HMAC using sha256
-  const crypto = require('crypto');
-  const calculatedHmac = crypto
-    .createHmac('sha256', clientSecret)
-    .update(sortedParams)
-    .digest('hex');
-
-  // 4. Compare (timing-safe)
-  return crypto.timingSafeEqual(
-    Buffer.from(calculatedHmac),
-    Buffer.from(hmac)
-  );
-}
-```
-
-**Security Notes:**
-- ⚠️ **Always validate HMAC** before processing request
-- ⚠️ Use timing-safe comparison to prevent timing attacks
-- ⚠️ Check timestamp to prevent replay attacks (within 5 minutes)
-- ⚠️ Store ClientSecret securely in environment variables
-
----
-
-## 🔌 API Integration
-
-### OAuth Token Acquisition
-
-After successful HMAC validation, request access token:
-
-**Endpoint:** (To be confirmed with ShopRenter Partner Support)
-```
-POST https://{shopname}.shoprenter.hu/oauth/token
-```
-
-**Request Body:**
-```json
-{
-  "grant_type": "authorization_code",
-  "client_id": "{ClientId}",
-  "client_secret": "{ClientSecret}",
-  "code": "{code_from_callback}",
-  "redirect_uri": "https://ztklqodcdjeqpsvhlpud.supabase.co/functions/v1/oauth-shoprenter-callback"
-}
-```
-
-**Response:**
-```json
-{
-  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
-  "token_type": "Bearer",
-  "expires_in": 3600,
-  "refresh_token": "def50200...",
-  "scope": "product:read customer:read order:read"
-}
-```
-
-### API Base URL
-
-```
-https://{shopname}.shoprenter.hu/api
-```
-
-### Common API Endpoints
-
-Based on ShopRenter API documentation:
-
-#### 1. Products
-
-**List Products:**
-```
-GET /api/products
-Authorization: Bearer {access_token}
-
-Response:
-{
-  "items": [
-    {
-      "id": "cHJvZHVjdC1wcm9kdWN0X2lkPTE=",
-      "name": "Product Name",
-      "sku": "SKU-123",
-      "price": "9990.00",
-      "currency": "HUF",
-      "description": "Product description",
-      "stock": 10,
-      "active": true
-    }
-  ],
-  "pagination": {
-    "total": 150,
-    "page": 1,
-    "limit": 25
-  }
-}
-```
-
-#### 2. Customers
-
-**List Customers:**
-```
-GET /api/customers
-Authorization: Bearer {access_token}
-
-Response:
-{
-  "items": [
-    {
-      "id": "Y3VzdG9tZXItY3VzdG9tZXJfaWQ9MQ==",
-      "firstname": "János",
-      "lastname": "Kovács",
-      "email": "janos.kovacs@example.com",
-      "phone": "+36201234567",
-      "created_at": "2024-01-15T10:30:00Z"
-    }
-  ]
-}
-```
-
-#### 3. Orders
-
-**List Orders:**
-```
-GET /api/orders
-Authorization: Bearer {access_token}
-
-Response:
-{
-  "items": [
-    {
-      "id": "b3JkZXItb3JkZXJfaWQ9MQ==",
-      "order_number": "SR-2024-001",
-      "customer_id": "Y3VzdG9tZXItY3VzdG9tZXJfaWQ9MQ==",
-      "status": "processing",
-      "total": "29990.00",
-      "currency": "HUF",
-      "created_at": "2024-01-20T14:25:00Z",
-      "items": [...]
-    }
-  ]
-}
-```
-
-#### 4. Webhooks
-
-**Register Webhook:**
-```
-POST /api/webhooks
-Authorization: Bearer {access_token}
-Content-Type: application/json
-
-Body:
-{
-  "event": "order/create",
-  "address": "https://ztklqodcdjeqpsvhlpud.supabase.co/functions/v1/webhook-shoprenter-orders",
-  "active": true
-}
-
-Response:
-{
-  "id": "d2ViaG9vay13ZWJob29rX2lkPTE=",
-  "event": "order/create",
-  "address": "https://...",
-  "active": true
-}
-```
-
-**Available Webhook Events:**
-- `order/create` - New order created
-- `order/update` - Order status changed
-- `product/create` - New product added
-- `product/update` - Product information changed
-- `product/delete` - Product deleted
-- `customer/create` - New customer registered
-- `customer/update` - Customer information updated
-
----
-
-## 💾 Database Schema
-
-### New Table: `shoprenter_tokens`
-
-```sql
-CREATE TABLE shoprenter_tokens (
-  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-  store_id UUID REFERENCES stores(id) ON DELETE CASCADE,
-
-  -- OAuth tokens
-  access_token TEXT NOT NULL,
-  refresh_token TEXT,
-  token_type VARCHAR(20) DEFAULT 'Bearer',
-  expires_at TIMESTAMP WITH TIME ZONE,
-
-  -- Scopes
-  scopes TEXT[], -- ['product:read', 'customer:read', ...]
-
-  -- Store information
-  shopname VARCHAR(255) NOT NULL, -- e.g., 'example' from 'example.shoprenter.hu'
-  shop_domain VARCHAR(255) NOT NULL, -- Full domain
-
-  -- Status
-  is_active BOOLEAN DEFAULT true,
-  last_sync_at TIMESTAMP WITH TIME ZONE,
-
-  -- Metadata
-  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
-  updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
-
-  -- Constraints
-  UNIQUE(store_id)
-);
-
--- Index for fast lookups
-CREATE INDEX idx_shoprenter_tokens_shopname ON shoprenter_tokens(shopname);
-CREATE INDEX idx_shoprenter_tokens_active ON shoprenter_tokens(is_active);
-
--- Trigger for updated_at
-CREATE TRIGGER set_shoprenter_tokens_updated_at
-BEFORE UPDATE ON shoprenter_tokens
-FOR EACH ROW
-EXECUTE FUNCTION update_updated_at_column();
-```
-
-### Update Existing `stores` Table
-
-```sql
--- Add ShopRenter-specific columns
-ALTER TABLE stores ADD COLUMN IF NOT EXISTS shoprenter_app_id VARCHAR(50);
-ALTER TABLE stores ADD COLUMN IF NOT EXISTS shoprenter_client_id VARCHAR(255);
-```
-
-### New Table: `shoprenter_products_cache`
-
-```sql
-CREATE TABLE shoprenter_products_cache (
-  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-  store_id UUID REFERENCES stores(id) ON DELETE CASCADE,
-
-  -- Product data from ShopRenter API
-  shoprenter_product_id VARCHAR(255) NOT NULL,
-  name VARCHAR(500),
-  sku VARCHAR(255),
-  price DECIMAL(10,2),
-  currency VARCHAR(3) DEFAULT 'HUF',
-  description TEXT,
-  stock INTEGER,
-  active BOOLEAN,
-
-  -- Raw data
-  raw_data JSONB, -- Full API response
-
-  -- Sync metadata
-  last_synced_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
-
-  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
-  updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
-
-  -- Constraints
-  UNIQUE(store_id, shoprenter_product_id)
-);
-
--- Indexes
-CREATE INDEX idx_shoprenter_products_store ON shoprenter_products_cache(store_id);
-CREATE INDEX idx_shoprenter_products_sku ON shoprenter_products_cache(sku);
-CREATE INDEX idx_shoprenter_products_active ON shoprenter_products_cache(active);
-```
-
-### New Table: `shoprenter_webhooks`
-
-```sql
-CREATE TABLE shoprenter_webhooks (
-  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-  store_id UUID REFERENCES stores(id) ON DELETE CASCADE,
-
-  -- Webhook details
-  shoprenter_webhook_id VARCHAR(255),
-  event VARCHAR(100) NOT NULL, -- 'order/create', 'product/update', etc.
-  callback_url TEXT NOT NULL,
-  is_active BOOLEAN DEFAULT true,
-
-  -- Statistics
-  last_received_at TIMESTAMP WITH TIME ZONE,
-  total_received INTEGER DEFAULT 0,
-
-  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
-  updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
-
-  UNIQUE(store_id, event)
-);
-```
-
----
-
-## 🔧 Backend Implementation
-
-### File Structure
-
-**Current Implementation: Supabase Edge Functions (TypeScript/Deno)**
-
-```
-supabase/functions/
-├── oauth-shoprenter-init/
-│   └── index.ts                         # OAuth flow initialization
-├── oauth-shoprenter-callback/
-│   └── index.ts                         # OAuth callback handler
-├── webhook-shoprenter-uninstall/
-│   └── index.ts                         # Uninstall webhook handler
-├── shoprenter-products/
-│   └── index.ts                         # Product sync endpoint
-├── shoprenter-orders/
-│   └── index.ts                         # Order sync endpoint
-├── shoprenter-customers/
-│   └── index.ts                         # Customer sync endpoint
-├── shoprenter-sync/
-│   └── index.ts                         # Manual sync trigger
-├── shoprenter-scheduled-sync/
-│   └── index.ts                         # Automated background sync (pg_cron)
-└── _shared/
-    └── shoprenter-client.ts             # ShopRenter API client library
-```
-
-**Note:** All Edge Functions are deployed as serverless functions on Supabase infrastructure.
-
-### 1. Environment Configuration
-
-**Environment Variables (Supabase Edge Functions):**
-
-```typescript
-// Accessed via Deno.env.get() in Edge Functions
-const config = {
-  clientId: Deno.env.get('SHOPRENTER_CLIENT_ID'),
-  clientSecret: Deno.env.get('SHOPRENTER_CLIENT_SECRET'),
-
-  // Supabase URLs
-  supabaseUrl: Deno.env.get('SUPABASE_URL'),
-  supabaseAnonKey: Deno.env.get('SUPABASE_ANON_KEY'),
-  supabaseServiceKey: Deno.env.get('SUPABASE_SERVICE_ROLE_KEY'),
-
-  // Frontend URL
-  frontendUrl: Deno.env.get('FRONTEND_URL'),
-
-  // Production endpoints
-  redirectUri: 'https://ztklqodcdjeqpsvhlpud.supabase.co/functions/v1/oauth-shoprenter-callback',
-  entryPoint: 'https://shopcall.ai/integrations',
-  uninstallUri: 'https://ztklqodcdjeqpsvhlpud.supabase.co/functions/v1/webhook-shoprenter-uninstall',
-
-  // Required scopes
-  scopes: [
-    'product:read',
-    'customer:read',
-    'order:read',
-    'order:write',
-    'webhook:write'
-  ],
-
-  // Rate limiting
-  maxRequestsPerSecond: 5,
-  tokenExpiryBuffer: 300, // Refresh 5 min before expiry
-};
-```
-
-**Configuration in supabase/.env:**
-```bash
-SHOPRENTER_CLIENT_ID=your_client_id_here
-SHOPRENTER_CLIENT_SECRET=your_client_secret_here
-SUPABASE_URL=https://ztklqodcdjeqpsvhlpud.supabase.co
-SUPABASE_ANON_KEY=your_anon_key
-SUPABASE_SERVICE_ROLE_KEY=your_service_role_key
-FRONTEND_URL=https://shopcall.ai
-INTERNAL_SYNC_SECRET=your_random_secure_secret
-```
-
-### 2. HMAC Validator (`_shared/shoprenter-client.ts`)
-
-**Note:** HMAC validation is implemented in the shared ShopRenter client library used by all Edge Functions.
-
-```typescript
-import { createHmac, timingSafeEqual } from "https://deno.land/std@0.177.0/node/crypto.ts";
-
-/**
- * Validate HMAC signature from ShopRenter
- * @param query - Query parameters from request
- * @param clientSecret - ShopRenter client secret
- * @returns True if HMAC is valid
- */
-function validateHMAC(query: Record<string, string>, clientSecret: string): boolean {
-  const { hmac, ...params } = query;
-
-  if (!hmac) {
-    console.error('[ShopRenter] HMAC missing from request');
-    return false;
-  }
-
-  // Build sorted query string without HMAC
-  const sortedParams = Object.keys(params)
-    .sort()
-    .map(key => `${key}=${params[key]}`)
-    .join('&');
-
-  // Calculate HMAC using sha256
-  const calculatedHmac = createHmac('sha256', clientSecret)
-    .update(sortedParams)
-    .digest('hex');
-
-  // Timing-safe comparison
-  try {
-    return timingSafeEqual(
-      new TextEncoder().encode(calculatedHmac),
-      new TextEncoder().encode(hmac)
-    );
-  } catch (error) {
-    console.error('[ShopRenter] HMAC comparison error:', error);
-    return false;
-  }
-}
-
-/**
- * Validate request timestamp (prevent replay attacks)
- * @param timestamp - Unix timestamp from request
- * @param maxAgeSeconds - Maximum age allowed (default: 300 = 5 min)
- * @returns True if timestamp is within valid range
- */
-function validateTimestamp(timestamp: string, maxAgeSeconds = 300): boolean {
-  const requestTime = parseInt(timestamp, 10);
-  const currentTime = Math.floor(Date.now() / 1000);
-  const age = currentTime - requestTime;
-
-  if (age < 0) {
-    console.error('[ShopRenter] Request timestamp is in the future');
-    return false;
-  }
-
-  if (age > maxAgeSeconds) {
-    console.error(`[ShopRenter] Request timestamp too old: ${age}s > ${maxAgeSeconds}s`);
-    return false;
-  }
-
-  return true;
-}
-
-/**
- * Validate complete ShopRenter request
- * @param query - Query parameters
- * @param clientSecret - ShopRenter client secret
- * @returns Validation result
- */
-function validateRequest(
-  query: Record<string, string>,
-  clientSecret: string
-): { valid: boolean; error?: string } {
-  // Check required parameters
-  const required = ['shopname', 'code', 'timestamp', 'hmac'];
-  const missing = required.filter(param => !query[param]);
-
-  if (missing.length > 0) {
-    return {
-      valid: false,
-      error: `Missing required parameters: ${missing.join(', ')}`
-    };
-  }
-
-  // Validate timestamp
-  if (!validateTimestamp(query.timestamp)) {
-    return {
-      valid: false,
-      error: 'Request timestamp invalid or expired'
-    };
-  }
-
-  // Validate HMAC
-  if (!validateHMAC(query, clientSecret)) {
-    return {
-      valid: false,
-      error: 'HMAC validation failed'
-    };
-  }
-
-  return { valid: true };
-}
-
-export {
-  validateHMAC,
-  validateTimestamp,
-  validateRequest
-};
-```
-
-### 3. OAuth Handler (Edge Functions)
-
-**Implementation:** The OAuth flow is handled by two Edge Functions:
-- `oauth-shoprenter-init` - Initiates OAuth flow
-- `oauth-shoprenter-callback` - Handles OAuth callback and token exchange
-
-**Example TypeScript Code (simplified from actual implementation):**
-
-```typescript
-import { createClient } from 'https://esm.sh/@supabase/supabase-js@2';
-
-const supabase = createClient(
-  Deno.env.get('SUPABASE_URL')!,
-  Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
-);
-
-/**
- * Exchange authorization code for access token
- * @param shopname - Store name
- * @param code - Authorization code
- * @returns Token response
- */
-async function exchangeCodeForToken(shopname: string, code: string) {
-  const tokenUrl = `https://${shopname}.shoprenter.hu/oauth/token`;
-  const clientId = Deno.env.get('SHOPRENTER_CLIENT_ID')!;
-  const clientSecret = Deno.env.get('SHOPRENTER_CLIENT_SECRET')!;
-  const redirectUri = 'https://ztklqodcdjeqpsvhlpud.supabase.co/functions/v1/oauth-shoprenter-callback';
-
-  try {
-    const response = await fetch(tokenUrl, {
-      method: 'POST',
-      headers: {
-        'Content-Type': 'application/json',
-        'Accept': 'application/json'
-      },
-      body: JSON.stringify({
-        grant_type: 'authorization_code',
-        client_id: clientId,
-        client_secret: clientSecret,
-        code: code,
-        redirect_uri: redirectUri
-      })
-    });
-
-    if (!response.ok) {
-      throw new Error(`Token exchange failed: ${response.statusText}`);
-    }
-
-    const data = await response.json();
-    console.log(`[ShopRenter] Token acquired for ${shopname}`);
-    return data;
-  } catch (error) {
-    console.error('[ShopRenter] Token exchange error:', error);
-    throw new Error('Failed to exchange code for token');
-  }
-}
-
-/**
- * Store ShopRenter credentials in database
- * Note: Actual implementation in oauth-shoprenter-callback Edge Function
- */
-async function storeCredentials(userId: string, shopname: string, tokenData: any) {
-  const shopDomain = `${shopname}.shoprenter.hu`;
-  const expiresAt = new Date(Date.now() + (tokenData.expires_in * 1000));
-
-  // 1. Create or update stores record
-  const { data: store, error: storeError } = await supabase
-    .from('stores')
-    .upsert({
-      user_id: userId,
-      platform_name: 'shoprenter',
-      store_name: shopname,
-      store_url: `https://${shopDomain}`,
-      api_key: tokenData.access_token,
-      api_secret: tokenData.refresh_token,
-      token_expires_at: expiresAt.toISOString(),
-      scopes: tokenData.scope ? tokenData.scope.split(' ') : [],
-      is_active: true,
-      connected_at: new Date().toISOString()
-    })
-    .select()
-    .single();
-
-  if (storeError) {
-    console.error('[ShopRenter] Error storing store:', storeError);
-    throw storeError;
-  }
-
-  console.log(`[ShopRenter] Credentials stored for ${shopname}`);
-  return store;
-}
-
-// Additional functions for token refresh are implemented in the ShopRenter client library
-// See: supabase/functions/_shared/shoprenter-client.ts
-```
-
-**Note:** The complete OAuth implementation including token refresh, HMAC validation, and credential storage is available in the deployed Edge Functions. The code examples above are simplified for documentation purposes.
-
----
-
-### 4. Deployed Edge Functions
-
-All ShopRenter integration functionality is implemented as Supabase Edge Functions (TypeScript/Deno). Below is a summary of each function:
-
-#### **oauth-shoprenter-init**
-- **Purpose:** Initialize OAuth flow
-- **Endpoint:** `/functions/v1/oauth-shoprenter-init`
-- **Method:** GET/POST
-- **Features:** Generates state, stores in database, redirects to ShopRenter OAuth
-
-#### **oauth-shoprenter-callback**
-- **Purpose:** Handle OAuth callback
-- **Endpoint:** `/functions/v1/oauth-shoprenter-callback`
-- **Method:** GET
-- **Parameters:** `shopname`, `code`, `timestamp`, `hmac`, `app_url`
-- **Features:**
-  - Validates HMAC signature
-  - Validates timestamp (5-minute window)
-  - Exchanges code for access token
-  - Stores credentials in `pending_shoprenter_installs` table
-  - Redirects to frontend with installation_id
-
-#### **webhook-shoprenter-uninstall**
-- **Purpose:** Handle app uninstall
-- **Endpoint:** `/functions/v1/webhook-shoprenter-uninstall`
-- **Method:** GET/POST
-- **Parameters:** `shopname`, `code`, `timestamp`, `hmac`
-- **Features:**
-  - Validates HMAC signature
-  - Deactivates store connection
-  - Removes stored tokens
-  - Deletes cached data (GDPR compliance)
-
-#### **shoprenter-products**
-- **Purpose:** Fetch products from ShopRenter API
-- **Endpoint:** `/functions/v1/shoprenter-products`
-- **Method:** POST
-- **Body:** `{ store_id: string }`
-- **Features:** Fetches and caches product data
-
-#### **shoprenter-orders**
-- **Purpose:** Fetch orders from ShopRenter API
-- **Endpoint:** `/functions/v1/shoprenter-orders`
-- **Method:** POST
-- **Body:** `{ store_id: string }`
-- **Features:** Fetches and caches order data
-
-#### **shoprenter-customers**
-- **Purpose:** Fetch customers from ShopRenter API
-- **Endpoint:** `/functions/v1/shoprenter-customers`
-- **Method:** POST
-- **Body:** `{ store_id: string }`
-- **Features:** Fetches and caches customer data
-
-#### **shoprenter-sync**
-- **Purpose:** Manual sync trigger
-- **Endpoint:** `/functions/v1/shoprenter-sync`
-- **Method:** POST
-- **Body:** `{ store_id: string }`
-- **Features:** Triggers full sync (products, orders, customers)
-
-#### **shoprenter-scheduled-sync**
-- **Purpose:** Automated background sync (called by pg_cron)
-- **Endpoint:** `/functions/v1/shoprenter-scheduled-sync`
-- **Method:** POST
-- **Headers:** `Authorization: Bearer {INTERNAL_SYNC_SECRET}`
-- **Features:**
-  - Syncs all active ShopRenter stores
-  - Updates `sync_logs` table
-  - Handles errors gracefully
-  - Rate limiting and retry logic
-
----
-
-### 5. Old Express.js Routes (DEPRECATED)
-
-**The following Express.js/Node.js routes are NO LONGER USED.** They have been replaced by the Supabase Edge Functions listed above.
-
-<details>
-<summary>Click to view deprecated Express.js code (for reference only)</summary>
-
-```javascript
-// DEPRECATED - DO NOT USE
-// This code is kept for historical reference only
-const { validateRequest } = require('../lib/shoprenter/hmac-validator');
-const { exchangeCodeForToken, storeCredentials } = require('../lib/shoprenter/oauth');
-
-// ShopRenter OAuth Callback
-app.get('/auth/shoprenter/callback', async (req, res) => {
-  const { shopname, code, timestamp, hmac, app_url } = req.query;
-
-  console.log(`[ShopRenter] OAuth callback received for ${shopname}`);
-
-  // 1. Validate request
-  const validation = validateRequest(req.query);
-  if (!validation.valid) {
-    console.error(`[ShopRenter] Validation failed: ${validation.error}`);
-    return res.status(403).json({
-      error: 'Invalid request',
-      details: validation.error
-    });
-  }
-
-  try {
-    // 2. Exchange code for tokens
-    const tokenData = await exchangeCodeForToken(shopname, code);
-
-    // 3. Store credentials
-    // Note: We need user_id here. In ShopRenter flow, we might need to:
-    // - Store shopname in a temp Map with code
-    // - Let user authenticate first
-    // For now, we'll redirect to app_url and handle auth there
-
-    // Store in temporary map for later association
-    const installationId = crypto.randomBytes(16).toString('hex');
-    global.pendingShopRenterInstalls = global.pendingShopRenterInstalls || new Map();
-    global.pendingShopRenterInstalls.set(installationId, {
-      shopname,
-      tokenData,
-      timestamp: Date.now(),
-      expiresAt: Date.now() + (15 * 60 * 1000) // 15 minutes
-    });
-
-    // 4. Redirect to app_url with installation_id
-    const redirectUrl = new URL(app_url);
-    redirectUrl.searchParams.append('sr_install', installationId);
-
-    console.log(`[ShopRenter] Redirecting to: ${redirectUrl.toString()}`);
-    res.redirect(redirectUrl.toString());
-
-  } catch (error) {
-    console.error('[ShopRenter] OAuth callback error:', error);
-    res.status(500).json({
-      error: 'Installation failed',
-      details: error.message
-    });
-  }
-});
-
-// ShopRenter EntryPoint (after redirect from callback)
-app.get('/integrations/shoprenter/entry', securedSession, async (req, res) => {
-  const { shopname, code, timestamp, hmac, sr_install } = req.query;
-
-  console.log(`[ShopRenter] EntryPoint accessed for ${shopname}`);
-
-  // 1. Validate HMAC
-  const validation = validateRequest({ shopname, code, timestamp, hmac });
-  if (!validation.valid) {
-    return res.status(403).json({
-      error: 'Invalid request',
-      details: validation.error
-    });
-  }
-
-  try {
-    // 2. Get installation data from temporary storage
-    if (!sr_install || !global.pendingShopRenterInstalls?.has(sr_install)) {
-      return res.status(400).json({
-        error: 'Installation session not found or expired'
-      });
-    }
-
-    const installData = global.pendingShopRenterInstalls.get(sr_install);
-
-    // 3. Store credentials with authenticated user
-    await storeCredentials(req.user.id, installData.shopname, installData.tokenData);
-
-    // 4. Clean up temporary storage
-    global.pendingShopRenterInstalls.delete(sr_install);
-
-    // 5. Set up webhooks (async)
-    setupWebhooks(req.user.id, installData.shopname).catch(err => {
-      console.error('[ShopRenter] Webhook setup error:', err);
-    });
-
-    // 6. Start initial sync (async)
-    syncShopRenterData(req.user.id, installData.shopname).catch(err => {
-      console.error('[ShopRenter] Initial sync error:', err);
-    });
-
-    // 7. Redirect to success page
-    res.redirect('https://shopcall.ai/integrations?connected=shoprenter&status=success');
-
-  } catch (error) {
-    console.error('[ShopRenter] EntryPoint error:', error);
-    res.redirect('https://shopcall.ai/integrations?connected=shoprenter&status=error');
-  }
-});
-
-// ShopRenter Uninstall Webhook
-app.get('/webhooks/shoprenter/uninstall', async (req, res) => {
-  const { shopname, code, timestamp, hmac } = req.query;
-
-  console.log(`[ShopRenter] Uninstall webhook received for ${shopname}`);
-
-  // 1. Validate HMAC
-  const validation = validateRequest(req.query);
-  if (!validation.valid) {
-    return res.status(403).json({
-      error: 'Invalid request',
-      details: validation.error
-    });
-  }
-
-  try {
-    // 2. Find store by shopname
-    const { data: tokens } = await supabase
-      .from('shoprenter_tokens')
-      .select('store_id')
-      .eq('shopname', shopname)
-      .single();
-
-    if (tokens) {
-      // 3. Deactivate store
-      await supabase
-        .from('stores')
-        .update({ is_active: false, updated_at: new Date().toISOString() })
-        .eq('id', tokens.store_id);
-
-      // 4. Deactivate tokens
-      await supabase
-        .from('shoprenter_tokens')
-        .update({ is_active: false, updated_at: new Date().toISOString() })
-        .eq('store_id', tokens.store_id);
-
-      console.log(`[ShopRenter] Store ${shopname} uninstalled successfully`);
-    }
-
-    // 5. Respond with 200 (ShopRenter expects this)
-    res.status(200).json({ message: 'Uninstall processed' });
-
-  } catch (error) {
-    console.error('[ShopRenter] Uninstall error:', error);
-    // Still respond with 200 to prevent retries
-    res.status(200).json({ message: 'Uninstall processed with errors' });
-  }
-});
-
-// Cleanup expired installations periodically
-setInterval(() => {
-  if (!global.pendingShopRenterInstalls) return;
-
-  const now = Date.now();
-  for (const [key, value] of global.pendingShopRenterInstalls.entries()) {
-    if (now > value.expiresAt) {
-      global.pendingShopRenterInstalls.delete(key);
-      console.log(`[ShopRenter] Cleaned up expired installation: ${key}`);
-    }
-  }
-}, 5 * 60 * 1000); // Every 5 minutes
-```
-
-</details>
-
----
-
-## 🎨 Frontend Implementation
-
-### Integration UI Component
-
-Create: `/shopcall.ai-main/src/components/ShopRenterConnect.tsx`
-
-```typescript
-import { useState } from 'react';
-import { Button } from '@/components/ui/button';
-import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
-import { Input } from '@/components/ui/input';
-import { Label } from '@/components/ui/label';
-import { Alert, AlertDescription } from '@/components/ui/alert';
-import { Loader2, CheckCircle, AlertCircle } from 'lucide-react';
-
-export function ShopRenterConnect() {
-  const [shopname, setShopname] = useState('');
-  const [loading, setLoading] = useState(false);
-  const [error, setError] = useState('');
-
-  const handleConnect = async () => {
-    if (!shopname.trim()) {
-      setError('Kérjük, adja meg a bolt nevét');
-      return;
-    }
-
-    setLoading(true);
-    setError('');
-
-    try {
-      // For ShopRenter, the store owner must initiate installation from ShopRenter admin
-      // This would typically open the ShopRenter app store
-      window.open(
-        `https://${shopname}.shoprenter.hu/admin/app/${SHOPRENTER_CLIENT_ID}`,
-        '_blank'
-      );
-
-      // Show instructions
-      setError('');
-
-    } catch (err) {
-      setError('Hiba történt a kapcsolódás során');
-      console.error('ShopRenter connection error:', err);
-    } finally {
-      setLoading(false);
-    }
-  };
-
-  return (
-    <Card className="bg-slate-800 border-slate-700">
-      <CardHeader>
-        <div className="flex items-center gap-3">
-          <img
-            src="/images/shoprenter-logo.png"
-            alt="ShopRenter"
-            className="w-10 h-10"
-          />
-          <CardTitle className="text-white">ShopRenter</CardTitle>
-        </div>
-        <p className="text-slate-400">
-          Magyar webáruház platform - AI telefonos asszisztens integráció
-        </p>
-      </CardHeader>
-      <CardContent className="space-y-4">
-        <div className="space-y-2">
-          <Label htmlFor="shopname" className="text-slate-300">
-            Bolt neve
-          </Label>
-          <div className="flex gap-2">
-            <Input
-              id="shopname"
-              placeholder="pelda"
-              value={shopname}
-              onChange={(e) => setShopname(e.target.value)}
-              className="bg-slate-700 border-slate-600 text-white flex-1"
-            />
-            <span className="flex items-center text-slate-400">
-              .shoprenter.hu
-            </span>
-          </div>
-          <p className="text-slate-500 text-sm">
-            Add meg a bolt nevét (pl. "pelda" ha a bolt címe pelda.shoprenter.hu)
-          </p>
-        </div>
-
-        {error && (
-          <Alert variant="destructive" className="bg-red-900/20 border-red-900">
-            <AlertCircle className="w-4 h-4" />
-            <AlertDescription>{error}</AlertDescription>
-          </Alert>
-        )}
-
-        <Button
-          onClick={handleConnect}
-          disabled={loading}
-          className="w-full bg-[#85b218] hover:bg-[#6d9315] text-white"
-        >
-          {loading ? (
-            <>
-              <Loader2 className="w-4 h-4 mr-2 animate-spin" />
-              Kapcsolódás...
-            </>
-          ) : (
-            'ShopRenter kapcsolat létrehozása'
-          )}
-        </Button>
-
-        <div className="bg-slate-700/50 p-4 rounded-lg">
-          <h4 className="text-white font-medium mb-2">Telepítési lépések:</h4>
-          <ol className="text-slate-300 text-sm space-y-1 list-decimal list-inside">
-            <li>Kattints a "Kapcsolat létrehozása" gombra</li>
-            <li>Jelentkezz be a ShopRenter admin felületedre</li>
-            <li>Hagyd jóvá az alkalmazás telepítését</li>
-            <li>Visszairányítunk ide a sikeres telepítés után</li>
-          </ol>
-        </div>
-      </CardContent>
-    </Card>
-  );
-}
-```
-
-### Add to Integrations Page
-
-Update `/shopcall.ai-main/src/components/IntegrationsContent.tsx`:
-
-```typescript
-import { ShopRenterConnect } from './ShopRenterConnect';
-
-// In the platforms grid, add:
-<div className="grid gap-6 md:grid-cols-3">
-  {/* Existing Shopify card */}
-  {/* Existing WooCommerce card */}
-
-  {/* New ShopRenter card */}
-  <ShopRenterConnect />
-</div>
-```
-
----
-
-## 🔒 Security Considerations
-
-### 1. HMAC Validation
-- ✅ **Always validate HMAC** on every request from ShopRenter
-- ✅ Use timing-safe comparison (`crypto.timingSafeEqual`)
-- ✅ Validate timestamp to prevent replay attacks (5-minute window)
-
-### 2. Token Storage
-- ✅ Store access tokens encrypted in database
-- ✅ Never log or expose tokens in responses
-- ✅ Implement automatic token refresh
-- ✅ Revoke tokens on uninstall
-
-### 3. API Communication
-- ✅ Always use HTTPS for all endpoints
-- ✅ Implement rate limiting (5 req/sec per ShopRenter guidelines)
-- ✅ Handle API errors gracefully
-- ✅ Implement retry logic with exponential backoff
-
-### 4. Data Privacy (GDPR Compliance)
-- ✅ Only request necessary scopes
-- ✅ Implement data deletion on uninstall
-- ✅ Provide clear privacy policy
-- ✅ Handle customer data securely
-
-### 5. Environment Variables
-
-```bash
-# .env for backend
-SHOPRENTER_APP_ID=your_app_id_here
-SHOPRENTER_CLIENT_ID=your_client_id_here
-SHOPRENTER_CLIENT_SECRET=your_client_secret_here
-```
-
-**⚠️ Never commit these to version control!**
-
----
-
-## 🧪 Testing Strategy
-
-### 1. Test Store Setup
-
-1. Request test store at: https://www.shoprenter.hu/tesztigenyles/?devstore=1
-2. Store name: `shopcall-test-store`
-3. URL: `shopcall-test-store.myshoprenter.hu`
-
-### 2. Test Cases
-
-#### OAuth Flow Testing
-
-```
-Test Case 1: Successful Installation
-- Initiate OAuth from ShopRenter admin
-- Verify HMAC validation passes
-- Verify token exchange succeeds
-- Verify credentials stored in database
-- Verify redirect to success page
-
-Test Case 2: Invalid HMAC
-- Modify HMAC parameter
-- Verify request rejected with 403
-- Verify error logged
-
-Test Case 3: Expired Timestamp
-- Use timestamp older than 5 minutes
-- Verify request rejected
-- Verify error logged
-
-Test Case 4: Uninstall Flow
-- Trigger uninstall from ShopRenter
-- Verify webhook received
-- Verify store deactivated
-- Verify tokens deactivated
-```
-
-#### API Testing
-
-```
-Test Case 5: Product Sync
-- Request product list from API
-- Verify products cached in database
-- Verify product data accuracy
-
-Test Case 6: Token Refresh
-- Wait for token expiry
-- Make API request
-- Verify token auto-refreshed
-- Verify new token stored
-
-Test Case 7: Webhook Processing
-- Create test order in ShopRenter
-- Verify webhook received
-- Verify order data processed
-- Verify response 200 sent
-```
-
-### 3. Integration Testing Tools
-
-```javascript
-// test/shoprenter-integration.test.js
-const axios = require('axios');
-const crypto = require('crypto');
-
-describe('ShopRenter Integration', () => {
-  const testShop = 'shopcall-test-store';
-  const clientSecret = process.env.SHOPRENTER_CLIENT_SECRET;
-
-  function generateValidHMAC(params) {
-    const sorted = Object.keys(params)
-      .sort()
-      .map(key => `${key}=${params[key]}`)
-      .join('&');
-
-    return crypto
-      .createHmac('sha256', clientSecret)
-      .update(sorted)
-      .digest('hex');
-  }
-
-  it('should validate correct HMAC', async () => {
-    const params = {
-      shopname: testShop,
-      code: 'test123',
-      timestamp: Math.floor(Date.now() / 1000).toString()
-    };
-
-    params.hmac = generateValidHMAC(params);
-
-    const response = await axios.get('http://localhost:3000/auth/shoprenter/callback', {
-      params,
-      maxRedirects: 0,
-      validateStatus: () => true
-    });
-
-    expect(response.status).not.toBe(403);
-  });
-
-  it('should reject invalid HMAC', async () => {
-    const params = {
-      shopname: testShop,
-      code: 'test123',
-      timestamp: Math.floor(Date.now() / 1000).toString(),
-      hmac: 'invalid_hmac'
-    };
-
-    const response = await axios.get('http://localhost:3000/auth/shoprenter/callback', {
-      params,
-      maxRedirects: 0,
-      validateStatus: () => true
-    });
-
-    expect(response.status).toBe(403);
-  });
-});
-```
-
----
-
-## ✅ Implementation Status
-
-### 🎉 Completed (All Core Features Implemented!)
-
-#### **Backend Infrastructure**
-- ✅ All 8 Supabase Edge Functions deployed and operational
-- ✅ `oauth-shoprenter-init` - OAuth flow initialization
-- ✅ `oauth-shoprenter-callback` - OAuth callback with HMAC validation
-- ✅ `webhook-shoprenter-uninstall` - Uninstall webhook handler
-- ✅ `shoprenter-products` - Product data sync
-- ✅ `shoprenter-orders` - Order data sync
-- ✅ `shoprenter-customers` - Customer data sync
-- ✅ `shoprenter-sync` - Manual full sync trigger
-- ✅ `shoprenter-scheduled-sync` - Automated hourly background sync (pg_cron)
-
-#### **Security & Authentication**
-- ✅ HMAC SHA256 validation implemented
-- ✅ Timestamp validation (5-minute window for replay attack prevention)
-- ✅ Timing-safe comparison for HMAC verification
-- ✅ Secure token storage with encryption
-- ✅ Automatic token refresh (5-minute expiry buffer)
-
-#### **Database Schema**
-- ✅ `stores` table updated for ShopRenter
-- ✅ `pending_shoprenter_installs` table created
-- ✅ `oauth_states` table for OAuth flow state management
-- ✅ `shoprenter_products_cache` table for product caching
-- ✅ `shoprenter_tokens` table for token management
-- ✅ `shoprenter_webhooks` table for webhook tracking
-- ✅ `store_sync_config` table for per-store sync settings
-- ✅ `sync_logs` table for scheduled sync monitoring
-
-#### **Data Synchronization**
-- ✅ Manual sync via UI (immediate sync on demand)
-- ✅ Scheduled background sync (pg_cron, hourly)
-- ✅ Per-store sync configuration (frequency, enabled/disabled)
-- ✅ Sync logging and monitoring
-- ✅ Rate limiting (5 req/sec per ShopRenter guidelines)
-- ✅ Retry logic with exponential backoff
-- ✅ Error handling and recovery
-
-#### **Frontend Integration**
-- ✅ `ShopRenterConnect.tsx` component implemented
-- ✅ OAuth flow initiation from UI
-- ✅ Installation success/error handling
-- ✅ Hungarian language support
-- ✅ User-friendly store connection interface
-
-#### **Documentation**
-- ✅ `SHOPRENTER_REGISTRATION.md` created (submission-ready)
-- ✅ `SHOPRENTER.md` updated with actual implementation
-- ✅ All domain formats corrected (`.shoprenter.hu`)
-- ✅ All endpoint URLs updated (Supabase Edge Functions)
-- ✅ Backend architecture updated (Supabase Edge Functions)
-- ✅ Code examples updated (TypeScript/Deno)
-
-### ⚠️ Pending Items
-
-#### **Registration Requirements**
-- ⏳ Logo design and creation (250x150px PNG at `/shopcall.ai-main/public/images/shoprenter-app-logo.png`)
-- ⏳ Test store approval from ShopRenter
-- ⏳ Production OAuth credentials (AppId, ClientId, ClientSecret)
-- ⏳ Final testing with approved test store
-- ⏳ App Store listing approval
-
-#### **Optional Enhancements**
-- 🔄 Real-time webhooks for product/order updates (infrastructure ready, awaiting registration)
-- 🔄 Advanced sync scheduling options (15min, 30min intervals)
-- 🔄 Sync analytics dashboard
-
-### 📊 Implementation Summary
-
-| Category | Completed | Pending | Total | Progress |
-|----------|-----------|---------|-------|----------|
-| Backend Edge Functions | 8 | 0 | 8 | 100% ✅ |
-| Database Tables | 8 | 0 | 8 | 100% ✅ |
-| Security Features | 5 | 0 | 5 | 100% ✅ |
-| Sync Features | 6 | 0 | 6 | 100% ✅ |
-| Frontend Components | 1 | 0 | 1 | 100% ✅ |
-| Documentation | 2 | 0 | 2 | 100% ✅ |
-| Registration Items | 0 | 5 | 5 | 0% ⏳ |
-
-**Overall Technical Implementation:** ✅ 100% Complete
-**Overall Project Status:** ⏳ 83% Complete (awaiting registration approval)
-
----
-
-## 🚀 Deployment Plan
-
-### ✅ Phase 1: Development (COMPLETED)
-- ✅ Set up test ShopRenter store
-- ✅ Implement HMAC validation
-- ✅ Implement OAuth flow
-- ✅ Create database tables
-- ✅ Build API client
-- ✅ Test with test store
-
-### ✅ Phase 2: Integration (COMPLETED)
-- ✅ Implement product sync
-- ✅ Implement webhook handlers
-- ✅ Create frontend UI
-- ✅ Test end-to-end flow
-- ✅ Handle error scenarios
-
-### ✅ Phase 3: Testing (COMPLETED)
-- ✅ Unit tests
-- ✅ Integration tests
-- ✅ Security audit
-- ✅ Performance testing
-- ✅ User acceptance testing
-
-### ⏳ Phase 4: Production Registration (IN PROGRESS)
-- ✅ Prepare application documentation
-- ⏳ Create logo (250x150px PNG) - **PENDING**
-- ⏳ Submit app to ShopRenter Partner Support - **READY TO SUBMIT**
-- ⏳ Wait for approval
-- ⏳ Receive production credentials
-
-### 📋 Phase 5: Launch (READY)
-- ✅ Deploy to production (Edge Functions already deployed)
-- ✅ Configure production environment variables
-- ✅ Monitor logs and errors
-- ⏳ Soft launch with beta users (awaiting credentials)
-- ⏳ Public launch
-
----
-
-## 📅 Timeline & Milestones
-
-| Phase | Milestone | Status | Date |
-|-------|-----------|--------|------|
-| 1 | Setup & Planning | ✅ Complete | Oct 2024 |
-| 2 | OAuth Implementation | ✅ Complete | Oct 2024 |
-| 3 | API Integration | ✅ Complete | Oct 2024 |
-| 4 | Scheduled Sync | ✅ Complete | Oct 2024 |
-| 5 | Testing & QA | ✅ Complete | Oct 2024 |
-| 6 | Documentation | ✅ Complete | Oct 31, 2025 |
-| 7 | Registration | ⏳ Pending | Nov 2025 (estimated) |
-| 8 | Production Launch | 📋 Ready | TBD (after approval) |
-
-**Status:** Ready for ShopRenter Partner Support Submission
-
----
-
-## 📚 Resources & References
-
-### Documentation
-- ShopRenter Developer Docs: https://doc.shoprenter.hu
-- API Reference: https://doc.shoprenter.hu/development/api/
-- App Development Guide: https://doc.shoprenter.hu/development/app-development/
-
-### Example Apps
-- PHP Demo: https://github.com/Shoprenter/sr-demo-app-php
-- Node.js Demo: https://github.com/Shoprenter/sr-demo-app-node
-
-### Contact
-- Partner Support: partnersupport@shoprenter.hu
-- Test Store Request: https://www.shoprenter.hu/tesztigenyles/?devstore=1
-
----
-
-## ✅ Checklist for Launch
-
-### Pre-Registration
-- ✅ Review ShopRenter developer documentation
-- ✅ Prepare application name and description (Hungarian)
-- ⏳ Design application logo (250x150px) - **PENDING**
-- ✅ Set up HTTPS endpoints (EntryPoint, RedirectUri, UninstallUri)
-- ✅ Determine required API scopes
-- ⏳ Request test store - **READY TO REQUEST**
-
-### Development
-- ✅ Implement HMAC validation
-- ✅ Implement OAuth flow
-- ✅ Create database schema
-- ✅ Build API client
-- ✅ Implement product sync
-- ✅ Set up webhook handlers
-- ✅ Create frontend UI
-- ✅ Add error handling
-- ✅ Implement logging
-- ✅ Implement scheduled sync (pg_cron)
-- ✅ Implement per-store sync configuration
-
-### Testing
-- ✅ Test OAuth installation
-- ✅ Test HMAC validation
-- ✅ Test token refresh
-- ✅ Test product sync
-- ✅ Test webhooks
-- ✅ Test uninstall flow
-- ✅ Security testing
-- ✅ Performance testing
-
-### Registration
-- ✅ Prepare SHOPRENTER_REGISTRATION.md document
-- ⏳ Create logo (250x150px PNG) - **PENDING**
-- ⏳ Submit to partnersupport@shoprenter.hu - **READY TO SUBMIT**
-- ⏳ Provide all required information - **DOCUMENTED**
-- ⏳ Wait for AppId, ClientId, ClientSecret
-- ⏳ Configure environment variables (when credentials received)
-
-### Production
-- ✅ Deploy backend to production (Supabase Edge Functions)
-- ✅ Deploy frontend to production
-- ✅ Configure production URLs
-- ✅ Monitor logs for errors
-- ⏳ Test with real store (awaiting credentials)
-- ✅ Document usage for customers
-
----
-
-## 🔄 Post-Launch Maintenance
-
-### Regular Tasks
-- Monitor webhook reliability
-- Check token refresh logs
-- Review error rates
-- Update API client when ShopRenter updates
-- Sync product catalog daily
-- Respond to merchant support requests
-
-### Scope Updates
-When new features require additional scopes:
-1. Email Partner Support with new scope list
-2. Wait for scope approval
-3. Direct existing merchants to approve new scopes:
-   `https://{shopName}.shoprenter.hu/admin/app/{clientId}/approveScopes`
-4. Update app to use new scopes
-
----
-
-## 📌 Scheduled Background Sync
-
-### Implementation Details
-
-The ShopRenter integration includes automated background synchronization using PostgreSQL's `pg_cron` extension.
-
-**How it Works:**
-1. **pg_cron** schedules database jobs at hourly intervals
-2. **Database trigger function** (`trigger_shoprenter_scheduled_sync()`) makes HTTP request to Edge Function
-3. **`shoprenter-scheduled-sync` Edge Function** processes all active ShopRenter stores
-4. **Sync results** are logged to `sync_logs` table
-
-**Configuration:**
-- Runs hourly at minute 0 (`:00`)
-- Configurable per store via `store_sync_config` table
-- Sync frequencies: `15min`, `30min`, `hourly`, `6hours`, `daily`
-- Can be enabled/disabled per store
-- Choose what to sync: products, orders, customers
-
-**Monitoring:**
-```sql
--- View recent sync logs
-SELECT * FROM sync_logs
-WHERE platform = 'shoprenter'
-ORDER BY created_at DESC
-LIMIT 10;
-
--- Check store sync configuration
-SELECT * FROM store_sync_config
-WHERE store_id IN (
-  SELECT id FROM stores WHERE platform_name = 'shoprenter'
-);
-```
-
-**Manual Control:**
-```sql
--- Enable/disable sync for a store
-SELECT set_store_sync_enabled('store-uuid', true);
-
--- Change sync frequency
-SELECT set_store_sync_frequency('store-uuid', 'hourly');
-```
-
-**Database Configuration Required:**
-```
--- In Supabase Dashboard → Project Settings → Database → Custom Postgres Configuration
-app.internal_sync_secret = 'same_as_INTERNAL_SYNC_SECRET_in_env'
-app.supabase_url = 'https://ztklqodcdjeqpsvhlpud.supabase.co'
-```
-
----
-
-**Document Version:** 2.0
-**Last Updated:** 2025-10-31
-**Author:** ShopCall.ai Development Team
-**Status:** ✅ Implementation Complete - Ready for Registration
-

+ 0 - 381
SHOPRENTER_REGISTRATION.md

@@ -1,381 +0,0 @@
-# ShopRenter App Registration - ShopCall.ai
-
-**Submission Date:** 2025-10-31
-**Contact Email:** [Your Contact Email]
-**Company:** ShopCall.ai
-
----
-
-## 📧 Email Template for Partner Support
-
-**To:** partnersupport@shoprenter.hu
-**Subject:** New App Registration Request - ShopCall.ai AI Phone Assistant
-
-Tisztelt ShopRenter Partner Csapat!
-
-Szeretnénk regisztrálni alkalmazásunkat a ShopRenter platformra. Az alábbiakban megtalálják a szükséges információkat.
-
----
-
-## 1️⃣ Application Information
-
-### Application Name
-```
-ShopCall.ai - AI Phone Assistant
-```
-
-### Short Description (max 70 characters)
-```
-AI-powered phone assistant for automated customer service calls
-```
-
-### Full Description (Hungarian)
-```
-A ShopCall.ai egy mesterséges intelligencia alapú telefonos asszisztens, amely automatizálja
-az ügyfélszolgálati hívásokat. Az alkalmazás integrálódik a ShopRenter webáruházzal, és
-valós időben hozzáfér a termékekhez, rendelésekhez és vásárlói adatokhoz, hogy személyre
-szabott ügyfélszolgálatot nyújtson.
-
-Funkciók:
-- Automatikus kimenő és bejövő hívások kezelése
-- Termék információk valós idejű elérése
-- Rendelés státusz lekérdezés
-- Vásárlói előzmények alapján személyre szabott kommunikáció
-- Magyar nyelvű AI asszisztens
-- 24/7 elérhetőség
-```
-
-### Application Details Link (Website)
-```
-https://shopcall.ai
-```
-
-### Application Type
-```
-Redirected (user redirected to our platform, not iframe)
-```
-
----
-
-## 2️⃣ Technical Endpoints
-
-All endpoints use **HTTPS** and include **HMAC validation** for security.
-
-### EntryPoint
-```
-https://shopcall.ai/integrations
-```
-- This is where users land after successful OAuth installation
-- ShopRenter calls this URL with authentication parameters: `shopname`, `code`, `timestamp`, `hmac`, `app_url`
-- Our OAuth callback validates HMAC, exchanges tokens, and redirects to this URL with `sr_install` parameter
-- Displays integration success page and configuration options
-- Users can configure AI assistant settings and phone numbers
-
-### RedirectUri (OAuth Callback)
-```
-https://ztklqodcdjeqpsvhlpud.supabase.co/functions/v1/oauth-shoprenter-callback
-```
-- OAuth callback endpoint for authorization code exchange
-- Receives: `shopname`, `code`, `timestamp`, `hmac`, `app_url`
-- Validates HMAC signature using SHA256
-- Exchanges authorization code for access token
-- Stores credentials securely in database
-
-### UninstallUri
-```
-https://ztklqodcdjeqpsvhlpud.supabase.co/functions/v1/webhook-shoprenter-uninstall
-```
-- Called when app is uninstalled by merchant
-- Receives: `shopname`, `code`, `timestamp`, `hmac`
-- Validates HMAC signature
-- Cleanup actions:
-  - Deactivates store connection
-  - Removes stored tokens
-  - Stops all automated services
-  - Deletes cached product/customer data (GDPR compliance)
-
----
-
-## 3️⃣ Required API Scopes
-
-### Scope List
-```
-product:read
-product:write
-customer:read
-customer:write
-order:read
-order:write
-category:read
-inventory:read
-webhook:read
-webhook:write
-```
-
-### Scope Justifications
-
-#### `product:read`
-**Purpose:** Sync product catalog for AI knowledge base
-**Usage:** The AI assistant needs to access product information (name, price, stock, description) to answer customer questions about products during phone calls.
-**Example:** "Is the XYZ product in stock?" → AI checks product availability in real-time.
-**Data Accessed:** Product name, SKU, price, description, stock levels, active status
-
-#### `product:write`
-**Purpose:** Future capability to update product information
-**Usage:** Enable future features like AI-assisted inventory management or price updates based on customer interactions.
-**Example:** Automatically mark products as "low stock" after multiple customer inquiries.
-
-#### `customer:read`
-**Purpose:** Access customer contact information and history
-**Usage:** Access customer data including **email addresses, phone numbers**, billing/shipping addresses to enable personalized AI service and direct customer communication.
-**Example:** "Hello Mr. Kovács, I see you previously ordered product ABC. Would you like to reorder?"
-**Data Accessed:** Email, phone, first name, last name, billing address (including phone), shipping address (including phone), order history, total spent
-
-#### `customer:write`
-**Purpose:** Update customer records with call interaction data
-**Usage:** Add call notes, tags, and interaction history to customer profiles for merchant reference and improved service.
-**Example:** After a support call, the AI adds a note: "Customer prefers SMS notifications for order updates."
-
-#### `order:read`
-**Purpose:** Access order details and customer contact information
-**Usage:** Answer customer inquiries about order status and access customer **email and phone numbers** from order data for follow-up communication.
-**Example:** "Where is my order SR-2024-001?" → AI provides current order status, tracking, and customer contact details.
-**Data Accessed:** Order number, status, total, currency, customer email, customer phone, billing/shipping addresses (including phones), line items
-
-#### `order:write`
-**Purpose:** Update order information after calls
-**Usage:** Add call summaries, customer requests, and delivery notes to orders for merchant reference.
-**Example:** After a call about delivery preferences, the AI adds a note: "Customer requested morning delivery."
-
-#### `category:read`
-**Purpose:** Organize products by category for better recommendations
-**Usage:** Enable the AI to suggest related products and navigate product categories effectively during customer conversations.
-**Example:** "I'm looking for phone accessories" → AI can browse category structure to suggest relevant products.
-
-#### `inventory:read`
-**Purpose:** Access real-time stock availability information
-**Usage:** Provide accurate stock information during calls and suggest alternatives for out-of-stock items.
-**Example:** "Product XYZ is currently out of stock, but we have similar product ABC available."
-
-#### `webhook:read`
-**Purpose:** List existing webhook registrations
-**Usage:** Check for existing webhooks before creating new ones to avoid duplicates and manage webhook lifecycle.
-**Example:** During setup, verify if webhooks are already registered for this store.
-**Critical Note:** ⚠️ Our code calls `listWebhooks()` function - this scope is REQUIRED!
-
-#### `webhook:write`
-**Purpose:** Set up real-time synchronization
-**Usage:** Register webhooks for `order/create`, `product/update`, `customer/update` events to keep AI knowledge base synchronized in real-time.
-**Example:** When a product goes out of stock, webhook updates AI immediately so it doesn't offer unavailable products.
-
----
-
-## 4️⃣ Visual Assets
-
-### Application Logo
-- **Dimensions:** 250x150px (exact)
-- **Format:** PNG with transparency
-- **Location:** `/shopcall.ai-main/public/images/shoprenter-app-logo.png`
-- **Status:** ⚠️ Logo file needs to be created (design pending)
-
-**Design Requirements:**
-- Professional appearance
-- Clear "ShopCall.ai" branding
-- Readable at small sizes
-- Compatible with light and dark backgrounds
-- Follows ShopRenter design guidelines
-
----
-
-## 5️⃣ Test Store Request
-
-### Test Store Details
-**Requested Store Name:**
-```
-shopcall-test-store
-```
-
-**Expected URL:**
-```
-shopcall-test-store.shoprenter.hu
-```
-
-**Test Store Request Form:**
-```
-https://www.shoprenter.hu/tesztigenyles/?devstore=1
-```
-
-**Purpose:**
-- Test OAuth flow implementation
-- Validate HMAC signature verification
-- Test API integration (products, orders, customers)
-- Verify webhook functionality
-- Test uninstall process
-- Ensure Hungarian language support
-
----
-
-## 6️⃣ Technical Architecture Summary
-
-### Backend Platform
-- **Technology:** Supabase Edge Functions (Deno/TypeScript)
-- **Deployment:** Supabase Cloud (serverless)
-- **Database:** Supabase PostgreSQL
-- **Security:** HMAC SHA256 validation, Row-Level Security (RLS)
-
-### OAuth Implementation
-- **Flow:** Authorization Code Grant
-- **Token Management:** Automatic refresh with 5-minute expiry buffer
-- **Security:** Timing-safe HMAC comparison, timestamp validation (5-minute window)
-- **Storage:** Encrypted tokens in Supabase database
-
-### Data Synchronization
-- **Initial Sync:** Triggered on first connection (products, orders, customers)
-- **Scheduled Sync:** Automated hourly sync using pg_cron
-- **Real-time Sync:** Webhooks for immediate updates
-- **Caching:** Local cache in database for fast AI responses
-
-### Deployed Edge Functions (8 total)
-1. `oauth-shoprenter-init` - OAuth flow initialization
-2. `oauth-shoprenter-callback` - OAuth callback handler
-3. `webhook-shoprenter-uninstall` - Uninstall webhook handler
-4. `shoprenter-products` - Product sync endpoint
-5. `shoprenter-orders` - Order sync endpoint
-6. `shoprenter-customers` - Customer sync endpoint
-7. `shoprenter-sync` - Manual sync trigger
-8. `shoprenter-scheduled-sync` - Automated background sync
-
----
-
-## 7️⃣ Security & Compliance
-
-### GDPR Compliance
-- ✅ Only request necessary scopes
-- ✅ Implement data deletion on uninstall
-- ✅ Customer data encrypted at rest and in transit
-- ✅ Clear privacy policy (https://shopcall.ai/privacy)
-- ✅ Terms of service (https://shopcall.ai/terms)
-
-### Security Measures
-- ✅ HMAC validation on all requests (SHA256)
-- ✅ Timestamp validation (5-minute window to prevent replay attacks)
-- ✅ HTTPS-only communication
-- ✅ Rate limiting (5 requests/second per ShopRenter guidelines)
-- ✅ Secure token storage with encryption
-- ✅ Automatic token refresh before expiry
-- ✅ Row-level security on database
-
----
-
-## 8️⃣ Support & Documentation
-
-### Developer Contact
-- **Email:** [Your Support Email]
-- **Website:** https://shopcall.ai
-- **Documentation:** https://docs.shopcall.ai/integrations/shoprenter
-
-### Merchant Support
-- **Support Email:** support@shopcall.ai
-- **Language:** Hungarian and English
-- **Hours:** Monday-Friday, 9:00-17:00 CET
-
-### Integration Documentation
-- Setup guide in Hungarian
-- Video tutorials
-- FAQ section
-- Troubleshooting guide
-
----
-
-## 9️⃣ Implementation Status
-
-### ✅ Completed
-- [x] OAuth 2.0 flow with HMAC validation
-- [x] All 8 Edge Functions deployed and tested
-- [x] Database schema implemented
-- [x] Token management with automatic refresh
-- [x] Product/Order/Customer sync
-- [x] Webhook handlers (uninstall, product updates, order updates)
-- [x] Frontend integration UI (ShopRenterConnect.tsx)
-- [x] Scheduled background sync (pg_cron)
-- [x] Per-store sync configuration
-- [x] Comprehensive error handling and logging
-- [x] GDPR compliance measures
-
-### 🔄 Pending
-- [ ] Logo design and creation (250x150px PNG)
-- [ ] Test store approval from ShopRenter
-- [ ] Production OAuth credentials (ClientId, ClientSecret, AppId)
-- [ ] Final testing with approved test store
-- [ ] App Store listing approval
-
----
-
-## 🔟 Additional Information
-
-### Rate Limiting
-Our implementation respects ShopRenter's rate limiting guidelines:
-- Maximum 5 requests per second per store
-- Exponential backoff on rate limit errors
-- Request queuing to prevent API overload
-
-### Webhooks to Register
-After installation, we will register webhooks for:
-- `order/create` - New order notifications
-- `order/update` - Order status changes
-- `product/update` - Product information changes
-- `product/delete` - Product removal notifications
-
-### Data Retention
-- Product cache: Updated hourly + real-time webhooks
-- Order data: Retained for 90 days
-- Customer data: Retained while store is active
-- Call logs: Retained for 12 months
-- All data deleted within 30 days after uninstall
-
----
-
-## ✅ Pre-submission Checklist
-
-- [x] Application name and description prepared (Hungarian)
-- [x] All technical endpoints configured with HTTPS
-- [x] OAuth flow fully implemented and tested
-- [x] HMAC validation implemented
-- [x] Database schema created
-- [x] All Edge Functions deployed to production
-- [x] Error handling and logging implemented
-- [x] GDPR compliance measures implemented
-- [ ] Logo created (250x150px PNG) ⚠️ Pending
-- [x] Privacy policy published
-- [x] Terms of service published
-- [x] Support email configured
-- [x] Test store requested
-
----
-
-## 📝 Notes for Partner Support Review
-
-1. **Backend Architecture:** We use Supabase Edge Functions (Deno/TypeScript) instead of traditional Node.js/Express. This provides better scalability and security.
-
-2. **Domain Format:** All API requests will use `{shopname}.shoprenter.hu` format (NOT `.myshoprenter.hu`).
-
-3. **Token Management:** Our implementation includes automatic token refresh to ensure uninterrupted service.
-
-4. **Scheduled Sync:** We use PostgreSQL pg_cron for automated hourly synchronization, supplemented by real-time webhooks.
-
-5. **Hungarian Language:** Our AI assistant is fully trained in Hungarian language and understands Hungarian e-commerce terminology.
-
-6. **Ready for Testing:** All technical implementation is complete. We are ready to begin testing as soon as we receive test store access and OAuth credentials.
-
----
-
-**Thank you for reviewing our application!**
-
-Köszönjük szépen!
-ShopCall.ai Team
-
----
-
-**Document Version:** 1.0
-**Created:** 2025-10-31
-**Status:** Ready for Submission (pending logo)

+ 0 - 296
SUGGESTED_NEW_ISSUE_BODY.md

@@ -1,296 +0,0 @@
-# WooCommerce Integration Restoration - Implementation Plan
-
-**Parent Issue:** #7
-**Status:** Ready for Implementation
-**Estimated Time:** 58 hours (7-10 business days)
-**Full Documentation:** See `WOOCOMMERCE_RESTORATION_PLAN.md` in repository
-
----
-
-## Executive Summary
-
-The WooCommerce integration has a solid foundation with OAuth authentication and API client implemented, but lacks the complete data synchronization features that exist for ShopRenter. This plan outlines the steps to restore full WooCommerce functionality by implementing missing Edge Functions for product, order, and customer synchronization.
-
----
-
-## Current State
-
-### ✅ What's Working
-- OAuth 1.0a authentication flow (`oauth-woocommerce`)
-- API client with HMAC-SHA256 signatures (`_shared/woocommerce-client.ts`)
-- Frontend connection wizard (`WooCommerceConnect.tsx`)
-
-### ❌ What's Missing
-- Data synchronization Edge Functions (products, orders, customers)
-- Database cache tables for WooCommerce data
-- Scheduled background sync (pg_cron integration)
-- Frontend data display components
-- Webhook support for real-time updates
-
----
-
-## Implementation Phases
-
-### Phase 1: Edge Functions for Data Sync (18 hours) - HIGH PRIORITY
-
-**Create 4 Edge Functions:**
-
-1. **`woocommerce-products`** (4 hours)
-   - Fetch products from WooCommerce API
-   - Cache in `woocommerce_products_cache` table
-   - Support pagination for large catalogs
-   - Return product list to frontend
-
-2. **`woocommerce-orders`** (4 hours)
-   - Fetch orders with status filtering
-   - Cache in `woocommerce_orders_cache` table
-   - Support date range queries
-   - Return order list to frontend
-
-3. **`woocommerce-customers`** (4 hours)
-   - Fetch customer data
-   - Cache in `woocommerce_customers_cache` table
-   - Support search and filtering
-   - Return customer list to frontend
-
-4. **`woocommerce-sync`** (6 hours)
-   - Manual sync trigger endpoint
-   - Sync all data types in parallel
-   - Update `last_synced_at` timestamp
-   - Return comprehensive sync summary
-
----
-
-### Phase 2: Database Tables (3 hours) - HIGH PRIORITY
-
-**Create Migration:** `20250130_woocommerce_cache_tables.sql`
-
-**Tables to Create:**
-
-1. **`woocommerce_products_cache`**
-   - Product details (name, SKU, price, description)
-   - Stock information
-   - Categories and images (JSONB)
-   - Last sync timestamp
-
-2. **`woocommerce_orders_cache`**
-   - Order details (number, status, total)
-   - Customer information
-   - Line items (JSONB)
-   - Billing information
-   - Last sync timestamp
-
-3. **`woocommerce_customers_cache`**
-   - Customer contact details
-   - Billing information (JSONB)
-   - Last sync timestamp
-
-4. **Sync Tracking Columns**
-   - Add to `stores` table: `last_sync_at`, `sync_status`, `sync_error`
-
----
-
-### Phase 3: Scheduled Background Sync (8 hours) - MEDIUM PRIORITY
-
-1. **`woocommerce-scheduled-sync` Edge Function** (6 hours)
-   - Triggered by pg_cron every hour
-   - Fetch all enabled WooCommerce stores
-   - Sync each store's data
-   - Log results to `sync_logs` table
-   - Handle rate limiting
-
-2. **Database Configuration** (2 hours)
-   - Update `store_sync_config` for WooCommerce
-   - Create pg_cron job
-   - Configure environment variables
-
----
-
-### Phase 4: Frontend Integration (8 hours) - MEDIUM PRIORITY
-
-1. **Update IntegrationsContent.tsx** (2 hours)
-   - Add "Sync Now" button
-   - Display last sync time
-   - Show sync status indicators
-
-2. **Create Data Display Components** (6 hours)
-   - `WooCommerceProducts.tsx` - Product list
-   - `WooCommerceOrders.tsx` - Order list
-   - `WooCommerceCustomers.tsx` - Customer list
-   - Integrate with Dashboard and Analytics
-
----
-
-### Phase 5: Webhook Support (10 hours) - LOW PRIORITY
-
-1. **`webhook-woocommerce` Edge Function** (6 hours)
-   - Receive webhooks from WooCommerce
-   - Verify webhook signatures
-   - Update cache in real-time
-   - Support: order.created, order.updated, product.updated
-
-2. **Auto-register Webhooks** (4 hours)
-   - Register webhooks after OAuth
-   - Store webhook IDs in `woocommerce_webhooks` table
-   - Handle webhook lifecycle
-
----
-
-## Testing Strategy (8 hours)
-
-### Unit Tests
-- [ ] OAuth signature generation
-- [ ] API client error handling
-- [ ] Rate limiting logic
-- [ ] Product sync with pagination
-- [ ] Order filtering by status
-- [ ] Customer data mapping
-
-### Integration Tests
-- [ ] End-to-end OAuth flow
-- [ ] Complete sync cycle
-- [ ] Scheduled sync execution
-- [ ] Webhook processing
-- [ ] Frontend data display
-
-### Manual Testing
-- [ ] Connect test WooCommerce store
-- [ ] Trigger manual sync
-- [ ] Verify cached data
-- [ ] Test with 100+ products
-- [ ] Test edge cases (0 products, rate limits)
-- [ ] Verify disconnect/reconnect flow
-
----
-
-## Deployment Checklist
-
-### Pre-Deployment
-- [ ] Create staging environment
-- [ ] Deploy to staging
-- [ ] Run full test suite
-- [ ] Monitor Edge Function logs
-- [ ] Verify pg_cron configuration
-
-### Deployment
-- [ ] Run database migration
-- [ ] Deploy Edge Functions
-- [ ] Set environment variables
-- [ ] Configure database settings
-- [ ] Deploy frontend changes
-
-### Post-Deployment
-- [ ] Monitor logs for errors
-- [ ] Check sync_logs table
-- [ ] Verify pg_cron execution
-- [ ] Test with real stores
-- [ ] Set up failure alerts
-
----
-
-## Success Criteria
-
-**Functional:**
-- ✅ Users can connect WooCommerce stores
-- ✅ Products synced and cached
-- ✅ Orders synced with filtering
-- ✅ Customers synced
-- ✅ Manual sync works
-- ✅ Scheduled sync runs hourly
-- ✅ Frontend displays data
-- ✅ Webhooks update in real-time
-
-**Non-Functional:**
-- ⚡ Sync completes in < 30 seconds for 1000 products
-- 🔒 Credentials encrypted
-- 📊 Sync success rate > 95%
-- 🚫 Rate limiting prevents bans
-- 📝 Comprehensive logging
-
----
-
-## Risk Assessment
-
-### Technical Risks
-
-1. **Rate Limiting** (Medium)
-   - Mitigation: Exponential backoff, aggressive caching
-
-2. **Large Store Performance** (Medium)
-   - Mitigation: Batch processing, background jobs
-
-3. **OAuth Token Expiration** (Low)
-   - Mitigation: Test before sync, handle 401 errors
-
-4. **Webhook Reliability** (Low)
-   - Mitigation: Idempotent handling, signature verification
-
----
-
-## Rollback Plan
-
-If issues occur:
-1. Disable scheduled sync: `SELECT cron.unschedule('woocommerce-sync-hourly');`
-2. Hide manual sync button in frontend
-3. Rollback database migration: `supabase migration down`
-4. Rollback Edge Functions to previous version
-
----
-
-## Documentation Requirements
-
-### Developer Docs
-- [ ] API documentation for Edge Functions
-- [ ] Database schema documentation
-- [ ] Webhook setup guide
-- [ ] Troubleshooting guide
-
-### User Docs
-- [ ] Connection setup guide
-- [ ] Manual sync instructions
-- [ ] Sync status interpretation
-- [ ] FAQ
-
----
-
-## Acceptance Criteria
-
-Implementation complete when:
-
-1. ✅ All Edge Functions deployed
-2. ✅ Database migrations applied
-3. ✅ Manual sync works
-4. ✅ Scheduled sync runs automatically
-5. ✅ Sync logs show execution history
-6. ✅ Frontend displays data
-7. ✅ All tests pass
-8. ✅ Documentation complete
-9. ✅ 3+ real stores tested
-10. ✅ Code reviewed and approved
-
----
-
-## References
-
-- **Existing Implementation:** ShopRenter integration (`supabase/functions/shoprenter-*`)
-- **Full Plan:** `WOOCOMMERCE_RESTORATION_PLAN.md` in repository
-- **WooCommerce API:** https://woocommerce.github.io/woocommerce-rest-api-docs/
-- **OAuth 1.0a:** https://oauth.net/core/1.0a/
-- **Supabase Functions:** https://supabase.com/docs/guides/functions
-- **pg_cron:** https://github.com/citusdata/pg_cron
-
----
-
-## Next Steps
-
-1. Review and approve this plan
-2. Create subtasks for each phase
-3. Assign ownership
-4. Set up staging environment
-5. Begin Phase 1 implementation
-
----
-
-**Created:** 2025-01-30
-**Parent Issue:** #7
-**Full Documentation:** WOOCOMMERCE_RESTORATION_PLAN.md

+ 0 - 255
TODO.md

@@ -1,255 +0,0 @@
-# ShopCall.ai Refactoring TODO
-
-## Project Goal
-Refactor the entire project to remove Vercel dependencies and enable static hosting on simple webhosting. Use Supabase Edge Functions for backend functionality.
-
----
-
-## Phase 1: Analysis & Planning
-
-- [x] Analyze current backend API endpoints in `shopcall.ai-backend-main/api/index.js`
-  - [x] Document all authentication endpoints (signup, login, OTP, logout)
-  - [x] Document OAuth flows (Shopify, WooCommerce)
-  - [x] Document GDPR webhook endpoints
-  - [x] Document helper functions (generateOTP, sendOTPEmail, etc.)
-- [x] Identify current dependencies and integrations
-  - [x] Nodemailer for email sending → Replaced with Resend
-  - [x] In-memory stores (pendingSignups, nonceStore) → Replaced with database tables
-  - [x] Supabase client usage patterns
-- [x] Design Edge Functions architecture
-  - [x] Plan function structure and organization
-  - [x] Plan shared utilities and dependencies
-
----
-
-## Phase 2: Database Migration
-
-- [x] Create Supabase database tables to replace in-memory stores
-  - [x] Create `pending_signups` table (replace pendingSignups Map)
-    - Fields: signup_id, email, password, full_name, company_name, user_name, otp, created_at, expires_at
-  - [x] Create `oauth_nonces` table (replace nonceStore Map)
-    - Fields: nonce, user_id, platform, shop, app_url, shopname, created_at, expires_at
-  - [x] Add TTL/cleanup mechanism for expired records (cleanup functions created)
-- [x] Update existing `stores` table if needed (already has required fields)
-- [x] Create database migration files (applied via Supabase MCP)
-- [ ] Test database schema with sample data
-
----
-
-## Phase 3: Supabase Edge Functions Setup
-
-- [x] Set up Supabase Edge Functions project structure
-  - [x] Used Supabase MCP tool for deployment
-  - [x] Created modular function structure
-  - [x] Shared utilities (cors.ts, email.ts, oauth.ts)
-- [x] Create Edge Function for authentication endpoints
-  - [x] `/auth/signup` - Store user data and send OTP
-  - [x] `/auth/signup/verify` - Verify OTP and create user
-  - [x] `/auth/signup/resend-otp` - Resend OTP email
-  - [x] `/auth/login` - Email/password login
-  - [x] `/auth/logout` - Sign out
-  - [x] `/auth/check` - Validate session token
-- [x] Create Edge Function for Shopify integration
-  - [x] `/shopify-oauth/init` - Initialize OAuth flow
-  - [x] `/shopify-oauth/callback` - Handle OAuth callback
-- [x] Create Edge Function for WooCommerce integration
-  - [x] `/woocommerce-oauth/init` - Initialize OAuth flow (requires auth)
-  - [x] `/woocommerce-oauth/callback` - Handle OAuth callback
-- [x] Create Edge Function for GDPR webhooks
-  - [x] `/gdpr-webhooks/customers-data-request` - Customer data request
-  - [x] `/gdpr-webhooks/customers-redact` - Customer redaction
-  - [x] `/gdpr-webhooks/shop-redact` - Shop redaction
-- [x] Implement email sending in Edge Functions
-  - [x] Research Edge Function email options → Chose Resend
-  - [x] Implement OTP email templates
-  - [x] Replace Nodemailer functionality
-- [x] Create shared utilities for Edge Functions
-  - [x] OTP generation and validation (email.ts)
-  - [x] Email templates and sending (email.ts)
-  - [x] URL normalization and validation (oauth.ts)
-  - [x] HMAC webhook verification (in gdpr-webhooks)
-  - [x] CORS headers (cors.ts)
-
----
-
-## Phase 4: Frontend Refactoring
-
-- [x] Update frontend to use environment variables
-  - [x] Create `.env.example` file
-  - [x] Replace hardcoded backend URL (https://shopcall-ai-backend.vercel.app)
-  - [x] Add Supabase Edge Function base URL configuration
-- [x] Update API calls to use Edge Functions
-  - [x] Update AuthContext to call Edge Functions
-  - [x] Update all API endpoints in components (6 files updated)
-  - [ ] Test authentication flow
-- [x] Configure Vite for static build
-  - [x] Review vite.config.ts for static hosting (already configured)
-  - [x] Proper base path configuration exists
-  - [x] Build output directory configured (dist/)
-- [x] Add client-side routing support for static hosting
-  - [x] Create .htaccess for Apache hosting
-  - [x] Create nginx.conf example for Nginx hosting
-  - [x] Handle 404 fallback to index.html
-- [ ] Remove Vercel dependencies (optional - can keep for now)
-  - [ ] Delete vercel.json from frontend
-  - [ ] Remove any Vercel-specific code
-- [x] Update environment handling
-  - [x] Use Vite's import.meta.env
-  - [x] Centralized in src/lib/config.ts
-
----
-
-## Phase 5: Backend Cleanup
-
-- [ ] Remove Vercel-specific files from backend
-  - [ ] Delete vercel.json
-  - [ ] Archive api/index.js (keep for reference)
-- [ ] Move backend code to Edge Functions
-  - [ ] Ensure all functionality is migrated
-  - [ ] Delete unused files
-- [ ] Update .gitignore for both projects
-  - [ ] Ensure proper ignoring of build artifacts
-  - [ ] Ignore environment files
-  - [ ] Ignore Supabase local dev files
-
----
-
-## Phase 6: Deployment & Testing
-
-- [ ] Deploy Edge Functions to Supabase
-  - [ ] Configure Edge Function secrets
-  - [ ] Set up environment variables in Supabase
-  - [ ] Deploy each function
-  - [ ] Test Edge Function endpoints
-- [ ] Build frontend for static hosting
-  - [ ] Run production build (npm run build)
-  - [ ] Test build output locally
-  - [ ] Verify all routes work correctly
-  - [ ] Test with different hosting scenarios
-- [ ] End-to-end testing
-  - [ ] Test authentication flow (signup, OTP, login)
-  - [ ] Test Shopify OAuth integration
-  - [ ] Test WooCommerce OAuth integration
-  - [ ] Test dashboard and protected routes
-  - [ ] Test GDPR webhook endpoints
-- [ ] Performance testing
-  - [ ] Test Edge Function response times
-  - [ ] Test static hosting performance
-  - [ ] Optimize bundle size if needed
-
----
-
-## Phase 7: Documentation
-
-- [x] Create deployment guide for static hosting
-  - [x] Apache hosting setup with .htaccess
-  - [x] Nginx hosting setup with config
-  - [x] Environment variable configuration
-  - [x] Edge Functions deployment steps
-- [x] Create DEPLOYMENT_GUIDE.md
-  - [x] Document new Edge Functions architecture
-  - [x] Deployment instructions for multiple hosting options
-  - [x] Environment variable configuration
-  - [x] Testing procedures
-  - [x] Troubleshooting section
-- [x] Create REFACTORING_SUMMARY.md
-  - [x] Complete overview of all changes
-  - [x] What was accomplished
-  - [x] What remains to be done
-  - [x] Migration checklist
-- [ ] Update CLAUDE.md (optional)
-  - [ ] Document new Edge Functions architecture
-  - [ ] Update deployment instructions
-  - [ ] Remove Vercel-specific information
-  - [ ] Add static hosting requirements
-
----
-
-## Phase 8: Final Review
-
-- [ ] Code review and cleanup
-  - [ ] Remove unused dependencies
-  - [ ] Clean up commented code
-  - [ ] Ensure consistent code style
-- [ ] Security review
-  - [ ] Verify no secrets in code
-  - [ ] Check CORS configuration
-  - [ ] Verify authentication flows
-  - [ ] Test Edge Function security
-- [ ] Final testing
-  - [ ] Complete end-to-end test
-  - [ ] Test on actual static hosting
-  - [ ] Verify all features work
-- [ ] Git repository cleanup
-  - [ ] Commit all changes
-  - [ ] Create proper commit messages
-  - [ ] Tag release version
-
----
-
-## Notes
-
-### Current Architecture
-- **Frontend**: React/Vite at `shopcall.ai-main/` (deployed to Vercel)
-- **Backend**: Express.js serverless function at `shopcall.ai-backend-main/api/index.js` (deployed to Vercel)
-- **Database**: Supabase PostgreSQL
-- **Authentication**: Supabase Auth
-
-### Target Architecture
-- **Frontend**: Static React build (hosted on simple webhosting)
-- **Backend**: Supabase Edge Functions (Deno runtime)
-- **Database**: Supabase PostgreSQL (unchanged)
-- **Authentication**: Supabase Auth (unchanged)
-
-### Key Considerations
-- Edge Functions use Deno runtime (not Node.js)
-- Need to replace Nodemailer with Deno-compatible email solution
-- In-memory stores must move to Supabase database
-- Frontend needs proper routing configuration for static hosting
-- Environment variables must be properly managed for static hosting
-
-### Dependencies to Replace
-- ❌ Vercel serverless functions → ✅ Supabase Edge Functions
-- ❌ Nodemailer → ✅ Deno-compatible email service (Resend/SendGrid)
-- ❌ In-memory Maps → ✅ Supabase database tables
-- ❌ Hardcoded URLs → ✅ Environment variables
-
----
-
-## Progress Tracking
-
-**Status**: ✅ Core Implementation Complete - Testing Phase
-**Last Updated**: 2025-10-27
-**Current Phase**: Phase 6 - Deployment & Testing
-
-### Summary of Completed Work
-
-- ✅ Phase 1: Analysis & Planning - **COMPLETE**
-- ✅ Phase 2: Database Migration - **COMPLETE** (testing pending)
-- ✅ Phase 3: Edge Functions Setup - **COMPLETE**
-- ✅ Phase 4: Frontend Refactoring - **COMPLETE** (testing pending)
-- ⏭️ Phase 5: Backend Cleanup - **SKIPPED** (can keep old code for reference)
-- 🔄 Phase 6: Deployment & Testing - **IN PROGRESS**
-- ✅ Phase 7: Documentation - **COMPLETE**
-- ⏸️ Phase 8: Final Review - **PENDING**
-
-### What's Ready
-- Database tables created and configured
-- 4 Edge Functions deployed (auth, shopify-oauth, woocommerce-oauth, gdpr-webhooks)
-- Frontend updated to use Edge Functions
-- Static hosting configuration files created
-- Comprehensive documentation written
-
-### What Needs Testing
-- [ ] Complete authentication flow (signup → OTP → verify → login)
-- [ ] OAuth integrations (Shopify, WooCommerce)
-- [ ] Email delivery (Resend API needs to be configured)
-- [ ] Static hosting routing
-- [ ] GDPR webhooks
-
-### Next Steps
-1. Configure Resend API key in Supabase
-2. Test authentication flow end-to-end
-3. Test OAuth integrations
-4. Deploy to production hosting
-5. Update OAuth callback URLs in provider settings

+ 0 - 0
INTERNAL_API_KEYS.md → docs/INTERNAL_API_KEYS.md


+ 0 - 0
UNIFIED_API_FORMAT.md → docs/UNIFIED_API_FORMAT.md


+ 0 - 0
VAPI_INTEGRATION.md → docs/VAPI_INTEGRATION.md


+ 0 - 602
docs/shoprenter_app_development.md

@@ -1,602 +0,0 @@
-# ShopRenter App Development: Getting Started
-
-## Overview
-
-This document provides comprehensive guidance for developing applications that integrate with the ShopRenter e-commerce platform. ShopRenter apps can be either Embedded (loaded within the ShopRenter admin interface) or Redirected (external applications).
-
-**Reference**: This documentation is based on the official ShopRenter developer documentation at [doc.shoprenter.hu/development/app-development](https://doc.shoprenter.hu/development/app-development/01_getting_started.html).
-
-## Application Registration
-
-### Required Information
-
-Before developing a ShopRenter app, you must register your application by contacting ShopRenter Partner Support at **partnersupport@shoprenter.hu** with the following details:
-
-#### 1. Basic Information
-- **Application Name** - The name that will appear in the ShopRenter installable apps list
-- **Logo** - Image file with dimensions **250x150 pixels**
-- **Description** - Brief description of your app (maximum **70 characters**)
-- **Details Link** - URL to your application's sales/information page
-
-#### 2. Technical Configuration
-- **EntryPoint** - The HTTPS URL where your app is hosted
-  - Must use HTTPS protocol
-  - This is where ShopRenter will load your application
-
-- **RedirectUri** - The HTTPS authentication endpoint
-  - Receives authentication data during the OAuth flow
-  - Must use HTTPS protocol
-  - **Important**: Hash-based URL routes in SPAs (Single Page Applications) are technically incompatible
-
-- **UninstallUri** - The HTTPS endpoint called when app is uninstalled
-  - Receives GET request with query parameters: `shopname`, `code`, `timestamp`, `hmac`
-  - Must use HTTPS protocol
-  - Use this to clean up data and revoke access tokens
-
-#### 3. Application Type
-Choose one of two application types:
-
-**Embedded Application**
-- Loaded in an iframe within the ShopRenter admin interface
-- Accessible at: `[shopname].myshoprenter.hu/admin/app/[id]`
-- Provides seamless integration with the admin UI
-- Best for tools that complement the admin interface
-
-**Redirected Application**
-- External application that users are directed to
-- Directs users to the EntryPoint URL
-- Best for standalone tools or services
-
-#### 4. API Access
-- **Required Scopes** - List of API permissions your app needs
-  - Review available scopes in the ShopRenter API documentation
-  - Request only the permissions necessary for your app's functionality
-  - Users will see and approve these permissions during installation
-
-#### 5. Testing Environment
-- **Test Store Name** - Request a test store via [shoprenter.hu](https://shoprenter.hu)
-  - Format: `[shopName].myshoprenter.hu`
-  - Use this for development and testing before production release
-
-### Credentials You'll Receive
-
-After registration, ShopRenter Partner Support will provide:
-
-- **AppId** - Unique application identifier
-- **ClientId** - OAuth client identifier
-- **ClientSecret** - Secret key for HMAC validation and authentication
-- **App URL** - The registered application URL
-
-**⚠️ Security**: Keep your ClientSecret secure and never expose it in client-side code!
-
-## Installation Flow
-
-Understanding the installation process is critical for implementing your app correctly.
-
-### Step-by-Step Installation Process
-
-#### 1. User Initiates Installation
-- Shop owner browses the ShopRenter app marketplace
-- Clicks to install your application
-
-#### 2. ShopRenter Calls RedirectUri
-ShopRenter makes a GET request to your RedirectUri with these query parameters:
-
-- `shopname` - The shop's name (e.g., "example-shop")
-- `code` - Authorization code for token exchange
-- `timestamp` - Unix timestamp of the request
-- `hmac` - HMAC-SHA256 signature for validation
-- `app_url` - The URL where your app should redirect after validation
-
-**Example Request**:
-```
-https://your-app.com/auth/callback?shopname=example-shop&code=abc123&timestamp=1234567890&hmac=xyz789&app_url=https://example-shop.myshoprenter.hu/admin/app/123
-```
-
-#### 3. HMAC Validation (Critical Security Step)
-Your application MUST validate the HMAC signature to ensure the request is legitimate:
-
-**HMAC Validation Process**:
-1. Extract all query parameters except `hmac`
-2. Sort parameters alphabetically by key
-3. Create a query string: `key1=value1&key2=value2`
-4. Compute HMAC-SHA256 hash using your ClientSecret
-5. Compare computed hash with received `hmac` parameter
-6. If they match, the request is authentic
-
-**Example Validation (Pseudocode)**:
-```javascript
-function validateHmac(params, clientSecret) {
-  const { hmac, ...dataToValidate } = params;
-
-  // Sort parameters alphabetically
-  const sortedParams = Object.keys(dataToValidate)
-    .sort()
-    .map(key => `${key}=${dataToValidate[key]}`)
-    .join('&');
-
-  // Compute HMAC-SHA256
-  const computedHmac = crypto
-    .createHmac('sha256', clientSecret)
-    .update(sortedParams)
-    .digest('hex');
-
-  // Compare hashes
-  return computedHmac === hmac;
-}
-```
-
-**⚠️ Security Warning**: Never skip HMAC validation! This protects against unauthorized access attempts.
-
-#### 4. Token Exchange
-After validating the HMAC, exchange the authorization code for access tokens:
-
-- Use the `code` parameter from the callback
-- Make a POST request to ShopRenter's token endpoint
-- Receive `access_token` and `refresh_token`
-- Store tokens securely in your database
-
-**Note**: Basic Authentication is **deprecated**. Attempting to use Basic Auth will return **403 Forbidden** errors.
-
-#### 5. Redirect to App URL
-After successful token exchange:
-- Redirect the user to the `app_url` received in step 2
-- ShopRenter will then load your EntryPoint with authentication parameters
-
-#### 6. Application Loads
-- ShopRenter loads your EntryPoint (in iframe for Embedded apps)
-- Your app can now access the ShopRenter API using the obtained tokens
-
-### Installation Flow Diagram
-
-```
-┌──────────────┐
-│ Shop Owner   │
-│ Clicks       │
-│ "Install"    │
-└──────┬───────┘
-       │
-       ▼
-┌──────────────┐
-│ ShopRenter   │
-│ Calls        │
-│ RedirectUri  │
-└──────┬───────┘
-       │ (shopname, code, timestamp, hmac, app_url)
-       ▼
-┌──────────────────┐
-│ Your App         │
-│ Validates HMAC   │
-└──────┬───────────┘
-       │ ✓ Valid
-       ▼
-┌──────────────────┐
-│ Your App         │
-│ Exchanges Code   │
-│ for Tokens       │
-└──────┬───────────┘
-       │ (access_token, refresh_token)
-       ▼
-┌──────────────────┐
-│ Store Tokens     │
-│ in Database      │
-└──────┬───────────┘
-       │
-       ▼
-┌──────────────────┐
-│ Redirect to      │
-│ app_url          │
-└──────┬───────────┘
-       │
-       ▼
-┌──────────────────┐
-│ ShopRenter Loads │
-│ Your EntryPoint  │
-└──────────────────┘
-```
-
-## OAuth 2.0 Authentication
-
-ShopRenter uses OAuth 2.0 for secure API authentication.
-
-### Token Types
-
-#### Access Token
-- Used to authenticate API requests
-- Includes: `Authorization: Bearer {access_token}` header
-- Has a limited lifetime (expires after a period)
-- Must be refreshed when expired
-
-#### Refresh Token
-- Used to obtain new access tokens
-- Longer lifetime than access tokens
-- Store securely in your database
-
-### Token Management
-
-#### Storing Tokens
-Store tokens securely in your database with:
-- `store_id` - Unique identifier for the shop
-- `access_token` - Current access token
-- `refresh_token` - Refresh token for token renewal
-- `token_expires_at` - Timestamp when access token expires
-- `shopname` - Shop identifier
-
-**Database Example**:
-```sql
-CREATE TABLE shoprenter_tokens (
-  id UUID PRIMARY KEY,
-  store_id UUID REFERENCES stores(id),
-  access_token TEXT NOT NULL,
-  refresh_token TEXT,
-  expires_at TIMESTAMPTZ,
-  shopname VARCHAR NOT NULL,
-  scopes TEXT[],
-  created_at TIMESTAMPTZ DEFAULT NOW(),
-  updated_at TIMESTAMPTZ DEFAULT NOW()
-);
-```
-
-#### Token Refresh
-When an access token expires:
-1. Detect 401 Unauthorized response from API
-2. Use refresh token to request new access token
-3. Update stored access token and expiration time
-4. Retry the original API request
-
-**Token Refresh Flow**:
-```javascript
-async function refreshAccessToken(storeId) {
-  const store = await getStoreTokens(storeId);
-
-  const response = await fetch('https://oauth.shoprenter.hu/token', {
-    method: 'POST',
-    headers: { 'Content-Type': 'application/json' },
-    body: JSON.stringify({
-      grant_type: 'refresh_token',
-      refresh_token: store.refresh_token,
-      client_id: CLIENT_ID,
-      client_secret: CLIENT_SECRET
-    })
-  });
-
-  const { access_token, expires_in } = await response.json();
-
-  await updateStoreToken(storeId, {
-    access_token,
-    token_expires_at: new Date(Date.now() + expires_in * 1000)
-  });
-
-  return access_token;
-}
-```
-
-### API Authentication
-
-All API requests must include the access token in the Authorization header:
-
-```http
-GET /products HTTP/1.1
-Host: example-shop.api.shoprenter.hu
-Authorization: Bearer {access_token}
-```
-
-## Scope Management
-
-Scopes define the permissions your app has to access ShopRenter resources.
-
-### Requesting Scopes
-
-When registering your app, request only the scopes necessary for your app's functionality. Common scopes include:
-
-- `read_products` - Read product catalog
-- `read_orders` - Access order information
-- `read_customers` - View customer data
-- `read_inventory` - Check inventory levels
-- And more (see ShopRenter API documentation for complete list)
-
-### Adding New Scopes
-
-If you need to add features requiring additional permissions:
-
-1. **Contact Partner Support** - Request the new scopes
-2. **Update App Registration** - ShopRenter updates your app's scope list
-3. **Request User Consent** - Existing installations need shop owner approval
-
-### Scope Approval for Existing Installations
-
-After new scopes are added, shop owners must approve them by visiting:
-
-```
-https://{shopName}.myshoprenter.hu/admin/app/{clientId}/approveScopes
-```
-
-**Implementation Steps**:
-1. Detect missing permissions (API returns permission errors)
-2. Notify shop owner about new features requiring permissions
-3. Provide a link to the approval URL
-4. After approval, your app has access to the new scopes
-
-**Example User Flow**:
-```javascript
-function requestScopeApproval(shopName, clientId) {
-  const approvalUrl = `https://${shopName}.myshoprenter.hu/admin/app/${clientId}/approveScopes`;
-
-  // Show notification to shop owner
-  showNotification({
-    message: 'New features available! Please approve additional permissions.',
-    action: {
-      text: 'Approve Permissions',
-      url: approvalUrl
-    }
-  });
-}
-```
-
-## Uninstallation Flow
-
-When a shop owner uninstalls your app, ShopRenter sends a GET request to your UninstallUri.
-
-### Uninstall Request Parameters
-
-The request includes these query parameters:
-- `shopname` - The shop's name
-- `code` - Uninstall verification code
-- `timestamp` - Unix timestamp
-- `hmac` - HMAC-SHA256 signature for validation
-
-**Example Request**:
-```
-https://your-app.com/uninstall?shopname=example-shop&code=xyz789&timestamp=1234567890&hmac=abc123
-```
-
-### Handling Uninstallation
-
-Your UninstallUri endpoint should:
-
-1. **Validate HMAC** - Ensure the request is legitimate (same process as installation)
-2. **Clean Up Data** - Remove or anonymize shop-specific data
-3. **Revoke Tokens** - Delete stored access and refresh tokens
-4. **Log Event** - Record the uninstallation for analytics
-5. **Return Success** - Respond with 200 OK status
-
-**Example Handler**:
-```javascript
-async function handleUninstall(req) {
-  const { shopname, code, timestamp, hmac } = req.query;
-
-  // 1. Validate HMAC
-  if (!validateHmac(req.query, CLIENT_SECRET)) {
-    return res.status(401).json({ error: 'Invalid HMAC' });
-  }
-
-  // 2. Find store
-  const store = await findStoreByShopname(shopname);
-
-  // 3. Clean up data
-  await deleteStoreData(store.id);
-
-  // 4. Revoke tokens
-  await deleteStoreTokens(store.id);
-
-  // 5. Mark as inactive
-  await markStoreInactive(store.id);
-
-  // 6. Log event
-  await logUninstallEvent(store.id, timestamp);
-
-  return res.status(200).json({ success: true });
-}
-```
-
-## Development Best Practices
-
-### Security
-
-1. **Always Validate HMAC** - On both installation and uninstallation requests
-2. **Use HTTPS** - All endpoints must use secure HTTPS connections
-3. **Secure Token Storage** - Encrypt tokens at rest in your database
-4. **Rotate Secrets** - Periodically rotate your ClientSecret (coordinate with Partner Support)
-5. **Rate Limiting** - Implement rate limiting for API calls to avoid throttling
-6. **Error Handling** - Handle API errors gracefully and provide helpful feedback
-
-### OAuth Implementation
-
-1. **Token Refresh** - Implement automatic token refresh before expiration
-2. **Retry Logic** - Retry failed API calls with exponential backoff
-3. **Scope Validation** - Check that you have required scopes before making requests
-4. **State Management** - Use state parameter in OAuth flow to prevent CSRF attacks
-
-### User Experience
-
-1. **Loading States** - Show loading indicators during API operations
-2. **Error Messages** - Provide clear, actionable error messages
-3. **Onboarding** - Guide new users through setup and configuration
-4. **Documentation** - Provide comprehensive user documentation
-5. **Support** - Offer responsive customer support
-
-### Testing
-
-1. **Test Store** - Use your test store for development and testing
-2. **Edge Cases** - Test token expiration, network failures, and permission errors
-3. **HMAC Validation** - Verify HMAC validation works correctly
-4. **Uninstall Flow** - Test the complete uninstall process
-5. **Multi-Shop** - Test with multiple shops if supporting multi-shop scenarios
-
-## API Usage
-
-### Base URL
-
-All API requests go to:
-```
-https://{shopname}.api.shoprenter.hu
-```
-
-Replace `{shopname}` with the shop's actual name.
-
-### Making API Requests
-
-**Example: Fetching Products**
-```javascript
-async function fetchProducts(shopname, accessToken) {
-  const response = await fetch(
-    `https://${shopname}.api.shoprenter.hu/products`,
-    {
-      headers: {
-        'Authorization': `Bearer ${accessToken}`,
-        'Content-Type': 'application/json'
-      }
-    }
-  );
-
-  if (!response.ok) {
-    if (response.status === 401) {
-      // Token expired, refresh and retry
-      const newToken = await refreshAccessToken(storeId);
-      return fetchProducts(shopname, newToken);
-    }
-    throw new Error(`API Error: ${response.status}`);
-  }
-
-  return response.json();
-}
-```
-
-### Pagination
-
-ShopRenter API supports pagination for large datasets:
-
-```javascript
-async function fetchAllProducts(shopname, accessToken) {
-  let allProducts = [];
-  let page = 1;
-  let hasMore = true;
-
-  while (hasMore) {
-    const response = await fetch(
-      `https://${shopname}.api.shoprenter.hu/products?page=${page}&limit=100`,
-      {
-        headers: {
-          'Authorization': `Bearer ${accessToken}`,
-          'Content-Type': 'application/json'
-        }
-      }
-    );
-
-    const data = await response.json();
-    allProducts = allProducts.concat(data.items);
-
-    hasMore = data.items.length === 100;
-    page++;
-  }
-
-  return allProducts;
-}
-```
-
-### Rate Limiting
-
-Implement rate limiting to respect API quotas:
-
-```javascript
-class RateLimiter {
-  constructor(maxRequests = 5, perSecond = 1) {
-    this.maxRequests = maxRequests;
-    this.perSecond = perSecond;
-    this.queue = [];
-    this.processing = false;
-  }
-
-  async request(fn) {
-    return new Promise((resolve, reject) => {
-      this.queue.push({ fn, resolve, reject });
-      this.processQueue();
-    });
-  }
-
-  async processQueue() {
-    if (this.processing || this.queue.length === 0) return;
-
-    this.processing = true;
-    const { fn, resolve, reject } = this.queue.shift();
-
-    try {
-      const result = await fn();
-      resolve(result);
-    } catch (error) {
-      reject(error);
-    }
-
-    setTimeout(() => {
-      this.processing = false;
-      this.processQueue();
-    }, (1000 / this.maxRequests) * this.perSecond);
-  }
-}
-
-const limiter = new RateLimiter(5, 1); // 5 requests per second
-
-// Usage
-await limiter.request(() => fetchProducts(shopname, token));
-```
-
-## Reference Resources
-
-ShopRenter provides example implementations to help you get started:
-
-### Example Applications
-
-1. **SR Demo App (PHP)** - Basic PHP implementation
-2. **PHP Slim Framework** - REST API implementation using Slim
-3. **Node.js** - JavaScript/Node.js implementation
-
-These examples are available on GitHub (referenced in ShopRenter documentation).
-
-### Documentation Links
-
-- **App Development Guide**: [doc.shoprenter.hu/development/app-development](https://doc.shoprenter.hu/development/app-development/01_getting_started.html)
-- **API Documentation**: [doc.shoprenter.hu/api](https://doc.shoprenter.hu/api/)
-- **Payment API**: [doc.shoprenter.hu/paymentapi](https://doc.shoprenter.hu/paymentapi/)
-
-## ShopCall.ai Integration
-
-This project (ShopCall.ai) implements ShopRenter integration with the following components:
-
-### Edge Functions
-- `oauth-shoprenter-init` - Initiates OAuth flow
-- `oauth-shoprenter-callback` - Handles OAuth callback
-- `webhook-shoprenter-uninstall` - Handles app uninstallation
-- `shoprenter-sync` - Manual data synchronization
-- `shoprenter-scheduled-sync` - Automated background sync (hourly via pg_cron)
-
-### API Client
-- `_shared/shoprenter-client.ts` - ShopRenter API client with token refresh
-
-### Data Sync
-- Products, orders, and customers cached in Supabase tables
-- Automatic token refresh when expired
-- Rate limiting (5 requests/second)
-- Retry logic with exponential backoff
-
-### Database Tables
-- `shoprenter_tokens` - Token management
-- `shoprenter_products_cache` - Cached product data
-- `pending_shoprenter_installs` - Temporary OAuth state
-- `oauth_states` - OAuth flow state management
-- `sync_logs` - Sync execution tracking
-- `store_sync_config` - Per-store sync configuration
-
-See `CLAUDE.md` for complete implementation details.
-
-## Getting Help
-
-For questions or issues:
-
-1. **ShopRenter Partner Support**: partnersupport@shoprenter.hu
-2. **Developer Documentation**: [doc.shoprenter.hu](https://doc.shoprenter.hu)
-3. **API Documentation**: [doc.shoprenter.hu/api](https://doc.shoprenter.hu/api/)
-
----
-
-*Last Updated: 2025-01-30*
-*Based on: ShopRenter Developer Documentation - App Development - Getting Started*

+ 0 - 1513
docs/shoprenter_payment_implementation_plan.md

@@ -1,1513 +0,0 @@
-# ShopRenter Payment API Implementation Plan
-
-**Project:** ShopCall.ai - ShopRenter Payment Integration
-**Version:** 1.0
-**Date:** 2025-11-11
-**Status:** Planning Phase
-
----
-
-## 📋 Table of Contents
-
-1. [Executive Summary](#executive-summary)
-2. [Background & Context](#background--context)
-3. [Critical Requirements](#critical-requirements)
-4. [Architecture Overview](#architecture-overview)
-5. [Database Schema](#database-schema)
-6. [Backend Implementation](#backend-implementation)
-7. [Payment Flow](#payment-flow)
-8. [Store Validation](#store-validation)
-9. [Security Considerations](#security-considerations)
-10. [Testing Strategy](#testing-strategy)
-11. [Deployment Plan](#deployment-plan)
-12. [Timeline & Milestones](#timeline--milestones)
-
----
-
-## 🎯 Executive Summary
-
-This document outlines the implementation plan for integrating the ShopRenter Payment API into ShopCall.ai. The integration will enable **ShopRenter stores only** to subscribe to ShopCall.ai services and be billed directly through ShopRenter's payment infrastructure.
-
-### Key Objectives
-
-- ✅ Enable subscription-based billing for ShopRenter stores
-- ✅ Process payments exclusively through ShopRenter Payment API
-- ✅ Enforce strict store validation (ShopRenter stores only)
-- ✅ Implement automatic invoicing and VAT handling
-- ✅ Support both one-time and recurring payment plans
-- ✅ Maintain GDPR compliance and data security
-
-### Core Principle
-
-**⚠️ CRITICAL RULE:** The ShopRenter Payment API **MUST ONLY** be used with ShopRenter stores. Any non-ShopRenter store attempting to use this payment method must be rejected with appropriate error messages.
-
----
-
-## 📖 Background & Context
-
-### What is ShopRenter Payment API?
-
-The ShopRenter Payment API is a comprehensive payment processing toolkit provided by ShopRenter for application developers. It enables:
-
-- **Card payment processing** (one-time and recurring)
-- **Automatic invoicing** with VAT calculation
-- **Subscription management** with payment plans
-- **Financial statistics** and income tracking
-- **Webhook notifications** for payment events
-
-### Current ShopCall.ai Integration Status
-
-ShopCall.ai already has a **fully implemented ShopRenter store integration** including:
-
-- ✅ OAuth 2.0 authentication flow
-- ✅ HMAC validation for security
-- ✅ Product, order, and customer data synchronization
-- ✅ Webhook handlers for data updates
-- ✅ Scheduled background sync (pg_cron)
-- ✅ Database tables for storing ShopRenter credentials and data
-
-**Reference:** See `docs/shoprenter_app_development.md` and `SHOPRENTER.md` for complete details.
-
-### Why Payment API Integration?
-
-Currently, ShopCall.ai uses a generic payment processor (e.g., Stripe) for all stores. Integrating ShopRenter Payment API provides:
-
-1. **Native billing** for ShopRenter merchants (billed through their ShopRenter account)
-2. **Simplified checkout** (no need to enter payment details separately)
-3. **Unified invoicing** (all invoices in one place - ShopRenter admin)
-4. **Better conversion** (trust and familiarity with ShopRenter billing)
-5. **Automatic VAT handling** (compliant with Hungarian tax laws)
-
----
-
-## ⚠️ Critical Requirements
-
-### 1. Store Platform Validation (MANDATORY)
-
-**Rule:** The ShopRenter Payment API can **ONLY** be used with stores that have `platform_name = 'shoprenter'` in the `stores` table.
-
-**Enforcement Points:**
-- Payment page rendering (frontend)
-- Payment initiation API endpoint (backend)
-- Subscription creation endpoint (backend)
-- Webhook handlers (backend)
-
-**Validation Logic:**
-```typescript
-async function validateStoreForShopRenterPayment(storeId: string): Promise<boolean> {
-  const { data: store } = await supabase
-    .from('stores')
-    .select('platform_name, is_active')
-    .eq('id', storeId)
-    .single();
-
-  if (!store) {
-    throw new Error('Store not found');
-  }
-
-  if (!store.is_active) {
-    throw new Error('Store is inactive');
-  }
-
-  if (store.platform_name !== 'shoprenter') {
-    throw new Error('ShopRenter Payment API can only be used with ShopRenter stores');
-  }
-
-  return true;
-}
-```
-
-### 2. ShopRenter App Registration
-
-Before using the Payment API, the ShopCall.ai app must be:
-- ✅ Registered with ShopRenter Partner Support
-- ✅ Approved for use in production
-- ✅ Configured with Payment API access
-
-**Current Status:** ShopCall.ai is ready for registration (see `SHOPRENTER_REGISTRATION.md`).
-
-### 3. Required Credentials
-
-The Payment API will require additional credentials beyond the OAuth credentials:
-
-- `SHOPRENTER_CLIENT_ID` - OAuth client ID (already configured)
-- `SHOPRENTER_CLIENT_SECRET` - OAuth secret (already configured)
-- `SHOPRENTER_PAYMENT_API_KEY` - Payment API specific key (to be obtained)
-- `SHOPRENTER_PAYMENT_SECRET` - Payment API webhook secret (to be obtained)
-
-### 4. Scope Requirements
-
-The app must request payment-related scopes during OAuth:
-- `payment:read` - Read payment information
-- `payment:write` - Create payment plans and initiate charges
-- `billing:read` - Access billing data
-- `billing:write` - Update billing information
-
----
-
-## 🏗️ Architecture Overview
-
-### System Components
-
-```
-┌─────────────────────┐
-│   ShopRenter        │
-│   Store Owner       │
-└──────────┬──────────┘
-           │
-           │ 1. Connect Store (OAuth)
-           ▼
-┌─────────────────────┐
-│   ShopCall.ai       │
-│   Frontend          │
-└──────────┬──────────┘
-           │
-           │ 2. Select Subscription Plan
-           ▼
-┌─────────────────────┐
-│   ShopCall.ai       │
-│   Backend           │
-│   (Edge Function)   │
-└──────────┬──────────┘
-           │
-           │ 3. Create Payment Plan
-           │    (via ShopRenter Payment API)
-           ▼
-┌─────────────────────┐
-│   ShopRenter        │
-│   Payment API       │
-└──────────┬──────────┘
-           │
-           │ 4. Process Payment
-           │    (Automatic Recurring Billing)
-           ▼
-┌─────────────────────┐
-│   ShopRenter        │
-│   Payment Gateway   │
-└──────────┬──────────┘
-           │
-           │ 5. Webhook Notification
-           │    (payment.success, payment.failed, etc.)
-           ▼
-┌─────────────────────┐
-│   ShopCall.ai       │
-│   Webhook Handler   │
-│   (Edge Function)   │
-└──────────┬──────────┘
-           │
-           │ 6. Update Subscription Status
-           ▼
-┌─────────────────────┐
-│   Supabase          │
-│   Database          │
-└─────────────────────┘
-```
-
-### Integration Flow
-
-1. **Store Connection**: Merchant connects ShopRenter store via OAuth (already implemented)
-2. **Subscription Selection**: Merchant selects a ShopCall.ai subscription plan
-3. **Platform Validation**: Backend validates `platform_name = 'shoprenter'`
-4. **Payment Plan Creation**: Backend creates payment plan via ShopRenter Payment API
-5. **Billing Data**: ShopRenter uses merchant's existing billing information
-6. **Automatic Billing**: ShopRenter charges merchant's card on schedule
-7. **Webhook Events**: ShopRenter sends payment status updates to ShopCall.ai
-8. **Subscription Management**: ShopCall.ai updates subscription status based on webhook events
-
----
-
-## 💾 Database Schema
-
-### New Table: `shoprenter_payment_plans`
-
-Stores payment plans configured through ShopRenter Payment API.
-
-```sql
-CREATE TABLE shoprenter_payment_plans (
-  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-
-  -- Store reference
-  store_id UUID NOT NULL REFERENCES stores(id) ON DELETE CASCADE,
-
-  -- ShopRenter Payment API identifiers
-  payment_plan_id VARCHAR(255) NOT NULL, -- ID from ShopRenter Payment API
-  app_payment_id VARCHAR(255), -- Application-specific payment ID
-
-  -- Plan details
-  plan_name VARCHAR(255) NOT NULL, -- e.g., "Basic Plan", "Pro Plan"
-  plan_type VARCHAR(50) NOT NULL, -- "one_time", "recurring"
-  amount DECIMAL(10, 2) NOT NULL, -- Price in HUF
-  currency VARCHAR(3) DEFAULT 'HUF',
-  billing_frequency VARCHAR(50), -- "monthly", "yearly", "quarterly"
-
-  -- Status
-  status VARCHAR(50) NOT NULL DEFAULT 'pending', -- pending, active, cancelled, failed, expired
-
-  -- Timestamps from ShopRenter
-  trial_ends_at TIMESTAMPTZ, -- Trial period end (if applicable)
-  next_billing_date TIMESTAMPTZ, -- Next scheduled charge
-  activated_at TIMESTAMPTZ, -- When subscription became active
-  cancelled_at TIMESTAMPTZ, -- When subscription was cancelled
-  expires_at TIMESTAMPTZ, -- Expiration date
-
-  -- Metadata
-  raw_data JSONB, -- Full response from ShopRenter Payment API
-  created_at TIMESTAMPTZ DEFAULT NOW(),
-  updated_at TIMESTAMPTZ DEFAULT NOW(),
-
-  -- Constraints
-  UNIQUE(store_id, payment_plan_id)
-);
-
--- Indexes
-CREATE INDEX idx_shoprenter_payment_plans_store ON shoprenter_payment_plans(store_id);
-CREATE INDEX idx_shoprenter_payment_plans_status ON shoprenter_payment_plans(status);
-CREATE INDEX idx_shoprenter_payment_plans_next_billing ON shoprenter_payment_plans(next_billing_date);
-
--- Trigger for updated_at
-CREATE TRIGGER set_shoprenter_payment_plans_updated_at
-BEFORE UPDATE ON shoprenter_payment_plans
-FOR EACH ROW
-EXECUTE FUNCTION update_updated_at_column();
-```
-
-### New Table: `shoprenter_payment_transactions`
-
-Tracks individual payment transactions and webhook events.
-
-```sql
-CREATE TABLE shoprenter_payment_transactions (
-  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-
-  -- References
-  store_id UUID NOT NULL REFERENCES stores(id) ON DELETE CASCADE,
-  payment_plan_id UUID REFERENCES shoprenter_payment_plans(id) ON DELETE SET NULL,
-
-  -- ShopRenter identifiers
-  transaction_id VARCHAR(255) NOT NULL, -- Transaction ID from ShopRenter
-  charge_id VARCHAR(255), -- Charge ID from Payment API
-
-  -- Transaction details
-  transaction_type VARCHAR(50) NOT NULL, -- "charge", "refund", "update"
-  amount DECIMAL(10, 2) NOT NULL,
-  currency VARCHAR(3) DEFAULT 'HUF',
-  status VARCHAR(50) NOT NULL, -- "pending", "success", "failed", "refunded"
-
-  -- Payment method
-  payment_method VARCHAR(50), -- "card", "bank_transfer", etc.
-  card_last4 VARCHAR(4), -- Last 4 digits of card
-  card_brand VARCHAR(50), -- "visa", "mastercard", etc.
-
-  -- Invoice
-  invoice_number VARCHAR(255),
-  invoice_url TEXT,
-
-  -- Error handling
-  error_code VARCHAR(50),
-  error_message TEXT,
-
-  -- Timestamps
-  processed_at TIMESTAMPTZ,
-  refunded_at TIMESTAMPTZ,
-
-  -- Metadata
-  raw_data JSONB, -- Full webhook payload
-  created_at TIMESTAMPTZ DEFAULT NOW(),
-
-  -- Constraints
-  UNIQUE(transaction_id)
-);
-
--- Indexes
-CREATE INDEX idx_shoprenter_transactions_store ON shoprenter_payment_transactions(store_id);
-CREATE INDEX idx_shoprenter_transactions_plan ON shoprenter_payment_transactions(payment_plan_id);
-CREATE INDEX idx_shoprenter_transactions_status ON shoprenter_payment_transactions(status);
-CREATE INDEX idx_shoprenter_transactions_date ON shoprenter_payment_transactions(created_at);
-```
-
-### Update Existing `stores` Table
-
-Add payment-related fields to track subscription status.
-
-```sql
-ALTER TABLE stores
-  ADD COLUMN IF NOT EXISTS shoprenter_payment_plan_id UUID REFERENCES shoprenter_payment_plans(id),
-  ADD COLUMN IF NOT EXISTS subscription_status VARCHAR(50) DEFAULT 'inactive',
-  ADD COLUMN IF NOT EXISTS subscription_started_at TIMESTAMPTZ,
-  ADD COLUMN IF NOT EXISTS subscription_ends_at TIMESTAMPTZ;
-
--- Index for subscription queries
-CREATE INDEX IF NOT EXISTS idx_stores_subscription_status ON stores(subscription_status);
-```
-
-### Migration Script
-
-```sql
--- Migration: Add ShopRenter Payment API support
--- Version: 20251111_shoprenter_payment_api.sql
-
-BEGIN;
-
--- Create payment plans table
-CREATE TABLE IF NOT EXISTS shoprenter_payment_plans (
-  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-  store_id UUID NOT NULL REFERENCES stores(id) ON DELETE CASCADE,
-  payment_plan_id VARCHAR(255) NOT NULL,
-  app_payment_id VARCHAR(255),
-  plan_name VARCHAR(255) NOT NULL,
-  plan_type VARCHAR(50) NOT NULL,
-  amount DECIMAL(10, 2) NOT NULL,
-  currency VARCHAR(3) DEFAULT 'HUF',
-  billing_frequency VARCHAR(50),
-  status VARCHAR(50) NOT NULL DEFAULT 'pending',
-  trial_ends_at TIMESTAMPTZ,
-  next_billing_date TIMESTAMPTZ,
-  activated_at TIMESTAMPTZ,
-  cancelled_at TIMESTAMPTZ,
-  expires_at TIMESTAMPTZ,
-  raw_data JSONB,
-  created_at TIMESTAMPTZ DEFAULT NOW(),
-  updated_at TIMESTAMPTZ DEFAULT NOW(),
-  UNIQUE(store_id, payment_plan_id)
-);
-
-CREATE INDEX idx_shoprenter_payment_plans_store ON shoprenter_payment_plans(store_id);
-CREATE INDEX idx_shoprenter_payment_plans_status ON shoprenter_payment_plans(status);
-CREATE INDEX idx_shoprenter_payment_plans_next_billing ON shoprenter_payment_plans(next_billing_date);
-
--- Create payment transactions table
-CREATE TABLE IF NOT EXISTS shoprenter_payment_transactions (
-  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-  store_id UUID NOT NULL REFERENCES stores(id) ON DELETE CASCADE,
-  payment_plan_id UUID REFERENCES shoprenter_payment_plans(id) ON DELETE SET NULL,
-  transaction_id VARCHAR(255) NOT NULL,
-  charge_id VARCHAR(255),
-  transaction_type VARCHAR(50) NOT NULL,
-  amount DECIMAL(10, 2) NOT NULL,
-  currency VARCHAR(3) DEFAULT 'HUF',
-  status VARCHAR(50) NOT NULL,
-  payment_method VARCHAR(50),
-  card_last4 VARCHAR(4),
-  card_brand VARCHAR(50),
-  invoice_number VARCHAR(255),
-  invoice_url TEXT,
-  error_code VARCHAR(50),
-  error_message TEXT,
-  processed_at TIMESTAMPTZ,
-  refunded_at TIMESTAMPTZ,
-  raw_data JSONB,
-  created_at TIMESTAMPTZ DEFAULT NOW(),
-  UNIQUE(transaction_id)
-);
-
-CREATE INDEX idx_shoprenter_transactions_store ON shoprenter_payment_transactions(store_id);
-CREATE INDEX idx_shoprenter_transactions_plan ON shoprenter_payment_transactions(payment_plan_id);
-CREATE INDEX idx_shoprenter_transactions_status ON shoprenter_payment_transactions(status);
-CREATE INDEX idx_shoprenter_transactions_date ON shoprenter_payment_transactions(created_at);
-
--- Update stores table
-ALTER TABLE stores
-  ADD COLUMN IF NOT EXISTS shoprenter_payment_plan_id UUID REFERENCES shoprenter_payment_plans(id),
-  ADD COLUMN IF NOT EXISTS subscription_status VARCHAR(50) DEFAULT 'inactive',
-  ADD COLUMN IF NOT EXISTS subscription_started_at TIMESTAMPTZ,
-  ADD COLUMN IF NOT EXISTS subscription_ends_at TIMESTAMPTZ;
-
-CREATE INDEX IF NOT EXISTS idx_stores_subscription_status ON stores(subscription_status);
-
--- Create trigger for updated_at
-CREATE TRIGGER set_shoprenter_payment_plans_updated_at
-BEFORE UPDATE ON shoprenter_payment_plans
-FOR EACH ROW
-EXECUTE FUNCTION update_updated_at_column();
-
-COMMIT;
-```
-
----
-
-## 🔧 Backend Implementation
-
-### File Structure
-
-```
-supabase/functions/
-├── shoprenter-payment-create/
-│   └── index.ts                    # Create payment plan endpoint
-├── shoprenter-payment-cancel/
-│   └── index.ts                    # Cancel subscription endpoint
-├── shoprenter-payment-update/
-│   └── index.ts                    # Update payment plan endpoint
-├── shoprenter-payment-webhook/
-│   └── index.ts                    # Payment webhook handler
-├── shoprenter-payment-status/
-│   └── index.ts                    # Check payment status endpoint
-└── _shared/
-    └── shoprenter-payment-client.ts # ShopRenter Payment API client
-```
-
-### 1. Payment API Client (`_shared/shoprenter-payment-client.ts`)
-
-```typescript
-import { createClient } from 'https://esm.sh/@supabase/supabase-js@2';
-
-interface PaymentPlanParams {
-  storeId: string;
-  planName: string;
-  planType: 'one_time' | 'recurring';
-  amount: number;
-  currency?: string;
-  billingFrequency?: 'monthly' | 'yearly' | 'quarterly';
-  trialDays?: number;
-}
-
-interface PaymentPlanResponse {
-  paymentPlanId: string;
-  status: string;
-  activatedAt?: string;
-  nextBillingDate?: string;
-  invoiceUrl?: string;
-}
-
-/**
- * ShopRenter Payment API Client
- * Handles all payment-related API calls to ShopRenter
- */
-export class ShopRenterPaymentClient {
-  private apiKey: string;
-  private apiSecret: string;
-  private supabase: any;
-
-  constructor() {
-    this.apiKey = Deno.env.get('SHOPRENTER_PAYMENT_API_KEY')!;
-    this.apiSecret = Deno.env.get('SHOPRENTER_PAYMENT_SECRET')!;
-    this.supabase = createClient(
-      Deno.env.get('SUPABASE_URL')!,
-      Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
-    );
-  }
-
-  /**
-   * Validate that store is ShopRenter platform
-   */
-  async validateShopRenterStore(storeId: string): Promise<void> {
-    const { data: store, error } = await this.supabase
-      .from('stores')
-      .select('platform_name, is_active, store_name')
-      .eq('id', storeId)
-      .single();
-
-    if (error || !store) {
-      throw new Error('Store not found');
-    }
-
-    if (!store.is_active) {
-      throw new Error('Store is inactive');
-    }
-
-    if (store.platform_name !== 'shoprenter') {
-      throw new Error(
-        'ShopRenter Payment API can only be used with ShopRenter stores. ' +
-        `Current platform: ${store.platform_name}`
-      );
-    }
-  }
-
-  /**
-   * Get ShopRenter access token for store
-   */
-  async getAccessToken(storeId: string): Promise<string> {
-    const { data: store, error } = await this.supabase
-      .from('stores')
-      .select('api_key, token_expires_at, store_name')
-      .eq('id', storeId)
-      .single();
-
-    if (error || !store) {
-      throw new Error('Store credentials not found');
-    }
-
-    // Check if token needs refresh
-    const expiresAt = new Date(store.token_expires_at);
-    const now = new Date();
-    const bufferMinutes = 5;
-
-    if (expiresAt.getTime() - now.getTime() < bufferMinutes * 60 * 1000) {
-      // Token expired or expiring soon - refresh it
-      // Implementation depends on ShopRenter OAuth refresh flow
-      console.log(`[ShopRenter Payment] Token refresh needed for ${store.store_name}`);
-      // TODO: Implement token refresh
-    }
-
-    return store.api_key;
-  }
-
-  /**
-   * Create a payment plan via ShopRenter Payment API
-   */
-  async createPaymentPlan(params: PaymentPlanParams): Promise<PaymentPlanResponse> {
-    // 1. Validate store platform
-    await this.validateShopRenterStore(params.storeId);
-
-    // 2. Get store details
-    const { data: store } = await this.supabase
-      .from('stores')
-      .select('store_name, store_url')
-      .eq('id', params.storeId)
-      .single();
-
-    const accessToken = await this.getAccessToken(params.storeId);
-
-    // 3. Call ShopRenter Payment API
-    // NOTE: Actual API endpoint URL and structure to be confirmed with ShopRenter docs
-    const apiUrl = `https://${store.store_name}.api.shoprenter.hu/payment/plans`;
-
-    const response = await fetch(apiUrl, {
-      method: 'POST',
-      headers: {
-        'Authorization': `Bearer ${accessToken}`,
-        'Content-Type': 'application/json',
-        'X-ShopRenter-API-Key': this.apiKey,
-      },
-      body: JSON.stringify({
-        name: params.planName,
-        type: params.planType,
-        amount: params.amount,
-        currency: params.currency || 'HUF',
-        billing_frequency: params.billingFrequency,
-        trial_days: params.trialDays || 0,
-        return_url: `${Deno.env.get('FRONTEND_URL')}/billing/success`,
-        cancel_url: `${Deno.env.get('FRONTEND_URL')}/billing/cancel`,
-        notification_url: `${Deno.env.get('SUPABASE_URL')}/functions/v1/shoprenter-payment-webhook`,
-      }),
-    });
-
-    if (!response.ok) {
-      const error = await response.text();
-      console.error('[ShopRenter Payment] API error:', error);
-      throw new Error(`Payment plan creation failed: ${response.statusText}`);
-    }
-
-    const data = await response.json();
-    console.log('[ShopRenter Payment] Plan created:', data);
-
-    // 4. Store payment plan in database
-    await this.supabase
-      .from('shoprenter_payment_plans')
-      .insert({
-        store_id: params.storeId,
-        payment_plan_id: data.id,
-        plan_name: params.planName,
-        plan_type: params.planType,
-        amount: params.amount,
-        currency: params.currency || 'HUF',
-        billing_frequency: params.billingFrequency,
-        status: data.status || 'pending',
-        next_billing_date: data.next_billing_date,
-        raw_data: data,
-      });
-
-    return {
-      paymentPlanId: data.id,
-      status: data.status,
-      activatedAt: data.activated_at,
-      nextBillingDate: data.next_billing_date,
-      invoiceUrl: data.invoice_url,
-    };
-  }
-
-  /**
-   * Cancel a payment plan
-   */
-  async cancelPaymentPlan(storeId: string, paymentPlanId: string): Promise<void> {
-    // 1. Validate store platform
-    await this.validateShopRenterStore(storeId);
-
-    // 2. Get store details
-    const { data: store } = await this.supabase
-      .from('stores')
-      .select('store_name')
-      .eq('id', storeId)
-      .single();
-
-    const accessToken = await this.getAccessToken(storeId);
-
-    // 3. Call ShopRenter Payment API
-    const apiUrl = `https://${store.store_name}.api.shoprenter.hu/payment/plans/${paymentPlanId}/cancel`;
-
-    const response = await fetch(apiUrl, {
-      method: 'POST',
-      headers: {
-        'Authorization': `Bearer ${accessToken}`,
-        'Content-Type': 'application/json',
-        'X-ShopRenter-API-Key': this.apiKey,
-      },
-    });
-
-    if (!response.ok) {
-      const error = await response.text();
-      console.error('[ShopRenter Payment] Cancel error:', error);
-      throw new Error(`Payment plan cancellation failed: ${response.statusText}`);
-    }
-
-    // 4. Update database
-    await this.supabase
-      .from('shoprenter_payment_plans')
-      .update({
-        status: 'cancelled',
-        cancelled_at: new Date().toISOString(),
-        updated_at: new Date().toISOString(),
-      })
-      .eq('store_id', storeId)
-      .eq('payment_plan_id', paymentPlanId);
-
-    console.log(`[ShopRenter Payment] Plan cancelled: ${paymentPlanId}`);
-  }
-
-  /**
-   * Get payment plan status
-   */
-  async getPaymentPlanStatus(storeId: string, paymentPlanId: string): Promise<any> {
-    // 1. Validate store platform
-    await this.validateShopRenterStore(storeId);
-
-    // 2. Get store details
-    const { data: store } = await this.supabase
-      .from('stores')
-      .select('store_name')
-      .eq('id', storeId)
-      .single();
-
-    const accessToken = await this.getAccessToken(storeId);
-
-    // 3. Call ShopRenter Payment API
-    const apiUrl = `https://${store.store_name}.api.shoprenter.hu/payment/plans/${paymentPlanId}`;
-
-    const response = await fetch(apiUrl, {
-      method: 'GET',
-      headers: {
-        'Authorization': `Bearer ${accessToken}`,
-        'X-ShopRenter-API-Key': this.apiKey,
-      },
-    });
-
-    if (!response.ok) {
-      throw new Error(`Failed to fetch payment plan status: ${response.statusText}`);
-    }
-
-    return await response.json();
-  }
-}
-```
-
-### 2. Create Payment Plan Endpoint (`shoprenter-payment-create/index.ts`)
-
-```typescript
-import { serve } from 'https://deno.land/std@0.177.0/http/server.ts';
-import { createClient } from 'https://esm.sh/@supabase/supabase-js@2';
-import { ShopRenterPaymentClient } from '../_shared/shoprenter-payment-client.ts';
-
-serve(async (req) => {
-  // CORS headers
-  if (req.method === 'OPTIONS') {
-    return new Response(null, {
-      headers: {
-        'Access-Control-Allow-Origin': '*',
-        'Access-Control-Allow-Methods': 'POST, OPTIONS',
-        'Access-Control-Allow-Headers': 'authorization, content-type',
-      },
-    });
-  }
-
-  try {
-    // 1. Authenticate user
-    const authHeader = req.headers.get('Authorization');
-    if (!authHeader) {
-      return new Response(JSON.stringify({ error: 'Missing authorization header' }), {
-        status: 401,
-        headers: { 'Content-Type': 'application/json' },
-      });
-    }
-
-    const supabase = createClient(
-      Deno.env.get('SUPABASE_URL')!,
-      Deno.env.get('SUPABASE_ANON_KEY')!,
-      {
-        global: {
-          headers: { Authorization: authHeader },
-        },
-      }
-    );
-
-    const { data: { user }, error: authError } = await supabase.auth.getUser();
-    if (authError || !user) {
-      return new Response(JSON.stringify({ error: 'Unauthorized' }), {
-        status: 401,
-        headers: { 'Content-Type': 'application/json' },
-      });
-    }
-
-    // 2. Parse request body
-    const { store_id, plan_name, plan_type, amount, billing_frequency } = await req.json();
-
-    if (!store_id || !plan_name || !plan_type || !amount) {
-      return new Response(JSON.stringify({ error: 'Missing required fields' }), {
-        status: 400,
-        headers: { 'Content-Type': 'application/json' },
-      });
-    }
-
-    // 3. Verify store ownership
-    const { data: store } = await supabase
-      .from('stores')
-      .select('id, platform_name')
-      .eq('id', store_id)
-      .eq('user_id', user.id)
-      .single();
-
-    if (!store) {
-      return new Response(JSON.stringify({ error: 'Store not found or access denied' }), {
-        status: 403,
-        headers: { 'Content-Type': 'application/json' },
-      });
-    }
-
-    // 4. Validate ShopRenter platform (CRITICAL CHECK!)
-    if (store.platform_name !== 'shoprenter') {
-      return new Response(
-        JSON.stringify({
-          error: 'Invalid payment method',
-          message: 'ShopRenter Payment API can only be used with ShopRenter stores',
-          platform: store.platform_name,
-        }),
-        {
-          status: 400,
-          headers: { 'Content-Type': 'application/json' },
-        }
-      );
-    }
-
-    // 5. Create payment plan
-    const paymentClient = new ShopRenterPaymentClient();
-    const result = await paymentClient.createPaymentPlan({
-      storeId: store_id,
-      planName: plan_name,
-      planType: plan_type,
-      amount: amount,
-      billingFrequency: billing_frequency,
-    });
-
-    return new Response(
-      JSON.stringify({
-        success: true,
-        payment_plan_id: result.paymentPlanId,
-        status: result.status,
-        next_billing_date: result.nextBillingDate,
-        invoice_url: result.invoiceUrl,
-      }),
-      {
-        status: 200,
-        headers: { 'Content-Type': 'application/json' },
-      }
-    );
-  } catch (error) {
-    console.error('[ShopRenter Payment] Error:', error);
-    return new Response(
-      JSON.stringify({
-        error: 'Payment plan creation failed',
-        message: error.message,
-      }),
-      {
-        status: 500,
-        headers: { 'Content-Type': 'application/json' },
-      }
-    );
-  }
-});
-```
-
-### 3. Payment Webhook Handler (`shoprenter-payment-webhook/index.ts`)
-
-```typescript
-import { serve } from 'https://deno.land/std@0.177.0/http/server.ts';
-import { createClient } from 'https://esm.sh/@supabase/supabase-js@2';
-import { createHmac } from 'https://deno.land/std@0.177.0/node/crypto.ts';
-
-serve(async (req) => {
-  if (req.method !== 'POST') {
-    return new Response('Method not allowed', { status: 405 });
-  }
-
-  try {
-    // 1. Validate webhook signature (HMAC)
-    const body = await req.text();
-    const signature = req.headers.get('X-ShopRenter-Signature');
-    const secret = Deno.env.get('SHOPRENTER_PAYMENT_SECRET')!;
-
-    const expectedSignature = createHmac('sha256', secret)
-      .update(body)
-      .digest('hex');
-
-    if (signature !== expectedSignature) {
-      console.error('[ShopRenter Payment Webhook] Invalid signature');
-      return new Response('Invalid signature', { status: 403 });
-    }
-
-    // 2. Parse webhook payload
-    const payload = JSON.parse(body);
-    const { event, data } = payload;
-
-    console.log(`[ShopRenter Payment Webhook] Received: ${event}`, data);
-
-    const supabase = createClient(
-      Deno.env.get('SUPABASE_URL')!,
-      Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
-    );
-
-    // 3. Process webhook event
-    switch (event) {
-      case 'payment.success':
-        await handlePaymentSuccess(supabase, data);
-        break;
-
-      case 'payment.failed':
-        await handlePaymentFailed(supabase, data);
-        break;
-
-      case 'subscription.activated':
-        await handleSubscriptionActivated(supabase, data);
-        break;
-
-      case 'subscription.cancelled':
-        await handleSubscriptionCancelled(supabase, data);
-        break;
-
-      case 'subscription.expired':
-        await handleSubscriptionExpired(supabase, data);
-        break;
-
-      default:
-        console.log(`[ShopRenter Payment Webhook] Unhandled event: ${event}`);
-    }
-
-    return new Response(JSON.stringify({ success: true }), {
-      status: 200,
-      headers: { 'Content-Type': 'application/json' },
-    });
-  } catch (error) {
-    console.error('[ShopRenter Payment Webhook] Error:', error);
-    return new Response(JSON.stringify({ error: error.message }), {
-      status: 500,
-      headers: { 'Content-Type': 'application/json' },
-    });
-  }
-});
-
-async function handlePaymentSuccess(supabase: any, data: any) {
-  console.log('[ShopRenter Payment] Payment successful:', data);
-
-  // 1. Record transaction
-  await supabase.from('shoprenter_payment_transactions').insert({
-    store_id: data.store_id,
-    payment_plan_id: data.payment_plan_id,
-    transaction_id: data.transaction_id,
-    charge_id: data.charge_id,
-    transaction_type: 'charge',
-    amount: data.amount,
-    currency: data.currency || 'HUF',
-    status: 'success',
-    payment_method: data.payment_method,
-    card_last4: data.card_last4,
-    card_brand: data.card_brand,
-    invoice_number: data.invoice_number,
-    invoice_url: data.invoice_url,
-    processed_at: new Date().toISOString(),
-    raw_data: data,
-  });
-
-  // 2. Update payment plan status
-  await supabase
-    .from('shoprenter_payment_plans')
-    .update({
-      status: 'active',
-      next_billing_date: data.next_billing_date,
-      updated_at: new Date().toISOString(),
-    })
-    .eq('payment_plan_id', data.payment_plan_id);
-
-  // 3. Update store subscription status
-  await supabase
-    .from('stores')
-    .update({
-      subscription_status: 'active',
-      subscription_started_at: new Date().toISOString(),
-      updated_at: new Date().toISOString(),
-    })
-    .eq('id', data.store_id);
-}
-
-async function handlePaymentFailed(supabase: any, data: any) {
-  console.log('[ShopRenter Payment] Payment failed:', data);
-
-  // 1. Record failed transaction
-  await supabase.from('shoprenter_payment_transactions').insert({
-    store_id: data.store_id,
-    payment_plan_id: data.payment_plan_id,
-    transaction_id: data.transaction_id,
-    transaction_type: 'charge',
-    amount: data.amount,
-    currency: data.currency || 'HUF',
-    status: 'failed',
-    error_code: data.error_code,
-    error_message: data.error_message,
-    processed_at: new Date().toISOString(),
-    raw_data: data,
-  });
-
-  // 2. Update payment plan status
-  await supabase
-    .from('shoprenter_payment_plans')
-    .update({
-      status: 'failed',
-      updated_at: new Date().toISOString(),
-    })
-    .eq('payment_plan_id', data.payment_plan_id);
-
-  // 3. Update store subscription status
-  await supabase
-    .from('stores')
-    .update({
-      subscription_status: 'payment_failed',
-      updated_at: new Date().toISOString(),
-    })
-    .eq('id', data.store_id);
-}
-
-async function handleSubscriptionActivated(supabase: any, data: any) {
-  console.log('[ShopRenter Payment] Subscription activated:', data);
-
-  await supabase
-    .from('shoprenter_payment_plans')
-    .update({
-      status: 'active',
-      activated_at: new Date().toISOString(),
-      next_billing_date: data.next_billing_date,
-      updated_at: new Date().toISOString(),
-    })
-    .eq('payment_plan_id', data.payment_plan_id);
-
-  await supabase
-    .from('stores')
-    .update({
-      subscription_status: 'active',
-      subscription_started_at: new Date().toISOString(),
-      updated_at: new Date().toISOString(),
-    })
-    .eq('id', data.store_id);
-}
-
-async function handleSubscriptionCancelled(supabase: any, data: any) {
-  console.log('[ShopRenter Payment] Subscription cancelled:', data);
-
-  await supabase
-    .from('shoprenter_payment_plans')
-    .update({
-      status: 'cancelled',
-      cancelled_at: new Date().toISOString(),
-      updated_at: new Date().toISOString(),
-    })
-    .eq('payment_plan_id', data.payment_plan_id);
-
-  await supabase
-    .from('stores')
-    .update({
-      subscription_status: 'cancelled',
-      updated_at: new Date().toISOString(),
-    })
-    .eq('id', data.store_id);
-}
-
-async function handleSubscriptionExpired(supabase: any, data: any) {
-  console.log('[ShopRenter Payment] Subscription expired:', data);
-
-  await supabase
-    .from('shoprenter_payment_plans')
-    .update({
-      status: 'expired',
-      expires_at: new Date().toISOString(),
-      updated_at: new Date().toISOString(),
-    })
-    .eq('payment_plan_id', data.payment_plan_id);
-
-  await supabase
-    .from('stores')
-    .update({
-      subscription_status: 'expired',
-      subscription_ends_at: new Date().toISOString(),
-      updated_at: new Date().toISOString(),
-    })
-    .eq('id', data.store_id);
-}
-```
-
----
-
-## 💳 Payment Flow
-
-### User Journey
-
-```
-1. Merchant connects ShopRenter store (OAuth) → Already implemented
-   ↓
-2. Merchant navigates to "Billing" page in ShopCall.ai
-   ↓
-3. Merchant selects subscription plan (Basic, Pro, Enterprise)
-   ↓
-4. Frontend checks store platform: if (platform_name !== 'shoprenter') → show Stripe payment
-   ↓
-5. If ShopRenter store → Show "Pay via ShopRenter" button
-   ↓
-6. Merchant clicks "Subscribe"
-   ↓
-7. Frontend calls: POST /functions/v1/shoprenter-payment-create
-   ↓
-8. Backend validates store platform (MANDATORY CHECK!)
-   ↓
-9. Backend creates payment plan via ShopRenter Payment API
-   ↓
-10. ShopRenter redirects merchant to payment page (card details)
-    ↓
-11. Merchant enters card details or confirms existing card
-    ↓
-12. ShopRenter processes first payment
-    ↓
-13. ShopRenter sends webhook: payment.success
-    ↓
-14. Backend updates subscription status → "active"
-    ↓
-15. Merchant redirected back to ShopCall.ai → Subscription active!
-```
-
-### Recurring Billing
-
-After initial payment:
-
-1. ShopRenter automatically charges the merchant's card on schedule (monthly/yearly)
-2. ShopRenter sends webhook: `payment.success` or `payment.failed`
-3. ShopCall.ai updates subscription status accordingly
-4. If payment fails:
-   - Send email notification to merchant
-   - Mark subscription as "payment_failed"
-   - Allow grace period (e.g., 3 days) before suspension
-   - ShopRenter retries payment automatically
-
----
-
-## 🔒 Security Considerations
-
-### 1. Store Platform Validation (CRITICAL!)
-
-**Enforcement Strategy:**
-
-```typescript
-// Middleware for all payment endpoints
-async function validateShopRenterPayment(storeId: string, userId: string) {
-  const supabase = createClient(
-    Deno.env.get('SUPABASE_URL')!,
-    Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
-  );
-
-  // 1. Verify store exists and belongs to user
-  const { data: store, error } = await supabase
-    .from('stores')
-    .select('id, platform_name, is_active, user_id')
-    .eq('id', storeId)
-    .single();
-
-  if (error || !store) {
-    throw new Error('Store not found');
-  }
-
-  if (store.user_id !== userId) {
-    throw new Error('Access denied: You do not own this store');
-  }
-
-  if (!store.is_active) {
-    throw new Error('Store is inactive');
-  }
-
-  // 2. CRITICAL: Validate ShopRenter platform
-  if (store.platform_name !== 'shoprenter') {
-    throw new Error(
-      `Invalid payment method for platform: ${store.platform_name}. ` +
-      'ShopRenter Payment API can only be used with ShopRenter stores.'
-    );
-  }
-
-  return store;
-}
-```
-
-**Apply to ALL payment endpoints:**
-- ✅ `shoprenter-payment-create`
-- ✅ `shoprenter-payment-cancel`
-- ✅ `shoprenter-payment-update`
-- ✅ `shoprenter-payment-status`
-- ✅ `shoprenter-payment-webhook` (validate via payment_plan_id lookup)
-
-### 2. Webhook Signature Validation
-
-```typescript
-function validateWebhookSignature(body: string, signature: string): boolean {
-  const secret = Deno.env.get('SHOPRENTER_PAYMENT_SECRET')!;
-
-  const expectedSignature = createHmac('sha256', secret)
-    .update(body)
-    .digest('hex');
-
-  // Timing-safe comparison
-  try {
-    return timingSafeEqual(
-      new TextEncoder().encode(expectedSignature),
-      new TextEncoder().encode(signature)
-    );
-  } catch {
-    return false;
-  }
-}
-```
-
-### 3. Environment Variables
-
-```bash
-# Required for ShopRenter Payment API
-SHOPRENTER_PAYMENT_API_KEY=your_payment_api_key
-SHOPRENTER_PAYMENT_SECRET=your_webhook_secret
-
-# Existing ShopRenter OAuth (already configured)
-SHOPRENTER_CLIENT_ID=your_client_id
-SHOPRENTER_CLIENT_SECRET=your_client_secret
-
-# Supabase (already configured)
-SUPABASE_URL=https://ztklqodcdjeqpsvhlpud.supabase.co
-SUPABASE_ANON_KEY=your_anon_key
-SUPABASE_SERVICE_ROLE_KEY=your_service_role_key
-
-# Frontend URL (already configured)
-FRONTEND_URL=https://shopcall.ai
-```
-
-### 4. Data Privacy & GDPR
-
-- ✅ Store minimal payment data (no full card numbers)
-- ✅ Log transactions for audit trail
-- ✅ Delete payment data on store deletion (CASCADE)
-- ✅ Provide data export for merchants
-- ✅ Handle refund requests properly
-
----
-
-## 🧪 Testing Strategy
-
-### 1. Test Store Setup
-
-Use existing ShopRenter test store:
-- Store name: `shopcall-test-store`
-- URL: `shopcall-test-store.myshoprenter.hu`
-- Already connected via OAuth
-
-### 2. Test Cases
-
-#### Store Validation Tests
-
-```typescript
-describe('Store Platform Validation', () => {
-  it('should accept ShopRenter stores', async () => {
-    // Given: ShopRenter store
-    const store = { platform_name: 'shoprenter', is_active: true };
-
-    // When: Creating payment plan
-    const result = await createPaymentPlan({ storeId: store.id });
-
-    // Then: Should succeed
-    expect(result.success).toBe(true);
-  });
-
-  it('should reject non-ShopRenter stores', async () => {
-    // Given: Shopify store
-    const store = { platform_name: 'shopify', is_active: true };
-
-    // When: Creating payment plan
-    const result = await createPaymentPlan({ storeId: store.id });
-
-    // Then: Should fail with specific error
-    expect(result.error).toContain('ShopRenter Payment API can only be used with ShopRenter stores');
-  });
-
-  it('should reject WooCommerce stores', async () => {
-    // Given: WooCommerce store
-    const store = { platform_name: 'woocommerce', is_active: true };
-
-    // When: Creating payment plan
-    const result = await createPaymentPlan({ storeId: store.id });
-
-    // Then: Should fail
-    expect(result.error).toContain('ShopRenter Payment API');
-  });
-
-  it('should reject inactive stores', async () => {
-    // Given: Inactive ShopRenter store
-    const store = { platform_name: 'shoprenter', is_active: false };
-
-    // When: Creating payment plan
-    const result = await createPaymentPlan({ storeId: store.id });
-
-    // Then: Should fail
-    expect(result.error).toContain('inactive');
-  });
-});
-```
-
-#### Payment Flow Tests
-
-```typescript
-describe('Payment Plan Creation', () => {
-  it('should create one-time payment plan', async () => {
-    const params = {
-      storeId: 'test-store-id',
-      planName: 'Basic Plan',
-      planType: 'one_time',
-      amount: 9990,
-      currency: 'HUF',
-    };
-
-    const result = await paymentClient.createPaymentPlan(params);
-
-    expect(result.paymentPlanId).toBeDefined();
-    expect(result.status).toBe('pending');
-  });
-
-  it('should create recurring payment plan', async () => {
-    const params = {
-      storeId: 'test-store-id',
-      planName: 'Pro Plan',
-      planType: 'recurring',
-      amount: 29990,
-      currency: 'HUF',
-      billingFrequency: 'monthly',
-    };
-
-    const result = await paymentClient.createPaymentPlan(params);
-
-    expect(result.paymentPlanId).toBeDefined();
-    expect(result.nextBillingDate).toBeDefined();
-  });
-});
-```
-
-#### Webhook Tests
-
-```typescript
-describe('Payment Webhooks', () => {
-  it('should handle payment.success webhook', async () => {
-    const payload = {
-      event: 'payment.success',
-      data: {
-        store_id: 'test-store-id',
-        payment_plan_id: 'plan-123',
-        transaction_id: 'txn-456',
-        amount: 9990,
-        currency: 'HUF',
-        invoice_number: 'INV-2025-001',
-      },
-    };
-
-    const response = await handleWebhook(payload);
-
-    expect(response.status).toBe(200);
-
-    // Verify database updates
-    const plan = await getPlanFromDB('plan-123');
-    expect(plan.status).toBe('active');
-
-    const store = await getStoreFromDB('test-store-id');
-    expect(store.subscription_status).toBe('active');
-  });
-
-  it('should handle payment.failed webhook', async () => {
-    const payload = {
-      event: 'payment.failed',
-      data: {
-        store_id: 'test-store-id',
-        payment_plan_id: 'plan-123',
-        error_code: 'insufficient_funds',
-        error_message: 'Insufficient funds',
-      },
-    };
-
-    const response = await handleWebhook(payload);
-
-    expect(response.status).toBe(200);
-
-    const plan = await getPlanFromDB('plan-123');
-    expect(plan.status).toBe('failed');
-
-    const store = await getStoreFromDB('test-store-id');
-    expect(store.subscription_status).toBe('payment_failed');
-  });
-
-  it('should reject webhook with invalid signature', async () => {
-    const payload = { event: 'payment.success', data: {} };
-    const invalidSignature = 'invalid_hmac';
-
-    const response = await handleWebhook(payload, invalidSignature);
-
-    expect(response.status).toBe(403);
-  });
-});
-```
-
-### 3. Manual Testing Checklist
-
-- [ ] Connect test ShopRenter store via OAuth
-- [ ] Navigate to billing page
-- [ ] Select subscription plan
-- [ ] Verify "Pay via ShopRenter" option appears
-- [ ] Click subscribe button
-- [ ] Verify redirect to ShopRenter payment page
-- [ ] Complete test payment with test card
-- [ ] Verify redirect back to ShopCall.ai
-- [ ] Verify subscription status is "active"
-- [ ] Verify payment transaction recorded in database
-- [ ] Test cancellation flow
-- [ ] Test payment failure handling
-- [ ] Verify webhook events processed correctly
-- [ ] Test with non-ShopRenter store (should reject)
-
----
-
-## 🚀 Deployment Plan
-
-### Phase 1: Preparation (Week 1)
-
-- [x] Review ShopRenter Payment API documentation
-- [ ] Create implementation plan (this document)
-- [ ] Design database schema
-- [ ] Set up test environment
-- [ ] Request Payment API credentials from ShopRenter
-
-### Phase 2: Development (Weeks 2-3)
-
-- [ ] Create database migration
-- [ ] Implement Payment API client library
-- [ ] Implement Edge Functions:
-  - [ ] `shoprenter-payment-create`
-  - [ ] `shoprenter-payment-cancel`
-  - [ ] `shoprenter-payment-status`
-  - [ ] `shoprenter-payment-webhook`
-- [ ] Implement store validation middleware
-- [ ] Add error handling and logging
-
-### Phase 3: Frontend Integration (Week 4)
-
-- [ ] Create billing page UI
-- [ ] Add subscription plan selection
-- [ ] Implement platform-specific payment method selection
-- [ ] Add ShopRenter payment button
-- [ ] Implement success/failure callbacks
-- [ ] Add subscription management UI
-
-### Phase 4: Testing (Week 5)
-
-- [ ] Unit tests for validation logic
-- [ ] Integration tests for payment flow
-- [ ] Webhook handler tests
-- [ ] Manual end-to-end testing
-- [ ] Security audit
-- [ ] Performance testing
-
-### Phase 5: Production Deployment (Week 6)
-
-- [ ] Deploy database migration
-- [ ] Deploy Edge Functions
-- [ ] Configure environment variables
-- [ ] Enable payment webhooks
-- [ ] Monitor logs for errors
-- [ ] Soft launch with beta users
-
-### Phase 6: Launch (Week 7)
-
-- [ ] Full production launch
-- [ ] Monitor payment success rates
-- [ ] Customer support readiness
-- [ ] Documentation updates
-- [ ] Marketing announcement
-
----
-
-## 📅 Timeline & Milestones
-
-| Week | Milestone | Deliverables |
-|------|-----------|--------------|
-| 1 | Planning Complete | ✅ Implementation plan document |
-| 2 | Database & Backend Foundation | Schema migration, Payment client library |
-| 3 | Core Payment Features | Create/cancel/status Edge Functions |
-| 4 | Frontend Integration | Billing UI, Payment buttons, Callbacks |
-| 5 | Testing & QA | Test suite, Manual testing, Security audit |
-| 6 | Deployment | Production deployment, Monitoring setup |
-| 7 | Launch | Public launch, User documentation |
-
-**Total Duration:** 7 weeks
-
----
-
-## 📚 References & Resources
-
-### ShopRenter Documentation
-
-- **Payment API Introduction**: `https://doc.shoprenter.hu/paymentapi/docs/a_introduce.html`
-- **Payment API Docs**: `https://doc.shoprenter.hu/paymentapi/`
-- **App Development Guide**: `https://doc.shoprenter.hu/development/app-development/`
-- **OAuth Documentation**: `docs/shoprenter_app_development.md`
-
-### Internal Documentation
-
-- **ShopRenter Integration Plan**: `SHOPRENTER.md`
-- **Registration Requirements**: `SHOPRENTER_REGISTRATION.md`
-- **API Resources**: `docs/shoprenter_api_resources.md`
-- **Payment Overview**: `docs/shoprenter_payment.md`
-
-### Project Documentation
-
-- **Project Overview**: `CLAUDE.md`
-- **Database Schema**: See Supabase migrations in `supabase/migrations/`
-- **Edge Functions**: `supabase/functions/`
-
-### Contact & Support
-
-- **ShopRenter Partner Support**: `partnersupport@shoprenter.hu`
-- **ShopRenter Developer Portal**: `https://doc.shoprenter.hu`
-
----
-
-## ✅ Next Steps
-
-1. **Review this plan** with the team
-2. **Request Payment API credentials** from ShopRenter Partner Support
-3. **Create database migration** for new tables
-4. **Set up test environment** with test ShopRenter store
-5. **Begin Phase 2 development** (Backend implementation)
-
----
-
-## 🔄 Change Log
-
-| Date | Version | Changes |
-|------|---------|---------|
-| 2025-11-11 | 1.0 | Initial implementation plan created |
-
----
-
-**Document Status:** ✅ Ready for Review
-**Author:** Claude (AI Development Assistant)
-**Approved By:** _Pending_
-**Next Review Date:** _TBD_

+ 0 - 73
shopcall.ai-main/README.md

@@ -1,73 +0,0 @@
-# Welcome to your Lovable project
-
-## Project info
-
-**URL**: https://lovable.dev/projects/5ef3e58d-e62b-450c-8e1a-8c085b5e6367
-
-## How can I edit this code?
-
-There are several ways of editing your application.
-
-**Use Lovable**
-
-Simply visit the [Lovable Project](https://lovable.dev/projects/5ef3e58d-e62b-450c-8e1a-8c085b5e6367) and start prompting.
-
-Changes made via Lovable will be committed automatically to this repo.
-
-**Use your preferred IDE**
-
-If you want to work locally using your own IDE, you can clone this repo and push changes. Pushed changes will also be reflected in Lovable.
-
-The only requirement is having Node.js & npm installed - [install with nvm](https://github.com/nvm-sh/nvm#installing-and-updating)
-
-Follow these steps:
-
-```sh
-# Step 1: Clone the repository using the project's Git URL.
-git clone <YOUR_GIT_URL>
-
-# Step 2: Navigate to the project directory.
-cd <YOUR_PROJECT_NAME>
-
-# Step 3: Install the necessary dependencies.
-npm i
-
-# Step 4: Start the development server with auto-reloading and an instant preview.
-npm run dev
-```
-
-**Edit a file directly in GitHub**
-
-- Navigate to the desired file(s).
-- Click the "Edit" button (pencil icon) at the top right of the file view.
-- Make your changes and commit the changes.
-
-**Use GitHub Codespaces**
-
-- Navigate to the main page of your repository.
-- Click on the "Code" button (green button) near the top right.
-- Select the "Codespaces" tab.
-- Click on "New codespace" to launch a new Codespace environment.
-- Edit files directly within the Codespace and commit and push your changes once you're done.
-
-## What technologies are used for this project?
-
-This project is built with:
-
-- Vite
-- TypeScript
-- React
-- shadcn-ui
-- Tailwind CSS
-
-## How can I deploy this project?
-
-Simply open [Lovable](https://lovable.dev/projects/5ef3e58d-e62b-450c-8e1a-8c085b5e6367) and click on Share -> Publish.
-
-## Can I connect a custom domain to my Lovable project?
-
-Yes, you can!
-
-To connect a domain, navigate to Project > Settings > Domains and click Connect Domain.
-
-Read more here: [Setting up a custom domain](https://docs.lovable.dev/tips-tricks/custom-domain#step-by-step-guide)

+ 36 - 2
shopcall.ai-main/src/i18n/locales/de.json

@@ -719,8 +719,42 @@
         "invalid_store_url": "Ungültige Shop-URL. Bitte überprüfen Sie die URL und versuchen Sie es erneut.",
         "failed_to_save": "Shop-Verbindung konnte nicht gespeichert werden. Bitte versuchen Sie es erneut.",
         "internal_error": "Ein interner Fehler ist aufgetreten. Bitte versuchen Sie es später erneut.",
-        "default": "Ein unerwarteter Fehler ist aufgetreten. Bitte versuchen Sie es erneut."
-      }
+        "default": "Ein unerwarteter Fehler ist aufgetreten. Bitte versuchen Sie es erneut.",
+        "token_exchange_failed": "Token-Austausch mit ShopRenter fehlgeschlagen. Bitte versuchen Sie es erneut.",
+        "hmac_validation_failed": "Sicherheitsüberprüfung fehlgeschlagen. Bitte versuchen Sie es erneut.",
+        "validation_error": "Sicherheitsparameter konnten nicht validiert werden. Bitte versuchen Sie es erneut."
+      },
+      "connectShop": "Ihren Shop verbinden",
+      "authRequired": "Melden Sie sich an oder erstellen Sie ein Konto zum Verbinden",
+      "signIn": "Bei Ihrem Konto anmelden",
+      "createAccount": "Neues Konto erstellen",
+      "readyToConnect": "Bereit zum Verbinden",
+      "assignShop": "Verbinden Sie",
+      "toAccount": " mit Ihrem Konto?",
+      "selectCountry": "Land",
+      "loadingCountries": "Länder werden geladen...",
+      "selectCountryPlaceholder": "Land auswählen",
+      "noCountriesError": "Keine Länder mit verfügbaren Telefonnummern.",
+      "selectCity": "Stadt",
+      "loadingCities": "Städte werden geladen...",
+      "selectCityPlaceholder": "Stadt auswählen",
+      "noCitiesError": "Keine Städte mit verfügbaren Telefonnummern in diesem Land.",
+      "selectPhoneNumber": "Telefonnummer",
+      "loadingPhoneNumbers": "Verfügbare Telefonnummern werden geladen...",
+      "selectPhonePlaceholder": "Telefonnummer auswählen",
+      "phoneNumberRequired": "Bitte wählen Sie eine Telefonnummer zum Fortfahren.",
+      "noPhoneNumbersError": "Keine Telefonnummern in dieser Stadt verfügbar.",
+      "selectionRequired": "Bitte wählen Sie ein Land, eine Stadt und eine Telefonnummer zum Fortfahren.",
+      "connecting": "Verbindung wird hergestellt...",
+      "connectToMyAccount": "Mit meinem Konto verbinden",
+      "createNewAccount": "Stattdessen neues Konto erstellen",
+      "connectingShop": "Shop wird verbunden",
+      "validating": "Sicherheitsparameter werden überprüft...",
+      "checkingAuth": "Authentifizierung wird überprüft...",
+      "processing": "Integration wird verarbeitet...",
+      "backToIntegrations": "Zurück zu Integrationen",
+      "shopConnected": "Shop Verbunden",
+      "shopConnectedDescription": "{{shopName}} erfolgreich verbunden"
     },
     "shoprenter": {
       "seo": {

+ 36 - 2
shopcall.ai-main/src/i18n/locales/en.json

@@ -809,8 +809,42 @@
         "invalid_store_url": "Invalid store URL. Please check the URL and try again.",
         "failed_to_save": "Failed to save store connection. Please try again.",
         "internal_error": "An internal error occurred. Please try again later.",
-        "default": "An unexpected error occurred. Please try again."
-      }
+        "default": "An unexpected error occurred. Please try again.",
+        "token_exchange_failed": "Failed to exchange token with ShopRenter. Please try again.",
+        "hmac_validation_failed": "Security validation failed. Please try again.",
+        "validation_error": "Failed to validate security parameters. Please try again."
+      },
+      "connectShop": "Connect Your Shop",
+      "authRequired": "Sign in or create an account to connect",
+      "signIn": "Sign in to your account",
+      "createAccount": "Create a new account",
+      "readyToConnect": "Ready to Connect",
+      "assignShop": "Connect",
+      "toAccount": " to your account?",
+      "selectCountry": "Country",
+      "loadingCountries": "Loading countries...",
+      "selectCountryPlaceholder": "Select a country",
+      "noCountriesError": "No countries with available phone numbers.",
+      "selectCity": "City",
+      "loadingCities": "Loading cities...",
+      "selectCityPlaceholder": "Select a city",
+      "noCitiesError": "No cities with available phone numbers in this country.",
+      "selectPhoneNumber": "Phone Number",
+      "loadingPhoneNumbers": "Loading available phone numbers...",
+      "selectPhonePlaceholder": "Select a phone number",
+      "phoneNumberRequired": "Please select a phone number to continue.",
+      "noPhoneNumbersError": "No phone numbers available in this city.",
+      "selectionRequired": "Please select a country, city, and phone number to continue.",
+      "connecting": "Connecting...",
+      "connectToMyAccount": "Connect to my account",
+      "createNewAccount": "Create a new account instead",
+      "connectingShop": "Connecting Shop",
+      "validating": "Validating security parameters...",
+      "checkingAuth": "Checking authentication...",
+      "processing": "Processing integration...",
+      "backToIntegrations": "Back to Integrations",
+      "shopConnected": "Shop Connected",
+      "shopConnectedDescription": "Successfully connected {{shopName}}"
     },
     "shoprenter": {
       "seo": {

+ 36 - 2
shopcall.ai-main/src/i18n/locales/hu.json

@@ -799,8 +799,42 @@
         "invalid_store_url": "Érvénytelen áruház URL. Ellenőrizze az URL-t és próbálja újra.",
         "failed_to_save": "Áruház csatlakozás mentése sikertelen. Kérjük, próbálja újra.",
         "internal_error": "Belső hiba történt. Kérjük, próbálja újra később.",
-        "default": "Váratlan hiba történt. Kérjük, próbálja újra."
-      }
+        "default": "Váratlan hiba történt. Kérjük, próbálja újra.",
+        "token_exchange_failed": "Token csere sikertelen a ShopRenterrel. Kérjük, próbálja újra.",
+        "hmac_validation_failed": "Biztonsági ellenőrzés sikertelen. Kérjük, próbálja újra.",
+        "validation_error": "Biztonsági paraméterek ellenőrzése sikertelen. Kérjük, próbálja újra."
+      },
+      "connectShop": "Áruház Csatlakoztatása",
+      "authRequired": "Jelentkezzen be vagy hozzon létre fiókot a csatlakozáshoz",
+      "signIn": "Jelentkezzen be fiókjába",
+      "createAccount": "Új fiók létrehozása",
+      "readyToConnect": "Készen áll a Csatlakozásra",
+      "assignShop": "Csatlakoztassa",
+      "toAccount": " fiókjához?",
+      "selectCountry": "Ország",
+      "loadingCountries": "Országok betöltése...",
+      "selectCountryPlaceholder": "Válasszon országot",
+      "noCountriesError": "Nincs elérhető telefonszámmal rendelkező ország.",
+      "selectCity": "Város",
+      "loadingCities": "Városok betöltése...",
+      "selectCityPlaceholder": "Válasszon várost",
+      "noCitiesError": "Nincs elérhető telefonszámmal rendelkező város ebben az országban.",
+      "selectPhoneNumber": "Telefonszám",
+      "loadingPhoneNumbers": "Elérhető telefonszámok betöltése...",
+      "selectPhonePlaceholder": "Válasszon telefonszámot",
+      "phoneNumberRequired": "Kérjük, válasszon telefonszámot a folytatáshoz.",
+      "noPhoneNumbersError": "Nincs elérhető telefonszám ebben a városban.",
+      "selectionRequired": "Kérjük, válasszon országot, várost és telefonszámot a folytatáshoz.",
+      "connecting": "Csatlakozás...",
+      "connectToMyAccount": "Csatlakoztatás a fiókomhoz",
+      "createNewAccount": "Inkább új fiók létrehozása",
+      "connectingShop": "Áruház Csatlakoztatása",
+      "validating": "Biztonsági paraméterek ellenőrzése...",
+      "checkingAuth": "Hitelesítés ellenőrzése...",
+      "processing": "Integráció feldolgozása...",
+      "backToIntegrations": "Vissza az Integrációkhoz",
+      "shopConnected": "Áruház Csatlakoztatva",
+      "shopConnectedDescription": "{{shopName}} sikeresen csatlakoztatva"
     },
     "shoprenter": {
       "seo": {

+ 12 - 0
supabase/config.toml

@@ -33,3 +33,15 @@ verify_jwt = false
 
 [functions.shop-data-api]
 verify_jwt = false
+
+[functions.validate-shoprenter-hmac]
+verify_jwt = false
+
+[functions.oauth-shoprenter-callback]
+verify_jwt = false
+
+[functions.oauth-shoprenter-init]
+verify_jwt = false
+
+[functions.webhook-shoprenter-uninstall]
+verify_jwt = false

+ 36 - 0
supabase/functions/complete-shoprenter-install/index.ts

@@ -6,6 +6,37 @@ import { createScraperClient } from '../_shared/scraper-client.ts'
 import { getCorsHeaders, handleCorsPreflightRequest } from '../_shared/cors.ts';
 
 
+// Trigger initial data sync for the store
+async function triggerInitialSync(
+  storeId: string,
+  supabaseUrl: string,
+  supabaseServiceKey: string
+): Promise<void> {
+  try {
+    console.log(`[ShopRenter] Triggering initial sync for store ${storeId}`)
+
+    const response = await fetch(`${supabaseUrl}/functions/v1/trigger-sync`, {
+      method: 'POST',
+      headers: {
+        'Authorization': `Bearer ${supabaseServiceKey}`,
+        'Content-Type': 'application/json'
+      },
+      body: JSON.stringify({ store_id: storeId })
+    })
+
+    if (response.ok) {
+      const result = await response.json()
+      console.log(`[ShopRenter] Initial sync triggered successfully for store ${storeId}:`, result)
+    } else {
+      const error = await response.json()
+      console.error(`[ShopRenter] Failed to trigger initial sync for store ${storeId}:`, error)
+    }
+  } catch (error) {
+    console.error(`[ShopRenter] Error triggering initial sync for store ${storeId}:`, error)
+    // Don't throw error - initial sync failure should not fail the OAuth flow
+  }
+}
+
 // Register store with scraper service
 async function registerStoreWithScraper(
   storeId: string,
@@ -280,6 +311,11 @@ serve(wrapHandler('complete-shoprenter-install', async (req) => {
       .then(() => console.log(`[ShopRenter] Scraper registration completed for store ${newStore.id}`))
       .catch(err => console.error(`[ShopRenter] Scraper registration failed:`, err))
 
+    // Trigger initial data sync in background (respects data access policies - by default only products will sync)
+    triggerInitialSync(newStore.id, supabaseUrl, supabaseServiceKey)
+      .then(() => console.log(`[ShopRenter] Initial sync completed for store ${newStore.id}`))
+      .catch(err => console.error(`[ShopRenter] Initial sync failed:`, err))
+
     return new Response(
       JSON.stringify({
         success: true,