# Projects and secrets

A Project ties a repository, its secrets and its shared connections together inside your org. Sessions in it get all three without naming them.

Your **org** is the account boundary: its members, its API keys, its billing and every session
anyone in it starts. Every path starts with it, `/o/{org}/…`. A **Project** lives inside an org
and gathers what a set of runs shares: its context (today, one repository), a default harness, standing instructions,
secrets and connections.

You get a **personal org** the first time you sign in, and only you are in it. A **company org**
is one you create or are invited to, shared by its members. Every member of an org can see and
work in every Project in it; a Project has no member list of its own. So a Project you want to
keep to yourself goes in your personal org, and one your team works in goes in the company org.

You do not need a Project to start work. A session in no Project is written `p/_` in the
console's paths, and `POST /o/{org}/sessions` with an API key starts one there. It can still
clone a repository named in `resources`; it just gets no Project secrets.

_Figure: project context, on the page at /docs/concepts/projects._
## What a Project holds

You create a Project in the console. It records:

- **Its context**, today a GitHub repository, reached through a GitHub App installation in your org. A run in the Project
  works on that repository, and a `resources` entry on a Project run may only name it.
- **A default harness**, used when a run or an automation does not choose one.
- **A goal and instructions.** The instructions, which an org admin sets, reach every run in the
  Project ahead of its prompt.
- **Secrets**, described below.
- **Connections** that members add for the Project, described below.

An org admin can pause a Project. While it is paused, no run starts in it (`409 PROJECT_PAUSED`)
and none of its [automations](/docs/concepts/automations) fire.

## Secrets

A secret is a value a run needs but that should not sit in your prompt: an API key, a token, a
website login. It belongs to one Project and reaches every session in it. You never name a
secret on a run; starting the session in the Project is enough. A session in no Project gets no
secrets.

Add one on the Project's page in the console, or with
[`POST /o/{org}/secrets`](/docs/api/create-secret) and the Project's `id`.
[`GET /o/{org}/p`](/docs/api/list-projects) lists your org's Projects with their ids, and an API
key can call it. The value is sealed: no response, list or log returns it.
[`GET /o/{org}/secrets`](/docs/api/list-secrets) lists names, kinds, targets and when each was
last used, never values. A name is unique within its Project, and deleting a Project deletes its
secrets.

```bash
curl https://api.prix.dev/o/$ORG/p -H "Authorization: Bearer $RUSH_API_KEY"   # find the Project's id

curl -X POST https://api.prix.dev/o/$ORG/secrets \
  -H "Authorization: Bearer $RUSH_API_KEY" -H "Content-Type: application/json" \
  -d '{"project_id": "'$PROJECT'", "name": "EXA_API_KEY", "value": "…"}'
```

Then start the session in that Project with
[`POST /o/{org}/p/{project}/sessions`](/docs/api/create-project-session), by the Project's name
or id. [Update a secret](/docs/api/update-secret) to replace its value; only its creator or an
org admin can.

### Three kinds

A secret has one of three `kind`s. They differ in whether the agent ever holds the value.

| `kind` | How the session receives it | Does the agent hold the value? |
| --- | --- | --- |
| `env` (default) | As the environment variable `name`. Names Rush sets itself (`ANTHROPIC_*`, `RUSH_*`, `PATH`, `GITHUB_TOKEN`, …) are `422 SECRET_NAME_INVALID`. | Yes, like any environment variable. |
| `header` | Outside the sandbox, the header `header_name` is added to the session's HTTPS requests to each host in `targets`. `header_format` is `{value}`, `Bearer {value}` or `Basic {value}`; for Basic, send `username:password` and Rush encodes it. A plain `http://` request gets no header. | No. It never enters the sandbox. |
| `login` | A username, password and optional two-factor setup key for one https site. Rush types them into the session's browser on that site only (below). | Not in its conversation. It shares the browser the login is typed into, so a filled field is readable from inside the sandbox. |

Use `header` whenever the service takes a token in a header, and `env` only for a tool that has to
read the value itself.

### How the agent knows

Each session's instructions list the secrets attached to it: the name, the kind, where it goes,
and your `description`, never the value. Each entry tells the agent how to use it: read `$NAME`,
do nothing because the header is added for it, or sign in with `rush-sign-in`. Your prompt does not
need to mention them.

### Website sign-ins

`rush-sign-in` is a command installed in every session's sandbox. To use a `login` secret the
agent opens the site's login page in its browser and runs:

```bash
rush-sign-in <name>              # fill the form and press Enter
rush-sign-in <name> --no-submit  # fill it and leave submitting to the agent
```

Rush opens the secret on its side and types the username, the password and, when you saved a
two-factor setup key, the current six-digit code into that page. It fills only a tab on the
secret's own site and stops if the page navigates away. The command prints which fields it
filled, never what it typed.

| Answer | What it means |
| --- | --- |
| `{"signed_in": true, …}` | The fields were filled, and Enter was pressed unless `--no-submit`. |
| `SIGN_IN_ORIGIN_MISMATCH` | No browser tab is on the secret's site. Open its login page first. |
| `SIGN_IN_FIELDS_NOT_FOUND` | The page has no login form yet, often because it is still loading. Wait for it and run the command again. |
| `SIGN_IN_BROWSER_UNAVAILABLE` | The session has no browser to sign in with. |
| `SECRET_NOT_FOUND` / `SECRET_KIND_MISMATCH` | The Project has no secret by that name, or it is not a `login`. |
| `SIGN_IN_RATE_LIMITED` | More than 10 sign-ins in a minute from one session. |

_Figure: project map, on the page at /docs/concepts/projects._
## Members and connections

Members of the org work in its Projects, and a Project's secrets reach every session any of them
starts there. A connection is personal: it belongs to the person who signed in. Each member
switches their own connections on or off per Project in the console, and a member can add a
connection to one Project, where it reaches every run in that Project and no other.

[Connections](/docs/concepts/connections) covers signing in and naming a connection on a run.
