Skip to content

Role-Based Access Control (RBAC)

The GenAI IDP Accelerator implements a comprehensive Role-Based Access Control system with server-side enforcement at the AppSync API layer, supplemented by UI-level navigation and action controls for a clean user experience. It also supports config-version scoping to restrict non-admin users to specific configuration versions (use cases).

Four roles are defined as Cognito User Pool groups:

RoleCognito GroupDescription
AdminAdminFull access to all operations including user management and pricing
AuthorAuthorRead + write access to documents, configuration, tests, discovery
ReviewerReviewerHITL review operations + limited document visibility
ViewerViewerRead-only access to documents, configuration, agent chat

Users can belong to multiple groups. Permissions are the union of all group permissions. For example, a user in both Author and Reviewer groups can both write documents and perform HITL reviews.

Feature / API Admin Author Reviewer Viewer
──────────────────────────────────────────────────────────────────────
DOCUMENTS
List documents ✅ ✅† ✅*† ✅†
View document details ✅ ✅† ✅*† ✅†
Upload documents ✅ ✅ ❌ ❌
Delete documents ✅ ✅ ❌ ❌
Reprocess documents ✅ ✅ ❌ ❌
Abort workflows ✅ ✅ ❌ ❌
HITL REVIEW
Claim/Release review ✅ ❌ ✅ ❌
Complete section review ✅ ❌ ✅ ❌
Skip all section reviews ✅ ❌ ✅ ❌
Process changes (edit mode) ✅ ❌ ✅ ❌
CONFIGURATION
View config versions ✅ ✅† ❌ ✅†
View/Edit configuration ✅ ✅ ❌ ❌
Save as Version (new) ✅ ❌ ❌ ❌
Save as Default ✅ ❌ ❌ ❌
Delete config version ✅ ❌ ❌ ❌
Set active version ✅ ✅ ❌ ❌
Sync BDA ✅ ✅ ❌ ❌
DISCOVERY
List/run discovery jobs ✅ ✅ ❌ ❌
AGENT CHAT & CODE EXPLORER
Chat with agent ✅ ✅ ❌ ✅
Code intelligence ✅ ✅ ❌ ✅
TEST STUDIO
View/run test sets ✅ ✅ ❌ ❌
Create/delete test sets ✅ ✅ ❌ ❌
CAPACITY PLANNING
Calculate capacity ✅ ✅ ❌ ✅
USER MANAGEMENT
List all users ✅ ❌ ❌ ❌
Create/delete users ✅ ❌ ❌ ❌
Edit user scope ✅ ❌ ❌ ❌
View own profile ✅ ✅ ✅ ✅
PRICING
View pricing ✅ ✅ ❌ ✅
Edit pricing ✅ ❌ ❌ ❌
✅* = Reviewer sees only HITL-pending docs + their own completed reviews (server-side filtered)
✅† = Scoped by allowedConfigVersions if set (see Config-Version Scoping below)

Config-Version Scoping (Use Case Isolation)

Section titled “Config-Version Scoping (Use Case Isolation)”

Non-admin users can optionally be assigned allowedConfigVersions — a list of configuration version names that restricts their view and access to only those use cases. This enables multi-tenant or multi-use-case deployments where different teams see only their relevant documents and configurations.

  • Admin users: Always unrestricted — allowedConfigVersions is ignored even if set
  • All other roles (Author, Reviewer, Viewer): If allowedConfigVersions is set and non-empty, the user can only:
    • See documents processed with those config versions (server-side filtering)
    • See and select those config versions in all version dropdowns
    • View/edit configuration for those versions only
  • No scope set (empty/null): User sees all versions and documents (unrestricted)
LayerEnforcement
Document List (server-side)listDocuments Lambda resolver filters by ConfigVersion field using allowedConfigVersions from UsersTable
Config Versions List (server-side)getConfigVersions Lambda resolver filters returned versions
Config Version Access (server-side)getConfigVersion Lambda resolver rejects requests for out-of-scope versions
Version Dropdowns (UI)useConfigurationVersions hook filters versions client-side for immediate UX
Default Version Selection (UI)All version pickers auto-select the first available scoped version

All pages with config version selectors automatically respect scope:

PageBehavior
View/Edit ConfigurationShows only scoped versions in Versions panel; loads first scoped version
Upload DocumentsVersion picker shows only scoped versions
DiscoveryVersion picker shows only scoped versions
Test StudioTest runner version picker shows only scoped versions
Capacity PlanningVersion picker shows only scoped versions
Reprocess DocumentDefaults to document’s current ConfigVersion (if in scope)
Document ListServer-side filtered — only shows documents matching scoped versions

Admins can manage user scope via the User Management page:

  1. Create user with scope: When creating a new user, optionally select config versions from the multiselect
  2. Edit user scope: Click “Edit scope” on any non-Admin user row to add/remove config versions
  3. Remove scope: Clear all selections to make a user unrestricted

Admin users’ scope cannot be edited (they are always unrestricted).

All authenticated users can call getMyProfile to retrieve their own profile including allowedConfigVersions. This is used by the UI to apply client-side scope filtering immediately on page load.

query GetMyProfile {
getMyProfile {
userId
email
persona
allowedConfigVersions
}
}
mutation UpdateUser($userId: ID!, $allowedConfigVersions: [String]) {
updateUser(userId: $userId, allowedConfigVersions: $allowedConfigVersions) {
userId
email
allowedConfigVersions
}
}

Layer 1: AppSync Schema Auth Directives (Server-Side)

Section titled “Layer 1: AppSync Schema Auth Directives (Server-Side)”

Every GraphQL mutation and many queries have @aws_auth(cognito_groups: [...]) directives that enforce access at the AppSync level. If a user’s Cognito group is not in the allowed list, AppSync returns an Unauthorized error before any resolver code runs.

Key mutations and their allowed roles:

MutationAllowed Roles
deleteConfigVersionAdmin
createUser, updateUser, deleteUserAdmin
updatePricing, restoreDefaultPricingAdmin
deleteDocument, updateConfiguration, setActiveVersionAdmin, Author
uploadDocument, reprocessDocument, abortWorkflowAdmin, Author
startTestRun, addTestSet, addTestSetFromUpload, deleteTests, deleteTestSetsAdmin, Author
syncBdaIdp, uploadDiscoveryDocument, deleteDiscoveryJob, autoDetectSectionsAdmin, Author
copyToBaselineAdmin, Author
processChanges, completeSectionReview, claimReview, releaseReview, skipAllSectionsReviewAdmin, Reviewer
sendAgentChatMessage, deleteChatSession, updateChatSessionTitle, deleteAgentJobAll authenticated users (see note below)
updateAgentChatMessageAll authenticated users (also IAM for backend)

AppSync Limitation: Agent Chat mutations and queries require both @aws_cognito_user_pools and @aws_iam (for backend Lambda calls and return type resolution). AppSync does not support @aws_auth(cognito_groups: [...]) combined with @aws_iam on the same field — it causes “Not Authorized” errors for all users. Therefore, Agent Chat mutations (sendAgentChatMessage, deleteChatSession, etc.) and queries (listAvailableAgents, listChatSessions, getChatMessages) use @aws_cognito_user_pools @aws_iam instead. Reviewer exclusion from Agent Chat is enforced via UI navigation (Agent Chat page is hidden for Reviewer) and session scoping (each user only sees their own sessions).

Key queries and their allowed roles:

QueryAllowed Roles
getDocument, listDocuments, listDocumentsByDateRange, etc.All authenticated (server-side filtering in resolvers)
getFileContents, getStepFunctionExecutionAll authenticated
getConfigVersions, getConfigVersion, getPricing, calculateCapacityAdmin, Author, Viewer
listAvailableAgents, listChatSessions, getChatMessages, getAgentChatMessagesAll authenticated (UI-enforced, see AppSync limitation above)
submitAgentQuery, getAgentJobStatus, listAgentJobsAdmin, Author, Viewer
listConfigurationLibrary, getConfigurationLibraryFileAdmin, Author, Viewer
listDiscoveryJobsAdmin, Author
getTestRun, getTestRuns, getTestRunStatus, compareTestRuns, getTestSets, listBucketFiles, validateTestFileNameAdmin, Author
queryKnowledgeBase, chatWithDocumentAll authenticated
listUsersAll authenticated (non-admin sees only self in resolver)
getMyProfileAll authenticated

Note: The updateConfiguration mutation is schema-level restricted to Admin+Author, but the resolver additionally enforces that saveAsVersion and saveAsDefault operations within that mutation are Admin-only.

Lambda resolvers apply additional filtering based on the caller’s identity:

Document Filtering:

  • Admin: See all documents
  • Author/Viewer: See all documents, filtered by allowedConfigVersions if scope is set
  • Reviewer-only: See only HITL-pending documents + their own completed reviews, plus config-version scope

Configuration Filtering:

  • getConfigVersions: Returns only versions in user’s scope (or all if unrestricted)
  • getConfigVersion: Rejects request if version is not in user’s scope

User Management Filtering:

  • listUsers: Admin sees all users; non-admin sees only their own profile
  • getMyProfile: Returns the calling user’s own profile (including allowedConfigVersions)

The UI adapts based on the user’s role and scope:

  • Navigation sidebar shows only relevant features per role
  • Action buttons (delete, reprocess, upload, save, import) are hidden for roles that can’t perform those actions
  • Version dropdowns are automatically filtered to show only scoped versions
  • The top navigation badge shows the user’s role with color coding (blue=Admin, green=Author, grey=Reviewer/Viewer)
  • Admin-only buttons: “Save as Version”, “Save as Default” in Configuration; Import/Restore/Save in Pricing
  • Pricing page: Shows “View Pricing” (read-only) for non-admin; “Pricing Configuration” (editable) for admin

This layer is NOT a security boundary — it’s purely for user experience. Security is enforced at Layers 1 & 2.

Admins can create users with any of the four roles via the User Management page. Each user is:

  1. Created in DynamoDB (source of truth)
  2. Synced to Cognito (for authentication)
  3. Added to the appropriate Cognito group (for authorization)
  4. Optionally assigned allowedConfigVersions for config-version scoping
FieldDescription
userIdUnique identifier (UUID)
emailUser’s email address (used as Cognito username)
personaRole: Admin, Author, Reviewer, or Viewer
statusUser status (active)
allowedConfigVersionsOptional list of config version names for scoping
createdAtCreation timestamp
┌─────────────────────────────────┐
│ Browser (UI) │ Layer 3: Navigation/button hiding + scope filtering (UX only)
│ useUserRole + getMyProfile │
│ useConfigurationVersions │ ← Filters versions by allowedConfigVersions
└────────────┬────────────────────┘
│ GraphQL
┌────────────▼────────────────────┐
│ AppSync API │ Layer 1: @aws_auth directives (DENY if wrong group)
│ Schema Directives │
└────────────┬────────────────────┘
┌────────────▼────────────────────┐
│ Lambda Resolvers │ Layer 2: Server-side filtering
│ • listDocuments: ConfigVersion │ ← Filters by allowedConfigVersions from UsersTable
│ • getConfigVersions: scope │ ← Filters version list
│ • getConfigVersion: scope │ ← Rejects out-of-scope access
│ • listUsers: self-only │ ← Non-admin sees only own profile
└────────────┬────────────────────┘
┌────────────▼────────────────────┐
│ DynamoDB │
│ TrackingTable (documents) │
│ ConfigurationTable (versions) │
│ UsersTable (scope data) │
└─────────────────────────────────┘

To add a new role:

  1. Add a AWS::Cognito::UserPoolGroup in template.yaml
  2. Add the group name to relevant @aws_auth directives in schema.graphql
  3. Update the VALID_PERSONAS dict in src/lambda/user_management/index.py
  4. Add role detection in src/ui/src/hooks/use-user-role.ts
  5. Add navigation items in src/ui/src/components/genaiidp-layout/navigation.tsx
  6. Pass the new group as an environment variable to the UserManagement Lambda
  • Knowledge Base queries do not currently enforce config-version scope. KB results may include documents from out-of-scope config versions.
  • Agent Companion Chat analytics queries (Athena) do not filter by config-version scope.
  • GetDocument API (direct document access by URL) does not enforce config-version scope at the resolver level. UI navigation hides out-of-scope documents, but direct API access is not blocked.
  • These limitations are tracked for Phase 3 implementation.