# Kytchen Workspace Architecture

## BYOLLM (Bring Your Own LLM)

Kytchen is **not** an inference service.

- Your MCP client (Claude Desktop, Cursor, Codex, Windsurf, Gemini, etc.) runs the LLM with **your** subscription / API keys.
- Kytchen Cloud provides **dataset hosting + sandbox/tool execution + evidence/metrics**.
- Kytchen API keys (`kyt_sk_...`) authenticate access to your **workspace + datasets**, not to an LLM provider.

## Product Goal: Simpler Than “DIY Supabase”

Kytchen should feel like “turnkey infrastructure”:

- No schema/migrations/config for users: just create a workspace + upload files.
- Copy/paste MCP config in 10 seconds (or one-click “Install to Cursor/Claude/Codex”).
- Default-safe limits (rate limits, retention) with clear upgrade paths.

## Naming Options

| Name | Vibe | Examples |
|------|------|----------|
| **Workspace** | Standard SaaS | "Create a workspace for your team" |
| **Vault** | Secure, premium | "Your data lives in your Kytchen Vault" |
| **Context** | Technical, fits product | "Connect to your Kytchen Context" |
| **Space** | Modern, collaborative | "Invite teammates to your Space" |
| **Library** | Academic, organized | "Query your document library" |

**Recommendation**: **Workspace** (familiar) or **Vault** (differentiated + security connotation)

---

## User Flow

```
1. SIGN UP
   └─► kytchen.dev/signup
       └─► Create account (Supabase Auth)

2. CREATE WORKSPACE
   └─► kytchen.dev/workspaces/new
       └─► Name: "Acme Corp Research"
       └─► Creates workspace record in DB
       └─► User becomes "owner"

3. UPLOAD DATASETS
   └─► kytchen.dev/workspaces/acme-corp/datasets
       └─► Drag & drop files (txt, json, csv, pdf)
       └─► Files uploaded to Supabase Storage
       └─► Metadata stored in Postgres
       └─► Content hash computed for dedup

4. GENERATE API KEY
   └─► kytchen.dev/workspaces/acme-corp/settings/api-keys
       └─► Create key: "Cursor Dev"
       └─► Returns: kyt_sk_abc123... (show once)
       └─► Hash stored in DB, prefix for display

5. CONFIGURE MCP CLIENT
   └─► User adds to their Claude/Cursor/Codex config:
       {
         "mcpServers": {
           "kytchen": {
             "command": "kytchen",
             "env": { "KYTCHEN_API_KEY": "kyt_sk_abc123..." }
           }
         }
       }

6. QUERY VIA MCP
   └─► User in Claude: "Use kytchen to find sales trends in Q4"
   └─► kytchen MCP client authenticates with API key
   └─► Kytchen Cloud returns available datasets
   └─► LLM selects relevant dataset(s)
   └─► The LLM runs the reasoning loop by calling Kytchen tools (peek/search/exec)
   └─► Kytchen Cloud executes those tools over stored data + records evidence/metrics
   └─► The final answer is generated by the client LLM (and can be persisted as a run)
```

---

## API Design

### Authentication

All API requests include:
```
Authorization: Bearer kyt_sk_abc123...
```

API key encodes:
- Workspace ID (derived from key lookup)
- Permissions (read, write, admin)
- Rate limits (based on plan)

### Endpoints

#### Datasets

```http
# List datasets in workspace (workspace derived from API key)
GET /v1/datasets
Response: {
  "datasets": [
    {
      "id": "ds_abc123",
      "name": "Q4 Sales Report",
      "size_bytes": 1048576,
      "format": "csv",
      "created_at": "2025-12-15T00:00:00Z",
      "content_hash": "sha256:..."
    }
  ]
}

# Upload dataset
POST /v1/datasets
Content-Type: multipart/form-data
Body: { file: <binary>, name: "Q4 Sales Report" }
Response: { "id": "ds_abc123", ... }

# Get dataset metadata
GET /v1/datasets/:id
Response: { "id": "ds_abc123", "name": "...", ... }

# Delete dataset
DELETE /v1/datasets/:id
Response: { "deleted": true }
```

#### Queries

```http
# Start a query run (BYOLLM: Kytchen does not generate the answer)
POST /v1/query
Body: {
  "query": "Find all sales trends in Q4",
  "dataset_ids": ["ds_abc123"],  // optional, defaults to all
  "budget": {
    "max_iterations": 20,
    "max_wall_time_seconds": 60
  }
}
Response: {
  "id": "run_xyz789",
  "status": "running",
  "tool_session_id": "sess_123",
  "budget": { "max_iterations": 20, "max_wall_time_seconds": 60 }
}

# Persist the final answer (optional, but enables dashboards/audit)
POST /v1/runs/:id/finalize
Body: {
  "answer": "Q4 sales increased 23% YoY...",
  "success": true
}
Response: { "id": "run_xyz789", "status": "completed" }

# Get query history
GET /v1/runs
Response: { "runs": [...] }

# Get specific run
GET /v1/runs/:id
Response: { "id": "run_xyz789", ... }
```

#### Workspaces (Web Dashboard)

```http
# List workspaces for authenticated user
GET /v1/workspaces
Response: { "workspaces": [...] }

# Create workspace
POST /v1/workspaces
Body: { "name": "Acme Corp Research" }
Response: { "id": "ws_abc123", ... }

# Invite member
POST /v1/workspaces/:id/members
Body: { "email": "teammate@acme.com", "role": "member" }
```

#### API Keys

```http
# List API keys (masked)
GET /v1/api-keys
Response: {
  "keys": [
    { "id": "key_abc", "prefix": "kyt_sk_abc...", "name": "Cursor Dev", "created_at": "..." }
  ]
}

# Create API key
POST /v1/api-keys
Body: { "name": "Cursor Dev" }
Response: { "key": "kyt_sk_abc123...", "id": "key_abc" }  // key shown ONCE

# Revoke API key
DELETE /v1/api-keys/:id
```

---

## MCP Tools (What the LLM sees)

When connected via MCP, the LLM has these tools:

### `kytchen_list_datasets`
```
Lists all datasets in the connected workspace.

Returns:
- id: Dataset identifier
- name: Human-readable name
- size: Size in bytes
- format: File format (csv, json, txt, pdf)
- preview: First 500 chars of content
```

### `kytchen_query`
```
Starts a query run and returns a `run_id`/`tool_session_id`.

The client LLM then performs the reasoning loop by calling Kytchen tools
(`kytchen_search`, `kytchen_peek`, optional `kytchen_exec_python`, etc.).

Parameters:
- query (required): The question to answer
- dataset_ids (optional): Specific datasets to query, defaults to all
- budget (optional): { max_iterations, max_wall_time_seconds }

Returns:
- run_id: The run identifier for history/audit
- tool_session_id: Binds tool calls to this run for evidence/metrics
- budget: The applied budget
```

### `kytchen_peek`
```
Preview a portion of a dataset.

Parameters:
- dataset_id (required): Which dataset
- start (optional): Start line/char
- end (optional): End line/char

Returns:
- content: The requested portion
```

### `kytchen_search`
```
Search for a pattern in a dataset.

Parameters:
- dataset_id (required): Which dataset
- pattern (required): Regex pattern
- max_results (optional): Limit results

Returns:
- matches: Array of { line, content, context }
```

### `kytchen_exec_python` (optional, power tool)
```
Execute Python in a sandboxed REPL (the core “LLM inside code” primitive).

Parameters:
- tool_session_id (required): Bind execution + evidence to a run
- code (required): Python code to execute

Returns:
- stdout: Captured print output
- result: Stringified return value (best-effort)
- errors: Exception text (if any)
```

---

## Database Schema (Supabase)

```sql
-- Workspaces
CREATE TABLE workspaces (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  name TEXT NOT NULL,
  slug TEXT UNIQUE NOT NULL,  -- URL-friendly: "acme-corp"
  plan TEXT DEFAULT 'free' CHECK (plan IN ('free', 'pro', 'team', 'enterprise')),
  created_at TIMESTAMPTZ DEFAULT now(),
  updated_at TIMESTAMPTZ DEFAULT now()
);

-- Workspace members
CREATE TABLE workspace_members (
  workspace_id UUID REFERENCES workspaces(id) ON DELETE CASCADE,
  user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE,
  role TEXT DEFAULT 'member' CHECK (role IN ('owner', 'admin', 'member')),
  invited_at TIMESTAMPTZ DEFAULT now(),
  accepted_at TIMESTAMPTZ,
  PRIMARY KEY (workspace_id, user_id)
);

-- API keys
CREATE TABLE api_keys (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  workspace_id UUID REFERENCES workspaces(id) ON DELETE CASCADE,
  key_hash TEXT NOT NULL,  -- bcrypt hash
  key_prefix TEXT NOT NULL,  -- "kyt_sk_abc" for display
  name TEXT,
  permissions TEXT[] DEFAULT ARRAY['read', 'write'],
  last_used_at TIMESTAMPTZ,
  revoked_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ DEFAULT now()
);

-- Datasets
CREATE TABLE datasets (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  workspace_id UUID REFERENCES workspaces(id) ON DELETE CASCADE,
  name TEXT NOT NULL,
  description TEXT,
  storage_path TEXT NOT NULL,  -- Supabase Storage path
  size_bytes BIGINT NOT NULL,
  content_hash TEXT NOT NULL,  -- SHA256
  format TEXT,  -- csv, json, txt, pdf
  line_count INT,
  created_at TIMESTAMPTZ DEFAULT now(),
  updated_at TIMESTAMPTZ DEFAULT now()
);

-- Query runs
CREATE TABLE runs (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  workspace_id UUID REFERENCES workspaces(id) ON DELETE CASCADE,
  api_key_id UUID REFERENCES api_keys(id),
  dataset_ids UUID[] NOT NULL,
  query TEXT NOT NULL,
  answer TEXT,
  success BOOLEAN,
  error TEXT,
  iterations INT,
  wall_time_seconds DECIMAL(10,3),
  created_at TIMESTAMPTZ DEFAULT now()
);

-- Evidence citations
CREATE TABLE evidence (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  run_id UUID REFERENCES runs(id) ON DELETE CASCADE,
  dataset_id UUID REFERENCES datasets(id),
  snippet TEXT NOT NULL,
  line_start INT,
  line_end INT,
  note TEXT
);

-- Usage counters (limits + billing)
CREATE TABLE workspace_usage (
  workspace_id UUID PRIMARY KEY REFERENCES workspaces(id) ON DELETE CASCADE,
  storage_bytes BIGINT DEFAULT 0,
  requests_this_month INT DEFAULT 0,
  egress_bytes_this_month BIGINT DEFAULT 0,
  last_reset_at TIMESTAMPTZ DEFAULT date_trunc('month', now()),
  updated_at TIMESTAMPTZ DEFAULT now()
);

-- Reset monthly counters (cron job)
CREATE OR REPLACE FUNCTION reset_monthly_usage()
RETURNS void AS $$
  UPDATE workspace_usage
  SET requests_this_month = 0,
      egress_bytes_this_month = 0,
      last_reset_at = now(),
      updated_at = now()
  WHERE last_reset_at < date_trunc('month', now());
$$ LANGUAGE sql;

-- Row Level Security
ALTER TABLE workspaces ENABLE ROW LEVEL SECURITY;
ALTER TABLE workspace_members ENABLE ROW LEVEL SECURITY;
ALTER TABLE api_keys ENABLE ROW LEVEL SECURITY;
ALTER TABLE datasets ENABLE ROW LEVEL SECURITY;
ALTER TABLE runs ENABLE ROW LEVEL SECURITY;
ALTER TABLE evidence ENABLE ROW LEVEL SECURITY;
ALTER TABLE workspace_usage ENABLE ROW LEVEL SECURITY;

-- Policies (user can access workspaces they're a member of)
CREATE POLICY workspace_access ON workspaces
  FOR ALL USING (
    id IN (SELECT workspace_id FROM workspace_members WHERE user_id = auth.uid())
  );

-- Similar policies for other tables...
```

---

## Storage Architecture

```
Supabase Storage Bucket: "datasets"

Structure:
/datasets
  /{workspace_id}
    /{dataset_id}
      /original.{ext}     # Original uploaded file
      /processed.txt      # Extracted text (for PDFs, etc.)
      /metadata.json      # Size, line count, format info
```

### File Processing Pipeline

1. **Upload** → Store original in Supabase Storage
2. **Extract** → If PDF/DOCX, extract text via worker
3. **Index** → Compute line count, content hash
4. **Ready** → Mark dataset as queryable

---

## Rate Limits by Plan

Pricing is **storage-first** (users bring their own LLM). We enforce safety via hard limits:
storage caps, rate limits, request timeouts, evidence retention, and egress caps.

| Plan | Price | Storage | Rate limit | Timeout | Egress/mo | Evidence retention | Workspaces |
|------|------:|--------:|-----------:|--------:|----------:|------------------:|-----------:|
| Free (Developer) | $0 | 50MB | 5 req/min | 15s | 1GB | 3 days | 1 |
| Pro | $19/mo | 10GB | 100 req/min | 60s | 50GB | 90 days | 3 |
| Team | $99/mo | 50GB | 200 req/min | 120s | 200GB | 1 year | Unlimited |
| Enterprise | Custom | Unlimited | Custom | Custom | Custom | Custom | Custom |

Overage (recommended):
- Storage: Pro `$0.50/GB/mo`, Team `$0.40/GB/mo`

---

## Example: Full Integration Flow

### 1. User signs up, creates workspace

```bash
# Via web dashboard at kytchen.dev
# Creates workspace "acme-research" with slug "acme-research"
```

### 2. Uploads dataset via dashboard or CLI

```bash
# Future CLI option:
kytchen upload ./sales-q4.csv --name "Q4 Sales Data"
```

### 3. Gets API key

```bash
# Dashboard shows: kyt_sk_live_abc123...
# User copies to their config
```

### 4. Configures MCP

```json
// ~/.codex/config.toml or ~/.cursor/mcp.json
{
  "mcpServers": {
    "kytchen": {
      "command": "kytchen",
      "env": {
        "KYTCHEN_API_KEY": "kyt_sk_live_abc123..."
      }
    }
  }
}
```

### 5. Queries from Claude/Cursor/Codex

```
User: "Use kytchen to analyze Q4 sales and find the top performing regions"

Claude/Codex:
1. Calls kytchen_list_datasets → sees "Q4 Sales Data"
2. Calls kytchen_query(
     query="Find top performing regions in Q4 sales",
     dataset_ids=["ds_abc123"]
   )
3. Claude uses kytchen_search / kytchen_peek (and optional kytchen_exec_python) to iterate
4. Claude writes the final answer to the user
5. (Optional) Claude calls /v1/runs/:id/finalize to persist the answer for audit/history
```

---

## Deployment Architecture

```
┌─────────────────────────────────────────────────────────────┐
│  Vercel                                                      │
│  ┌─────────────────────────────────────────────────────────┐ │
│  │  Next.js Frontend (kytchen.dev)                           │ │
│  │  - Dashboard                                            │ │
│  │  - Auth (Supabase)                                      │ │
│  │  - Dataset upload UI                                    │ │
│  └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│  Railway / Render / Fly.io                                   │
│  ┌─────────────────────────────────────────────────────────┐ │
│  │  Python API (FastAPI)                                   │ │
│  │  - /v1/datasets                                         │ │
│  │  - /v1/query (creates runs + tool sessions)             │ │
│  │  - /v1/api-keys                                         │ │
│  │  - Authenticates via Supabase                           │ │
│  └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│  Supabase                                                    │
│  ┌───────────────┐  ┌───────────────┐  ┌───────────────┐    │
│  │   Postgres    │  │   Storage     │  │     Auth      │    │
│  │   (data)      │  │   (files)     │  │   (users)     │    │
│  └───────────────┘  └───────────────┘  └───────────────┘    │
└─────────────────────────────────────────────────────────────┘
```

---

## Security Considerations

1. **API Key Hashing** - Store bcrypt hash, not plaintext
2. **RLS** - All queries scoped to workspace via Supabase RLS
3. **File Validation** - Scan uploads, limit file types
4. **Hard Storage Limits** - Enforce plan caps before upload/write
5. **Rate Limiting** - Per API key, enforced at API layer (Redis/Upstash)
6. **Request Timeouts** - Per-plan timeouts to prevent abuse
7. **Egress Caps** - Track and cap bandwidth per workspace/month
8. **Audit Log** - Runs + evidence recorded for provenance
9. **Data Isolation** - Each workspace's data completely isolated

---

## Implementation Priority

### Phase 1: Core API (Week 1-2)
- [ ] Supabase project setup
- [ ] Database schema migration
- [ ] FastAPI with auth middleware
- [ ] Dataset upload/list/delete endpoints
- [ ] Query runs: `POST /v1/query`, `POST /v1/runs/:id/finalize`
- [ ] Tool endpoints: peek/search/exec (BYOLLM loop via MCP)
- [ ] Plan enforcement: storage/rate-limit/timeout/egress/retention

### Phase 2: MCP Client (Week 2-3)
- [ ] Rewrite kytchen CLI as API client
- [ ] MCP tool implementations
- [ ] Test with Claude Desktop, Cursor, Codex

### Phase 3: Web Dashboard (Week 3-4)
- [ ] Next.js project setup
- [ ] Supabase Auth integration
- [ ] Workspace management UI
- [ ] Dataset upload/management UI
- [ ] API key management

### Phase 4: Billing (Week 4+)
- [ ] Stripe integration
- [ ] Usage tracking
- [ ] Plan enforcement
- [ ] Upgrade/downgrade flows
