Skip to main content

Documentation Index

Fetch the complete documentation index at: https://recipe.uselettuce.dev/llms.txt

Use this file to discover all available pages before exploring further.

Lettuce can pull projects directly from GitLab through a GitLab OAuth application that your operator (the team running the Lettuce backend) registers once. Users in your account then click Connect GitLab, authorize Lettuce on their personal account, pick projects from a list, and Lettuce indexes them plus wires up push webhooks — no copy-pasting URLs or webhook secrets. The manual “paste a git URL” flow keeps working alongside this — use it for public projects hosted anywhere git speaks.
There are two audiences here. Operators (you self-host Lettuce) do the one-time GitLab OAuth-app setup. Users (you sign in to Lettuce on the web) just click Connect GitLab and pick projects.

For operators — one-time setup

You only do this once per Lettuce deployment. The same flow works for gitlab.com or any self-hosted GitLab (CE or EE).
1

Open the right Applications page

For gitlab.com or a self-hosted GitLab where each user authorizes Lettuce themselves, register a user-owned application at https://gitlab.com/-/user_settings/applications.For a group-owned OAuth app, go to your group → SettingsApplications. For an instance-wide app on self-hosted GitLab, use the Admin Area → Applications.Whichever scope you pick, the rest of the form is the same.
2

Fill in the application form

  • Name: Lettuce (anything you like — users see this on the authorize screen).
  • Redirect URI: https://<your-lettuce-host>/v1/integrations/gitlab/callback — GitLab is strict about exact-match. No trailing slash, no path variants. The host must equal CODEWAZE_PUBLIC_URL on the backend.
  • Confidential: Yes. Lettuce holds the client secret on a server, so the public-client mode would just weaken the flow.
  • Expire access tokens: leave at the default (on). Lettuce refreshes tokens automatically using the refresh token GitLab issues.
  • Scopes: tick exactly these three:
    • api — read-only OAuth-bound REST access (used to list projects and register webhooks).
    • read_repository — git-over-HTTPS clone access.
    • write_repository — needed to register the per-account push webhook on each added project.
3

Save and copy the credentials

Click Save application. GitLab shows the Application ID and Secret once — copy both immediately. If you miss the secret you’ll need to regenerate it.
4

Set env vars on the Lettuce backend

# Required
GITLAB_APP_CLIENT_ID=<application id>
GITLAB_APP_CLIENT_SECRET=<application secret>

# Optional — only set for self-hosted GitLab. Omit for gitlab.com.
GITLAB_BASE_URL=https://gitlab.acme.dev
Notes:
  • CODEWAZE_PUBLIC_URL must already be set on the backend to a URL GitLab can reach — the Redirect URI above is built from it.
  • GITLAB_BASE_URL defaults to https://gitlab.com. Self-hosted operators point it at their own host; OAuth, REST, and clone URLs all derive from this one value.
5

Restart the backend

Lettuce reads the env vars at request time, so a rolling restart is enough. On the next request, GET /v1/integrations reports available.gitlab: true and the GitLab tab in every user’s Add-repo dialog activates.

How the security model works

  • The OAuth client secret lives only in GITLAB_APP_CLIENT_SECRET on the backend. It is never written to the database and never sent to the browser.
  • Per-account tokens (access + refresh) are stored on the provider_installations row. The access token is short-lived (default 2h on gitlab.com); Lettuce refreshes proactively within 60 seconds of expiry whenever a call is made. If the refresh-token cycle fails (rare — the user revoked Lettuce on GitLab, or the secret rotated), the install is flagged meta.needs_reauth = true and the UI prompts the user to reconnect instead of returning a 500.
  • The OAuth state param on the callback is an HMAC of (account_id, provider, timestamp, nonce) signed with the backend’s admin token — same construction as the GitHub vertical. The browser comes back from gitlab.com with no Lettuce session cookie; the HMAC rebinds the install to the account that started it.
  • The webhook secret is per-account, stored in accounts.webhook_secret, and reused across every repo. GitLab sends it back to us in the X-Gitlab-Token header on each delivery; Lettuce compares it with hmac.compare_digest. (GitLab does not HMAC the body the way GitHub does, so a literal token compare is the strongest available check.) Rotating the secret via POST /v1/account/webhook/rotate invalidates every existing GitLab webhook for that account.

For users — connect GitLab and add projects

This is what users see in the Lettuce UI once the operator has set up the OAuth app above.
1

Open the Repos page

Sign in to Lettuce, go to Repos, click + Add repo.
2

Connect GitLab

On the GitLab tab, click Connect GitLab →. You’re redirected to GitLab (or your operator’s self-hosted GitLab if they set GITLAB_BASE_URL).GitLab shows an authorize screen listing the three scopes Lettuce is asking for — api, read_repository, write_repository. Click Authorize.GitLab redirects you back to Lettuce with a green toast.
3

Pick a project

The Add-repo dialog now lists every GitLab project you have Developer or higher access to (across all your groups), most-recently-active first. Filter by group/project substring, then click one.Lettuce:
  1. Registers the project against your account.
  2. Auto-creates a push webhook on it so future commits trigger a re-index. (Idempotent — if the hook already exists from a previous add, we leave it alone.)
  3. Queues a clone + index job. Status moves from pending to indexing to ready — usually in a few seconds for small repos.
No copy-pasting URLs, no fiddling with webhook secrets.
4

(Optional) Self-hosted GitLab note

If your operator set GITLAB_BASE_URL, the Connect GitLab button takes you to that host, not gitlab.com. Everything else (scope screen, project picker, webhook auto-register) is identical.
5

(Optional) Add more later

The dialog remembers your connection — re-open it any time to add another project. Tokens refresh automatically; you only need to come back here if you revoke Lettuce on GitLab or change your password and the refresh-token cycle fails. In that case the GitLab tab shows a Reconnect GitLab button.

Disconnecting

Owners can disconnect the GitLab integration from the Lettuce side at DELETE /v1/integrations/gitlab (a UI button is on the roadmap). Disconnecting:
  • Removes the provider_installations row and discards the stored access and refresh tokens.
  • Leaves all your existing repos in place — they keep working as long as they’re public. Private repos will fail their next re-clone until you reconnect or switch them to a paste-URL with credentials.
To fully revoke access, also remove the authorization on the GitLab side: User Settings → Applications → Authorized applications → find Lettuce → Revoke.

Troubleshooting

The operator hasn’t set GITLAB_APP_CLIENT_ID and GITLAB_APP_CLIENT_SECRET (or the backend hasn’t been restarted since). GET /v1/integrations returns available.gitlab: false in that state.
The signed state param is older than 15 minutes, or the backend’s admin token has rotated since you started the install. Restart the install from the Add-repo dialog.
You clicked Cancel (or denied one of the requested scopes) on the GitLab authorize screen. Restart the install if it was an accident — Lettuce needs all three scopes (api, read_repository, write_repository) to function.
Lettuce’s refresh token was rejected. That happens when you revoked Lettuce on GitLab, GitLab itself rotated tokens (rare), or the operator rotated the client secret. Click Reconnect GitLab to authorize afresh.
Check the Recent ingestion jobs section on the Repos page — failed clones surface the underlying git error there. Common cases: your role on the project dropped below Developer (re-grant access on GitLab), or the operator’s backend can’t reach the GitLab host.
The auto-webhook step may have failed if your role on the project is below Maintainer (project webhooks require Maintainer or Owner on some GitLab versions). Use Automatic refresh on the Repos page — it shows the per-account webhook URL + secret you can paste into the project’s Settings → Webhooks manually. Set Trigger to Push events and the Secret token to the value Lettuce shows.
GitLab compares the redirect URI byte-for-byte against the value you registered. Common gotchas: trailing slash present in one but not the other, http vs https, or a different port. The expected value is <CODEWAZE_PUBLIC_URL>/v1/integrations/gitlab/callback with no trailing slash.

What’s next

Bitbucket integration lands in the next Lettuce release — same shape: operator-side OAuth app, user-side one-click connect, auto-webhooks. Until then, paste your Bitbucket git URL on the Other (paste URL) tab.