This page is part of the wikibot.io PRD (Product Requirements Document). See also: Design/Data Model, Design/Auth, Design/Implementation Phases, Design/PRD Operations.


PRD/TRD: Serverless Wiki-as-a-Service Platform

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.

The platform is a freemium service:

  • Free tier: 1 wiki, full read/write/MCP access, no semantic search
  • Premium tier: Multiple wikis, semantic search (Bedrock embeddings + FAISS), 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.

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

Prior art

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.


Architecture

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.

┌──────────────────────────────────────────────────────────────────────┐
│  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, trigger reindex if premium               │
└──────────┬──────────────┬───────────────────┬────────────────────────┘
           │              │                   │
     ┌─────▼─────┐ ┌─────▼──────┐  ┌────────▼─────────┐
     │  EFS      │ │  DynamoDB  │  │  Bedrock           │
     │           │ │            │  │  titan-embed-v2    │
     │  Git repos│ │  Users     │  │  (premium only)    │
     │  FAISS    │ │  Wikis     │  │                    │
     │  indexes  │ │  ACLs      │  └────────────────────┘
     └───────────┘ └────────────┘

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 (premium) EFS
Metadata Users, wikis, ACLs DynamoDB
Secrets API keys, auth provider secrets, Git creds Env vars (dev), Secrets Manager (prod)
Embeddings Semantic search (premium) Bedrock titan-embed-text-v2
Frontend Static SPA S3 + CloudFront
Async jobs Reindex on write (premium) SQS + 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).

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