148 lines
6.7 KiB
Markdown
148 lines
6.7 KiB
Markdown
# Git Provider Setup
|
|
|
|
This document covers manual setup for GitHub OAuth, Puter Git (Gitea), webhooks, and Convex environment variables.
|
|
|
|
> **Never place admin or user tokens in checked-in `.env` files or browser variables.** All secrets must be Convex environment variables set via `npx convex env set`.
|
|
|
|
## GitHub OAuth Application
|
|
|
|
1. Go to GitHub **Settings → Developer settings → OAuth Apps** and open the app whose client ID will be stored in Convex.
|
|
2. Set the application name and homepage URL. The homepage URL should be the current `SITE_URL`.
|
|
3. Set the single **Authorization callback URL** to exactly:
|
|
```text
|
|
<SITE_URL>/api/auth/callback/github
|
|
```
|
|
GitHub OAuth Apps support one callback URL. Scheme, host, port, and path must match the `redirect_uri` sent by Better Auth exactly.
|
|
4. Generate a client secret.
|
|
5. Set the credentials on the Convex deployment—not only in the local `.env` file:
|
|
```bash
|
|
cd packages/backend
|
|
npx convex env set GITHUB_CLIENT_ID <your-client-id>
|
|
npx convex env set GITHUB_CLIENT_SECRET <your-client-secret>
|
|
npx convex env list
|
|
```
|
|
|
|
The configured `SITE_URL`, GitHub callback URL, and browser URL are one unit. For a shared Convex deployment, switch all three before testing a different public origin. See [Auth Proxy](./auth-proxy.md#one-origin-per-shared-oauth-deployment) for the deployment boundary.
|
|
|
|
### Requested scopes
|
|
|
|
Zopu requests GitHub identity and private-repository access: `read:user`, `user:email`, `repo`, and `read:org`. `repo` grants access to private repositories; `read:org` permits organization repository discovery.
|
|
|
|
## GitHub Webhook (manual setup for OAuth-based version)
|
|
|
|
1. Go to the GitHub repository Settings > Webhooks > Add webhook.
|
|
2. Payload URL: `<CONVEX_SITE_URL>/api/git/webhooks/github`
|
|
3. Content type: `application/json`
|
|
4. Secret: generate a strong random string and set it as:
|
|
```
|
|
npx convex env set GITHUB_WEBHOOK_SECRET <your-webhook-secret>
|
|
```
|
|
5. Select individual events:
|
|
- Push
|
|
- Repository (created, deleted, transferred, renamed, visibility)
|
|
- Delete
|
|
- Create
|
|
- Public
|
|
- Fork
|
|
6. Do not select "Send me everything."
|
|
|
|
## Puter Git (Gitea) Admin Token
|
|
|
|
1. As a Gitea admin, go to Settings > Applications > Generate New Token.
|
|
2. Select scopes: `write:admin`, `write:organization`, `write:repository`.
|
|
3. Set the token:
|
|
```
|
|
npx convex env set PUTER_GIT_ADMIN_TOKEN <your-admin-token>
|
|
```
|
|
|
|
This token is used only for platform administration (user creation, organization creation, repository creation, migration). It is never used for end-user operations.
|
|
|
|
## Puter Git Webhook
|
|
|
|
After a repository is created or migrated, Zopu ensures a webhook is configured automatically. If manual setup is needed:
|
|
|
|
1. Go to the Gitea repository Settings > Webhooks > Add Webhook > Gitea.
|
|
2. Target URL: `<CONVEX_SITE_URL>/api/git/webhooks/puter`
|
|
3. HTTP method: POST
|
|
4. Content-Type: `application/json`
|
|
5. Secret: generate a strong random string and set it as:
|
|
```
|
|
npx convex env set GITEA_WEBHOOK_SECRET <your-webhook-secret>
|
|
```
|
|
6. Trigger on: Push events, Repository events.
|
|
|
|
## Credential Encryption Key
|
|
|
|
Generate a 32-byte encryption key for AES-GCM credential encryption:
|
|
|
|
```bash
|
|
openssl rand -base64 32 | base64 | tr -d '\n' | pbcopy
|
|
```
|
|
|
|
Set it as:
|
|
|
|
```
|
|
npx convex env set GIT_CREDENTIAL_ENCRYPTION_KEY <base64url-encoded-32-bytes>
|
|
```
|
|
|
|
The key must be exactly 32 bytes when base64url-decoded.
|
|
|
|
## Same-Origin Proxy for Better Auth Callbacks
|
|
|
|
Better Auth requires the callback URL to be on the same origin as `SITE_URL`. If your Convex deployment uses a different origin:
|
|
|
|
1. Configure a reverse proxy (e.g., Caddy) to forward `/api/auth/*` to the Convex deployment.
|
|
2. Set `SITE_URL` to the proxy origin.
|
|
3. Set `CONVEX_SITE_URL` to the Convex deployment URL.
|
|
|
|
## Validation Procedures
|
|
|
|
### Verify a Puter PAT connection
|
|
|
|
1. Connect a Puter PAT through the UI.
|
|
2. Verify the connection state shows `active`.
|
|
3. List private repositories to confirm token validity.
|
|
|
|
### Verify GitHub OAuth
|
|
|
|
1. Click "Connect GitHub" in the UI.
|
|
2. Complete the GitHub OAuth flow.
|
|
3. Verify the connection state shows `active`.
|
|
|
|
### OAuth diagnostics
|
|
|
|
| Symptom | Cause | Fix |
|
|
| --- | --- | --- |
|
|
| `Provider not found` from `/api/auth/link-social` | `GITHUB_CLIENT_ID` or `GITHUB_CLIENT_SECRET` is absent from the Convex deployment env store. A local `.env` does not configure cloud functions. | Set both variables with `npx convex env set` and verify with `npx convex env list`. |
|
|
| GitHub `Invalid Redirect URI` | GitHub's saved callback does not exactly equal the app's `redirect_uri`. | Set the OAuth App's single callback to `<SITE_URL>/api/auth/callback/github`. |
|
|
| `state_mismatch` at a `convex.site` page | Better Auth started on the public origin but GitHub returned to the direct Convex host, so the public-origin state cookie is unavailable. | Set Better Auth `baseURL` to `SITE_URL`; proxy `/api/auth/*` through the public origin. |
|
|
| `email_doesn't_match` after selecting GitHub | A deployment predates the explicit-link policy or has not received the current auth configuration. | Deploy the current backend. Explicit `linkSocial` allows a different GitHub email without changing the Zopu account email. |
|
|
| `externalEmail` is `null` during `connectGithub` | The GitHub account hides its public email; GitHub returns `null` from `/user`. | Deploy the current backend, which normalizes nullable provider emails before Convex persistence. |
|
|
|
|
GitHub connections are explicit authenticated account links. The linked GitHub email may differ from the existing Zopu account email; Zopu retains the existing account email and only stores the GitHub identity and OAuth credential needed for repository access.
|
|
|
|
### Reconnection
|
|
|
|
If a token is expired or revoked:
|
|
|
|
1. The connection state shows `reauth-required`.
|
|
2. Reconnect the provider through the UI.
|
|
3. The old connection state is updated to `active`.
|
|
4. Projects, repositories, Work, and artifacts are not deleted.
|
|
|
|
## Environment Variables Summary
|
|
|
|
| Variable | Required | Description |
|
|
| --- | --- | --- |
|
|
| `SITE_URL` | Yes | Public-facing URL |
|
|
| `CONVEX_SITE_URL` | Yes | Convex deployment URL (may differ from SITE_URL with proxy) |
|
|
| `GIT_CREDENTIAL_ENCRYPTION_KEY` | Yes | Base64url-encoded 32-byte AES-GCM key |
|
|
| `PUTER_GIT_ADMIN_TOKEN` | Yes | Gitea admin token for provisioning |
|
|
| `GITHUB_CLIENT_ID` | For GitHub | OAuth app client ID |
|
|
| `GITHUB_CLIENT_SECRET` | For GitHub | OAuth app client secret |
|
|
| `GITHUB_WEBHOOK_SECRET` | For GitHub webhooks | HMAC verification secret |
|
|
| `GITEA_WEBHOOK_SECRET` | For Puter webhooks | HMAC verification secret |
|
|
| `FLUE_DB_TOKEN` | Yes | Private agent backend token |
|
|
| `FLUE_URL` | Optional | Private agent backend URL |
|
|
| `NATIVE_APP_URL` | Optional | Native app deep-link scheme |
|