Roles & Permissions
How access works in AEO Optima — org roles, project roles, platform admin tiers, and the V/E/X/A capability model.
How access works
AEO Optima uses three layers of access that combine to decide what each user can do:
- Organization role — your role on the workspace (Owner, Admin, Member, Viewer). Set when you join or are invited.
- Project role (optional override) — your role on a specific project (Project Admin, Project Member, Project Viewer). Set per-project via Settings → Project Team.
- Platform admin tier (operator-only) — Platform Owner (T0) or Tenant Platform Admin (T1). Granted by the platform operator, not via UI.
Permissions are computed from these three together using the V/E/X/A capability model (View / Edit / Execute / Admin). Most users only need to think about layer 1 — the other layers exist for edge cases.
Organization roles
Every member of an org has one of four roles, set at the org level and applied across all projects in that org by default.
Owner
Full, unrestricted access. The owner created the organization, can transfer ownership, and is the only role that can change the billing plan or delete the org. Every org has exactly one owner.
Admin
Almost everything the owner can do — manage team, projects, integrations, API keys, settings — except delete the org or change the billing plan. Ideal for team leads.
Member
Active contributor. Can create and edit projects, prompts, snapshots, schedules, and run any workflow. Cannot invite new members, change roles, manage org settings, or see billing.
Viewer
Read-only across every project in the org. Can browse dashboards, analytics, snapshots, and reports. Cannot create, edit, or trigger anything.
Project roles (optional)
By default, project access is derived from the org role. Project roles override this on a per-project basis — useful for two scenarios:
- Agency clients — an external user is a Viewer at the org level, but you want to give them edit access to their specific project only. Add them to that project with
project_memberand they can edit just that one. - Cross-team contributors — an org Member is a stakeholder on most projects but actually owns one. Give them
project_adminon that project and they can manage its settings + team without changing their org role.
Project roles are set under Settings → Project Team on each project.
| Project role | What it means |
|---|---|
| Project Admin | Full management of this project — settings, members, schedules, integrations |
| Project Member | Write-capable on this project — edit prompts, trigger captures, manage content |
| Project Viewer | Read-only on this project, even if their org role would grant write elsewhere |
Precedence rule: If a user has both an org role and a project role on a project, the more permissive of the two applies. An org admin who's set to project_viewer on Project X still has admin access there (org role wins on the upper end). An org viewer who's project_member on Project X gets edit access on that one project (project role elevates on the lower end).
The V/E/X/A capability model
Every action in the app maps to one of four capabilities. This is what the system actually checks under the hood — role names are just shorthand.
| Capability | Meaning | Typical actions |
|---|---|---|
| View | Read access | Browse dashboards, see snapshot results, read reports |
| Edit | Write to data | Create/edit prompts, projects, brand facts, schedules |
| Execute | Trigger an operation | Run a snapshot, generate a report, run a GEO audit |
| Admin | Manage scope | Invite/remove members, change roles, configure integrations, delete |
| Capability | Owner | Admin | Member | Viewer | Project Admin | Project Member | Project Viewer |
|---|---|---|---|---|---|---|---|
| View | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Edit | ✓ | ✓ | ✓ | — | ✓ | ✓ | — |
| Execute | ✓ | ✓ | ✓ | — | ✓ | ✓ | — |
| Admin (project) | ✓ | ✓ | — | — | ✓ | — | — |
| Admin (org) | ✓ | ✓ | — | — | — | — | — |
Today Edit and Execute behave identically. They're kept separate so a future tier can allow "trigger a capture" without allowing "edit prompt text" — for example, a contractor who runs captures but doesn't touch the prompt library.
Platform admin tiers
Two operator-only tiers exist on top of the org/project model. These are granted by the platform operator (via env-var allowlist for T0; via the platform admin console for T1) — there's no self-service for either.
T0 — Platform Owner
Cross-organization god-mode. Used by the platform operator to manage the multi-tenant platform itself.
- Switch into any organization via the sidebar org switcher
- Access the Platform Cockpit (runway, infra balance, killswitches, override approvals)
- View cost intelligence across every tenant
- Pause/resume any organization, allocate credits, run support sessions
- See platform-scope alerts (OpenRouter balance, Render plan utilization, etc.)
- Every override is audit-logged with
actorRole: platform_admin
T0 status is granted via the PLATFORM_ADMIN_EMAILS environment variable. The org switcher and capability hooks treat T0 as the highest tier of access on every org.
T1 — Tenant Platform Admin
Org-scoped admin grant designed for enterprise customers who delegate operational ownership to a specific contact (often the customer's IT/security lead). T1 admins manage exactly one organization at platform-admin elevation, without being a regular org member.
- Visibility into their tenant org's budget alerts, audit logs, cost data, and team
- Cannot switch into other organizations
- Cannot see platform-scope cockpit data (that's T0 only)
- Cannot grant T1 to other users (T0 only)
T1 requires Enterprise plan. The platform_admins table has a database-level trigger (trg_enforce_t1_requires_enterprise_pa) that rejects T1 grants against non-Enterprise orgs. This is enforced at write time and cannot be bypassed via the UI.
Checking your role
Your current role is displayed in the header dropdown. Platform admins see "Platform Admin" or "Platform Admin (Tenant)" instead of "Owner" — the label reflects your actual identity even when the system grants you owner-level access for the current org.
If you need elevated access, contact an org owner/admin and ask them to update your role under Settings → Team (for org roles) or Settings → Project Team on the specific project (for project roles).
Managing team members
Owners and admins manage team membership under Settings → Team:
- Invite new members — Send an email invitation with a pre-assigned role.
- Change roles — Promote/demote members between Owner, Admin, Member, Viewer.
- Remove members — Revoke access.
For project-level roles, use Settings → Project Team on the specific project. Adding a row there overrides the user's org-level access for that one project (see precedence rule above).
Invitations vs join requests
Two ways to add team members:
- Invitations (admin-initiated) — an owner/admin sends an email with a direct accept link.
- Join requests (user-initiated) — a user requests to join; an owner/admin reviews and approves with a chosen role.
Invitations are immutable once sent — the role can't be changed after the invite is created. Cancel and resend if you need a different role.
Best practices
- Principle of least privilege. Start with the lowest role that fits the responsibility. Upgrade as needed.
- Use Viewer for stakeholders. Executives, clients, external reviewers — anyone who needs to see reports but shouldn't change anything.
- Use project roles for client engagements. Set the user as an org Viewer + add them to specific projects as
project_member. This is the recommended pattern for agency-style work where each client should only see their own project. - Keep T0 to one or two people. Platform Owner is for the platform operator. Even within the operator's team, the principle of least privilege still applies.
- Reserve T1 for Enterprise customers with a clear operational reason for cross-membership admin access.
- Review roles quarterly. As responsibilities shift, roles should follow.
Audit trail
Every privileged action writes a row to audit_logs. T0/T1 override actions are tagged with actorRole: platform_admin and impersonated: true so you can distinguish operator overrides from regular customer activity in the audit feed.
Next steps
- Quick Start Guide — Set up your first project
- Core Concepts — Data model and terminology