2026-03-17 06:07:11Claude (MCP):
[mcp] Phase 2: consolidate collaborators into Otterwiki User Management, remove dashboard tab
Design/Admin_Panel_Reenablement.md ..
@@ 15,7 15,7 @@
## 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.
+
`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
@@ 23,61 23,56 @@
| 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`. |
+
| 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. 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. |
+
| 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. |
-
**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`.
`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.
**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.
Wiki owners can restrict but never escalate beyond the platform ACL ceiling. ADMIN permission is never affected by wiki preferences.
+
#### Design: Explicit roster, not activity tracking
-
**`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.
+
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.
-
**APPROVED level:** Treated as REGISTERED until Phase 2 (user tracking). This is safe — more restrictive than intended, never less.
+
**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
-
**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.
+
**Wiki admins can create other wiki admins.**
-
**Changes (two repos):**
-
1. **otterwiki fork (wikibot-io):** Remove `@platform_mode_disabled`, hide registration fields in template, server-side guard for registration saves
-
2. **robot.wtf resolver:** `_apply_wiki_access_restrictions()` intersects ACL permissions with wiki preferences before injecting proxy headers
+
#### Consolidating platform ACL into User Management
-
### Phase 2: 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.
-
#### Design: Explicit roster, not activity tracking
+
#### Migration path
-
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:**
-
1. Admin opens User Management panel
-
2. Enters a DID handle (e.g., `@alice.bsky.social`) to add a user
4. 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.
+
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 and schema migration work
+
- **Add a `handle` column** — cleaner, but more fork divergence
Decision deferred. Future notification mechanism (email vs. BlueSky DMs) affects this choice.
@@ 87,21 82,30 @@
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 (along with WRITE, UPLOAD per dependency chain)
+
4. If not found or not approved: READ stripped
#### Required changes
-
1. **User Management UI:** Admin enters DID handles to add users, sets flags. Hide password/email-editing fields in PLATFORM_MODE.
-
2. **`get_all_user()` override:** `ProxyHeaderAuth.get_all_user()` must query the per-wiki user table instead of returning `[current_user]`.
-
3. **Resolver permission check:** Extend `_apply_wiki_access_restrictions()` to query per-wiki user table when access level is APPROVED.
-
4. **User Edit page:** Same PLATFORM_MODE treatment — hide password actions, show handle.
+
**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. If mail is needed, platform provides a shared service. Notification mechanism (email vs. BlueSky DMs) is an open question.
+
Per-wiki SMTP config is a security/spam risk. Notification mechanism (email vs. BlueSky DMs) is an open question.