Properties
category: reference
tags: [architecture, admin, permissions, multi-tenancy]
last_updated: 2026-03-17
confidence: high

Admin Panel Re-enablement

Analysis of which Otterwiki admin panels can be re-enabled in robot.wtf's multi-tenant platform, now that per-wiki SQLite databases are deployed.

Background

Otterwiki has 8 admin panels. Three are gated by PLATFORM_MODE (added in feat/P2-8-admin-panel-hiding). Per-wiki databases landed on 2026-03-17, meaning each wiki's preferences, drafts, user, and cache tables are now isolated.

Upstream bug found

handle_permissions_and_registration in otterwiki/preferences.py is missing the has_permission("ADMIN") guard that every other admin handler has. Fix submitted as fix/permissions-admin-guard — PR pending to redimp. Red/green verified.

Panel Status

Already working (no changes needed)

Panel Route Notes
Application Preferences /-/admin SITE_NAME, SITE_DESCRIPTION, SITE_LOGO, etc. SERVER_NAME hidden in PLATFORM_MODE.
Sidebar Preferences /-/admin/sidebar_preferences Pure preferences. Works.
Content and Editing /-/admin/content_and_editing COMMIT_MESSAGE, WIKILINK_STYLE, etc. Works.
Repository Management /-/admin/repository_management GIT_WEB_SERVER, remote push/pull. Git remote push/pull + SSH key storage is a security concern — consider gating in PLATFORM_MODE.

Phase 1: Permissions panel ✅ DEPLOYED (2026-03-17)

READ_ACCESS / WRITE_ACCESS / ATTACHMENT_ACCESS configurable via Otterwiki admin. Resolver enforces by intersecting with platform ACL. Registration fields hidden in PLATFORM_MODE. READ_ACCESS replaces is_public as sole source of truth for anonymous access.

Phase 2: User Management (consolidated)

Key decision (2026-03-17): Remove the "Collaborators" tab from the platform dashboard entirely. All user/access management happens in Otterwiki's User Management panel. This consolidates three layers (platform ACL, wiki preferences, per-wiki roster) into two places the wiki owner actually sees: the Permissions panel and the User Management panel.

Routes: /-/admin/user_management, /-/user/<uid>

Design: Explicit roster, not activity tracking

The per-wiki user table is an explicit roster managed by wiki admins, not an activity log. Users only exist there because an admin added them.

Admin workflow:

  1. Admin opens User Management panel in Otterwiki's admin
  2. Enters a DID handle (e.g., @alice.bsky.social) to add a user
  3. Sets per-user flags: role (viewer/editor/admin), is_approved
  4. User can now access the wiki at whatever level their flags grant

Wiki admins can create other wiki admins.

Consolidating platform ACL into User Management

Currently, the platform dashboard has a "Collaborators" tab that manages the acls table in robot.db (granting owner/editor/viewer roles). Phase 2 moves this into Otterwiki's User Management panel:

  • Remove the Collaborators tab from the dashboard (wiki_settings.html)
  • Remove the Collaborators API endpoints from the management API (or deprecate)
  • User Management becomes the single place to manage who can access the wiki and at what level
  • The per-wiki user table replaces the platform acls table as the source of truth for per-wiki access
  • The resolver reads from the per-wiki user table instead of (or in addition to) the platform ACL table
  • The platform ACL ceiling is enforced implicitly: the wiki owner's own role (from the wikis table) is the ceiling. The owner can grant up to their own level but not beyond.

Migration path

  1. On Phase 2 deploy, migrate existing acls entries into per-wiki user tables
  2. Remove Collaborators tab from dashboard
  3. Remove or deprecate ACL management API endpoints
  4. Resolver reads permissions from per-wiki user table

email field decision — deferred

Otterwiki's User model keys on email. Two options:

  • Appropriate email for DID handles — quick, minimal schema divergence, but blocks future email notifications
  • Add a handle column — cleaner, but more fork divergence

Decision deferred. Future notification mechanism (email vs. BlueSky DMs) affects this choice.

Permission flow with APPROVED level

Once Phase 2 lands, the APPROVED access level becomes fully functional:

  1. Wiki owner sets READ_ACCESS=APPROVED in Permissions panel
  2. Resolver checks per-wiki user table for the authenticated user's handle
  3. If found and is_approved=True: READ permission granted
  4. If not found or not approved: READ stripped

Required changes

Otterwiki fork:

  1. Re-enable User Management + User Edit panels in PLATFORM_MODE
  2. Customize add-user form: accept DID handle, hide password fields
  3. Override ProxyHeaderAuth.get_all_user() to query per-wiki user table
  4. Map user flags to roles (viewer/editor/admin) for display

robot.wtf:

  1. Remove Collaborators tab from wiki_settings.html
  2. Remove or deprecate ACL management endpoints in management/routes.py
  3. Extend _apply_wiki_access_restrictions() to query per-wiki user table for APPROVED level and per-user role
  4. Migration script: copy acls entries to per-wiki user tables
  5. Resolver reads per-wiki user table for permission computation

Keep disabled: Mail Preferences

Per-wiki SMTP config is a security/spam risk. Notification mechanism (email vs. BlueSky DMs) is an open question.

Implementation Order

  1. Permissions panel ✅ Deployed
  2. Hide SERVER_NAME ✅ Deployed
  3. Remove is_public toggle ✅ Deployed
  4. User Management — consolidate collaborators + explicit roster + APPROVED level (Phase 2)