bytespace-proxy.md

Bytespace Proxy Architecture

The Bytespace Proxy is a secure intermediary that handles all external API calls on behalf of the bot0 daemon. This architecture ensures that sensitive credentials never exist on the daemon, which runs AI agents that could be vulnerable to prompt injection attacks.

Overview

┌─────────────────────────────────────────────────────────────────────────────────┐
│                     UNIFIED PROXY ARCHITECTURE                                   │
│                                                                                  │
│   Daemon                     Proxy (Bytespace or Self-Hosted)   Backend          │
│   ──────                     ────────────────────────────────   ───────          │
│                                                                                  │
│   NO SECRETS                 Retrieves keys from ctx0 DB:                        │
│   on daemon                  • User's API keys (encrypted)                       │
│                              • Or Bytespace business keys                        │
│                                                                                  │
│   ┌──────────────┐           ┌──────────────┐           ┌──────────────┐        │
│   │              │  Request  │              │  Request  │              │        │
│   │    Daemon    │──────────▶│    Proxy     │──────────▶│  Anthropic/  │        │
│   │   (bot0)     │ (session  │  (open src)  │ (with     │  OpenAI/     │        │
│   │              │  token)   │              │  API key) │  Google      │        │
│   │              │◀──────────│              │◀──────────│              │        │
│   └──────────────┘  Stream   └──────────────┘  Response └──────────────┘        │
│                                                                                  │
└─────────────────────────────────────────────────────────────────────────────────┘

Core Components

1. Proxy Package (@bot0/proxy)

The proxy package provides the core functionality for secure credential management and request proxying. It's designed to be used by both Bytespace (hosted) and self-hosted deployments.

Location: packages/proxy/src/

packages/proxy/
├── src/
│   ├── lib/
│   │   ├── encryption.ts      # AES-256-GCM encryption utilities
│   │   ├── validation.ts      # API key and credential validation
│   │   └── types.ts           # Type definitions
│   ├── routes/
│   │   ├── keys.ts            # API key CRUD operations
│   │   ├── db-credentials.ts  # Self-hosted DB credential management
│   │   ├── llm.ts             # LLM request proxy
│   │   └── db.ts              # Database request proxy
│   └── index.ts               # Main exports
└── package.json

2. Bytespace API Routes

Bytespace implements the proxy endpoints with billing integration.

Location: apps/bytespace/src/app/api/

EndpointPurpose
/api/keysManage user API keys
/api/keys/[id]Delete specific API key
/api/db-credentialsManage self-hosted database credentials
/api/proxy/llm/[provider]/[...path]Proxy LLM requests to providers
/api/proxy/dbProxy database operations

Deployment Tiers

The proxy architecture supports three deployment tiers, allowing users to choose their level of self-hosting.

Tier 1: Fully Hosted (Default)

Everything runs on Bytespace infrastructure.

┌────────────────────────────────────────────────────┐
│  TIER 1: Fully Hosted                               │
│  ─────────────────────                              │
│  • LLM Proxy: Bytespace                            │
│  • ctx0 DB: Bytespace                              │
│  • API Keys: Bytespace (encrypted)                 │
│  • Credits: Bytespace                              │
│                                                    │
│  User provides: Nothing (pay-as-you-go credits)   │
└────────────────────────────────────────────────────┘

Benefits:

  • Zero configuration
  • Pay-as-you-go pricing
  • No infrastructure to manage

Tier 2: Self-Hosted Database

User hosts their own ctx0 database on Supabase.

┌────────────────────────────────────────────────────┐
│  TIER 2: Self-Hosted DB                            │
│  ───────────────────────                           │
│  • LLM Proxy: Bytespace                            │
│  • ctx0 DB: User's Supabase                        │
│  • API Keys: User's ctx0 DB (encrypted)            │
│  • Credits: Bytespace (if using Bytespace credits) │
│                                                    │
│  User provides: Supabase URL + credentials         │
└────────────────────────────────────────────────────┘

Benefits:

  • Full control over conversation history and memories
  • Data stays in user's infrastructure
  • Can still use Bytespace credits for LLM calls

Tier 3: Fully Self-Hosted

User runs their own proxy server and database.

┌────────────────────────────────────────────────────┐
│  TIER 3: Fully Self-Hosted                         │
│  ────────────────────────────────────────          │
│  • LLM Proxy: User's proxy (open source)           │
│  • ctx0 DB: User's Supabase                        │
│  • API Keys: User's ctx0 DB (user's encryption key)│
│  • Credits: N/A (user's own API keys)              │
│                                                    │
│  User provides: Everything (no Bytespace needed)   │
└────────────────────────────────────────────────────┘

Benefits:

  • Complete independence from Bytespace
  • User controls encryption key
  • No usage tracking or billing

LLM Proxy

The LLM proxy forwards requests to AI providers while handling authentication and billing.

Supported Providers

ProviderBase URLAuth Header
Anthropichttps://api.anthropic.comx-api-key
OpenAIhttps://api.openai.comAuthorization: Bearer
Googlehttps://generativelanguage.googleapis.comx-goog-api-key
XAIhttps://api.x.aiAuthorization: Bearer

Request Flow

typescript
// Daemon sends request to proxy POST /api/proxy/llm/anthropic/v1/messages Authorization: Bearer <session_token> Content-Type: application/json { "model": "claude-sonnet-4-6", "messages": [{ "role": "user", "content": "Hello" }], "max_tokens": 1024 }

Proxy Processing:

  1. Validate session token - Verify the request comes from an authenticated user
  2. Retrieve API key - Get user's key from ctx0_api_keys table, or use Bytespace fallback
  3. Credit check (if using Bytespace credits) - Verify user has sufficient credits
  4. Forward request - Send to LLM provider with decrypted API key
  5. Stream response - Return streaming response to daemon
  6. Log usage (if using Bytespace credits) - Record tokens for billing

API Key Priority

1. User's own API key (from ctx0_api_keys, encrypted)
   ↓ if not found
2. Bytespace fallback key (requires credit check)
   ↓ if no credits
3. Error: "Add credits or configure your own API key"

Code Example

typescript
import { createLlmProxy } from '@bot0/proxy'; const llmProxy = createLlmProxy({ // Optional billing hooks (Bytespace only) billingHook: { checkCredits: async (userId) => { const result = await creditLimitCheck(userId, 'bot0_daemon'); return { canMakeRequest: result.canMakeRequest, reason: result.limitExceededReason, }; }, logUsage: async (userId, model, inputTokens, outputTokens) => { await logAIUsage(model, inputTokens, outputTokens, 0, 'bot0_daemon', userId); }, }, // Optional fallback keys (Bytespace business keys) fallbackKeys: { anthropic: process.env.BYTESPACE_ANTHROPIC_KEY, openai: process.env.BYTESPACE_OPENAI_KEY, google: process.env.BYTESPACE_GOOGLE_KEY, }, });

Database Proxy

The database proxy allows the daemon to interact with ctx0 tables without having database credentials.

Supported Operations

OperationDescription
selectQuery rows with filters
insertInsert new rows
updateUpdate existing rows
deleteDelete rows
upsertInsert or update based on conflict
rpcCall database functions

Security: User ID Enforcement

For all ctx0 tables (prefixed with ctx0_), the proxy automatically:

  • Filters queries by user_id on SELECT, UPDATE, DELETE
  • Sets user_id on INSERT and UPSERT

This prevents users from accessing other users' data, even if they craft malicious requests.

Request Format

typescript
POST /api/proxy/db Authorization: Bearer <session_token> Content-Type: application/json { "operation": "select", "table": "ctx0_sessions", "select": "id, created_at, summary", "filters": { "status": "active" } }

Response Format

typescript
{ "data": [...], // Query results "error": null // Or error message string }

Code Example

typescript
// From daemon const db = new ProxiedSupabaseClient(config.sessionToken, config.proxyUrl); // Query sessions const { data: sessions } = await db .from('ctx0_sessions') .select('id, summary') .eq('status', 'active'); // Insert message await db .from('ctx0_session_messages') .insert({ session_id: sessionId, role: 'user', content: 'Hello' });

Encryption

All credentials are encrypted at rest using AES-256-GCM.

Encryption Process

typescript
import { encryptSecret, decryptSecret } from '@bot0/proxy'; // Encrypt an API key const { encrypted, nonce } = encryptSecret('sk-ant-api03-...'); // encrypted: Base64 ciphertext + auth tag // nonce: Base64 12-byte nonce // Decrypt when needed const apiKey = decryptSecret(encrypted, nonce);

Key Storage

WhatWhere StoredHow Protected
Encryption keyEnvironment variable (API_KEY_ENCRYPTION_KEY)Server-side only
Encrypted credentialsDatabase (ctx0_api_keys, ctx0_db_credentials)AES-256-GCM
Session tokensDaemon config (~/.bot0/config.json)Revocable server-side

Generating Encryption Key

For self-hosted deployments:

bash
# Generate a 32-byte (256-bit) key openssl rand -hex 32 > ~/.bot0/encryption_key # Set in environment export API_KEY_ENCRYPTION_KEY=$(cat ~/.bot0/encryption_key)

Database Schema

ctx0_api_keys

Stores encrypted API keys for LLM providers.

sql
CREATE TABLE ctx0_api_keys ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL, -- Provider info provider TEXT NOT NULL, -- 'anthropic', 'openai', 'google' name TEXT, -- User's label -- Encrypted key storage encrypted_key TEXT NOT NULL, -- AES-256-GCM encrypted key_nonce TEXT NOT NULL, -- Unique nonce key_suffix TEXT NOT NULL, -- Last 4 chars (sk-...xxxx) -- Status is_active BOOLEAN DEFAULT true, is_valid BOOLEAN DEFAULT true, -- Usage stats request_count INT DEFAULT 0, total_input_tokens BIGINT DEFAULT 0, total_output_tokens BIGINT DEFAULT 0, -- Timestamps created_at TIMESTAMPTZ DEFAULT NOW(), last_used_at TIMESTAMPTZ, last_validated_at TIMESTAMPTZ, UNIQUE(user_id, provider) );

ctx0_db_credentials

Stores encrypted Supabase credentials for self-hosted users.

sql
CREATE TABLE ctx0_db_credentials ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL, -- Connection info supabase_url TEXT NOT NULL, project_name TEXT, -- Encrypted credentials encrypted_anon_key TEXT NOT NULL, anon_key_nonce TEXT NOT NULL, encrypted_service_role_key TEXT NOT NULL, service_role_key_nonce TEXT NOT NULL, -- Display info anon_key_suffix TEXT NOT NULL, -- Status is_active BOOLEAN DEFAULT true, is_valid BOOLEAN DEFAULT true, -- Usage stats request_count INT DEFAULT 0, last_used_at TIMESTAMPTZ, UNIQUE(user_id) );

Daemon Integration

The daemon uses proxied clients that route all requests through the proxy.

ProxiedAnthropicClient

typescript
import { ProxiedAnthropicClient } from '@bot0/daemon'; const client = new ProxiedAnthropicClient({ sessionToken: config.sessionToken, proxyUrl: config.proxyUrl, }); // Uses Anthropic SDK interface, but routes through proxy const response = await client.createMessage({ model: 'claude-sonnet-4-6', messages: [{ role: 'user', content: 'Hello' }], max_tokens: 1024, });

ProxiedSupabaseClient

typescript
import { ProxiedSupabaseClient } from '@bot0/daemon'; const db = new ProxiedSupabaseClient( config.sessionToken, config.proxyUrl ); // Supabase-like interface, but routes through proxy const { data } = await db .from('ctx0_sessions') .select('*') .eq('status', 'active');

Daemon Configuration

The daemon stores only non-secret configuration:

json
// ~/.bot0/config.json { "proxyUrl": "https://api.bytespace.ai", "sessionToken": "byt_xxx...", "defaultProvider": "anthropic", "defaultModel": "claude-sonnet-4-6" }

What's NOT in the config:

  • API keys (stored encrypted on proxy)
  • Database credentials (stored encrypted on proxy)
  • Encryption keys (only on proxy server)

API Reference

POST /api/keys

Add or update an API key.

Request:

json
{ "provider": "anthropic", "apiKey": "sk-ant-api03-...", "name": "My Anthropic Key" }

Response:

json
{ "id": "uuid", "provider": "anthropic", "name": "My Anthropic Key", "suffix": "xxxx", "createdAt": "2024-01-01T00:00:00Z" }

GET /api/keys

List all API keys (masked).

Response:

json
[ { "id": "uuid", "provider": "anthropic", "name": "My Anthropic Key", "suffix": "xxxx", "isActive": true, "requestCount": 42, "createdAt": "2024-01-01T00:00:00Z", "lastUsedAt": "2024-01-15T12:00:00Z" } ]

DELETE /api/keys/[id]

Delete an API key.

Response:

json
{ "success": true }

POST /api/db-credentials

Save self-hosted database credentials.

Request:

json
{ "supabaseUrl": "https://xxx.supabase.co", "anonKey": "eyJ...", "serviceRoleKey": "eyJ...", "projectName": "My ctx0" }

POST /api/proxy/llm/[provider]/[...path]

Forward LLM request to provider.

Request: Same as native provider API Response: Streaming response from provider

POST /api/proxy/db

Execute database operation.

Request:

json
{ "operation": "select" | "insert" | "update" | "delete" | "upsert" | "rpc", "table": "ctx0_sessions", "data": {}, "filters": {}, "select": "*" }

Self-Hosting Guide

Prerequisites

  • Node.js 20+
  • Supabase project (for ctx0 database)
  • 32-byte encryption key

Setup Steps

  1. Clone and build the proxy package:

    bash
    git clone https://github.com/bot0/bot0.git cd bot0 pnpm install pnpm --filter @bot0/proxy build
  2. Generate encryption key:

    bash
    openssl rand -hex 32 > encryption_key.txt
  3. Set up Supabase:

    • Create a new Supabase project
    • Run the ctx0 migrations from packages/ctx0/migrations/
  4. Configure environment:

    bash
    export API_KEY_ENCRYPTION_KEY=$(cat encryption_key.txt) export CTX0_SUPABASE_URL=https://your-project.supabase.co export CTX0_SUPABASE_SERVICE_KEY=your-service-role-key
  5. Deploy the proxy:

    • Use the routes from packages/proxy/src/routes/
    • Deploy as Express, Fastify, or Next.js API routes
  6. Configure daemon:

    json
    // ~/.bot0/config.json { "proxyUrl": "https://your-proxy.example.com" }

What's Bytespace-Proprietary

The following components are not open-sourced and remain Bytespace-only:

ComponentPurpose
Credit trackingPay-as-you-go billing
logAIUsageUsage logging for billing
creditLimitCheckCredit limit enforcement
Subscription managementPro/Enterprise tiers
Bytespace business keysFallback API keys

Self-hosted users bypass all billing by using their own API keys.

Archived product

A chapter of bot0, preserved.

bot0 was a working product by Bytespace Labs. This site preserves its original design and product experience. The hosted service is no longer running; downloads, new accounts and purchases are unavailable.

Product descriptions, documentation and pricing reflect the product when it was active. The interactions preserved here are not connected to its former backend.

Interested in the technology?

We’re open to discussing an acquisition of the technology and codebase behind bot0.

Discuss an acquisition