Blame
|
1 | --- |
||||||
| 2 | category: reference |
|||||||
| 3 | tags: [architecture, admin, permissions, multi-tenancy] |
|||||||
| 4 | last_updated: 2026-03-17 |
|||||||
| 5 | confidence: high |
|||||||
| 6 | --- |
|||||||
| 7 | ||||||||
| 8 | # Admin Panel Re-enablement |
|||||||
| 9 | ||||||||
| 10 | 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. |
|||||||
| 11 | ||||||||
| 12 | ## Background |
|||||||
| 13 | ||||||||
| 14 | 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. |
|||||||
| 15 | ||||||||
|
16 | ## Upstream bug found |
||||||
| 17 | ||||||||
|
18 | `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. |
||||||
|
19 | |||||||
|
20 | ## Panel Status |
||||||
| 21 | ||||||||
| 22 | ### Already working (no changes needed) |
|||||||
| 23 | ||||||||
| 24 | | Panel | Route | Notes | |
|||||||
| 25 | |-------|-------|-------| |
|||||||
|
26 | | Application Preferences | `/-/admin` | SITE_NAME, SITE_DESCRIPTION, SITE_LOGO, etc. SERVER_NAME hidden in PLATFORM_MODE. | |
||||||
|
27 | | Sidebar Preferences | `/-/admin/sidebar_preferences` | Pure preferences. Works. | |
||||||
| 28 | | Content and Editing | `/-/admin/content_and_editing` | COMMIT_MESSAGE, WIKILINK_STYLE, etc. Works. | |
|||||||
|
29 | | Repository Management | `/-/admin/repository_management` | ✅ **Gated in PLATFORM_MODE** (2026-03-17). Route, nav link, pull webhook, and auto-push/pull all disabled. SSH key storage and outbound connections blocked. May re-enable with sandboxing if demand emerges. | |
||||||
|
30 | |||||||
|
31 | ### Phase 1: Permissions panel ✅ DEPLOYED (2026-03-17) |
||||||
|
32 | |||||||
|
33 | `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. |
||||||
|
34 | |||||||
|
35 | ### Phase 2: User Management (consolidated) |
||||||
|
36 | |||||||
|
37 | **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. |
||||||
|
38 | |||||||
|
39 | **Routes:** `/-/admin/user_management`, `/-/user/<uid>` |
||||||
|
40 | |||||||
|
41 | #### Design: Explicit roster, not activity tracking |
||||||
|
42 | |||||||
|
43 | 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. |
||||||
|
44 | |||||||
|
45 | **Admin workflow:** |
||||||
| 46 | 1. Admin opens User Management panel in Otterwiki's admin |
|||||||
| 47 | 2. Enters a DID handle (e.g., `@alice.bsky.social`) to add a user |
|||||||
| 48 | 3. Sets per-user flags: role (viewer/editor/admin), `is_approved` |
|||||||
| 49 | 4. User can now access the wiki at whatever level their flags grant |
|||||||
|
50 | |||||||
|
51 | **Wiki admins can create other wiki admins.** |
||||||
|
52 | |||||||
|
53 | #### Consolidating platform ACL into User Management |
||||||
|
54 | |||||||
|
55 | 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: |
||||||
|
56 | |||||||
|
57 | - **Remove the Collaborators tab** from the dashboard (`wiki_settings.html`) |
||||||
| 58 | - **Remove the Collaborators API endpoints** from the management API (or deprecate) |
|||||||
| 59 | - **User Management becomes the single place** to manage who can access the wiki and at what level |
|||||||
| 60 | - **The per-wiki `user` table replaces the platform `acls` table** as the source of truth for per-wiki access |
|||||||
| 61 | - **The resolver reads from the per-wiki user table** instead of (or in addition to) the platform ACL table |
|||||||
| 62 | - **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. |
|||||||
|
63 | |||||||
|
64 | #### Migration path |
||||||
|
65 | |||||||
|
66 | 1. On Phase 2 deploy, migrate existing `acls` entries into per-wiki `user` tables |
||||||
| 67 | 2. Remove Collaborators tab from dashboard |
|||||||
| 68 | 3. Remove or deprecate ACL management API endpoints |
|||||||
| 69 | 4. Resolver reads permissions from per-wiki user table |
|||||||
|
70 | |||||||
| 71 | #### `email` field decision — deferred |
|||||||
| 72 | ||||||||
| 73 | Otterwiki's User model keys on `email`. Two options: |
|||||||
| 74 | - **Appropriate `email` for DID handles** — quick, minimal schema divergence, but blocks future email notifications |
|||||||
|
75 | - **Add a `handle` column** — cleaner, but more fork divergence |
||||||
|
76 | |||||||
| 77 | Decision deferred. Future notification mechanism (email vs. BlueSky DMs) affects this choice. |
|||||||
| 78 | ||||||||
| 79 | #### Permission flow with APPROVED level |
|||||||
| 80 | ||||||||
| 81 | Once Phase 2 lands, the APPROVED access level becomes fully functional: |
|||||||
| 82 | 1. Wiki owner sets `READ_ACCESS=APPROVED` in Permissions panel |
|||||||
| 83 | 2. Resolver checks per-wiki `user` table for the authenticated user's handle |
|||||||
| 84 | 3. If found and `is_approved=True`: READ permission granted |
|||||||
|
85 | 4. If not found or not approved: READ stripped |
||||||
|
86 | |||||||
| 87 | #### Required changes |
|||||||
|
88 | |||||||
|
89 | **Otterwiki fork:** |
||||||
| 90 | 1. Re-enable User Management + User Edit panels in PLATFORM_MODE |
|||||||
| 91 | 2. Customize add-user form: accept DID handle, hide password fields |
|||||||
| 92 | 3. Override `ProxyHeaderAuth.get_all_user()` to query per-wiki user table |
|||||||
| 93 | 4. Map user flags to roles (viewer/editor/admin) for display |
|||||||
| 94 | ||||||||
| 95 | **robot.wtf:** |
|||||||
| 96 | 1. Remove Collaborators tab from `wiki_settings.html` |
|||||||
| 97 | 2. Remove or deprecate ACL management endpoints in `management/routes.py` |
|||||||
| 98 | 3. Extend `_apply_wiki_access_restrictions()` to query per-wiki user table for APPROVED level and per-user role |
|||||||
| 99 | 4. Migration script: copy `acls` entries to per-wiki `user` tables |
|||||||
| 100 | 5. Resolver reads per-wiki user table for permission computation |
|||||||
|
101 | |||||||
| 102 | ### Keep disabled: Mail Preferences |
|||||||
| 103 | ||||||||
|
104 | Per-wiki SMTP config is a security/spam risk. Notification mechanism (email vs. BlueSky DMs) is an open question. |
||||||
|
105 | |||||||
| 106 | ## Implementation Order |
|||||||
| 107 | ||||||||
|
108 | 1. ~~Permissions panel~~ ✅ Deployed |
||||||
| 109 | 2. ~~Hide SERVER_NAME~~ ✅ Deployed |
|||||||
| 110 | 3. ~~Remove is_public toggle~~ ✅ Deployed |
|||||||
|
111 | 4. ~~User Management~~ ✅ Deployed (2026-03-17) — platform ACL removed entirely, per-wiki user table is sole permission source, role UI (admin/editor/viewer) deployed, APPROVED access level functional, dashboard collapsed to single-page card |
||||||
| 112 | 5. ~~Repository Management~~ ✅ Gated in PLATFORM_MODE (2026-03-17) — route, nav, webhook, auto-push/pull all disabled |
|||||||
| 113 | ||||||||
| 114 | ### Remaining disabled |
|||||||
| 115 | - **Mail Preferences** — per-wiki SMTP is a security/spam risk. Notification mechanism (email vs. BlueSky DMs) is an open question. |
|||||||
