## Summary
UNLISTED views are personal views tied to a specific user, so API keys
should not be able to create them.
## Changes
- Added check in `canUserCreateView` to block API keys from creating
UNLISTED views
- Refactored the service to use smaller functions with early returns (no
nested if/else)
## Behavior Matrix
### Creating Views
| Caller | Visibility | Has VIEWS Permission | Result |
|--------|------------|---------------------|--------|
| User | UNLISTED | (not checked) | ✅ Allow |
| User | WORKSPACE | Yes | ✅ Allow |
| User | WORKSPACE | No | ❌ Denied |
| **API Key** | **UNLISTED** | (not checked) | **❌ Denied** |
| API Key | WORKSPACE | Yes | ✅ Allow |
| API Key | WORKSPACE | No | ❌ Denied |
Fixes#16739
- Remove empty string coercion in createCoreView that caused PostgreSQL
UUID errors for API keys
- Add permission check allowing API keys with VIEWS permission to manage
workspace views they created
API keys with 'Manage Views' permission can now create, update, and
delete workspace views via both GraphQL and REST APIs.
First PR to implement application tokens
- add new application role in twenty-server
- move duplicated constants and types to twenty-shared
- will add role configuration utils into twenty-sdk in another PR
## Overview
This PR strengthens our permission system by introducing more granular
role-based access control across the platform.
## Changes
### New Permissions Added
- **Applications** - Control who can install and manage applications
- **Layouts** - Control who can customize page layouts and UI structure
- **AI** - Control access to AI features and agents
- **Upload File** - Separate permission for file uploads
- **Download File** - Separate permission for file downloads (frontend
visibility)
### Security Enhancements
- Implemented whitelist-based validation for workspace field updates
- Added explicit permission guards to core entity resolvers
- Enhanced ESLint rule to enforce permission checks on all mutations
- Created `CustomPermissionGuard` and `NoPermissionGuard` for better
code documentation
### Affected Components
- Core entity resolvers: webhooks, files, domains, applications,
layouts, postgres credentials
- Workspace update mutations now use whitelist validation
- Settings UI updated with new permission controls
### Developer Experience
- ESLint now catches missing permission guards during development
- Explicit guard markers make permission requirements clear in code
review
- Comprehensive test coverage for new permission logic
## Testing
- ✅ All TypeScript type checks pass
- ✅ ESLint validation passes
- ✅ New permission guards properly enforced
- ✅ Frontend UI displays new permissions correctly
## Migration Notes
Existing workspaces will need to assign the new permissions to roles as
needed. By default, all new permissions are set to `false` for non-admin
roles.