Blame

34510b Claude (MCP) 2026-03-15 01:39:13
[mcp] Add VPS implementation phases (V0-V7) with dev.robot.wtf migration"
1
---
2
category: reference
3
tags: [design, tasks, phases, vps]
351d75 Claude (MCP) 2026-03-15 07:36:32
[mcp] Add completion status markers to VPS phase headings (2026-03-15)
4
last_updated: 2026-03-15
34510b Claude (MCP) 2026-03-15 01:39:13
[mcp] Add VPS implementation phases (V0-V7) with dev.robot.wtf migration"
5
confidence: medium
6
---
7
8
# VPS Implementation Phases
9
10
Implementation sequence for robot.wtf on the Debian 12 / Proxmox VM. Phase designations prefixed with **V** to distinguish from the archived AWS phases (P0–P4).
11
c71840 Claude (MCP) 2026-03-15 02:43:01
[mcp] Rewrite VPS phases: add VS (auth spikes) phase, renumber dependency graph
12
See [[Design/VPS_Architecture]] for the architecture these phases build toward. See [[Dev/V3_V5_Risk_Research]] for the auth risk assessment informing the spike phase.
34510b Claude (MCP) 2026-03-15 01:39:13
[mcp] Add VPS implementation phases (V0-V7) with dev.robot.wtf migration"
13
14
---
15
16
## What we're starting with
17
18
Phases 1 and 2 of the AWS build produced working, tested components:
19
20
- **TenantResolver WSGI middleware** — resolves slug from Host header, authenticates (JWT or bearer token), checks ACL, sets Otterwiki proxy headers, swaps per-wiki config. Currently wraps DynamoDB calls. (P2-5b-7)
21
- **ManagementMiddleware** — wiki CRUD, ACL management, bearer token generation. WSGI middleware over DynamoDB. (P2-4)
22
- **Auth middleware** — platform JWT (RS256) validation and user resolution. (P2-2)
23
- **ACL enforcement** — role-to-permission mapping, public wiki handling. (P2-3)
24
- **Wiki bootstrap template** — parameterized starter pages. (P2-6)
25
- **Admin panel hiding** — PLATFORM_MODE flag hides conflicting Otterwiki admin sections. (P2-8)
26
- **MCP server** — 12 tools, Streamable HTTP, bearer token auth. Working on Lambda.
27
- **REST API plugin** — full CRUD, search, semantic search, history, links.
28
- **Semantic search** — FAISS + MiniLM, chunking, embedding, deduplication.
29
- **Otterwiki fork** — PROXY_HEADER auth mode, all plugins installed.
30
- **E2E test suite** — 17 tests covering cross-path (API↔MCP) operations.
31
32
The port is primarily: DynamoDB → SQLite, EFS paths → local disk paths, Mangum wrapper → Gunicorn, WorkOS → ATProto OAuth.
33
34
---
35
351d75 Claude (MCP) 2026-03-15 07:36:32
[mcp] Add completion status markers to VPS phase headings (2026-03-15)
36
## V0: VM Infrastructure — COMPLETE
37
38
**Status:** Complete as of 2026-03-15. Ansible-provisioned VM is live, Caddy serving valid TLS on bare domain and wildcard subdomains.
34510b Claude (MCP) 2026-03-15 01:39:13
[mcp] Add VPS implementation phases (V0-V7) with dev.robot.wtf migration"
39
40
**Goal:** Ansible-provisioned Debian 12 VM with Caddy serving valid TLS on bare domain and wildcard.
41
42
**Tasks:**
43
44
- V0-1: Ansible playbook for base VM provisioning (Python 3.11+, git, build-essential, common tools)
45
- V0-2: Install Caddy with DNS challenge plugin (Cloudflare, Route 53, or OVHcloud — depends on where robot.wtf zone is hosted)
46
- V0-3: Configure DNS: `robot.wtf` A record + `*.robot.wtf` A record → VM static IP
47
- V0-4: Caddyfile with wildcard TLS via DNS challenge. Bare domain serves a static placeholder page. Wildcard subdomains serve a placeholder.
48
- V0-5: Generate RS256 signing keypair for platform JWTs (`/srv/data/signing_key.pem`, `/srv/data/signing_key.pub`)
49
- V0-6: Generate ATProto OAuth confidential client JWK (`/srv/data/client_jwk.json`)
50
- V0-7: Create `/srv` directory structure per [[Design/VPS_Architecture]] storage layout
51
- V0-8: Initialize SQLite database with schema from [[Design/VPS_Architecture]]
52
53
**Exit criteria:**
54
- `https://robot.wtf` serves HTTPS with valid cert
55
- `https://anything.robot.wtf` serves HTTPS with valid wildcard cert
56
- Ansible playbook is idempotent (can re-run without breaking things)
57
- SQLite database exists with empty tables
58
59
---
60
c71840 Claude (MCP) 2026-03-15 02:43:01
[mcp] Rewrite VPS phases: add VS (auth spikes) phase, renumber dependency graph
61
## VS: Auth Spikes
62
63
**Goal:** Validate both auth flows empirically before building the real thing. Kill unknowns early.
64
65
These are throwaway prototypes, not production code. The point is to prove the protocol flows work against real counterparts (bsky.social PDS, Claude.ai MCP client) so that V3 and V5 are pure implementation, not discovery.
66
351d75 Claude (MCP) 2026-03-15 07:36:32
[mcp] Add completion status markers to VPS phase headings (2026-03-15)
67
### VS-1: ATProto OAuth Spike — COMPLETE
68
69
**Status:** Complete as of 2026-03-15. Full ATProto OAuth flow validated end-to-end on robot.wtf.
c71840 Claude (MCP) 2026-03-15 02:43:01
[mcp] Rewrite VPS phases: add VS (auth spikes) phase, renumber dependency graph
70
71
Deploy the Bluesky cookbook Flask demo (`bluesky-social/cookbook/python-oauth-web-app`) directly on the VM behind Caddy. Minimal adaptation — just enough to run it at `robot.wtf/auth/` with the robot.wtf client JWK.
72
73
**Tasks:**
74
75
- VS-1a: Clone the cookbook demo, install deps, configure Caddy to proxy `robot.wtf/auth/*` to the demo on a local port.
76
- VS-1b: Publish client metadata at `https://robot.wtf/auth/client-metadata.json` with scope `"atproto"` (identity-only) and redirect URI `https://robot.wtf/auth/oauth/callback`.
77
- VS-1c: Log in with a real Bluesky account. Walk through the full flow: handle entry → PDS redirect → approve → callback → token → DID.
78
- VS-1d: Test with a non-bsky.social PDS if one is accessible (e.g., a self-hosted PDS on the ATProto community server). This validates that the flow isn't accidentally Bluesky-specific.
79
- VS-1e: Document what worked, what didn't, any PDS quirks encountered.
80
81
**Exit criteria:**
82
- A real Bluesky login completes end-to-end on robot.wtf
83
- The DID and handle are retrieved from the token response
84
- DPoP nonce handling works without manual intervention
85
- Findings documented in a Dev summary page
86
87
**Expected time:** Half a day. The demo is ready to run.
88
351d75 Claude (MCP) 2026-03-15 07:36:32
[mcp] Add completion status markers to VPS phase headings (2026-03-15)
89
### VS-2: MCP OAuth AS Stub — COMPLETE
90
91
**Status:** Complete as of 2026-03-15. Persistent SQLite OAuth provider deployed; Claude.ai OAuth flow validated end-to-end.
c71840 Claude (MCP) 2026-03-15 02:43:01
[mcp] Rewrite VPS phases: add VS (auth spikes) phase, renumber dependency graph
92
93
Build a minimal, hard-coded OAuth 2.1 AS that implements the five endpoints Claude.ai needs. No real auth, no database, no ATProto — just the protocol surface with canned responses. Deploy behind Caddy and point Claude.ai at it.
94
95
**Tasks:**
96
97
- VS-2a: Implement the stub AS as a single Flask file (~150 lines):
98
- `GET /.well-known/oauth-authorization-server` → static JSON metadata
99
- `POST /auth/oauth/register` → accept any DCR request, return a `client_id` + `client_secret`
100
- `GET /auth/oauth/authorize` → auto-approve (no consent UI), redirect with auth code
101
- `POST /auth/oauth/token` → exchange code for a JWT access token (hard-coded claims)
102
- `GET /.well-known/jwks.json` → serve the RS256 public key
103
- VS-2b: Implement the protected resource metadata on a wiki subdomain:
104
- `GET https://{slug}.robot.wtf/.well-known/oauth-protected-resource` → point to robot.wtf AS
105
- VS-2c: Deploy a minimal MCP endpoint (FastMCP with one dummy tool, e.g., `echo`) behind the protected resource metadata. Wire it to return 401 with `WWW-Authenticate` header on unauthenticated requests, and accept the stub JWT on authenticated requests.
106
- VS-2d: Add the MCP URL in Claude.ai settings. Walk through the flow: Claude.ai discovers AS → registers → redirects to authorize → gets token → calls the echo tool.
107
- VS-2e: If it fails, inspect what Claude.ai actually sent (log all requests) and iterate. Document the exact request shapes, headers, and timing.
108
- VS-2f: Test the same flow with Claude Code (`claude mcp add --transport http`) to verify OAuth discovery works there too.
109
110
**Exit criteria:**
111
- Claude.ai completes the MCP OAuth flow against the stub and successfully calls a tool
112
- OR: documented exactly where/why Claude.ai's client diverges from the spec, with a plan to accommodate
113
- Claude Code OAuth discovery tested
114
- Findings documented in a Dev summary page
115
116
**Expected time:** 1–2 days, mostly debugging Claude.ai's behavior.
117
118
### Why spike before building
119
120
The research ([[Dev/V3_V5_Risk_Research]]) assessed V3 as low risk and V5 as medium risk, but both assessments are based on documentation and code reading, not empirical testing. The spikes turn "should work" into "does work" for a cost of ~2 days, before committing to the full implementation in V3 and V5. If either spike reveals a fundamental incompatibility, we find out before building the real system, not after.
121
122
---
123
351d75 Claude (MCP) 2026-03-15 07:36:32
[mcp] Add completion status markers to VPS phase headings (2026-03-15)
124
## V1: Otterwiki on Caddy — COMPLETE
125
126
**Status:** Complete as of 2026-03-15. Single Otterwiki instance running behind Gunicorn/Caddy with multi-tenant slug routing operational.
34510b Claude (MCP) 2026-03-15 01:39:13
[mcp] Add VPS implementation phases (V0-V7) with dev.robot.wtf migration"
127
128
**Goal:** Single Otterwiki instance running behind Gunicorn behind Caddy, with multi-tenant slug-based routing on wildcard subdomains. No auth yet — test users hardcoded in SQLite.
129
130
**Tasks:**
131
132
- V1-1: Port TenantResolver from DynamoDB to SQLite. Replace `UserModel.get()`, `WikiModel.get()`, `AclModel.query()` with SQLite queries. The WSGI middleware structure, proxy header injection, and config-swapping logic stay unchanged.
133
- V1-2: Port data access layer. Create a thin `db.py` module that wraps SQLite (or SQLAlchemy if preferred). Same interface as the DynamoDB models but backed by SQLite.
134
- V1-3: Gunicorn configuration. Otterwiki Flask app wrapped in TenantResolver, served by Gunicorn on port 8000. Multiple workers (sized to VM CPU cores).
135
- V1-4: Caddy routing for wiki subdomains. `*.robot.wtf` routes to Gunicorn on port 8000. Caddy handles TLS, Gunicorn handles WSGI.
136
- V1-5: Manual smoke test. Insert a test user and wiki directly into SQLite. `git init --bare /srv/wikis/testuser/repo.git`. Commit a Home page. Verify `https://testuser.robot.wtf` serves the wiki.
137
138
**Exit criteria:**
139
- Browsing, editing, and saving wiki pages works at `{slug}.robot.wtf`
140
- Gunicorn stays up, serves multiple requests, workers don't crash
141
- Config-swap per request works (if multiple test wikis exist, each resolves correctly)
142
143
---
144
351d75 Claude (MCP) 2026-03-15 07:36:32
[mcp] Add completion status markers to VPS phase headings (2026-03-15)
145
## V2: Migrate dev.wikibot.io → dev.robot.wtf — PARTIAL
146
147
**Status:** Partial as of 2026-03-15. Dev wiki (this wiki) migrated to dev.robot.wtf. The Third Gulf War wiki (3gw.robot.wtf / 3gw.robot.wtf) remains on the home server via DNS CNAME exception and has not been migrated.
34510b Claude (MCP) 2026-03-15 01:39:13
[mcp] Add VPS implementation phases (V0-V7) with dev.robot.wtf migration"
148
149
**Goal:** The existing development wiki (Third Gulf War research + this dev wiki) running on the VPS under robot.wtf, proving the full Otterwiki stack works in the new environment with real data.
150
151
**Tasks:**
152
153
- V2-1: Export git repos from the existing AWS deployment. `git clone --bare` from the EFS-backed repos (or from the dev.wikibot.io git remote if accessible). Copy to `/srv/wikis/` on the VM.
154
- V2-2: Create corresponding user and wiki records in SQLite. The existing deployment uses UUIDs and DynamoDB; the VPS uses DIDs and SQLite. For the dev migration, create placeholder user records (the owner's DID can be updated once ATProto auth is wired in V3).
155
- V2-3: Rebuild FAISS indexes from the migrated repos. Run the existing embedding code against the local repos with MiniLM.
156
- V2-4: Wire up the MCP server (FastMCP sidecar on port 8001) with bearer token auth against SQLite. Generate new bearer tokens for the migrated wikis.
157
- V2-5: Configure Caddy to route MCP traffic (`{slug}.robot.wtf/mcp`) to port 8001.
158
- V2-6: Verify end-to-end: browse the wiki in a browser, connect Claude Code via MCP bearer token, run a few tool calls.
159
- V2-7: Update MCP connection config in Claude.ai / Claude Code to point at `dev.robot.wtf` instead of `dev.wikibot.io`.
160
161
**Exit criteria:**
162
- The Third Gulf War wiki is browsable at its new robot.wtf subdomain
163
- This dev wiki is browsable at its new robot.wtf subdomain
164
- MCP tools work against the migrated wikis via Claude Code (bearer token)
165
- Semantic search returns results from the migrated FAISS indexes
166
- The old AWS deployment can be left running in parallel until confidence is high, then decommissioned
167
168
**Note:** Auth at this point is still placeholder/hardcoded. The migrated wikis use bearer tokens for MCP and don't require browser login (the wiki owner can browse without auth during this phase, or auth can be faked via a test JWT). Real ATProto auth comes in V3.
169
170
---
171
351d75 Claude (MCP) 2026-03-15 07:36:32
[mcp] Add completion status markers to VPS phase headings (2026-03-15)
172
## V3: ATProto OAuth (Browser Login) — COMPLETE
173
174
**Status:** Complete as of 2026-03-15. Production auth service live with full signup flow; real Bluesky users can sign in and create accounts.
34510b Claude (MCP) 2026-03-15 01:39:13
[mcp] Add VPS implementation phases (V0-V7) with dev.robot.wtf migration"
175
176
**Goal:** Real users can sign in with their Bluesky handle and get a platform JWT.
177
c71840 Claude (MCP) 2026-03-15 02:43:01
[mcp] Rewrite VPS phases: add VS (auth spikes) phase, renumber dependency graph
178
VS-1 proved the flow works. This phase replaces the spike with production code: proper error handling, session management, signup flow, and integration with the TenantResolver.
34510b Claude (MCP) 2026-03-15 01:39:13
[mcp] Add VPS implementation phases (V0-V7) with dev.robot.wtf migration"
179
180
**Tasks:**
181
c71840 Claude (MCP) 2026-03-15 02:43:01
[mcp] Rewrite VPS phases: add VS (auth spikes) phase, renumber dependency graph
182
- V3-1: Auth service scaffold. Flask app on port 8003. Caddy routes `robot.wtf/auth/*` to it. (May already exist from VS-1 — evolve the spike or rewrite clean.)
183
- V3-2: Publish ATProto OAuth client metadata at `https://robot.wtf/auth/client-metadata.json`. This URL becomes the `client_id` in the ATProto OAuth protocol — it must be stable. (May already exist from VS-1.)
184
- V3-3: Implement the ATProto OAuth flow. Adapt the Bluesky cookbook demo: handle input → DID resolution → PDS discovery → PAR → redirect → callback → token exchange → profile fetch. Store ATProto tokens in the `oauth_sessions` table. Incorporate lessons from VS-1.
34510b Claude (MCP) 2026-03-15 01:39:13
[mcp] Add VPS implementation phases (V0-V7) with dev.robot.wtf migration"
185
- V3-4: Platform JWT issuance. On successful ATProto auth, mint a platform JWT (RS256, same signing key from V0-5), set as HttpOnly cookie on `.robot.wtf`.
186
- V3-5: Signup flow. First-time users: after ATProto auth, prompt for platform username. Default to ATProto handle prefix (e.g., `sderle` from `sderle.bsky.social`, or domain prefix from a custom handle). Validate against reserved names and existing slugs. Create user record in SQLite.
187
- V3-6: Wire TenantResolver to validate platform JWTs from the cookie. Replace the hardcoded test auth from V1.
188
- V3-7: Handle refresh on login. Update `handle` and `display_name` from the PDS profile on each login (handles can change).
189
- V3-8: Login/logout UI. Minimal pages served by the auth service: login page (handle input field), logout endpoint (clear cookie). The management SPA comes later in V6; this is just the bare auth flow.
190
191
**Exit criteria:**
192
- A real Bluesky user can visit `robot.wtf/auth/login`, enter their handle, authorize on their PDS, and land back at robot.wtf with a valid platform JWT
193
- The platform JWT cookie works across subdomains (the user's wiki at `{slug}.robot.wtf` recognizes them)
194
- First-time signup creates a user record with DID, handle, and chosen username
195
- Returning users are recognized by DID; handle updates are reflected
196
197
---
198
351d75 Claude (MCP) 2026-03-15 07:36:32
[mcp] Add completion status markers to VPS phase headings (2026-03-15)
199
## V4: Management API + Wiki Lifecycle — COMPLETE
200
201
**Status:** Complete as of 2026-03-15. Wiki CRUD, ACL management, tier limits, and git HTTP read all operational.
34510b Claude (MCP) 2026-03-15 01:39:13
[mcp] Add VPS implementation phases (V0-V7) with dev.robot.wtf migration"
202
203
**Goal:** Authenticated users can create wikis, manage collaborators, and get MCP bearer tokens via API.
204
205
**Tasks:**
206
207
- V4-1: Port ManagementMiddleware from DynamoDB to SQLite. Same endpoints, same WSGI middleware pattern. Replace DynamoDB calls with SQLite queries.
208
- V4-2: Wire management API at `robot.wtf/api/*`. Caddy routes to the platform API service on port 8002.
209
- V4-3: Wiki creation flow. `POST /api/wikis` → create SQLite records + `git init --bare` + bootstrap template + generate bearer token. Returns token (shown once).
210
- V4-4: Wiki deletion, ACL management, token regeneration — port remaining endpoints.
211
- V4-5: Tier limit enforcement. 1 wiki per user, 500 pages, 3 collaborators. Enforced in middleware on write operations.
212
- V4-6: Git smart HTTP (read-only). Caddy routes `{slug}.robot.wtf/repo.git/*` to the platform API. dulwich serves `git-upload-pack` from the bare repo. Users can `git clone https://{slug}.robot.wtf/repo.git`.
213
- V4-7: Integration test. Create a user (via V3 auth flow), create a wiki (via API), browse it, connect MCP, clone via git.
214
215
**Exit criteria:**
216
- Authenticated user can create a wiki and get a bearer token
217
- Wiki appears at `{slug}.robot.wtf` with bootstrap template pages
218
- ACL grants/revocations work
219
- `git clone https://{slug}.robot.wtf/repo.git` works
220
- Tier limits enforced (cannot create second wiki)
221
222
---
223
351d75 Claude (MCP) 2026-03-15 07:36:32
[mcp] Add completion status markers to VPS phase headings (2026-03-15)
224
## V5: MCP OAuth AS (Claude.ai) — COMPLETE
225
226
**Status:** Complete as of 2026-03-15. Claude.ai successfully connected to a robot.wtf wiki via OAuth; full MCP OAuth flow operational in production.
34510b Claude (MCP) 2026-03-15 01:39:13
[mcp] Add VPS implementation phases (V0-V7) with dev.robot.wtf migration"
227
228
**Goal:** Claude.ai can connect to a robot.wtf wiki via its standard MCP OAuth flow.
229
c71840 Claude (MCP) 2026-03-15 02:43:01
[mcp] Rewrite VPS phases: add VS (auth spikes) phase, renumber dependency graph
230
VS-2 proved (or debugged) the protocol surface. This phase replaces the stub with production code: authlib's `AuthorizationServer`, real DCR persistence, ATProto-backed consent UI, proper token lifecycle.
34510b Claude (MCP) 2026-03-15 01:39:13
[mcp] Add VPS implementation phases (V0-V7) with dev.robot.wtf migration"
231
232
**Tasks:**
233
c71840 Claude (MCP) 2026-03-15 02:43:01
[mcp] Rewrite VPS phases: add VS (auth spikes) phase, renumber dependency graph
234
- V5-1: Implement OAuth 2.1 AS using authlib's `AuthorizationServer` + `AuthorizationCodeGrant` (PKCE) + `ClientRegistrationEndpoint` (RFC 7591). Wire model callbacks against SQLite (`mcp_oauth_clients` table for DCR, authorization codes in a transient table or in-memory store). Incorporate findings from VS-2 about Claude.ai's specific requirements.
34510b Claude (MCP) 2026-03-15 01:39:13
[mcp] Add VPS implementation phases (V0-V7) with dev.robot.wtf migration"
235
- V5-2: MCP protected resource metadata. Each wiki's MCP endpoint serves `/.well-known/oauth-protected-resource` pointing to robot.wtf's AS. Caddy routes this from the wiki subdomain to the MCP sidecar (or a small handler).
236
- V5-3: Authorization UI. The `/auth/oauth/authorize` endpoint renders a consent page. If the user is already logged in (platform JWT cookie): show "Authorize Claude to access {wiki}?". If not logged in: show "Sign in with Bluesky" which triggers the ATProto flow (V3) and then returns to consent.
237
- V5-4: Token issuance. The AS issues JWTs containing the user's DID and authorized wiki slug, signed with the platform RS256 key. MCP sidecar validates these the same way it validates platform JWTs.
c71840 Claude (MCP) 2026-03-15 02:43:01
[mcp] Rewrite VPS phases: add VS (auth spikes) phase, renumber dependency graph
238
- V5-5: Test against Claude.ai. Full end-to-end: add wiki MCP URL in Claude.ai, complete OAuth flow with real ATProto login, call wiki tools.
239
- V5-6: Test against Claude Code. Verify `claude mcp add --transport http` with OAuth discovery works (in addition to the existing bearer token path).
34510b Claude (MCP) 2026-03-15 01:39:13
[mcp] Add VPS implementation phases (V0-V7) with dev.robot.wtf migration"
240
241
**Exit criteria:**
242
- Claude.ai can discover, authenticate, and use MCP tools on a robot.wtf wiki
243
- Claude Code can connect via OAuth (in addition to the existing bearer token path)
244
- Token refresh works (Claude.ai doesn't lose connection after token expiry)
245
246
---
247
351d75 Claude (MCP) 2026-03-15 07:36:32
[mcp] Add completion status markers to VPS phase headings (2026-03-15)
248
## V6: Frontend + Landing Page — COMPLETE
249
250
**Status:** Complete as of 2026-03-15. Landing page live at robot.wtf/; management UI live at robot.wtf/app/*.
34510b Claude (MCP) 2026-03-15 01:39:13
[mcp] Add VPS implementation phases (V0-V7) with dev.robot.wtf migration"
251
252
**Goal:** Web UI for account management and a landing page that explains what robot.wtf is.
253
254
**Tasks:**
255
256
- V6-1: Landing page. Static HTML/CSS at `robot.wtf/`. Explains what robot.wtf is, shows how to get started, links to sign in. Tone and structure adapted from [[Design/Landing_Page]] but reframed as a free volunteer project, not a product. Served by Caddy's file_server.
257
- V6-2: Management SPA. Svelte app at `robot.wtf/app/*`. Served by Caddy (try_files fallback to index.html for client-side routing). Screens from the archived [[Design/Frontend]], minus billing:
258
- Dashboard (wiki list — for now just one wiki, but the UI should handle the general case)
259
- Wiki settings (display name, public/private toggle, link to Otterwiki admin panel)
260
- Collaborators (list, invite by handle/email, change role, revoke)
261
- MCP connection instructions (bearer token display/regen, Claude Code command, Claude.ai setup walkthrough)
262
- Account settings (username, connected ATProto handle, delete account)
263
- V6-3: `/api/me` endpoint. Returns current user info from platform JWT. The SPA uses this to determine login state and populate the UI.
264
- V6-4: "Logged in" detection on landing page. Small inline script checks for a companion cookie or probes `/api/me` to swap "Sign in" for "Dashboard" link.
265
266
**Exit criteria:**
267
- New user can visit `robot.wtf`, understand the service, sign in, create a wiki, and connect MCP — entirely through the web UI
268
- Returning user can manage collaborators, regenerate tokens, toggle public access
269
- Landing page is clear, honest, and matches the documentation style (write like a README, not a pitch deck)
270
271
---
272
351d75 Claude (MCP) 2026-03-15 07:36:32
[mcp] Add completion status markers to VPS phase headings (2026-03-15)
273
## V7: Semantic Search + Operational Hardening — NOT STARTED
274
275
**Status:** Not started as of 2026-03-15. ChromaDB deployed and numpy pinned, but embedding worker and search integration not yet verified.
34510b Claude (MCP) 2026-03-15 01:39:13
[mcp] Add VPS implementation phases (V0-V7) with dev.robot.wtf migration"
276
277
**Goal:** Semantic search works. Backups run. The service is ready for real users.
278
279
**Tasks:**
280
281
- V7-1: Embedding background worker. In-process thread (or dedicated worker process) that polls the `reindex_queue` table in SQLite. On dequeue: read page from git repo, chunk, embed with MiniLM, update FAISS index on disk.
282
- V7-2: Wire reindex queue. Otterwiki write operations (via MCP or REST API) write `{wiki_slug, page_path, action}` to `reindex_queue` on page save/delete.
283
- V7-3: Wire semantic search into MCP sidecar and REST API. Load FAISS index from disk, embed query with MiniLM, search, deduplicate, return results.
284
- V7-4: Backup cron. Daily: SQLite `.backup` + `rsync` of `/srv/wikis` and `/srv/data` to offsite storage. Alert on failure.
285
- V7-5: Health checks. Each service (Otterwiki, MCP, platform API, auth) exposes `/health`. External monitor (UptimeRobot free tier) pings them.
286
- V7-6: Log rotation. systemd journal or logrotate configuration so logs don't fill the disk.
287
- V7-7: Disk space monitoring. Cron job alerts when usage exceeds 80%.
288
- V7-8: Account deletion. User can delete their account from the SPA. Deletes wiki (git repo, FAISS index), SQLite records, ACL grants. Requires typing username to confirm.
289
- V7-9: Announce to the ATProto community. Post on Bluesky, add to ATProto app directories if any exist.
290
291
**Exit criteria:**
292
- Semantic search returns relevant results for queries against indexed wikis
293
- Backups run daily and succeed
294
- Health checks pass and alert on failure
295
- A real user who is not the operator can sign up, create a wiki, connect MCP, and use it without assistance
296
297
---
298
299
## Dependency graph
300
301
```
302
V0 (VM + Caddy + TLS)
c71840 Claude (MCP) 2026-03-15 02:43:01
[mcp] Rewrite VPS phases: add VS (auth spikes) phase, renumber dependency graph
303
├─ VS-1 (ATProto OAuth spike)
304
├─ VS-2 (MCP OAuth AS stub)
305
34510b Claude (MCP) 2026-03-15 01:39:13
[mcp] Add VPS implementation phases (V0-V7) with dev.robot.wtf migration"
306
└─ V1 (Otterwiki on Caddy)
307
├─ V2 (Migrate dev wikis)
c71840 Claude (MCP) 2026-03-15 02:43:01
[mcp] Rewrite VPS phases: add VS (auth spikes) phase, renumber dependency graph
308
└─ V3 (ATProto OAuth — informed by VS-1)
34510b Claude (MCP) 2026-03-15 01:39:13
[mcp] Add VPS implementation phases (V0-V7) with dev.robot.wtf migration"
309
└─ V4 (Management API)
c71840 Claude (MCP) 2026-03-15 02:43:01
[mcp] Rewrite VPS phases: add VS (auth spikes) phase, renumber dependency graph
310
├─ V5 (MCP OAuth AS — informed by VS-2)
34510b Claude (MCP) 2026-03-15 01:39:13
[mcp] Add VPS implementation phases (V0-V7) with dev.robot.wtf migration"
311
└─ V6 (Frontend + Landing)
312
└─ V7 (Semantic search + Ops)
313
```
314
c71840 Claude (MCP) 2026-03-15 02:43:01
[mcp] Rewrite VPS phases: add VS (auth spikes) phase, renumber dependency graph
315
VS-1, VS-2, and V1 can all run in parallel after V0. The spikes don't block V1 — they're independent experiments on the same VM. V2 and V3 can run in parallel after V1. V4 depends on V3 (needs real auth). V5 and V6 can run in parallel after V4. V7 is the final polish.
34510b Claude (MCP) 2026-03-15 01:39:13
[mcp] Add VPS implementation phases (V0-V7) with dev.robot.wtf migration"
316
317
**Minimum viable launch:** After V4, the service is usable — users can sign in with Bluesky, create a wiki, connect via Claude Code (bearer token), and browse the web UI. Claude.ai MCP OAuth (V5), the polished frontend (V6), and semantic search (V7) are improvements on a working service.
318
319
---
320
321
## What's not in scope
322
323
These items were part of the commercial wikibot.io design and are deliberately excluded from robot.wtf:
324
325
- Stripe integration, billing, premium tiers, upgrade/downgrade flows, lapse enforcement
326
- Multiple wikis per user (could be added later as a free feature if resource limits allow)
327
- Read/write git push (only read-only clone)
328
- External git sync (bidirectional GitHub/GitLab)
329
- Custom domains
330
- CDN read path / fragment caching (not needed — no Lambda cold starts)
331
- Lambda library mode / lazy loading (not needed — persistent processes)
332
- WAF (not needed at this scale — Caddy + rate limiting if abuse appears)
333
- Pulumi / IaC (replaced by Ansible for VM setup, systemd for services)
334
- CI/CD pipeline (deploy is `git pull` + restart; add GitHub Actions later if it matters)