# Runlocal sign-in guide

Each route of this API needs credentials, but this guide and
https://warmhearted-akita-551.eu-west-1.convex.site/api/v1/client-config. A request with no credentials gets 401 AUTH.REQUIRED. An
account with no invite gets 403 AUTH.NOT_INVITED: stop, and tell the user to ask
Runlocal for access. Do not sign in again.

This guide has the sign-in steps only. https://warmhearted-akita-551.eu-west-1.convex.site/api/v1/client-config states each value
that the steps need: the sign-in endpoints, the name of the key variable, the
key file with its access modes, and the schema of that file. The agent skill is
public at https://www.runlocal.ai/skill.md, and it has the rules of conduct.

## 1. Use a key that the user has

Read the environment variable that client-config names, then the entry for this
API origin in the key file, when it has not expired. Send the key as
Authorization: Bearer KEY, and verify it with GET https://warmhearted-akita-551.eu-west-1.convex.site/api/v1/auth/status. A stored
key that answers 401 is expired or revoked: remove its entry, and sign in.

## 2. Or sign in with the device

Use the OAuth 2.0 device authorization grant (RFC 8628) with the values of
client-config. You install nothing, and the user completes the sign-in in a
browser.

- Show the user the verification address and the user code. Never show the
  device code.
- Stop when the user denies the sign-in or the code expires. Do not start again
  without the user.
- Keep the access token and the refresh token in memory only. The refresh token
  rotates, so replace both tokens after each refresh.
- Refresh before the access token expires, as client-config states. An expired
  token is not a credential: each route answers it with 401 AUTH.REQUIRED.
- Use the access token as the bearer token for the whole task. Sign in again
  only when the session cannot be refreshed.

## 3. Offer a key for next time

After a device sign-in, you can offer to keep an API key. Create one only after
the user approves its purpose and its place: POST https://warmhearted-akita-551.eu-west-1.convex.site/api/v1/auth/api-keys with
the session token, and a name that says which machine or task the key is for.
The API shows the key one time.

Keep the key in the key file, in the form that its schema states, with the
access modes that client-config states. The file is in the home folder of the
user. It is never in the `.runlocal` folder of a project, which Git tracks.
Replace a stored key before it expires, as client-config states, and tell the
user that they can revoke the old key in the workspace. When the user does not
approve the file, continue with the session.

Never print a credential, and never write one to a repository, a request, the
chat, or a log. Never write a session token or a refresh token to a file.

## After the sign-in

GET https://warmhearted-akita-551.eu-west-1.convex.site/api/v1 for discovery, and https://warmhearted-akita-551.eu-west-1.convex.site/api/v1/agent-guide for the procedure. Send the
bearer token with each request.
