---
category: reference
tags: [tasks, milestones, launch]
last_updated: 2026-03-18
confidence: high
---

# Pre-Launch Milestone

Work required before opening robot.wtf to the ATProto community. Everything here is either a bug, a missing feature that blocks usability, or a safety issue.

## Completed

### ~~MCP wiki routing (bug)~~ ✅ FIXED (2026-03-15)
Fixed and deployed. See [[Tasks/MCP_Wiki_Routing]].

### ~~Multi-tenant semantic search (bug)~~ ✅ FIXED (2026-03-17)
See [[Tasks/Semantic_Search_Architecture]] and [[Tasks/Semantic_Search_Multi_Tenant]].

### ~~FAISS index corruption risk~~ ✅ RESOLVED (2026-03-15)
Sync thread removed. Index updates now happen through page lifecycle hooks only.

### ~~Log rotation~~ ✅ DONE (V7-6)
systemd journal / logrotate configured so logs don't fill the disk.

### ~~OAuth token refresh~~ ✅ FIXED (2026-03-17)
ACCESS_TOKEN_EXPIRY_SECONDS extended from 3600 to 7 days (604800). Refresh tokens set to 30 days.

### ~~Per-wiki databases~~ ✅ DEPLOYED (2026-03-17)
Each wiki gets `/srv/data/wikis/{slug}/wiki.db` with preferences, drafts, user, cache tables. Resolver swaps DB per-request.

### ~~Permissions panel~~ ✅ DEPLOYED (2026-03-17)
Wiki owners can set READ_ACCESS/WRITE_ACCESS/ATTACHMENT_ACCESS via Otterwiki's admin UI. Resolver enforces by intersecting with platform ACL.

### ~~MCP OAuth hardcoded defaults~~ ✅ DEPLOYED (2026-03-17)
CONSENT_URL and PLATFORM_DOMAIN no longer default to robot.wtf. InMemoryOAuthProvider fallback when unset.

### ~~MCP OAuth dynamic base URL~~ ✅ DEPLOYED (2026-03-17)
OAuth metadata endpoint uses request Host header. Each wiki's MCP endpoint works correctly.

### ~~SERVER_NAME hidden~~ ✅ DEPLOYED (2026-03-17)
SERVER_NAME field hidden from Application Preferences in PLATFORM_MODE.

### ~~Remove is_public toggle~~ ✅ DEPLOYED (2026-03-17)
READ_ACCESS replaces is_public as sole source of truth. Migration seeds READ_ACCESS=REGISTERED for private wikis.

### ~~Login return_to redirect~~ ✅ DEPLOYED (2026-03-17)
Resolver passes wiki URL as return_to when redirecting to login. Auth server accepts *.robot.wtf URLs.

### ~~SITE_NAME lazy init~~ ✅ DEPLOYED (2026-03-17)
display_name passed through to _init_wiki_db during lazy init.

### ~~Upstream bug fix~~ submitted (2026-03-17)
`handle_permissions_and_registration` missing ADMIN guard — PR pending to redimp/otterwiki (`fix/permissions-admin-guard`).

## Blocking

### ~~Harden per-wiki DB initialization~~ ✅ DEPLOYED (2026-03-17)
Comprehensive `_init_wiki_db()`: seeds SITE_NAME, READ_ACCESS, WRITE_ACCESS, ATTACHMENT_ACCESS (all REGISTERED), AUTH_METHOD (PROXY_HEADER), DISABLE_REGISTRATION, AUTO_APPROVAL (False), schema version marker. All INSERT OR IGNORE. Owner auto-seeded as admin.

### ~~Post-deploy smoke test~~ ✅ MERGED (2026-03-17)
Shell script in Ansible `post_tasks` — checks all 4 services (systemctl + HTTP), auth/MCP well-known endpoints, dynamic wiki enumeration from DB. Retry loop with 30s ceiling per service.

### ~~Disk usage cap~~ ✅ DEPLOYED (2026-03-17)
Disk quota (50MB) enforced via resolver — API gets 413, web UI gets WRITE stripped. Page count quota (500 pages) added. Cron populates both `disk_usage_bytes` and `page_count` every 15 minutes. Constants consolidated in `app/constants.py`. Cron script hardened with slug validation and trailing-slash guards.

### ~~Management UI usability~~ ✅ DEPLOYED (2026-03-17)
- ~~Wiki creation flow should default slug to username~~ Done: derives slug from Bluesky handle when username not set. Reserved names (DNS-sensitive) return empty, forcing manual entry.
- ~~MCP connection instructions need to be clearer~~ Addressed: MCP info now on dashboard card with Claude Code example
- ~~Settings page layout needs work~~ Addressed: collapsed to single-page card layout

### Landing page copy
Draft is live at robot.wtf/. Updated 2026-03-17. Still needs screenshots once UI is polished.

## UX issues

### ~~Login page UX~~ ✅ DEPLOYED (2026-03-17)
JWT cookie detection: auto-redirects if authenticated, pre-fills handle if expired (sanitized, length-capped). Auth templates (login, consent, signup, error) restyled to match landing page — Pico CSS replaced with shared `style.css` + auth-specific styles. Site icon (`robot.wtf.svg`) added to favicon and nav across all pages. See [[Plans/Login_Page_UX]].

### ~~Landing page redirect~~ ✅ FIXED (2026-03-17)
Landing page no longer auto-redirects authenticated users to dashboard. Only `/auth/login` auto-redirects.

### ~~Permissions registration checkboxes~~ ✅ DEPLOYED (2026-03-17)
Five registration checkboxes (DISABLE_REGISTRATION, EMAIL_NEEDS_CONFIRMATION, AUTO_APPROVAL, NOTIFY_ADMINS, NOTIFY_USER_ON_APPROVAL) hidden in PLATFORM_MODE via otterwiki fork template guards. ADMIN option also hidden from access level dropdowns. Deploy fix: `state: forcereinstall` on otterwiki pip task.

### ~~Multi-worker preference staleness~~ ✅ FIXED (2026-03-17)
`update_app_config()` now called on fast path in `_swap_database()`, so preference changes (e.g. READ_ACCESS) propagate immediately across workers. See [[Design/Resolver]].

### ~~Admin UI cleanup (otterwiki fork)~~ ✅ ALREADY DONE (confirmed 2026-03-17)
All three items were completed during Phase 2 User Management work: mail tab hidden (`@platform_mode_disabled` + nav guard), "Email" → "Handle" conditional in templates, "Approved" checkbox replaced by Role dropdown (Admin/Editor/Viewer) with `is_approved` auto-set. Tests cover all three.

### ~~No navigation from wiki to dashboard~~ ✅ DEPLOYED (2026-03-18)
Dashboard link added to otterwiki dropdown menu in PLATFORM_MODE. See [[Plans/Wiki_To_Dashboard_Navigation]].

## Safety

### Backup coverage gaps
Backup cron runs every 4 hours, retains 7 days. Uses `sqlite3 .backup` for consistency.

**What IS backed up:** `robot.db`, `mcp_oauth.db`, per-wiki `wiki.db` files.

**What is NOT backed up:**
- **Git repos** (`/srv/data/wikis/{slug}/repo/`) — all wiki content. Relies on Proxmox VM snapshots. **Verify Proxmox snapshot schedule is actually running.**
- **Signing keys** (`signing_key.pem`, `signing_key.pub`, `client_jwk.json`, `client_jwk_pub.json`) — losing these breaks all OAuth sessions. Generated once, never backed up. Should be added to backup script or Ansible vault.
- FAISS indexes — can be rebuilt from wiki content (not critical).

**Recommended actions (in priority order):**
1. Verify Proxmox snapshots are running on schedule
2. Add `git bundle create` per wiki to the backup script
3. Add signing key backup to the script
4. Write and test a restore script
5. Automate a periodic integrity check (`PRAGMA integrity_check` on all DBs)

### Backup verification
No tested restore path exists. Minimal local test: pull a backup, run integrity checks on each DB, verify schema matches.

### ~~Rate limiting + security headers~~ ✅ DEPLOYED (2026-03-17)
**Security headers:** HSTS (1 month), CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy applied globally via Caddy snippet.

**Rate limiting:** Flask-Limiter on auth (1/min login/signup, 2/min consent POST) and API (1/min create, 2/min delete) Flask routes. `limits` library in WSGI middleware: 5/min wiki writes, 5/min API writes, 15/min API reads. ProxyFix at outermost WSGI layer. Retry-After on all 429s. fail2ban on proxy-1 as backstop. Per-worker in-memory storage (~4x effective limits). See [[Plans/Rate_Limiting_And_Security_Headers]].

### OWASP remaining items
From [[Security/OWASP_2025_Audit]]:
- ~~**Bcrypt linear scan DoS**~~ ✅ MERGED (2026-03-17)
- ~~**Security response headers**~~ Plan ready (see above)
- **Security logging:** No audit trail for auth events, ACL changes, wiki deletions. **Plan at [[Plans/Security_Logging]].** ACL hooks (`permission_changed`, `user_flags_changed`) implemented for upstream otterwiki on `feat/admin-action-hooks` — pushed to schuyler/otterwiki, ready for PR to redimp/otterwiki.

### ~~Git remote push/pull security~~ ✅ DEPLOYED (2026-03-17)
Repository Management panel hidden in PLATFORM_MODE (`@platform_mode_disabled` decorator + nav guard). Pull webhook also gated. `auto_push_if_enabled()` and `auto_pull_webhook()` return early in PLATFORM_MODE — prevents outbound SSH even if previously configured. Feature may be re-enabled with proper sandboxing if there's demand.

### ~~Monitoring dashboard~~ ✅ DEPLOYED (2026-03-18)
`/app/admin/stats` page in management UI showing service health, disk usage, wiki/user counts, journal tail. Admin-only via `PLATFORM_ADMIN_DIDS`. Ansible `healthcheck`/`diskmon` roles added to deploy. See [[Plans/Monitoring_Dashboard]].

## Not blocking but important

### ~~Phase 2: User Management~~ ✅ DEPLOYED (2026-03-17)
Platform ACL removed entirely. Per-wiki user table is sole source of truth. Resolver restructured: owner gets ADMIN via `wikis.owner_did`, per-wiki user flags derive permissions, APPROVED access level functional, bearer tokens wiki-scoped. Dashboard collapsed to single-page card layout. Otterwiki role UI (admin/editor/viewer dropdown) deployed. Repository Management gated in PLATFORM_MODE. Init hardening comprehensive.

### ~~Semantic search background sync (V7-1, V7-2, V7-3)~~ ✅ DEPLOYED (2026-03-18)
Multi-tenant FAISS backend via `BackendRegistry` — per-wiki indexes at `/srv/data/faiss/{slug}/`. ChromaDB deprecated and disabled. Sync thread replaced by lifecycle hooks (`page_saved`/`page_deleted`/`page_renamed`). `reindex_all` is per-wiki scoped. Auto-reindex on first wiki access. See [[Tasks/Semantic_Search_Architecture]] and [[Tasks/Semantic_Search_Multi_Tenant]].

### Wiki stats plugin
Track page count and disk usage via otterwiki lifecycle hooks. Enables tier limits and quota enforcement. Design at [[Design/Wiki_Stats_Plugin]]. **Parked — design only.**

### SMTP alerts test
Health check and disk monitoring alerts configured but not tested end-to-end.

### ~~CI/CD pipeline (Phase 1)~~ ✅ MERGED (2026-03-18)
Per-repo pytest CI via GitHub Actions on all 5 repos. `deploy.sh` wrapper in robot.wtf. Auto-deploy deferred to Phase 3. See [[Plans/CI_CD_Pipeline]].

## Post-launch

### Account deletion (V7-8)
User can delete their account from the management UI. Deletes wiki (git repo, FAISS index), SQLite records, ACL grants. Requires typing username to confirm.

### Announce to ATProto community (V7-9)
Post on Bluesky, add to ATProto app directories if any exist. Gated on semantic search (V7-1–V7-3) and a real user being able to sign up and use the service end-to-end without assistance.

### Git clone auth
Read-only git clone works (V4-6) but has no auth — anyone can clone any wiki. Should require bearer token or platform JWT for private wikis.

### Multiple wikis per user
Currently limited to 1 wiki per user. The data model supports multiple wikis. Needs UI for wiki selection and limit increase.

### Bluesky DM alerts
Translate health check / disk monitoring alerts into Bluesky DMs via ATProto API. Small webhook relay.

### Wiki import
Import existing git repos (from GitHub, local, etc.) as a new wiki. Upload or provide a git URL.

### Attachment size limits
Per-file and per-wiki attachment size enforcement. Currently no limits on uploaded files.

### SEO for public wikis
Public wikis (READ_ACCESS=ANONYMOUS) should be indexable by search engines. Needs: proper `<meta>` tags, `robots.txt` that allows crawling of public wikis, `sitemap.xml` generation per wiki, OpenGraph tags for link previews. Private wikis should have `noindex, nofollow`.

### Proxmox CPU type change
Change from kvm64 to host to enable numpy 2.4+ and remove the pin. Requires VM reboot. See [[Dev/Proxmox_CPU_Type]].
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