Blame
|
1 | This page is part of the **wikibot.io PRD** (Product Requirements Document). See also: [[Design/Platform_Overview]], [[Design/Data_Model]], [[Design/Auth]], [[Design/Operations]]. |
||||||
|
2 | |||||||
| 3 | --- |
|||||||
| 4 | ||||||||
| 5 | ## Implementation Sequence |
|||||||
| 6 | ||||||||
|
7 | > **Superseded.** This page describes the AWS/WorkOS implementation phases and freemium pricing for wikibot.io. See [[Design/VPS_Architecture]] for the current plan (robot.wtf, free service, no billing). The API surface, frontend screens, and tier limit concepts are preserved here for reference if a commercial model is ever revisited. |
||||||
| 8 | ||||||||
|
9 | ### Phase 0: EFS + Lambda + Auth proof of concept |
||||||
| 10 | ||||||||
| 11 | Validate the two core technical risks: git on EFS via Lambda, and MCP OAuth via WorkOS. |
|||||||
| 12 | ||||||||
| 13 | **EFS + Lambda:** |
|||||||
| 14 | 1. Pulumi project scaffold (VPC, subnets, security groups, VPC endpoints for DynamoDB + S3) |
|||||||
| 15 | 2. EFS filesystem + Lambda with VPC config and EFS mount |
|||||||
| 16 | 3. X-Ray tracing enabled on Lambda and API Gateway |
|||||||
| 17 | 4. Create a bare git repo on EFS |
|||||||
| 18 | 5. Lambda function that mounts EFS, commits a file, reads it back |
|||||||
| 19 | 6. Measure via X-Ray: cold start latency (including VPC attach), git read latency, git write latency |
|||||||
| 20 | 7. Test concurrent reads and writes from multiple Lambda invocations |
|||||||
| 21 | 8. Set up AWS Budgets billing alarm ($50/mo threshold) |
|||||||
| 22 | ||||||||
| 23 | **WorkOS + MCP OAuth:** |
|||||||
| 24 | 9. Set up WorkOS AuthKit with Google OAuth (one provider is enough to validate) |
|||||||
| 25 | 10. Prototype FastMCP + WorkOS integration on Lambda — serve an MCP endpoint with OAuth 2.1 |
|||||||
| 26 | 11. Test Claude.ai connecting to the MCP endpoint via OAuth flow |
|||||||
| 27 | 12. Verify raw provider `sub` retrieval via WorkOS API (especially Apple — if available) |
|||||||
| 28 | ||||||||
| 29 | **Exit criteria**: |
|||||||
| 30 | - EFS: page read <500ms warm, page write <1s warm, cold start <5s total |
|||||||
| 31 | - MCP OAuth: Claude.ai can authenticate and call an MCP tool via WorkOS OAuth flow on Lambda |
|||||||
| 32 | ||||||||
| 33 | --- |
|||||||
| 34 | ||||||||
| 35 | ### FREE TIER (Phases 1–4) |
|||||||
| 36 | ||||||||
| 37 | ### Phase 1: Single-user serverless wiki |
|||||||
| 38 | ||||||||
| 39 | Port the existing stack to the chosen platform. No multi-tenancy yet — one user, one wiki, running serverless instead of a VPS. |
|||||||
| 40 | ||||||||
| 41 | 1. Pulumi project scaffold (dev stack, base resources) |
|||||||
| 42 | 2. Adapt Otterwiki for Lambda (Mangum adapter, EFS mount for repo storage) |
|||||||
| 43 | 3. Git storage on EFS (bare repos at /mnt/efs/{user}/{wiki}/repo.git) |
|||||||
| 44 | 4. Port REST API plugin (unchanged logic, new storage backend) |
|||||||
| 45 | 5. Port MCP server (Streamable HTTP instead of SSE) |
|||||||
| 46 | 6. Routing and TLS |
|||||||
| 47 | 7. Deploy and test end-to-end |
|||||||
| 48 | ||||||||
| 49 | ### Phase 2: Multi-tenancy and auth |
|||||||
| 50 | ||||||||
| 51 | 1. Auth provider setup (WorkOS AuthKit + FastMCP integration) |
|||||||
| 52 | 2. DynamoDB tables (Users, Wikis, ACLs) |
|||||||
| 53 | 3. Management API (create/list/delete wikis, token generation, ACLs) |
|||||||
| 54 | 4. Per-wiki routing and user namespace (`{username}.wikibot.io`) |
|||||||
| 55 | 5. ACL enforcement in middleware |
|||||||
| 56 | 6. Wiki bootstrap template (Home, Meta/Wiki Usage Guide, Meta/Page Template) |
|||||||
| 57 | 7. CLI tool for wiki management (`wiki create`, etc.) |
|||||||
| 58 | ||||||||
| 59 | ### Phase 3: Frontend |
|||||||
| 60 | ||||||||
| 61 | 1. SPA scaffold (auth flow, dashboard, wiki settings) |
|||||||
| 62 | 2. Static hosting (S3 + CloudFront) |
|||||||
| 63 | 3. MCP connection instructions page (copy-paste `claude mcp add` command) |
|||||||
| 64 | 4. Public wiki toggle |
|||||||
| 65 | ||||||||
| 66 | ### Phase 4: Git remote access and launch prep |
|||||||
| 67 | ||||||||
| 68 | 1. Hosted Git remote (read-only clone/pull for free tier) |
|||||||
| 69 | 2. Rate limiting |
|||||||
| 70 | 3. Monitoring and alerting (Pulumi-managed) |
|||||||
| 71 | 4. Backup strategy (AWS Backup for EFS, DynamoDB PITR) |
|||||||
| 72 | 5. Landing page and docs |
|||||||
| 73 | ||||||||
| 74 | **Free tier is shippable after Phase 4.** |
|||||||
| 75 | ||||||||
| 76 | --- |
|||||||
| 77 | ||||||||
| 78 | ### PREMIUM TIER (Phases 5+) |
|||||||
| 79 | ||||||||
| 80 | ### Phase 5: Stripe integration and premium gating |
|||||||
| 81 | ||||||||
| 82 | 1. Stripe subscription setup ($4.99/month) |
|||||||
|
83 | 2. Tier enforcement in middleware (wiki count, author count per wiki) |
||||||
|
84 | 3. Upgrade/downgrade flows in frontend |
||||||
| 85 | 4. Webhook handling for subscription lifecycle |
|||||||
| 86 | ||||||||
| 87 | ### Phase 6: Semantic search |
|||||||
| 88 | ||||||||
|
89 | 1. ReindexQueue DynamoDB table with Streams enabled |
||||||
| 90 | 2. Embedding Lambda (VPC+EFS, container image with all-MiniLM-L6-v2) |
|||||||
| 91 | 3. DynamoDB Streams → Lambda event source mapping |
|||||||
| 92 | 4. DynamoDB write on page save in wiki Lambda |
|||||||
| 93 | 5. FAISS index build on EFS (384-dim MiniLM vectors) |
|||||||
| 94 | 6. Wire into MCP and API handlers |
|||||||
| 95 | 7. Available to all users (not tier-gated) |
|||||||
| 96 | ||||||||
| 97 | See [[Design/Async_Embedding_Pipeline]] for full architecture. |
|||||||
|
98 | |||||||
|
99 | ### Phase 7: Deferred features (build when there's demand) |
||||||
| 100 | ||||||||
| 101 | Not scheduled. Build these when users ask for them, not before. |
|||||||
|
102 | |||||||
| 103 | 1. Read/write Git remote access (push/pull) |
|||||||
| 104 | 2. External Git sync (bidirectional, scheduled) |
|||||||
| 105 | 3. Custom domains (TLS cert provisioning, DNS validation) |
|||||||
| 106 | 4. Custom wiki styling (CSS upload/editor) |
|||||||
| 107 | 5. Create wiki from remote template repo |
|||||||
| 108 | ||||||||
| 109 | --- |
|||||||
| 110 | ||||||||
| 111 | ## Frontend |
|||||||
| 112 | ||||||||
| 113 | ### Technology |
|||||||
| 114 | ||||||||
| 115 | Static SPA (React or Svelte) deployed to S3 + CloudFront. Communicates with backend via API Gateway. |
|||||||
| 116 | ||||||||
| 117 | ### Screens |
|||||||
| 118 | ||||||||
| 119 | **Public:** |
|||||||
| 120 | - Landing / marketing page |
|||||||
| 121 | - Login / signup (OAuth provider selection: Google, GitHub, Microsoft, Apple) |
|||||||
| 122 | ||||||||
| 123 | **Authenticated user:** |
|||||||
| 124 | - Dashboard: list of my wikis, create new wiki button |
|||||||
| 125 | - Wiki settings: rename, regenerate MCP token, manage collaborators, connect external Git remote, delete |
|||||||
| 126 | - MCP connection instructions: copy-paste `claude mcp add` command with token |
|||||||
| 127 | ||||||||
| 128 | **Admin (stretch):** |
|||||||
| 129 | - User list, usage metrics, tier management |
|||||||
| 130 | ||||||||
| 131 | ### MVP scope |
|||||||
| 132 | ||||||||
| 133 | The frontend can start as a CLI tool (`wiki create`, `wiki list`, `wiki token`, `wiki grant`) that calls the management API directly. Build the SPA when the workflow is validated. |
|||||||
| 134 | ||||||||
| 135 | --- |
|||||||
| 136 | ||||||||
| 137 | ## API Surface |
|||||||
| 138 | ||||||||
| 139 | ### Management API (new) |
|||||||
| 140 | ||||||||
| 141 | | Method | Endpoint | Description | |
|||||||
| 142 | |--------|----------|-------------| |
|||||||
| 143 | | `POST` | `/admin/wikis` | Create a wiki. Body: `{slug, display_name}`. Initializes bare repo on EFS, creates DynamoDB records. Returns MCP token (shown once). | |
|||||||
| 144 | | `GET` | `/admin/wikis` | List caller's wikis. Returns array of `{slug, display_name, page_count, last_accessed}`. | |
|||||||
| 145 | | `GET` | `/admin/wikis/{slug}` | Wiki details including MCP endpoint URL and connection instructions. | |
|||||||
| 146 | | `DELETE` | `/admin/wikis/{slug}` | Delete wiki (EFS repo, DynamoDB records, FAISS index). Requires confirmation. | |
|||||||
| 147 | | `POST` | `/admin/wikis/{slug}/token` | Regenerate MCP bearer token. Invalidates old token. Returns new token (shown once). | |
|||||||
| 148 | | `POST` | `/admin/wikis/{slug}/acl` | Grant access. Body: `{email, role}`. Looks up user by email in DynamoDB. | |
|||||||
| 149 | | `DELETE` | `/admin/wikis/{slug}/acl/{user_sub}` | Revoke access. | |
|||||||
| 150 | | `GET` | `/admin/wikis/{slug}/acl` | List access grants. | |
|||||||
| 151 | ||||||||
| 152 | ### Wiki API (existing, adapted) |
|||||||
| 153 | ||||||||
|
154 | Same endpoints as the existing `otterwiki-api`, but scoped under `/{user}/{wiki}/api/v1/`. Authentication via OAuth JWT or MCP bearer token instead of a single API key. Includes full-text search and semantic search. |
||||||
|
155 | |||||||
| 156 | ### MCP endpoint (existing, adapted) |
|||||||
| 157 | ||||||||
| 158 | Same tools as the existing `otterwiki-mcp`, exposed at `/{user}/{wiki}/mcp`. Authentication via bearer token or OAuth. |
|||||||
| 159 | ||||||||
| 160 | --- |
|||||||
| 161 | ||||||||
| 162 | ## Freemium Tiers |
|||||||
| 163 | ||||||||
|
164 | The premium tier is about **scale**, not features. Free users get a complete, fully-featured wiki. Premium unlocks multiple wikis and collaboration. |
||||||
| 165 | ||||||||
|
166 | | Feature | Free | Premium | |
||||||
| 167 | |---------|------|---------| |
|||||||
|
168 | | Wikis | 1 | 12 | |
||||||
| 169 | | Authors per wiki | 1 | 25 | |
|||||||
|
170 | | Pages per wiki | 500 | Unlimited | |
||||||
|
171 | | Full-text search | Yes | Yes | |
||||||
| 172 | | Semantic search | Yes (MiniLM + FAISS) | Yes | |
|||||||
|
173 | | Git remote access | Read-only (clone/pull) | Read-only (clone/pull) | |
||||||
|
174 | | Public read-only access | Yes (optional per wiki) | Yes (optional per wiki) | |
||||||
| 175 | | MCP access | Yes | Yes | |
|||||||
| 176 | | Web UI | Yes | Yes | |
|||||||
|
177 | | REST API access | Yes | Yes | |
||||||
|
178 | | Attachment storage | 50MB total | 1GB total | |
||||||
| 179 | | Max attachment size | 5MB | 25MB | |
|||||||
|
180 | |||||||
| 181 | ### Deferred features (build when there's demand) |
|||||||
| 182 | ||||||||
| 183 | These were originally planned as premium differentiators but don't fit the "scale, not features" model. Defer until users ask for them: |
|||||||
| 184 | ||||||||
| 185 | - Read/write Git remote access (push/pull) |
|||||||
| 186 | - External Git sync (bidirectional, GitHub/GitLab) |
|||||||
| 187 | - Custom domains (CNAME + TLS provisioning) |
|||||||
| 188 | - Custom wiki styling (CSS) |
|||||||
| 189 | - Create wiki from template repo |
|||||||
|
190 | |||||||
|
191 | ### Pricing (undecided — two options) |
||||||
|
192 | |||||||
|
193 | AWS costs per user are near-zero regardless of usage. Margins are essentially 100% minus Stripe's cut under either model. The pricing decision is about conversion, simplicity, and what signal we want to send — not about covering costs. |
||||||
| 194 | ||||||||
| 195 | **Option A: Flat tier — $4.99/month** |
|||||||
| 196 | ||||||||
| 197 | One price, one upgrade. Free users get 1 wiki and 1 author. Paying users get 12 wikis and 25 authors per wiki. Annual option: $49/year (~2 months free). |
|||||||
| 198 | ||||||||
| 199 | Pros: simple Stripe integration (one subscription plan), higher ARPU per paying user, Stripe's per-transaction fee ($0.30 + 2.9%) is a smaller percentage of the charge. Comparable to Obsidian Sync ($5/month) and well under Notion Plus ($10/user/month). |
|||||||
| 200 | ||||||||
| 201 | Cons: the jump from $0 to $5 is a real psychological barrier. Users who only want a second wiki are paying for 12 wikis and 25 collaborators they don't need. "Premium tier" language and comparison tables add friction. |
|||||||
| 202 | ||||||||
| 203 | **Option B: Per-wiki — $1/month per additional wiki** |
|||||||
| 204 | ||||||||
| 205 | No tiers. One free wiki per account. Every additional wiki costs $1/month. Collaborators are unlimited (or generous — e.g., 25 per wiki for everyone). Bill monthly in aggregate. |
|||||||
| 206 | ||||||||
| 207 | Pros: the upgrade decision is tiny ("add a wiki for a dollar"). No tier concept, no feature gating, no comparison tables. The pitch fits on a button: "One wiki free. Extra wikis, a dollar a month each." Conversion rate from free to paid should be higher because the barrier is lower. Pricing scales linearly with value received. |
|||||||
| 208 | ||||||||
| 209 | Cons: lower ARPU — a typical researcher with 2–3 projects pays $2–3/month instead of $5. Stripe's per-transaction fee hurts more on small charges (on a $2 charge, Stripe takes ~18%; on $5, it's ~9%). Slightly more billing complexity (metered/usage-based Stripe integration vs. simple subscription). Revenue from a 25-person team using one wiki: $0. |
|||||||
| 210 | ||||||||
| 211 | **Competitive context (March 2026):** |
|||||||
| 212 | ||||||||
| 213 | The market doesn't have a direct comparable — no one offers a hosted, git-backed, MCP-native research wiki as a service. The closest reference points are adjacent products: Obsidian (free local app, $5/month sync, $10/month publish, $50/year commercial), Notion ($10/user/month for teams), Roam Research ($15/month), and self-hosted options like Docmost (free, but you run it yourself). Wikibot.io's differentiator is zero-setup MCP integration with semantic search — a combination none of these offer. |
|||||||
| 214 | ||||||||
| 215 | **Decision needed before Phase 5.** Either model works with the current architecture. The data model supports both (wiki count is already tracked). Phase 5 implementation differs slightly: Option A is a simple Stripe subscription; Option B is usage-based billing with monthly aggregation. |
|||||||
|
216 | |||||||
|
217 | ### Paid wiki perks |
||||||
| 218 | ||||||||
| 219 | Paid wikis get a custom slug: `{slug}.wikibot.io` (e.g., `third-gulf-war.wikibot.io`). The free wiki lives under the user's namespace (`{username}.wikibot.io/{wiki}`). This is a nice vanity benefit that costs nothing to implement — it's just a routing rule. |
|||||||
| 220 | ||||||||
| 221 | ### Lapse policy |
|||||||
| 222 | ||||||||
| 223 | If a paid wiki's payment lapses (subscription canceled, card declined, etc.), the wiki becomes **read-only with MCP disabled**. The web UI still works for reading. Git clone still works. But no writes via any path (web UI, API, MCP) and the MCP endpoint returns 402. The data is preserved indefinitely — the user can resume paying at any time to restore full access, or git clone their data out for free. |
|||||||
| 224 | ||||||||
| 225 | This is deliberately non-hostile: the user's data is never deleted or held hostage. But the wiki stops being a living workspace, which is the thing they're paying for. |
|||||||
| 226 | ||||||||
|
227 | ### Enforcement |
||||||
| 228 | ||||||||
|
229 | Enforced in the Lambda middleware before any operation: |
||||||
| 230 | - Wiki creation: check wiki count against limit (1 free, additional wikis require payment) |
|||||||
| 231 | - Write operations: check wiki payment status (lapsed → reject with 402) |
|||||||
| 232 | - MCP connections: check wiki payment status (lapsed → reject with 402) |
|||||||
| 233 | - Page creation: check page count against limit |
|||||||
| 234 | - ACL grants: check collaborator count against limit |
|||||||