# Forgejo API CORS Proxy

Base URL for browser API calls:

```text
https://forgejo-api.tionis.dev
```

Canonical Forgejo UI and OAuth authorization origin:

```text
https://forge.tionis.dev
```

OpenAPI and interactive documentation:

- OpenAPI spec: https://forge.tionis.dev/swagger.v1.json
- Swagger UI: https://forge.tionis.dev/api/swagger

## Purpose

This origin is a CORS-enabled facade for selected Forgejo API endpoints. It lets trusted static browser apps use Forgejo as a backend without enabling broad CORS on the main Forgejo UI origin.

Use `https://forge.tionis.dev` for OAuth authorization redirects. Use `https://forgejo-api.tionis.dev` for the OAuth token exchange and API requests.

## Proxied Paths

Only these paths are proxied:

- `/login/oauth/access_token`
- `/api/v1/*`

The Forgejo web UI, Swagger UI, and OpenAPI JSON are not mirrored through this facade. Read the API schema from `https://forge.tionis.dev/swagger.v1.json` and the interactive docs at `https://forge.tionis.dev/api/swagger`.

## CORS Contract

Matching proxied paths return:

```http
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: false
Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS
Access-Control-Allow-Headers: Authorization, Content-Type, Accept
Access-Control-Max-Age: 86400
```

`OPTIONS` preflight requests to proxied paths return `204 No Content` with the same CORS headers.

## Authentication

Authenticate API calls with OAuth bearer tokens:

```http
Authorization: Bearer TOKEN
```

Do not rely on Forgejo browser cookies. The proxy removes request `Cookie` headers before forwarding to Forgejo and removes response `Set-Cookie` headers before returning to the browser.

## OAuth Browser Flow

1. Register the static browser app as a public OAuth2 app in Forgejo.
2. Redirect the user to `https://forge.tionis.dev/login/oauth/authorize`.
3. Receive the authorization code at the static app redirect URI.
4. Exchange the code at `https://forgejo-api.tionis.dev/login/oauth/access_token`.
5. Call `https://forgejo-api.tionis.dev/api/v1/...` with `Authorization: Bearer TOKEN`.

## Example Fetch Calls

Token exchange:

```js
const body = new URLSearchParams({
  client_id: CLIENT_ID,
  code: AUTHORIZATION_CODE,
  grant_type: "authorization_code",
  redirect_uri: REDIRECT_URI,
});

const tokenResponse = await fetch("https://forgejo-api.tionis.dev/login/oauth/access_token", {
  method: "POST",
  headers: {
    "Accept": "application/json",
    "Content-Type": "application/x-www-form-urlencoded",
  },
  body,
});
```

API request:

```js
const userResponse = await fetch("https://forgejo-api.tionis.dev/api/v1/user", {
  headers: {
    "Accept": "application/json",
    "Authorization": `Bearer ${token}`,
  },
});
```

Version request without authentication:

```js
const versionResponse = await fetch("https://forgejo-api.tionis.dev/api/v1/version", {
  headers: {
    "Accept": "application/json",
  },
});
```

## Implementation Notes For Agents

- Generate API clients from `https://forge.tionis.dev/swagger.v1.json`.
- Set the generated client's server or base URL to `https://forgejo-api.tionis.dev/api/v1` when running in a browser.
- Keep OAuth authorize links on `https://forge.tionis.dev`.
- Keep OAuth token requests on `https://forgejo-api.tionis.dev/login/oauth/access_token`.
- Send bearer tokens in the `Authorization` header.
- Do not set `credentials: "include"` on browser fetch requests to this facade.
- Do not call paths outside `/login/oauth/access_token` or `/api/v1/*` through this facade; they return `404`.
