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. A non-admin authenticated user can POST and overwrite READ_ACCESS/WRITE_ACCESS settings. Fix submitted as fix/permissions-admin-guard on our fork — PR pending to redimp. Red/green verified: POST returns 302 (succeeds) without fix, 403 with fix.
Panel Status
Already working (no changes needed)
| Panel | Route | Notes |
|---|---|---|
| Application Preferences | /-/admin |
SITE_NAME, SITE_DESCRIPTION, SITE_LOGO, etc. All stored in per-wiki preferences. update_app_config() reloads from the right DB. app_renderer sees changes via live reference to app.config. |
| 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. Works but git remote push/pull + SSH key storage is a security concern — wiki owners storing arbitrary SSH keys that the platform executes. Consider gating push/pull behind a platform-level flag. |
Flag: SERVER_NAME in Application Preferences could break Flask's URL generation in multi-tenant mode. Should be hidden or read-only in PLATFORM_MODE.
Phase 1: Permissions panel (in progress)
Route: /-/admin/permissions_and_registration
What it controls:
READ_ACCESS— ANONYMOUS / REGISTERED / APPROVEDWRITE_ACCESS— same optionsATTACHMENT_ACCESS— same options- Registration settings (DISABLE_REGISTRATION, AUTO_APPROVAL, etc.) — not applicable to ATProto auth
Permission model (three layers):
- Platform ACL grants the ceiling (owner/editor/viewer → READ, WRITE, UPLOAD, ADMIN)
- Per-wiki preferences (READ_ACCESS/WRITE_ACCESS/ATTACHMENT_ACCESS) restrict further
- Per-user flags in per-wiki user table (Phase 2) restrict further still
Wiki owners can restrict but never escalate beyond the platform ACL ceiling. ADMIN permission is never affected by wiki preferences.
READ_ACCESS as source of truth for public access: The wiki's READ_ACCESS preference replaces the separate is_public flag in robot.db. If READ_ACCESS=ANONYMOUS, anonymous users get through. Otherwise, authentication is required. One place to manage access, in Otterwiki's native admin UI.
APPROVED level: Treated as REGISTERED until Phase 2 (user tracking). This is safe — more restrictive than intended, never less.
MCP bearer tokens: Full access regardless of wiki preferences. MCP tokens are platform-granted; wiki owners shouldn't be able to break their own integrations.
Changes (two repos):
- otterwiki fork (wikibot-io): Remove
@platform_mode_disabled, hide registration fields in template, server-side guard for registration saves - robot.wtf resolver:
_apply_wiki_access_restrictions()intersects ACL permissions with wiki preferences before injecting proxy headers
Phase 2: User Management
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. No passive tracking — if a wiki is publicly readable, authenticated visitors are not recorded.
Admin workflow:
- Admin opens User Management panel
- Enters a DID handle (e.g.,
@alice.bsky.social) to add a user - Sets per-user flags:
is_approved,allow_read,allow_write,allow_upload,is_admin - User can now access the wiki at whatever level their flags grant (intersected with wiki preferences and platform ACL ceiling)
Wiki admins can create other wiki admins. No reason to restrict this — the platform ACL is still the outer boundary.
email field decision — deferred
Otterwiki's User model keys on email. Two options:
- Appropriate
emailfor DID handles — quick, minimal schema divergence, but blocks future email notifications - Add a
handlecolumn — cleaner, but more fork divergence and schema migration work
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:
- Wiki owner sets
READ_ACCESS=APPROVEDin Permissions panel - Resolver checks per-wiki
usertable for the authenticated user's handle - If found and
is_approved=True: READ permission granted - If not found or not approved: READ stripped (along with WRITE, UPLOAD per dependency chain)
Required changes
- User Management UI: Admin enters DID handles to add users, sets flags. Hide password/email-editing fields in PLATFORM_MODE.
get_all_user()override:ProxyHeaderAuth.get_all_user()must query the per-wiki user table instead of returning[current_user].- Resolver permission check: Extend
_apply_wiki_access_restrictions()to query per-wiki user table when access level is APPROVED. - User Edit page: Same PLATFORM_MODE treatment — hide password actions, show handle.
Keep disabled: Mail Preferences
Per-wiki SMTP config is a security/spam risk. If mail is needed, platform provides a shared service. Notification mechanism (email vs. BlueSky DMs) is an open question.
Implementation Order
- Permissions panel — in progress (Phase 1)
- Hide SERVER_NAME — quick template fix (opportunistic)
- User Management — explicit roster + APPROVED level (Phase 2)