Commit b734e3

2026-03-20 19:52:37 Claude (MCP): [mcp] Rewrite Platform_Overview for VPS deployment; archive AWS version
Design/Platform_Overview.md ..
@@ 1,111 1,76 @@
- This page is part of the **wikibot.io PRD** (Product Requirements Document). See also: [[Design/Data_Model]], [[Design/Auth]], [[Design/Implementation_Phases]], [[Design/Operations]].
-
+ ---
+ status: current
+ platform: robot.wtf
---
- # PRD/TRD: Serverless Wiki-as-a-Service Platform
+ > Extracted from the original wikibot.io design. AWS-specific content archived at [[Archive/AWS_Design/Platform_Overview]].
- > **Superseded.** This page describes the AWS serverless architecture for wikibot.io. The project has pivoted to a VPS deployment as robot.wtf with ATProto auth. See [[Design/VPS_Architecture]] for the current plan. This page is preserved as an archive — the application logic (ACL model, middleware, MCP tools) carries forward; the AWS infrastructure design does not.
+ See also: [[Design/Data_Model]], [[Design/Auth]], [[Design/VPS_Architecture]], [[Design/Operations]].
+
+ ---
+
+ # Platform Overview: robot.wtf
## Overview
- A multi-tenant, serverless platform that lets users create and manage private research wikis — each backed by its own Git repo and exposed via its own MCP endpoint. Built on AWS (Lambda + EFS + DynamoDB + API Gateway) with near-zero cost at rest. Based on the Otterwiki + semantic search + MCP stack already built for the Third Gulf War project. Product name: **wikibot.io**.
+ A multi-tenant platform that lets users create and manage private research wikis — each backed by its own Git repo and exposed via its own MCP endpoint. Based on the Otterwiki + semantic search + MCP stack built for the Third Gulf War project.
The platform is a freemium service:
- **Free tier**: 1 wiki, 1 author, full read/write/MCP access, semantic search included
- **Premium tier**: Multiple wikis (up to 12), multiple authors (up to 25 per wiki), external Git sync
- ---
-
## Context
### Why this exists
- Setting up a research wiki with MCP integration currently requires: forking Otterwiki, writing API and semantic search plugins, deploying an MCP server, configuring reverse proxy + TLS + auth, and wiring it all together. This took weeks of work. The resulting system is useful enough that it should be productized — but the per-instance infrastructure cost and setup complexity make it impractical to self-host for casual use.
-
- A serverless architecture solves both problems: zero cost when idle (no VPS bill for abandoned wikis), and the setup complexity is absorbed by the platform.
+ Setting up a research wiki with MCP integration currently requires: forking Otterwiki, writing API and semantic search plugins, deploying an MCP server, configuring reverse proxy + TLS + auth, and wiring it all together. This took weeks of work. The resulting system is useful enough that it should be productized — but the per-instance infrastructure cost and setup complexity make it impractical to self-host for casual use. The platform absorbs that setup complexity.
### Key users
- **Researcher** — creates wikis, writes/reads notes via MCP from Claude.ai or Claude Code, browses via web UI
- - **Admin** (initially: just us) — manages user accounts, monitors usage, handles billing tier changes
+ - **Admin** — manages user accounts, monitors usage, handles billing tier changes
- ### Prior art
+ ## Multi-Tenancy Model
- The existing single-tenant system (documented in `otterwiki-research-wiki-prd.md`) proves the core workflow. This PRD describes the multi-tenant wrapper around it.
+ Each user owns zero or more wikis. Each wiki has its own:
- ---
+ - Git bare repo (filesystem)
+ - FAISS vector index (filesystem)
+ - ACL entries (database)
- ## Architecture
+ Isolation is at the filesystem path level: `{data_dir}/{user}/{wiki}/`.
- AWS Lambda + EFS + DynamoDB + API Gateway + CloudFront. EFS eliminates the git-on-S3 clone/push cycle — git repos live on a persistent NFS filesystem that Lambda mounts directly.
+ ## Routing
```
- ┌──────────────────────────────────────────────────────────────────────┐
- │ Clients │
- │ │
- │ Claude.ai ──── MCP (Streamable HTTP) ──────┐ │
- │ Claude Code ── MCP (Streamable HTTP) ──────┤ │
- │ Any MCP client ─ MCP (Streamable HTTP) ────┤ │
- │ Browser ────── HTTPS ──────────────────────┤ │
- │ Git CLI ────── HTTPS (smart HTTP) ─────────┤ │
- │ CLI ────────── HTTPS ──────────────────────┤ │
- └─────────────────────────────────────────────┼────────────────────────┘
-
- ┌─────────────────────────────────────────────▼────────────────────────┐
- │ Edge / Routing │
- │ │
- │ {user}.wikibot.io/{wiki}/mcp → Compute (MCP handler) │
- │ {user}.wikibot.io/{wiki}/api/* → Compute (REST API handler) │
- │ {user}.wikibot.io/{wiki}/ → Compute (Otterwiki Flask) │
- │ {user}.wikibot.io/{wiki}.git/* → Compute (Git smart HTTP) │
- │ wikibot.io/auth/* → Compute (OAuth flows) │
- │ wikibot.io/admin/* → Compute (management API) │
- │ wikibot.io/ → Static (SPA) │
- │ │
- │ OAuth JWT validation on all routes except /auth/* and public wikis │
- └─────────────────────────────────────────────┬────────────────────────┘
-
- ┌─────────────────────────────────────────────▼────────────────────────┐
- │ Compute (scale-to-zero) │
- │ │
- │ 1. Resolve user + wiki from hostname + path │
- │ 2. Check ACL in DynamoDB │
- │ 3. Access git repo on EFS (/mnt/efs/{user}/{wiki}/repo.git) │
- │ 4. Route to appropriate handler: │
- │ - MCP: FastMCP Streamable HTTP handler │
- │ - API: REST endpoints (same as existing otterwiki-api) │
- │ - Web: Otterwiki Flask app │
- │ - Git: Smart HTTP protocol (dulwich) │
- │ 5. On write: persist repo, write reindex record to DynamoDB │
- └──────────┬──────────────┬────────────────────────────────────────────┘
- │ │
- ┌─────▼─────┐ ┌─────▼──────┐
- │ EFS │ │ DynamoDB │
- │ │ │ │
- │ Git repos│ │ Users │───── DynamoDB Streams
- │ FAISS │ │ Wikis │ │
- │ indexes │ │ ACLs │ ▼
- └───────────┘ │ Reindex Q │ Embedding Lambda (VPC+EFS)
- └────────────┘ MiniLM (local, no Bedrock)
+ {user}.robot.wtf/{wiki}/mcp → MCP handler (Streamable HTTP)
+ {user}.robot.wtf/{wiki}/api/* → REST API handler
+ {user}.robot.wtf/{wiki}/ → Otterwiki Flask app (web UI)
+ {user}.robot.wtf/{wiki}.git/* → Git smart HTTP (dulwich)
+ robot.wtf/auth/* → OAuth / ATProto auth flows
+ robot.wtf/admin/* → Management API
+ robot.wtf/ → Landing page
```
- ### Component inventory
-
- | Component | Purpose | AWS Service |
- |-----------|---------|-------------|
- | Routing / TLS | Request routing, cert management | API Gateway + CloudFront + ACM |
- | Edge security (post-launch) | Rate limiting, bot control, OWASP rules | WAF (on API Gateway + CloudFront) |
- | Auth | OAuth (Google, GitHub, Microsoft, Apple) | WorkOS AuthKit (recommended) |
- | Compute | Application logic, scale-to-zero | Lambda (VPC, Mangum adapter) |
- | Git storage | Bare git repos | EFS (mounted by Lambda) |
- | Vector indexes | FAISS files | EFS |
- | Metadata | Users, wikis, ACLs, reindex queue | DynamoDB |
- | Secrets | API keys, auth provider secrets, Git creds | Env vars (dev), Secrets Manager (prod) |
- | Embeddings | Semantic search | all-MiniLM-L6-v2 (runs locally on Lambda) |
- | Frontend | Static SPA | S3 + CloudFront |
- | Async jobs | Reindex on write | DynamoDB Streams → Lambda |
- | Scheduled tasks | Git sync, cleanup jobs | EventBridge Scheduler |
- | Tracing | Request latency, per-service breakdown | X-Ray |
-
- For a user with one 200-page wiki that's idle: effectively $0/month (a few KB of DynamoDB, a few MB on EFS Infrequent Access at $0.016/GB/month).
\ No newline at end of file
+ Auth token validation on all routes except `/auth/*` and public wikis.
+
+ ## Application Logic
+
+ Request handling follows this sequence:
+
+ 1. Resolve user + wiki from hostname + path
+ 2. Check ACL (database lookup)
+ 3. Access git repo on disk
+ 4. Route to handler:
+ - **MCP**: FastMCP Streamable HTTP handler
+ - **API**: REST endpoints (otterwiki-api)
+ - **Web**: Otterwiki Flask app
+ - **Git**: Smart HTTP protocol (dulwich)
+ 5. On write: persist repo, queue reindex
+
+ ## Semantic Search
+
+ - **Model**: all-MiniLM-L6-v2 (runs locally, no external API calls)
+ - **Index**: FAISS, one index per wiki, stored alongside the git repo
+ - **Reindex**: triggered on write (async)
\ No newline at end of file
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9