Teams and users
Every person who uses Onnie in your organization is a workspace member with an assigned role. Teams let you group members so you can assign work or set context without listing individuals. Roles and row-level security together control what each person can see and do.
Members and roles
Workspace membership is tracked in the workspace_members table. Each member has exactly one of three roles:
| Role | What it means |
|---|---|
viewer | Can read projects (public ones), tables, tasks, and pages. Cannot create or update anything. |
editor | Can create and edit projects, tables, tasks, pages, routines, and bots. Cannot manage members or billing. |
admin | Everything an editor can do, plus invite and remove members, create teams, change roles, manage API keys, and update billing. |
The workspace owner is a special case. The owner always has full admin privileges and additionally can delete the workspace and transfer ownership to another member. The owner is stored in workspaces.owner_id — distinct from the workspace_members role column.
Role checks are enforced in the database via row-level security helper functions (is_workspace_member, is_workspace_editor, is_workspace_admin). Application code cannot bypass them.
Inviting members
Admins can invite people to the workspace from Settings → Members → Invite.
When you invite by email:
- An invitation record is created in
workspace_invitationswith statuspendingand the role you selected. - The invitee receives an email with a link. Once they click through and authenticate, the invitation transitions to
acceptedand aworkspace_membersrow is created. - Invitations can expire —
expires_atis set when the invitation is created with an expiry. Expired invitations can be re-sent.
In either case, only admins can create invitations (workspace_invitations: admin insert RLS policy).
Permissions model
Row-level security governs access at the data layer. Here is a plain-English summary of what each role can do across the major entity types:
| Entity | Viewer | Editor | Admin |
|---|---|---|---|
| Workspace (read) | ✓ | ✓ | ✓ |
| Workspace (update name/icon) | — | ✓ | ✓ |
| Projects (public, read) | ✓ | ✓ | ✓ |
| Projects (create/edit/delete) | — | ✓ | ✓ |
| Tables, tasks, pages (read) | ✓ | ✓ | ✓ |
| Tables, tasks, pages (write) | — | ✓ | ✓ |
| Routines, bots, skills (write) | — | ✓ | ✓ |
| Members (invite/remove/change role) | — | — | ✓ |
| Teams (create/edit) | — | — | ✓ |
| API keys (create/revoke) | — | — | ✓ |
Private projects add a further layer: only the members explicitly listed in project_members — plus workspace admins — can read or write a private project's content.
Teams
Teams are named groups of workspace members (workspace_teams and team_members tables). They are purely organizational — you use them in the assignment picker, in bot instructions, and in skill references.
An admin creates a team under Settings → Teams and adds workspace members to it. A member can belong to multiple teams. Teams do not change the underlying role — a viewer added to a team is still a viewer.
Removing members
Admins can remove a member from Settings → Members. The workspace_members row is deleted, which the database cascades into:
- Team membership. The member is removed from all teams they belonged to in this workspace.
- Tasks. Tasks that were assigned to the removed member stay in place — they become unassigned. No task data is deleted.
- Project membership. Project membership in private projects is NOT automatically cleaned up when a workspace member is removed. An admin should manually remove the user from any private projects they no longer need access to. (If the user is deleted from
auth.usersentirely, the cascade applies.)
Chat history is not affected. Each user's conversations in engine_chats and engine_messages are private to that user. Workspace admins cannot read other users' chats — there is no admin override on the RLS policies for those tables. When a member is removed, their chat history stays in the database scoped to their user ID and is inaccessible to anyone else in the workspace.
A member can also remove themselves from a workspace using the same delete path (workspace_members: admin or self delete RLS policy).
Ownership transfer
The workspace owner is the person in workspaces.owner_id. There is exactly one owner per workspace at all times. To transfer ownership, the current owner opens Settings → Danger Zone → Transfer workspace and selects another member. After the transfer the previous owner becomes a regular admin unless they remove themselves.
Only the owner can transfer ownership or delete the workspace. Admin-role members cannot do either.
Bots as collaborators
Onniebots are not workspace members in the workspace_members sense — they don't have a role entry in that table — but they act as collaborators: they can be assigned Tasks, they appear in the assignment picker, and they can take actions on behalf of the workspace within the tools they are allowed. Bot identities are tracked in engine_bots scoped to workspace_id.
See AI Agents for how to create and configure bots.