Skip to content

ADR-074 Implementation Checklist

Status: Accepted Started: 2025-12-09 Completed: 2025-12-09 ADR: ADR-074: Platform Admin Role

Phase 1: Database Migration ✅ COMPLETE

  • [x] Create migration file schema/migrations/028_platform_admin_resources.sql
  • [x] Register 15 resource types with available_actions
  • [x] Create platform_admin role with parent_role = 'admin'
  • [x] Grant permissions to contributor role (graph:read, ingest:create, etc.)
  • [x] Grant permissions to curator role (vocabulary:write, ontologies:create)
  • [x] Grant permissions to admin role (users, oauth_clients, read-only platform)
  • [x] Grant permissions to platform_admin role (full platform access)
  • [x] Test migration is idempotent (can run multiple times safely)
  • [x] Apply migration to dev environment

Results: 19 resources, 5 roles, ~83 permission grants

Phase 2: Replace require_role with require_permission ✅ COMPLETE

Replaced Depends(require_role("admin")) with Depends(require_permission("resource", "action")):

Platform Administration (Critical) ✅

  • [x] admin.py - /admin/statusadmin:status
  • [x] admin.py - /admin/backupbackups:create
  • [x] admin.py - /admin/backupsbackups:read
  • [x] admin.py - /admin/restorebackups:restore
  • [x] admin.py - /admin/keys GET → api_keys:read
  • [x] admin.py - /admin/keys/{provider} POST → api_keys:write
  • [x] admin.py - /admin/keys/{provider} DELETE → api_keys:delete

Embedding Configuration ✅

  • [x] embedding.py - /admin/embedding/config GET → embedding_config:read
  • [x] embedding.py - /admin/embedding/configs GET → embedding_config:read
  • [x] embedding.py - /admin/embedding/config POST → embedding_config:create
  • [x] embedding.py - /admin/embedding/config/{id} DELETE → embedding_config:delete
  • [x] embedding.py - /admin/embedding/config/{id}/activateembedding_config:activate
  • [x] embedding.py - /admin/embedding/config/reloadembedding_config:reload
  • [x] embedding.py - /admin/embedding/regenerateembedding_config:regenerate
  • [x] embedding.py - /admin/embedding/statusembedding_config:read
  • [x] admin.py - /admin/regenerate-concept-embeddingsembedding_config:regenerate

Extraction Configuration ✅

  • [x] extraction.py - /admin/extraction/config GET → extraction_config:read
  • [x] extraction.py - /admin/extraction/config POST → extraction_config:write

User Management ✅

  • [x] auth.py - /users GET → users:read
  • [x] auth.py - /users/{id} GET → users:read
  • [x] auth.py - /users/{id} PUT → users:write
  • [x] auth.py - /users/{id} DELETE → users:delete

OAuth Client Management (Admin) ✅

  • [x] oauth.py - /auth/oauth/clients GET → oauth_clients:read
  • [x] oauth.py - /auth/oauth/clients POST → oauth_clients:create
  • [x] oauth.py - /auth/oauth/clients/{id} GET → oauth_clients:read
  • [x] oauth.py - /auth/oauth/clients/{id} PATCH → oauth_clients:write
  • [x] oauth.py - /auth/oauth/clients/{id} DELETE → oauth_clients:delete
  • [x] oauth.py - /auth/oauth/clients/{id}/rotate-secretoauth_clients:write

Ontology Management ✅

  • [x] ontology.py - /ontology/{name} DELETE → ontologies:delete
  • [x] ontology.py - /ontology/{name}/renameontologies:create

RBAC Management ✅

  • [x] rbac.py - All 17 endpoints → rbac:read/write/create/delete

Vocabulary Configuration ✅

  • [x] vocabulary_config.py - /admin/vocabulary/config GET → vocabulary_config:read
  • [x] vocabulary_config.py - /admin/vocabulary/config PUT → vocabulary_config:write
  • [x] vocabulary_config.py - /admin/vocabulary/profiles GET → vocabulary_config:read
  • [x] vocabulary_config.py - /admin/vocabulary/profiles POST → vocabulary_config:create
  • [x] vocabulary_config.py - /admin/vocabulary/profiles/{name} GET → vocabulary_config:read
  • [x] vocabulary_config.py - /admin/vocabulary/profiles/{name} DELETE → vocabulary_config:delete

Vocabulary Operations ✅

  • [x] vocabulary.py - Write operations → vocabulary:write

Results: 9 route files updated, ~60 endpoints migrated to permission-based auth

Phase 3: Verify and Test ✅ COMPLETE

  • [x] Fix require_permission to be sync factory (was incorrectly async)
  • [x] Fix PermissionChecker._get_user_roles to include user's primary_role
  • [x] Fix role hierarchy with migration 029 (admin → curator → contributor)
  • [x] Add api/tests/test_permissions.py for permission coverage testing
  • [x] Test role inheritance (platform_admin → admin → curator → contributor)
  • [x] Verify API starts and responds to authenticated requests
  • [ ] Test explicit deny functionality (deferred - no deny grants yet)
  • [ ] Verify public endpoints still work without auth
  • [ ] Test authenticated-only endpoints (personal OAuth clients, etc.)

Results: 23/23 permission tests passing for admin role

Phase 4: CLI Role Management ✅ COMPLETE (Already Implemented)

CLI commands already existed at kg admin rbac:

  • [x] kg admin rbac role list - List all roles with hierarchy
  • [x] kg admin rbac role show <role> - Show role details with permissions
  • [x] kg admin rbac role create - Create custom role
  • [x] kg admin rbac role delete - Delete custom role
  • [x] kg admin rbac resource list - List all resource types and actions
  • [x] kg admin rbac permission list - List permissions (filterable by role/resource)
  • [x] kg admin rbac permission grant - Grant permission to role
  • [x] kg admin rbac permission revoke - Revoke permission

Also fixed: - [x] kg admin status - Updated AdminService for containerized environment - Replaced docker exec with direct database connections - Check API keys from encrypted database storage - Detect container via /.dockerenv

Phase 5: Web UI Updates ✅ COMPLETE

  • [x] Update AdminDashboard to check permissions per section
  • Added canViewUsers, canViewAllOAuthClients, canViewSystemStatus permission checks
  • Tabs now show/hide based on actual permissions instead of role equality
  • [x] Hide/disable features based on effective permissions
  • "All OAuth Clients" section only shows if user has oauth_clients:read
  • Users tab only shows if user has users:read
  • System tab only shows if user has admin:status
  • [x] Add visual indicator for platform admin users
  • Purple "Platform Admin" badge in header for platform_admin role
  • Role-colored badges in user list (purple=platform_admin, blue=admin, green=curator, gray=contributor)
  • [x] Add /users/me/permissions API endpoint
  • Returns role, role_hierarchy, permissions list, and can map for easy checking
  • [x] Update auth store with permissions state
  • loadPermissions() called after authentication
  • hasPermission(resource, action) helper method
  • isPlatformAdmin() helper method

Results: Permission-based UI visibility implemented with graceful degradation

Phase 6: Documentation ✅ COMPLETE

  • [x] Update docs/reference/api/ADMIN-ENDPOINTS.md
  • Added permission-based access level section
  • Updated all endpoint tables to show required resource:action permissions
  • Added role hierarchy documentation
  • [ ] Add Platform Admin setup to operator docs (deferred - operator workflow unchanged)
  • [ ] Document recovery procedure for self-lockout (deferred - future enhancement)
  • [ ] Update CLAUDE.md with platform admin workflow (not needed - existing RBAC CLI docs cover this)

Progress Log

2025-12-09

  • Created ADR-074 with full resource inventory (15 resources)
  • Updated all API endpoint docstrings with RBAC authorization format
  • Implementation checklist created
  • Phase 1 complete: Migration 028 applied - 19 resources, 5 roles, ~83 permissions
  • Phase 2 complete: Replaced require_role → require_permission in 9 route files (~60 endpoints)
  • Fixed require_permission async/sync bug (was async def, should be def)
  • Fixed PermissionChecker to include primary_role from users table
  • Created migration 029 to fix role hierarchy (admin → curator → contributor)
  • Added api/tests/test_permissions.py for permission coverage testing
  • Phase 3 complete: 23/23 permission tests passing
  • Phase 4 complete: CLI RBAC commands already existed (kg admin rbac)
  • Fixed AdminService for containerized environment (replaced docker exec with direct connections)
  • Phase 5 complete: Web UI updated with permission-based access control
  • Added /users/me/permissions endpoint
  • Updated authStore with loadPermissions(), hasPermission(), isPlatformAdmin()
  • AdminDashboard now uses permission checks instead of role equality
  • Added platform admin badge and role-colored user badges
  • Phase 6 complete: Updated ADMIN-ENDPOINTS.md with permission-based documentation