Effect primitives: - git-provider: GitProvider, connection states, normalized errors, URL normalization, host compatibility, credential freshness window - git-provisioning: validated Puter commands, migration states, idempotency keys, safe replacement rules, owner-safe guards - git-webhook: supported events, signature verification, delivery states - host-repository: provider-neutral credential-safe clone via GIT_ASKPASS Normalized Convex schema: - gitProviderAccounts, refined gitConnections, gitProviderOrganizations, gitRepositories, gitMigrations, gitWebhookDeliveries - projects: gitRepositoryId + instructions fields - Schema fields optional for backward compatibility, with backfill cron Backend: - Connection health: verify action, hourly reconciliation (covers stale active + reauth-required + undefined-state legacy connections) - Puter provisioning: createPuterUser/Organization/Repository with owner binding, startGithubMigration (durable via scheduler), getMigration - Org ownership: explicit member add with admin role + verification - Webhook HTTP actions: HMAC verification, delivery persistence with idempotency, repository resolution, byte-length payload limit - Automatic Puter webhook creation after repo creation/migration with fail-loud state tracking - Repository sync after connection (Gitea + GitHub) - AgentOS execution resolves gitRepositoryId for real clone URL - Credential gating: state + freshness checks before execution and project creation - listForOrganization for cross-project Work filtering Frontend: - /projects onboarding page with GitHub OAuth (linkSocial) and Puter PAT - Zero-project redirect, repository selection, context editor - Provider-aware settings panel (no serverUrl for Puter) - Project selection via ?project= query param - GitHub scopes: repo + read:org Agent runtime: - Clones user repository with GIT_ASKPASS credential helper (no token in URL, args, or git config), provider-aware username - Removed fixed Zopu source path and .env copy
4.5 KiB
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
.envfiles or browser variables. All secrets must be Convex environment variables set vianpx convex env set.
GitHub OAuth Application
- Go to GitHub Settings > Developer settings > OAuth Apps > New OAuth App.
- Set the application name (e.g., "Zopu").
- Set the homepage URL to your
SITE_URL(e.g.,https://zopu.cheaptricks.puter.wtf). - Set the callback URL to
<SITE_URL>/api/auth/callback/github. - Generate a client secret.
- Set Convex environment variables:
npx convex env set GITHUB_CLIENT_ID <your-client-id> npx convex env set GITHUB_CLIENT_SECRET <your-client-secret>
Requested scopes
Zopu requests repo and read:org. The repo scope grants access to private repositories. read:org allows listing organization repositories.
GitHub Webhook (manual setup for OAuth-based version)
- Go to the GitHub repository Settings > Webhooks > Add webhook.
- Payload URL:
<CONVEX_SITE_URL>/api/git/webhooks/github - Content type:
application/json - Secret: generate a strong random string and set it as:
npx convex env set GITHUB_WEBHOOK_SECRET <your-webhook-secret> - Select individual events:
- Push
- Repository (created, deleted, transferred, renamed, visibility)
- Delete
- Create
- Public
- Fork
- Do not select "Send me everything."
Puter Git (Gitea) Admin Token
- As a Gitea admin, go to Settings > Applications > Generate New Token.
- Select scopes:
write:admin,write:organization,write:repository. - 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:
- Go to the Gitea repository Settings > Webhooks > Add Webhook > Gitea.
- Target URL:
<CONVEX_SITE_URL>/api/git/webhooks/puter - HTTP method: POST
- Content-Type:
application/json - Secret: generate a strong random string and set it as:
npx convex env set GITEA_WEBHOOK_SECRET <your-webhook-secret> - Trigger on: Push events, Repository events.
Credential Encryption Key
Generate a 32-byte encryption key for AES-GCM credential encryption:
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:
- Configure a reverse proxy (e.g., Caddy) to forward
/api/auth/*to the Convex deployment. - Set
SITE_URLto the proxy origin. - Set
CONVEX_SITE_URLto the Convex deployment URL.
Validation Procedures
Verify a Puter PAT connection
- Connect a Puter PAT through the UI.
- Verify the connection state shows
active. - List private repositories to confirm token validity.
Verify GitHub OAuth
- Click "Connect GitHub" in the UI.
- Complete the GitHub OAuth flow.
- Verify the connection state shows
active.
Reconnection
If a token is expired or revoked:
- The connection state shows
reauth-required. - Reconnect the provider through the UI.
- The old connection state is updated to
active. - 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 |