--- 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]].
