Permission Catalog
This page is the canonical catalog of Reply Pilot application permissions.
The permission code is the string used by backend and Flask authorization
checks. Keep this page in sync with public.app_permission,
AppPermissionCodes, backend authorization checks, Flask permission gates, and
seeded role grants.
Permission List
| Code | Definition | Scope and important behavior |
|---|---|---|
company.view_assigned |
User can view companies assigned to them. | Assigned company means party_organization.default_email_sales_user_id = app_user.id. Companies without an assigned default email sales user are not visible through this permission alone. Task search reuses this scope: tasks without linked party and tasks linked to non-company parties are visible; company-linked tasks are visible when the linked company is assigned to the user. Exact-task reads also include any active Jira task assigned to the current local user or Jira-account profile. Company delegation remains limited to active assigned Reply Pilot Task items. Normalized Done tasks never delegate access. |
company.view_all |
User can view all companies. | Bypasses the assigned-company read scope for backend read model and search proxy, including task search. No separate task.* or ticket.* permission exists. |
company.write |
User can perform global company write operations. | Accepted for creating self-assigned companies, creating company-linked Reply Pilot Task issues, and existing-company and linked-task mutations, where backend still checks company visibility. |
company.write_assigned |
User can create self-assigned companies and write existing companies and linked tasks within their company visibility scope. | New companies are assigned to the current user as default_email_sales_user_id. For users without company.view_all, existing writes remain limited to companies where the user is the default email communication owner; this also covers creating company-linked Reply Pilot Task issues for visible assigned companies. |
company.merge |
User can merge duplicate companies. | Merge endpoints still require access to the affected company records. |
security.manage_roles |
User can manage role assignments. | Required for listing all roles, reading another user's assigned role IDs, and replacing user roles. Backend prevents removing the last role manager. |
security.impersonate_user |
User can start a controlled impersonation session for another user. | Kept separate from admin. Cannot impersonate self, users with security.manage_roles, or users with security.impersonate_user. Starts are recorded in app_user_impersonation_audit. |
Delegated task read exception: backend read-model company endpoints may also
expose the company linked to an active Reply Pilot Task when the current app
user is its local assignee or the cached Jira assignee matches the user's Jira
profile. This includes the company's notes and activities. Exact-task reads use
the same active-assignee rule for all Jira work types. The assignee may also trigger
POST /api/tasks/{taskId}/refresh-from-jira as read-side cache synchronization;
the backend always uses the Jira key stored on that task and ignores any client
supplied key. Delegation does not expose unrelated companies or unrelated tasks
at the same company and excludes unassigned or normalized Done tasks.
Delegated company collaboration exception: an active assigned Reply Pilot Task
allows its assignee to add company notes, create/update/remove company contact
methods, create a new person linked to the company, and remove a person-company
relationship. A related person's profile, notes, and contacts may be edited only
when the user can collaborate with every active, unmerged company linked through
CONTACT_FOR; a standalone person requires global company.write. Delegation
does not allow company fields, visibility, identifiers, requirements, ownership,
merge, task creation, task-company relinking, or email-thread relinking.
Delegated task mutation exception: assignment to any active Jira task permits
the existing operations for that exact task type, including Supplier Onboarding
edit/reply, Email Reply edit/status/reassignment/send/forward, and Reply Pilot
resolve/reassignment. Reply Pilot close remains requester-only. Jira keys and
work types are loaded and validated server-side; legacy client jira_key fields
are ignored. Changing an Email Reply task's company still requires normal write
access to the source and destination companies. Reassignment or a transition to
normalized Done immediately removes assignment-derived access. No separate
permission code is introduced by these exceptions.
Seeded System Roles
| Role | Permissions | Notes |
|---|---|---|
admin |
company.view_assigned, company.view_all, company.write, company.write_assigned, company.merge, security.manage_roles |
Full normal administration. security.impersonate_user is intentionally not included. |
sales |
company.view_assigned, company.write_assigned |
Can create self-assigned companies and view/mutate assigned companies and their linked tasks. Cannot view unassigned/all companies. |
sales_manager |
company.view_assigned, company.view_all, company.write, company.write_assigned, company.merge |
Can view and mutate all companies and merge companies. |
support_impersonator |
security.impersonate_user |
Dedicated support role for impersonation. |
Maintenance Rules
- When adding, renaming, deleting, or changing the meaning of a permission, update this page in the same change.
- When changing seeded role grants, update the role table above in the same change.
- When changing authorization behavior without changing the database grant, update the scope and important behavior column.
- Keep permission labels and descriptions aligned with Liquibase seed data.