# Who can do what

The Markdown copy of <https://yeeted.ai/docs/who-can-do-what.html>.

A shared Yeeted project has one owner and any number of members, each with a role. When a person works through an AI agent, a second set of limits applies: the permissions that person gave that agent connection. This guide lists what each role can do, where to do it on the dashboard and through your agent, and answers the situations people most often find confusing.

ON THIS PAGE

- [The four roles](https://yeeted.ai/docs/who-can-do-what.html#roles)
- [What each role can do](https://yeeted.ai/docs/who-can-do-what.html#matrix)
- [Where to do each thing](https://yeeted.ai/docs/who-can-do-what.html#where)
- [Agent permissions and roles together](https://yeeted.ai/docs/who-can-do-what.html#agents)
- [Inviting people](https://yeeted.ai/docs/who-can-do-what.html#invitations)
- [Main, branches, production and hotfixes](https://yeeted.ai/docs/who-can-do-what.html#lines)
- [Project-wide settings in yeeted.yaml](https://yeeted.ai/docs/who-can-do-what.html#settings)
- [Secrets, databases and what development code sees](https://yeeted.ai/docs/who-can-do-what.html#data)
- [Edge cases](https://yeeted.ai/docs/who-can-do-what.html#edge-cases)

## The four roles

- **owner**: the account the project belongs to. There is exactly one, and sharing cannot change who it is. Everything a member does on the project is billed to the owner's plan and limited by it.
- **admin**: everything the owner can do except delete the project, grant the admin role, or change or remove another admin.
- **developer**: reads everything, changes code, and works in development: deploys, secrets that are for development only, and development databases. Production stays with the owner and admins.
- **read_only**: reads the code, clones it, and sees logs and status. Changes nothing, and sees no secrets or databases.

## What each role can do

| Action | owner | admin | developer | read_only |
| --- | --- | --- | --- | --- |
| Read code, clone or download it, read logs and status | Yes | Yes | Yes | Yes |
| Edit code on main and on ordinary branches, upload source, revert on main, claim files | Yes | Yes | Yes | No |
| Ship a branch to main and deploy to development | Yes | Yes | Yes | No |
| Deploy to production or promote to production | Yes | Yes | No | No |
| Roll back, save a checkpoint | Yes | Yes | Development only | No |
| Start, edit and ship a production hotfix | Yes | Yes | No (can read and preview one) | No |
| Secrets for development only: list, set, replace, delete | Yes | Yes | Yes | No |
| Production and shared secrets: set, replace, delete | Yes | Yes | No (sees their names) | No |
| Development databases | Yes | Yes | Attach, read schema, query. Not export, snapshot, move, rotate, restore or delete | No |
| Production databases | Yes | Yes | No (can see that they exist) | No |
| Custom domains: add, verify, remove | Yes | Yes | No (can list them) | No (can list them) |
| Apply project-wide yeeted.yaml settings (WAF, depends_on, repo, custom domains) | Yes | Yes | Can edit the file; it is applied only by the owner or an admin | No |
| Invite people, raise or lower roles | Yes, any role | developer and read_only | No | No |
| Remove people | Anyone but the owner | developers and read_only members | No | No |
| Leave the project | No | Yes | Yes | Yes |
| Delete the project | Yes | No | No | No |

Through an agent, each of these also needs the matching [agent permission](https://yeeted.ai/docs/who-can-do-what.html#agents).

## Where to do each thing

On the dashboard, open a shared project from the **Projects** tab; the project page shows your role next to its name. Through an agent, ask in plain words; the tool names are listed so you can recognise them in your agent's replies.

| Action | Dashboard | Agent (MCP tool) |
| --- | --- | --- |
| Read and clone code | Project page: **Download source**. Projects tab: **Source** | `source_read`, `source_tree`, `source_search`, `source_git_token` (clone), `source_export` |
| Logs and status | **Logs & Metrics** tab; **Services** tab, then the service | `status`, `logs_query`, `build_logs`, `diagnose` |
| Edit code, branches, revert | Project page: **Upload source** (a whole archive). File edits and branches are agent only | `source_edit` (with `branch` for a branch), `source_upload`, `revert` |
| Coordinate with other agents | Not on the dashboard | `source_status`, `source_events`, `source_claim`, `source_release`, `source_task_done` |
| Ship to main, deploy development | Project page: **Deploy**, then **Cancel** in the dialog (it reads "OK = production, Cancel = development"). Services tab: **Relaunch** on a failed or destroyed service | `ship`, `deploy` (development is the default), `deploy(branch=...)` for a preview, `redeploy` |
| Deploy or promote production | Project page: **Deploy**, then **OK** in the dialog (builds the stored main for production) | `promote`, `deploy(service_type="production")` |
| Roll back, checkpoint | Not on the dashboard | `rollback`, `checkpoint`, `versions_list` |
| Hotfix | Not on the dashboard | `hotfix`, then `source_edit(branch=...)`, `deploy(branch=...)`, `ship(branch, to="production")` |
| Secrets | **Secrets** tab: pick the project, name, value and environment, then **Set secret**; **Delete** on a row | `secrets_list`, `secrets_set`, `secrets_delete` |
| Databases | **Databases** tab: **Export** (every engine except Redis), **Restore**, **Move**, **Rotate**, **Delete** | `database_attach`, `database_list`, `database_schema`, `database_query`, `database_export`, `database_snapshot`, `database_move`, `database_rotate_password`, `database_restore`, `database_delete` |
| Custom domains | **Domains** tab: **Add domain**, **Verify**, **Remove**. Service page, Custom domains: **Save domain** | `domains_list`, `domain_set`, `domain_verify`, `domain_remove` |
| Project-wide yeeted.yaml settings | The settings question on **Deploy** (see [below](https://yeeted.ai/docs/who-can-do-what.html#settings)). Project page: **Link GitHub repo** or **Edit repo link** | `apply_settings=true` on `deploy`, `redeploy`, `ship` or `promote` |
| Invite, change roles, remove | Project page, **Members**: email, role, **Invite**; the role list on a member's row; **Remove**; under Open invitations, **Confirm** and **Withdraw** | `project_share` (asks only), `project_members`, `project_unshare` |
| Accept or decline an invitation | **Invitations** tab: **Accept**, **Decline** | Agents cannot. `invites` lists what is waiting |
| Leave a project | Project page, **Members**: **Leave** on your own row | `project_unshare` with your own email (needs Share projects) |
| Delete the project | **Services** tab: **Delete** (stored code is kept for 30 days) | `project_delete` |
| Choose what an agent may do | **Connect agent** tab, Connected agents: **Permissions**, tick, **Save permissions**. OAuth credentials for CI and scripts have the same button | `whoami` shows what the connection holds; agents cannot change it |

## Agent permissions and roles together

An agent acts as the person who connected it. Each connection carries the permissions that person chose for it, on the permissions step when it first connects or later on the **Connect agent** tab. An agent can do something only when **both** allow it: the person's role on the project and the connection's permissions. Neither one widens the other. On the dashboard, signed in yourself, only your role applies.

| Permission | What it covers |
| --- | --- |
| Deploy apps | deploy, redeploy, promote, rollback, checkpoints, smoke tests |
| Read logs | build and app logs, diagnosis, health |
| Manage secrets | listing secret names, setting secrets |
| Manage databases | attach, query, export, snapshot, move, rotate, replicate |
| Manage domains | adding, verifying and listing custom domains |
| Read and change source code | reading, cloning, editing and uploading code, branches, hotfixes, revert, claims |
| Share projects | asking to share, listing members, removing people |
| Delete projects, databases, secrets; restore databases; remove domains | each destructive action separately. These are never ticked for a new connection |

Shipping a branch needs both Deploy apps and Read and change source code. Deleting a project also needs Delete databases and Delete secrets, because it removes them. A tool whose permission the connection lacks is hidden from the agent, and asking for it anyway is refused. A tool the connection holds is listed whatever your role on a given project is; your role is checked when the agent uses it. Each person chooses permissions for their own connections: a project's owner does not set them for a member's agent.

### Worked examples

- **A developer whose agent connection has no Manage secrets permission.** The agent does not see `secrets_list` or `secrets_set`, and `project_context` leaves out the secrets section, naming it as not granted. The developer can still set a development secret on the Secrets tab, and the deployed app still receives every secret it is given: the permission limits the agent, not the app.
- **An admin's agent without Deploy apps.** It can read and edit code (with Read and change source code), but it cannot deploy, promote, roll back or ship, because shipping deploys. The admin can deploy from the dashboard, or tick Deploy apps for that connection.
- **An agent asked to share a project.** It needs Share projects, and its person must be the owner or an admin. `project_share` only asks: the invitation waits on the project's Members panel until the owner or an admin clicks **Confirm**, then the invited person is emailed and accepts on their own Invitations tab. A developer's agent is refused, and an admin's agent asking for the admin role is refused, because only the owner grants it.
- **A read_only member's agent with every permission ticked.** It can read and clone the code, read logs and check status. Every change it tries (an edit, a deploy, a secret, a database query) is refused by the role, with a reply saying so. Its `project_context` shows no secrets or databases, because a read_only member sees neither.

## Inviting people

Sharing needs two people to agree: someone who may grant the access, and the person receiving it.

- **From the dashboard**, the owner or an admin enters an email and role in the Members panel and clicks **Invite**. The invitation goes straight to that person.
- **Through an agent**, `project_share` only requests it. It appears under Open invitations as "requested by ... through an agent; needs your confirmation" until the owner or an admin clicks **Confirm**. Until then the invited person sees nothing and gets no email.
- **The invited person** signs in with the address the invitation was sent to and clicks **Accept** on the Invitations tab. They need a Yeeted account but no plan of their own.
- An invitation expires 7 days after it was first made, whether it was waiting for confirmation or for acceptance, so a late confirmation leaves the invited person less time. An open invitation can be withdrawn at any time, and a person can have only one open invitation per project.
- **Raising a role** (picking a higher role on a member's row) is a new invitation the member accepts. **Lowering** takes effect at once. Only the owner grants admin, and only the owner can change or remove an admin.
- **Leaving**: any member but the owner can leave with **Leave**. Removing or lowering someone also withdraws the invitations they had sent.
- **Billing**: deploys, databases and usage on a shared project count against the owner's plan, never the member's.
- **Erasure**: when a member erases their account, they disappear from every member list and their invitations are removed. When an owner erases theirs, their projects are deleted and every member loses access.

## Main, branches, production and hotfixes

- **main** is the project's code. The owner, admins and developers edit it with `source_edit`, or on a branch with `source_edit(branch=...)`, and `ship` merges a branch into main and deploys development.
- **Production** runs a tested development build: `promote` moves it there. That is for the owner and admins.
- **prod** is the exact code production runs. A **hotfix** is a branch started from prod with `hotfix` (or `source_edit(branch, from="prod")`), previewed with `deploy(branch=...)` and shipped with `ship(branch, to="production")`; Yeeted then merges it into main. Starting, editing and shipping a hotfix is for the owner and admins, even to main. A developer can read a hotfix branch and deploy its preview.
- A hotfix may not change the database schema: migrations, ORM model and schema files and any `.sql` file are refused. Make those changes on main and ship them through development.
- `revert` undoes a range of changes on main as one new commit; it is a code change, so developers can use it.
- Claims (`source_claim`) tell other agents you are working on some files. They never block anyone. Developers and up can claim and close tasks; only the owner or an admin can clear someone else's claim.

## Project-wide settings in yeeted.yaml

Most of yeeted.yaml describes the app, but four settings belong to the whole project: `waf`, `depends_on`, `repo` and the custom domain of each environment. A developer may edit these lines, but only the owner or an admin applies them. When a deploy uses code Yeeted already stores (a deploy by commit, `redeploy`, `ship`, `promote`, or the dashboard's Deploy and Relaunch) and that code's yeeted.yaml differs from what the project runs with, the difference is **held**:

- **Owner or admin on the dashboard**: before anything deploys, a question lists each change as "setting: current -> new". **OK** deploys and applies them; **Cancel** deploys the code and keeps the current settings.
- **Owner or admin through an agent**, when the client does not ask (see the next point): the code deploys, the project keeps its settings, and the reply lists them as held. Repeat the same call with `apply_settings=true` after reading the list to apply them.
- **Owner or admin through an agent whose AI client can show a question**: before anything deploys (for `ship`, before it merges), the client asks you directly, listing each change. **Apply** deploys and applies them; **Deploy without** deploys the code and keeps the current settings; **Cancel** deploys nothing. With no answer within 45 seconds the code deploys and the settings are held, as above. Clients that cannot show the question work as in the previous point, with `apply_settings`. Developers are never asked.
- **Developer**: the code deploys and the settings are not applied; `apply_settings` is ignored. The next owner or admin deploy of that code lists them.

`source_blame` on yeeted.yaml shows who wrote each line. To drop a held change, change yeeted.yaml back.

## Secrets, databases and what development code sees

A secret is shared (used by both environments) or set for development or production only; one set for an environment overrides the shared value there. Nobody can read a secret's value back, owner included; only the running app receives it. A developer may set and delete development-only secrets and sees the names of all of them.

A developer's code runs in development with everything development has: secrets shared with both environments, the development copy of production data where your plan makes one, and your other development services. Give developer access only to people you would trust with that.

## Edge cases

### Why did my deploy skip my yeeted.yaml changes?

If you are a developer, project-wide settings (WAF, depends_on, repo, custom domains) are applied only by the owner or an admin; your code deployed without them. If you are the owner or an admin deploying through an agent, they were held because your client could not ask you, nobody answered in time, or you chose to keep the current settings: repeat the call with `apply_settings=true` to apply them. A yeeted.yaml that does not validate applies nothing, and custom domains also need the agent's Manage domains permission.

### Why was my promote refused?

The reply says which case it is. What you are promoting is older than production (it lacks a fix production runs): to go back to an earlier version use `rollback`, otherwise deploy main to development and promote that. A shipped hotfix has not reached main yet because of a conflict: resolve it with `source_edit(branch=<hotfix>, merge_main=true)`, `ship` it, then promote. There is no development build yet: deploy development first. Your role is developer or read_only: ask the owner or an admin.

### Why was my hotfix refused?

The branch did not start from prod, it changes schema files, it lacks something production already runs, it carries commits merged in from main, or its tip has no tested preview. Start a fresh hotfix from prod for the first three, have the owner or an admin ship it into main for the fourth, and run `deploy(branch=...)` for the last.

### Why can't my developer edit the hotfix branch?

A hotfix goes to production, so starting, editing and shipping one is for the owner and admins, even shipping it to main. Your developer can read it and deploy its preview, and can make the same fix on main or an ordinary branch.

### My invitation says it is waiting for confirmation.

It was requested through an agent. The project's owner or an admin opens the project's Members panel and clicks **Confirm**. Only then is the invited person emailed.

### The person I invited sees nothing on their Invitations tab.

It may still need confirmation, it may have expired (7 days from when it was first made) or been withdrawn, or they are signed in with a different email address than the one invited.

### I was raised to admin but nothing changed.

A higher role is an invitation. Open the Invitations tab and click **Accept**. Only the owner can offer admin.

### Accepting says the person who invited me can no longer grant this.

Their own role was lowered or they left, so the invitation was withdrawn. Ask the project's owner to invite you again.

### Who pays for a shared project?

The owner. Members' deploys and databases count against the owner's plan and its limits, and a member needs no plan.

### What happens when the owner deletes the project?

Its deployments stop, its databases and secrets are removed, and open invitations are withdrawn. Its stored code is kept for 30 days. Admins cannot delete a project.

### Can an agent accept or confirm an invitation?

No. Confirming and accepting are done by people on the dashboard, whatever permissions the agent holds.

### What does a developer's code see in development?

Everything development has: development-only and shared secrets, development databases, the development copy of production data where your plan makes one, and your other development services. See [above](https://yeeted.ai/docs/who-can-do-what.html#data).

### Why does project_context not show secrets?

The connection may lack Manage secrets (the reply names the sections it left out), your role may be read_only, or the project has none. Databases, stored source and domains follow the same rule with their own permissions.

### My agent lists deploy but says my role can't change production.

Which tools an agent sees follows the connection's permissions; whether a call succeeds also follows your role on that project. A developer deploys to development; production is for the owner and admins.

### I clicked OK on the Deploy question and was told I don't have permission.

OK means production. As a developer, click **Cancel** to deploy development.

### Setting a secret as a developer says insufficient permissions.

Choose development as its environment. Shared and production secrets are for the owner and admins.

### My developer's agent deploy did not bring up the projects in depends_on.

Dependencies are project-wide settings, so a developer's deploy through an agent deploys only the project itself. Deploy each dependency, or ask the owner or an admin.

### deploy_group refuses a project shared with me.

A group deploy runs as your own account, so it is refused on projects you do not own. Deploy each service with `deploy`.

### A rollback to a checkpoint restored code but not data.

Restoring a database replaces data, so it needs the connection's Restore databases permission. Without it a checkpoint rollback restores code only.

### Can an admin make someone else an admin or remove an admin?

No. Only the owner grants admin and changes or removes an admin. An admin manages developers and read_only members.

### Two agents are editing the same files.

Claims are advisory and never block an edit. Check `source_status` before starting; each edit names the version of the file it read, so an edit made on a stale copy is refused with the current content instead of overwriting.
