Melso Docs

GitHub

Verified request, response and authorization contracts.

GitHub connections belong to the member who connects them. Every human workspace member can connect their GitHub account; other members and machine credentials cannot list, browse, or disconnect that connection. Several people can authorize the same GitHub App installation independently.

Connecting authorizes Melso on behalf of the GitHub user. The repository picker lists only repositories available to both that user and the App. Only me is the default: selected repositories go into a private My repositories Area. Only its owner can see its Tasks, files, and repository work. Its membership cannot be widened, and its existing Tasks cannot be moved into shared Areas.

To delegate a repository, select an Area or Whole company, or use Change where it's used. The sharer must have GitHub admin permission on that repository and permission to edit the Melso destination. This shares just that repository, not the connection or other repositories. Members of the destination can use the repository without connecting GitHub themselves. An existing company share can also be used in an Area. The member's GitHub permission is checked again when issuing agent credentials or performing live PR actions; removing a share, revoking the authorization, or disconnecting stops new credential issuance.

A coding Run's credentials cover its Task's repositories. Personal read-only access stays read-only; shared repositories receive the App's approved coding permissions. Tokens never receive Workflows or Administration access. The chat command VM gets read-only access to company repositories and repositories in Areas the member can open; when the member's Vault holds a GH_TOKEN or GITHUB_TOKEN, it uses that token instead. User OAuth credentials stay encrypted on the server and never reach a Run or browser.

Existing repositories explicitly linked to the company or an Area keep their sharing on upgrade. Existing connections become private to their original connector; reconnect to enable personal repository browsing. No other repositories from those installations are shared. Disconnect removes that member's connection and its repository grants; it never uninstalls the shared GitHub App.

Self-hosted deployments must configure MELSO_VCS_SECRET_KEY (base64, 32 bytes) before enabling personal connections. It encrypts the user and refresh tokens at rest; preserve it across restarts and include it in your secret backup/rotation plan.

Examples use the environment variables from Overview. UUID placeholders must be replaced with your own IDs.

GET /api/workspaces/{workspaceId}/github/installations

Auth: Workspace member with access to this resource.

Request: Path: workspace UUID.

Response: {installations:GitHubInstallationResponse[],can_manage:boolean,configured:boolean,repository_browse_configured:boolean,configuration_error:string}; only the current member’s connections are included. has_shared_repositories:boolean reports usable repositories without exposing other members’ connections. can_manage is true for human members and false for machine credentials.

Status: 200; 503 GitHub authorization unavailable. Authentication and resource-access errors follow Overview.

curl -sS -X GET "$MELSO_URL/api/workspaces/$WORKSPACE_ID/github/installations" \
  -H "Authorization: Bearer $MELSO_TOKEN" -H "X-Workspace-ID: $WORKSPACE_ID"

GET /api/workspaces/{workspaceId}/github/connect

Auth: Human workspace member; Run/MCP actors rejected.

Request: Optional query return_to:"github"|"repositories"|"chat", the page GitHub returns to. Optional mode:"install" opens GitHub's installation page to add another account instead of finding existing installations.

Response: {configured:boolean,url?:string,error?:string}. Open url in the member's browser; it expires with its one-use state after 10 minutes.

Status: 200; 400 invalid return target or mode; 403 human member required. Authentication and resource-access errors follow Overview.

curl -sS -X GET "$MELSO_URL/api/workspaces/$WORKSPACE_ID/github/connect" \
  -H "Authorization: Bearer $MELSO_TOKEN" -H "X-Workspace-ID: $WORKSPACE_ID"

GET /api/workspaces/{workspaceId}/github/connect/candidates

Auth: The human workspace member who authorized on GitHub.

Request: Query state:string, the github_choose value GitHub returned to the page.

Response: {candidates:{installation_id:integer,account_login:string,account_type:string,account_avatar_url?:string}[],return_to:string}. The user authorization proof stays on the server.

Status: 200; 400 invalid state; 403 human member required; 404 no pending choice. Authentication and resource-access errors follow Overview.

POST /api/workspaces/{workspaceId}/github/connect/complete

Auth: The human workspace member who authorized on GitHub.

Request: {state:string,installation_ids:integer[]}, installations from the pending choice.

Response: Empty.

Status: 204; 400 installation outside the choice; 403 access revoked; 404 no pending choice; 409 the choice expired or an installation changed. Authentication and resource-access errors follow Overview.

GET /api/workspaces/{workspaceId}/github/installations/{installationId}/repositories

Auth: The human member who owns the connection.

Request: Path: workspace and installation record UUIDs. Query page?:integer (default 1), per_page?:integer (default/max 100).

Response: {repositories:GitHubRepositoryResponse[],total_count:integer,next_page:integer|null}.

Status: 200; 403 reconnect required; 404 installation mismatch; 502 GitHub request failed; 503 GitHub unavailable. Authentication and resource-access errors follow Overview.

curl -sS -X GET "$MELSO_URL/api/workspaces/$WORKSPACE_ID/github/installations/$INSTALLATION_ID/repositories" \
  -H "Authorization: Bearer $MELSO_TOKEN" -H "X-Workspace-ID: $WORKSPACE_ID"

DELETE /api/workspaces/{workspaceId}/github/installations/{installationId}

Auth: The human member who owns the connection.

Request: Path: workspace and installation record IDs.

Removes only this member’s connection and its repository grants. Other members’ connections to the installation remain. The GitHub App stays installed. Mirrored PR history is retained but requires a current repository grant to read.

Response: Empty.

Status: 204; 404 no connection owned by this member matches the installation. Authentication and resource-access errors follow Overview.

curl -sS -X DELETE "$MELSO_URL/api/workspaces/$WORKSPACE_ID/github/installations/$INSTALLATION_ID" \
  -H "Authorization: Bearer $MELSO_TOKEN" -H "X-Workspace-ID: $WORKSPACE_ID"

POST /api/workspaces/{workspaceId}/github/personal-repositories

Auth: Human workspace member.

Request: {urls:string[]}; 1–100 GitHub repository URLs the member can access through their own connection.

Response: Empty. Creates or reuses the member's private My repositories Area and adds the repositories atomically. Repeating the request is safe.

Status: 204; 400 invalid input; 403 machine credential; 422 GitHub access could not be verified.

GET /api/tasks/{id}/pull-requests

Auth: Workspace member with access to this resource.

Request: Path: Task ID.

Response: {pull_requests:GitHubPullRequestResponse[]}.

Status: 200. Authentication and resource-access errors follow Overview.

curl -sS -X GET "$MELSO_URL/api/tasks/$ID/pull-requests" \
  -H "Authorization: Bearer $MELSO_TOKEN" -H "X-Workspace-ID: $WORKSPACE_ID"

GET /api/pull-requests/resolve

Auth: Workspace member with access to this resource.

Request: Query owner:string, repo:string, number:integer required.

Response: {id:UUID} for an authorized linked PR.

Status: 200; 400 missing/invalid query; 404 no accessible PR. Authentication and resource-access errors follow Overview.

curl -sS -X GET "$MELSO_URL/api/pull-requests/resolve?owner=example&repo=product&number=1" \
  -H "Authorization: Bearer $MELSO_TOKEN" -H "X-Workspace-ID: $WORKSPACE_ID"

GET /api/pull-requests/{id}

Auth: Workspace member with access to this resource.

Request: Path: PR record UUID.

Response: GitHubPullRequestDetailResponse.

Status: 200; 404 inaccessible PR. Authentication and resource-access errors follow Overview.

curl -sS -X GET "$MELSO_URL/api/pull-requests/$ID" \
  -H "Authorization: Bearer $MELSO_TOKEN" -H "X-Workspace-ID: $WORKSPACE_ID"

POST /api/pull-requests/{id}/merge

Auth: Workspace owner/admin (a person), or a workspace API key with admin scope. Run and MCP credentials are rejected, and tasks API keys get 403 workspace_key_scope; can_merge on the PR detail reports whether the caller may merge.

Request: merge_method?:"merge"|"squash"|"rebase", commit_title?:string, commit_message?:string.

Response: {merged:boolean,sha:string,pull_request:GitHubPullRequestResponse}.

Status: 200; 400 invalid method; 403 denied; 409 merge/check conflict; 502 GitHub failure. Authentication and resource-access errors follow Overview.

This action merges the PR. Use it only after review and authorization; closing keywords may also complete linked Tasks.

curl -sS -X POST "$MELSO_URL/api/pull-requests/$ID/merge" \
  -H "Authorization: Bearer $MELSO_TOKEN" -H "X-Workspace-ID: $WORKSPACE_ID" \
  -H "Content-Type: application/json" -d '{"merge_method":"squash"}'

GitHubPullRequestDetailResponse

Source: server/internal/handler/github_pr_detail.go (GitHubPullRequestDetailResponse). Referenced nested objects retain their handler-defined fields; clients should tolerate additional fields.

FieldJSON type
bodystring
commits_countinteger
checksGitHubPullRequestCheckResponse[]
preferred_merge_methodstring
allow_merge_commitboolean
allow_squash_mergeboolean
allow_rebase_mergeboolean
can_mergeboolean
review_decisionstring (may be omitted)
review_taskGitHubPRReviewTaskResponse or null (may be omitted)

GitHubInstallationResponse

Source: server/internal/handler/github.go (GitHubInstallationResponse). Referenced nested objects retain their handler-defined fields; clients should tolerate additional fields.

FieldJSON type
idstring
workspace_idstring
installation_idinteger or null (may be omitted)
requires_reconnectboolean
account_loginstring
account_typestring
account_avatar_urlstring or null
created_atstring

GitHubPullRequestResponse

Source: server/internal/handler/github.go (GitHubPullRequestResponse). Referenced nested objects retain their handler-defined fields; clients should tolerate additional fields.

FieldJSON type
idstring
providerstring
workspace_idstring
repo_ownerstring
repo_namestring
numberinteger
titlestring
statestring
html_urlstring
branchstring or null
head_shastring or null: the head commit Melso last mirrored for the pull request; null when unknown
author_loginstring or null
author_avatar_urlstring or null
merged_atstring or null
closed_atstring or null
pr_created_atstring
pr_updated_atstring
mergeable_statestring or null
mergeablestring or null
merge_state_statusstring or null
snapshot_availableboolean or null (may be omitted)
checks_rollupstring or null
checks_conclusionstring or null
checks_totalinteger
checks_passedinteger
checks_failedinteger
checks_runninginteger
checks_pendinginteger
failed_check_namesstring[]
snapshot_staleboolean
snapshot_fetched_atstring or null
snapshot_head_shastring or null: the head commit the stored CI and merge snapshot describes. It equals head_sha exactly when snapshot_available is true; another commit means the snapshot is for an older head, and its fields stay empty until one for the current head arrives. Null before the first snapshot and when snapshots are not configured. Always null for other providers, whose check counts describe head_sha
additionsinteger
deletionsinteger
changed_filesinteger

GitHubRepositoryResponse

Source: server/internal/handler/github.go (GitHubRepositoryResponse). Referenced nested objects retain their handler-defined fields; clients should tolerate additional fields.

FieldJSON type
idinteger
full_namestring
html_urlstring
clone_urlstring
descriptionstring or null
privateboolean
archivedboolean
default_branchstring

GitHubPullRequestDetailResponse also includes every GitHubPullRequestResponse field.