DOCS · INTEGRATIONS
GitLab
gitlab.com and self-managed, connected with an api-scoped access token — same write path, same fail-closed webhook rule.
On this page
GitLab has no App-installation concept, so a connection is a token — plus the instance URL for self-managed. specd is explicit about the trade-off that makes rather than hiding it.
What it needs
| Scope | Why |
|---|---|
api (personal or project access token) | Read repository contents, push branches, open merge requests, register a webhook. |
What it listens to
| Event | What specd does with it |
|---|---|
| Merge request merged | Setup branch → mark adopted and index knowledge/. Spec branch → mark the spec delivered and re-index. |
| Push to the default branch | Re-index if knowledge/ changed. |
There is no installation lifecycle to track: a token is valid until revoked or expired, and GitLab sends no webhook for that. A build or index that starts failing with 401s is the signal — reconnect with a fresh token.
Connect a project
There is no browser flow yet; connect over the API. Create the token under Edit profile → Access Tokens, or a project access token under the project's Settings → Access Tokens. Grant the api scope and at least the Maintainer role — anything less can read and propose changes but cannot register the webhook.
curl -X POST "$SPECD_API/projects/$PROJECT_SLUG/connections/vcs" \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "provider": "gitlab", "accessToken": "'"$GITLAB_TOKEN"'" }'The complete walkthrough — self-managed instance URLs, webhook registration, verification — is in docs/gitlab.md in the repository.
When a self-managed instance does not connect
specd reaches your instance from the machine specd runs on, not from your browser — so every check is about that machine. A bare host like gitlab.example.com is accepted and read as https; anything that cannot become an http(s) origin is refused on the connect call itself.
| What the error says | What to fix |
|---|---|
does not resolve from the machine specd runs on | Wrong hostname, or this machine is not on the VPN that can see it. |
refused the connection | The host resolves; the port is wrong, or nothing is serving there. |
did not answer in time | Typically a firewall, or a VPN that is not connected. |
presented a certificate this machine does not trust | An internal CA — point NODE_EXTRA_CA_CERTS at it where specd runs, rather than disabling verification. |
answered with an HTML page rather than JSON | An SSO or access portal intercepted the API call and served its login page at 200. The request never reached GitLab. |
→ 401 | The instance answered. The token is the problem, not the network. |
Webhook trust
GitLab offers a token echo rather than an HMAC signature, so specd uses that, compared in constant time. The rule is identical to GitHub's: an unset secret rejects everything, deliveries are deduped, and specd acts only for a registered repository.