# Altixia Git auth.md

You are an agent. **Altixia Git** (`https://git.altixia.com`) is Altixia's private Forgejo
instance: the source code of Altixia's tools and of its clients' websites. Every repository
requires an account; nothing is readable anonymously except the documents listed at the end.

## Who can get access

Accounts are created by Altixia for its team and its clients — there is **no self-service
registration and no agent registration endpoint**. An agent always acts **for a person who
already has an account**, with a credential that person creates and hands over.

## How a person signs in (browser)

`https://git.altixia.com` redirects to **Altixia ID** (`https://id.altixia.com`). That sign-in
is for the web interface only: **an Altixia ID access token is not accepted by this API.**

## How an agent authenticates (API)

The API lives at `https://git.altixia.com/api/v1` (OpenAPI 2.0: `/swagger.v1.json`). It accepts
credentials issued by this Forgejo instance only — two ways to get one:

### 1. OAuth2 with the person's Altixia ID sign-in (preferred)

A public OAuth2 client is registered for agents on the whole instance — nothing to set up per
person, no client secret:

| | |
|---|---|
| `client_id` | `d3d18cf7-01e1-465e-9050-667d88c646fa` |
| Authorization endpoint | `https://git.altixia.com/login/oauth/authorize` |
| Token endpoint | `https://git.altixia.com/login/oauth/access_token` |
| Grant | authorization code, **PKCE `S256` required** |
| Redirect URI | `http://127.0.0.1:<any port>` or `http://127.0.0.1:<any port>/callback` (also `[::1]`) |
| Scopes | API scopes, e.g. `read:repository write:repository` — the token is limited to them |

1. Start a listener on a free loopback port, then open the authorization URL in the person's
   browser: `response_type=code`, `client_id`, `redirect_uri`, `scope`, `state`,
   `code_challenge`, `code_challenge_method=S256`.
2. The person signs in through **Altixia ID** and approves the request.
3. Exchange the `code` at the token endpoint with `grant_type=authorization_code`, `client_id`,
   `redirect_uri` and `code_verifier`.
4. Call the API with `Authorization: Bearer <access_token>`. It lasts one hour; renew it with
   `grant_type=refresh_token`.

This needs a browser on the person's machine: there is no device flow.

### 2. Personal access token (no browser available)

The account holder signs in, opens *Settings › Applications › Generate new token*, picks the
narrowest scopes that do the job (for example `read:repository` + `write:repository`), and gives
the token to the agent. Send it as `Authorization: token <TOKEN>` (`Bearer` works too).

An **Altixia ID access token is not accepted by this API** — Altixia ID authenticates the
person; Forgejo issues the token.

Protected resource metadata (RFC 9728): `/.well-known/oauth-protected-resource`.

A request without a valid credential is refused (`401`/`403`); retrying will not help — ask the
account holder for a token.

## Rules that will stop you

- `main` is protected on most repositories: direct pushes are refused. Create a branch, open a
  pull request, then merge it.
- On some repositories (client websites) **merging into `main` deploys the site** within about a
  minute. Read the repository's README before merging.

## Public documents

- `/llms.txt` — what this host is, for agents
- `/.well-known/api-catalog` — API catalog (RFC 9727)
- `/.well-known/agent-skills/index.json` — skill: using the Altixia Git API
- `/.well-known/ai-catalog.json` — capability manifest
- `/api/swagger` — API reference
