Files
Business-Management/changelog/2026-04-18_category-scopes-group-admin.md
curo1305 fec3953009 feat: category scopes, group-admin role, and permission model
- Three category scopes: personal / group / system (watch)
- PascalCase-with-dashes naming convention enforced at backend + frontend
- is_group_admin flag on GroupMembership; PATCH endpoint for admins to toggle it
- Categories router: scope-based list/create/rename/delete with _check_can_manage_cat
- Documents router: delete uses is_admin + can_delete share flag + group-admin check; remove_category requires doc ownership; assign_category accepts group/system categories
- Proxy layers inject x-user-is-admin and x-user-admin-groups headers
- Frontend: ManageCategoriesDialog grouped by scope with lock icons; SourcePanel scope picker + client-side name validation; AdminGroupsPage group-admin checkbox

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 22:16:49 +02:00

3.2 KiB

2026-04-18 — Category scopes, group admin role, and permission model

Timestamp: 2026-04-18T00:00:00Z

Summary

Introduces three category scopes (personal / group / system), a PascalCase-with-dashes naming convention, a group-admin role on group memberships, and a full permission model for who can create, rename, and delete categories and documents.

Files Added

  • backend/alembic/versions/e1f2a3b4c5d6_add_group_member_is_admin.py — adds is_group_admin BOOLEAN to group_memberships
  • features/doc-service/alembic/versions/0005_add_share_can_delete.py — adds can_delete BOOLEAN to document_shares (backfill from feat/document-delete-permissions)
  • features/doc-service/alembic/versions/0006_add_category_scope.py — adds scope VARCHAR(16) and group_id VARCHAR to document_categories; data-migrates watch categories to scope='system'

Files Modified

  • backend/app/models/group.py — added is_group_admin to GroupMembership
  • backend/app/schemas/group.py — added is_group_admin to GroupMemberOut; new GroupMemberAdminUpdate
  • backend/app/schemas/user.py — added is_group_admin to UserGroupOut
  • backend/app/routers/users.pyget_my_groups now joins GroupMembership to include is_group_admin
  • backend/app/routers/groups.pyget_group includes is_group_admin; new PATCH /{id}/members/{user_id}/admin endpoint
  • backend/app/routers/categories_proxy.py — injects x-user-is-admin and x-user-admin-groups headers
  • backend/app/routers/documents_proxy.py — injects x-user-admin-groups header (was already injecting x-user-is-admin)
  • features/doc-service/app/models/category.py — added scope, group_id columns
  • features/doc-service/app/schemas/category.pyCategoryOut includes scope/group_id; CategoryCreate accepts group_id
  • features/doc-service/app/deps.py — added get_user_is_admin, get_user_admin_groups
  • features/doc-service/app/routers/categories.py — full rewrite: name validation regex, scope-based list/create, _check_can_manage_cat permission helper, scope-aware rename/delete
  • features/doc-service/app/routers/documents.pydelete_document enforces is_admin/can_delete/group-admin hierarchy; remove_category requires doc ownership; assign_category accepts group/system categories
  • frontend/src/api/client.tsCategoryOut gains scope/group_id; createCategory accepts optional groupId; UserGroupOut/GroupMemberOut gain is_group_admin; new adminSetGroupMemberAdmin(); ApiError exported
  • frontend/src/components/ManageCategoriesDialog.tsx — categories grouped by scope; lock icons for unmanageable categories; rename/delete gated by scope permissions; inline rename error display
  • frontend/src/components/SourcePanel.tsx — categories shown in sections (Mine / Group name / System); scope picker on new category form; client-side name validation
  • frontend/src/pages/AdminGroupsPage.tsx — group admin checkbox column in members table
  • backend/CLAUDE.md — updated group_memberships model, migration chain, endpoints
  • features/doc-service/CLAUDE.md — updated document_categories model, document_shares model, migration chain, deps note