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.
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.
Re-enable now: Permissions panel (medium effort)
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
Current state: ProxyHeaderAuth.has_permission() ignores these entirely — it trusts proxy headers from the resolver.
Proposed integration: The resolver reads these preferences after _swap_database() and intersects them with platform ACL permissions before injecting proxy headers.
- Platform ACL grants the ceiling (owner/editor/viewer → READ, WRITE, UPLOAD, ADMIN)
- Per-wiki READ_ACCESS/WRITE_ACCESS restrict further (e.g., if WRITE_ACCESS=APPROVED and user isn't approved, strip WRITE from headers)
- Wiki owner can restrict but never escalate beyond what the platform ACL grants
Changes needed:
- otterwiki fork (wikibot-io branch): Modify the permissions_and_registration template to hide registration-related fields when
PLATFORM_MODEis true. Remove@platform_mode_disableddecorator from the route. - robot.wtf resolver: After
_swap_database()andupdate_app_config(), readREAD_ACCESS/WRITE_ACCESS/ATTACHMENT_ACCESSfromapp.config. Apply them when computing thex-otterwiki-permissionsheader — intersect with ACL-granted permissions.
Phase 2: User Management (high effort)
Routes: /-/admin/user_management, /-/user/<uid>
Problem: ProxyHeaderAuth creates transient user objects from headers. Nothing persists to the per-wiki DB. get_all_user() returns only [current_user].
Required changes:
- User tracking: Resolver upserts a User record into per-wiki DB on each authenticated request (ATProto handle as email field, display name as name, null password_hash)
get_all_user()override: Query per-wiki user table instead of returning[current_user]- Template changes: Hide password/email fields in PLATFORM_MODE; show ATProto handles
- ACL integration: Per-user flags (allow_read, allow_write, is_admin) feed into permission computation alongside READ_ACCESS/WRITE_ACCESS
Keep disabled: Mail Preferences
Per-wiki SMTP config is a security/spam risk. If mail is needed, platform provides a shared service.
Implementation Order
- Permissions panel — re-enable with resolver integration (this sprint)
- Hide SERVER_NAME — quick template fix (opportunistic)
- User Management — user tracking + template customization (Phase 2)
