SYSTEM DESIGN

Built for the age of API agents

Edge-first. Encrypted credentials. Transparent proxy. Every layer designed so humans and AI agents call any API through one hub.

SYSTEM OVERVIEW

Client, edge, storage, upstream

Every request follows the same path. Any client hits the edge for auth and routing. The edge reads metadata from D1, specs from R2, and proxies to upstream APIs.

CLIENTS
Browser
Human
Claude
MCP Agent
ChatGPT
MCP Agent
CLI / API
Developer
EDGE RUNTIME
Auth Layer
Ed25519 verify, session tokens, API keys, scopes
Router + Proxy
REST routes, transparent proxy, header injection
MCP Server
JSON-RPC 2.0, 6 tools for AI agents
Discovery
OpenAPI fetch, parse, endpoint extraction
STORAGE
D1 (SQLite)
actors, apis, endpoints, connections, keys, sessions, request_log
R2 (Object)
OpenAPI specs (JSON, up to 10 MB)
UPSTREAM
OpenAIStripeGitHubSlack...any API
CREDENTIAL VAULT

Encrypted at rest, decrypted only at proxy time.

Every credential goes through a dedicated encryption pipeline before touching the database.

INPUT
{"token": "sk-proj-..."}
KEY DERIVATION
HKDF-SHA256 key = SIGNING_KEY salt = actor_id → 256-bit AES key
ENCRYPT
AES-GCM-256 random IV (12 bytes) → ciphertext + IV
D1 STORAGE
auth_config = (encrypted blob) auth_config_iv = (12 byte IV)
PROXY PIPELINE

Nine steps from client to upstream.

Every proxied request follows this exact path.

1
Client requestPOST /proxy/cn_a8f3/v1/chat/completions
2
Auth middlewareValidate bearer token, extract actor, check scope
3
Connection lookupSELECT from connections WHERE id = ? AND actor = ?
4
Decrypt credentialsHKDF → AES key → AES-GCM-256 decrypt → JSON
5
Build upstream requestbase_url + path, method, body forwarded
6
Inject auth headersBearer / API key / Basic / OAuth + extra headers
7
Fetch upstreamfetch(url, {method, headers, body})
8
Background loggingINSERT request_log + UPDATE connection counter
9
Respond to clientForward status + headers + body + X-Proxy-Duration-Ms
DATA MODEL

Eight tables, one database.

D1 (SQLite at the edge) stores all metadata. R2 stores raw specs.

actors

actor, public_key, created_at, updated_at

Registered identities with Ed25519 public keys

apis

id, actor, slug, name, base_url, auth_type, spec_key

API definitions with optional R2 spec reference

endpoints

id, api_id, method, path, summary, operation_id

Extracted from uploaded OpenAPI specs

connections

id, actor, name, base_url, auth_type, auth_config (encrypted), auth_config_iv

Credential vault — AES-GCM-256 encrypted at rest

api_keys

id, actor, name, prefix, key_hash, scope, expires_at

Scoped API keys, SHA-256 hashed

sessions

id, actor, token, expires_at

Active bearer tokens (2h TTL default)

challenges

id, actor, nonce, expires_at

Ed25519 challenge nonces (5min TTL)

request_log

id, actor, connection_id, method, path, status, duration_ms

Audit trail for every proxied request

Read the code, not just the diagram.

The entire hub is one Cloudflare Worker. Edge runtime, D1 database, R2 storage.

# API Architecture Purpose-built for developers and AI agents to connect, proxy, and call any API. api.liteio.dev is an edge-first API hub. Every design decision — from credential encryption to the transparent proxy pipeline to MCP integration — serves both human developers and AI agents through one unified interface. ## System Overview
Client (Human or Agent) │ │ HTTPS ▼ ┌─────────────────────────────────────────────┐ │ Edge Runtime │ │ ┌────────┐ ┌──────────┐ ┌─────────────┐ │ │ │ Auth │ │ Router │ │ MCP Server │ │ │ │ Layer │ │ + Proxy │ │ (6 Tools) │ │ │ └────────┘ └──────────┘ └─────────────┘ │ └──────────────────┬──────────────────────────┘ │ ┌──────────┼──────────┐ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │ D1 (SQL) │ │ R2 (Blob)│ │ Upstream APIs│ │ │ │ │ │ │ │ actors │ │ specs/ │ │ OpenAI │ │ apis │ │ {api}/ │ │ Stripe │ │ endpoints│ │ spec.json│ │ GitHub │ │ conn. │ │ │ │ Slack │ │ keys │ │ │ │ ...any API │ │ sessions │ │ │ │ │ │ req_log │ │ │ │ │ └──────────┘ └──────────┘ └──────────────┘
### Layers
LayerTechnologyRole
Edge RuntimeCloudflare WorkersRequest handling, auth, proxy, MCP
D1 (SQL)Cloudflare D1 (SQLite)Metadata: actors, APIs, connections, keys, logs
R2 (Blob)Cloudflare R2OpenAPI spec storage (JSON, up to 10 MB)
UpstreamAny REST APITarget APIs called through the proxy
ProtocolREST + MCPUnified access for humans and AI agents
## Credential Vault Credentials are never stored in plaintext. The encryption pipeline:
┌─────────────┐ │ SIGNING_KEY │ (Worker secret) └──────┬──────┘ │ HKDF-SHA256 salt = actor_id │ ┌──────▼──────┐ │ Per-Actor │ │ AES-GCM Key│ └──────┬──────┘ │ ┌──────────────────┼──────────────────┐ ▼ ▼ ┌───────────┐ ┌───────────┐ │ Encrypt │ │ Decrypt │ │ (on save) │ │ (on proxy)│ └─────┬─────┘ └─────┬─────┘ │ │ ▼ ▼ auth_config ←── D1 storage ──→ plaintext auth_config_iv (injected as HTTP headers)
### Key Points - HKDF-SHA256 derives a unique AES key per actor from a single Worker secret - AES-GCM-256 encrypts the full auth_config JSON object - Random IV per encryption — stored alongside ciphertext in D1 - Decrypt only at proxy time — credentials flow from D1 → memory → upstream request → garbage collected - Masked in all responses — API responses show sk-p*.. style masking ## Proxy Pipeline Every proxied request follows this exact path:
1. Client sends request POST /proxy/cn_a8f3e1b2/v1/chat/completions Authorization: Bearer sk_user_api_key 2. Auth middleware → Validate bearer token (session or API key) → Extract actor identity → Check scope (must include "proxy" or "*") 3. Connection lookup → SELECT * FROM connections WHERE id = ? AND actor = ? → Verify connection exists and belongs to this actor 4. Credential decryption → Derive AES key: HKDF(SIGNING_KEY, actor) → Decrypt auth_config: AES-GCM-256(key, iv, ciphertext) → Parse JSON: {"token": "sk-proj-actual-key"} 5. Build upstream request → URL: connection.base_url + remaining path → Method: same as client request → Body: forwarded as-is → Headers: stripped (no Authorization, Cookie, Host from client) 6. Inject auth headers → bearer: Authorization: Bearer {token} → api_key: {header}: {key} → basic: Authorization: Basic base64({username}:{password}) → oauth2_token: Authorization: Bearer {access_token} → Extra headers merged from connection config 7. Fetch upstream → fetch(upstream_url, {method, headers, body}) → Capture status, headers, body, duration 8. Background logging → INSERT INTO request_log (actor, connection_id, method, path, status, duration_ms) → UPDATE connections SET request_count = request_count + 1 9. Respond to client → Forward upstream status code → Forward upstream headers (stripped: set-cookie, transfer-encoding) → Forward upstream body → Add X-Proxy-Duration-Ms header
## Data Model ### Core Tables
actors ┌──────────┬────────────┬────────────┬──────────┐ │ actor │ public_key │ created_at │ updated │ ├──────────┼────────────┼────────────┼──────────┤ │ my-app │ base64... │ 1711065600 │ 17110656 │ │ demo │ base64... │ 1711070000 │ 17110700 │ └──────────┴────────────┴────────────┴──────────┘ apis ┌──────────┬─────────┬──────────────────────┬───────────┐ │ id │ slug │ base_url │ spec_key │ ├──────────┼─────────┼──────────────────────┼───────────┤ │ api_f1a2 │ openai │ https://api.openai.. │ specs/... │ │ api_b3c4 │ stripe │ https://api.stripe.. │ specs/... │ └──────────┴─────────┴──────────────────────┴───────────┘ connections ┌──────────┬─────────┬──────────────────────┬───────────┬──────────────┐ │ id │ name │ base_url │ auth_type │ auth_config │ ├──────────┼─────────┼──────────────────────┼───────────┼──────────────┤ │ cn_a8f3 │ OpenAI │ https://api.openai.. │ bearer │ (encrypted) │ │ cn_d5e6 │ Stripe │ https://api.stripe.. │ bearer │ (encrypted) │ └──────────┴─────────┴──────────────────────┴───────────┴──────────────┘ endpoints (extracted from OpenAPI specs) ┌──────────┬──────────┬────────┬──────────────────────┐ │ id │ api_id │ method │ path │ ├──────────┼──────────┼────────┼──────────────────────┤ │ ep_1a2b │ api_f1a2 │ GET │ /v1/models │ │ ep_3c4d │ api_f1a2 │ POST │ /v1/chat/completions │ └──────────┴──────────┴────────┴──────────────────────┘
### Supporting Tables
TablePurpose
sessionsActive bearer tokens with TTL (2h default)
challengesEd25519 challenge nonces (5min TTL)
api_keysScoped API keys (SHA-256 hashed, prefix stored)
rate_limitsSliding window counters per actor + action
request_logAudit trail for every proxied request
## Discovery Engine The spec discovery pipeline:
1. Fetch spec from URL → GET https://example.com/openapi.json → Accept JSON only, max 10 MB 2. Detect version → "openapi" field → OpenAPI 3.x → "swagger" field → Swagger 2.x 3. Normalize → Extract: title, version, description, servers/host/basePath → Detect auth type from securitySchemes 4. Extract endpoints → Walk paths object → For each path + method: summary, operationId, parameters, requestBody, responses → Resolve $ref pointers (one level) 5. Store → API definition → D1 (apis table) → Raw spec JSON → R2 (specs bucket) → Extracted endpoints → D1 (endpoints table, batch insert)
## MCP Protocol The MCP server implements JSON-RPC 2.0 for AI agent integration. ### Methods
MethodDescription
initializeHandshake with protocol version (2024-11-05)
tools/listReturn 6 available tools with schemas
tools/callExecute a tool with parameters
### Tool Flow
AI Agent MCP Server Upstream API │ │ │ │ tools/call: api_call │ │ │ {connection_id, method, │ │ │ path} │ │ │ ─────────────────────────→ │ │ │ │ decrypt credentials │ │ │ build request │ │ │ ────────────────────────→│ │ │ │ │ │ ←──── response ────────│ │ │ │ │ ←── {status, body, │ │ │ duration_ms} │ │
## Security Model -
No plaintext credentials — AES-GCM-256 encrypted at rest, HKDF per-actor key derivation - Actor isolation — every query includes WHERE actor = ?, no cross-tenant access - Ed25519 auth — no passwords, challenge-response with public-key cryptography - Scoped API keys — restrict to read, write, proxy, or admin; set TTL and revoke - Header stripping — client Authorization/Cookie stripped before upstream; upstream Set-Cookie stripped before client - Audit logging — every proxy call logged with actor, method, status, duration (no body stored) - Rate limiting — D1-backed sliding window, fail-open design - CORS** — configurable, defaults to allow all origins ## Links - Developer Guide — Quickstart, code examples - API Reference — Full endpoint documentation - Marketplace — Browse popular APIs - MCP Tools — AI agent integration